所谓的线性回归,就是要找一个线性的超平面,去尽可能地拟合各个样本点。在一维的情况下,如图所示:
我们要寻找一条直线,让它尽可能地穿过这些点。“尽可能”可能有一些度量,比如说让误差平方和最小。
求解这条直线的方法有最小二乘方法等。
线性回归是一种简单但却使用的回归技术。
多重共线性(Multicollinearity)是指线性回归模型中的自变量之间由于存在高度相关关系而使模型的权重参数估计失真或难以估计准确的一种特性,多重是指一个自变量可能与多个其他自变量之间存在相关关系。共线性不影响模型的预测而是影响对模型的解释。神经网格本来可解释性就差,就不存在这种共线性的问题。
所谓物以类聚,人以群分,你的圈子基本决定了你的状态。我们可以用周围的邻居来判断自己的情况,基于这个思想,就有了k-NN算法。k近邻算法不仅可以用于分类,也可以用于回归,我这里将它放在了分类的条目下。
分类问题中,一个对象的分类是由其邻居的“多数表决”确定的,k个最近邻居(k为正整数,通常较小)中最常见的分类决定了赋予该对象的类别。若k=1,则该对象的类别直接由最近的一个节点赋予。无论是分类还是回归,衡量邻居的权重都非常有用,使较近邻居的权重比较远邻居的权重大。例如,一种常见的加权方案是给每个邻居权重赋值为1/d,其中d是到邻居的距离。这样会避免一些单纯计数带来的问题。
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 ) \log(N) log(N),N 为实例的个数,KD 树更加适用于点的
数量远大于空间维度的 KNN 搜索,如果空间维度与点个数差不多时,它的效率基于等于线性扫描。
关于 KD 数的构建,搜索和 KNN 查找,网上有很多资料,这里就不介绍了。
可以观察到 KD-tree 是这样一种 tree。它的第一层的第一个元素大于左子树的第一个元素,小于右子树的第一个元素。第二层的第二个元素大于左子树的第二个元素,小于右子树的第二个元素。第 i 层的第 i%k 个元素大于左子树的第 i%k 个元素,小于右子树的,依次类推。
朴素贝叶斯真的很朴素,用到的仅仅只是贝叶斯公式。以二分类为例,它给定若干组的带标签的数据,当新给一组特征时,我们需要判断它属于哪一类。
我们通过比较这组特征下的条件概率 P ( 标签1 ∣ { 特征1,特征2,特征3 } ) P(\text{标签1}|\{\text{特征1,特征2,特征3}\}) P(标签1∣{ 特征1,特征2,特征3})和 P ( 标签2 ∣ { 特征1,特征2,特征3 } ) P(\text{标签2}|\{\text{特征1,特征2,特征3}\}) P(标签2∣{ 特征1,特征2,特征3})大小来对其分类。条件概率的计算可通过贝叶斯公式来计算,即
P ( 标签i ∣ { 特征1,特征2,特征3 } ) = P ( { 特征1,特征2,特征3 } ∣ 标签i ) ∗ P ( 标签i ) P ( { 特征1,特征2,特征3 } ) P(\text{标签i}|\{\text{特征1,特征2,特征3}\}) = \frac{P(\{\text{特征1,特征2,特征3}\}|\text{标签i} )* P(\text{标签i})}{P(\{\text{特征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 ∣ 标签i ) ∗ P ( 特征2 ∣ 标签i ) ∗ P ( 特征3 ∣ 标签i ) P ( { 特征1,特征2,特征3 } ) = P ( 特征1 ) ∗ P ( 特征2 ∣ 标签i ) ∗ P ( 特征3 ) \begin{aligned} P(\{\text{特征1,特征2,特征3}\}|\text{标签i} ) &=& P(\text{特征1}|\text{标签i} )*P(\text{特征2}|\text{标签i} )*P(\text{特征3}|\text{标签i} ) \\ P(\{\text{特征1,特征2,特征3}\} ) &=& P(\text{特征1})*P(\text{特征2}|\text{标签i} )*P(\text{特征3} )\end{aligned} 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)**都是可以通过统计已有的样本数据,用频率来概率得到。
注意要,使用朴素贝叶斯分类方法,我们假设了特征之间相互独立,看起来很有局限。事实上,我们在处理文本数据的时候,常常用到这种方法。
主要就是利用贝叶斯公式,把某组特征下产生某个标签的概率进行了拆解,进一步拆解是利用到了特征之间的不相关性。
基本过程如下:
就这么简单。特征为离散值时直接统计即可(表示统计概率)。特征为连续值的时候假定特征符合高斯分布。
拉普拉斯校验
当某个类别下某个特征划分没有出现时,会有 P ( a ∣ y ) = 0 P(a \mid y)=0 P(a∣y)=0, 就是导致分类器质量降低, 所以此时引入 Laplace 校验,就是对每个类别下所有划分的计数加1。
特征不独立问题
参考改进的贝叶斯网络,使用有向无环图来进行概率图的描述。
优缺点
逻辑回归在有些书中也叫对数几率回归,常用于分类问题,特别是二分类问题。逻辑回归是线性回归的一个延伸,对于二分类问题,我们需要将回归的连续值搞成离散值,基本做法是看其是否大于零。那么参数如何选取呢?所谓的逻辑回归,就是我们在原有的线性回归的基础上,外套一个Sigmoid函数作为取值的概率(准确地来说,应该是取值为正样本 1 的概率),其实上也就是:
p ( y = 1 ∣ x ) = e w T x + b 1 + e w T x + b p ( y = 0 ∣ x ) = 1 1 + e w T x + b \begin{aligned} &p(y=1 \mid \boldsymbol{x})=\frac{e^{\boldsymbol{w}^{\mathrm{T}} \boldsymbol{x}+b}}{1+e^{\boldsymbol{w}^{\mathrm{T}} \boldsymbol{x}+\boldsymbol{b}}} \\ &p(y=0 \mid \boldsymbol{x})=\frac{1}{1+e^{\boldsymbol{w}^{\mathrm{T}} \boldsymbol{x}+b}} \end{aligned} p(y=1∣x)=1+ewTx+bewTx+bp(y=0∣x)=1+ewTx+b1
我们通过最大似然估计来估计参数,最大似然估计就是写出在参数下出现这个结果的概率(为了计算方便,一般取个对数),然后对于参数变量,极大化这个概率值,一般可以直接对参数直接求导。其实,也就是极大化如下的似然函数。
ℓ ( w , b ) = ∑ i = 1 m ln p ( y i ∣ x i ; w , b ) \ell(\boldsymbol{w}, b)=\sum_{i=1}^{m} \ln p\left(y_{i} \mid \boldsymbol{x}_{i} ; \boldsymbol{w}, b\right) ℓ(w,b)=i=1∑mlnp(yi∣xi;w,b)
所谓的Sigmoid函数,它的表达式和图像如图所示,图像右端 y y y的取值表示将线性回归的连续值按零点离散化。
逻辑回归的并行化最主要的就是对目标函数梯度计算的并行化。逻辑回归的条件分布是伯努利分布,而线性回归的是高斯分布。逻辑回归认为函数其概率服从伯努利分布,将其写成指数族分布的形式,最后是可以推导得到 sigmoid 函数,这也是用这个函数的原因。
逻辑回归用于多分类:
对于多分类问题,我们可以用 softmax,这时候优化的参数,不是向量,而是矩阵 θ \theta θ。我们用线性函数外套一个 softmax 作为每个第 j 个类别取值的概率:
p j = e θ j T x ∑ s = 1 k e θ s T x p_{j}=\frac{e^{\theta_{j}^{T} x}}{\sum_{s=1}^{k} e^{\theta_{s}^{T} x}} pj=∑s=1keθsTxeθjTx
别的过程是一样的。
优缺点:
优点
缺点
支持向量机,我们先说线性的情况,以可分的二维的二分类问题为例,它其实上就是寻找一根直线,将平面上的数据点正确地分为两类,并满足分割的间隔达到最大。如图所示,
要分割(a)所示的数据点,显然(b)的分割间隔要大于©的分割间隔。这里可变参数是分割线(“决策面”)的斜率和截距。所谓的间隔就是分割线离两个数据集合的距离,它是用离它最近的一个点来衡量的。我们引两根平行于分割线的面,相切两个数据集,那么就形成了一个间隙。这个间隙内部不含任何的数据点。间隙边缘上的点称作支持向量。
如果将直线表示为 w ⃗ T x ⃗ + b ⃗ = 0 \vec{w}^T\vec{x}+\vec{b}={0} wTx+b=0,那么合理的分割如图。
通过数学推导,我们可以知道,这个问题其实就是求解如下的一个优化问题( w ⃗ \vec{w} w和 b ⃗ \vec{b} b是待求变量):
KaTeX parse error: Unknown column alignment: @ at position 70: …\begin{array}{r@̲{\quad}r@{}l@{\…
其中 y i ∈ { − 1 , 1 } y_i\in \{-1,1\} yi∈{ −1,1},表示两类样本的标签。通过最优化的基本理论(拉格朗日对偶,KKT条件,SMO算法等),我们可以求解这个优化问题。
一般情况下,数据点不一定可以通过一个线性的超平面将其分开。那么我们可以将其映射到更高维的空间中,使其在高维的特征空间中线性可分,通过线性SVM方法将其分开。
线性情况下,最后的决策面的表达式可以表示为 f ( x ) = ∑ i = 1 n α i y i < x i , x > + b f(\textbf{x}) =\sum\limits_{i=1}^n \alpha_iy_i\left<\textbf{x}_i,\textbf{x}\right>+b f(x)=i=1∑nαiyi⟨xi,x⟩+b,这里的 α i \alpha_i αi是原问题拉格朗日乘子系数。对应于高维特征空间,使用线性SVM方法,最后决策面的表达式为:
f ( x ) = ∑ i = 1 n α i y i < Φ ( x i ) , Φ ( x ) > + b f(\textbf{x}) =\sum\limits_{i=1}^n \alpha_iy_i\left<\Phi(\textbf{x}_i),\Phi(\textbf{x})\right>+b f(x)=i=1∑nαiyi⟨Φ(xi),Φ(x)⟩+b,也就是说,分类决策函数只依赖于输入x与训练样本的输入的内积。
这里的 Φ \Phi Φ是原始空间到高维空间的一个映射,比如说它可以是 ( x , y ) → ( x , y , x 2 + y 2 ) (x,y)\rightarrow(x,y,x^2+y^2) (x,y)→(x,y,x2+y2)。因为升维可能造成计算量暴涨,我们寻求一种方法可以直接计算内积 < Φ ( x i ) , Φ ( x ) > \left<\Phi(\textbf{x}_i),\Phi(\textbf{x})\right> ⟨Φ(xi),Φ(x)⟩,即寻找一个函数 k ( x i , x ) k(x_i,x) k(xi,x)来表示 < Φ ( x i ) , Φ ( x ) > \left<\Phi(\textbf{x}_i),\Phi(\textbf{x})\right> ⟨Φ(xi),Φ(x)⟩,这种替换技巧叫做核技巧。因为核函数方法的存在,使得高维空间中的两个向量的内积可以直接计算,大大减少了计算量。
高维空间的决策平面用核函数来表达,那么高维空间中的对偶问题等也可以用核函数来表达,当使用SMO算法迭代求解时,计算量就会大大减小。简单地说,核方法通过用核函数表示高维空间中向量的内积,将原空间升维至高维空间和在高维空间中使用线性SVM方法两个步骤合成了一个步骤。所谓的升维,也可以理解为在原来线性基的基础上,添加一些非线性的基函数,使得分割线不再是直线。
常用的核函数为径向基函数,它的表达式为:
κ ( x 1 , x 2 ) = e − ∣ ∣ x 1 − x 2 ∣ ∣ 2 2 σ 2 \kappa(x_1,x_2) = e^{\frac{-||x_1-x_2||^2}{2\sigma^2}} κ(x1,x2)=e2σ2−∣∣x1−x2∣∣2
σ \sigma σ越小,非线性化程度越高。如果 σ \sigma σ选得很小,则可以将任意的数据映射为线性可分。这有可能会过拟合问题。
常用核函数有:多项式核函数、高斯核函数、字符串核函数。
数学推导:
关于第一步的数学推导,我们只需要有以下的几个基本认知:
优缺点:
优点:
缺点:
我们知道,在做有监督的问题中,有一个损失函数,用来衡量模型的好坏。在回归问题中,如果我们已经知道方程的形式,我们可以做出问题的损失函数。那么我们要做的就是寻找方程的最佳参数,即寻找参数,使得损失函数函数达到最小。乍一听,这就是个优化问题。当然可以对参数的各个分量求导,最后解方程组。问题是,你能确定最后的方程组好解?一般的数值解法有梯度下降法、牛顿法、拟牛顿方法以及信赖域方法等等。
梯度下降方法简单易行,可是当数据量比较大时,梯度下降的计算就特别大。为解决大数据量的优化求解,我们一般可以采用随机梯度下降。
所谓的随机梯度下降,就是相比梯度下将,我们不选择全部的数据点,而是每次随机选择一个或者若干个数据点来构建损失函数,接着再用梯度下降方法求解。看起来很不靠谱的样子,事实上多做几次这个操作,它是可以收敛的最优解的某个邻域的。
随机梯度下降比起梯度下降:
说完随机梯度下降,顺便提一下 Adam加速,Adam使用动量和自适应学习率来加快收敛速度。其在SGD基础上加入了一、二阶动量。
AdaGrad 能够实现学习率的自动更改。如果这次梯度大,那么学习速率衰减的就快一些;如果这次梯度小,那么学习速率衰减的就满一些。
所谓的线性判别分析(LDA),实际上是一种有监督的降维方法。之所以把它放在分类的标题下,是因为数据通过这种方式,在距离上有了更高的区分度,也可以说是为后续的分类做了降维处理。
线性判别分析,以二维数据点举例,就是要一条直线,使得数据点在这根直线上的投影满足类内方差尽可能小,类间距离尽可能大,如图所示。
投影面的选择,往往会影响类内方差,和类间距离。显然图所示的右边一个图更能满足我们的要求。
我们将类间距离的度量作为分子,类内距离的度量作为分母,形成一个目标函数,我们要做的就是最大化这个目标函数。利用广义瑞利商等一些基本的知识,我们就将问题转化为了求特征值的问题。
决策树,顾名思义就是像树一样不断分支。我们对每个特征,选择一定的条件进行判断,就可以将数据不断地分类,直到最后叶子节点满足一定的条件,比如说有同一个标签,那么这就是一棵决策树。举个例子,比如说西瓜好坏的判断,从数据中,我们可能会学习出如图所示的一棵决策树。
分类问题,往往是给定若干组数据,每组数据有一些特征和标签。需要找一棵决策树,使得每组数据按照决策树路径走,最后尽可能地能走到使它正确分类的叶子节点中。一般来说,可能满足条件的决策树有很多,用于做判断特征选择的次序和特征判断条件(阈值设定不同等)的不同都会导致树的不同,我们要做的就是找一棵最好的树。在不同的算法中,“好”的标准往往不同。
比较常用的决策树有ID3、C4.5和分类回归树(CART),他们分别使用信息增益、信息增益率和基尼指数来作为分类条件选择好坏的标准。C4.5是为解决ID3因偏向细小分割造成的过拟合问题的,CART方法的过拟合往往由剪枝方法来处理。
优缺点:
优点:
缺点:
2. 单棵决策树分类能力弱,并且对连续值变量难以处理。
3. 容易过拟合(后续出现了随机森林,减小了过拟合现象)。
基本概念:
信息熵:
Ent ( D ) = − ∑ k = 1 ∣ Y ∣ p k log 2 p k \operatorname{Ent}(D)=-\sum_{k=1}^{|\mathcal{Y}|} p_{k} \log _{2} p_{k} Ent(D)=−k=1∑∣Y∣pklog2pk
信息增益:
Gain ( D , a ) = Ent ( D ) − ∑ v = 1 V ∣ D v ∣ ∣ D ∣ Ent ( D v ) \operatorname{Gain}(D, a)=\operatorname{Ent}(D)-\sum_{v=1}^{V} \frac{\left|D^{v}\right|}{|D|} \operatorname{Ent}\left(D^{v}\right) Gain(D,a)=Ent(D)−v=1∑V∣D∣∣Dv∣Ent(Dv)
增益率:
Gain _ ratio ( D , a ) = Gain ( D , a ) IV ( a ) \operatorname{Gain}\_{\operatorname{ratio}}(D, a)=\frac{\operatorname{Gain}(D, a)}{\operatorname{IV}(a)} Gain_ratio(D,a)=IV(a)Gain(D,a)
IV ( a ) = − ∑ v = 1 V ∣ D v ∣ ∣ D ∣ log 2 ∣ D v ∣ ∣ D ∣ \operatorname{IV}(a)=-\sum_{v=1}^{V} \frac{\left|D^{v}\right|}{|D|} \log _{2} \frac{\left|D^{v}\right|}{|D|} IV(a)=−v=1∑V∣D∣∣Dv∣log2∣D∣∣Dv∣
基尼值:
Gini ( D ) = ∑ k = 1 ∣ Y ∣ ∑ k ′ ≠ k p k p k ′ = 1 − ∑ k = 1 ∣ Y ∣ p k 2 \begin{aligned} \operatorname{Gini}(D) &=\sum_{k=1}^{|\mathcal{Y}|} \sum_{k^{\prime} \neq k} p_{k} p_{k^{\prime}} \\ &=1-\sum_{k=1}^{|\mathcal{Y}|} p_{k}^{2} \end{aligned} 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-mean算法,就是要找到点的一个划分(假设分成k类),使得类内平方和达到最小。用数学来表述就是要求解下式表示的优化问题。
arg min S ∑ i = 1 k ∑ x ∈ S i ∣ ∣ x − μ i ∣ ∣ 2 \mathop {\arg \min }\limits_S \sum\limits_{i = 1}^k {\sum\limits_{x \in {S_i}} {||x - {\mu _i}|{|^2}} } Sargmini=1∑kx∈Si∑∣∣x−μi∣∣2
算法的基本思想是迭代。首先选择k个点作为k个类中心,将所有点按距离中心的远近分配给k个类。接着计算k个类的重心作为新的类中心,继续前述的分配过程,直到中心不再改变,那么分类也不再改变。
容易想到,更新中心为重心步骤,类内距离平方是不增的,重新分配点的步骤距离也是不增,距离平方和有下界,故而算法必然是收敛的。
事实上,算法收敛到会收敛到一个局部最优值,初始点选择得不同,那么最终收敛到的结果可能就不同。
初始点的选择:
首先随机选取一个点作为初始点,然后选择距离与该点最远的那个点作为中心点,再选择距离与前两个点最远的店作为第三个中心店,以此类推,直至选取大 k 个。
选用层次聚类或者 Canopy 算法进行初始聚类。
kmeans 的优化:使用 kd 树。将所有的观测实例构建成一颗 kd 树,之前每个聚类中心都是需要和每个观测点做依次距离计算,现在这些聚类中心根据 kd 树只需要计算附近的一个局部区域即可。
k 怎么选?
EM算法可以形象地比喻鸡生蛋,蛋生鸡的过程。EM 用于隐含变量的概率模型的极大似然估计。它一般分为两步:
如果概率模型的变量都是观测变量,那么给定数据之后就可以直接使用极大似然法或者
贝叶斯估计模型参数。但是当模型含有隐含变量的时候就不能简单的用这些方法来估计,EM 就是一种含有隐含变量的概率模型参数的极大似然估计法。
应用到的地方:混合高斯模型、混合朴素贝叶斯模型、因子分析模型。
所谓的主成分分析,不过是在高维的空间中寻找一个低维的正交坐标系,比如说在三维空间中寻找一个二维的直角坐标系。那么这个二维的直角坐标系就会构成一个平面,将三维空间中的各个点在这个二维平面上做投影,就得到了各个点在二维空间中的一个表示,由此数据点就从三维降成了二维。
这个过程的关键在于,我们如何选取这个低维的坐标系,即坐标系原点在哪?各个轴朝哪个方向?一个原则就是使得各个点到到这个平面的距离平方和达到最小。由此,通过简单地数学推导,就能得到原点的表达公式和坐标系的各个基向量的表达公式。
下面以基于矩阵的视角写出PCA算法的算法流程,输入为p*N矩阵X,输出为d*N矩阵Y。矩阵的每一列都表示一个对象,每一行都表示对象的一个特征表示。
选取了2000x1680的数据集进行了测试,选取降维后维数为20,其降维前后的图像(降维后的图像指的是投影点还原到原空间对应的坐标值重构出的图像)如下所示(选取第一个点为代表):
当数据具备某些非线性结构,如流形结构时,我们希望降维后的数据仍然保持这些结构。那么就提出了LLE降维算法。
LLE (Locally linear embedding):在数据降维后仍然保留原始高维数据的拓扑结构,这种拓扑结构表现为数据点的局部邻接关系。
此算法我们首先要寻求每个数据点的k个最近邻,然后将当前数据点用k个最近邻线性表出,那么就有相对的权重系数。
我们希望数据在降维后数据点之间依然能保持这种线性表出的关系,并且在满足另外一些约束条件的前提下,我们很容易求得降维后的数据。
具体原理和公式网络上有很多人整理得很好,这里不提了。
下面时LLE算法的算法流程,输入为p*N矩阵X,输出为d*N矩阵Y。矩阵的每一列都表示一个对象,每一行都表示对象的一个特征表示。
独立成分分析的经典问题是“鸡尾酒会问题”(cocktail party problem)。该问题描述的是给定混合信号,如何分离出鸡尾酒会中同时说话的每个人的独立信号。当有N个信号源时,通常假设观察信号也有N个(例如N个麦克风或者录音机)。
我所理解的神经网络,无非就是向量和矩阵做乘法,对得到的向量加一个偏置后,外嵌套一个激活函数,得到一个新的向量。对新的向量反复以上过程,就得到新的一层网络……最后的结果和最后的标签有偏差,我们通过链式法则等方式,调整权值矩阵,使偏差达到最小。训练多层神经网络的过程一般就叫做深度学习。
我们所需要考虑的细节就是矩阵的规模,激活函数选什么,内存处理等等问题。
深度学习中的一些基本概念。
对于一维卷积的理解,是在一次坐火车的时候。所谓的一维卷积,无非就是两列火车相向而驰,从头碰头,到尾离尾的过程。我们把两个向量比作两列火车,向量的元素比作每个车厢,那么两个向量做卷积得到的值的每个分量就是计算每个时刻火车重叠部分的点乘,所谓的点乘,就是对应位置做乘法最后求和。花了一点时间做了一个gif如下:
这里需要注意的是,两列火车的长度不定,更不一定等长,可能只有一节车厢,也可能有一列火车或者两列火车有无限长度。所以,卷积的长度=长火车的车厢数+短火车的车厢数-1。当然,也有的一维卷积只考虑计算短火车和长火车重叠部分包含短火车的时刻,即所谓的没有padding。当然,滑动步长也可以不是1。
理解了一维卷积,二维卷积不过只是在一维卷积的基础上,将一维向二维进行了扩充。即拿一个所谓的小矩阵(卷积核、滤波器)去按一定的顺序去扫原矩阵,每个“时刻”都计算矩阵的一个点积,得到一个数值。如下图所示:
可以看出,在从有数字的地方开始卷(没有padding)的话,且步长为1的话,卷出来的矩阵边长=大矩阵边长-小矩阵边长+1。
那么,这么多有什么意义呢?举个简单的例子,它可以提取边缘,如下:
卷积网络,经常说padding,那么所谓的padding又是什么意思呢?一般来说,为了减少信息的丢失或者其他的一些目的。padding表示在原有向量或者矩阵的边缘上扩充地补一些数,比如说补0(zero padding)。padding有三种模式,valid、same和full。什么意思呢?
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掉。
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。
好像要说清楚这个东西不是特别容易的事情。一句话解释就是:反卷积相对于卷积,像是一个逆过程,注意,这里说的逆,只是规模上的逆,而不是整整意义下恢复原来矩阵的逆,想想这也是不可能的。
转置卷积,把矩阵拉成向量来理解比较好理解。举个栗子:4x4的输入,卷积Kernel为3x3, 没有Padding / Stride, 则输出为2x2。这时,输入矩阵可展开为16维向量,记作 x x x,输出矩阵可展开为4维向量,记作 y y y。那么卷积运算可表示为 y = C x y = Cx y=Cx。事实上, C C C可以表示为如下:
那么,转置卷积是什么呢?没错,就是 x ^ = C T y ^ \hat x = C^T\hat y x^=CTy^。
矩阵拉成向量确实好理解了,但是它在原矩阵(向量)时,又是怎么样一种表现呢?能否可视化一下?二维比较抽象,以一维举个例子。考虑no padding,步长为1的卷子,看看它的反卷积是什么。因为:
由上描述,可知:
可以看得出来,这种情况下的反卷积,其实就是把卷积核倒过来,然后对输入做full_padding的卷积。这是没有步长的情况,我们再来看看有步长的情况。假设步长是2,依然是没有padding的卷积,我们来看看反卷积。
反卷积表示为:
我们找一下上面两种情况的规律,发现所谓的反卷积,就是把卷积核倒一下,对输入矩阵做一些0值得插补,最后做各种形式的卷积(same、full等)。我们把这个推广到二维,梳理一下过程如下:
注意:计算padding按规则补0时,统一按照padding=‘SAME’、步长为1*1的方式来计算。
通过以上的介绍,我们已经基本了解了反卷积操作的过程,看下面几张图能够更好地帮助理解。
上图是步长为2的反卷积的一个图示,在蓝色内部补够0后,需要做到5的same padding,所以需要在蓝色外部也要做padding。这里灰色那个是卷积核,表示原卷积核的一个上下颠倒,左右颠倒。当然,反卷积还有很多更一般的情况,总结起来为一下几种:
反卷积,可以理解为卷积操作的逆运算。千万不要当成反卷积操作可以复原卷积操作的输入值,反卷积并没有那个功能,它仅仅是将卷积变换过程中的步骤反向变换一次而已,通过将卷积核转置,与卷积后的结果再做一遍卷积,所以它还有个名字叫转置卷积。
虽然它不能还原出原来卷积的样子,但是在作用上具有类似的效果,可以将带有小部分缺失的信息最大化恢复,也可以用来恢复被卷积生成后的原始输入。
就是梯度下降的步长。
应用梯度下降方法,需要导数,求导数的方法,有反向传播,其实就是链式法则。
正则化是针对过拟合而提出的,正则化项是模型参数向量的范数,是为了降低模型的复杂度。一般的优化问题只是最小化经验风险,正则化是在此基础上加上模型复杂度这一项。并用一定的比率来衡量这一项的系数。加上这一项,可以防止模型训练过度复杂,有效的降低过拟合的风险。
避免过拟合,提高泛化能力的方法有:
正则化(Regularization)包括L1正则化、L2正则化。正则化其实就是在原有的loss funtion后面加上权重。
L2正则化(权重衰减)为:
对权重求导,可得:
这里体现了权重的一个衰减。
L1正则化为:
这个也可以做类似的求导。
L正则化,有点罚函数的味道,这里因为把权重加入到损失函数了,就尽量使得权重尽量小了。人们普遍认为:更小的权值w,从某种意义上说,表示网络的复杂度更低,对数据的拟合刚刚好(这个法则也叫做奥卡姆剃刀)。
参数服从拉普拉斯分布导出 L1 正则化,参数服从高斯分布,导出 L2 正则化。
softmax是一种归一化,它的好处就是使得计算上非常方便,谁用谁知道。
Softmax计算简单,效果显著,非常好用。它也能缓解局部极值的问题。
所谓的dropout,就是以一定的概率p(比如说0.5)先把隐藏层的部分节点藏起来(之所以叫藏起来,是因为与之相关的权重一直都在,只是不更新,下一次选择的时候,如果被藏的节点显示出来了,与之相关的权重还是保持原来的权重),变成一个比较小的网络,对于这个比较小的网络训练,训练到一定程度后,这些显示节点的权重有所更新了,这时候显示隐藏节点,重新以概率p进行选择……反复进行这个过程,知道训练好一个网络。测试的时候,用的是所有的节点,只不过权重得乘以p。
它的基本过程如下:
dropout是一种有效的防止过拟合的方法,另外也是为了减少计算量。它是缓解过拟合的技巧之一。
dropout也是一种集成,如图:
它相当于训练时随机丢弃部分神经元,测试时整合所有神经元。dropout为什么能work呢?好像大家都没有一个很好的解释。简单地理解,有时候,老板交付的任务,两个人单独完成再整合,总比两个人一块做结果要好,有点“三个和尚没水喝”的意思,但也不是绝对的。
我们知道,在做有监督的问题中,有一个损失函数,用来衡量模型的好坏。在回归问题中,如果我们已经知道方程的形式,我们可以做出问题的损失函数。那么我们要做的就是寻找方程的最佳参数,即寻找参数,使得损失函数函数达到最小。乍一听,这就是个优化问题。当然可以对参数的各个分量求导,最后解方程组。问题是,你能确定最后的方程组好解?一般的数值解法有梯度下降法、牛顿法、拟牛顿方法以及信赖域方法等等。梯度下降方法简单易行,可是当数据量比较大时,梯度下降的计算就特别大。
为解决大数据量的优化求解,我们一般可以采用随机梯度下降。所谓的随机梯度下降,就是相比梯度下降,我们不选择全部的数据点,而是每次随机选择一个或者若干个数据点(一个数据点)来构建损失函数,接着再用梯度下降方法求解。看起来很不靠谱的样子,事实上多做几次这个操作,它是可以收敛的最优解的某个邻域的。
如果一个隐层包含足够多的神经元,三层前馈神经网络(输入-隐层
-输出)能以任意精度逼近任意预定的连续函数。
当隐层足够宽时,双隐层感知器(输入-隐层1-隐层2-输出)可以逼
近任意非连续函数:可以解决任何复杂的分类问题。
常用激活函数如下:
白化的目的是去除输入数据的冗余信息。比如训练数据是图像,由于图像中相邻像素之间具有很强的相关性,所以用于训练时输入是冗余的。白化的目的就是降低输入的冗余性。
所谓白化,就是对输入数据分布变换到均值为0,方差为1的正态分布,那么神经网络较快收敛。BN也是源于这个想法。
梯度下降,一般是沿着当前点的负梯度方向走一小步,到下一点,又沿那个那个点的负梯度方向走一步,那么这样走走停停,无疑是走得很慢。
而一个真正的小球的下降要比这聪明多了,从A点滚动到B点的时候,小球带有一定的初速度,在当前初速度下继续加速下降,小球会越滚越快,更快的奔向谷底。momentum动量法就是模拟这一过程来加速神经网络的优化的。
它的基本算法如下:
最为关键的一步就是,走的步长 v n v_n vn(称为速度)是由当前的负梯度方向和前一步的速度 v n − 1 v_{n-1} vn−1做线性组合得到的。前一步的速度又和前前步的速度有关,以此类推,就把速度积累下来了。也就是说,当前的行走的方向和步长,还要综合考虑之前所有的走过的步的方向和步长。我们知道,不管是做傅里叶分析还是做半加速迭代,都习惯把之前的值做个加权平均,好像收敛就会快很多,monmentum好像就有点这个意思。它是为了解决一般SGD方法一直震荡而迟迟不收敛的情况。
动量方法有点像CG,要结合之前的信息。
交叉熵和KL散度以及JS散度都是衡量两个分布(向量)的距离的一种度量。
交叉熵:
KL散度(KL距离,相对熵):
JS散度(JS距离,KL散度的变形):
所谓的batch normalization(批量归一化、批量正则化)就是“减去均值,除以方差”的标准化过程,比如一般正态分布变成标准正态分布。基本思想就是让每个隐层节点的激活输入分布固定下来,来提升训练速度。
它有什么用呢?它主要是为了**避免梯度消失,加速收敛。**把输入数据重新拉回到均值为0,方差为1的区域,这样让每层的输入落在(-1,1)区间,这段刚好是激活函数性能最好的区域。它是分布变得更加均匀,从而梯度方向更接近极值点方向,如下图:
另外,它也克服神经网络受不同初值影响较大的缺点。促进神经网络稳定性发展:使不同层相对独立,每一层可以专注解决本层的问题。
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层用来将输入“压平”,即把多维的输入一维化,常用在从卷积层到全连接层的过渡。其实就是把矩阵拉成一条。
在做二维卷积中,用滤波器卷一次得到的结果就是一个特征图,不同的滤波器,做多次卷积操作就会得到多个特征图。滤波器就是卷积核。
强化学习到底是什么?若是想略微了解强化学习大概的意思和操作,把握一个主干知识,而不做深入研究,看这篇文章就很够了。
强化学习考察的是对于一个对象(智能体),从一个状态执行某种动作到下一个状态,并在这个过程中,给其一定的奖赏或者惩罚,是它尽可能往好的方面去做。就像马戏团的驯养师,对其宠物,若其表现好,就给它一点吃的,若其表现不好,就抽它两鞭子,使得它最后,能够有一系列出色的表现。
为了说清楚这个问题,我们需要介绍一下状态空间 S S S、动作集 A A A、状态转移概率 P P P和奖赏 R R R。
如图所示,状态空间表示所有状态的一个集合,动作集表示所有动作的一个集合。
状态转移概率是一个函数,表示在当前状态 s s s下,执行某个动作 a a a之后,转移到某个状态的概率,即 P : S × A × S ↦ R P : S \times A \times S \mapsto \mathbb{R} P:S×A×S↦R指定了转移概率。举例比如说状态 s 1 s_1 s1下,执行动作 a 1 a_1 a1,可能转移到 s 1 s_1 s1,也可能转移 s 2 s_2 s2,二者概率不同。图示 s 2 s_2 s2也是可以以一定的概率执行相应的动作,执行相应的动作,都以一定的概率转移到不同的状态,为了图示简明,没有画出来。
R : S × A × S ↦ R R : S \times A \times S \mapsto \mathbb{R} R:S×A×S↦R指定了奖赏。这个奖赏不仅跟起始状态和动作有关,也和动作执行后达到的状态有关。
还有一个是策略函数 π \pi π,它表示给你一个状态,你应该要执行什么动作,当然,如果你执行的动作不确定,而是以一定概率执行相应的动作,那么 π \pi π其实就是对应于动作的概率函数,即用 π ( s , a ) \pi(s,a) π(s,a)表示在状态s下选择动作a的概率。要有 ∑ a π ( s , a ) = 1 \sum_{a} \pi(s, a)=1 ∑aπ(s,a)=1。
给定一个策略 π \pi π(这个策略不一定是最优的),那么对于执行动作的步数有限(设为 T T T步)和无限的时候,我们分别定义状态值函数:
{ V T π ( s ) = E π [ 1 T ∑ t = 1 T r t ∣ s 0 = s ] V γ π ( s ) = E π [ ∑ t = 0 + ∞ γ t r t + 1 ∣ s 0 = s ] \left\{\begin{array}{l}{V_{T}^{\pi}(s)=\mathbb{E}_{\pi}\left[\frac{1}{T} \sum_{t=1}^{T} r_{t} | s_{0}=s\right]} \\ {V_{\gamma}^{\pi}(s)=\mathbb{E}_{\pi}\left[\sum_{t=0}^{+\infty} \gamma^{t} r_{t+1} | s_{0}=s\right]}\end{array}\right. { VTπ(s)=Eπ[T1∑t=1Trt∣s0=s]Vγπ(s)=Eπ[∑t=0+∞γtrt+1∣s0=s]
这个状态值函数的意思就是在当前状态 s s s下,平均累积奖赏的一个数学期望,它是一个函数,对于不同的状态 s s s,它有不同的值。当步数是无穷的时候,我们定义一个折扣因子 γ \gamma γ,使得距离越远的地方,奖赏的对累积奖赏影响越小。这里的数学期望,其实有两层含义,一个是指定动作之后,可能会以不同的概率转移到不同的状态,可以求一个期望。另一个是,对于状态 s s s而言,会以 π ( s , a ) \pi(s,a) π(s,a)的概率执行不同的动作,对于不同的动作可以求一个期望。
所以,我们想要做的,其实就是想办法找一个策略,使得这个状态值函数达到最大。这是我们的目标。
有了这个优化目标,我们来看看如何最大化这个优化目标。
不妨考虑模型已知的情况,即状态空间,动作空间,转移概率和奖赏我们都是知道的。在模型不是已知的情况下,比如说奖赏Reward不清楚,我们可以使用模特卡洛的方法,让智能体多做几次动作,计算累积回报,求得平均来得到我们需要的奖赏值。贪婪算法是在“探索”(exploration)和“利用”(exploitation)之间取一个折中,所谓的探索,其实就是以频率替代概率,多做几次实验,取平均值,来作为我们需要的值的期望,所谓的利用,就是在策略中选择期望最大的动作。
对于有限步情况,考虑某一个指定的策略 π \pi π,因为模型已知,它的状态值函数根据数学期望的定义可以进行拆分和全概率展开:
V T π ( s ) = E π [ 1 T ∑ t = 1 T r t ∣ s 0 = s ] = E π [ 1 T r 1 + T − 1 T 1 T − 1 ∑ t = 2 T r t ∣ s 0 = s ] = ∑ a ∈ A π ( s , a ) ∑ s ′ ∈ S P ( s ′ ∣ s , a ) ( 1 T R ( s ′ ∣ s , a ) + T − 1 T E π [ 1 T − 1 ∑ t = 1 T − 1 r t ∣ s 0 = s ′ ] ) = ∑ a ∈ A π ( s , a ) ∑ s ′ ∈ S P ( s ′ ∣ s , a ) ( 1 T R ( s ′ ∣ s , a ) + T − 1 T V T − 1 π ( s ′ ) ) \begin{aligned} V_{T}^{\pi}(s) &=\mathbb{E}_{\pi}\left[\frac{1}{T} \sum_{t=1}^{T} r_{t} | s_{0}=s\right] \\ &=\mathbb{E}_{\pi}\left[\frac{1}{T} r_{1}+\frac{T-1}{T} \frac{1}{T-1} \sum_{t=2}^{T} r_{t} | s_{0}=s\right] \\ &=\sum_{a \in A} \pi(s, a) \sum_{s^{\prime} \in S} P(s^{\prime}|s,a)\left(\frac{1}{T} R(s'|s,a)+\frac{T-1}{T} \mathbb{E}_{\pi}\left[\frac{1}{T-1} \sum_{t=1}^{T-1} r_{t} | s_{0}=s^{\prime}\right]\right) \\ &=\sum_{a \in A} \pi(s, a) \sum_{s^{\prime} \in S} P(s^{\prime}|s,a)\left(\frac{1}{T} R(s'|s,a)+\frac{T-1}{T} V_{T-1}^{\pi}\left(s^{\prime}\right)\right) \end{aligned} 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 ′ ) ) V_{\gamma}^{\pi}(s)=\sum_{a \in A} \pi(s, a) \sum_{s^{\prime} \in S} P(s^{\prime}|s,a)\left(R(s'|s,a)+\gamma V_{\gamma}^{\pi}\left(s^{\prime}\right)\right) Vγπ(s)=a∈A∑π(s,a)s′∈S∑P(s′∣s,a)(R(s′∣s,a)+γVγπ(s′))
上面这俩方程,姑且就叫做值函数递归方程(也叫贝尔曼方程?)。从值函数递归方程上看,我们可以知道,当模型已知,策略已知的情况下,我们其实是可以递归地求得在该策略下各个时刻的状态值函数。也就是说,从值函数的初始值 V 0 π V^\pi_0 V0π出发,通过一次迭代求得各个状态的一步奖赏 V 1 π V_1^\pi V1π,进而再通过一次迭代求得 V 2 π V_2^\pi V2π……
状态-动作值表示的是在某状态下,执行动作 a a a后的一个平均累积奖赏。它和状态值函数相比,因为动作给定了,所以不再计算关于动作的期望。即:
{ Q T π ( s , a ) = ∑ s ′ ∈ S P ( s ′ ∣ s , a ) ( 1 T R ( s ′ ∣ s , a ) + T − 1 T V T − 1 π ( s ′ ) ) Q γ π ( s , a ) = ∑ s ′ ∈ S P ( s ′ ∣ s , a ) ( R ( s ′ ∣ s , a ) + γ V γ π ( s ′ ) ) \left\{\begin{array}{l}{Q_{T}^{\pi}(s, a)=\sum_{s^{\prime} \in S} P(s^{\prime}|s,a)\left(\frac{1}{T} R(s'|s,a)+\frac{T-1}{T} V_{T-1}^{\pi}\left(s^{\prime}\right)\right)} \\ {Q_{\gamma}^{\pi}(s, a)=\sum_{s^{\prime} \in S} P(s^{\prime}|s,a)\left(R(s'|s,a)+\gamma V_{\gamma}^{\pi}\left(s^{\prime}\right)\right)}\end{array}\right. { 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 ) = 1 ∣ A ( s ) ∣ \pi(s, a)=\frac{1}{|A(s)|} π(s,a)=∣A(s)∣1,然后通过值函数递归表达式,算出该策略下每一个时刻的值函数。有了值函数,我们通过状态-动作值函数的表达式,可以求解每一个时刻的状态动作值。有了状态-动作值函数,我们可以通过关于动作最大化状态-动作值函数,进行更新策略: π ′ ( s ) = arg max a ∈ A Q π ( s , a ) \pi^{\prime}(s)=\underset{a \in A}{\arg \max } Q^{\pi}(s, a) π′(s)=a∈AargmaxQπ(s,a)。有了更新后的策略,重复以上过程,直到收敛。这就是所谓的策略迭代算法,通过不断地迭代策略,来找到最优策略。容易证明,上述算法是收敛的。
另一个经典的迭代方法是值迭代方法。用 V ∗ V^* V∗和 Q ∗ Q^* Q∗来表示最优策略 π ∗ \pi^* π∗下的状态值函数和状态-动作值函数。
容易想到的是,某一时刻某一状态下,最优值函数必然是最优策略下的状态-动作值函数关于动作的一个最大化,即:
V ∗ ( s ) = max a ∈ A Q ∗ ( s , a ) V^{*}(s)=\max _{a \in A} Q^{ {*}}(s, a) V∗(s)=a∈AmaxQ∗(s,a)
这个是容易证明的。简单地想,如果某个策略下的某一步的值函数不是最优的,那么一定可以改成状态-动作值的最大化相对应的策略,使状态值增大。
把这个写开,就成了:
{ V T ∗ ( s ) = max a ∈ A ∑ s ′ ∈ S P ( s ′ ∣ s , a ) ( 1 T R ( s ′ ∣ s , a ) + T − 1 T V T − 1 ∗ ( s ′ ) ) V γ ∗ ( s ) = max a ∈ A ∑ s ′ ∈ S P ( s ′ ∣ s , a ) ( R ( s ′ ∣ s , a ) + γ V γ ∗ ( s ′ ) ) \left\{\begin{array}{l}{V_{T}^{*}(s)=\max _{a \in A} \sum_{s^{\prime} \in S} P(s^{\prime}|s,a)\left(\frac{1}{T} R(s'|s,a)+\frac{T-1}{T} V_{T-1}^{*}\left(s^{\prime}\right)\right)} \\ {V_{\gamma}^{*}(s)=\max _{a \in A} \sum_{s^{\prime} \in S} P(s^{\prime}|s,a)\left(R(s'|s,a)+\gamma V_{\gamma}^{*}\left(s^{\prime}\right)\right)}\end{array}\right. { 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′))
上式是关于最优值函数的一个迭代公式,就被称为是贝尔曼最优性方程。其对应的最优状态-动作值函数为:
{ Q T ∗ ( s , a ) = ∑ s ′ ∈ S P ( s ′ ∣ s , a ) ( 1 T R ( s ′ ∣ s , a ) + T − 1 T max a ′ ∈ A Q T − 1 ∗ ( s ′ , a ′ ) ) Q γ ∗ ( s , a ) = ∑ s ′ ∈ S P ( s ′ ∣ s , a ) ( R ( s ′ ∣ s , a ) + γ max a ′ ∈ A Q γ ∗ ( s ′ , a ′ ) ) \left\{\begin{array}{l}{Q_{T}^{*}(s, a)=\sum_{s^{\prime} \in S} P(s^{\prime}|s,a)\left(\frac{1}{T} R(s'|s,a)+\frac{T-1}{T} \max _{a^{\prime} \in A} Q_{T-1}^{*}\left(s^{\prime}, a^{\prime}\right)\right)} \\ {Q_{\gamma}^{*}(s, a)=\sum_{s^{\prime} \in S} P(s^{\prime}|s,a)\left(R(s'|s,a)+\gamma \max _{a^{\prime} \in A} Q_{\gamma}^{*}\left(s^{\prime}, a^{\prime}\right)\right)}\end{array}\right. { 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′))
由贝尔曼最优性方程,容易知道,我们不需要通过策略迭代,一次性就可以把最优策略 π ∗ \pi^* π∗下的值函数统统求出来。由此,所谓的值迭代算法,就不言而喻了。或通过迭代贝尔曼公式,或通过迭代最优动作价值函数进而关于动作求最大化,都能够求得最优策略。不再细述。
强化学习的算法除了值迭代和策略迭代,比较经典的还有Q learning、Sarsa和TD(时序差分),最新的算法还有SAC和TD3等。这些算法的目标都是最大化值函数,都大同小异,可以简单地理解成求动作值函数的各种不同的方法,若只想浅窥深度学习,而不做细致研究,不必再在乎这些算法的推导以及收敛性证明,在合适的情形下直接拿来用就好了。
Q学习算法,需要了解Q表。Q-table 其实就是把状态和动作一个作为行标,一个作为列标搞成表格。我们要求状态-动作值函数( Q Q Q函数)其实也就是要想办法求出最优动作下的Q表。
具体的算法是先随意初始化一个Q表,然后随机地选择状态 s s s和动作 a a a,根据奖赏函数计算出奖赏 R R R,然后根据上述最优状态-动作值函数的迭代公式,更新Q表。如此反复,直到Q表不再变化。
看简单的例子链接或者链接,就很容易明白Q学习时怎么操作的了。
Sarsa是Q学习算法的改进。Sarsa和Q以及TD本质上都是一脉同根的。
对于三者的一个差别和理解,可以看这个链接。
所谓深度强化学习,只不过是用神经网络去表示出最优策略下的状态-动作值函数 Q ∗ ( s , a ) Q^*(s,a) Q∗(s,a)。有了 Q ∗ ( s , a ) Q^*(s,a) Q∗(s,a)的神经网络表示,下面的事情不就好办了?
为什么要用深度学习呢?因为当状态空间和动作空间很大的时候,甚至在连续的情况下,往往是连续的,用值迭代算法,或者Q学习算法,来计算 Q Q Q函数,计算量都太大。而我们知道,神经网络刚好就是来逼近一个复杂的高数据量的函数的,用它来表示 Q Q Q函数,岂不妙哉?基于这样一个想法,才有了深度强化学习。
深度学习需要提供训练数据,标签怎么找?可以将下一步的 Q Q Q值作为标签。直观上理解就是, Q Q Q值变化不大了,往往达到了最优。
但是若使用相同的网络来生成下一个目标 Q Q Q值和估计当前 Q Q Q值,会导致振荡性甚至发散。还有就是,深度学习要求样本之间相互独立且同分布,但强化学习样本并不满足这个条件。因此DQN中使用三个技巧来来解决这一系列问题:经验回放,目标网络和自适应性学习率调整方法。所以,深度强化学习就有了一系列可学习和研究的东西。
这个链接和这个链接上有关于DQN的简单介绍,看看也就明白了。
有几本理论比较清晰的书籍,见此GitHub。
如果对于机器学习没有了解,可以看一下先修课程。
张志华老师的视频教程1,提取码aqyf ,视频教程2,提取码777p ,视频教程3,提取码rjgi。
另外,也可以在哔哩哔哩上搜索张志华老师的机器学习课程以及莫烦的python教程。
Bagging的想法很简单,就是在训练集中均匀、有放回地抽取m个子集作为m个训练集,分别使用分类回归算法,可以得到m个模型,再通过取平均值、取多数票等方法,得到Bagging的结果。
Bagging算法可与其他分类、回归算法结合,提高其准确率、稳定性的同时,通过降低结果的方差,避免过拟合的发生。
过程如下:
在机器学习中,随机森林是一个包含多个决策树的分类器,并且其输出的类别是由个别树输出的类别的众数而定。这个方法结合了 bagging 想法和随机子空间想法,建造决策树的集合。误差使用最后统计误分得个数占总预测样本的比率作为 RF 的 oob (out-of-bag)误分率。每棵树选部分的数据来训练,剩下的作为验证。子树特征也不必选全部的,也是选部分的。回归采用平均,分类采用投票。
每棵树的按照如下规则生成:
随机性的引入,使得随机森林不容易陷入过拟合,并且具有很好得抗噪能力(比如:对缺省值不敏感)。
随机森林分类效果(错误率)与两个因素有关:
减小特征选择个数 m,树的相关性和分类能力也会相应的降低。增大m,两者也会随之增大。所以关键问题是如何选择最优的 m,这也是随机森林唯一的一个参数。
优缺点
“三个臭皮匠顶个诸葛亮”,弱分类器按准确率给予一定权重组合成一个强学习器,降低偏差,这就是 boosting 的基本思想。一个经典的提升算法例子是 AdaBoost。
采用决策树作为弱分类器的梯度提升算法被称为 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 奇异值分解,以此得到缺失值新的估计;重复这个过程,直到收敛。
我不知道为什么网上那么多人总喜欢用公式去表达这几个东西,明明很简单的东西,你给个公式,我还要首先理解一下你公式里面每个字符表示的意思,这不是浪费时间么。
准确率(accuracy)就是我们通常意义下的分类分对的比率。这个有问题啊。比如说 100 个人里面,有 1 个坏蛋,那么我一股脑全当成好人,那还有 0.99 的准确率。
精确率(precision)是对结果而言的,就是你分的所有正样本里面,分对的样本占的百分比。
所谓的召回召回,就是在实际的正样本里面,你判断对的百分比有多少,也就是你召回来的正样本有多少。
F1 值就是精确率和召回率在某种意义下的平均。 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+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 是衡量一个字词在一个文件中的重要性的。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。一个词语在一篇文章中出现次数越多, 同时在所有文档中出现次数越少, 越能够代表该文章。 通过上面的叙述,一个简单的想法就是用词在文章里面的比率除以词在语料库里面的占比,来衡量它在这篇文章中的重要性。但是语料库太大了,一个一个数不现实。不妨用有这个词的文件在语料库里面的占比作为除数。把除变成乘,在取个 log 就有: TFIDF ( w ) = 在某一文章中词条 w 出现的次数 该文章中所有的词条数目 ∗ log ( 语料库的文档总数 包含词条 w 的文档数 + 1 ) \text{TFIDF}(w) =\frac{\text { 在某一文章中词条 } w \text { 出现的次数 }}{\text { 该文章中所有的词条数目 }}*\log \left(\frac{\text { 语料库的文档总数 }}{\text { 包含词条 } w \text { 的文档数 }+1}\right) TFIDF(w)= 该文章中所有的词条数目 在某一文章中词条 w 出现的次数 ∗log( 包含词条 w 的文档数 +1 语料库的文档总数 ) 分母之所以要加1,是为了避免分母为 0。 泛化能力是指模型对未知数据的预测能力。 所谓的过拟合就是说训练得太好了,以至于在测试集上效果不好。过拟合发生在测试误差和训练误差相差太大的情况下。如果一味的去提高训练数据的预测能力,所选模型的复杂度往往会很高,这种现象称为过拟合。特征越多,模型越复杂,越容易过拟合。 产生的原因: 解决方法 判别式模型举例:要确定一个羊是山羊还是绵羊,用判别模型的方法是从历史数据中学习到模型,然后通过提取这只羊的特征来预测出这只羊是山羊的概率,是绵羊的概率。 生成式模型举例:利用生成模型是根据山羊的特征首先学习出一个山羊的模型,然后根据绵羊的特征学习出一个绵羊的模型,然后从这只羊中提取特征,放到山羊模型中看概率是多少,在放到绵羊模型中看概率是多少,哪个大就是哪个。 如果模型是参数的线性函数,并且存在线性分类面,那么就是线性分类器,否则不是。 常见的线性分类器有:LR、贝叶斯分类、单层感知机、线性回归。常见的非线性分类器:决策树、RF、GBDT、多层感知机。SVM 两种都有(看线性核还是高斯核)。 线性分类器速度快、编程方便,但是可能拟合效果不会很好。非线性分类器编程复杂,但是效果拟合能力强。 特征多,数据系数,往往更容易线性可分,我们选择线性分类器,否则,我们选择非线性分类器。 他们都是可以防止过拟合,降低模型复杂度。 为了消除数据特征之间的量纲影响,我们需要对特征进行归一化处理,使得不同指标之间具有可比性。 N 折交叉验证有两个用途:模型评估和模型选择。把这种策略用于划分训练集和测试集,就可以进行模型评估。把这种策略用于划分训练集和验证集,就可以进行模型选择。 交叉验证的核心思想:对数据集进行多次划分,对多次评估的结果取平均,从而消除单次划分时数据划分得不平衡而造成的不良影响。因为这种不良影响在小规模数据集上更容易出现,所以交叉验证方法在小规模数据集上更能体现出优势。 这种过拟合可能不是模型导致的,而是因为数据集划分不合理造成的。这种情况在用小规模数据集训练模型时很容易出现,所以在小规模数据集上用交叉验证的方法评估模型更有优势。 交叉验证与正则化不同:交叉验证通过寻找最佳模型的方式来解决过拟合。而正则化则是通过约束参数的范数来解决过拟合。 误差=偏差+方差。Bias 是用所有可能的训练数据集训练出的所有模型的输出的平均值与真实模型的输出值之间的差异。Variance 是不同的训练数据集训练出的模型输出值之间的差异。Bias 和 Variance 是不可兼得的。过拟合的情况是 Bias 很小,但是方差很大,训练集上搞好了,可以追求 Bias 很小。词袋模型
TF-IDF
泛化
过拟合
生成模型和判别模型
线性分类器和非线性分类器
L1 和 L2 正则化
归一化方法
交叉验证
Bias(偏差)、Error(误差)、Variance(方差)