推荐系统概括

  • 推荐系统方法综述
    • 推荐系统的目的
      • 评价指标
        • Accuracy
        • logloss
        • AUC
        • F1 score
    • Collaborative Fliter
    • CTR
      • LR
        • POLY2
        • FM
        • FFM
        • 小结
      • LR+GBDT
      • LR+DNN
      • Wide and deep
        • DeepFM

推荐系统方法综述

推荐系统的目的

评价指标

Accuracy

a c c u r a c y = 预 测 正 确 的 样 本 数 总 样 本 数 accuracy=\frac{预测正确的样本数}{总样本数} accuracy=
缺点 对样本分布敏感。在测试集里,有100个sample,99个反例,只有1个正例。如果我的模型不分青红皂白对任意一个sample都预测是反例,那么我的模型的accuracy是 正确的个数/总个数 = 99/100 = 99%

logloss

2分类问题:
l o g l o s s = − ∑ i = 1 n y i l o g ( p ( x i ) ) + ( 1 − y i ) l o g ( 1 − p ( x i ) ) logloss=-\sum_{i=1}^ny_ilog(p(x_i))+(1-y_i)log(1-p(x_i)) logloss=i=1nyilog(p(xi))+(1yi)log(1p(xi))

AUC

为什么 AUC 和 logloss 比 accuracy 更常用呢?因为很多机器学习的模型对分类问题的预测结果都是概率,如果要计算 accuracy,需要先把概率转化成类别,这就需要手动设置一个阈值,如果对一个样本的预测概率高于这个预测,就把这个样本放进一个类别里面,低于这个阈值,放进另一个类别里面。
所以这个阈值很大程度上影响了 accuracy 的计算。使用 AUC 或者 logloss 可以避免把预测概率转换成类别1

AUC 是 Area under curve 的首字母缩写。AUC 就是 ROC 曲线下的面积,衡量学习器优劣的一种性能指标。

ROC 曲线的横坐标是假正率,纵坐标是真正率,由上图:
T P R = T P T P + F N = P ( T P ∣ Y = 1 ) TPR=\frac{TP}{TP+FN}=P(TP|Y=1) TPR=TP+FNTP=P(TPY=1)
F P R = F P F P + T N = P ( F P ∣ Y = 1 ) FPR=\frac{FP}{FP+TN}=P(FP|Y=1) FPR=FP+TNFP=P(FPY=1)
其纵轴、横轴均是条件于真实 label Y的概率的,我们讲这个叫条件概率。那么意思就是说,无论Y的真实概率是多少,都不会影响 TPR 和 FPR。也就是说,这两个 metric 是不会受 imbalanced data 影响的,相反 p r e c i s i o n = T P T P + F P = P ( T P ∣ Y ^ = 1 ) precision=\frac{TP}{TP+FP=P(TP|\hat{Y}=1)} precision=TP+FP=P(TPY^=1)TP,是基于预测label Y 的概率的,会随着测试集里面的正反比例而变化。

AUC代表模型预估样本之间的排序关系,即正负样本之间预测的 gap 越大,AUC越大。另外值得注意的是,AUC的计算方法同时考虑了学习器对于正例和负例的分类能力,在样本不平衡的情况下,依然能够对分类器做出合理的评价。AUC对样本类别是否均衡并不敏感,这也是不均衡样本通常用AUC评价学习器性能的一个原因。
ROC 曲线越靠近左上角,模型的查全率就越高。最靠近左上角的ROC曲线上的点是分类错误最少的最好阈值,其假正例和假反例总数最少。可以对不同的学习器比较性能。将各个学习器的ROC曲线绘制到同一坐标中,直观地鉴别优劣,靠近左上角的ROC曲所代表的学习器准确性最高。
ROC曲线能很容易的查出任意阈值对学习器的泛化性能影响。
有助于选择最佳的阈值。ROC曲线越靠近左上角,模型的查全率就越高。最靠近左上角的ROC曲线上的点是分类错误最少的最好阈值,其假正例和假反例总数最少。
可以对不同的学习器比较性能。将各个学习器的ROC曲线绘制到同一坐标中,直观地鉴别优劣,靠近左上角的ROC曲所代表的学习器准确性最高。

F1 score

F 1 = 2 ∗ p r e c i s i o n ∗ r e c a l l p r e c i s i o n + r e c a l l F1=\frac{2*precision*recall}{precision+recall} F1=precision+recall2precisionrecall
基本上问题就是如果你的两个模型,一个precision特别高,recall特别低,另一个recall特别高,precision特别低的时候,f1-score可能是差不多的,你也不能基于此来作出选择。

Collaborative Fliter

CTR

根据用户的询问,给于用户信息度相关的广告,会极大的增加用户点击广告的可能性,会增加用户的体验,同时也会增加广告公司的收入。

CTR 指的是click through rate,代表点击该广告的概率。例如某个广告ad在过去一段时间内被展示了1000次,并且受到50次的点击次数,那么 CTR (ad)=0.05.

因此,如何根据历史广告信息和用户信息,较为精准的预测新的广告会被点击的概率具有重要意义,
但是这里存在一个问题:这种根据过去的信息预测点击率的方法有着极大的 Variance ,并且根据 大数定理 广告需要被大量投递后,才能获得较为精准的 CTR 结果。

因此如何能够精准构建广告信息和 CTR 之间的数学模型有着极其重要的意义。
C T R = f ( X a d ) CTR=f(X_{ad}) CTR=f(Xad)
进一步思考,我们可以发现广告点击问题本质上是一个2分类问题: {点击,不点击} ,因此可以构建基于机器学习方法的 CTR 估计模型。

大数定理 :大数定律说如果统计数据足够大,那么事物出现的频率就能无限接近他的期望值。
大数定理有3种:辛钦大数定理、切比雪夫、伯努利大数定理

辛钦大数定理:



切比雪夫不等式:在不知道随机变量的具体概率密度函数的情况下,可以根据总体的均值和方差时,用切比雪夫不等式来估算一定条件下的概率。

伯努利大数定理:

伯努利大数定理是日常中最常被使用的,它的直观表达就是只要做的试验够多,出现的次数除以总次数的结果接近统计概率p,这也是频率到概率概念演变的理论基础举个例子,结合概率论里面的概念。”抛5次硬币“是一种试验,一共作n重,“ 3次出现正面”,称为事件A,n重试验出现A的次数为fA另外已知"抛5次3次正面"的概率是p,这是一个先验可统计概率。如果n很大,则出现A的次数除以n就可做为统计的概率p.
引用博文大数定理的通俗理解2

中心极限定理
(1). 样本的平均值约等于总体的平均值
(2).不管样本是什么分布,任意一个总体的样本平均值会围绕着总体平均值周围,并且呈正态分布。
中心极限定理3
基于机器学习LR的CTR估计的发展历程如下图:

LR

根据前文所诉:CTR 估计问题本质上是一个2分类问题,不妨设{点击,不点击}={1,0},LR模型使用Logit将广告的特征值加权和映射到(0,1)区间,映射后的值就是 CTR 估计值.
y ^ = w 0 + ∑ i = 1 n w i x i \hat{y}=w_0+\sum_{i=1}^n w_ix_i y^=w0+i=1nwixi
将输入 y ^ \hat{y} y^通过logit函数之后获得ctr值。
C T R = l o g i t ( y ^ ) CTR=logit(\hat{y}) CTR=logit(y^)
优化目标
首先可求当根据原始特征 X X X时,预测为1的概率:
P ( y = 1 ∣ x ; w ) = 1 1 + e − w T X P(y=1|x;w)= \frac{1}{1+e^{-w^TX}} P(y=1x;w)=1+ewTX1
因此预测为0的概率:
P ( y = 0 ∣ x ; w ) = 1 − 1 1 + e − w T X = 1 1 + e w T X P(y=0|x;w)=1- \frac{1}{1+e^-w^TX}=\frac{1}{1+e^{w^TX}} P(y=0x;w)=11+ewTX1=1+ewTX1
根据极大似然思想:
J ( w ) = m a x w ∏ i = 1 n P ( y = 1 ∣ x ; w ) y = 1 ( y = 0 ∣ x ; w ) y = 0 = m a x ∏ i = 1 n P ( y = 1 ∣ x ; w ) y ( y = 0 ∣ x ; w ) 1 − y J ( w ) = m i n − ∑ i = 1 m y i l o g ( l o g i t ( X i ) ) + ( 1 − y i ) l o g ( 1 − l o g i t ( X i ) ) J(w)=max_{w} \prod_{i=1}^{n} P(y=1|x;w)^{y=1}(y=0|x;w)^{y=0}\\=max \prod_{i=1}^{n} P(y=1|x;w)^{y}(y=0|x;w)^{1-y}\\J(w)=min -\sum_{i=1}^m y^ilog(logit(X^i))+(1-y^i)log(1-logit(X^i)) J(w)=maxwi=1nP(y=1x;w)y=1(y=0x;w)y=0=maxi=1nP(y=1x;w)y(y=0x;w)1yJ(w)=mini=1myilog(logit(Xi))+(1yi)log(1logit(Xi))

当label={-1,1}时: J ( w ) = m i n ∑ i = 1 m l o g ( 1 + e − y y ^ ) J(w)=min\sum_{i=1}^m log(1+e^{-y\hat{y}}) J(w)=mini=1mlog(1+eyy^)
当label是多目标时,有 T T T个类别: J ( w ) = m i n − ∑ i = 1 m ∑ j = 1 T y i j l o g ( p i j ) J(w)=min-\sum_{i=1}^m\sum_{j=1}^T y_{ij}log(p_{ij}) J(w)=mini=1mj=1Tyijlog(pij)

LR方法存在很明显的缺陷: (1).LR方法无法捕捉特征之间的联系。(2).LR方法在数据特征有缺失时或者特征空间很大时表现不佳。

POLY2

由于LR方法无法捕捉特征之间的联系,因此可以组合特征建立特征之间的关系:
y ^ = w 0 + ∑ i = 1 n w i x i + ∑ i = 1 n ∑ j = i + 1 n w i j x i x j \hat{y}=w_0+\sum_{i=1}^n w_ix_i+\sum_{i=1}^n\sum_{j=i+1}^n w_{ij}x_ix_j y^=w0+i=1nwixi+i=1nj=i+1nwijxixj
由于对特征进行了组合,因此数据矩阵必定是一个非常稀疏的矩阵。由于 ∂ y ^ ∂ w i j = x i x j , 因 此 w i j 在 x i = 0 或 者 x j = 0 时 不 能 得 到 很 好 的 调 整 。 \frac{\partial\hat{y}}{\partial w_{ij}}=x_ix_j,因此w_{ij}在x_i=0或者x_j=0时不能得到很好的调整。 wijy^=xixj,wijxi=0xj=0
POLY2 方法虽然能够捕捉特征之间的联系(度为2),但是由于数据稀疏问题,往往不能得到较好的结果。

FM

FM 方法不同于 PLOY2 ,FM 方法通过对每一位特征引入一个隐向量 V V V,使得 FM 方法能够使用稀疏的数据矩阵中,获得可信的结果。
y ^ = w 0 + ∑ i = 1 n w i x i + ∑ i = 1 n ∑ j = i + 1 n < V i , V j > x i x j < V i , V j > = ∑ f = 1 k V i f ∗ V j f \hat{y}=w_0+\sum_{i=1}^n w_ix_i+\sum_{i=1}^n\sum_{j=i+1}^n <V_i,V_j>x_ix_j\\<V_i,V_j>=\sum_{f=1}^kV_{if}*V_{jf} y^=w0+i=1nwixi+i=1nj=i+1n<Vi,Vj>xixj<Vi,Vj>=f=1kVifVjf

FM 方法将特征的联系矩阵 W W W分解为 W = V ⋅ V T W=V\cdot V^T W=VVT。其理论依据是,任何的正定矩阵 W W W总存在 V n ∗ k V_{n*k} Vnk,使得 W = V ⋅ V T W=V\cdot V^T W=VVT,在 k k k充分大的条件下。

FM 方法通过提出隐向量的思想解决了 PLOY2 方法中 w i j w_{ij} wijx i = 0 x_i=0 xi=0或者 x j = 0 x_j=0 xj=0时不能得到很好的调整的问题。FM 通过分解 W W W打破了矩阵里面参数的独立性,即 w i j = < V i , V j > w_{ij}=<V_i,V_j> wij=<Vi,Vj>V i V_i ViV j V_j Vj 可以由其他特征下学习的结果,因此 FM 能够在稀疏数据集上获得较好的结果。
FM 方法在不调整计算的情况下的时间复杂度 O ( k n 2 ) O(kn^2) O(kn2),但是通过调整上式,其时间复杂度可降为 O ( k n ) O(kn) O(kn)
∑ i = 1 n ∑ j = i + 1 n < V i , V j > x i x j = 1 2 ∑ i = 1 n ∑ j = 1 n < V i , V j > x i x j − 1 2 ∑ i = 1 n < V i , V i > x i x i = 1 2 ( ∑ i = 1 n ∑ j = 1 n ∑ i = f k v i f v j f x i x j − ∑ i = 1 n ∑ f = 1 k v i f v i f x i x i ) = 1 2 ∑ f = 1 k ( ( ∑ i = 1 n v i f x i ) 2 − ∑ i = 1 n v i f 2 x i 2 ) \sum_{i=1}^n\sum_{j=i+1}^n <V_i,V_j>x_ix_j\\= \frac{1}{2}\sum_{i=1}^n\sum_{j=1}^n <V_i,V_j>x_ix_j-\frac{1}{2}\sum_{i=1}^n <V_i,V_i>x_ix_i \\= \frac{1}{2}(\sum_{i=1}^n\sum_{j=1}^n \sum_{i=f}^kv_{if}v_{jf}x_ix_j-\sum_{i=1}^n\sum_{f=1}^kv_{if}v_{if}x_ix_i)\\=\frac{1}{2}\sum_{f=1}^k((\sum_{i=1}^nv_{if}x_i)^2-\sum_{i=1}^nv_{if}^2x_i^2) i=1nj=i+1n<Vi,Vj>xixj=21i=1nj=1n<Vi,Vj>xixj21i=1n<Vi,Vi>xixi=21(i=1nj=1ni=fkvifvjfxixji=1nf=1kvifvifxixi)=21f=1k((i=1nvifxi)2i=1nvif2xi2)
很明显的可以看出 ( ∑ i = 1 n v i f x i ) 2 (\sum_{i=1}^nv_{if}x_i)^2 (i=1nvifxi)2这一项不需要重复计算,因此时间复杂度降为 O ( k n ) O(kn) O(kn)

求解 V V V 通过SGD方法求解 V V V:
∂ ∂ θ y ^ ( X ) = 1 , w h e n θ = w 0 ∂ ∂ θ y ^ ( X ) = x i , w h e n θ = w i ∂ ∂ θ y ^ ( X ) = x i ∑ j = 1 n v j f x j − v i f x i 2 , w h e n θ = v i f \frac{\partial}{\partial\theta}\hat{y}(X)=1, \ when\ \theta=w_0\\ \frac{\partial}{\partial\theta}\hat{y}(X)=x_i, \ when\ \theta=w_i\\ \frac{\partial}{\partial\theta}\hat{y}(X)=x_i\sum_{j=1}^nv_{jf}x_j-v_{if}x_i^2, \ when\ \theta=v_{if} θy^(X)=1,whenθ=w0θy^(X)=xi,whenθ=wiθy^(X)=xij=1nvjfxjvifxi2,whenθ=vif
FM 的优点:
(1). 可以在稀疏的数据矩阵中对特征进行交叉。
(2).预测和参数的调整都是基于 O ( k n ) O(kn) O(kn)的时间复杂度。

#########2020.5.1 hwf#############
import tensorflow as tf
import os
import numpy as np
class Fm():def __init__(self,num_classes,k,batch_size,feature_size,train_feature,train_label,save_dir):self.num_classes=num_classesself.k=kself.batch_size=batch_sizeself.feature_size=feature_sizeself.train_feature=train_featureself.train_label=train_labelself.save_dir=save_dirdef bulid_model(self):self.x=tf.placeholder('float32',[None,self.feature_size])self.y=tf.placeholder('float32',[None,self.num_classes])with tf.variable_scope('linear_layer'):w0=tf.get_variable('w0',shape=[self.num_classes],initializer=tf.zeros_initializer)w=tf.get_variable('w',shape=[self.feature_size,self.num_classes],initializer=tf.truncated_normal_initializer(mean=0.0,stddev=0.01))linear_out=tf.add(tf.matmul(self.x,w),w0)with tf.variable_scope('interaction_layer'):embeding=tf.get_variable('v',shape=[self.feature_size,self.k],initializer=tf.truncated_normal_initializer(mean=0.0,stddev=0.01))interaction_out=tf.multiply(0.5,tf.reduce_sum(tf.subtract(tf.pow(tf.matmul(self.x,embeding),2),tf.matmul(tf.pow(self.x,2),tf.pow(embeding,2))),axis=1,keepdims=True))with tf.variable_scope('out_layer'):output=tf.add(linear_out,interaction_out)with tf.variable_scope('accuracy'):correct_prediction = tf.equal(tf.cast(tf.argmax(output,1), tf.float32), tf.cast(tf.argmax(self.y,1), tf.float32))self.accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))# add summary to accuracytf.summary.scalar('accuracy', self.accuracy)if self.num_classes==2:y_prob=tf.nn.sigmoid(output)cross_entropy = tf.nn.sigmoid_cross_entropy_with_logits(labels=self.y, logits=y_prob)elif self.num_classes>2:y_prob=tf.nn.softmax(output)cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=self.y, logits=y_prob)mean_loss = tf.reduce_mean(cross_entropy)self.loss = mean_losstf.summary.scalar('loss', self.loss)self.optimizer=tf.train.AdamOptimizer()self.train_op=self.optimizer.minimize(self.loss)# def next_batch(self):#     print('mext+_natch',self.train_feature)#     print(self.batch_size)#     input_queue = tf.train.slice_input_producer([self.train_feature,self.train_label], shuffle=False)#     feature_batch, label_batch = tf.train.batch(input_queue, batch_size=self.batch_size, num_threads=2, capacity=128,allow_smaller_final_batch=True)#     return feature_batch,label_batchdef shuffle_list(self,data):num = data[0].shape[0]p = np.random.permutation(num)return [d[p] for d in data]def batch_generator(self,data, batch_size, shuffle=False):if shuffle:data = self.shuffle_list(data)batch_count = 0while True:if batch_count * batch_size + batch_size > len(data[0]):batch_count = 0if shuffle:data = self.shuffle_list(data)start = batch_count * batch_sizeend = start + batch_sizebatch_count += 1yield [d[start:end] for d in data]def train(self,iteration):self.Saver = tf.train.Saver(max_to_keep=100)merge = tf.summary.merge_all()nums_batch=len(self.train_label)//self.batch_size+1init = tf.initialize_all_variables()ckpt=tf.train.get_checkpoint_state(self.save_dir)with tf.Session() as self.sess:coord = tf.train.Coordinator()threads = tf.train.start_queue_runners(self.sess, coord)self.sess.run(init)train_writer=tf.summary.FileWriter('./log/train_logs',self.sess.graph)if ckpt and ckpt.model_model_checkpoint_path:self.Saver.restore(self.sess,ckpt.model_model_checkpoint_path)print("加载模型成功"+ckpt.model_model_checkpoint_path)global_step=int(ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1])else:global_step =0for epoch in range(iteration):for _ in range(nums_batch):#feature_batch, label_batch = self.next_batch()feature, label = next(self.batch_generator([self.train_feature,self.train_label],batch_size=self.batch_size))#feature,label = self.sess.run([feature_batch, label_batch])feed_dic={self.x:feature, self.y:label}loss, accuracy, summary, _ = self.sess.run([self.loss, self.accuracy,merge, self.train_op], feed_dict=feed_dic)train_writer.add_summary(summary, global_step=global_step)global_step+=1if epoch % 100 == 0:print('save_model_{}'.format(epoch))self.Saver.save(self.sess, os.path.join(self.save_dir, 'fm'), global_step=global_step)print("Epoch {1},  loss = {0:.3g}, accuracy={2:.3g}".format(loss, epoch + 1,accuracy))coord.request_stop()coord.join(threads)
if __name__=='__main__':x_train,  x_test,y_train, y_test = load_data()print(x_train)# initialize the modelnum_classes = 5lr = 0.01batch_size = 128k = 40#reg_l1 = 2e-2#reg_l2 = 0feature_length = x_train.shape[1]save_dir=r'./model/'# initialize FM modelmodel =Fm(num_classes,k,batch_size,feature_length,x_train,y_train,save_dir=save_dir)model.bulid_model()model.train(12222)# build graph for model

FFM

FM 方法有仍然存在问题, 离散特征 x i x_i xi进行onehot编码后, x i x_i xi会被编码成 x i 1 , x i 2 , x i 3 . . x i t x_{i1},x_{i2},x_{i3}..x_{it} xi1,xi2,xi3..xit,这些feature被称为一个field。其中特征 x f i l e d i , f e a t u r e j x_{filed_i,feature_j} xfiledi,featurej的隐向量 V i j V_{ij} Vij跟其他的filed的特征进行组合时,如 < V i j ⋅ V a b > <V_{ij}\cdot V_{ab}> <VijVab>< V i j ⋅ V c d > <V_{ij}\cdot V_{cd}> <VijVcd>由于 x f i l e d i , f e a t u r e j , x f i l e d a , f e a t u r e b x_{filed_i,feature_j},x_{filed_a,feature_b} xfiledi,featurej,xfileda,featurebx f i l e d i , f e a t u r e j , x f i l e d c , f e a t u r e d x_{filed_i,feature_j},x_{filed_c,feature_d} xfiledi,featurej,xfiledc,featured属于不同field,因此他们的隐向量组合也会不同。
FFM 对的每一个feature都会包含 f f f个隐向量, f f f是其他field的个数。
y f f m = ∑ i = 1 n ∑ j = i + 1 n < V i , f 1 , V j , f 2 > x i x j 其 中 f 1 表 示 j 的 f i l e d , f 2 表 示 i 的 f i e l d 。 y_{ffm}=\sum_{i=1}^n\sum_{j=i+1}^n <V_{i,f1},V_{j,f2}>x_ix_j\\其中f1表示j的filed,f2表示i的field。 yffm=i=1nj=i+1n<Vi,f1,Vj,f2>xixjf1jfiledf2ifield
ffm的变量个数为 n f k nfk nfk,时间复杂度为 O ( n n k ) O(nnk) O(nnk)

小结

Model variable complexity
LM n n n O ( n ) O(n) O(n)
Poly2 B B B O ( n 2 ) O(n^2) O(n2)
FM n k nk nk O ( n k ) O(nk) O(nk)
FFm n f k nfk nfk O ( n f k ) O(nfk) O(nfk)

LR+GBDT

核心思想:模型想要得到好的预测结果的最重要的影响因素是 好的特征组合,即特征决定下限,模型决定上限。因此利用GBDT算法对原始特征进行特征重要性划分这种思想,对原始特征进行高维特征组合,减少人工的特征组合。

如上图所示假设有 T T T个树,不妨设 T = 2 , T 1 有 5 个 叶 子 节 点 , T 2 有 3 个 叶 子 节 点 T=2,T_1有5个叶子节点,T_2有3个叶子节点 T=2T15,T23,样本 X i X_i Xi在第一棵树中被划分到节点2,在第二棵树中被划分到节点3,则通过GBDT后的: t r a n s f o r m e d f e a t u r e = [ 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 ] transformed\ feature=[0,1,0,0,0,0,1,0] transformedfeature=[0,1,0,0,0,0,1,0]
之后再结合 t r a n s f o r m e d f e a t u r e transformed\ feature transformedfeatureL M LM LM模型获得预测结果。

from sklearn.ensemble.gradient_boosting import GradientBoostingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score
from sklearn.preprocessing import OneHotEncoder
from xgboost import XGBClassifier
import numpy as np
from lightgbm import LGBMClassifier
from sklearn.model_selection import train_test_split#gbdt.apply(x_test)
#返回值为 dimension[n,n_estimator,n_leaves_index]
#假设gbdt.apply(x_test)返回值[[1,1,2],[2,2,2],[3,1,3],[4,5,4]]
#其中[1,1,2],[2,2,2],[3,1,3],[4,5,4]。表示第1,2,3,4个样本,[1,1,2]表示样本1,被划分到第一棵树的第一个叶子节点,被划分到第二棵树的第一个叶子节点,被划分到第3棵树的第二个叶子节点。
#通过OneHotEncoder()之后可以获得每个树的叶子节点的特征组合。
# oneHot=OneHotEncoder()
# oneHot.fit([[1,1,2],[2,2,2],[3,1,3],[4,5,4]])
# print(oneHot.transform([[1,1,2],[2,2,2],[3,1,3],[4,5,4]]).toarray())
#[[1. 0. 0. 0. 1. 0. 0. 1. 0. 0.]
# [0. 1. 0. 0. 0. 1. 0. 1. 0. 0.]
# [0. 0. 1. 0. 1. 0. 0. 0. 1. 0.]
# [0. 0. 0. 1. 0. 0. 1. 0. 0. 1.]]random_seed=10
class GBDT_LR():def __init__(self,data,label,gbdt_name):self.gbdt_set=['xgboost','gbdt','lgb']self.gbdt_name=gbdt_nameself.data=dataself.label=labelself.x_train,self.x_test,self.y_train,self.y_test=train_test_split(self.data,self.label,train_size=0.7,random_state=random_seed)self.gbdt=self.init_gbdt()def init_gbdt(self):if self.gbdt_name == 'xgboost':gbdt = XGBClassifier()elif self.gbdt_name=='gbdt':gbdt=GradientBoostingClassifier()elif self.gbdt_name=='lgb':gbdt=LGBMClassifier()else:print('no valid gbdt model')return gbdtdef gbdt_train(self):self.gbdt.fit(self.x_train,self.y_train)def gbdt_predict(self):self.gbdt_predict =self.gbdt.predict_proba(self.x_test)def cal_auc(self):gbdt_auc=roc_auc_score(self.y_test,self.gbdt_predict)def LR(self):gbdt_encoder=OneHotEncoder()self.lr=LogisticRegression()self.x_train_leafs=self.gbdt.apply(self.x_train)self.x_test_leafs=self.gbdt.apply(self.x_test)gbdt_encoder.fit(self.x_train_leafs)x_train_encoder=gbdt_encoder.transform(self.x_train_leafs)x_test_encoder = gbdt_encoder.transform(self.x_test_leafs)self.lr.fit(x_train_encoder,self.y_train)self.gbdt_lr_predict=self.lr.predict_proba(x_test_encoder)gbdt_lr_auc=roc_auc_score(self.y_test,self.gbdt_lr_predict)print('基于gbdt编码后的LR AUC值:{:.2f}'.format(gbdt_lr_auc))lr2=LogisticRegression()lr2.fit(self.x_train)lr_predict=lr2.predict_proba(self.x_test)lr_auc=roc_auc_score(self.x_test,lr_predict)print('LR AUC值:{:.2f}'.format(lr_auc))

LR+DNN

Wide and deep

广度模型(FM,FFM)一般只能学习一阶和二阶的特征组合,不能很好的发现特征之间的更加高维和抽象的关系。
深度模型(FNN/DNN)一般学习的是不可视的高阶特征的组合,但是丢失了低阶特征的信息。
wide and deep模型结合广度模型和深度模型的优点,充分利用特征的低阶组合和高阶组合,能够达到单一模型达不到的精度。
wide and deep 模型有两个重要的概念:
memorization :通过一系列人工的特征叉乘(cross-product)来构造这些非线性特征,捕捉sparse特征之间的低阶(因为一般只做2阶的,更高阶难以计算)相关性,即“记忆” 历史数据中曾共同出现过的特征对。
优点:模型可解释强,实现高效,特征重要度易于分析。
缺点:需要人工的特征工程,无法捕捉未出现过的特征对,过高阶的特征叉乘容易出现过拟合。
generalization :Generalization 为sparse特征学习低维的dense embeddings来捕获特征相关性,学习到的embeddings本身带有一定的语义信息。可以联想到NLP中的词向量,不同词的词向量有相关性,因此文中也称Generalization是基于相关性之间的传递。这类模型的代表是DNN和FM。

Memorization趋向于更加保守,Memorization根据历史行为数据,产生的推荐通常和用户已有行为的物品直接相关的物品。而Generalization会学习新的特征组合,提高推荐物品的多样性。

这个是从人类的认知学习过程中演化来的。人类的大脑很复杂,它可以记忆(memorize)下每天发生的事情(麻雀可以飞,鸽子可以飞)然后泛化(generalize)这些知识到之前没有看到过的东西(有翅膀的动物都能飞)。但是泛化的规则有时候不是特别的准,有时候会出错(有翅膀的动物都能飞吗)。那怎么办那,没关系,记忆(memorization)可以修正泛化的规则(generalized rules),叫做特例(企鹅有翅膀,但是不能飞)。
Wide&Deep Mode就是希望计算机可以像人脑一样,可以同时发挥memorization和generalization的作用。–Heng-Tze Cheng(Wide&Deep作者)
link


如上图所示:wide and deep模型仍然存在问题,需要人工的特征工程为wide部分选取合适的特征。

DeepFM


DeepFM 方法基于wide and deep思想,解决了wide and deep中需要进行人为的特征工程的问题。
deepfm结合FM中对每一位特征构建一个隐向量 V V V的思想,对onehot后稀疏特征进行embedding。
y ^ = s i g m o d ( y F M + y D N N ) \hat{y}=sigmod(y_{FM}+y_{DNN}) y^=sigmod(yFM+yDNN)
由上式可知 DeepFM 可以分为 FMDNN 两个模块,下面分开来将。
在讲两个模块之前,必须得清楚 DeepFM sparse feature 和 dense embeddings是什么。


由上图,每个 x f i e l d , i x_{field,i} xfield,i都是只有某一个index的位置为1的稀疏向量。每个特征 x j x_j xj都蕴含一个隐向量 V j V_j Vj,上图中的dense embeddings层就是每一个非零特征 x j x_j xj对应的隐向量 V j V_j Vj,由于一个field只有一个index为1,其余都为零,因此dense embeddings节点个数 k ∗ f i e l d k*field kfield。这是因为在FM中,只有当特征 x j x_j xj不为0时,对应的隐向量 V j V_j Vj才会得到调整。上图中 [ V 1 , 1 , V 1 , 2 , V 1 , 3 , V 1 , k ] [V_{1,1},V_{1,2},V_{1,3},V_{1,k}] [V1,1,V1,2,V1,3,V1,k]表示field 1中的某一位不为0的特征的隐向量。不妨设 f i l e d i filed_i filedi的隐向量矩阵为 W t i k i W^i_{t_ik} Wtiki,其中 t i t_i ti表示 f i l e d i filed_i filedi中的特征的个数, k k k表示隐向量的维数。,不妨设 X f i l e d i , j = 1 X_{filed_i,j}=1 Xfiledi,j=1,则 X f i l e d i ∗ W t i k i = [ V t i , 1 , V t i , 2 , V t i , 3 , V t i , k ] X_{filed_i}*W^i_{t_ik}=[V_{t_i,1},V_{t_i,2},V_{t_i,3},V_{t_i,k}] XfilediWtiki=[Vti,1,Vti,2,Vti,3,Vti,k]

FM 模块:

FM 部分可回顾章节 FM 部分。
DNN DNN部分直接使用dense embeddings作为输入层
a 0 = [ e 1 , e 2 . . . e m ] a^0=[e_1,e_2...e_m] a0=[e1,e2...em]
e i e_i ei表示等 i i i个filed的embedding, m m m表示field的个数。

DeepFM 总结:
1.不需要任何的预训练
2.结合wide and deep思想,可以同时具备高阶和低阶的特征组合
3.使用了共享隐向量embedding的思想,避免了人为的特征工程。


  1. https://blog.csdn.net/Dby_freedom/article/details/89814644 ↩︎

  2. https://blog.csdn.net/haoso2/article/details/85290720 ↩︎

  3. 中心极限定理 ↩︎

推荐系统:CTR模型学习总结--LR、FM、FFM、Wide and Deep、DeepFM相关推荐

  1. 推荐系统CTR预估学习路线:深度模型

    推荐系统CTR预估学习路线:从LR到FM/FFM探索二阶特征的高效实现 推荐系统CTR预估学习路线:利用树模型自动化特征工程 推荐系统CTR预估学习路线:深度模型 推荐系统CTR预估学习路线:引入注意 ...

  2. CTR经典模型串讲:FM / FFM / 双线性 FFM 相关推导与理解

    CTR 系列文章: 广告点击率(CTR)预测经典模型 GBDT + LR 理解与实践(附数据 + 代码) CTR经典模型串讲:FM / FFM / 双线性 FFM 相关推导与理解 CTR深度学习模型之 ...

  3. 推荐系统CTR预估学习路线:引入注意力机制

    推荐系统CTR预估学习路线:从LR到FM/FFM探索二阶特征的高效实现 推荐系统CTR预估学习路线:利用树模型自动化特征工程 推荐系统CTR预估学习路线:深度模型 推荐系统CTR预估学习路线:引入注意 ...

  4. 推荐系统与深度学习(二)——FFM模型原理​

    作者:livan 来源:数据python与算法 前言 上一篇我们讲解了FM模型: 推荐系统与深度学习(一)--FM模型原理 从FM的公式我们可以看出: FM中每个特征所对应的向量是唯一的: Vi是Xi ...

  5. 推荐系统fmlr_推荐系统实践 0x0c FM系列(LR/FM/FFM)

    逻辑回归(LR) 在介绍FM系列之前,我想首先简单介绍一下逻辑回归.通常来说,逻辑回归模型能够综合利用更多的信息,如用户.物品.上下文等多种不同的特征,生成更为全面的结果.另外,逻辑回归将推荐问题看成 ...

  6. 推荐系统与深度学习(十四)——GBDT+LR模型原理

    公众号后台回复"图书",了解更多号主新书内容 作者:livan 来源:数据python与算法 模型原理 与GBDT+LR模型结缘是刚开始学习推荐系统的过程中,FaceBook一推出 ...

  7. CTR深度学习模型之 DeepFM 模型解读

    CTR 系列文章: 广告点击率(CTR)预测经典模型 GBDT + LR 理解与实践(附数据 + 代码) CTR经典模型串讲:FM / FFM / 双线性 FFM 相关推导与理解 CTR深度学习模型之 ...

  8. 深度学习CTR模型粗略记录

    深度学习CTR模型粗略记录 RoadMap FM:Factorization Machines DNN:Embedding+MLP WND:Wide & Deep Learning for R ...

  9. CTR 模型之 Deep Cross (DCN) 与 xDeepFM 解读

    CTR 系列文章: 广告点击率(CTR)预测经典模型 GBDT + LR 理解与实践(附数据 + 代码) CTR经典模型串讲:FM / FFM / 双线性 FFM 相关推导与理解 CTR深度学习模型之 ...

最新文章

  1. MySql,Sql Server分区技术浅析
  2. 下雨天我叫了顿外卖,就成了人渣?
  3. 计算机专业教学工作小结,计算机专业教学的工作总结
  4. 解决 “数据大屏“ 展示的屏幕适配问题
  5. DistributionDB过大的原因
  6. IDEA+Maven:cannot download sources
  7. fdisk 创建和维护磁盘分区命令(MBR分区方案)
  8. java wifi 对讲机_freevoice(局域网对讲机)——Android4项目实战视频教程 - 移动编程 - 私塾在线 - 只做精品视频课程服务...
  9. 16款app源码下载收集
  10. windows 10上fastboot无法识别设备问题
  11. 基于html的火柴人羽毛球网页游戏设计
  12. 计算机类专业都有什么区别?
  13. nihao, woshi mr jhon
  14. linux startx无效_startx命令_Linux startx 命令用法详解:用来启动X Window
  15. 腾云忆想构建云化IT生态,助力我国“双循环经济”数字化升级
  16. FastFlow: Unsupervised Anomaly Detection and Localization via 2D Normalizing Flows
  17. 一个快速写PRD的方法
  18. 关闭CPU风扇灯的正确做法
  19. 贪心算法之活动安排问题
  20. hp服务器安装ghost系统安装,惠普电脑/HP笔记本无法安装GHOST系统的解决方法

热门文章

  1. Debian 10安装教程
  2. rk3128 debian9 如何配置recover键(长按开机进入loader模式)
  3. 用html5做一个视频网页,如何使用HTML5在网页上制作交互式视频?
  4. 如何学IT?零基础入门自学Java编程系列:java简介跟计算机常识
  5. Python中的图像处理(第六章)Python图像量化及采样处理(2)
  6. python实现局域网攻击_mac泛洪攻击arp欺骗(python脚本)
  7. 步步高s5pro和s5区别
  8. deepin 服务器_深度官方并没有提供Deepin服务器版下载,也没有开发计划
  9. Android面试题精选——再聊Android-Handler机制-2,android物联网开发李天祥源代码
  10. Python查找文件夹中含有指定关键字的文件