判别模型 vs 生成模型
判别模型对P(Y|X)进行建模
生成模型对P(X, Y)及P(Y)进行建模
参数化模型 vs 非参数化模型
参数化模型:参数的维度固定,如LR、朴素贝叶斯、Kmeans、GMM
非参数化模型:参数的维度随着训练数据量的增大而增大,如决策树、SVM、KNN、AdaBoost
回归模型 vs 分类模型
区别主要在于:
1、预测的label不同,回归label为连续值,分类label为离散值
2、损失函数不同,回归一般可用MSE,分类一般用交叉熵
3、评价指标不同,回归一般就用均方误差,二分类有准确率、召回率、精确率、敏感度、F1、AUC等
它的基本思想就是将原始数据(dataset)进行分组,一部分做为训练集来训练模型,另一部分做为测试集来评价模型。
交叉验证
均方误差
MSE,一般用于回归模型
准确率、精确率、召回率
都是用于分类模型
准确率 = (TN + TP) / (TN + TP + FN + FP)
精确率 = TP / (TP + FP)
召回率 = TP / (TP + FN)
当正负样本数量不平衡的时候,准确率不再具有参考意义
F1
F1是精确率和召回率的调和平均数
2 / F1 = 1 / P + 1 / R
PR曲线、ROC曲线
PR曲线是精确率-召回率曲线
ROC曲线是真正率-假正率曲线
ROC与PR曲线的对比
AUC
指曲线下面积,一般指ROC曲线的AUC
ROC曲线的AUC的物理意义:随机取一个正样本以及一个负样本,模型对正样本打分高于负样本的概率,相当于是一个序的关系
AUC的计算方法有三种,最简单的是把曲线画出来之后进行计算,另外两种是根据其物理意义进行采样计算:AUC的计算方法
特征工程的一般流程
样本不平衡会导致预测结果不准确,例如99%的样本都是负样本,那么只要模型永远预测为负,则模型的准确率可以达到99%,但这是没有意义的
通常可以用几种方法来解决:
1、改变预测分类的阈值
2、使用对类别比例不敏感的模型,比如决策树、SVM
3、改变评价指标,比如弃用准确率,改用AUC
4、对负样本进行负采样,或者对正样本进行过采样,还有一种合成样本的方法SMOTE(个人感觉不是特别靠谱),从而使得正负样本比例维持在一个合理的范围
补充:
当使用负采样方法时,因为改变了数据的分布,因此对模型的预测值需要进行修正
负采样的预测值校准公式推导
有三种:
1、过滤型:主要利用特征与label的相关度直接过滤特征
2、包裹型:每次增加/减少特征,进行交叉验证找出能提升模型效果的特征
3、嵌入型:模型本身就带有特征选择的能力,比如决策树、带L1正则化的LR等
数据清洗
缺失值清理:填经验值、均值、中位数等,或者如果缺失过多可以直接去掉这个特征
格式内容清理:统一同一特征的格式,剔除明显有问题的数据
修正逻辑错误:比如身份证生日与生日不符
关联性验证:剔除和label不相关或相关性太低的特征
统计不同特征取值的个数,以及不同取值的个数:取值很少的连续特征可以转化为离散特征,如果大部分的数据在这个特征上取值相同,可以去掉这个特征(关联性太弱)
数据清洗流程
数据增广
例如对图像进行剪切、平移、旋转从而产生多个与同一标签对应的数据
扩大数据集,且能提升模型的鲁棒性
数据增广
预处理
对连续特征进行归一化
把离散特征转化为one-hot编码(进一步转换为embedding向量)
变长特征根据情况进行处理
各种优化方法的比较
基于一个原理:负梯度方向是函数值下降最快的方向
简单证明:可以看成是损失函数的一阶泰勒展开,而方向相反的两个向量乘积最小
梯度下降法是机器学习中应用最广的优化方法,有众多变种(优化器)
梯度下降优化算法
Batch Gradient Descent / Stochastic Gradient Descent / mini-batch Gradient Descent
BGD比较准确,但速度慢,SGD速度快,但每次梯度更新方向不准,mini-batch是一个折中方案
Momentum Gradient Descent
引入动量概念,类似加速度,学习速度会越来越快,若梯度方向发生改变,则速度会变慢
Nesterov accelerated gradient(NAG)
Momentum的改进,在t时刻做优化的时候,预先估算在下一时刻的梯度,并对t时刻的梯度进行修正,这样可以保证参数变化速度不至于过快
Adagrad
对不同的参数自适应地选择不同的学习率,对于经常出现的特征使用较小的学习率,反之则使用大学习率,适合处理稀疏数据。优化器会累计每个参数的历史梯度,总历史梯度和学习率大小呈负相关,因此,学习率会随学习轮次增加而不断减小,导致最后无法再进行学习。
Adadelta
是Adagrad的一种改进,为了防止学习率无限单调递减,在累计参数的历史梯度时,Adadelta限制了时间窗。Adadelta不需要设置默认学习率。
Adam
Adaptive Moment Estimation,也是自适应对不同参数选择不同的学习率。可以看做RMSprop和Momentum的结合
AdaMax
Adam的一种变种
Nadam
可以看做Adam和NAG的一种结合
AMSGrad
Adam的一种改进,但并不一定比Adam好
梯度下降的改进策略
每个epoch对数据集进行shuffle,或者用curriculum learning学习出一种合理的数据顺序;Batch normalization;Early stop;给梯度增加噪音
牛顿法又名切线法,它的基本思想是对损失函数的二阶泰勒展开进行求导。
从本质上去看,牛顿法是二阶收敛,梯度下降是一阶收敛,所以牛顿法就更快。
从几何上说,牛顿法就是用一个二次曲面去拟合你当前所处位置的局部曲面,而梯度下降法是用一个平面去拟合当前的局部曲面,通常情况下,二次曲面的拟合会比平面更好,所以牛顿法选择的下降路径会更符合真实的最优下降路径。
但牛顿法需要计算二阶导,也就是Hessian矩阵,这是非常耗时且耗内存的
同时牛顿法仅在Hessian矩阵正定时可以保证取到极小值,否则可能是极大值或者鞍点
为了解决Hessian矩阵计算复杂的问题,拟牛顿法会构造一个正定的矩阵去拟合Hessian矩阵
常见的方法有:DFP,BFGS,LBFGS
拟牛顿法(DFP)的推导
共轭梯度法是介于最速下降法与牛顿法之间的一个方法,它仅需利用一阶导数信息,但克服了最速下降法收敛慢的缺点,又避免了牛顿法需要存储和计算Hesse矩阵并求逆的缺点,共轭梯度法不仅是解决大型线性方程组最有用的方法之一,也是解大型非线性最优化最有效的算法之一
如果所有参数的初始化值相同,那么每个神经元的输出也都一样,那么每次更新时,传递到每层的每个参数的梯度也都一样(因为w、x都一样),导致到下一次所有参数的值还是一样,这样一来神经网络就退化成了每层只有一个神经元的网络
所有参数用相同值初始化的问题
保证神经网络中每一层的输入的方差、均值不变,同时保证反向传播的梯度在每一层的方差、均值不变,这样一来网络才不会随着参数更新而失去初始化时的特性
Xavier初始化原理
常用激活函数的总结
特点:
它能够把输入的连续实值变换为0和1之间的输出,特别的,如果是非常大的负数,那么输出就是0;如果是非常大的正数,输出就是1
导数:sigmoid * (1 - sigmoid)
缺点:
1、存在饱和区(主要问题)
2、输出不是以0为中心的,全是正数,且梯度也全是正数
特点:
把连续实数转化为-1和1之间的输出
导数:1 - tanh ^ 2
缺点:
存在饱和区
特点:
分段函数,输入是正数则为线性输出,输入是负数则输出全0
在负数段导数为0,正数段导数为1
不存在饱和区,因此不容易出现梯度消失的问题
计算快,收敛快,使得一部分神经元输出为0,相当于增加网络的稀疏性,不容易过拟合
缺点:
会出现神经元死亡的问题,不适合大的学习率
神经元死亡问题解释
解决relu神经元死亡问题,主要是保证负数输入的梯度不为0
PReLU有一个可学习的参数p,f(x)=max(px,x)
Leaky Relu提供一个默认的小值,f(x)=max(αx,x)
具有relu的优点,没有relu的缺点
但是需要两套神经网络的参数,代价太大(类似于Double DQN)
Batch Normalization介绍
实现方法
对一个batch的数据,在神经网络的每一层,每一个神经元上进行归一化(减去偏差,再除以标准差),之后再进行一次偏移和缩放
偏移和缩放的值是学习出来的
在训练阶段,batch normalization是用一个batch的数据来计算bias和variance,但在测试阶段,是用全量的测试数据的bias和variance
原理及优点
1、保证神经网络每一层的输入的分布大致相同,从而使训练更加稳定
2、把神经元输入拉到0均值1方差,不至于落入激活函数的饱和区,缓解了梯度消失的问题
3、梯度里增加了一项1 / var,当参数普遍较大时,神经元输出会偏大(经过BN层之前),那么var也会相应的偏大,从而减小梯度的尺度,保证梯度不会因为参数过大而梯度爆炸;反之也可以保证梯度不会因为参数过小而梯度消失
4、给数据添加了一定噪声,有一定轻微的正则化效果
5、可以使用更大的学习率
Layer Normalization
不再计算一个batch内的mean和var,而是计算一个layer里的不同神经元的mean和var
实现方法
在训练阶段,对于隐层的每个神经元,以一定的概率使其输出为0
在测试阶段,计算所有神经元,但输出时乘以dropout的概率,保证和训练时数据的尺度一致
原理及优点
相当于做了集成学习,网络结构是随机的,最后的结果是不同网络结构平均的结果
因此可以降低过拟合,并且减少不同神经元之间的耦合度,增加网络的鲁棒性
产生梯度爆炸或者梯度消失的根本原因:链式求导法则的连乘造成的指数效应
解决梯度爆炸的方法:
梯度裁剪、使用Batch Norm、使用较小的学习率、参数初始化到较小的值、进行正则化(保证参数不会过大)
解决梯度消失的方法:
使用Relu激活函数、使用Batch Norm、参数初始化增大一点、引入残差
过拟合的解决方法
正则化、使用Batch Normalization、Early Stop、集成学习、Dropout、扩大数据集、降低网络复杂度、减少特征数量
欠拟合的解决方法
改变网络结构、改变模型、增加网络复杂度、调参、增加新特征、增加训练轮数、解决梯度消失和梯度爆炸问题
权重计算函数
1、Dot Product
2、Scaled Dot Product
3、Bilinear
4、网络学习
5、Cosine
各种Attention
1、Self Attention,Query和Key是一致的
2、Soft Attention,关注所有的Key,Query和每个Key都产生一个权重
3、Hard Attention,每次只关注一个Key,Query和Key产生的权重只有一个不为0
4、Local Attention,每次只计算一个窗口内的Key与Query的相似度,避免了大量的计算
LR公式推导
LR公式推导
LR为什么用sigmoid函数
LR是广义线性模型在样本分布为伯努利分布时的特殊情况,可以利用广义线性模型推导出LR的公式P(y = 1|x) = sigmoid(wx + b)
广义线性模型
LR与SVM的异同
同:
1、都是分类模型(也可用于回归)
2、如果不考虑核函数,那么他们都是线性算法
3、都是监督学习
4、都是判别模型
异:
1、本质上Loss函数不同,LR为log loss,SVM为Hinge Loss
2、所有样本对于LR模型参数都有贡献,而只有支撑向量对于SVM的参数有贡献,因此SVM不用担心数据不均衡的问题,但如果SVM的支撑向量存在异常,对结果影响很大,相对而言异常点对于LR的影响不大
3、LR只能解决线性分类问题,而SVM可以利用核方法解决非线性分类问题
4、LR是基于概率的,SVM是基于距离的,因此SVM对于数据的距离很敏感
5、SVM自带正则化项,LR必须自己添加正则化
为什么线性回归不能做分类,而逻辑回归可以
所有的点都会对这两个模型的参数做出贡献,对于线性回归而言,异常点会造成非常大的影响,而对于逻辑回归而言,异常点的影响被sigmoid函数压缩了
Ridge Regression、Lasso Regression
线性回归的变种,Ridge Regression是在线性回归的基础上增加L2正则化,Lasso Regression是在线性回归的基础上增加L1正则化
Logistic Regression如何实现并行化
按行并行(数据并行,梯度合并)、按列并行(特征并行)
LR并行化
多类分类推广
可以利用多个二分类模型组合成多分类模型,具体实现方法有one vs all、one vs one两种
也可以把LR推广为Softmax函数
Softmax推导
当各类互斥时,用softmax更好,当各类可以重叠时,用one vs all更好
SVM公式推导
主要是构造对偶问题,利用KKT条件,优化时使用SMO方法,每次优化两个alpha,第一个和第二个alpha选择策略不同
SVM公式推导
朴素的SVM只能解决线性可分的情况,而对于线性不可分的数据集,要引入软间隔来解决
Hinge Loss
带软间隔的SVM可以看做是以Hinge Loss为损失函数,带L2正则化的线性回归
Hinge Loss
核函数
使用核函数可以把样本映射到高维空间,在低维空间线性不可分的样本在高维空间往往是线性可分的,使用核函数后,没有办法预先计算出w和b,因为无法使用单独的某个x(被映射到了高维空间,而我们不知道这个高维空间的实际值,只知道在高维空间中两个x的内积),因此必须保留所有支撑向量以计算预测值
常见核函数
原理
朴素贝叶斯算法原理
Laplace平滑
为了解决数据不足时可能出现的P(xj | Ci) = 0从而导致的连乘为0的问题
在统计每种xj出现的次数时,从1开始累积而不是从0
属于生成模型,假设数据的总体分布是由多个高斯分布叠加得到的,而每一类数据都服从其中一个高斯分布
高斯判别模型公式推导
无监督版的GDA,把label当成一个隐变量,从而使用EM算法+GDA的优化方法来优化模型
高斯混合模型公式推导
三要素
K值、距离度量方法(欧拉距离、cosine距离等)、输出决策策略(通常为投票或者均值)
KD-Tree
KNN的优化算法,加快最近邻的计算速度,本质思想类似于二分查找,但数据是k维的
KD Tree原理
ID3、C4.5、CART
决策树原理
决策树优点:
1、可解释性强
2、对数据尺度不敏感
3、可以处理缺失值
4、预测速度快
5、对异常点不敏感
决策树缺点:
1、容易过拟合
2、样本小的变动会对树结构产生大的影响
3、难以学习复杂的函数关系
Gini系数的优点:
1、计算速度快,不需要进行log计算
2、二叉树结构更适合计算机计算
信息增益的问题:
1、倾向于选择取值数量多的特征
信息增益比的问题:
1、倾向于选择取值数量少的特征
缺失值处理
1、如果有单独的缺失分支,使用此分支
2、把待分类的样本的属性a值分配一个最常出现的a的属性值,然后进行分支预测
3、根据其他属性为该待分类样本填充一个属性a值,然后进行分支处理
4、在决策树中属性a节点的分支上,遍历属性a节点的所有分支,探索可能所有的分类结果,然后把这些分类结果结合起来一起考虑,按照概率决定一个分类
5、待分类样本在到达属性a节点时就终止分类,然后根据此时a节点所覆盖的叶子节点类别状况为其分配一个发生概率最高的类
决策树剪枝
决策树剪枝
预剪枝策略:作为叶结点或作为根结点需要含的最少样本个数、分裂所需要的最小样本数、决策树的层数、结点的经验熵小于某个阈值才停止
后剪枝策略:主要是交叉验证
三类集成学习方法总结
Bagging主要是减少方差
Boosting主要是减少偏差
Stacking可以结合多种不同的基模型,提升准确率
是前向分步模型在损失函数为指数损失函数时的特例
Adaboost原理推导
基学习器为决策树模型,行列都进行采样,降低过拟合
随机森林原理
XGBoost原理详解
GBDT、XGBoost、LightGBM的对比
XGBoost的改进:
1、基模型可以用线性模型
2、引入二阶信息计算残差,预测更加准确
3、支持并行化(特征分裂并行计算)
4、引入了行采样(不放回)、列采样从而降低过拟合
5、特征分裂点的候选减少(只检查几个分位点,还可以进一步优化,检查加权分位点)
6、提供了处理缺失值的方法(计算一个默认方向)
7、Loss函数增加正则化项,引入多层模型的shrinkage
8、所有特征预排序
9、内置交叉验证
LightGBM的改进:
1、特征分裂算法用直方图法(每个特征一个直方图,不需要预排序记录大量索引,同时离散化连续特征,节省内存;每个节点的直方图等于父节点的直方图减去兄弟节点的直方图,节省一半的直方图计算量;分裂值只考虑桶间值,大大减少计算量)
2、leaf-wise分裂策略(带深度限制防止过拟合)
3、支持直接输入分类特征
4、支持两种并行(特征并行,不同节点计算不同特征的分裂点;数据并行,不同节点计算部分数据的直方图,最后合并)
1、随机森林采用的bagging思想,而GBDT采用的boosting思想。这两种方法都是Bootstrap思想的应用,Bootstrap是一种有放回的抽样方法思想。虽然都是有放回的抽样,但二者的区别在于:Bagging采用有放回的均匀取样,而Boosting根据错误率来取样(Boosting初始化时对每一个训练样例赋相等的权重1/n,然后用该算法对训练集训练t轮,每次训练后,对训练失败的样例赋以较大的权重),因此Boosting的分类精度要优于Bagging。Bagging的训练集的选择是随机的,各训练集之间相互独立,弱分类器可并行,而Boosting的训练集的选择与前一轮的学习结果有关,是串行的。
2、组成随机森林的树可以是分类树,也可以是回归树;而GBDT只能由回归树组成。
3、组成随机森林的树可以并行生成;而GBDT只能是串行生成。
4、对于最终的输出结果而言,随机森林采用多数投票等;而GBDT则是将所有结果累加起来,或者加权累加起来。
5、随机森林对异常值不敏感;GBDT对异常值非常敏感。
6、随机森林对训练集一视同仁;GBDT是基于权值的弱分类器的集成。
7、随机森林是通过减少模型方差提高性能;GBDT是通过减少模型偏差提高性能。
只有一个参数K,属于懒惰学习
K-means原理
基于CF-Tree数据结构,节省内存,但因为每个节点有限制,聚类出来的类别数不一定符合实际
BIRCH原理
基于密度,可以聚类任意的形状分布
主要参数有:邻域半径、核心点的邻域内最小元素数量、距离度量方法
DBSCAN原理
基于二分图的最小割
谱聚类原理
原理是,方差最大的维度上保有的信息量最大,因此PCA要把数据投影到若干个方差最大的坐标轴上
PCA的原理
当类别信息包含在数据的偏差里而不是方差里的时候,PCA降维可能会丢失重要的信息
LDA是一种带监督的降维算法,思想是最大化类间方差,最小化类内方差
LDA最多降维到(类别数 - 1)维
LDA降维后保证了最佳的分类性能
LDA的原理
把输入值当做label,把隐层输出作为降维后的目标向量
半监督学习
局部感知(稀疏连接)
卷积神经网络有两种神器可以降低参数数目,局部感知野和权值共享。先来说说局部感知,一般认为人对外界的认知是从局部到全局的,而图像的空间联系也是局部的像素联系较为紧密,而距离较远的像素相关性则较弱。因而,每个神经元其实没有必要对全局图像进行感知,只需要对局部进行感知,然后在更高层将局部的信息综合起来就得到了全局的信息。即,局部感受野指卷积层的神经元只和上一层map的局部相联系。
参数共享
权值共享(也就是卷积操作)减少了权值数量,降低了网络复杂度。可以看成是特征提取的方式。其中隐含的原理是:图像中的一部分的统计特性与其他部分是一样的。意味着我们在这一部分学习的特征也能用在另一部分上,所以对于这个图像上的所有位置,我们都能使用同样的学习特征。
多核卷积
如权值共享的部分所说我们用一个卷积核操作只能得到一部分特征可能获取不到全部特征,这么一来我们就引入了多核卷积。用每个卷积核来学习不同的特征(每个卷积核学习到不同的权重)来提取原图特征
池化层的意义:
1、引入局部平移不变性(也得益于共享权重和稀疏连接)
2、减少网络参数个数
3、压缩信息,突出整体结构信息
4、解决不同输入尺度的问题(需要动态调整pooling大小)
由于稀疏连接、权重共享、以及尤其是池化层的存在,CNN有着一定的局部平移不变性
但CNN对于大的平移没有不变性
CNN没有旋转不变性以及形变不变性,但可以通过数据增广来使得CNN学习到少量的这样的不变性
其中 l k − 1 l_{k-1} lk−1是第k−1层的感受野大小,而 f k f_k fk是当前层的卷积核大小, s i s_i si是第i层的步长
主要解决的问题:
1、通过shortcut保留了梯度,避免了网络过深时梯度消失的问题
2、当网络过深时会出现退化问题,网络拟合能力变差,而增加的shortcut可以保留浅层学习到的结果,就像电路被短路一样,浅层结果可以直接连到输出层,避免了网络退化
最主要的结构是Depthwise CNN与Pointwise CNN
Depthwise CNN与一般CNN相比,每个卷积核只处理一个同道,因此节省了计算量,而这样一来就会丢失同一空间位置上不同通道信息的融合信息,所以在之后增加一个Pointwise CNN来融合不同同道的信息
MobileNetV2引入了残差模块,但由于MobileNetV2的feature map数量本来就很少,Residual的压缩操作会进一步丢失信息,因此MobileNetV2采用了与之相反的Inverse Residual,就是先把通道给扩张后再进行压缩,从而保留了信息
由于压缩操作会丢失信息,relu也会导致丢失信息,因此MobileNetV2在bottleneck结构的输出部分选择了linear输出不加relu激活函数
主要是两个操作,squeeze和extraction
squeeze操作是对输入的每个通道(假设有C个)进行average pooling,相当于会得到一个C维的向量
extraction把squeeze得到的C维向量输入到若干全连接层,学习不同通道之间的关系,得到C个权重,对应不同的通道
最后再将extraction得到的C个权重用来对原始输入的C个通道分别进行scale,这里其实相当于做了一个self-attention
将一个较大的卷积拆成两个连续的较小的卷积(5 × 5 = 3 × 3 + 3 × 3,3 × 3 = 1 × 3 + 3 × 1)
用多个不同大小的卷积核提取不同尺度的特征,再合并
Inception网络
思想是卷积不作用于所有通道,而是作用于一个通道组,但这也会导致不同通道组之间的信息没有融合,因此把每一层的通道shuffle再使用这种方案,增加不同通道组之间信息的流通
比较经典的方法有CBOW和Skip-Gram两种,都是基于上下文
CBOW认为上下文信息对应一个核心词
Skip-Gram认为一个核心词对应一组上下文
二者是相反的
训练一个三层的网络,输入是one-hot形式,隐层为embedding lookup后的中间embedding表示,输出为词袋里每个词可能出现的概率(Softmax后)
不同的上下文one hot向量embedding后直接求和得到隐层
输出的label为核心词的one-hot向量
一般来说会把核心词和上下文单词反过来,也即把上下文单词作为输入,核心词作为label
其实就是层次化Softmax,如果直接连接隐层和输出层的话,由于词袋里元素太多,参数量会过大,计算softmax很耗时,因此采用二叉树的形式连接隐层和输出层,每个中间节点是一个二分类器,要优化的是从隐层embedding向量到对应的输出label叶子节点路径上所有的二分类器
哈夫曼树可以保证高频词路径短,减少计算量
基于哈夫曼树的word2vec
一个中心词对应2c个上下文词,那么每一个上下文词和中心词构成一组正样本,再负采样neg个不相关的词,和上下文词构成负样本,训练二分类器(每个词对应一个二分类模型)
其实就是把softmax每个输出都看作一个二分类器,而每次不是更新所有的分类器,仅更新极少的负例对应的二分类器
基于负采样的word2vec
GloVe算法
RNN、LSTM、GRU图解
LSTM可以更好地保存长短期信息,个人认为是类似于ResNet的残差思想,因为LSTM每层都会加上前一层输出与遗忘门的积,且遗忘门的值一般接近0或者1,而RNN的梯度传导在每一层内都是乘的,因此容易梯度消失或者爆炸
LSTM为什么可以解决RNN的梯度消失问题
主要利用Attention机制,是一个可以取代RNN的结构
Transformer原理
其实就是多个Transformer连接,同时进行两个预训练任务,从而学习文本的状态表示
BERT原理
常见的几种算法:
1、textCNN 模型
2、charCNN 模型
3、Bi-LSTM 模型
4、Bi-LSTM + Attention 模型
5、RCNN 模型
6、Adversarial LSTM 模型
7、Transformer 模型
8、ELMo 预训练模型
9、BERT 预训练模型
文本分类算法
协同过滤算法原理
矩阵分解算法原理
分解的是user对item对打分矩阵
认为每个user对应一个隐兴趣向量,每个item对应一个隐特征向量,二者的内积就是user对item对打分
打分矩阵一般是很稀疏的,可用已有的打分去学习user和item的隐特征向量,用学习到的隐向量去预测user对item对打分
FM算法原理
解决稀疏的特征做交叉后变得更加稀疏,导致数据不足交叉特征的权重难以学习的问题
实际上就是把一个交叉特征但权重拆成两个隐向量的内积,每个特征对应一个隐向量
FFM算法原理
在FM模型中,每一个特征会对应一个隐变量,但在FFM模型中,认为应该将特征分为多个field,每个特征对应每个field分别有一个隐变量
MLR算法原理
多个LR,同时学习LR的参数以及每个LR的权重
最后将每个LR的结果进行加权求和
深度CTR模型的基础框架,特征先经过embedding,然后输入两个模型——Wide模型和Deep模型,其中Wide是一个单层的线性回归,Deep是一个DNN,两个模型联合训练,同时捕获浅层特征和深层特征
Wide&Deep模型的Wide部分是需要手动进行特征工程的,可以手动增加一些交叉特征
大部分的深度CTR模型是在这个架构上进行改进的
Embedding -> DNN -> Predict
Embedding -> Linear -> Predict
微软于 2016 年提出的模型,非常基础
Embedding -> DNN -> Predict
和Deep Crossing网络结构一样
Embedding -> DNN -> Predict
有所不同的是,FNN用预训练的FM模型的Embedding层参数作为自身Embedding层的初始化值,避免了完全从随机状态训练 Embedding,提升了训练的稳定性
这里的Embedding不仅包含FM侧的Embedding,还包括Linear侧的Embedding,因此在FNN模型中,每个稀疏特征经过Embedding后的维度实际上是FM中(Embedding的维度 + 1)维
与上面两个模型不同的是,NFM在Embedding后,现将特征进行两两交叉后再输入到DNN中
Embedding -> Bi-Interaction (Hadamard积,向量求和) -> DNN -> Predict
Logit Embedding -> Linear -> Predict
在FM上引入Attention机制,对交叉特征利用Self Attention计算各自权重,最后加权求和,AFM没有DNN
Embedding -> Bi-Interaction -> Attention Based Pooling -> Predict
Embedding -> Linear -> Predict
PNN算法原理
和NFM类似,但DNN的输入同时包括原始的Embedding特征以及交叉特征(内积或外积交叉),且交叉特征不加和,而是直接平铺输入
Embedding -> Inner / Outer Product (内/外积后按位求和) -> Concat Raw Embedding -> DNN -> Predict
原始的FM实际上是把稀疏特征的one-hot全部concat,把每一个element当作一个feature,每个feature对应一个隐向量,这实际上和把稀疏特征进行Embedding是一致的,因为实际上Embedding Matrix中每行向量对应One-hot中的一位
Linear部分是所有one-hot特征进行线性回归,这其实就相当于把所有稀疏特征进行一个1维的Embedding
一阶(Linear) + 二阶(FM) + 高阶(DNN)特征
Embedding -> FM (内积求和) -> Predict
Embedding -> Linear -> Predict
Embedding -> DNN -> Predict
Deep&Cross算法原理
把FM的二阶交叉特征扩展到高阶,具体做法是引入一个Cross Network结构,在网络的每一层用原始输入和中间输出做交叉,再引入一个残差项,这样一来,第N层的输出就变成了1 ~ N+1阶的交叉特征的加和
Embedding -> Cross Network -> Predict
Embedding -> DNN -> Predict
xDeepFM算法原理
原版的DeepFM实际上是一个“Deep and FM”,而xDeepFM真正做到了“Deep FM”
其思想和Deep&Cross是一致的,也是把交叉特征从二阶推广到高阶
但其论文发现,Deep&Cross的交叉特征是bit-wise的,也就是说,输入embedding后先做了concat后才接入Cross Network,所以Cross Network无法区分不同的Field
xDeepFM是Vector-wise的交叉,主要改进是引入了一个叫做CIN的结构,CIN使用了一种和CNN类似的构造,其每一层输入为一个(batch_size, n_field, m_embedding)维度的tensor,输出一个形状为(batch_size, h, m_embedding)维度的tensor
具体做法是,对于第 l k l_k lk层,把 l k − 1 l_{k-1} lk−1层的输出和原始输入x中的向量进行两两交叉(把隐层输出的每一行看作一个维度为m_embedding的特征),也就是输入层x的n_field个向量和隐层 l k − 1 l_{k-1} lk−1的 h k − 1 h_{k-1} hk−1个向量两两交叉(Hadamard积),得到 n f i e l d ∗ h k − 1 n_{field}*h_{k-1} nfield∗hk−1个向量,再用 h k h_k hk个权重向量对这 n f i e l d ∗ h k − 1 n_{field}*h_{k-1} nfield∗hk−1个向量进行加权求和,得到 h k h_k hk个输出向量,这和CNN中的Feature Maps非常相似
最后把每一层的 h k h_k hk个向量各自做Sum pooling,连接起来得到最终的交叉特征输出
Embedding -> CIN -> Predict
Embedding -> Linear -> Predict
Embedding -> DNN -> Predict
AutoInt算法原理
利用Multi-head self attention对embedding后的特征进行重加权组合,用于最终的预测
Embedding -> Multi-head self attention -> Predict
CCPM算法原理
把特征stacking后作为一个图输入CNN中提取组合特征,感觉不是很靠谱,CNN只能捕捉到局部特征组合,对特征组合顺序敏感
FGCNN算法原理
也是基于CNN,CCPM的改进
使用重组层进行特征生成缓解了 CCPM 中 CNN 无法有效捕获全局组合特征的问题
实际上就是用一个全连接层去组合上一次CNN提取到的特征,但感觉毕竟CNN对特征输入顺序敏感,后面再怎么组合也没有从本质上解决这个问题(低层次特征依赖特征顺序),而且全连接层很浪费资源,个人觉得也不是很靠谱
NFM的一种改进,用Bi-Linear方式进行特征交叉,也就是 x 1 W x 2 x_1Wx_2 x1Wx2的形式,这相当于把FM变成了FFM,因为每个特征和不同的特征进行交叉时,所用的向量不同
Embedding -> Interaction (Bi-Linear) -> DNN -> Predict
Embedding -> Linear -> Predict
DNN的输入分为两部分,一部分和NFFM一样,另一部分embedding先使用SENet重组,再进行NFFM的操作
Embedding -> Interaction (Bi-Linear) -> DNN -> Predict
Embedding -> SENet -> Interaction (Bi-Linear) -> DNN -> Predict
强化学习是一个智能体与环境交互试错的过程,就是智能体根据环境的状态state,利用已学习到的策略policy,决策出一个动作action并在环境中执行,最后获得动作对应的回报reward的过程。
环境中一个连续完整的state、action序列称为一个轨迹 τ \tau τ(智能体连续决策产生的轨迹)
强化学习的目的是找到一个最优的策略,使得轨迹的期望回报值最大。
强化学习里经常用到两个重要的值函数
一个是V,V是state的函数,表示根据当前策略,从某个状态s开始,期望获得的reward
一个是Q,Q是state和action的函数,表示根据当前策略,从某个state开始,执行某个动作action后,期望得到的reward
其中V函数与Q函数满足以下关系:
优势(Advantage)值函数:
对于强化学习而言,探索和利用是一对互相权衡的概念,利用exploit是用已有的知识去做决策,这样产生的动作更准确;探索explore是指使用较为随机的动作去探索未知的知识,这样产生的动作准确度会很低,但其中可能包含一些回报很高而以前又从来没有尝试过的新动作,智能体可以从这些有效的新知识里面学到更优的策略,从而在以后的expolit中可以产生更加准确的动作。
如果只探索而不利用,会导致产生的数据大部分都是没有什么意义的垃圾数据,智能体难以有效地学习,而如果只利用不探索,则会导致产生的数据基本都是已知的知识,智能体难以学到新的更有效的方法。平衡两者的使用才能使得算法高效地学习。
RL中常见的探索方法:
1、 ϵ − g r e e d y \epsilon-greedy ϵ−greedy,以一定的概率随机选择一个动作,否则选择值函数最大的动作,一般用于基于值的强化学习模型中
2、根据策略提供的概率直接采样,一般用于基于随机策略的强化学习模型中
3、UCB,基于计数的探索方法,被选的次数越多,越不容易再被选中,Alpha go用过,但那是对蒙特卡洛树探索的时候用的,直觉上不同的s应该对a有独立的计数,但这在s连续的时候根本无法做到
4、乐观初始化,把初始Q值设置的很大,但只适合普通的Q-learning,DQN之类需要估计Q值的就没办法了
5、Random Start,前n局游戏随机选择动作,之后再按照policy选择动作
6、在确定动作值上加一个小的噪声进行探索,用于DDPG等基于确定策略的模型
二者的本质区别在于,
对于on-policy算法,目标策略和行为策略是同一个,包括Q-learning、DQN、DDPG、TD3、SAC等
对于off-policy算法,目标策略和行为策略不是同一个,包括Reinforce、TRPO、PPO、A3C等
目标策略是指最终得到的策略,行为策略是指产生数据进行采样的策略
on-policy算法收敛快,但可能会陷入局部最优,且更新需要完整的轨迹
off-policy算法通常可以使用Replay Buffer,数据利用效率高,可以收敛到全局最优,且探索的更加全面,可以每步更新,但是收敛很慢
在RL中,策略通常表示为一个参数化模型,通过学习确定策略参数
随机策略学习的是一个概率函数 π ( a ∣ s ) \pi(a|s) π(a∣s),表示在状态 s s s下,输出动作 a a a的概率
确定策略学习的是一个具体的动作值 a = μ ( s ) a=\mu(s) a=μ(s),表示在状态 s s s下,固定输出的动作 a a a的值
随机策略的探索可以直接基于输出的各个动作的概率值进行动作采样
确定策略因为输出的是一个固定的动作值,因此其本身无法进行探索,需要借助其他方式进行探索,因此基于确定策略的模型都是off-policy的
基于策略的模型直接学习策略参数
基于值的模型的策略实际上是一个贪心策略,也即每次贪心地挑选使得值函数最大化的动作,其原理是基于Bellman方程的最优策略形式的
如果可以确定状态转移方程,就可以说model is given,此时实际上强化学习智能体不需要实际与环境交互就可以确定直接求解,相当于变成了动态规划问题
而大部分时间我们是无法确定状态转移方程的,因此model是未知的,需要建立model,或者不建立model而通过和环境交互获取reward信息
如果自己建立模型拟合状态转移方程,且智能体基于这个学习到的model进行学习,那么就是model based,否则就是model free
基于Bellman公式进行更新(TD-error)
基于表格的RL算法(Q值用二维表格存储),因此只能处理离散状态、离散动作的问题
可以证明Q-Learning的收敛性
和Q-Learning非常相似
但是这个TD的部分中,对下一个状态的回报值预估使用的动作是 a t + 1 a_{t+1} at+1,也就是智能体在 t + 1 t+1 t+1时刻实际执行的动作,而不是一个贪心值 a r g m a x a ′ Q ( s t + 1 , a ′ ) argmax_{a'}Q(s_{t+1}, a') argmaxa′Q(st+1,a′),这也就是说,Sarsa算法进行采样的策略和优化使用的策略是同一个,因此Sarsa算法是on-policy的
为了解决Q-Learning不能处理连续状态的问题,引入DNN网络来估计Q值,输入的s可以是连续值,但因为还是基于值的方法,本质上是贪心策略,所以动作值没有办法也做成连续的
DQN解决了两个主要的问题:
1、因为RL与环境交互中产生的数据前后之间相关性太强,违反了机器学习中样本独立同分布的假设,从而会造成学习效果很差。因此DQN引入了Experience Replay机制,把过去交互产生的数据全部缓存起来,在训练时随机从中进行采样,这样就打破了样本之间高度相关的问题,同时提高了数据利用效率
2、在TD-error中,预测值 Q ( s t , a t ) Q(s_t, a_t) Q(st,at)和目标(label)值 Q ( s t + 1 , a r g m a x a ′ Q ( s t + 1 , a ′ ) ) Q(s_{t+1}, argmax_{a'}Q(s_{t+1}, a')) Q(st+1,argmaxa′Q(st+1,a′))是相关的,这会导致学习的不稳定。因此DQN引入了目标(target)网络,其参数是从当前估值(eval)网络的某个历史状态复制过来并固定的,因此在训练中,能够保证目标值相对稳定,和估计值的相关性降低,从而提升的学习的稳定度
T D = R ( s t , a t ) + γ m a x a ′ Q t a r g e t ( s t + 1 , a ′ ) − Q e v a l ( s t , a t ) TD = R(s_t, a_t) + \gamma max_{a'}Q_{target}(s_{t + 1}, a') - Q_{eval}(s_t, a_t) TD=R(st,at)+γmaxa′Qtarget(st+1,a′)−Qeval(st,at)
普通的DQN容易产生过估计的问题,因为目标值的计算中存在一个max操作,从而容易选择到被过估计的Q值,而因为过估计了目标值,导致估计值也朝着一个过高的目标进行学习,也产生了过估计,这个问题会沿着Bellman公式不断传导,从一个点扩散到全局,对学习造成严重的影响
而对于被低估的Q值,低估的问题却不会被传导,也是因为max操作的存在,被低估的Q值比较难以被选中
Double DQN的思路是从max操作入手,如果选择的值不再是最大值,那么过估计问题被传导的可能性就会下降。Double DQN利用了DQN本身就存在的两个网络这一点,把Q值的估计以及动作值a的选择解耦,分别用不同的网络进行,这样就可以降低过估计出现的概率
T D = R ( s t , a t ) + γ Q t a r g e t ( s t + 1 , a r g m a x a ′ Q e v a l ( s t + 1 , a ′ ) ) − Q e v a l ( s t , a t ) TD = R(s_t, a_t) + \gamma Q_{target}(s_{t + 1}, argmax_{a'}Q_{eval}(s_{t+1}, a')) - Q_{eval}(s_t, a_t) TD=R(st,at)+γQtarget(st+1,argmaxa′Qeval(st+1,a′))−Qeval(st,at)
Duel DQN原理
Duel DQN把估计Q值转化为同时估计V值以及A值函数
其做法是将神经网络最后一层拆成两部分,一部分连接一个单神经元输出层,预测V,另一部分连接多个神经元的输出层,预测A,而Q = V + A
按照作者的说法,这样可以使得训练更加稳定
学习一个分布,而不是一个值
代码实现
C51算法原理
基于值的RL算法有个重要的缺点,因为其策略是贪心策略,因此动作值必须是离散值,而在实际问题中动作值往往是连续的,那么就需要使用基于policy的算法了
Policy Gradient公式推导
PG算法是所有基于Policy算法的原型,基于Policy的算法直接对Policy参数进行优化
PG算法的目标是最大化期望累积回报值,因此可以把这个期望累积回报值作为Loss函数,计算其对Policy参数的梯度,进而用梯度下降法直接优化Policy参数,这就是策略梯度这个名字的由来了
基于定理
由于 b ( s t ) b(s_t) b(st)在这里是一个常数,因此我们有:
从而有:
这里 b ( s t ) b(s_t) b(st)被称为baseline,通常取一个只与 s t s_t st相关的函数,一般是V值函数
利用baseline,我们可以降低估计的方差
公式中的R其实也可以用Q取代,证明
实际上我觉得也可以从一开始就用Q函数做推导,DPG就是这么干的
主要是为了解决PG算法中学习率难以确定的问题,其核心思想是保证对于Policy的每次更新,期望累积回报单调递增
TRPO算法原理
TRPO公式推导
TRPO算法效果很好,但实现复杂,且参数更新要计算和存储Hessian矩阵,速度很慢
PPO算法是TRPO算法的一种工程改进,是OpenAI的默认算法
一种做法是通过clip操作限制更新的步长
PPO原理及推导
Actor-Critic框架包括两个模型,一个Actor模型,用于估计Policy,一个Critic模型,用于估计值函数
在这个框架下,Actor会在Critic的指导下进行Policy参数的学习,实际上就是Baseline Policy Gradient的方法,可以降低估计的方差,提升算法效果
Policy Gradient算法的分布式版本,有一个异步版(A3C)和一个同步版(A2C)
算法如下:
简单来说就是有一套全局global Actor-Critic模型参数,多套local Actor-Critic模型参数,local模型每次先从global模型处复制参数,之后并行地和环境交互并获取数据,计算得到的梯度累积起来,定时更新global模型的参数
通过并行化,一方面提高了速度,另一方面由于更新global模型的梯度来自于多个不同的环境,这就一定程度上打破了训练数据高度相关的问题,使得训练更加稳定
这里其实有一个问题,就是不同的local模型由于完成游戏的时间不同,导致他们新游戏开始时间不同,那么从global模型处复制参数的时间就不同,导致其实不同local模型使用的参数是global模型的不同历史版本,相当于变成了一个off-policy的模型,因此A2C通过同步各个模型的游戏开始时间来解决这一问题
原版的PG算法是随机策略算法,其估计的策略 π ( a ∣ s ) \pi(a|s) π(a∣s)需要在整个状态空间以及动作空间中进行探索,DPG算法将随机策略改变成确定策略,直接估计动作值 μ ( s ) \mu(s) μ(s),从而减小了探索空间,降低了算法对于数据量的需求
但确定策略无法得到动作的概率值,因此无法用PG的算法进行优化,所以DPG采用了Actor-Critic的架构,通过最大化Critic对动作的评价值来优化策略网络
而由于确定策略的引入,导致算法不能以PG的方法进行探索,需要将算法变成off-policy的,通过在动作值上添加一个小的扰动进行探索
跟DPG没有本质的区别,只是用DQN的方法来进行Q值的预测
算法架构:
TD3算法原理
DDPG的一种改进,包含6个网络,主要做了三个改进
Twin:引入两个Q值估计网络,在计算目标Q值时使用两个网络中估计较小的那个值,从而缓解过估计问题(至于为什么不采用DDQN的方法,是因为DDPG的target网络更新是poyak更新,与eval网络区别不够大)
Delay:Policy网络相比于Q值网络延迟更新,这是为了保证Q值网络学习到一个较好的状态,再开始Policy的学习,增加学习的稳定性
Clip:为估计的动作值增加一个小的扰动,并进行尺度裁剪,从而保证学习的鲁棒性
SAC算法原理及推导
Actor-Critic算法的改进,是一种随机策略算法,可处理连续动作(采用了重参数化技巧)和连续状态
核心思想是在损失函数中加入策略熵,学习策略熵的最大化,相当于鼓励探索,且倾向于多样化的策略(输出动作多样性增加)
MADDPG论文翻译
每个Agent对应一套Actor-Critic
Actor和普通DDPG的一样,而Critic的输入除了Agent自身的动作之外,还要输入其他Agent的动作,从而使得模型可以学习到不同Agent之间的合作/竞争关系
多关照池子里td-error大的那些experience,这些能够帮助我们更有效地更新网络
两个变种,alpha越大,优先级的体现越大
用SumTree数据结构来采样,省掉了排序
因为不同的样本有不同的权重,所以在梯度更新的时候也要加上权重,这里用到了重要性采样(加了归一化)
HIRO算法原理
是一种off-policy的层次强化学习框架,数据利用效率较高
off-policy导致随着学习的进行,下层网络的参数已经发生变化,但上层网络Replay中的数据记录的还是在当时的下层网络策略下产生的goal、reward,而由于上层网络的动作并不是一个实际和环境交互的动作,而是指导下层网络选择动作的一个隐藏状态,在下层网络策略改变后,原先的goal不再对应原先的action序列,从而不再对应原先的reward,这就造成了Replay中goal和reward的不匹配。
HIRO算法利用了一种Relabel的技术解决这个问题,其实做法相当暴力,就是在原先的goal和state之间随机选择10个不同的goal,选择其中能够使得现在的下层网络策略产生与原先动作序列最相近的动作序列的goal,替换原有的goal
例如GAIL算法,无法从环境中获取reward,而是直接学习reward,属于仿人学习(Imitation Learning)的一种
仿人学习介绍
可以构造多个二分类器,每个二分类器对应一个标签,判断一个样本是否属于这个标签
如果先下降然后不下降了,可能是遇到了瓶颈,考虑减小学习率,也可能欠拟合,考虑欠拟合解决方案
如果从一开始就不下降,可能网络设计不合理、学习率过大、数据有问题、没有归一化输入、梯度爆炸/梯度消失
如果训练loss下降,测试loss增大,是过拟合
如果下降但很慢,可能学习率太小