作者归档:feiguyun

第5章 梯度下降法

机器学习中一项重要任务就是求目标函数(或称为损失函数)的极小值或极大值。通过求目标函数的极值来确定相关权重参数,从而确定模型。如何求目标函数(注,这里的目标函数如果没有特别说明,一般指凸函数)的极值?最常用的一种方法就是梯度下降法。接下来我们将介绍梯度下降法及几种变种方法。

5.1.梯度下降法

梯度不仅是走向极值的方向,而且是下降最快的方向。
假设函数f(x)的有最小值,如图5-4所示。梯度下降法的数学表达式为:
x_1=x_0-\lambda\nabla f(x_0)
其中
1、参数λ称为步长或学习率,
图5-1 学习率对寻找最优点过程的影响
2、这里为何取梯度的负值?
从图5-2可知,无论从左到右还是从右到左,沿梯度的负方向都是指向极小值(如果梯度正方向将指向函数的极大值)。

图5-2 梯度下降法示意图
如何理解沿梯度是函数值下降最快的方向呢?下面进行简单说明。
根据导数的定义及泰勒公式,可得函数梯度与函数增量、自变量增量之间的关系。
f(x+\nabla x)-f(x)=(\nabla f(x))^T \nabla x+o(||\nabla x||)
如果\nabla x足够小,则可以忽略高阶无穷小项,从而得到:
f(x+\nabla x)-f(x)\approx(\nabla f(x))^T \nabla x
由于(\nabla f(x))^T \nabla x=||\nabla f(x)||?||\nabla x||cos\theta
其中\theta\nabla f(x)\nabla x之间的夹角,由于-1\leq cos\theta\leq 1,因此,
如果\nabla x=-\nabla f(x),cos\theta=-1,此时,当||\nabla f(x)||||\nabla x||一定时,沿梯度的反方向下降最快。
【说明】为何取负梯度?
求极小值,梯度的方向实际就是函数在此点下降最快的方向!而我们需要朝着下降最快的方向走,自然就是负的梯度的方向,所以此处需要加上负号。
如果求极大值,则取梯度的正方向即可。

5.2 单变量函数的梯度下降法

假设函数f(x)=x^2+3,
使用梯度下降法,得到极值点。具体采用迭代法,沿梯度方向(或梯度负方向)逐步靠近极值点,如下图所示:

具体实现方法:

用迭代法求函数f(x)=x^2+3的最优点。

用python代码实现:

运行结果:
x1:0.4000
x2:0.0800
x3:0.0160
x4:0.0032
x5:0.0006
x6:0.0001
x7:0.0000
练习:用梯度下降法求函数f(x)=(x-1)^2+2的极值点(迭代3次或以上),并用python实现这个过程。

5.3 多变量函数的梯度下降法

如何用梯度下降方法求极值?以下通过一个简单示例来说明。
假设f(X)=x_1^2+x_2^2,该函数的最小值点为(0,0),用梯度下降法来一步步逼近这个最小值点。
假设从点(1,3)开始,学习率设为\eta=0.1,函数f(X)的梯度为:
\nabla f(X)=(2x_1,2x_2)
梯度方向是下降最快的方向,如下图所示:

实现上图的python代码:


用Python实现代码以上过程:

运行结果
x1:0.1074,x2:0.3221
x1:0.0115,x2:0.0346
x1:0.0012,x2:0.0037
x1:0.0001,x2:0.0004
x1:0.0000,x2:0.0000
练习:
用梯度下降法求函数f(x_1,x_2)=(x_1-1)^2+(x_2-1)^2的最优点,并用python实现并可视化。

5.4 梯度下降法的应用

梯度可以通过迭代的方法来求极值点,但更重要的作用是通过这个过程,来求梯度中的权重参数,从而确定模型。
例如,
求梯度时,往往涉及很多样本,根据这些样本更新参数。每次更新时,如何选择样本是有讲究的。
如果样本总数不大,我们每次更新梯度时,可以使用所有样本。但如果样本比较大,如果每次都用所有样本更新,在性能上不是一个好的方法,这时我们可以采用其它方案,这样既保证效果,又不影响性能。训练时根据样本选择方案不同,大致可分为:
(1)随机梯度下降法
每次求梯度时,不是使用所有样本的数据,而是每次随机选取一个样本来求梯度。这种方法每次更新梯度较快,但这种方法更新梯度振幅较大,如果样本较大,这样方法也非常耗时,效果也不很理想。
(2)批量梯度下降法
针对随机梯度下降法的不足,人们又想到一个两全其美的方法,即批量随机梯度下降法,这种方法每次更新梯度时,随机选择一个批量来更新梯度。这种方法有更好稳定性,同时性能方面也不错,尤其适合与样本比较大时,优势更加明显。
用梯度下降法拟合一条直线:
h_{\theta} (x)={\theta}_1 x+{\theta}_0
其中:\theta_0 ,\theta_1为参数。
假设y为真实值,根据不同的样本x,代入h_{\theta}(x)便可得到预测值。
我们的目标是尽量使真实值y与预测值h_{\theta}(x)尽可能接近,换句话,就是使它们之间的距离,通过不断学习样本,不断更新参数\theta=[\theta_0,{\theta}_1],使以下目标函数的值最小。
L(\theta_0,\theta_1)=\frac{2}{m}\sum_{i=1}^m(y^i-h_{\theta}(x^i))^2
即:\underset{\theta_0,\theta_1}{lim}L(\theta_0,\theta_1)
使用批量梯度下降法处理以上这个回归问题,具体算法如下:
\theta_i=\theta_i-\lambda\frac{\partial}{\partial\theta_i}L(\theta_0,\theta_1),i=0,1
写成矩阵的形式:
h_{\theta}(x)=\theta_0+\theta_1 x_1+\cdots+\theta_n x_n
用X表示m个样本:X=\left(\begin{matrix}1&x_1^1&\cdots&x_n^1 \\ \vdots&\vdots&\ddots&\vdots \\ 1&x_1^m&\cdots&x_n^m\end{matrix}\right),这是一个m\times(n+1)矩阵
\theta=\left(\begin{matrix}\theta_0 \\ \theta_1\\ \vdots \\ \theta_n\end{matrix}\right) 这是一个(n+1)\times1矩阵
X\theta内积的形状为:m\times1
Y=\left(\begin{matrix}y_1 \\ y_2\\ \vdots \\ y_m\end{matrix}\right)这是一贯mx1向量,
使用矩阵向量方式定义损失值:

5.5 用Python实现批量梯度下降法

批量梯度下降法用Python实现:

训练模型并可视化运行结果

运行结果如下:
最终j_history值:
[0.10784944]
最终theta值:
[[-0.27223179]
[ 0.6187312 ]]
可视化结果如下:

【说明】

5.6np.array与np.mat的区别

1.生成数组所需数据格式不同
np.mat可以从string或list中生成;而np.array只能从list中生成。
2.生成的数组计算方式不同
np.array生成数组,用np.dot()表示内积,(*)号或np.multiply()表示对应元素相乘。
np.mat生成数组,(*)和np.dot()相同,都表示内积,对应元素相乘只能用np.multiply()。
3.生成维度不同
np.mat只生成2维,np.array可生成n维。
建议使用array格式,因很多numpy函数返回值都是array格式。

5.7 用Python实现随机梯度下降法

1.定义损失函数、梯度函数

2.运行梯度函数及可视化运行结果

3.运行结果
最终j_history值:
[0.07909981]
最终theta值:
[-0.25281579 0.60842649]

【练习】
把数据集改为:
m = 100000
x1 = np.random.normal(size = m)
X = x1.reshape(-1,1)
y = 4. * x1 + 3. +np.random.normal(0,3,size = m)
x= np.hstack([np.ones((len(x1),1)), X])

第4章 梯度

偏导数是对一个变量求导,它只反应函数与一个自变量之间的关系,无法反应所有自变量与函数的关系。梯度则连接函数所有自变量的导数,综合了对所有自变量的关系,对单变量而言,梯度就是微分;对多变量函数而言,它是多元函数对多个自变量偏导数形成的向量。

4.1 单变量函数的梯度

对单变量函数(如f(x)=3x^2+4),其微分就是梯度,梯度通常用倒三角(\nabla)表示:
如函数f(x)在点x处的梯度,可表示为
\nabla f(x)=D(f(x))=\frac{df}{dx}=6x
函数f(x)在点x的梯度就是函数在该点的切线斜率。

4.2 多变量函数的梯度

多变量函数(如f(x,y)=3x^2+xy+y^2+1)的梯度
对多变量函数,如y=f(x_1,x_2,\cdots,x_n),则函数y的梯度是对所有自变量的偏导数构成的向量,表示如下:
\nabla f(x)=[\frac{\partial f}{\partial x_1},\frac{\partial f}{\partial x_2},\cdots,\frac{\partial f}{\partial x_n}]^T
梯度的方向就是函数给定点上升最快的方向,梯度的反方向是函数在给定点下降最快的方向。
梯度有什么作用呢?它是寻找函数极值的重要依据,下节将详细介绍。

4.3梯度与梯度直方图(HOG)

图像的梯度(x和y导数)非常有用,因为边缘和拐角(强度突变的区域)周围的梯度幅度很大,并且边缘和拐角比平坦区域包含更多关于物体形状的信息。
方向梯度直方图(Histogram of Oriented Gradient,HOG)

4.3.1图像梯度

梯度的方向是函数 f(x,y) 变化最快的方向,当图像中存在边缘时,有一些相邻像素的灰度值变化比较大,即一定有较大的梯度值。所以可以求图像的梯度来确定图像的边缘。
图像梯度是指图像某像素在x和y两个方向上的变化率(与相邻像素比较),是一个二维向量,由2个分量组成,X轴的变化、Y轴的变化 。
其中X轴的变化是指当前像素右侧(X加1)的像素值减去当前像素左侧(X减1)的像素值,如下图所示:

同理,Y轴的变化是当前像素下方(Y加1)的像素值减去当前像素上方(Y减1)的像素值。
计算出来这2个分量,形成一个二维向量,就得到了该像素的图像梯度。
分别对图像按照x方向和y方向进行求偏导,得到x梯度图和y梯度图。
导数的含义就是计算像素灰度值的变化率,对于离散图像而言,在图像上使用一阶差分来计算相邻像素之间的差值,从而得到图像的梯度。
下面这个公式表示了图像的梯度:
\begin{aligned}\nabla f &=\left(\begin{matrix}f_x \\ f_y\end{matrix}\right)\\ &=\left(\begin{matrix}\frac{\partial f(x,y)}{\partial x}\\ \frac{\partial f(x,y)}{\partial y}\end{matrix}\right) \\&=\left(\begin{matrix}{f(x+1,y)-f(x-1,y)} \\ {f(x,y+1)-f(x,y-1)}\end{matrix}\right)\\&=\left(\begin{matrix}{55-105} \\ {90-40}\end{matrix}\right) \\&=\left(\begin{matrix}{-50} \\ {50}\end{matrix}\right)\end{aligned}
梯度是矢量,存在幅值和方向。
梯度的幅值(magnitude)为:
g=\sqrt{f_x^2+f_y^2}=\sqrt{(-50)^2+(50)^2}=70.71
如果g大于某阈值,则认为该点(x,y)为边缘点。
梯度的方向(direction)为:
tanh^{-1}(\frac{f_x}{f_y})=(\frac{-50}{50})=-45^0
也可以使用二阶差分求梯度:
\frac{\partial^2 f(x,y)}{\partial x^2}=f(x+1,y)+f(x-1,y)-2f(x,y)
\frac{\partial^2 f(x,y)}{\partial y^2}=f(x,y+1)+f(x,y-1)-2f(x,y)
下面为一个有关边缘求导的示意图:

图片中的大部分边缘都不是突变的而是渐变的,对于斜坡区域,一阶导数将斜坡变成了平坦区域即变成了粗线,二阶导数将斜坡变成了两条中间存在平台区域的细线。

4.3.2边缘提取

在图像上除使用一阶差分来计算相邻像素之间的变化率外,我们还可以利用卷积和特定的算子来计算相邻像素的变化率。prewitt算子和sobel算子可以计算相邻三个点之间的变化率。它们用于一阶算子的边缘检测,利用像素点上下、左右相邻点的灰度差求取边缘。
求梯度有三种卷积核(robert,prewitt,sobel算子),每种卷积核有两个,对图像分别做两次卷积,一个代表水平梯度,一个代表垂直梯度。
1、Prewitt算子
Prewitt的两个算子
计算水平梯度,检测垂直边缘。
\left(\begin{matrix}-1&0&1 \\ -1&0&1 \\ -1&0&1\end{matrix}\right)
计算垂直梯度,检测水平边缘。
\left(\begin{matrix}-1&-1&11 \\ 0&0&0 \\ 1&1&1\end{matrix}\right)
2.sobel算子
Sobel算子是典型的基于一阶导数的边缘检测算子,由于该算子中引入了类似局部平均的运算,因此对噪声具有平滑作用,能很好的消除噪声的影响。Sobel算子在Prewitt算子的基础上进行了改进,增强了中间位置的权重。与Prewitt算子、Roberts算子相比效果更好。
计算水平梯度,检测垂直边缘。
\left(\begin{matrix}-1&0&1 \\ -2&0&2 \\ -1&0&1\end{matrix}\right)
计算垂直梯度,检测水平边缘。
\left(\begin{matrix}-1&-2&-1 \\ 0&0&0 \\ 1&2&1\end{matrix}\right)
Sobel更强调了和边缘相邻的像素点对边缘的影响。相比较Prewitt算子,Sobel算子能够较好的抑制噪声效果。
假设原图像矩阵为A
则有:
f_x=\left(\begin{matrix}-1&0&1 \\ -2&0&2 \\ -1&0&1\end{matrix}\right)*A
f_y=\left(\begin{matrix}-1&-2&-1 \\ 0&0&0 \\ 1&2&1\end{matrix}\right)*A

4.3.3 sobel算子实例

运行结果:

执行sobel算子

运行结果

4.3.4 sobel算子与卷积核

sobel算子与卷积神经网络中的卷积核功能类似。这是卷积核有一个不足:就是提取概要信息,随着层数的增加将不可避免丢失很多信息,为避免这个问题,人们提出残差网络等方法弥补其不足。
【延伸思考】算子不同方向的偏导与卷积核的不同通道的作用有何异同?

第3章 偏导数与矩阵

3.1.黑塞矩阵

费马定理给出了多元函数极值的必要条件,黑塞矩阵的正定性是极值的充分条件。此外,黑塞矩阵与多元函数的极值、凹凸性有密切的关系。
黑塞矩阵是由多元函数的二阶偏导数组成的矩阵,假设函数f(x_1,x_2,\cdots,x_n)二阶可导,黑塞矩阵由所有二阶偏导数构成,函数f(x_1,x_2,\cdots,x_n)的黑塞矩阵定义为:
\nabla(\nabla f(x))=\nabla^2f(x)=\left(\begin{matrix}{\frac{\partial^2 f}{\partial x_1^2}}&\cdots& {\frac{\partial^2 f}{\partial x_1{\partial x_n}}}\\ {\vdots}&\cdots&\vdots \\ \frac{\partial^2 f}{{\partial x_n}{\partial x_1}}&\cdots&{\frac{\partial^2 f}{\partial x_n^2}}\end{matrix}\right)
这是一个n阶矩阵,一般情况下,多元函数的混合二阶偏导数与次序无关,即:
\frac{\partial^2 f}{\partial x_i\partial x_j}=\frac{\partial^2 f}{\partial x_j\partial x_i}
因此,黑塞矩阵是一个对称矩阵。
费马引理给出了多元函数极值的必要条件,极值的充分条件由黑塞矩阵的正定性决定。
例1:求函数f(x,y,z)=2x^2-xy+y^2-3z^2的黑塞矩阵。
函数f的黑塞矩阵为:
\left(\begin{matrix}{\frac{\partial^2 f}{\partial x^2}}&{\frac{\partial^2 f}{\partial x{\partial y}}}& {\frac{\partial^2 f}{\partial x{\partial z}}}\\ {\frac{\partial^2 f}{\partial y{\partial x}}}&{\frac{\partial^2 f}{\partial y^2}}&{\frac{\partial^2 f}{\partial y{\partial z}}}\\ \frac{\partial^2 f}{{\partial z}{\partial x}}&{\frac{\partial^2 f}{\partial z{\partial y}}}&{\frac{\partial^2 f}{\partial z^2}}\end{matrix}\right)=\left(\begin{matrix}4&-1&0 \\ -1&2&0 \\ 0&0&-6\end{matrix}\right)
练习:
求函数f(x,y)=x^2 y-xy^2对应的黑塞矩阵。

3.2 凹凸性判别法则

一元函数的凹凸性定义可以推广到多元函数,即:对于函数f(x),在其定义域内的任意两点x和y,及任意实数0\leq\theta\leq 1,都有:
f(\theta x+(1-\theta)y)\leq\theta f(x)+(1-\theta)f(y)
则函数f(x)为凸函数,反之,为凹函数。
函数f(x,y)=x^2+y^2是凸函数,f(x,y)=-x^2-y^2为凹函数。它们对应图像如下:

一元函数的凹凸性可根据二阶导数判断,多元函数可根据对应的黑塞矩阵的判断:
即:假设多元函数f(x)二阶可导,如果对应的黑塞矩阵半正定,则函数f(x)是凸函数;
如果对应的黑塞矩阵负正定,则函数f(x)是凹函数。

3.3 极值判别法则

一元函数的极值点的必要条件是该点为驻点,充分条件通过二阶导数来判断。这些规则可以推广到多元函数。多元函数的极值点的必要条件是该点为驻点,充分条件通过对应黑塞矩阵
来判断。具体规则如下:
(1)黑塞矩阵正定,函数在该点有极小值;
(2)黑塞矩阵负定,函数在该点有极大值;
(3)黑塞矩阵不定,则该点不是极值点,或是鞍点。

3.4雅可比矩阵

雅可比矩阵是由多个多元函数的所有偏导数构成的矩阵。假设:
y_1=f_1 (x_1,x_2,\cdots,x_n ),y_2=f_2 (x_1,x_2,\cdots,x_n ),\cdots,y_m=f_m (x_1,x_2,\cdots,x_n )
由这些函数构成的雅可比矩阵为:
\frac{\partial y}{\partial x}=\frac{\partial (y_1,y_2,\cdots,y_m)}{\partial (x_1,x_2,\cdots,x_n)}=\left(\begin{matrix}{\frac{\partial^2 f_1}{\partial x_1^2}}&\cdots& {\frac{\partial^2 f_1}{\partial x_1{\partial x_n}}}\\ {\vdots}&\cdots&\vdots \\ \frac{\partial^2 f_m}{{\partial x_n}{\partial x_1}}&\cdots&{\frac{\partial^2 f_m}{\partial x_n^2}}\end{matrix}\right)
这是一个m\times n的矩阵,每一行为一个多元函数的梯度(或所有偏导数)。

例2:求下列函数的雅可比矩阵:
u=x^2+2xy+z
v=3x-xy^2+z^2
这些函数的雅可比矩阵为:
\frac{\partial (u,v)}{\partial (x,y,z)}=\left(\begin{matrix}{\frac{\partial u}{\partial x}}&{\frac{\partial u}{\partial y}}& {\frac{\partial u}{\partial z}}\\ {\frac{\partial v}{\partial x}}&{\frac{\partial v}{\partial y}}&{\frac{\partial v}{\partial z}}\end{matrix}\right)=\left(\begin{matrix}{2x+2y} & 2x & 1 \\ {3-x^2} & {-2xy} & 2z\end{matrix}\right)
神经网络中通常包括多个多元函数的情况,如下图所示:

X=\left(\begin{matrix}x_1\\x_2\\ x_3\end{matrix}\right),w=\left(\begin{matrix}w_{11}&w_{12}\\w_{21}&w_{22}\\ w_{31}&w_{32}\end{matrix}\right),y=\left(\begin{matrix}y_1 \\ y_2 \end{matrix}\right)
上图可用如下表达式表示:
Y=W^TX=y=\left(\begin{matrix}w_{11}x_1+w_{12}x_2+w_{13}x_3 \\ w_{21}x_1+w_{22}x_2+w_{23}x_3 \end{matrix}\right)
由此可得:
\frac{\partial Y}{\partial X}=\frac{\partial (y_1,y_2)}{\partial (x_1,x_2,x_3)}=W^T
【延伸思考】对W^T X加上激活函数(如sigmoid函数),此时\frac{\partial Y}{\partial X}=?

3.5 链式法则的矩阵形式

前面我们介绍了雅可比矩阵,它是涉及多元复合函数求导,这里雅可比矩阵可以简化链式法则的表达形式。
假设z=g(y_1,y_2,\cdots,y_m),y_i=f_i (x_1,x_2,\cdots,x_n)
根据链式法则,z对x的偏导可以通过z对y_i求导,x_j对x求导来实现。具体计算过程如下:
\frac{\partial z}{\partial x_i}=\sum_{j=1}^m\frac{\partial z}{\partial y_j} \frac{\partial y_j}{\partial x_i}
写成矩阵的形式就是:

其中\frac{\partial Y}{\partial X}矩阵就是雅可比矩阵。

3.6 对向量和矩阵求导

在神经网络中我们常见如下表达式:
y=Wx
其中W为mxn矩阵,x是n维向量,y是m维向量。假设f为一个激活函数,y通过激活函数后为f(y)函数,现在对f(y)求导,激活函数不改变y的维度,所以f(y)也是m维向量。
根据链式法则,有:

用矩阵和向量表示,上式可简写为:
\nabla_w f=(\nabla_y f)x^T

3.7 应用:最小二乘法

最小二乘法(二乘”就是平方,所以又称最小平方法)是一种数学优化技术。 它通过最小化误差的平方(即通常我们称之为损失函数)和寻找数据的最佳函数匹配。 利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小。为解决过拟合问题可以在损失函数后加上正则项。
对多元函数的最小二乘法,可以用矩阵或向量表示,如对线性回归的函数y=w^T x+b,其中w和b为参数。如果用向量或矩阵来表示,可先作如下处理:
W=[w,b],X=[x,1]
则wx+b可表示为:W^T X,目标函数可表示为:
L(w)=\frac{1}{2}\sum_{k=1}^N(W^T X_k -y_k)^2
其中N表示样本总数,y_i表示第i个样本对应的标签值(或实际值)。L(w)
是一个凸函数,可用最小二乘法求其最小值:
(1)对函数L(w)求一阶偏导
\frac{\partial L}{\partial x_i}=\frac{1}{2}\sum_{k=1}^N(W^T X_k -y_k)x_{ki} \tag{3.1}
其中x_{ki}表示第k个样本的第i个分量。
(2)求二阶偏导,得到黑塞矩阵
\frac{\partial^2 L}{\partial w_i\partial w_j}=\sum_{k=1}^N x_{ki}x_{kj}
由此可得,目标函数的黑塞矩阵为:
其中n表示向量W的维度(或长度)。
(3)证明黑塞矩阵的正定性
对任意非0向量x有:
x^T Hx=x^T X^T Xx=(Xx)^T Xx\geq 0
故目标函数的黑塞矩阵为正定矩阵,由此可知,目标函数为凸函数,故存在极小值。驻点就是极值点。
(4)求解参数w
目标函数对参数w求导,并令导数为0,解得极值点。
由式(3.1)可得:
\sum_{k=1}^N(W^T X_k -y_k)x_{ki}=0
W^T X_k展开为:\sum_j^n w_j x_{kj},从而有:
\sum_{k=1}^N(\sum_{j=1}^n w_j x_{kj} -y_k)x_{ki}=0
对上式进行整理可得:
\sum_{k=1}^N\sum_{j=1}^n w_j x_{kj}x_{ki}=\sum_{k=1}^n y_k x_{ki}
写成矩阵的形式可得:
X^T Xw=X^T y
如果W的系数矩阵X^T X可逆,则可解得方程组的解w为:
W=(X^T X)^T X^T y
如果w的维度和样本数较大,这种计算非常好资源,尤其当X^T X不可逆,该如何求呢?
对这些情况,我们可以采用梯度下降,通过不断迭代,最后收敛于极值点来实现。

第2章 多元函数微积分

2.1一阶偏导数

前面主要介绍了一元函数,在机器学习中,要处理的函数大多是多元函数(如函数y=f(x_1,x_2,\cdots,x_n))。因此,我们需要把导数、微分拓展到多元函数上。
对多元函数如何求导呢?最简单有效的方法就是把多元微分转换为一元微分,具体实现方法就是每次只改变一个变量,其他变量的值固定不变,由此得到偏导数。
偏导数是多元函数对每个自变量的求导,对于多元函数y=f(x_1,x_2,\cdots,x_n),它在(x_1,x_2,\cdots,x_n)点处对x_i的偏导数定义为下式的极限。
\frac{\partial y}{\partial x}=\underset{\Delta x_i \to 0}{lim}\frac{f(x_1,\cdots,x_i+\Delta x_i,\cdots,x_n)-f(x_1,\cdots,x_i,\cdots,x_n)}{\Delta x_i} \tag{2.1}
这与导数的定义相同,其中\partial为偏导数符合。为计算\frac{\partial y}{\partial x_i},我们可以简单把变量x_i外的变量x_1,\cdots,x_{i-1},x_{i+1}\cdots,x_n作为常量,并计算y关于x_i的导数。对于偏导数的表示,以下几个表示方式是等价的:
\frac{\partial y}{\partial x_i}=\frac{\partial f}{\partial x_i}=f_{x_i}=f_i=D_i f
偏导数的几何意义,如图2-1所示,这里以一个二元函数为例,假设z=f(x,y),
则偏导\frac{\partial}{\partial x}f(x,y_0) 在点(x_0,y_0)值就是曲线z=f(x,y_0)在点(x_0,y_0)的切线斜率。

图2-1 偏导数的几何意义
例1 求函数z=x^2+3xy+y-1,求\frac{\partial z}{\partial x}\frac{\partial z}{\partial y}在点(4,-5)的值。
解:求\frac{\partial z}{\partial x},把y看作常量,然后对x求导。
\frac{\partial z}{\partial x}=\frac{\partial}{\partial x} (x^2+3xy+y-1)=2x+3y
\frac{\partial z}{\partial x}在点(4,-5)的值为:2\times4+3\times(-5)=-7
同理可得,\frac{\partial z}{\partial y}在点(4,-5)的值为:13

2.2 高阶偏导数

对偏导数继续求偏导数可以得到高阶偏导数,比一元函数的高阶导数复杂,每次求导时可以对多个变量进行求导,因此有多种组合。对多元函数y=f(x_1,x_2,\cdots,x_n)的二阶导数,可以先对x_i求偏导数,得到\frac{\partial y}{\partial x_i},然后将此一阶偏导数对x_j继续求偏导数。
\frac{\partial^2 y}{\partial x_j\partial x_i}=\frac{\partial}{\partial x_j}(\frac{\partial y}{\partial x_i})
如果二阶混合偏导数连续,则与求导顺序无关,即有:
\frac{\partial^2 y}{\partial x_j\partial x_i}=\frac{\partial^2 y}{\partial x_i\partial x_j}
例2:求函数f(x,y)=x^2+xy-y^2
(1)一阶偏导
(2)二阶偏导
解:(1)一阶偏导有:
\frac{\partial f}{\partial x}=2x+y
\frac{\partial f}{\partial y}=x-2y
(2)二阶偏导有:
\frac{\partial^2 f}{\partial x^2}=\frac{\partial}{\partial x}(2x+y)=2
\frac{\partial^2 f}{\partial x\partial y}=\frac{\partial}{\partial y}(2x+y)=1
\frac{\partial^2 f}{\partial y\partial x}=\frac{\partial}{\partial x}(x-2y)=1
\frac{\partial^2 f}{\partial y^2}=\frac{\partial}{\partial y}(x-2y)=-2
如果二阶混合偏导数连续,则与求导次序无关,即有:
\frac{\partial^2 f}{\partial x\partial y}=\frac{\partial^2 f}{\partial y\partial x}

2.3多元复合函数的链式法则

多元复合函数求导的链式法则是一元函数链式法则的推广。首先,我们看二元函数的情况,注意需要对相关的全部中间变量(如下例中u和v)应用链式法则。假设z=f(u,v),u=g(x,y),v=h(x,y),则z对x,y的偏导导数为:
\frac{\partial z}{\partial x}=\frac{\partial z}{\partial u} \frac{\partial u}{\partial x} +\frac{\partial z}{\partial v} \frac{\partial v}{\partial x}
同理
\frac{\partial z}{\partial y}=\frac{\partial z}{\partial u} \frac{\partial u}{\partial y} +\frac{\partial z}{\partial v} \frac{\partial v}{\partial y}
\frac{\partial z}{\partial x}的求导过程如图2-2所示。

图2-2 多元复合函数的链式法则
练习:

1.11最小二乘法应用实例

最小二乘法(又称为为最小平方法,二乘就是平方的含义),是用来衡量两个模型(样本模型与实际模型)之间距离(准确来说是欧氏距离)的一种方法,其背后的原理求凸函数的最小值。其应用很广泛,在线性回归算法中起到核心作用。两个模型之间的距离可表示为:
\sum_{i=1}^N(y_{true}-y_{prev} )^2
最小二乘法有不少优势,如简单明了、易解释。但也存在很多不足,对模型要比较简单,稍微复杂一点(如模型中参数多几个)或条件宽泛一点,可能就无法处理。当然,对于这些问题,我们可以采用梯度下降法解决。梯度下降法将在后续章节介绍。
这里我们先看一个简单实例,假设一个裁缝师傅有一块长2米的布,他共量了5次,但每次都不一样,具体数据如下,根据这些样本数据,如何确定其最终的结果呢?这个问题我们可以利用最小二乘法来解决。
单位是米

问题1:这个问题的目标是什么?
问题2:求平均值是一种直观方法,但这种方法好像不足让人信服,有人说,是否可以用出现次数多的那个为准?
问题3:如何用用最小二乘法确定最终结果,如何设定这个实际模型?
问题4:这个问题很简单,还可以做哪些延伸?如果由一维变为多维该如何处理?
问题5:如是否可以把这个问题转换为一个概率模型?然后,把用欧氏方法来衡量两个模型之间的相似度,转变为利用交叉熵方法来衡量两个分布之间近似程度?

问题1:主要目的就是通过这些演变数据获取背后的真实数据
问题2: 最小二乘法的本质是用欧氏视角去衡量两个模型之间的近似度,通过优化方法使它们之间的相似度最大化(距离最小化)。为更好理解,把这些点用坐标表示出来。

这是样本数据,我们假设样本数据背后反应的实际数据为y=y ̂这样一条直线,把这条直线视为实际模型,然后利用最小二乘法求出y ̂的值。
L(\hat y)=min\sum_{i=1}^5(\hat y-y_i )^2 =min((\hat y-2.02)^2+(\hat y-1.97)^2+(\hat y-1.98)^2+(\hat y-2.02)^2+(\hat y-2.01)^2)
这个计算过程,实际就是求各点到直线y=y ̂的距离(或样本与实际值的误差)最小化,计算过程如下图所示:

显然函数L(\hat y)是一元二次函数,是凸函数,故其驻点就是最小值点。
L(\hat y)求导,并令其为0得:
L'(\hat y)=2(\hat y-2.02)+2(\hat y-1.97)+2(\hat y-1.98)+2(\hat y-2.02)+2(\hat y-2.01)
解之得:
\hat y=\frac{2.02+1.97+1.98+2.02+2.01}{5}=10
这个结果就是求各个样本点的平均值,即\hat y=10这个模型与样本模型最接近。
问题4:加下来我们介绍梯度时,将介绍如何多维数据的情况。
问题5:这个问题如果用概率统计的思想来处理,该如何处理呢?
概率统计中需要有一个随机变量,随机变量的分布,衡量不同分布之间的相似度等。
实际值与样本的误差可作为一个随机变量:\hat y-y_i
假设这个随机变量的概率为p(\hat y-y_i),该误差是一个随机及独立的变量,正常情况下,这个概率应该满足正态分布(因正态分布的熵最大),不妨假设满足标准正态分布\phi(0,1)
这里y作为一个普通变量(非随机变量),故可以使用最大似然估计也可求出y的值,也是
\hat y=\frac{2.02+1.97+1.98+2.02+2.01}{5}=10
真可谓异曲同工!
大家不妨试一下。

1.10泰勒公式

如果一个复杂函数在某点处存在各阶导数,在这点附近,就可以用一个多项式函数,近似地替代这个复杂函数。这种化繁为简的功能就是泰勒公式的本质和意义所在。
如何用多项式函数近似表示这个复杂函数呢?根据微分的定义,如果函数f(x)在点a处可得,可用一次函数近似代替函数f(x),误差是x-a的高阶无穷小。
f(x)=f(a)+f'(a)(x-a)+o(x-a)
由此,我们可以推广到更高次阶的情况。假设函数f(x)n阶可导,函数f(x)可表示为:
f(x)=f(a)+f'(a)(x-a)+\frac{f''(a)}{2!}(x-a)^2+\cdots+\frac{f^{(n)}(a)}{n!} (x-a)^n+o(x-a)^n \tag{5.5}
这就是泰勒多项式,其中o(x-a)^n称为皮亚诺余项。
如果令\Delta x=x-a,式(5.5)可写成:
f(x)=f(a)+f'(a)\Delta x+\frac{f''(a)}{2!}\Delta x^2+\cdots+\frac{f^{(n)}(a)}{n!} \Delta x^n+o(\Delta x)^n
函数在x=0点处的泰勒公式称为麦克劳林公式,具体形式为:
f(x)=f(0)+f'(0)x+\frac{f''(0)}{2!}x^2+\cdots+\frac{f^{(n)}(0)}{n!} x^n+o(x^n) \tag{5.6}
把余项o(x^n)记为R_n (x),式(5.6)可写为:
f(x)=f(0)+f'(0)x+\frac{f''(0)}{2!}x^2+\cdots+\frac{f^{(n)}(0)}{n!} x^n+R_n (x) \tag{5.7}
基本函数的麦克劳林公式:

用泰勒公式近似sinx函数,分别取k=3,5的情况

 
从上图可以看出,泰勒公式精度随着k增大而精度越高。
实现上图的python代码:

利用泰勒公式可以将非线性问题化为线性问题,且具有很高的精确度,因此其在微积分的各个方面都有重要的应用,如用于梯度下降法、牛顿法、拟牛顿法等的推导。

1.9 导数与函数极值

费马定理给出了极值的必要条件,如何给出充分条件?这节将介绍导数与极值的关系,从而给出函数极值的几个充分条件。当然,讲到极值就离不开最大和最小值,极值一般指函数的局部属性,而最大值与最小值反映了函数一种整体属性.本节主要讨论极值与最大值、最小值的判定和求法。
极值定义:设函数y=f(x)在点x_0\delta领域内有定义,如果对去心领域内任何一点x都有f(x_0 )\le f(x)(或f(x_0 )\ge f(x)),则称f(x_0)是函数f(x)的极小值,或为极大值。
函数的极大值与极小值统称为函数的极值,使函数取得极值的点称为极值点。
如何判断一点是否为函数的极值点?费马定理只给出了极值点的必要条件,极值点的充分条件如何呢?这里介绍一种使用导数来判断是否极值的方法。
1)利用一阶导数
设函数f(x)在点x_0连续,在点x_0的某去心领域可导。
x\in(x_0-\delta,x_0),f'(x)<0; x\in(x_0,x_0+\delta),f'(x)>0,则函数f(x)在点x_0处取得极小值;
x\in(x_0-\delta,x_0),f'(x)>0; x\in(x_0,x_0+\delta),f'(x)<0,则函数f(x)在点x_0处取得极大值;
x\in(x_0-\delta,x_0),or x\in(x_0,x_0+\delta),f'(x)符合保持不变,则函数f(x)在点x_0处没有极值。
2)利用二阶导数
设函数f(x)在点x_0处二阶可导,且x_0为驻点(即f'(x_0 )=0)
f''(x_0 )<0, 则函数f(x)在点x_0处取得极大值; 如f''(x_0 )>0, 则函数f(x)在点x_0处取得极小值;
f''(x_0 )=0, 则函数f(x)在点x_0不一定取得极值,需进一步分析。
驻点、拐点、极值点、鞍点的异同(这里的函数为一元函数)

例1:判断下列函数在x=0处的情况
y=10x^2,y=10x^3
解:
这两个函数的图像为:
从图可知:

第1章 一元函数微积分

一元函数是微积分的核心内容,微积分为研究函数性质提供了理论和方法,在机器学习中被广泛使用,尤其在寻找函数极值方面。

1.1 导数的定义

导数定义为函数f(x)的自变量变化趋于0时,函数值的变化量与自变量变化量比值的极限,函数y=f(x)在x点处的导数定义为:
f'(x)=\underset{\Delta x \to 0}{lim} \frac{f(x+\Delta x)-f(x)}{\Delta x} \tag{5.1}
如果式(5.1)的极限存在,则称函数f(x)在x点处可导。
例1 当f(x)=3x时,
f'(x)=\underset{\Delta x \to 0}{lim}\frac{3(x+\Delta x)-3x}{\Delta x}=\underset{\Delta x \to 0}{lim}\frac{3\Delta x}{\Delta x}=3
例2 f(x)=x^2时,
\begin{aligned}f'(x)&=\underset{\Delta x \to 0}{lim}\frac{(x+\Delta x)^2-x^2}{\Delta x}\\&=\underset{\Delta x \to 0}{lim}\frac{2x\Delta x+(\Delta x)^2}{\Delta x}\\&=\underset{\Delta x \to 0}{lim}(2x+\Delta x)\\&=2x \end{aligned}
已知函数f(x),求导函数f'(x) ,称为对函数f(x)求导。当式(5.1)的极限存在时,称函数可导。导函数的含义如图5-1所示。作出函数f(x)的图像, f'(x)表示图像切线的斜率。
图5-1 导数的含义,f'(x)表示切线PQ的斜率。

式(5.1)的极限也可写成如下形式:
f'(x_0)=\underset{\Delta x \to x_0}{lim}\frac{f(x)-f(x_0)}{x-x_0} \tag{5.2}
式(5.1)与式(5.2)是等价的。
函数y=f(x)在x点处的导数除用f^' (x)表示之外,以下表达式是等价的。
f'(x)=y'=\frac{dy}{dx}=\frac{df}{dx}=\frac{d}{dx}f(x)=Df(x)
其中\frac{d}{dx}和D是微分运算符,表示微分操作。常见函数的微分有:
Dc=0(c是一个常数)
Dx^a=ax^{a-1} (a是任意实数)
De^x=e^x
Dln(x)=\frac{1}{x}
Dsinx=conx
Dconx=-sinx
基本函数的求导公式:
幂函数:(x^a )'=ax^{a-1}
指数函数:
(e^x )'=e^x
(a^x )'=a^x lna
三角函数:
(sinx )'=cosx
(cosx )'=-sin x
(tanx )'=\frac{1}{{cos}^2 x}={sec}^2 x
(cotx )'=\frac{-1}{{sin}^2 x}={-csc}^2 x
对数函数:
(lnx )'=\frac{1}{x}
(log_ax )'=\frac{1}{lna\frac{1}{x} }

1.2 导数的四则运算

1)加法
(f(x)+g(x))'=f'(x)+g'(x)
2)减法
(f(x)-g(x))'=f'(x)-g'(x)
3)乘法
(cf(x))'=cf'(x)
(f(x)g(x))'=f'(x)g(x)+f(x)g'(x)
4)除法
(\frac{f(x)}{g(x)})'=\frac{f'(x)g(x)-f(x)g'(x)}{g^2(x)}
5)倒数
(\frac{1}{f(x)})'=-\frac{f'(x)}{f^2(x)}

1.3 复合函数的导数

假设z=f(y),y=g(x)
则复合函数z=f(g(x))的导数为:
z'=f'(g(x))g'(x)\tag{5.3}
或写成如下:
\frac{dz}{dx}=\frac{dz}{dy}\frac{dy}{dx}\tag{5.4}
这称为链式法则,这个公式可以推广到多元函数。
例 3: 求sin(x^2)的导数
该函数是sin(x)x^2的复合函数,其导数为
(sin(x^2))'=cos(x^2)(x^2)'=2xcos(x^2)
练习:
1.求函数f(x)=\frac{1}{2}x^2+3x+4的导数。
2.求函数f(x)=(x^2+x)sin(x)的导数。
3.求函数f(x)=\frac{1}{1+e^{-x}}的导数,该函数也称为sigmoid函数。

1.4 高阶导数

对导数继续求导可以得到高阶导数,如二阶导数是一阶导数的导数,表示为:
f''(x)\frac{d^2 y}{dx^2}
例如:求函数f(x)=x^3+e^{-x}的二阶导数
其一阶导数为:f'(x)=3x^2+e^{-x}\times(-1)=3x^2-e^{-x}
其二阶导数为: f''(x)=6x+e^{-x}

1.5 导数与极值点

函数导数与极值点有一定关系,费马定理说明了两者的关系,费马定理的具体内容为:
假设函数f(x)在点x_0点可导,如果在x_0点处取得极值,则必定有:
f'(x_0 )=0
费马定理给出了可导函数取极值的一阶必要条件,导数为0的点又称为函数的驻点。
【注意】导数为0是函数取极值的必要条件,而不是充分条件。即
f'(x_0)=0\nRightarrow x_0f(x)的极值点。
例如,f(x)=x^3,在x=0处的导数为0,但x=0不是函数f(x)的极值点,如下图所示:

函数f(x)=x^3的图形
不过我们通常通过求函数的驻点来寻找函数的候选极值点。在SVM算法中使用。
如果函数f(x)在点x_0处导数等于0,是否存在x_0为极值点的充分条件呢?当然有:
(1)通过判断点x_0,左右侧导数来确定是极大还是极小值;
(2)如果函数f(x)存在二阶导数,则可通过在点x_0二阶导数大于0还是小于0来判断;
(3)如果函数f(x)为凸(或凹)函数,则驻点就是极值点。

1.6 导数与中值定理

微分中值定理建立了导数与函数值之间的关系,是导数应用的基础,在微积分理论中占有重要地位,本节将介绍 3 个中值定理,先介绍罗尔定理,然后再由它推出拉格朗日中值定理、柯西中值定理。
1、中值定理概览

2、简单证明
(1)证明罗尔中值定理:
基本思路:根据费马定理,要证明函数f(x)在某点导数为0,如果能说明这点为极值即可。如果f(x)在[a,b]为常数,则在该区域内,导数处处为0;如果函数f(x)不为常数,因f(x)在[a,b]上连续,故其在[a,b]上必定存在极值点,因f(a)=f(b),所以,这个极值点,不在端点a或b上,即在(a,b)至少存在一点\zeta,为函数f(x)的极值点,根据费马定理可得,该点的导数必为0,即有:f'(\zeta)=0
(2)拉格朗日中值定理
罗尔中值定理中条件f(a)=f(b)比较严苛,拉格朗日中值定理去掉这个条件,不过通过构造一个辅助函数,在利用罗尔中值定理可证明拉格朗日中值定理。
该辅助函数为:g(x)=f(x)-\frac{f(b)-f(a)}{b-a}x
可以证明g(a)=g(b),然后利用罗尔中值定理即可证明。
(3)柯西中值定理
通过构造一个辅助函数,再利用罗尔中值定理便可证明,该辅助函数为:
F(x)=f(x)-f(a)-\frac{f(b)-f(a)}{b-a}(g(x)-g(b))
可以证明F(a)=F(b),然后再利用罗尔中值定理便可证明。
3、实例
例1:证明当x>0,ln(x+1)<x 证明: 设f(t)=ln(t+1),显然f(t) 在[0,x]上满足拉格朗日中值定理,故在(0,x)中至少存在一点\zeta使得下式成立: f'(\zeta)=\frac{f(x)-f(0)}{x} 代入f(t)=ln(t+1)得:\frac{1}{1+\zeta}=\frac{f(x)-f(0)}{x}=\frac{ln(x+1)}{x}\zeta>0,故有:\frac{ln(x+1)}{x}<1,从而ln(x+1)<x

1.7 导数与函数的单调性

函数导数与函数的单调性有密切关系,当然需要满足一定条件。
定理;假设函数f(x) 在[a,b]连续,在(a,b)上可导,则有:
(1)如果在(a.b)内f'(x)>0 时,那么函数f(x)在[a,b]内单调递增;
(2)如果在(a.b)内f'(x)<0 时,那么函数f(x)在[a,b]内单调递减。
证明:利用拉格朗日中值定理可以证明。
在[a,b]上,任取两点x_1,x_2 (x_1<x_2),由拉格朗日中值定理可得: 在(x_1,x_2)内,至少存在一点\zeta,使得下式成立: f'(\zeta)=\frac{f(x_2 )-f(x_1)}{x_2-x_1} 这里f'(\zeta)>0,x_1<x_2 从而可得:f(x_2 )>f(x_1),即函数f(x)在[a,b]单调递增
同理可证明在(a,b)内f'(x)<0时,函数f(x)在[a,b]内单调递减。 例1:证明当x>0时,lnx<x-1
证明:令f(x)=x-1-lnx
f'(x)=1-\frac{1}{x}=\frac{x-1}{x}
0<x\le 1时,f'(x)<0,函数单调递减,所以f(x)>f(1)=0
x>1时,f'(x)>0,函数单调递增,所以f(x)>f(1)=0
所以,当x>0时,f(x)>0,即:lnx<x-1

1.8 导数与函数的凹凸性

函数的单调性反映在图形上就是曲线的上升或下降,但上升或下降过程中还
要考虑曲线的弯曲方向,如下图所示:

两条弧线都是上升的,但ADB 是凸的曲线弧,而ACB 是凹的曲线弧,即两者凹凸性不同.下面来讨论曲线的凹凸性及其判定方法.曲线的凹凸性可以用连接曲线弧上任意两点的弦的点与弧线上弦的点具有相同横坐标的点的位置关系来描述,我们有如下定义:
【说明】这里的定义以机器学习中命名为准,国内高中的凹凸定义可能与之相反。

例1,判断曲线y=x^3的凹凸性
解:该曲线的图像为:

当x>0时,y''=6x>0,y为凸函数
当x<0时,y''=6x<0,y为凹函数
【注意】这里函数y=x**3的凹凸性在点(0,0)处发生改变,我们称这样的点为拐点。
拐点的定义:
设y=f(x)在区间I上连续,x_0是I内的点.如果曲线y=f(x)在经过点(x_0,f(x_0))时,曲线的凹凸性(或函数二阶导的符号)改变了,那么就称点(x_0,f(x_0))为这曲线的拐点(反曲点)。需要明确的是:拐点是曲线上的一点,它由横坐标和纵坐标构成,不要只把横坐标当成拐点。

1.9 导数与函数极值

1.10泰勒公式

1.11最小二乘法应用实例

5.7 GPU加速

深度学习涉及很多向量或多矩阵运算,如矩阵相乘、矩阵相加、矩阵-向量乘法等。深层模型的算法,如BP、自编码器、CNN等,都可以写成矩阵运算的形式,无须写成循环运算。然而,在单核CPU上执行时,矩阵运算会被展开成循环的形式,本质上还是串行执行。GPU(Graphic Process Unit,图形处理器)的众核体系结构包含几千个流处理器,可将矩阵运算并行化执行,大幅缩短计算时间。随着NVIDIA、AMD等公司不断推进其GPU的大规模并行架构,面向通用计算的GPU已成为加速可并行应用程序的重要手段。得益于GPU众核(many-core)体系结构,程序在GPU系统上的运行速度相较于单核CPU往往提升几十倍乃至上千倍。
目前,GPU已经发展到了较为成熟的阶段。利用GPU来训练深度神经网络,可以充分发挥其数以千计计算核心的能力,在使用海量训练数据的场景下,所耗费的时间大幅缩短,占用的服务器也更少。如果对适当的深度神经网络进行合理优化,一块GPU卡相当于数十甚至上百台CPU服务器的计算能力,因此GPU已经成为业界在深度学习模型训练方面的首选解决方案。
如何使用GPU?现在很多深度学习工具都支持GPU运算,使用时只要简单配置即可。PyTorch支持GPU,可以通过to(device)函数来将数据从内存中转移到GPU显存,如果有多个GPU还可以定位到哪个或哪些GPU。PyTorch一般把GPU作用于张量(Tensor)或模型(包括torch.nn下面的一些网络模型以及自己创建的模型)等数据结构上。

5.7.1 单GPU加速

使用GPU之前,需要确保GPU是可以使用,可通过torch.cuda.is_available()的返回值来进行判断。返回True则具有能够使用的GPU。 通过torch.cuda.device_count()可以获得能够使用的GPU数量。
如何查看平台GPU的配置信息?在命令行输入命令nvidia-smi即可 (适合于Linux或Windows环境)。图5-28是GPU配置信息样例,从中可以看出共有2个GPU。
图5-28 GPU配置信息
把数据从内存转移到GPU,一般针对张量(我们需要的数据)和模型。对张量(类型为FloatTensor或者是LongTensor等),一律直接使用方法.to(device)或.cuda()即可。

对于模型来说,也是同样的方式,使用.to(device)或.cuda来将网络放到GPU显存。

5.7.2 多GPU加速

这里我们介绍单主机多GPU的情况,单机多GPU主要采用的是DataParallel函数,而不是DistributedParallel,后者一般用于多主机多GPU,当然也可用于单机多GPU。
使用多卡训练的方式有很多,当然前提是我们的设备中存在两个及以上GPU。使用时直接用model传入torch.nn.DataParallel函数即可,如下代码:

这时,默认所有存在的显卡都会被使用。
如果你的电脑有很多显卡,但只想利用其中一部分,如只使用编号为0、1、3、4的四个GPU,那么可以采用以下方式:

或者

其中CUDA_VISIBLE_DEVICES 表示当前可以被PyTorch程序检测到的GPU。
下面为单机多GPU的实现代码。
1)背景说明。这里使用波士顿房价数据为例,共506个样本,13个特征。数据划分成训练集和测试集,然后用data.DataLoader转换为可批加载的方式。采用nn.DataParallel并发机制,环境有2个GPU。当然,数据量很小,按理不宜用nn.DataParallel,这里只是为了说明使用方法。
2)加载数据。

3)把数据转换为批处理加载方式。 批次大小为128,打乱数据。

4)定义网络。

5)把模型转换为多GPU并发处理格式。

运行结果如下:
Let's use 2 GPUs
DataParallel(
(module): Net1(
(layer1): Sequential(
(0): Linear(in_features=13, out_features=16, bias=True)
)
(layer2): Sequential(
(0): Linear(in_features=16, out_features=32, bias=True)
)
(layer3): Sequential(
(0): Linear(in_features=32, out_features=1, bias=True)
)
)
)
6)选择优化器及损失函数。

7)模型训练,并可视化损失值。

运行的部分结果如下:
In Model: input size torch.Size([64, 13]) output size torch.Size([64, 1])
In Model: input size torch.Size([64, 13]) output size torch.Size([64, 1])
Outside: input size torch.Size([128, 13]) output_size torch.Size([128, 1])
In Model: input size torch.Size([64, 13]) output size torch.Size([64, 1])
In Model: input size torch.Size([64, 13]) output size torch.Size([64, 1])
Outside: input size torch.Size([128, 13]) output_size torch.Size([128, 1])
从运行结果可以看出,一个批次数据(batch-size=128)拆分成两份,每份大小为64,分别放在不同的GPU上。此时用GPU监控也可发现,两个GPU都同时在使用,如图5-29所示。
图5-29 同时使用多个GPU的情况
8)通过web查看损失值的变化情况,如图5-30所示。
图5-30 并发运行训练损失值变化情况
图形中出现较大振幅是由于采用批次处理,而且数据没有做任何预处理,对数据进行规范化应该更平滑一些,大家可以尝试一下。
单机多GPU也可使用DistributedParallel,它多用于分布式训练,但也可以用在单机多GPU的训练,配置比使用nn.DataParallel稍微麻烦一点,但是训练速度和效果更好一点。具体配置为:

单机运行时使用下列方法启动:

5.7.3使用GPU的注意事项

使用GPU可以提升训练的速度,但如果使用不当,可能影响使用效率,具体使用时要注意以下几点:
• GPU的数量尽量为偶数,奇数的GPU有可能会出现异常中断的情况;
• GPU很快,但数据量较小时,效果可能没有单GPU好,甚至还不如CPU;
• 如果内存不够大,使用多GPU训练的时候可通过设置pin_memory为False,当然使用精度稍微低一点的数据类型有时也有效果。

5.8 小结

本章从机器学习的这个比深度学习更宽泛的概念出发,首先说明其基本任务、一般流程等,然后说明在机器学习中解决过拟合、欠拟合的一些常用技巧或方法。同时介绍了各种激活函数、损失函数、优化器等机器学习、深度学习的核心内容。最后说明在程序中如何设置GPU设备、如何用GPU加速训练模型等内容。这章是深度学习的基础,接下来我们将从视觉处理、自然语言处理、生成式网络等方面,深入介绍深度学习的基础又核心的内容。