因子分解机(FM)系列总结

背景

  • 特征之间是关联的,线性模型中需要人工的特征组合,表达能力受限

  • one-hot编码带来特征空间暴增,数据稀疏,需要的参数量暴增


  • 在数据很稀疏的情况下,满足xi,xj都不为0的情况非常少,这样将导致wij无法通过训练得出。

FM

特点:

  • 可以自动进行特征组合

  • 数据稀疏的情况下表现依然良好

做法:

  • 利用矩阵分解的思想,引入辅助V矩阵,对W进行建模​


实现:

w0 = tf.Variable(tf.zeros([1]))
w = tf.Variable(tf.zeros([p]))
v = tf.Variable(tf.random_normal([k, p], mean=0, stddev=0.01))


linear_terms = tf.add(w0, tf.reduce_sum(tf.multiply(w, x), 1, keep_dims=True)) # n * 1

pair_interactions = 0.5 * tf.reduce_sum(
    tf.subtract(
        tf.pow(tf.matmul(x, tf.transpose(v)), 2),
        tf.matmul(tf.pow(x, 2), tf.transpose(tf.pow(v, 2)))
    ), axis=1, keep_dims=True)

y_hat = tf.add(linear_terms, pair_interactions)

lambda_w = tf.constant(0.001, name='lambda_w')
lambda_v = tf.constant(0.001, name='lambda_v')

l2_norm = tf.reduce_sum(
    tf.add(
        tf.multiply(lambda_w, tf.pow(w, 2)),
        tf.multiply(lambda_v, tf.pow(v, 2))
    )
)

error = tf.reduce_mean(tf.square(y - y_hat))
loss = tf.add(error, l2_norm)


注意:线性项和二次项是直接相加的(标量)

FFM

背景:

  • one-hot类型变量会导致严重的数据特征稀疏

做法:

  • 引入field的概念,同一类经过One-Hot编码生成的特征都可以放到同一个field

  • 在FFM中,每一维特征 xi,针对其它特征的每一种field fj,都会学习一个隐向量 ​。因此,隐向量不仅与特征相关,也与field相关。也就是说,“Day=26/11/15”这个特征与“Country”特征和“Ad_type"特征进行关联的时候使用不同的隐向量,这与“Country”和“Ad_type”的内在差异相符。

不足:

  • FFM的二次参数有 nfk 个,远多于FM模型的 nk个。

  • 此外,由于隐向量与field相关,FFM二次项并不能够化简,其预测复杂度是 O(kn^2)。

DeepFM

背景:

  • FM,FFM实际应用中受限于计算复杂度,一般也就只考虑到 2 阶交叉特征

优点/做法:

  • 不需要人工特征工程

  • FM 提取低阶组合特征,Deep 提取高阶组合特征,同时学习低阶和高阶的组合特征

  • FM 模块和 Deep 模块共享 Feature Embedding 部分,参数量少,可以更快的训练

DeepFM
  • one-hot 之前的特征维度,称之为field_size。

  • one-hot 之后的特征维度,称之为feature_size。

Embedding层作用:

  • Embedding 矩阵也就是隐向量 V

  • 输入层是onehot的,特别稀疏,直接全连接的话参数量太大,所以先降维再全连接

FM部分

FM

线性项(Addition Unit反映的是 1 阶的特征):
w_0+\sum_{i=1}^n{w_ix_i}

交叉项(内积单元反映的是 2 阶的组合特征对于预测结果的影响):
\sum_{i=1}^{n-1}\sum_{j=i+1}^{n}w_{ij}x_ix_j = \frac 1 2 \sum_{l=1}^k[(\sum_{i=1}^n v_{i,f}x_i)^2-\sum_{i=1}^n v_{i,f}^2x_i^2)]
注意:此处是向量,fm的输出维度是field_size(一阶) + embedding_size(二阶)

DNN部分

DNN

output部分

\hat y = sigmoid(tf.concat([y_{fm\_first\_order}, y_{fm\_second\_order}, y_{deep}], axis=1))

注意是concat,不是add

# model
self.embeddings = tf.nn.embedding_lookup(self.weights['feature_embeddings'], self.feat_index) # N * F * K
feat_value = tf.reshape(self.feat_value,shape=[-1,self.field_size,1])
self.embeddings = tf.multiply(self.embeddings,feat_value)
​
print(self.embeddings.shape)                #none, field_size, embedding_size
print(self.weights['feature_bias'].shape)  #feature_size, 1
​
# first order term          #none, field_size
self.y_first_order = tf.nn.embedding_lookup(self.weights['feature_bias'],self.feat_index)
self.y_first_order = tf.reduce_sum(tf.multiply(self.y_first_order,feat_value),2)
self.y_first_order = tf.nn.dropout(self.y_first_order,self.dropout_keep_fm[0]) 
​
# second order term                # None * K
# sum-square-part
self.summed_features_emb = tf.reduce_sum(self.embeddings,1) # None * k
self.summed_features_emb_square = tf.square(self.summed_features_emb) # None * K
# squre-sum-part
self.squared_features_emb = tf.square(self.embeddings)
self.squared_sum_features_emb = tf.reduce_sum(self.squared_features_emb, 1)  # None * K
# second order
self.y_second_order = 0.5 * tf.subtract(self.summed_features_emb_square,self.squared_sum_features_emb)
self.y_second_order = tf.nn.dropout(self.y_second_order,self.dropout_keep_fm[1])
​
# Deep component
self.y_deep = tf.reshape(self.embeddings,shape=[-1, self.field_size * self.embedding_size])
self.y_deep = tf.nn.dropout(self.y_deep,self.dropout_keep_deep[0])
​
for i in range(0,len(self.deep_layers)):
 self.y_deep = tf.add(tf.matmul(self.y_deep,self.weights["layer_%d" %i]), self.weights["bias_%d"%i])
 self.y_deep = self.deep_layers_activation(self.y_deep)
 self.y_deep = tf.nn.dropout(self.y_deep,self.dropout_keep_deep[i+1])
 print("y_deep:" + str(self.y_deep.shape))
​
#----DeepFM---------
 self.out = tf.add(tf.matmul(concat_input, self.weights['concat_projection']), self.weights['concat_bias'])

参考:

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352

推荐阅读更多精彩内容