大家好,今天我来梳理一下机器学习、算法、数据挖掘等岗位面试时必备的知识点,欢迎收藏学习,喜欢点赞支持。
机器学习主要分为监督学习和无监督学习。
- 有监督学习:对具有标记的训练样本进行学习,以尽可能对训练样本集外的数据进行分类预测。(LR、SVM、BP、RF、GBRT)
- 无监督学习:对未标记的样本进行训练学习,比发现这些样本中的结构知识。(KMeans、DL)
监督学习
回归
线性回归
所谓的线性回归,就是要找一个线性的超平面,去尽可能地拟合各个样本点。在一维的情况下,如图所示:
我们要寻找一条直线,让它尽可能地穿过这些点。“尽可能”可能有一些度量,比如说让误差平方和最小。
求解这条直线的方法有最小二乘方法等。
线性回归是一种简单但却使用的回归技术。
多重共线性(Multicollinearity)是指线性回归模型中的自变量之间由于存在高度相关关系而使模型的权重参数估计失真或难以估计准确的一种特性,多重是指一个自变量可能与多个其他自变量之间存在相关关系。共线性不影响模型的预测而是影响对模型的解释。神经网格本来可解释性就差,就不存在这种共线性的问题。
岭回归
lasso回归
分类
k最近邻分类
所谓物以类聚,人以群分,你的圈子基本决定了你的状态。我们可以用周围的邻居来判断自己的情况,基于这个思想,就有了k-NN算法。k近邻算法不仅可以用于分类,也可以用于回归,我这里将它放在了分类的条目下。
分类问题中,一个对象的分类是由其邻居的“多数表决”确定的,k个最近邻居(k为正整数,通常较小)中最常见的分类决定了赋予该对象的类别。若k=1,则该对象的类别直接由最近的一个节点赋予。无论是分类还是回归,衡量邻居的权重都非常有用,使较近邻居的权重比较远邻居的权重大。例如,一种常见的加权方案是给每个邻居权重赋值为1/d,其中d是到邻居的距离。这样会避免一些单纯计数带来的问题。
k 参数的选择可以使用交叉验证和自助法等等。
k-近邻算法的缺点是对数据的局部结构非常敏感。
三要素:
- k 值的选择
- 距离的度量(常见的距离度量有欧式距离,马氏距离等)
- 分类决策规则 (多数表决规则)
k 值的选择
k 值越小表明模型越复杂,更加容易过拟合。k 值越大,模型越简单,极端情况如果 k=N 的时候就表明无论什么点都是训练集中类别最多的那个类。所以一般 k 会取一个较小的值,然后用过交叉验证来确定。这里所谓的交叉验证就是将样本划分一部分出来为预测样本,比如 95% 训练,5% 预测,然后 k 分别取1,2,3,4,5之类的,进行预测,计算最后的分类误差,选择误差最小的 k。简单地来说,就是试一试。
KNN 的回归
在找到最近的 k 个实例之后,可以计算这 k 个实例的平均值作为预测值。或者还可以给这 k 个实例添加一个权重再求平均值,这个权重与度量距离成反比(距离越大,权重越低)。
优缺点:
KNN算法的优点:思想简单,理论成熟,既可以用来做分类也可以用来做回归;可用于非线性分类;训练时间复杂度为O(n);准确度高,对数据没有假设,对 outlier 不敏感。
KNN算法的缺点:计算量大;样本不平衡问题(即有些类别的样本数量很多,而其它样本的数量很少);需要大量的内存。
KNN 算法中 KD 树的应用
我们知道在上述 KNN 的计算中,我们要找一个点的 k 近邻,必须要计算这个点到所有点的距离,再取小的一部分。这个计算量超大。KD tree 就是为了解决这个问题的。顺着 KD tree 去搜索,我们可以很快地找到一个点的最近邻,而不需要计算这个点到所有点的距离。
当点随机分布的时候,搜索的复杂度为log(N),N 为实例的个数,KD 树更加适用于点的
数量远大于空间维度的 KNN 搜索,如果空间维度与点个数差不多时,它的效率基于等于线性扫描。
关于 KD 数的构建,搜索和 KNN 查找,网上有很多资料,这里就不介绍了。
可以观察到 KD-tree 是这样一种 tree。它的第一层的第一个元素大于左子树的第一个元素,小于右子树的第一个元素。第二层的第二个元素大于左子树的第二个元素,小于右子树的第二个元素。第 i 层的第 i%k 个元素大于左子树的第 i%k 个元素,小于右子树的,依次类推。
朴素贝叶斯分类
朴素贝叶斯真的很朴素,用到的仅仅只是贝叶斯公式。以二分类为例,它给定若干组的带标签的数据,当新给一组特征时,我们需要判断它属于哪一类。
我们通过比较这组特征下的条件概率P(标签1∣{特征1,特征2,特征3})和P(标签2∣{特征1,特征2,特征3})大小来对其分类。条件概率的计算可通过贝叶斯公式来计算,即
P(标签i∣{特征1,特征2,特征3})=P({特征1,特征2,特征3})P({特征1,特征2,特征3}∣标签i)∗P(标签i)
我们假设特征之间是独立的,那么就有
P({特征1,特征2,特征3}∣标签i)P({特征1,特征2,特征3})==P(特征1∣标签i)∗P(特征2∣标签i)∗P(特征3∣标签i)P(特征1)∗P(特征2∣标签i)∗P(特征3)
这些量和**P(标签i)**都是可以通过统计已有的样本数据,用频率来概率得到。
注意要,使用朴素贝叶斯分类方法,我们假设了特征之间相互独立,看起来很有局限。事实上,我们在处理文本数据的时候,常常用到这种方法。
主要就是利用贝叶斯公式,把某组特征下产生某个标签的概率进行了拆解,进一步拆解是利用到了特征之间的不相关性。
基本过程如下:
- 假设现在有样本 x=(a1,a2,a3,…an) 这个待分类项 (并认为 x 里面的特征独立)。
- 再假设现在有分类目标 Y={y1,y2,y3,y4…yn}。
- 那么 max{P(y1∣x),P(y2∣x),P(y3∣x)…P(yn∣x)} 就是最终的分类类别。
- 而根据贝叶斯公式 P(yi∣x)=P(x)P(x∣yi)∗P(yi)。
- 因为 x 对于每个分类目标来说都一样, 所以不用管分子,就是求 max{P(x∣yi)∗p(yi)}。
- P(x∣yi)∗P(yi)=P(yi)∗j=1∏n(P(aj∣yi))
- 而具体的 P(aj∣yi) 和 P(yi) 都是能从训练样本中统计出来:p(aj∣yi) 表示该类别下该特征出现的概率,p(yi) 表示全部类别中这个这个类别出现的概率。
就这么简单。特征为离散值时直接统计即可(表示统计概率)。特征为连续值的时候假定特征符合高斯分布。
拉普拉斯校验
当某个类别下某个特征划分没有出现时,会有 P(a∣y)=0, 就是导致分类器质量降低, 所以此时引入 Laplace 校验,就是对每个类别下所有划分的计数加1。
特征不独立问题
参考改进的贝叶斯网络,使用有向无环图来进行概率图的描述。
优缺点
- 优点: 对小规模的数据表现很好,适合多分类任务,适合增量式训练。
- 缺点:对输入数据的表达形式很敏感 (离散、连续, 值极大极小之类的) 。
logistic回归
逻辑回归在有些书中也叫对数几率回归,常用于分类问题,特别是二分类问题。逻辑回归是线性回归的一个延伸,对于二分类问题,我们需要将回归的连续值搞成离散值,基本做法是看其是否大于零。那么参数如何选取呢?所谓的逻辑回归,就是我们在原有的线性回归的基础上,外套一个Sigmoid函数作为取值的概率(准确地来说,应该是取值为正样本 1 的概率),其实上也就是:
p(y=1∣x)=1+ewTx+bewTx+bp(y=0∣x)=1+ewTx+b1
我们通过最大似然估计来估计参数,最大似然估计就是写出在参数下出现这个结果的概率(为了计算方便,一般取个对数),然后对于参数变量,极大化这个概率值,一般可以直接对参数直接求导。其实,也就是极大化如下的似然函数。
ℓ(w,b)=i=1∑mlnp(yi∣xi;w,b)
所谓的Sigmoid函数,它的表达式和图像如图所示,图像右端y的取值表示将线性回归的连续值按零点离散化。
逻辑回归的并行化最主要的就是对目标函数梯度计算的并行化。逻辑回归的条件分布是伯努利分布,而线性回归的是高斯分布。逻辑回归认为函数其概率服从伯努利分布,将其写成指数族分布的形式,最后是可以推导得到 sigmoid 函数,这也是用这个函数的原因。
逻辑回归用于多分类:
对于多分类问题,我们可以用 softmax,这时候优化的参数,不是向量,而是矩阵θ。我们用线性函数外套一个 softmax 作为每个第 j 个类别取值的概率:
pj=∑s=1keθsTxeθjTx
别的过程是一样的。
优缺点:
优点
- 实现简单。
- 分类时计算量非常小,速度很快,存储资源低。
缺点
- 容易欠拟合,一般准确度不太高。
- 只能处理两分类问题(在此基础上衍生出来的 softmax可以用于多分类),且必须线
性可分。
支持向量机
支持向量机,我们先说线性的情况,以可分的二维的二分类问题为例,它其实上就是寻找一根直线,将平面上的数据点正确地分为两类,并满足分割的间隔达到最大。如图所示,
要分割(a)所示的数据点,显然(b)的分割间隔要大于©的分割间隔。这里可变参数是分割线(“决策面”)的斜率和截距。所谓的间隔就是分割线离两个数据集合的距离,它是用离它最近的一个点来衡量的。我们引两根平行于分割线的面,相切两个数据集,那么就形成了一个间隙。这个间隙内部不含任何的数据点。间隙边缘上的点称作支持向量。
如果将直线表示为w Tx +b =0,那么合理的分割如图。
通过数学推导,我们可以知道,这个问题其实就是求解如下的一个优化问题(w 和b 是待求变量):
KaTeX parse error: Unknown column alignment: @ at position 70: …\begin{array}{r@̲{\quad}r@{}l@{\…
其中yi∈{−1,1},表示两类样本的标签。通过最优化的基本理论(拉格朗日对偶,KKT条件,SMO算法等),我们可以求解这个优化问题。
一般情况下,数据点不一定可以通过一个线性的超平面将其分开。那么我们可以将其映射到更高维的空间中,使其在高维的特征空间中线性可分,通过线性SVM方法将其分开。
线性情况下,最后的决策面的表达式可以表示为f(x)=i=1∑nαiyi⟨xi,x⟩+b,这里的αi是原问题拉格朗日乘子系数。对应于高维特征空间,使用线性SVM方法,最后决策面的表达式为:
f(x)=i=1∑nαiyi⟨Φ(xi),Φ(x)⟩+b,也就是说,分类决策函数只依赖于输入x与训练样本的输入的内积。
这里的Φ是原始空间到高维空间的一个映射,比如说它可以是(x,y)→(x,y,x2+y2)。因为升维可能造成计算量暴涨,我们寻求一种方法可以直接计算内积⟨Φ(xi),Φ(x)⟩,即寻找一个函数k(xi,x)来表示⟨Φ(xi),Φ(x)⟩,这种替换技巧叫做核技巧。因为核函数方法的存在,使得高维空间中的两个向量的内积可以直接计算,大大减少了计算量。
高维空间的决策平面用核函数来表达,那么高维空间中的对偶问题等也可以用核函数来表达,当使用SMO算法迭代求解时,计算量就会大大减小。简单地说,核方法通过用核函数表示高维空间中向量的内积,将原空间升维至高维空间和在高维空间中使用线性SVM方法两个步骤合成了一个步骤。所谓的升维,也可以理解为在原来线性基的基础上,添加一些非线性的基函数,使得分割线不再是直线。
常用的核函数为径向基函数,它的表达式为:
κ(x1,x2)=e2σ2−∣∣x1−x2∣∣2
σ越小,非线性化程度越高。如果σ选得很小,则可以将任意的数据映射为线性可分。这有可能会过拟合问题。
常用核函数有:多项式核函数、高斯核函数、字符串核函数。
数学推导:
关于第一步的数学推导,我们只需要有以下的几个基本认知:
- 我们用线性水平集函数z=wTx+b的零水平集wTx+b=0来表示决策面。
- 点到决策面的距离是:
r=∥w∥∣∣wTx+b∣∣.
这里的∥w∥实际上是表示这个水平集函数的斜率。 - 因为斜面的斜率不影响决策面,那么就不影响分类的结果,那么对于上述问题,事实上就多了一个自由度。那么我们就可以限制 w,是的支持向量的距离 $d = \frac{1} {|\boldsymbol{w}|} $。那么约束的目标函数实际上就有了。
- 上述约束,其实也就以为着,对于决策点 ∣∣wTx+b∣∣=1,那么要想其他点正确地分类,自然而然地就有:
{wTxi+b⩾+1,wTxi+b⩽−1,yi=+1yi=−1
优缺点:
优点:
- 使用核函数可以向高维空间进行映射,可以解决非线性的分类。
- 分类思想很简单,就是将样本与决策面的间隔最大化。
- 分类效果较好。
缺点:
- 对大规模数据训练比较困难。
- 无法直接支持多分类,一般使用间接的方法来做。直接方法可以在目标函数上下功夫,但计算量比较大。间接法有两种,一种是一对多,即取出一类作为一类,另外的 N-1 类作为一类,做一次二分类,接着在分得的子类中重复这个操作。第二种是一对一,即两两之间都进行一次分类,最后看哪一类被分到的次数最多,就选哪一类(vote 的思想,libsvm,可以用循环图加速)。
其他
随机梯度下降
我们知道,在做有监督的问题中,有一个损失函数,用来衡量模型的好坏。在回归问题中,如果我们已经知道方程的形式,我们可以做出问题的损失函数。那么我们要做的就是寻找方程的最佳参数,即寻找参数,使得损失函数函数达到最小。乍一听,这就是个优化问题。当然可以对参数的各个分量求导,最后解方程组。问题是,你能确定最后的方程组好解?一般的数值解法有梯度下降法、牛顿法、拟牛顿方法以及信赖域方法等等。
梯度下降方法简单易行,可是当数据量比较大时,梯度下降的计算就特别大。为解决大数据量的优化求解,我们一般可以采用随机梯度下降。
所谓的随机梯度下降,就是相比梯度下将,我们不选择全部的数据点,而是每次随机选择一个或者若干个数据点来构建损失函数,接着再用梯度下降方法求解。看起来很不靠谱的样子,事实上多做几次这个操作,它是可以收敛的最优解的某个邻域的。
随机梯度下降比起梯度下降:
- 可以避免局部极值
- 收敛速度快
- 易并行
说完随机梯度下降,顺便提一下 Adam加速,Adam使用动量和自适应学习率来加快收敛速度。其在SGD基础上加入了一、二阶动量。
AdaGrad 能够实现学习率的自动更改。如果这次梯度大,那么学习速率衰减的就快一些;如果这次梯度小,那么学习速率衰减的就满一些。
线性判别分析
所谓的线性判别分析(LDA),实际上是一种有监督的降维方法。之所以把它放在分类的标题下,是因为数据通过这种方式,在距离上有了更高的区分度,也可以说是为后续的分类做了降维处理。
线性判别分析,以二维数据点举例,就是要一条直线,使得数据点在这根直线上的投影满足类内方差尽可能小,类间距离尽可能大,如图所示。
投影面的选择,往往会影响类内方差,和类间距离。显然图所示的右边一个图更能满足我们的要求。
我们将类间距离的度量作为分子,类内距离的度量作为分母,形成一个目标函数,我们要做的就是最大化这个目标函数。利用广义瑞利商等一些基本的知识,我们就将问题转化为了求特征值的问题。
决策树
决策树,顾名思义就是像树一样不断分支。我们对每个特征,选择一定的条件进行判断,就可以将数据不断地分类,直到最后叶子节点满足一定的条件,比如说有同一个标签,那么这就是一棵决策树。举个例子,比如说西瓜好坏的判断,从数据中,我们可能会学习出如图所示的一棵决策树。
分类问题,往往是给定若干组数据,每组数据有一些特征和标签。需要找一棵决策树,使得每组数据按照决策树路径走,最后尽可能地能走到使它正确分类的叶子节点中。一般来说,可能满足条件的决策树有很多,用于做判断特征选择的次序和特征判断条件(阈值设定不同等)的不同都会导致树的不同,我们要做的就是找一棵最好的树。在不同的算法中,“好”的标准往往不同。
比较常用的决策树有ID3、C4.5和分类回归树(CART),他们分别使用信息增益、信息增益率和基尼指数来作为分类条件选择好坏的标准。C4.5是为解决ID3因偏向细小分割造成的过拟合问题的,CART方法的过拟合往往由剪枝方法来处理。
- ID3 选择信息增益最大的特征作为当前节点的决策特征。
- C4.5 选择信息增益率大的作为划分特征。
- CART 选择那个使得划分后基尼指数最小的属性作为最优划分属性。
优缺点:
优点:
- 计算量简单,可解释性强,比较适合处理有缺失属性值的样本,能够处理不相关的特
征。
缺点:
2. 单棵决策树分类能力弱,并且对连续值变量难以处理。
3. 容易过拟合(后续出现了随机森林,减小了过拟合现象)。
基本概念:
信息熵:
Ent(D)=−k=1∑∣Y∣pklog2pk
信息增益:
Gain(D,a)=Ent(D)−v=1∑V∣D∣∣Dv∣Ent(Dv)
增益率:
Gain_ratio(D,a)=IV(a)Gain(D,a)
IV(a)=−v=1∑V∣D∣∣Dv∣log2∣D∣∣Dv∣
基尼值:
Gini(D)=k=1∑∣Y∣k′=k∑pkpk′=1−k=1∑∣Y∣pk2
属性 a 基尼指数:
KaTeX parse error: Expected ‘}’, got ‘_’ at position 14: \text { Gini_̲index }(D, a)=\…
简单来说就是分而治之的思想。
Cart : 分类模型:采用基尼系数的大小度量特征各个划分点的优劣。回归模型:采用误差平方和度量。
无监督学习
聚类
k均值
所谓的k-mean算法,就是要找到点的一个划分(假设分成k类),使得类内平方和达到最小。用数学来表述就是要求解下式表示的优化问题。
Sargmini=1∑kx∈Si∑∣∣x−μi∣∣2
算法的基本思想是迭代。首先选择k个点作为k个类中心,将所有点按距离中心的远近分配给k个类。接着计算k个类的重心作为新的类中心,继续前述的分配过程,直到中心不再改变,那么分类也不再改变。
容易想到,更新中心为重心步骤,类内距离平方是不增的,重新分配点的步骤距离也是不增,距离平方和有下界,故而算法必然是收敛的。
事实上,算法收敛到会收敛到一个局部最优值,初始点选择得不同,那么最终收敛到的结果可能就不同。
初始点的选择:
-
首先随机选取一个点作为初始点,然后选择距离与该点最远的那个点作为中心点,再选择距离与前两个点最远的店作为第三个中心店,以此类推,直至选取大 k 个。
-
选用层次聚类或者 Canopy 算法进行初始聚类。
kmeans 的优化:使用 kd 树。将所有的观测实例构建成一颗 kd 树,之前每个聚类中心都是需要和每个观测点做依次距离计算,现在这些聚类中心根据 kd 树只需要计算附近的一个局部区域即可。
k 怎么选?
- 根据专家、行业经验进行主观判断
- 基于变化的算法:即定义一个函数,随着 k 的改变,认为在正确的 k 时会产生极值。
- 基于结构的算法:即比较类内距离,类间距离以确定 k。这也是比较常用的方法,如使用平均轮廓系数,越趋近于1,聚类效果越好。
- 基于一致性矩阵的算法:即认为在正确的 k 时,不同次聚类的结果会近似,以此确定 k。
- 基于层次聚类:即基于合并或分裂的思想,在一定情况下停止从而获得 k。
- 使用 BIC 算法进行初始划分。
- 基于采样的算法:即对样本采样,分别做聚类。根据这些结果的相似性确定 k。
- 使用 Canopy Method 算法进行初始划分。
分层次聚类
谱聚类
高斯混合模型
EM算法可以形象地比喻鸡生蛋,蛋生鸡的过程。EM 用于隐含变量的概率模型的极大似然估计。它一般分为两步:
- 第一步求期望(E)
- 第二步求极大(M)
如果概率模型的变量都是观测变量,那么给定数据之后就可以直接使用极大似然法或者
贝叶斯估计模型参数。但是当模型含有隐含变量的时候就不能简单的用这些方法来估计,EM 就是一种含有隐含变量的概率模型参数的极大似然估计法。
应用到的地方:混合高斯模型、混合朴素贝叶斯模型、因子分析模型。
降维
PCA降维
所谓的主成分分析,不过是在高维的空间中寻找一个低维的正交坐标系,比如说在三维空间中寻找一个二维的直角坐标系。那么这个二维的直角坐标系就会构成一个平面,将三维空间中的各个点在这个二维平面上做投影,就得到了各个点在二维空间中的一个表示,由此数据点就从三维降成了二维。
这个过程的关键在于,我们如何选取这个低维的坐标系,即坐标系原点在哪?各个轴朝哪个方向?一个原则就是使得各个点到到这个平面的距离平方和达到最小。由此,通过简单地数学推导,就能得到原点的表达公式和坐标系的各个基向量的表达公式。
下面以基于矩阵的视角写出PCA算法的算法流程,输入为p*N矩阵X,输出为d*N矩阵Y。矩阵的每一列都表示一个对象,每一行都表示对象的一个特征表示。
选取了2000x1680的数据集进行了测试,选取降维后维数为20,其降维前后的图像(降维后的图像指的是投影点还原到原空间对应的坐标值重构出的图像)如下所示(选取第一个点为代表):
LLE降维
当数据具备某些非线性结构,如流形结构时,我们希望降维后的数据仍然保持这些结构。那么就提出了LLE降维算法。
LLE (Locally linear embedding):在数据降维后仍然保留原始高维数据的拓扑结构,这种拓扑结构表现为数据点的局部邻接关系。
此算法我们首先要寻求每个数据点的k个最近邻,然后将当前数据点用k个最近邻线性表出,那么就有相对的权重系数。
我们希望数据在降维后数据点之间依然能保持这种线性表出的关系,并且在满足另外一些约束条件的前提下,我们很容易求得降维后的数据。
具体原理和公式网络上有很多人整理得很好,这里不提了。
下面时LLE算法的算法流程,输入为p*N矩阵X,输出为d*N矩阵Y。矩阵的每一列都表示一个对象,每一行都表示对象的一个特征表示。
MDS和t-SNE
独立成分分析
独立成分分析的经典问题是“鸡尾酒会问题”(cocktail party problem)。该问题描述的是给定混合信号,如何分离出鸡尾酒会中同时说话的每个人的独立信号。当有N个信号源时,通常假设观察信号也有N个(例如N个麦克风或者录音机)。
等距特征映射
谱嵌入
深度学习(一些基本概念)
我所理解的神经网络,无非就是向量和矩阵做乘法,对得到的向量加一个偏置后,外嵌套一个激活函数,得到一个新的向量。对新的向量反复以上过程,就得到新的一层网络……最后的结果和最后的标签有偏差,我们通过链式法则等方式,调整权值矩阵,使偏差达到最小。训练多层神经网络的过程一般就叫做深度学习。
我们所需要考虑的细节就是矩阵的规模,激活函数选什么,内存处理等等问题。
深度学习中的一些基本概念。
一维卷积(离散)
对于一维卷积的理解,是在一次坐火车的时候。所谓的一维卷积,无非就是两列火车相向而驰,从头碰头,到尾离尾的过程。我们把两个向量比作两列火车,向量的元素比作每个车厢,那么两个向量做卷积得到的值的每个分量就是计算每个时刻火车重叠部分的点乘,所谓的点乘,就是对应位置做乘法最后求和。花了一点时间做了一个gif如下:
这里需要注意的是,两列火车的长度不定,更不一定等长,可能只有一节车厢,也可能有一列火车或者两列火车有无限长度。所以,卷积的长度=长火车的车厢数+短火车的车厢数-1。当然,也有的一维卷积只考虑计算短火车和长火车重叠部分包含短火车的时刻,即所谓的没有padding。当然,滑动步长也可以不是1。
二维卷积(离散)
理解了一维卷积,二维卷积不过只是在一维卷积的基础上,将一维向二维进行了扩充。即拿一个所谓的小矩阵(卷积核、滤波器)去按一定的顺序去扫原矩阵,每个“时刻”都计算矩阵的一个点积,得到一个数值。如下图所示:
可以看出,在从有数字的地方开始卷(没有padding)的话,且步长为1的话,卷出来的矩阵边长=大矩阵边长-小矩阵边长+1。
那么,这么多有什么意义呢?举个简单的例子,它可以提取边缘,如下:
padding
卷积网络,经常说padding,那么所谓的padding又是什么意思呢?一般来说,为了减少信息的丢失或者其他的一些目的。padding表示在原有向量或者矩阵的边缘上扩充地补一些数,比如说补0(zero padding)。padding有三种模式,valid、same和full。什么意思呢?
- **valid:**表示不填充,那么在二维情况下,那么它输出的size就可以表示为:
out_height = ceil(float(in_height - filter_height + 1) / float(strides[1]))
out_width = ceil(float(in_width - filter_width + 1) / float(strides[2]))
这个表达式中的 out_height 表示输出的高度,in_height表示输入的高度,filter_height 表示滤波器的高度,strides表示步长(两个维度)。width亦如是。
也就是说当步长为1时,如果用valid(不填充),那么做完卷积之后,矩阵的边的长度就会减小 滤波器的长度-1。如果步长不为1,卷到后面如果不够的话,后面的也不填充,直接drop掉。
举个例子,一维,输入长度为13,滤波器长度为6,步长为5。后面两个数字,不够滤波器长度,直接drop掉。
- **same:**所谓的相同,做填充,使得输出的特征图的空间维度和输入的特征图的空间维度是相同的(这里特征图的概念后面会讲到)。事实上,这句话只是对步长为1的时候的描述是准确的。
我们先来看看这个输出长度的表达式,再理解这个就简单了。
out_height = ceil(float(in_height) / float(strides[1]))
out_width = ceil(float(in_width) / float(strides[2]))
我们现在要做的就是,在两边均匀地填充,使得卷出来的输出满足这个长度。一般的填充,我们都是尽可能均匀地填充在两边,如果要填充的个数为奇数个,实在无法均匀地填充地话,我们一般选择让右边多填充一个。
很容易计算得到,我们需要填充的量为,以宽为例:max{filter_width-in_width%strides[2],0}
,百分号表示取余,特别地,in_width%1
的值为1,算得这个数字之后,平均分配到两边。
下面举几个例子:
1、步长为1,卷出来的规模和原来的相同,体现了same的含义。
从这也可以看出,如果步长为1的话,我们做卷积一般是让卷积核的中心放到最边上一个开始卷,这样的话,能保持卷出来的规模和原来的一样。但是如果步长不为1的话就不一样了,可以看下面一个例子。
2、一维,输入长度为13,滤波器长度为6,步长为5。因为13/6取上界为3,所以要做一些填充,使得卷出来的东西长度为3。这也体现了所谓的same。
- **full:**如图所示,设输入的大小是7x7,filter的大小是3x3,full型的padding就是让卷积卷出来的矩阵在不完全失去原有信息的基础上尽可能大,所谓的不完全失去,就是做卷积卷积核和原矩阵至少有一格的重复。
橙色部分为输入, 蓝色部分为filter。full模式的意思是,从filter和输入矩阵刚相交开始就做卷积,白色部分为填0。
反卷积(转置卷积)
好像要说清楚这个东西不是特别容易的事情。一句话解释就是:反卷积相对于卷积,像是一个逆过程,注意,这里说的逆,只是规模上的逆,而不是整整意义下恢复原来矩阵的逆,想想这也是不可能的。
转置卷积,把矩阵拉成向量来理解比较好理解。举个栗子:4x4的输入,卷积Kernel为3x3, 没有Padding / Stride, 则输出为2x2。这时,输入矩阵可展开为16维向量,记作x,输出矩阵可展开为4维向量,记作y。那么卷积运算可表示为y=Cx。事实上,C可以表示为如下:
那么,转置卷积是什么呢?没错,就是x=CTy。
矩阵拉成向量确实好理解了,但是它在原矩阵(向量)时,又是怎么样一种表现呢?能否可视化一下?二维比较抽象,以一维举个例子。考虑no padding,步长为1的卷子,看看它的反卷积是什么。因为:
由上描述,可知:
可以看得出来,这种情况下的反卷积,其实就是把卷积核倒过来,然后对输入做full_padding的卷积。这是没有步长的情况,我们再来看看有步长的情况。假设步长是2,依然是没有padding的卷积,我们来看看反卷积。
反卷积表示为:
我们找一下上面两种情况的规律,发现所谓的反卷积,就是把卷积核倒一下,对输入矩阵做一些0值得插补,最后做各种形式的卷积(same、full等)。我们把这个推广到二维,梳理一下过程如下:
- 首先是将卷积核反转(并不是转置,而是上下左右方向进行递序操作)。
- 再将卷积结果作为输入,做补0扩充操作,即往每一个元素后面补0。这一步是根据步长来的,对于每个元素沿着步长方向补(步长-1)个0。例如,步长为1就不用补0了。
- 在扩充后的输入基础上再对整体补0。以原始输入的shape作为输出,按照前面介绍的卷积padding规则,计算pading的补0的位置及个数,得到补0的位置及个数,得到补0的位置要上下和左右各自颠倒一下。
- 将补0后的卷积结果作为真正的输入,反转后的卷积核为filter,进行步长为1的卷积操作。
注意:计算padding按规则补0时,统一按照padding=‘SAME’、步长为1*1的方式来计算。
通过以上的介绍,我们已经基本了解了反卷积操作的过程,看下面几张图能够更好地帮助理解。
上图是步长为2的反卷积的一个图示,在蓝色内部补够0后,需要做到5的same padding,所以需要在蓝色外部也要做padding。这里灰色那个是卷积核,表示原卷积核的一个上下颠倒,左右颠倒。当然,反卷积还有很多更一般的情况,总结起来为一下几种:
反卷积,可以理解为卷积操作的逆运算。千万不要当成反卷积操作可以复原卷积操作的输入值,反卷积并没有那个功能,它仅仅是将卷积变换过程中的步骤反向变换一次而已,通过将卷积核转置,与卷积后的结果再做一遍卷积,所以它还有个名字叫转置卷积。
虽然它不能还原出原来卷积的样子,但是在作用上具有类似的效果,可以将带有小部分缺失的信息最大化恢复,也可以用来恢复被卷积生成后的原始输入。
学习率
就是梯度下降的步长。
反向传播
应用梯度下降方法,需要导数,求导数的方法,有反向传播,其实就是链式法则。
正则化
正则化是针对过拟合而提出的,正则化项是模型参数向量的范数,是为了降低模型的复杂度。一般的优化问题只是最小化经验风险,正则化是在此基础上加上模型复杂度这一项。并用一定的比率来衡量这一项的系数。加上这一项,可以防止模型训练过度复杂,有效的降低过拟合的风险。
避免过拟合,提高泛化能力的方法有:
- L1、L2正则化
- 早点停止训练
- 数据集扩增
- dropout
- 其他
正则化(Regularization)包括L1正则化、L2正则化。正则化其实就是在原有的loss funtion后面加上权重。
L2正则化(权重衰减)为:
对权重求导,可得:
这里体现了权重的一个衰减。
L1正则化为:
这个也可以做类似的求导。
L正则化,有点罚函数的味道,这里因为把权重加入到损失函数了,就尽量使得权重尽量小了。人们普遍认为:更小的权值w,从某种意义上说,表示网络的复杂度更低,对数据的拟合刚刚好(这个法则也叫做奥卡姆剃刀)。
参数服从拉普拉斯分布导出 L1 正则化,参数服从高斯分布,导出 L2 正则化。
softmax
softmax是一种归一化,它的好处就是使得计算上非常方便,谁用谁知道。
Softmax计算简单,效果显著,非常好用。它也能缓解局部极值的问题。
dropout
所谓的dropout,就是以一定的概率p(比如说0.5)先把隐藏层的部分节点藏起来(之所以叫藏起来,是因为与之相关的权重一直都在,只是不更新,下一次选择的时候,如果被藏的节点显示出来了,与之相关的权重还是保持原来的权重),变成一个比较小的网络,对于这个比较小的网络训练,训练到一定程度后,这些显示节点的权重有所更新了,这时候显示隐藏节点,重新以概率p进行选择……反复进行这个过程,知道训练好一个网络。测试的时候,用的是所有的节点,只不过权重得乘以p。
它的基本过程如下:
- 首先随机(临时)删掉网络中一半的隐藏神经元(备份被删除神经元的参数),输入输出神经元保持不变(图中虚线为部分临时被删除的神经元)。
- 对于修改后的网络,使用一小批训练样本去训练,按随机梯度下降法更新对应的参数。
- 恢复隐藏的神经元,包括恢复与它相关的原来的参数,重复上述过程(此时被删除的神经元保持原样,而没有被删除的神经元已经有所更新)。
dropout是一种有效的防止过拟合的方法,另外也是为了减少计算量。它是缓解过拟合的技巧之一。
dropout也是一种集成,如图:
它相当于训练时随机丢弃部分神经元,测试时整合所有神经元。dropout为什么能work呢?好像大家都没有一个很好的解释。简单地理解,有时候,老板交付的任务,两个人单独完成再整合,总比两个人一块做结果要好,有点“三个和尚没水喝”的意思,但也不是绝对的。
历史
随机梯度下降(mini-batch)
我们知道,在做有监督的问题中,有一个损失函数,用来衡量模型的好坏。在回归问题中,如果我们已经知道方程的形式,我们可以做出问题的损失函数。那么我们要做的就是寻找方程的最佳参数,即寻找参数,使得损失函数函数达到最小。乍一听,这就是个优化问题。当然可以对参数的各个分量求导,最后解方程组。问题是,你能确定最后的方程组好解?一般的数值解法有梯度下降法、牛顿法、拟牛顿方法以及信赖域方法等等。梯度下降方法简单易行,可是当数据量比较大时,梯度下降的计算就特别大。
为解决大数据量的优化求解,我们一般可以采用随机梯度下降。所谓的随机梯度下降,就是相比梯度下降,我们不选择全部的数据点,而是每次随机选择一个或者若干个数据点(一个数据点)来构建损失函数,接着再用梯度下降方法求解。看起来很不靠谱的样子,事实上多做几次这个操作,它是可以收敛的最优解的某个邻域的。
万有逼近定理
-
如果一个隐层包含足够多的神经元,三层前馈神经网络(输入-隐层
-输出)能以任意精度逼近任意预定的连续函数。 -
当隐层足够宽时,双隐层感知器(输入-隐层1-隐层2-输出)可以逼
近任意非连续函数:可以解决任何复杂的分类问题。
几种激活函数
常用激活函数如下:
白化
白化的目的是去除输入数据的冗余信息。比如训练数据是图像,由于图像中相邻像素之间具有很强的相关性,所以用于训练时输入是冗余的。白化的目的就是降低输入的冗余性。
所谓白化,就是对输入数据分布变换到均值为0,方差为1的正态分布,那么神经网络较快收敛。BN也是源于这个想法。
动量方法
梯度下降,一般是沿着当前点的负梯度方向走一小步,到下一点,又沿那个那个点的负梯度方向走一步,那么这样走走停停,无疑是走得很慢。
而一个真正的小球的下降要比这聪明多了,从A点滚动到B点的时候,小球带有一定的初速度,在当前初速度下继续加速下降,小球会越滚越快,更快的奔向谷底。momentum动量法就是模拟这一过程来加速神经网络的优化的。
它的基本算法如下:
最为关键的一步就是,走的步长vn(称为速度)是由当前的负梯度方向和前一步的速度vn−1做线性组合得到的。前一步的速度又和前前步的速度有关,以此类推,就把速度积累下来了。也就是说,当前的行走的方向和步长,还要综合考虑之前所有的走过的步的方向和步长。我们知道,不管是做傅里叶分析还是做半加速迭代,都习惯把之前的值做个加权平均,好像收敛就会快很多,monmentum好像就有点这个意思。它是为了解决一般SGD方法一直震荡而迟迟不收敛的情况。
动量方法有点像CG,要结合之前的信息。
交叉熵和KL散度
交叉熵和KL散度以及JS散度都是衡量两个分布(向量)的距离的一种度量。
交叉熵:
KL散度(KL距离,相对熵):
JS散度(JS距离,KL散度的变形):
batch normalization
所谓的batch normalization(批量归一化、批量正则化)就是“减去均值,除以方差”的标准化过程,比如一般正态分布变成标准正态分布。基本思想就是让每个隐层节点的激活输入分布固定下来,来提升训练速度。
它有什么用呢?它主要是为了**避免梯度消失,加速收敛。**把输入数据重新拉回到均值为0,方差为1的区域,这样让每层的输入落在(-1,1)区间,这段刚好是激活函数性能最好的区域。它是分布变得更加均匀,从而梯度方向更接近极值点方向,如下图:
另外,它也克服神经网络受不同初值影响较大的缺点。促进神经网络稳定性发展:使不同层相对独立,每一层可以专注解决本层的问题。
maxout
maxout是一种新型的激活函数,能够缓解梯度消失,规避了ReLU神经元死亡的情况,但增加的参数和计算量。它其实就是在原有激活的基础上,取个最大值,如下所示:
既然maxout是一个函数,那么它的输入,输出是什么?函数图像又是如何?
如果我们设置maxout的参数k=5,maxout层就如下所示:
相当于在每个输出神经元前面又多了一层。这一层有5个神经元,此时maxout网络的输出计算公式为:
z1=w1*x+b1
z2=w2*x+b2
z3=w3*x+b3
z4=w4*x+b4
z5=w5*x+b5
out=max(z1,z2,z3,z4,z5)
所以这就是为什么采用maxout的时候,参数个数成k倍增加的原因。本来我们只需要一组参数就够了,采用maxout后,就需要有k组参数。
上采样和下采样
下采样就是变小输入,上采样就是就是变大矩阵,有点“插值”的意思。
一般来说下采样指的就是池化。上采样包括unpooling和转置卷积(transpose convolution)和一般的插值等。unpooling就是反池化,在池化过程中,记录下max-pooling在对应kernel中的坐标,在反池化过程中,将一个元素根据kernel进行放大,根据之前的坐标将元素填写进去,其他位置补0 。
池化
池化对特征图的每个局域进行下采样,作为这个区域的概括。池化包括平均池化mean-pooling和最大池化max-pooling。所谓的池化,其实就是讲输入分块,对每块去平均值或者最大值。
预训练
假设你想要解决一个复杂的任务,你没有太多的标记的训练数据,但不幸的是,你不能找到一个类似的任务训练模型。 不要失去所有希望! 首先,你当然应该尝试收集更多的有标签的训练数据,但是如果这太难或太昂贵,你仍然可以进行无监督的训练。 也就是说,如果你有很多未标记的训练数据,你可以尝试逐层训练层,从最低层开始,然后上升,使用无监督的特征检测算法,如限制玻尔兹曼机(RBM)或自动编码器。 每个层都被训练成先前训练过的层的输出(除了被训练的层之外的所有层都被冻结)。 一旦所有层都以这种方式进行了训练,就可以使用监督式学习(即反向传播)对网络进行微调。
然而,貌似主流的深度学习平台甚至都不支持RBM和预训练。所以,不必深究。
预训练在没有太多工具的情况下,能够解决梯度消失和局部极值,训练困难,训练时间长等问题。但它本质上无法解决梯度消失的问题。
自编码机
自编码器其实是通过神经网络,学会重构自己的过程。
自编码器(autoencoder)假设输出与输入相同(target=input),是一种尽可能复现输入信号的神经网络。将input输入一个encoder编码器,就会得到一个code,加一个decoder解码器,输出信息。通过调整encoder和decoder的参数,使得重构误差最小。它是一种非监督学习,因为无标签数据,误差的来源是直接重构后信号与原输入相比得到。
梯度消失(爆炸)和局部极值
所谓的梯度消失,具体来说,由于在向后传递过程中,sigmoid向下传递的梯度包含了一个f’(x) 因子(sigmoid关于输入的导数),因此一旦输入落入饱和区,f’(x) 就会变得接近于0,导致了向底层传递的梯度也变得非常小。此时,网络参数很难得到有效训练。这种现象被称为梯度消失。一般来说, sigmoid 网络在5 层之内就会产生梯度消失现象。Relu函数可以有效缓解这种情况。
反之,如何激活函数导数乘以很大的神经网络权重参数w,那么因为乘积大于1,就会发生梯度爆炸现象。
局部极小值很好理解,因为近似的函数非凸,就容易陷入局部极值。
Flatten
Flatten层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。其实就是把矩阵拉成一条。
特征图
在做二维卷积中,用滤波器卷一次得到的结果就是一个特征图,不同的滤波器,做多次卷积操作就会得到多个特征图。滤波器就是卷积核。
强化学习
强化学习到底是什么?若是想略微了解强化学习大概的意思和操作,把握一个主干知识,而不做深入研究,看这篇文章就很够了。
核心内容
元素简介
强化学习考察的是对于一个对象(智能体),从一个状态执行某种动作到下一个状态,并在这个过程中,给其一定的奖赏或者惩罚,是它尽可能往好的方面去做。就像马戏团的驯养师,对其宠物,若其表现好,就给它一点吃的,若其表现不好,就抽它两鞭子,使得它最后,能够有一系列出色的表现。
为了说清楚这个问题,我们需要介绍一下状态空间S、动作集A、状态转移概率P和奖赏R。
如图所示,状态空间表示所有状态的一个集合,动作集表示所有动作的一个集合。
状态转移概率是一个函数,表示在当前状态s下,执行某个动作a之后,转移到某个状态的概率,即P:S×A×S↦R指定了转移概率。举例比如说状态s1下,执行动作a1,可能转移到s1,也可能转移s2,二者概率不同。图示s2也是可以以一定的概率执行相应的动作,执行相应的动作,都以一定的概率转移到不同的状态,为了图示简明,没有画出来。
R:S×A×S↦R指定了奖赏。这个奖赏不仅跟起始状态和动作有关,也和动作执行后达到的状态有关。
还有一个是策略函数π,它表示给你一个状态,你应该要执行什么动作,当然,如果你执行的动作不确定,而是以一定概率执行相应的动作,那么π其实就是对应于动作的概率函数,即用π(s,a)表示在状态s下选择动作a的概率。要有∑aπ(s,a)=1。
优化目标:状态值函数
给定一个策略π(这个策略不一定是最优的),那么对于执行动作的步数有限(设为T步)和无限的时候,我们分别定义状态值函数:
{VTπ(s)=Eπ[T1∑t=1Trt∣s0=s]Vγπ(s)=Eπ[∑t=0+∞γtrt+1∣s0=s]
这个状态值函数的意思就是在当前状态s下,平均累积奖赏的一个数学期望,它是一个函数,对于不同的状态s,它有不同的值。当步数是无穷的时候,我们定义一个折扣因子γ,使得距离越远的地方,奖赏的对累积奖赏影响越小。这里的数学期望,其实有两层含义,一个是指定动作之后,可能会以不同的概率转移到不同的状态,可以求一个期望。另一个是,对于状态s而言,会以π(s,a)的概率执行不同的动作,对于不同的动作可以求一个期望。
所以,我们想要做的,其实就是想办法找一个策略,使得这个状态值函数达到最大。这是我们的目标。
有了这个优化目标,我们来看看如何最大化这个优化目标。
不妨考虑模型已知的情况,即状态空间,动作空间,转移概率和奖赏我们都是知道的。在模型不是已知的情况下,比如说奖赏Reward不清楚,我们可以使用模特卡洛的方法,让智能体多做几次动作,计算累积回报,求得平均来得到我们需要的奖赏值。贪婪算法是在“探索”(exploration)和“利用”(exploitation)之间取一个折中,所谓的探索,其实就是以频率替代概率,多做几次实验,取平均值,来作为我们需要的值的期望,所谓的利用,就是在策略中选择期望最大的动作。
对于有限步情况,考虑某一个指定的策略π,因为模型已知,它的状态值函数根据数学期望的定义可以进行拆分和全概率展开:
VTπ(s)=Eπ[T1t=1∑Trt∣s0=s]=Eπ[T1r1+TT−1T−11t=2∑Trt∣s0=s]=a∈A∑π(s,a)s′∈S∑P(s′∣s,a)(T1R(s′∣s,a)+TT−1Eπ[T−11t=1∑T−1rt∣s0=s′])=a∈A∑π(s,a)s′∈S∑P(s′∣s,a)(T1R(s′∣s,a)+TT−1VT−1π(s′))
对于无限步的情况,也可以类似展开得到如下结果:
Vγπ(s)=a∈A∑π(s,a)s′∈S∑P(s′∣s,a)(R(s′∣s,a)+γVγπ(s′))
上面这俩方程,姑且就叫做值函数递归方程(也叫贝尔曼方程?)。从值函数递归方程上看,我们可以知道,当模型已知,策略已知的情况下,我们其实是可以递归地求得在该策略下各个时刻的状态值函数。也就是说,从值函数的初始值V0π出发,通过一次迭代求得各个状态的一步奖赏V1π,进而再通过一次迭代求得V2π……
状态-动作值函数
状态-动作值表示的是在某状态下,执行动作a后的一个平均累积奖赏。它和状态值函数相比,因为动作给定了,所以不再计算关于动作的期望。即:
{QTπ(s,a)=∑s′∈SP(s′∣s,a)(T1R(s′∣s,a)+TT−1VT−1π(s′))Qγπ(s,a)=∑s′∈SP(s′∣s,a)(R(s′∣s,a)+γVγπ(s′))
所以,如果通过值函数递归方程算得了状态值函数,我们就可以通过上述表达来求得每一时刻的状态-动作值函数。
策略迭代和值迭代
策略迭代
通过以上的论述,相必大家有一定的想法来计算最优策略。一个自然而然的思路就是策略迭代算法。
算法的基本过程就是先随意给定一个策略,比如说π(s,a)=∣A(s)∣1,然后通过值函数递归表达式,算出该策略下每一个时刻的值函数。有了值函数,我们通过状态-动作值函数的表达式,可以求解每一个时刻的状态动作值。有了状态-动作值函数,我们可以通过关于动作最大化状态-动作值函数,进行更新策略:π′(s)=a∈AargmaxQπ(s,a)。有了更新后的策略,重复以上过程,直到收敛。这就是所谓的策略迭代算法,通过不断地迭代策略,来找到最优策略。容易证明,上述算法是收敛的。
值迭代
另一个经典的迭代方法是值迭代方法。用V∗和Q∗来表示最优策略π∗下的状态值函数和状态-动作值函数。
容易想到的是,某一时刻某一状态下,最优值函数必然是最优策略下的状态-动作值函数关于动作的一个最大化,即:
V∗(s)=a∈AmaxQ∗(s,a)
这个是容易证明的。简单地想,如果某个策略下的某一步的值函数不是最优的,那么一定可以改成状态-动作值的最大化相对应的策略,使状态值增大。
把这个写开,就成了:
{VT∗(s)=maxa∈A∑s′∈SP(s′∣s,a)(T1R(s′∣s,a)+TT−1VT−1∗(s′))Vγ∗(s)=maxa∈A∑s′∈SP(s′∣s,a)(R(s′∣s,a)+γVγ∗(s′))
上式是关于最优值函数的一个迭代公式,就被称为是贝尔曼最优性方程。其对应的最优状态-动作值函数为:
{QT∗(s,a)=∑s′∈SP(s′∣s,a)(T1R(s′∣s,a)+TT−1maxa′∈AQT−1∗(s′,a′))Qγ∗(s,a)=∑s′∈SP(s′∣s,a)(R(s′∣s,a)+γmaxa′∈AQγ∗(s′,a′))
由贝尔曼最优性方程,容易知道,我们不需要通过策略迭代,一次性就可以把最优策略π∗下的值函数统统求出来。由此,所谓的值迭代算法,就不言而喻了。或通过迭代贝尔曼公式,或通过迭代最优动作价值函数进而关于动作求最大化,都能够求得最优策略。不再细述。
Q学习、SARSA、时序差分学习
强化学习的算法除了值迭代和策略迭代,比较经典的还有Q learning、Sarsa和TD(时序差分),最新的算法还有SAC和TD3等。这些算法的目标都是最大化值函数,都大同小异,可以简单地理解成求动作值函数的各种不同的方法,若只想浅窥深度学习,而不做细致研究,不必再在乎这些算法的推导以及收敛性证明,在合适的情形下直接拿来用就好了。
Q学习
Q学习算法,需要了解Q表。Q-table 其实就是把状态和动作一个作为行标,一个作为列标搞成表格。我们要求状态-动作值函数(Q函数)其实也就是要想办法求出最优动作下的Q表。
具体的算法是先随意初始化一个Q表,然后随机地选择状态s和动作a,根据奖赏函数计算出奖赏R,然后根据上述最优状态-动作值函数的迭代公式,更新Q表。如此反复,直到Q表不再变化。
看简单的例子链接或者链接,就很容易明白Q学习时怎么操作的了。
SARSA和时序差分学习
Sarsa是Q学习算法的改进。Sarsa和Q以及TD本质上都是一脉同根的。
对于三者的一个差别和理解,可以看这个链接。
深度强化学习
所谓深度强化学习,只不过是用神经网络去表示出最优策略下的状态-动作值函数Q∗(s,a)。有了Q∗(s,a)的神经网络表示,下面的事情不就好办了?
为什么要用深度学习呢?因为当状态空间和动作空间很大的时候,甚至在连续的情况下,往往是连续的,用值迭代算法,或者Q学习算法,来计算Q函数,计算量都太大。而我们知道,神经网络刚好就是来逼近一个复杂的高数据量的函数的,用它来表示Q函数,岂不妙哉?基于这样一个想法,才有了深度强化学习。
深度学习需要提供训练数据,标签怎么找?可以将下一步的Q值作为标签。直观上理解就是,Q值变化不大了,往往达到了最优。
但是若使用相同的网络来生成下一个目标Q值和估计当前Q值,会导致振荡性甚至发散。还有就是,深度学习要求样本之间相互独立且同分布,但强化学习样本并不满足这个条件。因此DQN中使用三个技巧来来解决这一系列问题:经验回放,目标网络和自适应性学习率调整方法。所以,深度强化学习就有了一系列可学习和研究的东西。
这个链接和这个链接上有关于DQN的简单介绍,看看也就明白了。
一些学习资料
有几本理论比较清晰的书籍,见此GitHub。
如果对于机器学习没有了解,可以看一下先修课程。
集成学习
bagging
Bagging的想法很简单,就是在训练集中均匀、有放回地抽取m个子集作为m个训练集,分别使用分类回归算法,可以得到m个模型,再通过取平均值、取多数票等方法,得到Bagging的结果。
Bagging算法可与其他分类、回归算法结合,提高其准确率、稳定性的同时,通过降低结果的方差,避免过拟合的发生。
过程如下:
- 从 N 样本中有放回的采样 N 个样本。
- 对这 N 个样本在全属性上建立分类器 (CART、SVM)。
- 重复上面的步骤,建立 m 个分类器。
- 预测的时候使用投票的方法得到结果。
随机森林
在机器学习中,随机森林是一个包含多个决策树的分类器,并且其输出的类别是由个别树输出的类别的众数而定。这个方法结合了 bagging 想法和随机子空间想法,建造决策树的集合。误差使用最后统计误分得个数占总预测样本的比率作为 RF 的 oob (out-of-bag)误分率。每棵树选部分的数据来训练,剩下的作为验证。子树特征也不必选全部的,也是选部分的。回归采用平均,分类采用投票。
每棵树的按照如下规则生成:
- 如果训练集大小为 N,对于每棵树而言,随机且有放回地从训练集中的抽取 N 个训练样本(这种采样方式称为bootstrap sample方法),作为该树的训练集。从这里我们可以知道:每棵树的训练集都是不同的,而且里面包含重复的训练样本。
- 如果每个样本的特征维度为 M,指定一个常数 m<<M(取M ?)随机地从 M 个特征中选取 m 个特征子集,每次树进行分裂时,从这 m 个特征中选择最优的。
- 每棵树都尽最大程度的生长,并且没有剪枝过程。
随机性的引入,使得随机森林不容易陷入过拟合,并且具有很好得抗噪能力(比如:对缺省值不敏感)。
随机森林分类效果(错误率)与两个因素有关:
- 森林中任意两棵树的相关性:相关性越大,错误率越大。
- 森林中每棵树的分类能力:每棵树的分类能力越强,整个森林的错误率越低。
减小特征选择个数 m,树的相关性和分类能力也会相应的降低。增大m,两者也会随之增大。所以关键问题是如何选择最优的 m,这也是随机森林唯一的一个参数。
优缺点
- 能够处理大量特征的分类,并且还不用做特征选择
- 在训练完成之后能给出哪些feature的比较重要
- 训练速度很快
- 很容易并行
- 实现相对来说较为简单,简单,计算开销小
boosting
“三个臭皮匠顶个诸葛亮”,弱分类器按准确率给予一定权重组合成一个强学习器,降低偏差,这就是 boosting 的基本思想。一个经典的提升算法例子是 AdaBoost。
采用决策树作为弱分类器的梯度提升算法被称为 GBDT。GBDT 的精髓在于训练的时候都是以上一颗树的残差为目标,这个残差就是上一个树的预测值与真实值的差值。有点像多重网格的想法。由于用的是残差,也就是累加,所以用于分类树是没有意义的。所以GBDT中的树都是回归树,不是分类树。
GBDT的优点和局限性
优点:
- 预测阶段的计算速度快,树与树之间可以并行化计算。
- 在分布稠密的数据集上,泛化性能和表达能力都很好。
- 采用决策树作为弱分类器使得 GBDT 模型具有较好的解释性和鲁棒性,能够自动发现特征间的高阶关系,并且也不需要对数据进行特殊的预处理如归一化等。
局限性:
- 在高维稀疏的数据集上,表现不如支持向量机或者神经网络。
- 在处理文本分类特征问题上的优势不如在数值上明显。
- 训练需要串行训练,只能在决策树局部采用一些局部并行的手段提高训练速度。
Boosting 在训练的时候会给样本加一个权重,然后使 loss function 尽量去考虑那些分错类的样本(比如给分错类的样本的权重值加大)。Boosting 的好处就是每一步的参加就是变相了增加了分错 instance 的权重,而对已经对的 instance 趋向于 0,这样后面的树就可以更加关注错分的 instance 的训练了。相当于把搞错的,拿出来重新搞。
Shrinkage 认为,每次走一小步逐步逼近的结果要比每次迈一大步逼近结果更加容易避免
过拟合。
优缺点:
优点:
- 精度高
- 能处理非线性数据
- 能处理多特征类型
- 适合低维稠密数据
缺点:
- 并行麻烦(因为上下两颗树有联系)
- 多分类的时候复杂度很大
原始的 GBDT 算法基于经验损失函数的负梯度来构造新的决策树,只是在决策树构建完成后再进行剪枝。而 XGBoost 在决策树构建阶段就加入了正则。
其他方面
概率图模型
概率图模型是用图论方法以表现数个独立随机变量之关系的一种建模法。其图中的任一节点为随机变量,若两节点间无边相接则意味此二变量彼此条件独立。两种常见的概率图模型是具有向性边的图及具无向性边的图。
概率图模型通过构造基于图的表达来描述多维空间上的概率分布。图的节点和边描述了该分布不同变量之间具有的条件独立性质的集合。根据图的有向性,概率图模型可以分成两大类,分别是贝叶斯网络和马尔可夫网络。这两类网络均具有因子化和条件独立的性质,但条件独立的类型和将分布因子化的方式有所不同。概率图模型在图像视频分析中用途很广。
贝叶斯网
一般而言,贝叶斯网络的有向无环图中的节点表示随机变量。连接两个节点的箭头代表此两个随机变量是具有因果关系或是非条件独立的,而两个节点间若没有箭头相互连接一起的情况就称其随机变量彼此间为条件独立。若两个节点间以一个单箭头连接在一起,表示其中一个节点是“因(parents)”,另一个是“果(descendants or children)”,两节点就会产生一个条件概率值。
举例来说,贝叶斯网络可用来表示疾病和其相关症状间的概率关系,倘若已知某种症状下,贝叶斯网络就可用来计算各种可能罹患疾病之发生概率。
马尔科夫随机场
马尔可夫随机场似贝叶斯网络用于表示依赖关系。但是,一方面它可以表示贝叶斯网络无法表示的一些依赖关系,如循环依赖。另一方面,它不能表示贝叶斯网络能够表示的某些关系,如推导关系。
马尔可夫随机场要求一个变量在前一个变量的条件下,和前一个变量之前所有变量的联合是条件独立,也就是要满足马尔可夫性质。
推广搜相关
协同过滤分为 User-based CF 和 Item-based CF ,本质上都是寻求一种低秩逼近。基本过程是:初始的矩阵缺失值一个猜测,得到 Z;对 Z 做 rank-r 奇异值分解,以此得到缺失值新的估计;重复这个过程,直到收敛。
概念解释
准确率、精确率、召回率、F1值、ROC、AUC
我不知道为什么网上那么多人总喜欢用公式去表达这几个东西,明明很简单的东西,你给个公式,我还要首先理解一下你公式里面每个字符表示的意思,这不是浪费时间么。
准确率(accuracy)就是我们通常意义下的分类分对的比率。这个有问题啊。比如说 100 个人里面,有 1 个坏蛋,那么我一股脑全当成好人,那还有 0.99 的准确率。
精确率(precision)是对结果而言的,就是你分的所有正样本里面,分对的样本占的百分比。
所谓的召回召回,就是在实际的正样本里面,你判断对的百分比有多少,也就是你召回来的正样本有多少。
F1 值就是精确率和召回率在某种意义下的平均。F1=precision+recall2∗precision∗recall。
召回率是个新奇的东西,我们拿过来。我们再想,召回率是正样本中判定为 1 的比率,我们关注这个判定为 1 的事情,负样本中判定为 1 的我们叫 FRR。以 FPR 为横坐标,以召回率这个有趣的东西为纵坐标,画出来的曲线就叫 ROC 曲线。AUC(area under curve) 就是 ROC 的面积。AUC 越大越好,ROC 越拱越好。 ROC 和 AUC 通常是用来评价一个二值分类器的好坏。
ROC 曲线,x 轴为假阳率,y 轴为真阳率(召回率)。针对落在 y=x 上点,表示是采用随机猜测出来的结果。ROC 曲线建立:一般默认预测完成之后会有一个概率输出 p,这个概率越高,表示它对positive 的概率越大。现在假设我们有一个 threshold,如果 p>threshold,那么该预测结果为positive,否则为negitive。多设置几个 threshold,那么我们就可以得到多组真阳率和假阳率的值,就可以 plot 图像了。
AUC:AUC(Area Under Curve) 被定义为 ROC 曲线下的面积,显然这个面积不会大于1(一般情况下ROC 会在 y=x 的上方,所以0.5
当测试集中的正负样本发生变化时,ROC 曲线能基本保持不变,但是 precision 和 recall 可能就会有较大的波动。所以,这是一个衡量效果的一个不错的标准。
词袋模型
词袋模型是 NLP 里面的一个概念,顾名思义就是把单词丢进一个袋子里面。给你一句话,你可以数词袋里面每个单词出现的次数,就得到了一个词频向量。
TF-IDF
TF-IDF 是衡量一个字词在一个文件中的重要性的。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。一个词语在一篇文章中出现次数越多, 同时在所有文档中出现次数越少, 越能够代表该文章。
通过上面的叙述,一个简单的想法就是用词在文章里面的比率除以词在语料库里面的占比,来衡量它在这篇文章中的重要性。但是语料库太大了,一个一个数不现实。不妨用有这个词的文件在语料库里面的占比作为除数。把除变成乘,在取个 log 就有:
TFIDF(w)= 该文章中所有的词条数目 在某一文章中词条 w 出现的次数 ∗log( 包含词条 w 的文档数 +1 语料库的文档总数 )
分母之所以要加1,是为了避免分母为 0。
泛化
泛化能力是指模型对未知数据的预测能力。
过拟合
所谓的过拟合就是说训练得太好了,以至于在测试集上效果不好。过拟合发生在测试误差和训练误差相差太大的情况下。如果一味的去提高训练数据的预测能力,所选模型的复杂度往往会很高,这种现象称为过拟合。特征越多,模型越复杂,越容易过拟合。
产生的原因:
- 因为参数太多,会导致我们的模型复杂度上升,容易过拟合。(模型太复杂)
- 权值学习迭代次数足够多,拟合了训练数据中的噪声和训练样例中没有代表性的特征。(学太久)
解决方法
- L1、L2正则化
- 减少特征
- 权值衰减
- dropout
- 数据集扩增
- 早点停止训练
- 交叉验证法(训练集和测试集交换)
生成模型和判别模型
- 生成模型:由数据学习联合概率分布 P(X,Y),然后求出条件概率分布 P(Y|X) 作为预测的模型(朴素贝叶斯)。生成模型可以还原联合概率分布 P(X,Y),并且有较快的学习收敛速度,还可以用于隐变量的学习,如隐马尔可夫模型 HMM。
- 判别模型:由数据直接学习决策函数条件概率分布 P(Y|X) 作为预测的模型,即判别模型。直接面对预测,往往准确率较高。
判别式模型举例:要确定一个羊是山羊还是绵羊,用判别模型的方法是从历史数据中学习到模型,然后通过提取这只羊的特征来预测出这只羊是山羊的概率,是绵羊的概率。
生成式模型举例:利用生成模型是根据山羊的特征首先学习出一个山羊的模型,然后根据绵羊的特征学习出一个绵羊的模型,然后从这只羊中提取特征,放到山羊模型中看概率是多少,在放到绵羊模型中看概率是多少,哪个大就是哪个。
线性分类器和非线性分类器
如果模型是参数的线性函数,并且存在线性分类面,那么就是线性分类器,否则不是。
常见的线性分类器有:LR、贝叶斯分类、单层感知机、线性回归。常见的非线性分类器:决策树、RF、GBDT、多层感知机。SVM 两种都有(看线性核还是高斯核)。
线性分类器速度快、编程方便,但是可能拟合效果不会很好。非线性分类器编程复杂,但是效果拟合能力强。
特征多,数据系数,往往更容易线性可分,我们选择线性分类器,否则,我们选择非线性分类器。
L1 和 L2 正则化
他们都是可以防止过拟合,降低模型复杂度。
- L1 是在 loss function 后面加上模型参数的 1 范数。
- L2是在 loss function 后面加上模型参数的 2 范数。
- L1 会产生稀疏的特征。L2 会产生更多地特征但是都会接近于 0。
- L1 会趋向于产生少量的特征,而其他的特征都是 0,而 L2 会选择更多的特征,这些特征都会接近于 0。
- L1 在特征选择时候非常有用,而 L2 就只是一种规则化而已。
归一化方法
为了消除数据特征之间的量纲影响,我们需要对特征进行归一化处理,使得不同指标之间具有可比性。
- scaling 到一个区间
- 减去均值,除以方差
- 函数转化,如:y=log10(x),y=π/2arctanx
- softmax:取exi后,再求占比。
交叉验证
N 折交叉验证有两个用途:模型评估和模型选择。把这种策略用于划分训练集和测试集,就可以进行模型评估。把这种策略用于划分训练集和验证集,就可以进行模型选择。
交叉验证的核心思想:对数据集进行多次划分,对多次评估的结果取平均,从而消除单次划分时数据划分得不平衡而造成的不良影响。因为这种不良影响在小规模数据集上更容易出现,所以交叉验证方法在小规模数据集上更能体现出优势。
这种过拟合可能不是模型导致的,而是因为数据集划分不合理造成的。这种情况在用小规模数据集训练模型时很容易出现,所以在小规模数据集上用交叉验证的方法评估模型更有优势。
交叉验证与正则化不同:交叉验证通过寻找最佳模型的方式来解决过拟合。而正则化则是通过约束参数的范数来解决过拟合。
Bias(偏差)、Error(误差)、Variance(方差)
误差=偏差+方差。Bias 是用所有可能的训练数据集训练出的所有模型的输出的平均值与真实模型的输出值之间的差异。Variance 是不同的训练数据集训练出的模型输出值之间的差异。Bias 和 Variance 是不可兼得的。过拟合的情况是 Bias 很小,但是方差很大,训练集上搞好了,可以追求 Bias 很小。
技术交流
欢迎转载、收藏、有所收获点赞支持一下!
目前开通了技术交流群,群友已超过2000人,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友
- 方式①、发送如下图片至微信,长按识别,后台回复:加群;
- 方式②、添加微信号:dkl88191,备注:来自CSDN
- 方式③、微信搜索公众号:Python学习与数据挖掘,后台回复:加群