神经网络基础

假设有以下一张图片,要判断其输出是否为猫,若是,则可以用$y = 1$表示,否则用$y = 0$表示。

二元分类

计算机保存一张图片通常使用3个独立矩阵,分别对应红、绿、蓝三个颜色通道。如果输入像素是64×64,则会有3个64×64的矩阵,即输入是一个3×64×64的高维度数据,而输出是$y=0 \ or\ 1$。

机器学习之单变量线性回归一样,可以用$(x,y)$表示一个训练样本,其中$x \in R^n$,而$y = {0,1}$,通常用${(x^{(1)},y^{(1)}),(x^{(2)},y^{(2)})……(x^{(m)},y^{(m)}) }$表示整个训练集,其中$m$表示训练样本的大小,以上,由$m$个训练样本可以组成输入矩阵$X$,且$X \in R^{n×m}$,$Y$是一个输出矩阵,且$Y \in R^{1×m}$。

逻辑回归

对于以上分类问题,给定输入$x$,我们想知道$y$的输出概率,$\hat{y}$的输出概率代表着该分类问题的结果,$\hat{y}$的值表示是猫的概率可以简单表示为$\hat{y} = p{y=1|x}$,且$0 \le \hat{y} \le 1$。

对于线性回归,有$y = w^Tx+b$,而对于逻辑回归,采用激活函数,即:$ y = \delta(w^Tx+b) $表示,令$z = w^Tx+b$,则:

$\delta(z) = \frac{1}{1+e^{-z}}$,其函数图像如下所示:

当$\delta(z) > 0.5$,即也就是$w^Tx+b > 0 $时,认为其输出$\hat{y} = 1$
而$\delta(z) < 0.5$,即也就是$w^Tx+b < 0 $时,其输出$\hat{y} = 0$.

逻辑回归损失函数

对于逻辑回归问题,给定训练样本:
${(x^{(1)},y^{(1)}),(x^{(2)},y^{(2)})……(x^{(m)},y^{(m)}) }$,我们希望得到$\hat{y} \approx y$。逻辑回归的损失函数$L(\hat{y},y)$可以由以下公式定义:

$L(\hat{y},y) = -ylog(\hat{y}) -(1-y)log(1-\hat{y})$

对于以上损失函数,有:
若$y = 1$,则$L(y,\hat{y}) = -ylog(\hat{y})$,而想让损失函数$L(y,\hat{y})$尽可能小,意味着$\hat{y}$要尽可能大,又因为$0 \le\hat{y} \le 1$,所以$\hat{y} = 1$是,损失函数最小。

若$y = 0$,则$L(y,\hat{y}) = -log(1-\hat{y})$,损失函数要取得最小值,意味着$\hat{y}$需取得最大值,则需满足$\hat{y} = 0$。

以上损失函数只适用于单个样本,对于$m$个样本的损失函数可以有如下定义:

$J(w,b) = \frac{1}{m}\sum_{i=1}^{m}L(y,\hat{y}) = \frac{1}{m}\sum_{i=1}^{m}-y^{(i)}log(\hat{y}^{(i)})-(1-y^{(i)})log(1-\hat{y}^{(i)})$

梯度下降法

对于以上损失函数,需要找到损失函数$J(w,b)$的最小值,最常用的算法就是梯度下降算法,即对于一个凸函数,总能通过梯度下降算法找到它的全局最优解,对于此损失函数的梯度下降算法,在机器学习之逻辑回归的算法介绍中已经做了较为详细的推导,在此不再过多叙述,梯度下降算法的简单实现步骤如下所示:
$repeat \ \ {$
$w: = w- \alpha \frac{\partial J(w,b)}{\partial w}$

$}$
重复以上过程,直到损失函数收敛,以求得参数$w$的值,其中,$\alpha$代表学习率。

计算图

计算图介绍:

假设有一函数表达式为:$J(a,b,c) = 3(a+bc)$,其计算过程可以简单分为三个步骤,如下所示:

  • $u = bc$
  • $v = a +u $
  • $J =3*v $
    对于以上三个步骤,用计算图可以有如下表示

计算图的导数:

如上图所示,利用计算图从左向右的流程,一步步可以算出$J$的值,那么,依靠从右向左的反向传播就可以算出$J$对每个变量的导数,如下图所示:

其反向传播过程如图中红色箭头所示,根据导数定义以及链式计算法则,有如下计算:

$\frac{\partial J}{\partial v} = 3$

$\frac{\partial J}{\partial u} =\frac{\partial J}{\partial v} \frac{\partial v}{\partial u} = 3×1 = 3$

$\frac{\partial J}{\partial a} =\frac{\partial J}{\partial v} \frac{\partial v}{\partial a} = 3×1 =3$

$\frac{\partial J}{\partial b} =\frac{\partial J}{\partial v} \frac{\partial v}{\partial u} \frac{\partial u}{\partial b} = 3×1×5 =15$

$\frac{\partial J}{\partial c} =\frac{\partial J}{\partial v} \frac{\partial v}{\partial u} \frac{\partial u}{\partial c} = 3×1×4 =12$

逻辑回归中的梯度下降算法

单个样本的逻辑回归梯度下降算法

关于逻辑回归的损失函数,有如下公式:
$z= w^Tx+b$
$\hat{y} = a = \delta(z)$
$L(a,y) = -ylog(a)-(1-y)log(1-a)$
假设有两个输入特征$x_1,x_2$和两个参数$w_1,w_2$,则用计算图(流程图)表示其计算过程如下所示:

依照其计算图中的反向传播过程和链式法则,其导数计算如下所示:

$\frac{\partial L(a,y)}{\partial a} = -\frac{y}{a}+\frac{1-y}{1-a}$

$\frac{\partial L(a,y)}{\partial z} = \frac{\partial L}{\partial a} \frac{\partial a}{\partial z} = a-y$

$\frac{\partial L(a,y)}{\partial w_1} =\frac{\partial L}{\partial a} \frac{\partial a}{\partial z} \frac{\partial z}{\partial w_1} =x_1dz = x_1*(a-y)$

$\frac{\partial L(a,y)}{\partial w_2} =\frac{\partial L}{\partial a} \frac{\partial a}{\partial z} \frac{\partial z}{\partial w_2} = x_2dz = x_2*(a-y)$

$\frac{\partial L(a,y)}{\partial b} =\frac{\partial L}{\partial a} \frac{\partial a}{\partial z} \frac{\partial z}{\partial b} = dz = (a-y)$
···

最后,参数$w_1,w_2,b$的更新规律为:
$w_1 := w_1 - \alpha dw_1$
$w_2 := w_2 - \alpha dw_2$
$b := b - \alpha db$
其中,$\alpha$表示学习率。

$m$个样本的逻辑回归

$m$个样本的损失函数,如下所示:

$J(w,b) = \frac{1}{m}\sum_{i=1}^{m}L(a^{(i)},y^{(i)}) $

$a^{(i)} = \hat{y}^{(i)} = \delta(z^{(i)}) = \delta(w^Tx^{(i)} +b)$

其梯度计算公式,可以有如下表示:
$\frac{\partial J(w,b)}{\partial w} = \frac{1}
{m}\sum_{i=1}^{m}\frac{\partial }{\partial w}L(a^{(i)},y^{(i)}) $

在实际计算过程中,需要计算每一个样本的关于$w$的梯度,最后求和取平均,在一个具体算法实现中,其为代码可以如下所示:

假设有2个特征向量,$m$个样本,则有:
初始化:$J = 0, dw_1 = 0,dw_2 = 0$
$for i =1 to \ \ m:$

$ \ \ \ \ \ \ z^{(i)} = w^Tx^{(i)} +b;$

$ \ \ \ \ \ \ a^{(i)} =\delta(z^{(i)});$

$ \ \ \ \ \ \ J+ = -y^{(i)}log(a^{(i)})-(1-y^{(i)})log(1-a^{(i)});$

$ \ \ \ \ \ \ dz^{(i)} =a^{(i)} - y^{(i)};$

$ \ \ \ \ \ \ dw_1 +=x_1*dz^{(i)};$

$ \ \ \ \ \ \ dw_2 +=x_2*dz^{(i)};$

$ \ \ \ \ \ \ db \ +=dz^{(i)};$

$J/=m,dw_1/=m,dw_2/=m,db/=m;$

以上,是应用一次梯度下降的过程,应用多次梯度下降算法之后,其参数的更新如下所示:
$w_1 := w_1 - \alpha dw_1$
$w_2 := w_2 - \alpha dw_2$
$b := b - \alpha db$

注意:以上,算法实现过程中,有两个特征和参数,分别是$x_1,x_2$和$w_1,w_2$,当有$n$个特征和参数时,可以利用循环完成。

向量化

向量化的简单示例:

如以上算法表示,通过for循环来遍历$m$个样本和$n$个特征,当在整个算法运行过程中,需要考虑运行时间的问题,当样本数量和特征足够大时,采用传统的for循环不是一个明智的选择,为了减少算法运行时间,特地引入了向量化的实现。
将一以下代码作为示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import numpy as np
import random
import time
a = np.random.rand(1000000)
b = np.random.rand(1000000)
ts = time.time()
c = np.dot(a,b)
te = time.time()
print(c)
print("向量化的代码实现花费时间:"+str((te-ts)*1000)+" ms")

c = 0
ts = time.time()
for i in range(1000000):
c += a[i]*b[i]
te = time.time()
print(c)

print("for循环代码实现花费时间:"+str((te-ts)*1000)+" ms")

如上所示,同样实现两个数组(向量)相乘的过程,对于百万级别的数据,for循环的实现方式所花费的时间差不多是向量化的400倍左右,向量化的实现可以简单的理解为是一个并行的过程,而for循环可以简单理解为串行的过程,所以通过向量化的实现,大大节省了运行程序所耗费的时间。在算法实现过程中,应该尽量避免使用for循环。

用向量化实现逻辑回归:

对于逻辑回归的算法,需要考虑输入向量$X$和权重参数$W$,其中,$X \in R^{n×m}$,$W \in R^{n×1}$,而根据矩阵乘法运算法则和逻辑回归的实现原理,有:
$[z_1,z_2,……z_m] = [W^TX]+[b_1,b_2,……b_m]$

python中用numpy库,可以简单的用以下一行代码实现(一般认为$b$是一个R^{1×1}的偏置常量):

1
z = np.dot(W.T,x)+b

根据之前的学习,对于逻辑回归利用反向传播算法计算导数,有:

$ \ \ \ \ \ \ dz^{(i)} =a^{(i)} - y^{(i)};$
$ \ \ \ \ \ \ dw_1 +=x_1dz^{(i)};$
$ \ \ \ \ \ \ dw_2 +=x_2
dz^{(i)};$
$\ \ \ \ \ \ \ …$
$ \ \ \ \ \ \ dw_n +=x_n*dz^{(i)};$
$ \ \ \ \ \ \ db \ +=dz^{(i)};$
$J/=m,dw_1/=m,dw_2/=m,db/=m;$

对于以上,公式,有如下定义:
$dZ = [dz^{(1)},dz^{(2)}……dz^{(m)}]$
$A = [a^{(1)},a^{(2)},……a^{(m)}]$
$Y = [y^{(1)},y^{(2)}……y^{(m)}]$
$dZ = [A - Y]$
对于以上过程,摈弃传统的for循环实现,采用向量化的实现方式可以简单表示为:

1
2
dw = np.dot(X,dZ^T)
db = 1/m*np.sum(dZ)

综合以上所有向量化的实现,可以得到利用python实现的一个高度向量化的逻辑回归梯度下降算法(a代表学习率):

1
2
3
4
5
6
7
Z = np.dot(W^T,X)+b
A = np.exp(Z)
dZ = A-Y
dw = np.dot(X,dZ^T)
db = 1/m*np.sum(dZ)
w = w-a*dw
b = b-a*db

以上,只是实现一次梯度下降的伪代码,在实际算法运行过程中,我们仍然需要利用循环实现多次梯度下降。

-------------本文结束感谢您的阅读-------------