吴恩达深度学习--改善深层神经网络:超参数调试、正则化以及优化

正则化

参数惩罚项

在吴恩达的机器学习课程中,降到了加入参数项的惩罚项的正则化方法,目的是为了防止过拟合。正则化的方法如下:

dropout

在这个课程中,介绍了dropout正则化。dropout正则化就是每次迭代训练网络时随机删除网络中的一些神经元节点。dropout正则化可以防止过拟合的原因可能是这种方法限制了单一输入节点的作用,因为节点可以随机的被取消。实际上也是起到了压缩权重的方法,和加入参数项的惩罚项的正则化方法有类似之处。

使用dropout正则化的缺点是损失函数J不能被明确定义。

提前终止训练

可以通过提前终止训练的方法,在交叉验证集表现最好的时候保存模型。在实际操作中,可以每隔一定次数的迭代就保存一个模型,最后选择在交叉验证集表现最好的模型进行使用。

正则化输入

使得输入数据遵循:

梯度消失与梯度爆炸

在深层神经网络中,每一层都是以乘法形式运算。如果数值比1大,则随着网络的加深,数值会越来越大,产生梯度爆炸的现象;反正,则会产生梯度消失的现象。
解决方法是按照一定的规律设置初始权重为1左右,并且对于不同的激活函数,设置方法也不太相同。

优化算法

mini-batch

以特定数量的训练样本为一组进行计算损失和更新网络参数值,而不是所有训练样本为一组。这样可以加快训练速度,避免训练集样本过多时内存占用大的问题。

momentum

动量梯度下降(momentum)算法是利用指数加权平均的方法,在更新需要训练的网络参数的时候,参考之前的偏差,按照下式进行更新:

其中α为学习率。

由于初始的dW、db值为0,导致初期的计算结果与实际值偏移较大,可以用偏差修正的方法,即:

其中t为迭代次数。这样就可以在前期也可以得到较为准确的结果。

RMSprop

RMSprop算法应用于减缓b方向的学习和加速W方向的学习。(具体原理我也没弄明白)

公式如下:

其中ε是一个很小的数,目的是防止分母为0。

Adam

Adam算法(Adaptive Moment Estimation)就是将momentum和RMSprop结合起来,作用于更新网络参数的时候。

公式如下:

通常β1=0.9、β2=0.999、ε=10-8。

学习率衰减

通过迭代次数来减小学习率而不是使用固定的学习率,有助于提升模型训练速度和训练出更接近最优的模型。学习率衰减的方法有很多,视情况而定。

吴恩达深度学习--神经网络与深度学习

计算图

吴恩达老师用计算图形象的说明的链式求导的问题。链式求导是反向传播算法(BP算法)的核心依据。

举个例子,如果,f是关于z的函数,z又是关于x的函数,则链式求导就是:

向量化

在深度学习中,数据的处理量往往是巨大的。为了加快运算,可以采用并行运算的方法节约运算时间,增加效率。向量化的方法就是将神经网络间的运算表示为矩阵运算的形式,从而进行并行计算;而不是使用for循环。在python中可以使用numpy库进行矩阵运算。

激活函数

神经网络需要使用非线性激活函数,否则整个神经网络就可以用一层的线性结构来代替。

常用的非线性激活函数有ReLU、sigmoid、tanh等。

sigmoid函数并不是很常用,因为在原理零点的时候,sigmoid函数导数很小,训练网络时容易产生梯度消失。所以sigmoid函数大多数只作为二元分类的最后一层的激活函数。在大多数应用场景中,它的效果不如tanh函数。

ReLU函数的优点是执行速度快。有一种改进的ReLU函数叫做leaky ReLU,它在负半轴有一个很小的正斜率。

前向传播和反向传播

前向传播和反向传播的大概结构和原理如下图所示。

BP

反向传播算法运用于训练神经网络模型,更新学习参数以得到最小的loss值。反向传播的核心思想就是利用链式求导求出每一层参数w和b的误差dw和db,按照学习率更新参数w和b。

参数和超参数

参数指的是在神经网络中可以通过训练进行改变和优化的参数,比如网络中的权值。

超参数指的是训练之前预先设定好的参数。比如学习率,迭代次数,隐藏层层数,每层的神经元个数,选择的激活函数等。

吴恩达机器学习公开课

本文主要总结吴恩达老师机器学习公开课的知识点。课程共8次编程作业已经上传到我的GitHub上了。链接为:https://github.com/Andyflying/ML-assignment-professorNg

回归和分类

回归问题是指用已知数据拟合一个合适的假设函数h(x),或者可以理解为曲线,来预测新输入的变量的输出结果,如给定房间的大学位置等信息,预测房价。
而分类问题,顾名思义,是指用已知数据拟合一个合适的假设函数h(x),对未知数据进行分类。在分类问题中,用到的假设函数为logistic函数:

回归问题和分类问题的代价函数也有所不同。回归问题的代价函数为:

含义显而易见,就是要最小化预测值和真实值之间的误差。其中m为样本个数,x^i为第i个样本。前面的分母为2m的原因可能是求导方便。

分类问题的代价函数为:

由于标签只有0和1,而预测值是0~1之间的小数,所以采用这个代价函数更能反映预测的误差。

梯度下降算法

对代价函数求导,以一个学习率来逐渐更新需要学习的参数。

其中,mini-batch算法可以在训练集中取一部分求损失,然后进行梯度下降,这样可以提升速度。

正则化

正则化是防止过拟合的算法。在损失函数的基础上,加入参数项的惩罚项,目的是不让参数的值过大而产生比较歪歪曲曲的函数。如分类问题正则化代价函数为:

需要注意的是,正则化不作用于偏移项。

神经网络

(略,在我的吴恩达深度学习课程笔记中有这一部分的介绍。)

支持向量机

支持向量机是一个分类器,具体来说是最大间距分类器。

其优化目标和前面提到的logistic分类问题有些相似,具体是:

其中:

C为调节正则化的参数。

支持向量机和logistic分类不同的是支持向量机只返回0或1(是正样本还是负样本)的结果,并不会返回一个0~1之间的小数来表征概率。因为支持向量机是通过超平面将特征划分为两类的,其中法向量指向的是正类,另一侧为负类。

支持向量机的大边界分类的原理可以简单概括为在满足两个cost函数为0的情况下,最小化后面的正则项,即:

其中,p^i为x^i在向量θ上的投影。

要使得θ越小,所以p就得越大,由于θ参数是分类超平面的法向量,也就是说每个样本的特征向量在分类超平面的法向量的投影需要越大越好,也就是说每个样本的特征向量和分类超平面的法向量夹角越小越好。如图所示:

SVM

为了解决分类中的非线性问题,支持向量机引入了核函数的方法。

由于SVM分类器(未引入核函数之前)的模型是线性的,不能很好的对如下图所示的情况进行分类。所以需要引入核函数来处理非线性的问题。
核函数的解决方案是用新的特征f来代替输入向量的特征x,从而构造新的假设函数:

新的特征f如何构造呢?首先我们选取标定向量l,l的选取方法为训练集中每个x的位置。即:

给定一个训练实例x^i,分别对每个l求近似程度来构成新的特征f。求近似程度(f与x/l之间的映射关系)的方法就是我们说的核函数。下面以常用的高斯核函数为例说明其过程:

经过以上过程的处理,成功的在假设函数中用f替代了x,接下来的处理过程同上面介绍的线性的SVM。

K-means聚类

K-means是一种聚类算法,属于无监督学习。

可以设置K个聚类中心,也就是将你的训练样本分为K类。算法原理是首先,随机设置K个点,然后将每个训练样本归类到最近的聚类中心,然后将每个聚类中心移动到所以这一类的样本的平均值的位置。重复执行这个过程,直到距离中心不在变化。

需要充分理解K-means算法的损失函数,即:

其中,c^i是指x^i所属于是聚类中心,μ是指各个聚类中心的位置。

PCA

PCA (Principal Component Analysis,主成分分析)是一种降维算法。比如需要将三维的数据集降为二维,就是寻找一个离数据点最近的平面,将数据点映射到此平面内。下图为二维数据集降为一维:

PCA

PCA算法的数学原理详见https://andyflying.github.io/2019/10/10/pcaAlgorithm/

异常检测

感觉异常检测算法既可以看做监督学习,又可以看做无监督学习,有点迷。
异常分析简单讲就是将数据归一化之后,建立高斯分布模型。然后设置阈值,未能达到阈值的样本就认为是异常样本。
算法具体步骤是对给定数据集,计算每一个维度特征的均值μ和方差σ2。

当p(x)<ε时认为是异常。

但是上述算法存在问题,如图所示:
多元高斯分布问题

可以通过构建协方差矩阵来解决。当然通过自己根据特征的相关性添加新的组合特征向量也可以解决此问题。

推荐系统

推荐系统是根据用户对已有部分产品的评价来自动的为用户推荐同类产品,从而产生广告效益。(ps:很赚钱)

课程中讲的问题实例是推荐电影。利用已有的各个用户的评分数据去学习下图中?的数据。其中x1,x2可以看做是每个电影的类别信息,x项的多少可以根据情况设定。

电影推荐问题

采用的方法是协同过滤算法:

算法执行的过程是先对给定的x来优化θ:

让用给定的θ来优化x:

迭代执行上述两个优化过程,从而实现对总的损失函数J(x,θ)进行优化。

Codeforces-Round-#510-problem(D)-Petya-and-Array

题目链接

本题如果采用两层for循环遍历每个l和r,时间复杂度为O(n2),将会超时。所以可以采用分治的算法,将数组二分递归,完成一个分支之后将此次l和r之间的数进行排序,目的是能以O(n)的时间复杂度统计出此分支符合要求的个数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <bits/stdc++.h>
#define FOR(I,A,B) for(int I = (A); I < (B); I++)
#define FORE(I,A,B) for(int I = (A); I <= (B); I++)
#define PRII pair<int,int>
#define LL long long
#define INF 1000000001

using namespace std;
int n;
LL a[200005],t;
LL ans;
void dg(int l, int r){
if(l==r) return;
int mid=(l+r)/2;
dg(l,mid);
dg(mid+1,r);
for(int i=l,j=mid;i<=mid;i++){
while(j<r && (a[j+1]-a[i])<t) j++;
ans+=j-mid;
}
sort(a+l,a+r+1);
}
int main()
{
cin>>n>>t;
FORE(i,1,n){
cin>>a[i];
a[i]+=a[i-1];
}
dg(0,n);
cout<<ans<<endl;
return 0;
}

Bubble-Cup-11-Finals-Online-Mirror-Div-2-problem-H-Palindrome-Pairs

题目链接

此题是字符处理,两两枚举判断时间复杂度为O(n2),不能满足要求,可以利用小写字母只有26个可以优化时间复杂度。如果字符串字母都为偶数或者只有一个字母为奇数,则两两符合条件。统计每个字符串奇数字母并记录再根据上述条件求解即可,时间复杂度为O(n)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <bits/stdc++.h>
#define FOR(I,A,B) for(int I = (A); I < (B); I++)
#define FORE(I,A,B) for(int I = (A); I <= (B); I++)
#define PRII pair<int,int>
#define LL long long
#define INF 1000000001
#define N 200005
using namespace std;
int n;
map<int,int>m;
LL ans;
int main()
{
cin >> n;
FORE(i,1,n){
string s;
int w = 0;
cin >> s;
FOR(j,0,s.length()) w^=1<<(s[j]-'a');
ans+=m[w];
FOR(j,0,26){
if(m.find(w^(1<<j)) != m.end()) ans+=m[w^(1<<j)];
}
m[w]++;
}
cout << ans << endl;
return 0;
}