概述
文章目录
- 初识机器学习
- 入门分类回归算法
- 浅析逻辑回归
- 初探损失函数
- 什么是损失函数?
- 损失函数、代价函数和目标函数三者的区别
- 损失函数的Pytorch实现与机制
- 常用损失函数类型
- 1、nn.CrossEntropyLoss
- 数学原理
- 功能与使用
- 2、nn.NLLLoss()
- 数学原理
- 功能与使用
- 3、nn.BCELoss()
- 数学原理
- 功能与使用
- 4、nn.BCEWithLogitsLoss()
- 5、nn.L1Loss()
- 数学原理
- 功能与使用
- 6、nn.MSELoss()
- 数学原理
- 功能与使用
- 7、nn.SoftMarginLoss()
- 数学原理
- 功能与使用
- 8、nn.CosineEmbeddingLoss()
- 数学原理
- 功能与使用
- 9、nn.MarginRankingLoss()
- 数学原理
- 功能与使用
- 初窥梯度下降算法
- 场景假设(直观理解)
- 局部最优和全局最优:
- 为什么需要梯度下降?
- 梯度下降法缺点?
- 梯度下降的核心思想和算法步骤
- 核心思想
- 算法步骤
- 各种梯度下降法性能比较
- 初遇神经网络
- 基本概念
- 神经网络:神经网络就是按照一定规则将多个神经元连接起来的网络
- 全连接神经网络(FC)
- 神经网络架构
- 神经网络训练的是什么?
- 神经网络常用的模型结构
- 神经网络与机器学习的关系
- 神经网络的基本步骤与细节
- 基本步骤
- 细节介绍
- 正向传播和反向传播
- 正向传播
- 反向传播
- 激活函数
- 激活函数是什么?
- 为什么要使用激活函数
- 常见的几种激活函数
- 如何选择合适的激活函数?
- Batch_Size 大小设置
- batch_size介绍
- 为什么引入batch_size?
- 如何设置Batch_size值
- 学习率设置
- 学习率作用
- Dropout使用
- 什么时候需要用到Dropout?
- 总结
初识机器学习
机器学习起源:上世纪50年代,1959年在IBM工作的Arthur Samuel设计了一个下棋程序,这个程序具有学习的能力,它可以在不断的对弈中提高自己。
机器学习方法:支持向量机,回归,决策树,随机森林,强化方法,集成学习,深度学习等
机器学习作用:一定程度上可以帮助人们完成一些数据预测,自动化,自动决策,最优化等初步替代脑力的任务。
机器学习 本质:对于一个任务及其表现的度量方法,设计一种算法,让算法能够提取中数据所蕴含的规律。
学习方式:
- 有监督学习:输入机器的数据是带有标签,已知数据和其一一对应的标签,训练一个预测模型,将输入数据映射到标签的过程。常用于分类和回归问题
- 无监督学习:输入数据是无标签的,是为了推断出数据的一些内在结构。常用于关联规则的学习以及聚类
- 半监督学习:输入数据部分有标签,部分无标签,可以用来进行预测。【常用于在有监督的分类算法中加入无标记样本来实现半监督分类】
- 弱监督学习:数据集的标签是不可靠的,主要指标记不正确、多种标记、标记不充分、局部标记等。已知数据和其一一对应的弱标签,训练一个智能算法,将输入数据映射到一组更强的标签的过程。
监督学习的步骤:
- 数据的创建和分类,(标注-划分测试和训练集)
- 数据增强(data Augmentation), 一般搜集的数据都包含有扰动信息,需要对数据进行增强。数据增强一般包括,图像旋转,平移,颜色变换,裁剪,仿射变换
- 特征工程(Feature Engineering), 包括特征提取和特征选择【提出的不同的网络结构、正则化、归一化方法实际上就是深度学习背景下的特征工程】
- 构建预测模型和损失 构建模型预测和标签之间的损失函数,常见的损失函数(Loss Function)有交叉熵、均方差等
- 训练, 选择合适的模型和超参数,通过合适的优化方法不断缩小输出与标签之间的差距【优化方法:梯度下降法及其变种】
- 验证和模型选择. 需要进行模型测试。利用验证集来验证模型是否可以准确地得出结果
- 测试和应用.
当有了一个准确的模型,就可以将该模型部署到你的应用程序中。
机器学习和数据挖掘傻傻分不清:
机器学习关心的问题是如何构建计算机程序使用经验自动改进
数据挖掘是从数据中提取模式的特定算法的应用,在数据挖掘中,重点在于算法的应用,而不是算法本身。
联系:数据挖掘是一个过程,在此过程中机器学习算法被用作提取数据集中的潜在有价值模式的工具。
入门分类回归算法
分类算法
分类(Classification)是机器学习的主要任务之一,分类算法是一种典型的监督学习算法,是根据样本的特征将样本划分到合适的类别中。具体来说就是利用训练样本来进行训练,从而得到样本特征到样本标签的映射,再利用该映射来得到新样本的标签,最终达到将样本划分到不同类别的目的。(二元分类问题、多元分类)
常见的几种分类模型有:线性模型、决策树模型、朴素贝叶斯模型、BP神经网络模型等。
回归算法
机器学习的另一个重要任务就是回归(Regression),回归算法同样也是一种监督学习算法。与分类问题不同的是,在分类算法中,样本标签是一些离散的值,每一种标签都代表着一个类别;然而在回归问题中,样本标签是一些连续的值。回归分析的目的是预测连续的数值型的目标值,接受一系列连续数据,寻找一个最适合数据的方程对特定的值进行预测。
常见的几种回归模型有:线性回归、广义线性回归、决策树回归、随机森林回归、岭回归、梯度提高树回归、生存回归、保序回归等。
注意:逻辑回归虽然叫回归算法,不是回归算法,是一种分类算法。
分类算法与回归算法区别
区别:**分类和回归最主要的区别就是输出的结果不同,定性输出称为分类,即离散变量的预测;定量输出称为回归,即连续变量的预测。**例如:预测一个人是小学生、中学生还是大学生,这是一个分类问题;预测一个人的年龄是多少岁,就是一个回归问题。
如何进行选择? 取决于对任务的分析和理解
常用分类算法的优缺点?
分类算法如何评估?
对于众多分类算法而言,需要一个评判标准来评估算法的好坏。主要从以下几种指标来进行评价
对于二分类问题而言,即将实例分成正类(positive)或负类(negative),在实际分类中会出现以下四种情况,具体如下图所示:
(1)若一个实例是正类,并且被预测为正类,即为真正类(True Positive TP)
(2)若一个实例是正类,但是被预测为负类,即为假负类(False Negative FN)
(3)若一个实例是负类,但是被预测为正类,即为假正类(False Positive FP)
(4)若一个实例是负类,并且被预测为负类,即为真负类(True Negative TN)
- 准确率(Accuracy):对于给定的测试数据集,分类器正确分类的样本数与总样本数之比。
Accuracy = T P + T N P + N text { Accuracy }=frac{T P+T N}{P+N} Accuracy =P+NTP+TN
缺点:在正负样本不平衡的情况下,这个指标有很大的缺陷。例如:给定一组测试样本共1100个实例,其中1000个是正类,剩余100个是负类。即使分类模型将所有实例均预测为正类,Accuracy也有90%以上,这样就没什么意义了. - 灵敏度(sensitivity):表示的是所有正例中被分对的比例,衡量了分类器对正例的识别能力。
recall = T P P text { recall }=frac{T P}{P} recall =PTP - 特异性(specificity):表示的是所有负例中被分对的比例,衡量了分类器对负例的识别能力。
recall = T N N text { recall }=frac{T N}{N} recall =NTN - 精确率(Precision):正确分类的正例个数占分类为正例的实例个数的比例[查准率]
precision = T P T P + F P text { precision }=frac{T P}{T P+F P} precision =TP+FPTP - 召回率(recall):正确分类的正例个数占实际正例个数的比例[查全率]
recall = T P T P + F N text { recall }=frac{T P}{T P+F N} recall =TP+FNTP - F1值:为了能够评价不同算法优劣,在Precision和Recall的基础上提出了F1值的概念,来对Precision和Recall进行整体评价。F1的定义如下: F 1 = 精确率 ∗ 召回率 ∗ 2 精确率 + 召回率 F 1=frac{text { 精确率 } * text { 召回率 } * 2}{text { 精确率 }+text { 召回率 }} F1= 精确率 + 召回率 精确率 ∗ 召回率 ∗2
- ROC曲线:是以灵敏度(真阳性率)为纵坐标,以1减去特异性(假阳性率)为横坐标绘制的性能评价曲线。可以将不同模型对同一数据集的ROC曲线绘制在同一笛卡尔坐标系中,ROC曲线越靠近左上角,说明其对应模型越可靠。也可以通过ROC曲线下面的面积(Area Under Curve, AUC)来评价模型,AUC越大,模型越可靠。
什么样的分类器是最优的?
希望的指标结果是的Precision越高越好,同时Recall也越高越好。但是这两个指标在某些情况下山有矛盾的。比如之前说的地震预测,既然不能百分百预测地震的发生,但实际情况中能容忍一定程度的误报。假设在1000次预测中,共有5次预测发生了地震,真实情况中有一次发生了地震,其他4次则为误报。正确率由原来的999/1000=99.9下降为996/1000=99.6。召回率由0/1=0%上升为1/1=100%。对此解释为,虽然预测失误了4次,但真的地震发生前,分类器能预测对,没有错过,这样的分类器实际意义更为重大,正是我们想要的。在这种情况下,在一定正确率前提下,要求分类器的召回率尽量高。
回归类型划分
广义线性模型家族里,依据因变量不同,可以有如下划分:
(1)如果是连续的,就是多重线性回归。
(2)如果是二项分布,就是逻辑回归。
(3)如果是泊松(Poisson)分布,就是泊松回归。
(4)如果是负二项分布,就是负二项回归。
(5)逻辑回归的因变量可以是二分类的,也可以是多分类的,但是二分类的更为常用,也更加容易解释。所以实际中最常用的就是二分类的逻辑回归。
浅析逻辑回归
逻辑回归(LR)
概念:逻辑回归是应用非常广泛的一个分类机器学习算法,它将数据拟合到一个logit函数(或者叫做logistic函数)中,从而能够完成对事件发生的概率进行预测。
注意:声明的是逻辑回归是属于分类算法,最常用的就是二分类的逻辑回归。
优点:简单、可并行化、可解释强
逻辑回归和多重线性回归的区别:因变量不同【如果是连续的,就是多重线性回归;如果是二项分布,就是逻辑回归】
逻辑回归本质:假设数据服从这个分布,然后使用极大似然估计做参数的估计
逻辑回归的由来:追溯到线性回归
线性回归:对于多维空间中存在的样本点,我们用特征的线性组合去拟合空间中点的分布和轨迹
线性回归能对连续值结果进行预测,而现实生活中常见的另外一类问题是,分类问题。最简单的情况是是与否的二分类问题。比如说医生需要判断病人是否生病,银行要判断一个人的信用程度是否达到可以给他发信用卡的程度,邮件收件箱要自动对邮件分类为正常邮件和垃圾邮件等等。
当然,我们最直接的想法是,既然能够用线性回归预测出连续值结果,那根据结果设定一个阈值是不是就可以解决这个问题了呢?事实是,对于很标准的情况,确实可以的,这里我们套用Andrew Ng老师的课件中的例子,下图中X为数据点肿瘤的大小,Y为观测结果是否是恶性肿瘤。通过构建线性回归模型,如hθ(x)所示,构建线性回归模型后,我们设定一个阈值0.5,预测hθ(x)≥0.5的这些点为恶性肿瘤,而hθ(x)<0.5为良性肿瘤。
但很多实际的情况下,我们需要学习的分类数据并没有这么精准,比如说上述例子中突然有一个不按套路出牌的数据点出现,如下图所示:
现在你再设定0.5,这个判定阈值就失效了,而现实生活的分类问题的数据,会比例子中这个更为复杂,而这个时候我们借助于线性回归+阈值的方式,已经很难完成一个鲁棒性很好的分类器了。
这样,逻辑回归就诞生了,它的核心思想是,如果线性回归的结果输出是一个连续值,而值的范围是无法限定的,那我们有没有办法把这个结果值映射为可以帮助我们判断的结果呢。而如果输出结果是 (0,1) 的一个概率值,这样就可以很清晰了。
线性回归与逻辑回归的区别
前面已经介绍过一些,现在进行总结一下
- 线性回归的样本的输出,都是连续值,在逻辑回归中 ,只能取0和1
- 对于拟合函数也有本质的区别
线性回归: f ( x ) = θ T x = θ 1 x 1 + θ 2 x 2 + … + θ n x n 逻辑回归: f ( x ) = P ( y = 1 ∣ x ; θ ) = g ( θ T x ) , 其中, g ( z ) = 1 1 + e − z ~ begin{aligned}&text { 线性回归: } f(x)=theta^{T} x=theta_{1} x_{1}+theta_{2} x_{2}+ldots+theta_{n} x_{n}\&text { 逻辑回归: } f(x)=P(y=1 mid x ; theta)=gleft(theta^{T} xright) text {, 其中, } g(z)=frac{1}{1+e^{-tilde{z}}} end{aligned} 线性回归: f(x)=θTx=θ1x1+θ2x2+…+θnxn 逻辑回归: f(x)=P(y=1∣x;θ)=g(θTx), 其中, g(z)=1+e−z~1
可以看出,线性回归的拟合函数,是对f(x)的输出变量y的拟合,而逻辑回归的拟合函数是对为1类样本的概率的拟合。
那么,为什么要以1类样本的概率进行拟合呢,为什么可以这样拟合呢?
θ T x = 0 theta^{T} x=0 θTx=0 就相当于是1类和0类的决策边界:
当 θ T x > 0 , 则 y > 0.5 ; 若 θ T x → + ∞ , 则 y → 1 , 即 y 为 1 类 ; 当 θ T x < 0 , 则 y < 0.5 ; 若 θ T x → − ∞ , 则 y → 0 , 即 y 为 0 类 ; begin{aligned} &text { 当 } theta^{T} x>0, text { 则 } y>0.5 ;若theta ^{T}xrightarrow +infty ,则y rightarrow 1 ,即y为1类; \ &text { 当 } theta^{T} x<0, text { 则 } y<0.5 ;若 theta ^{T}xrightarrow -infty ,则y rightarrow 0,即y为0类; end{aligned} 当 θTx>0, 则 y>0.5;若θTx→+∞,则y→1,即y为1类; 当 θTx<0, 则 y<0.5;若θTx→−∞,则y→0,即y为0类;
这个时候就能看出区别,在线性回归中 θ T x theta^{T} x θTx 为预测值的拟合函数; 而在逻辑回归中 θ T x theta^{T} x θTx 为决策边界。下表2-3为线性回归和逻辑回归的区别。
逻辑回归常规步骤
- 寻找h函数(即预测函数)
Logistic函数(或称为Sigmoid函数),函数形式为: g ( z ) = 1 1 + e − z g(z)=frac{1}{1+e^{-z}} g(z)=1+e−z1
从函数图上可以看出,函数y=g(z)在z=0的时候取值为1/2,而随着z逐渐变小,函数值趋于0,z逐渐变大的同时函数值逐渐趋于1,而这正是一个概率的范围。
下面左图是一个线性的决策边界,右图是非线性的决策边界。
对于线性边界的情况,边界形式如下:
θ
0
+
θ
1
x
1
+
,
…
,
+
θ
n
x
n
=
∑
i
=
1
n
θ
i
x
i
=
θ
T
x
theta_{0}+theta_{1} x_{1}+, ldots,+theta_{n} x_{n}=sum_{i=1}^{n} theta_{i} x_{i}=theta^{T} x
θ0+θ1x1+,…,+θnxn=i=1∑nθixi=θTx
构造预测函数为:
h
θ
(
x
)
=
g
(
θ
T
x
)
=
1
1
+
e
−
θ
T
x
h_{theta}(x)=gleft(theta^{T} xright)=frac{1}{1+e^{-theta^{T} x}}
hθ(x)=g(θTx)=1+e−θTx1
函数
h
θ
(
x
)
h_{theta}(x)
hθ(x) 的值有特殊的含义,它表示结果取1的概率, 因此对于输入x分类结果为类别1和类别0 的概率分别为:
P
(
y
=
1
∣
x
;
θ
)
=
h
θ
(
x
)
P
(
y
=
0
∣
x
;
θ
)
=
1
−
h
θ
(
x
)
begin{aligned} &P(y=1 mid x ; theta)=h_{theta}(x)\ &P(y=0 mid x ; theta)=1-h_{theta}(x) end{aligned}
P(y=1∣x;θ)=hθ(x)P(y=0∣x;θ)=1−hθ(x)
3. 构造J函数(损失函数)
Cost函数和J函数如下,它们是基于最大似然估计推导得到的。
Cost
(
h
θ
(
x
)
,
y
)
=
{
−
log
(
h
θ
(
x
)
)
if
y
=
1
−
log
(
1
−
h
θ
(
x
)
)
if
y
=
0
J
(
θ
)
=
1
m
∑
i
=
1
n
Cost
(
h
θ
(
x
(
i
)
)
,
y
(
i
)
)
=
−
1
m
∑
i
=
1
n
(
y
(
i
)
log
h
θ
(
x
(
i
)
)
+
(
1
−
y
(
i
)
)
log
(
1
−
h
θ
(
x
(
i
)
)
)
)
begin{gathered} operatorname{Cost}left(h_{theta}(x), yright)= begin{cases}-log left(h_{theta}(x)right) & text { if } y=1 \ -log left(1-h_{theta}(x)right) & text { if } y=0end{cases} \ J(theta)=frac{1}{m} sum_{i=1}^{n} operatorname{Cost}left(h_{theta}left(x^{(i)}right), y^{(i)}right)=-frac{1}{m} sum_{i=1}^{n}left(y^{(i)} log h_{theta}left(x^{(i)}right)+left(1-y^{(i)}right) log left(1-h_{theta}left(x^{(i)}right)right)right) end{gathered}
Cost(hθ(x),y)={−log(hθ(x))−log(1−hθ(x)) if y=1 if y=0J(θ)=m1i=1∑nCost(hθ(x(i)),y(i))=−m1i=1∑n(y(i)loghθ(x(i))+(1−y(i))log(1−hθ(x(i))))
5. 想办法使得J函数最小并求得回归参数(θ)
使用梯度下降法求解最小值
θ
更新过程:
θ
j
:
=
θ
j
−
α
δ
δ
θ
j
J
(
θ
)
δ
δ
θ
J
(
θ
)
=
−
1
m
∑
i
=
1
m
(
y
i
1
h
θ
(
x
i
)
δ
δ
j
h
θ
(
x
i
)
−
(
1
−
y
i
)
1
1
−
h
θ
(
x
i
)
δ
δ
θ
h
θ
(
x
i
)
)
=
−
1
m
∑
i
=
1
m
(
y
i
1
g
(
θ
T
x
i
)
−
(
1
−
y
i
)
1
1
−
g
(
θ
T
x
i
)
)
δ
δ
θ
j
g
(
θ
T
x
i
)
=
−
1
m
∑
i
=
1
m
(
y
i
1
g
(
θ
T
x
i
)
−
(
1
−
y
i
)
1
1
−
g
(
θ
T
x
i
)
)
g
(
θ
T
x
i
)
(
1
−
g
(
θ
T
x
i
)
)
δ
δ
θ
θ
T
x
i
=
−
1
m
∑
i
=
1
m
(
y
i
(
1
−
g
(
θ
T
x
i
)
)
−
(
1
−
y
i
)
g
(
θ
T
x
i
)
)
x
i
j
=
−
1
m
∑
i
=
1
m
(
y
i
−
g
(
θ
T
x
i
)
)
x
i
j
=
1
m
∑
i
=
1
m
(
h
θ
(
x
i
)
−
y
i
)
x
i
j
begin{aligned} &theta text { 更新过程: }\ &begin{aligned} &theta_{j}:=theta_{j}-alpha frac{delta}{delta_{theta_{j}}} J(theta) \ &frac{delta}{delta_{theta}} J(theta)=-frac{1}{m} sum_{i=1}^{m}left(y_{i} frac{1}{h_{theta}left(x_{i}right)} frac{delta}{delta_{j}} h_{theta}left(x_{i}right)-left(1-mathrm{y}_{i}right) frac{1}{1-h_{theta}left(x_{i}right)} frac{delta}{delta_{theta}} h_{theta}left(x_{i}right)right) \ &=-frac{1}{m} sum_{i=1}^{m}left(y_{i} frac{1}{gleft(theta^{mathrm{T}} x_{i}right)}-left(1-mathrm{y}_{mathrm{i}}right) frac{1}{1-gleft(theta^{mathrm{T}} x_{i}right)}right) frac{delta}{delta theta_{j}} gleft(theta^{mathrm{T}} x_{i}right) \ &=-frac{1}{m} sum_{i=1}^{m}left(y_{i} frac{1}{gleft(theta^{mathrm{T}} x_{i}right)}-left(1-mathrm{y}_{mathrm{i}}right) frac{1}{1-gleft(theta^{mathrm{T}} x_{i}right)}right) gleft(theta^{mathrm{T}} x_{i}right)left(1-gleft(theta^{mathrm{T}} x_{i}right)right) frac{delta}{delta_{theta}} theta^{mathrm{T}} x_{i} \ &=-frac{1}{m} sum_{i=1}^{m}left(y_{i}left(1-gleft(theta^{mathrm{T}} x_{i}right)right)-left(1-mathrm{y}_{mathrm{i}}right) gleft(theta^{mathrm{T}} x_{i}right)right) x_{i}^{j} \ &=-frac{1}{m} sum_{i=1}^{m}left(y_{i}-gleft(theta^{mathrm{T}} x_{i}right)right) x_{i}^{j} \ &=frac{1}{m} sum_{i=1}^{m}left(h_{theta}left(x_{i}right)-y_{i}right) x_{i}^{j} end{aligned} end{aligned}
θ 更新过程: θj:=θj−αδθjδJ(θ)δθδJ(θ)=−m1i=1∑m(yihθ(xi)1δjδhθ(xi)−(1−yi)1−hθ(xi)1δθδhθ(xi))=−m1i=1∑m(yig(θTxi)1−(1−yi)1−g(θTxi)1)δθjδg(θTxi)=−m1i=1∑m(yig(θTxi)1−(1−yi)1−g(θTxi)1)g(θTxi)(1−g(θTxi))δθδθTxi=−m1i=1∑m(yi(1−g(θTxi))−(1−yi)g(θTxi))xij=−m1i=1∑m(yi−g(θTxi))xij=m1i=1∑m(hθ(xi)−yi)xij
theta更新过程可以写成:
θ
j
:
=
θ
j
−
α
1
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
x
j
(
i
)
theta_{j}:=theta_{j}-alpha frac{1}{m} sum_{i=1}^{m}left(h_{theta}left(x^{(i)}right)-y^{(i)}right) x_{j}^{(i)}
θj:=θj−αm1i=1∑m(hθ(x(i))−y(i))xj(i)
什么时候用逻辑回归?
- 用于概率预测。用于可能性预测时,得到的结果有可比性。比如根据模型进而预测在不同的自变量情况下,发生某病或某种情况的概率有多大。
- 用于分类。实际上跟预测有些类似,也是根据模型,判断某人属于某病或属于某种情况的概率有多大,也就是看一下这个人有多大的可能性是属于某病。进行分类时,仅需要设定一个阈值即可,可能性高于阈值是一类,低于阈值是另一类。
- 寻找危险因素。寻找某一疾病的危险因素等。
- 仅能用于线性问题。只有当目标和特征是线性关系时,才能用逻辑回归。在应用逻辑回归时注意两点:一是当知道模型是非线性时,不适用逻辑回归;二是当使用逻辑回归时,应注意选择和目标为线性关系的特征。
- 各特征之间不需要满足条件独立假设,但各个特征的贡献独立计算。
Python实现逻辑回归代码
from sklearn.linear_model import LogisticRegression
Model = LogisticRegression()
Model.fit(X_train, y_train)
Model.score(X_train,y_train)
# Equation coefficient and Intercept
Print(‘Coefficient’,model.coef_)
Print(‘Intercept’,model.intercept_)
# Predict Output
Predicted = Model.predict(x_test)
初探损失函数
什么是损失函数?
损失函数就是衡量模型输出与真实标签之间的差异,用来估量你模型的预测值f(x)与真实值Y的不一致程度,它是一个非负实值函数,通常使用L(Y, f(x))来表示,损失函数越小,模型的鲁棒性就越好。
损失函数、代价函数和目标函数三者的区别
- 损失函数(Loss Function)
功能:计算一个样本输出和真实标签之间的差异,表达式如下 Loss = f ( y ^ , y ) text { Loss }=f(hat{y}, y) Loss =f(y^,y) - 代价函数(Cost Function)
功能:计算整个训练集的loss的平均值,表达式如下 cost = 1 N ∑ i N f ( y ^ i , y i ) operatorname{cost}=frac{1}{mathrm{~N}} sum_{mathrm{i}}^{mathrm{N}}mathrm{f}left(hat{mathrm{y}}_{mathrm{i}}, mathrm{y}_{mathrm{i}}right) cost= N1i∑Nf(y^i,yi) - 目标函数(Objective Function)
定义:在机器学习中代表最终的训练目标,表达式如下【 regularization代表正则化】 O b j = cost + regularization O b j=text { cost }+text { regularization } Obj= cost + regularization
损失函数的Pytorch实现与机制
1、损失函数定义
在定义损失函数的时候,经常可以看到首先会对损失函数的计算规则进行定义,以交叉熵损失函数为例,定义语句如下:
criterion = torch.nn.CrossEntropyLoss()
常用的交叉熵损失函数正如上述pytorch自带损失函数定义形式,但是作为初学者也需要知道里面的机制,只需要在Ctrl+ B 即可,小曾带你一探究竟。
执行这句话的时候,就可以看到,其实所有损失函数都会继承一个父类,这个父类的名称是_Loss,其内容如下:
class _Loss(Module):
def __init__(self, size_average=None, reduce=None, reduction='mean'):
super(_Loss, self).__init__()
if size_average is not None or reduce is not None:
self.reduction = _Reduction.legacy_get_string(size_average, reduce)
else:
self.reduction = reduction
2、执行部分
loss = criterion(outputs, labels)
这句话本质上也是属于前向传播的一部分,同样也是会执行torch.nn.Module的forward函数。forward函数内容如下:
def forward(self, input, target):
return F.cross_entropy(input, target, weight=self.weight,
ignore_index=self.ignore_index, reduction=self.reduction)、
调用了定义的函数cross_entropy,函数如下:
if size_average is not None or reduce is not None:
reduction = _Reduction.legacy_get_string(size_average, reduce)
return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction)
通过上面的步骤以及调用关系了解损失函数的功能和机制
常用损失函数类型
1、nn.CrossEntropyLoss
数学原理
首先了解交叉熵、信息熵、和相对熵的概念
信息熵:主要衡量了信息的不确定程度,一个信息的熵越大说明越不确定。【描述整个概率分布的不确定性】
H
p
(
q
)
=
∑
x
p
(
x
)
log
2
(
1
q
(
x
)
)
H_{p}(q)=sum_{x} p(x) log _{2}left(frac{1}{q(x)}right)
Hp(q)=x∑p(x)log2(q(x)1)
相对熵:主要衡量了两个分布之间的差异,描述了两个分布之间的距离。
【注意:相对熵和距离函数有着本质区别,距离函数满足一个重要性质就是对称性,相对熵不满足对称性】
D
K
L
(
P
,
Q
)
=
E
x
∼
p
[
log
P
(
x
)
Q
(
x
)
]
=
E
x
∼
p
[
log
P
(
x
)
−
log
Q
(
x
)
]
=
∑
i
=
1
N
P
(
x
i
)
[
log
P
(
x
i
)
−
log
Q
(
x
i
)
]
=
∑
i
=
1
N
P
(
x
i
)
log
P
(
x
i
)
−
∑
i
=
1
N
P
(
x
i
)
log
Q
(
x
i
)
=
H
(
P
,
Q
)
−
H
(
P
)
begin{aligned} boldsymbol{D}_{K L}(boldsymbol{P}, boldsymbol{Q}) &=boldsymbol{E}_{boldsymbol{x} sim p}left[log frac{boldsymbol{P}(boldsymbol{x})}{boldsymbol{Q}(boldsymbol{x})}right] \ &=boldsymbol{E}_{boldsymbol{x} sim p}[log boldsymbol{P}(boldsymbol{x})-log boldsymbol{Q}(boldsymbol{x})] \ &=sum_{i=1}^{N} boldsymbol{P}left(boldsymbol{x}_{i}right)left[log Pleft(boldsymbol{x}_{i}right)-log boldsymbol{Q}left(boldsymbol{x}_{i}right)right] \ &=sum_{i=1}^{N} boldsymbol{P}left(boldsymbol{x}_{i}right) log boldsymbol{P}left(boldsymbol{x}_{i}right)-sum_{i=1}^{N} boldsymbol{P}left(boldsymbol{x}_{i}right) log boldsymbol{Q}left(boldsymbol{x}_{i}right) \ &=boldsymbol{H}(boldsymbol{P}, boldsymbol{Q})-boldsymbol{H}(mathrm{P}) end{aligned}
DKL(P,Q)=Ex∼p[logQ(x)P(x)]=Ex∼p[logP(x)−logQ(x)]=i=1∑NP(xi)[logP(xi)−logQ(xi)]=i=1∑NP(xi)logP(xi)−i=1∑NP(xi)logQ(xi)=H(P,Q)−H(P)
简单介绍一下上面的表达式:第一个等式就是相对熵的定义式。其中P是真实的分布而Q是模型拟合的分布,上面表达式的意思就是用模型拟合的分布Q去逼近真实的分布P。
交叉熵:若其中一个概率分布p为真实分布,另一个为理论(拟合)分布q,那么交叉熵就是用q的信息量来拟合p分布的信息熵。
【当训练目标是最小化交叉熵的时候,其实就是最小化相对熵】
交叉熵的表达式如下:
H
(
P
,
Q
)
=
−
∑
i
=
1
N
P
(
x
i
)
log
Q
(
x
i
)
mathbf{H}(boldsymbol{P}, boldsymbol{Q})=-sum_{i=1}^{N} boldsymbol{P}left(boldsymbol{x}_{i}right) log boldsymbol{Q}left(boldsymbol{x}_{i}right)
H(P,Q)=−i=1∑NP(xi)logQ(xi)
结合信息熵和相对熵的表达式,可得如下关系
H
(
P
,
Q
)
=
D
K
L
(
P
,
Q
)
+
H
(
P
)
mathbf{H}(boldsymbol{P}, boldsymbol{Q})=boldsymbol{D}_{K L}(boldsymbol{P}, boldsymbol{Q})+mathbf{H}(boldsymbol{P})
H(P,Q)=DKL(P,Q)+H(P)
功能与使用
交叉熵函数是nn.Logsoftmax()与nn.NLLLoss()结合,进行交叉熵计算。这里的nn.Logsoftmax()函数将输入的数据进行了归一化处理,变成了概率分布的形式,再取log后进行输出。而nn.NLLLoss()则是取负号操作。
整个过程的数学表达式如下,无weight时:
loss
(
x
,
class
)
=
−
log
(
exp
(
x
[
class
]
)
∑
j
exp
(
x
[
j
]
)
)
=
−
x
[
class
]
+
log
(
∑
j
exp
(
x
[
j
]
)
)
operatorname{loss}(x, text { class })=-log left(frac{exp (x[text { class }])}{sum_{j} exp (x[j])}right)=-x[text { class }]+log left(sum_{j} exp (x[j])right)
loss(x, class )=−log(∑jexp(x[j])exp(x[ class ]))=−x[ class ]+log(j∑exp(x[j]))
有weight时:
loss
(
x
,
class
)
=
weight
[
class
]
(
−
x
[
class
]
+
log
(
∑
j
exp
(
x
[
j
]
)
)
)
operatorname{loss}(x, text { class })=text { weight }[text { class }]left(-x[text { class }]+log left(sum_{j} exp (x[j])right)right)
loss(x, class )= weight [ class ](−x[ class ]+log(j∑exp(x[j])))
在使用CrossEntropyLoss函数时,其主要参数有
weight:各类别的loss设置权值(例如某类计算好loss后再乘1.5倍)
ignore_ index:忽略某个类别(在某类不计算loss)
reduction :计算模式,none代表逐个元素计算;sum代表所有元素求和,返回标量;mean代表加权平均,返回标量,none/sum/mean 三选一
size_average&reduce:不管,现在这两个变量用reduction就可以替代其作用了
使用实例
inputs = torch.tensor([[1, 2], [1, 3], [1, 3]], dtype=torch.float)
target = torch.tensor([0, 1, 1], dtype=torch.long)
loss_f_mean = nn.CrossEntropyLoss(weight=None, reduction='mean')
loss_mean = loss_f_mean(inputs, target)
输出结果:tensor(0.5224)
2、nn.NLLLoss()
数学原理
数学表达式:
ℓ
(
x
,
y
)
=
L
=
{
l
1
,
…
,
l
N
}
′
,
l
n
=
−
w
y
n
x
n
,
y
n
ell(x, y)=L=left{l_{1}, ldots, l_{N}right}^{prime}, quad l_{n}=-w_{y_{n}} x_{n, y_{n}}
ℓ(x,y)=L={l1,…,lN}′,ln=−wynxn,yn
功能与使用
功能:实现负对数似然函数中的负号功能,也就是对输入取了个负号。
其各项参数与nn.CrossEntropyLoss的参数一样。
使用实例
weights = torch.tensor([1, 1], dtype=torch.float)
loss_f_mean = nn.NLLLoss(weight=weights, reduction='mean')
loss_mean = loss_f_mean(inputs, target)
输出结果:tensor(-2.3333)
3、nn.BCELoss()
数学原理
其数学原理和交叉熵差不多类似,在此不多赘述,直接看数学表达式即可理解:
l
n
=
−
w
n
[
y
n
⋅
log
x
n
+
(
1
−
y
n
)
⋅
log
(
1
−
x
n
)
]
l_{n}=-w_{n}left[y_{n} cdot log x_{n}+left(1-y_{n}right) cdot log left(1-x_{n}right)right]
ln=−wn[yn⋅logxn+(1−yn)⋅log(1−xn)]
功能与使用
功能:二分类交叉熵损失函数,是交叉熵损失函数的一个特例。输入的标签是二分类的,要么是0,要么是1。
BCE原理是每一个神经元一一对应的去计算loss,所以输入的标签不再是整形而是浮点数,同时对输入的数据也有要求,BCE要求其范围必须在0到1之间,否则就会报错。【方法:对于输入inputs之前要经过sigmoid函数将其映射成一个概率值】
使用实例
inputs = torch.tensor([[1, 2], [2, 2], [3, 4], [4, 5]], dtype=torch.float)
target = torch.tensor([[1, 0], [1, 0], [0, 1], [0, 1]], dtype=torch.float)
inputs = torch.sigmoid(inputs)
weights = torch.tensor([1, 1], dtype=torch.float)
loss_f_mean = nn.BCELoss(weight=weights, reduction='mean')
loss_mean = loss_f_mean(inputs, target)
输出结果:tensor(1.4732)
4、nn.BCEWithLogitsLoss()
功能:结合Sigmoid与二分类交叉熵,也就是添加了sigmoid函数,是上面BCELoss的弥补。
在主要参数上有一点不同,这个函数在上面主要参数的基础上添加了pos_weight,代表正样本权值。这个参数主要是为了解决样本不均衡的问题,例如训练集中有100个正样本和900个负样本,那么我们的pos_weight就可以设置为9,以更关注正样本的loss,从而达到不偏斜的目的。
5、nn.L1Loss()
数学原理
数学表达式很简单理解,如下所示
l
n
=
∣
x
n
−
y
n
∣
l_{n}=left|x_{n}-y_{n}right|
ln=∣xn−yn∣
功能与使用
功能:计算inputs与target之差的绝对值
使用实例
inputs = torch.ones((2, 2))
target = torch.ones((2, 2)) * 3
loss_f = nn.L1Loss(reduction='none')
loss = loss_f(inputs, target)
输出结果:L1 loss:tensor([[2., 2.], [2., 2.]])
6、nn.MSELoss()
数学原理
数学表达式很简单理解,如下所示
l
n
=
(
x
n
−
y
n
)
2
l_{n}=left(x_{n}-y_{n}right)^{2}
ln=(xn−yn)2
功能与使用
功能:计算inputs与target之差的平方
使用实例
inputs = torch.ones((2, 2))
target = torch.ones((2, 2)) * 3
loss_f_mse = nn.MSELoss(reduction='none')
loss_mse = loss_f_mse(inputs, target)
输出结果:MSE loss:tensor([[4., 4.], [4., 4.]])
7、nn.SoftMarginLoss()
数学原理
数学表达式:
loss
(
x
,
y
)
=
∑
i
log
(
1
+
exp
(
−
y
[
i
]
∗
x
[
i
]
)
)
x
⋅
nelement
0
operatorname{loss}(x, y)=sum_{i} frac{log (1+exp (-y[i] * x[i]))}{x cdot text { nelement } 0}
loss(x,y)=i∑x⋅ nelement 0log(1+exp(−y[i]∗x[i]))
功能与使用
功能:计算二分类的logistic损失
inputs = torch.tensor([[0.3, 0.7], [0.5, 0.5]])
target = torch.tensor([[-1, 1], [1, -1]], dtype=torch.float)
loss_f = nn.SoftMarginLoss(reduction='none')
loss = loss_f(inputs, target)
输出结果:SoftMargin: tensor([[0.8544, 0.4032], [0.4741, 0.9741]])
8、nn.CosineEmbeddingLoss()
数学原理
其数学表达式为
cos
(
θ
)
=
A
⋅
B
∥
A
∥
∥
B
∥
=
∑
i
=
1
n
A
i
×
B
i
∑
i
=
1
n
(
A
i
)
2
×
∑
i
=
1
n
(
B
i
)
2
cos (theta)=frac{A cdot B}{|A||B|}=frac{sum_{i=1}^{n} A_{i} times B_{i}}{sqrt{sum_{i=1}^{n}left(A_{i}right)^{2}} times sqrt{sum_{i=1}^{n}left(B_{i}right)^{2}}}
cos(θ)=∥A∥∥B∥A⋅B=∑i=1n(Ai)2×∑i=1n(Bi)2∑i=1nAi×Bi
内部运算规则表达式
loss
(
x
,
y
)
=
{
1
−
cos
(
x
1
,
x
2
)
,
if
y
=
1
max
(
0
,
cos
(
x
1
,
x
2
)
−
margin
)
,
if
y
=
−
1
operatorname{loss}(x, y)= begin{cases}1-cos left(x_{1}, x_{2}right), & text { if } y=1 \ max left(0, cos left(x_{1}, x_{2}right)-operatorname{margin}right), & text { if } y=-1end{cases}
loss(x,y)={1−cos(x1,x2),max(0,cos(x1,x2)−margin), if y=1 if y=−1
功能与使用
功能:采用余弦相似度计算两个输入之间的相似性。主要参数有margin,这里margin可取值为[-1, 1],推荐为[0, 0.5]。cosine更加关注的是方向上的差异。
x1 = torch.tensor([[0.3, 0.5, 0.7], [0.3, 0.5, 0.7]])
x2 = torch.tensor([[0.1, 0.3, 0.5], [0.1, 0.3, 0.5]])
target = torch.tensor([[1, -1]], dtype=torch.float)
loss_f = nn.CosineEmbeddingLoss(margin=0., reduction='none')
loss = loss_f(x1, x2, target)
输出结果:Cosine Embedding Loss tensor([[0.0167, 0.9833]])
9、nn.MarginRankingLoss()
数学原理
loss ( x , y ) = max ( 0 , − y ∗ ( x 1 − x 2 ) + margin ) operatorname{loss}(x, y)=max left(0,-y *left(x_{1}-x_{2}right)+text { margin }right) loss(x,y)=max(0,−y∗(x1−x2)+ margin )
当y=1时,希望x1比x2大,当满足这个关系时,不产生loss;
当y=-1时,希望x2比x1大,当满足这个关系时,不产生loss。
功能与使用
功能:计算两个向量间的相似度,通常用于排序任务。具体就是计算两组数据之间的差异,返回一个nxn的loss矩阵。
使用实例
x1 = torch.tensor([[1], [2], [3]], dtype=torch.float)
x2 = torch.tensor([[2], [2], [2]], dtype=torch.float)
target = torch.tensor([1, 1, -1], dtype=torch.float)
loss_f_none = nn.MarginRankingLoss(margin=0, reduction='none')
loss = loss_f_none(x1, x2, target)
输出结果:tensor([[1., 1., 0.],[0., 0., 0.], [0., 0., 1.]])
初窥梯度下降算法
场景假设(直观理解)
一个人被困在山上,需要从山上下来(找到山的最低点,也就是山谷)。但此时山上的浓雾很大,导致可视度很低;因此,下山的路径就无法确定,必须利用自己周围的信息一步一步地找到下山的路。这个时候,便可利用梯度下降算法来帮助自己下山。
怎么做呢,首先以他当前的所处的位置为基准,寻找这个位置最陡峭的地方,然后朝着下降方向走一步,然后又继续以当前位置为基准,再找最陡峭的地方,再走直到最后到达最低处;同理上山也是如此,只是这时候就变成梯度上升算法了
局部最优和全局最优:
全局最优:是需要求得一个问题,在全值域范围内最优【图中整体最优解】
局部最优:是指对于一个问题的解在一定范围或区域内最优【图中局部最优解,在前半段这个范围内是最优解】
为什么需要梯度下降?
梯度下降是机器学习中常见优化算法之一,梯度下降法有以下几个作用:
(1)梯度下降是迭代法的一种,可以用于求解最小二乘问题。
(2)在求解机器学习算法的模型参数,即无约束优化问题时,主要有梯度下降法(Gradient Descent)和最小二乘法。
(3)在求解损失函数的最小值时,可以通过梯度下降法来一步步的迭代求解,得到最小化的损失函数和模型参数值。
(4)如果我们需要求解损失函数的最大值,可通过梯度上升法来迭代。梯度下降法和梯度上升法可相互转换。
(5)在机器学习中,梯度下降法主要有随机梯度下降法和批量梯度下降法。
梯度下降法缺点?
梯度下降法缺点有以下几点:
(1)靠近极小值时收敛速度减慢。
(2)直线搜索时可能会产生一些问题。
(3)可能会“之字形”地下降。
梯度概念也有需注意的地方:
- 梯度是一个向量,即有方向有大小。
- 梯度的方向是最大方向导数的方向。
- 梯度的值是最大方向导数的值。
梯度下降的核心思想和算法步骤
核心思想
- 初始化参数,随机选取取值范围内的任意数;
- 迭代操作: a)计算当前梯度; b)修改新的变量; c)计算朝最陡的下坡方向走一步; d)判断是否需要终止,如否,返回a);
算法步骤
- 确定优化模型的假设函数及损失函数。
- 相关参数初始化。主要初始化 θi、算法迭代步长 、 终 止 距 离 。
- 迭代计算。 a)计算当前位置时损失函数的梯度; b)计算当前位置下降的距离; c)判断是否终止; d)更新所有的 θi ;e)更新后继续迭代a、b、c、d 步骤
各种梯度下降法性能比较
下表简单对比随机梯度下降(SGD)、批量梯度下降(BGD)、小批量梯度下降(Mini-batch GD)、和Online GD的区别:
初遇神经网络
基本概念
神经网络:神经网络就是按照一定规则将多个神经元连接起来的网络
全连接神经网络(FC)
- 有三种层:输入层,输出层,隐藏层
- 同一层的神经元之间没有连接。
- fully connected的含义:第 N 层的每个神经元和第 N-1 层的所有神经元相连第 N-1 层神经元的输出就是第 N层神经元的输入。
- 每个连接都有一个权值。
神经网络架构
输入层:接受信息
隐藏层:对输入信息的传递和加工处理
输出层:得到输入信息的判断结果
举个例子:比如一张猫的图片作为输入,通过隐藏层对特征的提取以及加工,最后在输出的时候判断是否图片是猫。
神经网络训练的是什么?
通过上图网络架构可以看出,目前已知的输入(Input Layer)X和输出(Output Layer)Y,未知的是Input Layer 与 Hidden Layer1 、Hidden Layer2的权重(W)和偏置(b)
神经网络要得到的就是权重W和偏置b,我们统称其为神经网络的参数
神经网络常用的模型结构
下面就用一张图来介绍一下目前常用的模型
神经网络与机器学习的关系
传统的机器学习需要定义一些手工特征,从而有目的的去提取目标信息, 非常依赖任务的特异性以及设计特征的专家经验。
而神经网络属于深度学习的范畴,可以从大数据中先学习简单的特征,并从其逐渐学习到更为复杂抽象的深层特征,不依赖人工的特征工程。
关系图
神经网络的基本步骤与细节
基本步骤
- 定义网络结构(指定输出层、隐藏层、输出层的大小)
假设 X 为神经网络的输入特征矩阵,y 为标签向量。则含单隐层的神经网络的结构如下所示:
其中输入层和输出层的大小分别与 X 和 y 的 shape 有关。而隐层的大小可由我们手动指定。这里我们指定隐层的大小为4。
简单的代码实现:
def layer_sizes(X, Y):
n_x = X.shape[0] # size of input layer
n_h = 4 # size of hidden layer
n_y = Y.shape[0] # size of output layer
return (n_x, n_h, n_y)
- 初始化模型参数
假设 W1 为输入层到隐层的权重数组、b1 为输入层到隐层的偏置数组;W2 为隐层到输出层的权重数组,b2 为隐层到输出层的偏置数组。
其中对权值的初始化我们利用了 numpy 中的生成随机数的模块 np.random.randn ,偏置的初始化则使用了 np.zero 模块。
def initialize_parameters(n_x, n_h, n_y):
W1 = np.random.randn(n_h, n_x)*0.01
b1 = np.zeros((n_h, 1))
W2 = np.random.randn(n_y, n_h)*0.01
b2 = np.zeros((n_y, 1))
assert (W1.shape == (n_h, n_x))
assert (b1.shape == (n_h, 1))
assert (W2.shape == (n_y, n_h))
assert (b2.shape == (n_y, 1))
parameters = {"W1": W1, "b1": b1, "W2": W2, "b2": b2}
return parameters
还有一种常用的初始化参数的方法,参数初始化为正态分布
for name, param in self.named_parameters():
if 'weight' in name:
nn.init.xavier_normal_(param)
- 循环操作:执行前向传播/计算损失/执行后向传播/权值更新
前向传播:在定义好网络结构并初始化参数完成之后,就要开始执行神经网络的训练过程了。而训练的第一步则是执行前向传播计算。假设隐层的激活函数为 tanh 函数, 输出层的激活函数为 sigmoid 函数。
计算当前训练损失:前向传播计算完成后我们需要确定以当前参数执行计算后的的输出与标签值之间的损失大小。
执行反向传播:当前向传播和当前损失确定之后,就需要继续执行反向传播过程来调整权值了。
细节介绍
正向传播和反向传播
神经网络的计算主要有两种:前向传播(foward propagation, FP)作用于每一层的输入,通过逐层计算得到输出结果;反向传播(backward propagation, BP)作用于网络的输出,通过计算梯度由深到浅更新网络参数。
正向传播
从下到上,通过最下面input层,然后通过与节点相连接的隐层的w,b ,经过一层层运算,最后得到Output值的结果Y。
反向传播
反向传播的目的:减少误差
具体细节:
设最终误差为
E
E
E 且输出层的激活函数为线性激活函数, 对于输出那么
E
E
E 对于输出节点
y
l
y_{l}
yl 的偏导数是
y
l
−
t
l
y_{l}-t_{l}
yl−tl, 其中
t
l
t_{l}
tl 是真实值,
∂
y
l
∂
z
l
frac{partial y_{l}}{partial z_{l}}
∂zl∂yl 是指上面提到的激活函数,
z
l
z_{l}
zl 是上面提到的加权和,那么这一层的
E
E
E 对 于
z
l
z_{l}
zl 的偏导数为
∂
E
∂
z
l
=
∂
E
∂
y
i
∂
y
l
∂
z
l
frac{partial E}{partial z l}=frac{partial E}{partial y_{i}} frac{partial y_{l}}{partial z_{l}}
∂zl∂E=∂yi∂E∂zl∂yl 。 同理, 下一层也是这么计算,只不过
∂
E
∂
y
k
frac{partial E}{partial y_{k}}
∂yk∂E 计算方法变了,一直反向传播到输入层,最后有
∂
E
∂
x
i
∣
=
∂
E
∂
y
j
∂
y
j
∂
z
j
frac{partial E}{partial x_{i}} mid=frac{partial E}{partial y_{j}} frac{partial y_{j}}{partial z_{j}}
∂xi∂E∣=∂yj∂E∂zj∂yj, 且
∂
z
j
∂
x
i
∣
=
w
i
j
0
frac{partial z_{j}}{partial x_{i}} mid=w_{i} j_{0}
∂xi∂zj∣=wij0 然后调整这些过程中的权值,再不断进行前向传播和反向传播的过程,最终得到一个比较好的结果。
激活函数
激活函数是什么?
激活函数(Activation functions)对于人工神经网络 模型去学习、理解非常复杂和非线性的函数来说具有十分重要的作用。它们将非线性特性引入到我们的网络中。
主要作用:为了增加神经网络模型的非线性
为什么要使用激活函数
- 激活函数对模型学习、理解非常复杂和非线性的函数具有重要作用。
- 激活函数可以引入非线性因素。如果不使用激活函数,则输出信号仅是一个简单的线性函数。线性函数一个一级多项式,线性方程的复杂度有限,从数据中学习复杂函数映射的能力很小。没有激活函数,神经网络将无法学习和模拟其他复杂类型的数据,例如图像、视频、音频、语音等。
- 激活函数可以把当前特征空间通过一定的线性映射转换到另一个空间,让数据能够更好的被分类。
常见的几种激活函数
常见的传统激活函数主要有两个:sigmoid和tanh。
sigmoid函数
它是使用范围最广的一类激活函数,具有指数函数形状,在物理上最接近神经元。它的输出范围在(0,1)之间,可以被表示成概率,或者用于数据的归一化。
特点:它能够把输入的连续实值变换为0和1之间的输出,特别的,如果是非常大的负数,那么输出就是0;如果是非常大的正数,输出就是1.
缺点:在深度神经网络中梯度反向传递时导致梯度爆炸和梯度消失,其中梯度爆炸发生的概率非常小,而梯度消失发生的概率比较大。
【梯度消失:通过隐藏层从后向前看,梯度会变的越来越小,最终f’(x)变得接近于0,此时,网络参数很难得到有效训练,这种现象被称为梯度消失】
tanh激活函数
tanh函数与sigmoid函数相比,输出均值为0,这就使得其收敛速度要比sigmoid快,从而可以减少迭代次数。
优点:
解决了Sigmoid的输出不关于零点对称的问题
也具有Sigmoid的优点平滑,容易求导
缺点:
激活函数运算量大(包含幂的运算)
Tanh的导数图像虽然最大之变大,使得梯度消失的问题得到一定的缓解,但是不能根本解决这个问题
Relu激活函数
特点: 它在x>0时不存在饱和问题,从而使保持梯度不衰减,从而解决了梯度消失问题。
优点:
1.相比起Sigmoid和tanh,ReLU在SGD中能够快速收敛,这是因为它线性(linear)、非饱和(non-saturating)的形式。
2.Sigmoid和tanh涉及了很多很expensive的操作(比如指数),ReLU可以更加简单的实现。
3.有效缓解了梯度消失的问题。
4.在没有无监督预训练的时候也能有较好的表现。
缺点:
ReLU的输出不是z【ero-centered
Dead ReLU Problem,指的是某些神经元可能永远不会被激活,导致相应的参数永远不能被更新。
Leaky-ReLU激活函数
特点:为了避免ReLU在x<0时的神经元死亡现象,添加了一个参数。
ELU激活函数
正如上图黄色部分那条线,它结合了sigmoid和ReLU函数
优点:
1、融合了sigmoid和ReLU,左侧具有软饱和性,右侧无饱和性。
2、右侧线性部分使得ELU能够缓解梯度消失,而左侧软饱能够让ELU对输入变化或噪声更鲁棒。
3、ELU的输出均值接近于零,所以收敛速度更快。
如何选择合适的激活函数?
选择一个适合的激活函数并不容易,需要考虑很多因素,通常的做法是,如果不确定哪一个激活函数效果更好,可以把它们都试试,然后在验证集或者测试集上进行评价。然后看哪一种表现的更好,就去使用它。
常用经验
1、如果输出是 0、1 值(二分类问题),则输出层选择 sigmoid 函数,然后其它的所有单元都选择 Relu 函数。
2、如果在隐藏层上不确定使用哪个激活函数,那么通常会使用 Relu 激活函数。有时,也会使用 tanh 激活函数,但 Relu 的一个优点是:当是负值的时候,导数等于 0。
3、sigmoid 激活函数:除了输出层是一个二分类问题基本不会用它。
4、tanh 激活函数:tanh 是非常优秀的,几乎适合所有场合。
5、ReLu 激活函数:最常用的默认函数,如果不确定用哪个激活函数,就使用 ReLu 或者 Leaky ReLu,再去尝试其他的激活函数。
6、如果遇到了一些死的神经元,我们可以使用 Leaky ReLU 函数。
可以根据上述常用经验,进行尝试。
Batch_Size 大小设置
batch_size介绍
Batch一般被翻译为批量,设置batch_size的目的让模型在训练过程中每次选择批量的数据来进行处理。
Batch Size直观理解:一次训练所选取的样本数
Batch Size的大小影响模型的优化程度和速度。同时其直接影响到GPU内存的使用情况,假如你GPU内存不大,该数值最好设置小一点。
为什么引入batch_size?
情况1:训练过程中所有的训练数据直接输入到网络
缺点:
1、当训练集样本非常多时,直接将这些数据输入到神经网络的话会导致计算量非常大,同时对极端集的内存要求也比较高。
2、当所有样本同时输入到网络中时,往往很难确定一个全局最优学习率使得训练效果最佳。
情况2:训练过程每次只读取一个样本作为输入
缺点:在每个训练样本上得到的目标函数值差别可能较大,因此最后通过求和或者求平均值的方法而得到的目标函数值不足以代表每个样本。也就是说,这种方法得到的模型对样本的泛化能力差。
因此,就引入batch_size 这一概念,每次只输入一定数量的训练样本对模型进行训练,这个数量就是batch_size的大小。
优点:
1、可以充分利用计算机的并行运算结构,提高数据处理速度;
2、考虑了一定数量的样本数据,可以比较准确得代表梯度下降方向
3、跑完一次 epoch(全数据集)所需的迭代次数减少,对于相同数据量的处理速度进一步加快。
如何设置Batch_size值
batch的size设置的不能太大也不能太小,因此实际工程中最常用的就是mini-batch,一般size设置为几十或者几百。
注意:
1)batch数太小,而类别又比较多的时候,真的可能会导致loss函数震荡而不收敛,尤其是在你的网络比较复杂的时候。
2)随着batchsize增大,处理相同的数据量的速度越快。
3)随着batchsize增大,达到相同精度所需要的epoch数量越来越多。
4)由于上述两种因素的矛盾, Batch_Size 增大到某个时候,达到时间上的最优。
5)由于最终收敛精度会陷入不同的局部极值,因此 Batch_Size 增大到某些时候,达到最终收敛精度上的最优。
6)过大的batchsize的结果是网络很容易收敛到一些不好的局部最优点。同样太小的batch也存在一些问题,比如训练速度很慢,训练不容易收敛等。
7)具体的batch size的选取和训练集的样本数目相关。
8)GPU对2的幂次的batch可以发挥更佳的性能,因此设置成16、32、64、128…时往往要比设置为整10、整100的倍数时表现更优
经验:在设置BatchSize的时候,首先选择大点的BatchSize把GPU占满,观察Loss收敛的情况,如果不收敛,或者收敛效果不好则降低BatchSize,一般常用16,32,64等。
学习率设置
学习率作用
学习率 (learning rate),在迭代过程中会控制模型的学习进度
在梯度下降法中,都是给定的统一的学习率,整个优化过程中都以确定的步长进行更新, 在迭代优化的前期中**,学习率较大**,则前进的步长就会较长,这时便能以较快的速度进行梯度下降,而在迭代优化的后期,逐步减小学习率的值,减小步长,这样将有助于算法的收敛,更容易接近最优解。
总结起来就是:学习率越大,步幅越大,越快能够达到收敛,越容易接近最优解。
**经验:**一般设置初始值 是0.002,看训练神经网络的曲线,进行上下微调
Dropout使用
什么时候需要用到Dropout?
在机器学习的模型中,如果模型的参数太多,而训练样本又太少,训练出来的模型很容易产生过拟合的现象。
过拟合表现:模型在训练数据上损失函数较小,预测准确率较高;但是在测试数据上损失函数比较大,预测准确率较低。
[从图中我们能够看出,模型在训练集上表现很好,但是在交叉验证集上表现先好后差。这也正是过拟合的特征!]
Dropout可以比较有效的缓解过拟合的发生,在一定程度上达到正则化的效果。
简单使用:
self.drop_1 = nn.Dropout(p=0.5)
input_x = self.drop_1(input_x)
总结
上面的几个板块是我在研一期间了解并加以总结的,希望能够为各位小伙伴们提供一些帮助,同时也记录了当初从一开始接触机器学习大一些历程,慢慢的对里面的内容加深巩固,非常适合小白初学者来进行入门,如果对你有所帮助,还请点个关注,点个赞以资鼓励,谢谢大家了!
同时需要注明的是,我是看到 AI浩的文章有所启发, 也觉得需要对研一阶段学习内容进行一些总结,加深巩固,所以在此特别感谢AI浩!
这是大佬的主页:https://wanghao.blog.csdn.net/
https://wanghao.blog.csdn.net/article/details/119415450
https://wanghao.blog.csdn.net/article/details/119604015
还有就是我收藏的文章,觉得比较好的,也很有启发
https://blog.csdn.net/chibangyuxun/article/details/53148005
感兴趣的小伙伴可以去学习学习!
最后
以上就是端庄蜻蜓为你收集整理的小曾带你深入浅出机器学习(入门必备,近3万字带你了解机器学习)的全部内容,希望文章能够帮你解决小曾带你深入浅出机器学习(入门必备,近3万字带你了解机器学习)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复