咋形象理解embedding这个概念( 三 )


▌传统方法虽然目前有关推荐系统的模型中深度学习越来越占据重要地位,但是embedding的重要思想却贯穿始终,在传统的推荐方法中依然可以看到embedding的影子。例如基于矩阵分解的协同过滤模型,如下图所示:
咋形象理解embedding这个概念

通过将用户对物品的打分矩阵Rating Matrix分解成User Matrix和Item Matrix两个矩阵相乘,我们可以把User Matrix和Item Matrix相乘分别看作是A,B,C,D四个user embedding和W,X,Y,Z四个item embedding相乘。
可以看到打分矩阵比较稀疏,说明有的user没有给item打分,因此矩阵分解的目的就是通过分解的user embedding和item embedding相乘来填充user没有打分的item,从而可以进行推荐。而模型通过user embedding和item embedding相乘拟合user已给item的打分来学习embedding参数。
如上图所示,分解的user embedding B()和item embedding W()相乘得到3.63要尽量接近Rating Matrix中的B行W列也就是4.0,根据这种拟合学习得到embedding,最终再根据模型学习的user embedding和item embedding相乘得到user没有给item的打分,比如Rating Matrix中的A行W列的得分为user embedding A()和item embedding W()相乘得到3.16.
因为模型比较简单,这里直接给出利用tensorflow实现的模型的代码:
def build_model(user_indices, item_indices, rank, ratings, user_cnt, item_cnt, lr, lamb, mu, init_value): W_user = tf.Variable(tf.truncated_normal(, stddev=init_value/math.sqrt(float(rank)), mean=0), name = \u0026#39;user_embedding\u0026#39;, dtype=tf.float32) W_item = tf.Variable(tf.truncated_normal(, stddev=init_value/math.sqrt(float(rank)), mean=0), name = \u0026#39;item_embedding\u0026#39;, dtype=tf.float32) W_user_bias = tf.concat(, 1, name=\u0026#39;user_embedding_bias\u0026#39;) W_item_bias = tf.concat(, 1, name=\u0026#39;item_embedding_bias\u0026#39;) user_feature = tf.nn.embedding_lookup(W_user_bias, user_indices, name = \u0026#39;user_feature\u0026#39;) item_feature = tf.nn.embedding_lookup(W_item_bias, item_indices, name = \u0026#39;item_feature\u0026#39;) preds = tf.add(tf.reduce_sum( tf.multiply(user_feature , item_feature) , 1), mu) square_error = tf.sqrt(tf.reduce_mean( tf.squared_difference(preds, ratings))) loss = square_error + lamb*(tf.reduce_mean(tf.nn.l2_loss(W_user)) + tf.reduce_mean(tf.nn.l2_loss(W_item))) tf.summary.scalar(\u0026#39;square_error\u0026#39;, square_error) tf.summary.scalar(\u0026#39;loss\u0026#39;, loss) merged_summary = tf.summary.merge_all() #tf.global_variables_initializer() train_step = tf.train.GradientDescentOptimizer(lr).minimize(loss) # tf.train.AdadeltaOptimizer(learning_rate=lr).minimize(loss) # return train_step, square_error, loss, merged_summary虽然模型比较简单,但是可以发现embedding的思想其实贯穿在整个模型当中。
除了基于矩阵分解的协同过滤,还有基于自编码器的协同过滤,自编码器做协同过滤的思想主要是把用户对所有物品的打分组成一个固定维度的向量(没有打分的填充为0)然后通过自编码器对该打分向量进行编码解码然后得到和该打分向量维度相同的向量,该自编码器模型的输出向量就是为了拟合输入向量。如图所示为自编码器模型:


推荐阅读