深度学习概论
本文根据《吴恩达深度学习课程》编写
神经网络基础
神经网络浅讲:从神经元到深度学习
[Deep Learning] 神经网络基础
一个简单的神经网络
- Housing Price Prediction
在这里神经网络的作用就是通过左侧输出的这四个属性 x 1 x_1 x1、 x 2 x_2 x2、 x 3 x_3 x3、 x 4 x_4 x4(输入层),来预测最终的价格y(输出层),中间的这些圆圈被称之为“隐藏单元”(隐藏层),每个输入都同时来自四个特征 。
神经网络就是只要你给他足够的数据x,y(训练样本),它非常擅长于计算从x到y的精准映射函数。
监督学习Supervised Learning
- 标准神经网络(Standard neural network)
适用实例:
(1)Real Estate
(2)Online Advertising
- 卷积神经网络(CNN Convolution neural network)
适用实例:
Photo tagging
- 循环神经网络(RNN Recurrent neural network)
处理一维序列数据,输入\输出是一个序列。
适用实例:
(1)Speech recognition
(2)Machine translation
- 混合神经网络结构(Hybrid neural network architecture)
适用实例:
Autonomous driving
- Neural Network examples
- Structured Data
结构化数据也称作行数据,是由二维表结构来逻辑表达和实现的数据,严格地遵循数据格式与长度规范,主要通过关系型数据库进行存储和管理。
简单来说就是数据库,即每个特征都有着清晰的定义,例如表格。
- Unstructured Data
非结构化数据例如音频、原始音频、图像等,这里的特征可能是图像中的像素值或是文本中的单个单词,深度学习让计算机能够更好的理解非结构化数据。
规模推动深度学习的进步
Scale drives deep learning progress
这里的“规模”不仅指的是神经网络的规模,一个有许多隐藏单元的神经网络,有许多的参数,许多的连接;而且还有数据的“规模”,事实上要在神经网络上获得更好的表现,往往就是训练一个更大的神经网络,投入更多的数据。
在训练数据量不大的情况下,各种算法的性能相对排名并不是很确定,效果会取决于你手工设计的组件以及算法处理方面的一些细节。只有在大数据领域,非常庞大的训练集才能见到神经网络稳定地领先其他算法。
神经网络的一个巨大突破就是从sigmoid函数转换到ReLu函数
使用sigmoid函数时,机器学习问题是最左和最右延伸区域的斜率,梯度会接近0,所以学习会变得非常缓慢,因为使用梯度下降法时,梯度接近0时,参数会变化的很慢,学习也会变得很慢。
而通过改变激活函数,神经网路用修正线性单元ReLU,它的梯度对于所有为正值的输入,输出都是1,因此梯度不会逐渐趋向0,而ReLU在0左侧的梯度是0。
因此将sigmoid函数转换成ReLU函数,便能够使“梯度下降法”运行得更快。
训练神经网络的过程中你需要不断尝试,找出最快的最适合你的应用的神经网络。
课后作业
【测验】
神经网络编程基础
二分类Binary Classification
举例说明
判断一张图片的内容是否有猫
计算机保存一张图片,要保存三个独立矩阵,分别对应图片中的red,green,blue三个颜色通道
[为例方便表示,这里使用三个5×4的矩阵代指64×64的矩阵]
如果图片的像素是64×64的,那么就有三个64×64的矩阵分别对应图片中的红、绿、蓝三种像素的亮度,把这些像素亮度值都提出来,放进一个特征向量x。
下面定义一个特征向量x来表示这张图片,将所有的像素值都取出来,例如255、231这些值组成一个特征向量。
这个很长的特征向量把图中所有的红、绿、蓝像素强度值都列出来,如果图是64×64的,那么向量x的总维度为 n x = 64 × 64 × 3 = 12288 = n n_x=64×64×3=12288=n nx=64×64×3=12288=n
在二分类问题中,目标是训练出一个分类器,它以图片的特征向量x作为输入,预测输出的结果标签有的值是1或0, 即预测图片中是否有猫。
符号Notation
-
用一对(x,y)来表示一个单独的样本 x ∈ R n x x\in {R^{ {n_x}}} x∈Rnx, y ∈ { 0 , 1 } y\in\{0,1\} y∈{ 0,1}
-
训练集由m个训练样本构成
m training example:{(x(1), y(1)), (x(2), y(2)), …, (x(m), y(m))}
m是训练样本的个数,有时为了强调可以写作 m = m t r a i n m={m_{train}} m=mtrain,而测试集的样本数写为 m t e s t m_{test} mtest
-
用X表示训练集 X ∈ R n x × m X\in{R^{ {n_x} \times m}} X∈Rnx×m
有的时候矩阵X定义训练样本作为行向量堆叠,而不是这样列向量堆叠。
但是构建神经网络时,用上边这个约定形式会让构建过程简单的多。
>>>X.shape
>>>(n_x,m)
- 标签Y输出 Y ∈ R 1 × m Y \in {R^{1 \times m}} Y∈R1×m
>>>Y.shape
>>>(1,m)
逻辑回归Logistic Regression
Given x, want ŷ=P(y=1|x) 0 ≤ y ^ ≤ 1 0\le ŷ\le1 0≤y^≤1
x是一个样本,当x的特征满足要求时,y取值为1
x ∈ R n x x\in {R^{ {n_x}}} x∈Rnx
Logistic回归的参数parameters: w ∈ R n x w\in {R^{ {n_x}}} w∈Rnx, b ∈ R b\in {R} b∈R
Output ŷ = σ(wT+b)
(若ŷ = wT+b,很适合做线性回归(要求因变量必须是连续性数据变量),但是并不适合二分类,因为ŷ是一个概率应该介于0和1之间,但是这样得到的ŷ很可能比1大得多,或者甚至是负值,这样的概率是没有意义的,所以使用ŷ = σ(wT+b))
变成一个sigmoid函数
σ ( z ) = 1 1 + e − z \sigma (z) = \frac{1}{ {1 + {e^{ - z}}}} σ(z)=1+e−z1
如果z非常大那么e-z就接近0,此时σ(z)就接近于1;
相反如果z非常小σ(z)就接近于0。
所以当实现logistic回归时,要做的就是学习参数w和b,来使ŷ成为比较好的估计。
- 符号约定
当对神经网络编程时,通常会将参数w和b分开,这里b相当于一个个拦截器,但是也有不同的表示,例如:
x 0 = 1 x_0=1 x0=1, x ∈ R n x + 1 x\in{R{^{ {n_x}+1}}} x∈Rnx+1
ŷ = σ(θTx)
θ 0 θ_0 θ0扮演的时b的角色,是一个实数,而 θ 1 θ_1 θ1到 θ n x θ_{n_x} θnx的作用和w是一样的。
实际操作实现神经网络时,还是将b和w看做是独立的参数更好。
逻辑回归的成本函数Logistic Regression cost function
使用上标(i)来指明数据x, y, z 和第i个训练样本有关。
- 损失(误差)函数Loss(error) function:
可以用来衡量算法的运行情况
可以定义损失为L(ŷ, y) = 1/2(ŷ - y)2(误差平方),但是在logistic回归中不这么做,因为当学习这些参数时,会发现之后讨论的优化问题会变成非凸的(non-convex),导致最后会得到很多个局部最优解,所以梯度下降法可能找不到全局最优值。
所以在logistic函数中定义一个其他的损失函数来得到一个方便优化的凸的优化问题:
L(ŷ, y) = -(ylogŷ + (1-y)log(1-ŷ))
对于上边的误差平方函数如果想要误差最小那么就要让误差平方越小越好。
再看对于logistic回归的损失函数,也同样的希望它尽可能的小。
(1)If y = 1: L(ŷ, y) = -logŷ
此时如果想让-logŷ尽可能小,就意味着要让logŷ足够大,即ŷ足够大,又由sigmoid函数得出,ŷ永远不会比1大,也就是说如果y = 1时,要使ŷ足够大,但又由于它永远不会大于1,所以让ŷ无限接近1。
(2)If y = 0: L(ŷ, y) = -log(1-ŷ)
如果想要log(1-ŷ)尽可能小,那么就需要log(1-ŷ)够大,即让ŷ尽可能地小,无限接近于0。
损失函数是在单个训练样本中定义的,它衡量了在单个训练样本上的表现。
- 成本函数Cost function
它衡量的是在全体训练样本上的表现,是一个平均值
J ( w , b ) = 1 m ∑ i = 1 m L ( y ^ ( i ) , y ( i ) ) J(w,b) = \frac{1}{m}\sum\limits_{i = 1}^m {L({ {\hat y}^{(i)}},{y^{(i)}})} J(w,b)=m1i=1∑mL(y^(i),y(i)) = − 1 m ∑ i = 1 m [ y ( i ) log y ^ ( i ) + ( 1 − y ( i ) ) log ( 1 − y ^ ( i ) ) ] = - \frac{1}{m}\sum\limits_{i = 1}^m {[{y^{(i)}}\log { {\hat y}^{(i)}} + (1 - {y^{(i)}})\log (1 - { {\hat y}^{(i)}})]} =−m1i=1∑m[y(i)logy^(i)+(1−y(i))log(1−y^(i))]
即所有训练样本的损失函数的和
其中 y ^ {\hat y} y^是用一组特定的参数w和b通过logistic回归算法得出的预测输出值。
成本函数是基于参数的总成本。
在训练logistic回归模型时,需要找到合适的参数w和b,;来使成本函数J尽可能地小。
【损失函数和成本函数式子的详细解释在本文最后“逻辑回归的损失函数的说明”】
梯度下降Gradient Descent
在之前提到的logistic回归和成本函数J,需要找到满足成本函数去最小值的参数w和b,下面来看一下梯度下降法。
- 图中的横轴表示空间参数w和b,在实际应用中,w可以是更高维的,但是为了方便绘图,这里让w是一个实数,b也是一个实数,成本函数J(w,b)在构成的曲面上,曲面在不同点的高度即J(w,b)在某一点的值,需要做的就是找到一个w和b使得J最小。
J(w,b)是一个凸函数(只有一个局部最优)。凸函数这个性质也是我们使用logistic回归这个特定成本函数J的重要性原因之一。
- 要找到最合适的w和b,就要先用某初始值初始化w和b,对于logistic回归而言,几乎是任意的初始方法都有效,通常用0来初始化,随机数也可以,但是通常不这么做。
- 梯度下降法所做的就是从初始点开始,朝最陡的下坡方向走一步,在梯度下降一步后,继续沿着陡的方向迭代下去,直到收敛到这个全局最优解或者接近全局最优解。
- 在算法收敛前
Repeat {
w : = w − α d J ( w ) d w w: = w - \alpha \frac{ {dJ(w)}}{ {dw}} w:=w−αdwdJ(w)
}
α表示学习率,学习率可以控制每一次迭代或者梯度下降法的步长。
后面的导数表示参数w的更新或变化量,当开始编写代码时,会使用代码中变量名的约定,用dw表示导数的变量名,即表示为:
w:=w-αdw
J(w,b):
w : = w − α d J ( w , b ) d w w: = w - \alpha \frac{ {dJ(w,b)}}{ {dw}} w:=w−αdwdJ(w,b)(代码表示:dw) ; b : = b − α d J ( w , b ) d b b: = b - \alpha \frac{ {dJ(w,b)}}{ {db}} b:=b−αdbdJ(w,b)(代码表示:db)
一个神经网络的计算都是按照前向路径或前向传播步骤来实现的,首先计算出神经网络的输出,紧接着进行一个反向传输操作,后者用来计算出对应的梯度或导数。
计算图
- 计算 J(a,b,c) = 3(a+bc)
表示 u = bc;v = a+u;J = 3v
流程图就是
流程图是从左到右的计算
计算导数是从右向左
逻辑回归的梯度下降法Logistic Regression Gradient descent
- logistic回归公式
这里只考虑单个样本的情况,关于该样本的损失函数L,a是logistic回归的输出,y是样本的基本真值标签值。
- 单个样本实例的一次梯度更新
假设样本只有两个特征x1、x2,为了计算z,还需要输入参数w1、w2和b
在logistic回归中,我们需要做的是变换参数w和b的值来最小化损失函数。
计算损失函数的导数【引号“”内为编程表示】
(1)“da”:
“da” = d L ( a , y ) d a \frac{ {dL(a,y)}}{ {da}} dadL(a,y) = − y a + 1 − y 1 − a - \frac{y}{a} + \frac{ {1 - y}}{ {1 - a}} −ay+1−a1−y
(由Logistic公式求出)
(2)“dz”:
“dz” = d L d z \frac{ {dL}}{ {dz}} dzdL = d L ( a , y ) d z \frac{ {dL(a,y)}}{ {dz}} dzdL(a,y) = a − y a-y a−y
(由 d L d z \frac{ {dL}}{ {dz}} dzdL = d L d a \frac{ {dL}}{ {da}} dadL· d a d z \frac{ {da}}{ {dz}} dzda, d a d z \frac{ {da}}{ {dz}} dzda = a(1-a))
(3)“ d w 1 dw_1 dw1”、“ d w 2 dw_2 dw2”、“db”:
“ d w 1 dw_1 dw1” = d L d w 1 \frac{ {dL}}{ {dw_1}} dw1dL = x 1 x_1 x1·dz
“ d w 2 dw_2 dw2” = x 2 x_2 x2·dz
“db” = dz
梯度下降在m个样本上的应用
- 成本函数
J ( w , b ) = 1 m ∑ i = 1 m L ( a ( i ) , y ( i ) ) J(w,b) = \frac{1}{m}\sum\limits_{i = 1}^m {L({ {a}^{(i)}},{y^{(i)}})} J(w,b)=m1i=1∑mL(a(i),y(i))
训练样本的预测值 a(i) = y ^ \hat y y^(i) = σ(z(i)) = σ(wTx(i)+b)
- 全局成员函数对 w 1 w_1 w1求导(各项损失函数的对 w 1 w_1 w1求导的平均)
∂ ∂ w 1 J ( w , b ) = 1 m ∑ i = 1 m ∂ ∂ w 1 L ( a ( i ) , y ( i ) ) \frac{\partial }{ {\partial {w_1}}}J(w,b) = \frac{1}{m}\sum\limits_{i = 1}^m {\frac{\partial }{ {\partial {w_1}}}L({a^{(i)}},{y^{(i)}})} ∂w1∂J(w,b)=m1i=1∑m∂w1∂L(a(i),y(i))
得到全局梯度值
J = 0; dw_1 = 0; dw_2 = 0; db = 0
# For循环遍历训练集从1到m,计算相应的每个训练样本的导数,并相加。
For i = 1 to m
z^(i) = w^T*x^(i) + b
a^(i) = σ(z^(i))
J += -[y^(i)*loga^(i) + (1-y^(i))log(1-a^(i))]
dz^(i) = a^(i) - y^(i)
dw_1 += x_1^(i)*dz^(i) #累加器,为了求和,加i上标的是单个第i个样本的导
dw_2 += x_2^(i)*dz^(i)
db += dz^(i)
J /= m
dw_1 /= m; dw_2 /= m; db /= m
# 到这里已经计算除了损失函数J对各个参数的导数
完成这些计算后,应用一步梯度下降使得w_1获得更新,即w_1减去学习率乘上dw_1,w_2和b同理
但是计算中有两个缺点,当此方法应用到logistic回归,需要编写两个for循环,第一个for循环是遍历m个训练样本的小循环;第二个for循环是遍历所有特征的for循环,在这个例子中只有两个特征,所以n_x=2,但是如果有很多特征就需要编写很多的dw_1、dw_2、…dw_n;当应用深度学习算法时,会发现在代码中显式地使用for循环会使算法低效,同时在深度学习领域,会有越来越大的数据集,不使用显式for循环会对你处理更大的数据集有帮助。向量化技术可以帮助拜托这些显式的for循环。
向量化Vectorization
- 什么是向量化
在Logistic回归中需要计算 z = wT + b
其中w和b都是列向量(如果特征很多,那么他们就是很多维的向量)
w,b ∈ Rn_x
计算wT
z = 0
for i in rang(n-x):
z += w[i]*x[i]
z += b
z = np.dot(w, x) + b
GPU和CPU都有并行化的指令(SIMD指令),表示单指令流多数据流,意思就是如果使用了这样的内置函数,例如np.function或其他能去掉显式for循环的函数,这样numpy可以充分利用并行化去更快的进行计算,这点对GPU和CPU上面的计算都是成立的,只是GPU更擅长进行SIMD计算,不过CPU也并不差。
向量化实例
经验法则:
当建立新的神经网络时,或者只是做一个回归,那么一定要尽量避免for循环,使用一个内置函数或者找出其他办法去计算循环,通常会比直接用for循环更快
- 实例一
计算矩阵A和向量的乘积
(1)非向量化
u = A v u i = ∑ i ∑ j A i j v j u = n p . z e r o s ( ( n , 1 ) ) \begin{array}{l} u = Av\\ {u_i} = \sum\limits_i {\sum\limits_j { {A_{ij}}{v_j}} } \\ u = np.zeros((n,1)) \end{array} u=Avui=i∑j∑Aijvju=np.zeros((n,1))
f o r for for i . . . i... i...
f o r for for i . . . i... i...
u [ i ] + = A [ i ] [ j ] ∗ v [ j ] u[i]+=A[i][j]*v[j] u[i]+=A[i][j]∗v[j]
(2)向量化
u = n p . d o t ( A , v ) u=np.dot(A,v) u=np.dot(A,v)
- 实例二
对向量v中所有元素做指数运算
v = [ v 1 ⋮ v n ] v=\left[ \begin{matrix} v_1 \\ \vdots \\ v_n \end{matrix} \right] v=⎣⎢⎡v1⋮vn⎦⎥⎤
即,使
u = [ e v 1 ⋮ e v n ] u=\left[ \begin{matrix} e^{v_1} \\ \vdots \\ e^{v_n} \end{matrix} \right] u=⎣⎢⎡ev1⋮evn⎦⎥⎤
(1)非向量化
u = np.zeros((n,1))
for i in range(n)
u[i] = math.exp(v[i])
(2)向量化
import numpy as np
u = np.exp(v)
numpy中其他常用向量值函数:
np.log(v)
np.Abs(v)
np.maximum(v)
向量化逻辑回归Vectorizing Logistic Regression
Logistic回归梯度下降的优化
z(i) = wTx(i) + b
a(i) = σ(z(i))
a 是 z 的激活函数
X = [ x ( 1 ) x ( 2 ) . . . x ( m ) ] X=\left[ \begin{matrix} x^{(1)} & x^{(2)} & ... & x^{(m)} \end{matrix} \right] X=[x(1)x(2)...x(m)]
X.shape = ( n x n_x nx, m),有m个样本,每个样本包含n_x个特征
Z = [ z ( 1 ) z ( 2 ) . . . z ( m ) ] = w T X + [ b b . . . b ] = [ w T x ( 1 ) + b w T x ( 2 ) + b . . . w T x ( n ) + b ] Z=\left[ \begin{matrix} z^{(1)} & z^{(2)} & ... & z^{(m)} \end{matrix} \right]=w^TX+\left[ \begin{matrix} b & b & ... & b \end{matrix} \right]=\left[ \begin{matrix} w^Tx^{(1)}+b & w^Tx^{(2)}+b & ... & w^Tx^{(n)}+b \end{matrix} \right] Z=[z(1)z(2)...z(m)]=wTX+[bb...b]=[wTx(1)+bwTx(2)+b...wTx(n)+b]
向量化表示(只需一行代码即可)
Z = np.dot(w.T, X) + b
b本身是一个实数,但是当把前面这个向量和这个数相加时,python会自动把实数b扩展成为1×m的行向量(在python中称为broadcasting)
向量化逻辑回归的梯度计算
之前的一次梯度下降
改进,去掉显式for循环
import numpy as np
import scipy.special
J = 0, dw = np.zeros((n,1)), db = 0
Z = np.dot(w.T, X) + b
A = expit(Z)
J += -(y[i]*log(A[i]) + (1-y[i])*log(1-A[i]))
dZ = A - Y
dw = (1/m) * np.dot(X, dZ.T)
db = (1/m) * np.sum(dZ)
J = J/m
这样完成了一次梯度下降,然后梯度下降更新参数
w : = w − α ∗ d w w:= w - α*dw w:=w−α∗dw
b : = b − α ∗ d b b:= b - α*db b:=b−α∗db
其中α是学习率
虽然说尽量不要使用for的显式循环,但是当需要进行多次迭代梯度下降时,那么还是要使用for循环。
Python的广播机制Broadcasting in Python
解决实例问题
设上面这个矩阵为A,求出对应食物的总热量(每列求和)和各属性的占比。
import numpy as np
A = np.array([[56.0, 0.0, 4.4, 68.0],
[1.2, 104.0, 52.0, 8.0],
[1.8, 135.0, 99.0, 0.9]])
print(A)
cal = A.sum(axis = 0)
print(cal)
percentage = 100*A/cal.reshape(1, 4)
print(percentage)
axis=0 意味着让Python在竖直方向求和
而水平轴是 axis=1,即求水平和
A是一个3×4矩阵,让它除以一个1×4的矩阵,虽然在技术上,在求列和这行代码执行后,变量cal已经是一个1×4矩阵了,所以并不需要调用reshape,但是当编写Python程序时,如果不完全确定矩阵的尺寸,调用reshape命令来确保它是正确的尺寸,并且reshape是o(1)操作,成本很低。
这里需要解释是如何进行矩阵A除以cal矩阵的,这里用到了Python的广播机制
- Python的广播机制
垂直复制
单列向量复制
[ 1 2 3 4 ] + 100 = [ 1 2 3 4 ] + [ 100 100 100 100 ] = [ 101 102 103 104 ] \left[ \begin{matrix} 1 \\2 \\ 3 \\ 4 \end{matrix} \right] +100 =\left[ \begin{matrix} 1 \\2 \\ 3 \\ 4 \end{matrix} \right] + \left[ \begin{matrix}100 \\ 100 \\ 100 \\ 100 \end{matrix} \right] =\left[ \begin{matrix} 101 \\ 102 \\ 103 \\ 104 \end{matrix} \right] ⎣⎢⎢⎡1234⎦⎥⎥⎤+100=⎣⎢⎢⎡1234⎦⎥⎥⎤+⎣⎢⎢⎡100100100100⎦⎥⎥⎤=⎣⎢⎢⎡101102103104⎦⎥⎥⎤
多列向量复制
[ 1 2 3 4 5 6 ] + [ 100 200 300 ] = [ 1 2 3 4 5 6 ] + [ 100 200 300 100 200 300 ] = [ 101 202 303 104 205 306 ] \left[ \begin{matrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{matrix} \right] + \left[ \begin{matrix} 100 & 200 & 300 \end{matrix} \right] =\left[ \begin{matrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{matrix} \right] + \left[ \begin{matrix} 100 & 200 & 300 \\100 & 200 & 300 \end{matrix} \right] = \left[ \begin{matrix} 101 & 202 & 303 \\104 & 205 & 306 \end{matrix} \right] [142536]+[100200300]=[142536]+[100100200200300300]=[101104202205303306]
水平复制同理
documentation for NumPy (broadcasting)
python/numpy vectors 技巧分享
python-numpy程序语言提供了很高的灵活性,这既是它这个语言的优势(语言表达力更强,灵活性大,可以用一行代码代替完成很多运算),也是它的劣势(因为广播这么大的灵活性,有时会引入非常细微的错误,奇怪的bug),如果并不是非常熟悉所有复杂的广播运作的方式(比如,一个行向量可以和一个列向量相加),便会很容易写出包含很难调试的bug。
import numpy as np
a = np.random.randn(5)
print(a)
out:五个随机数
print(a.shape)
out (5,) 这是Python称之为 秩为1的数组,它既不是行向量也不是列向量,这导致它有一些略微不直观的效果
print(a.T)
输出的和a看起来并没有区别
print(np.dot(a, a.T))
得到一个数字(相当于矩阵的内积),并没有得到一个矩阵。
所以建议在编写神经网络程序时,不要使用像(5,)或是(n,)这种秩为1的数组的数据结构。
可以这样代替,
a = np.random.randn(5,1)
这样就可以令a变成5×1的列向量
这时a转置就是一个行向量了,这时可以发现一个微小的区别,就是这个数据结构中,有两个方括号,而之前只有一个方括号。
这时再进行a和a的转置相乘,便得到了一个向量的外积。
现在来分析一下一开始创建随机数数组的这句话
这里a.shape = (5,)
即秩为1的数组,这个数据结构的行为和行向量与或列向量并不一样,所以在编程实现的时候尽量不要使用这些秩为1的数组。
尽量使用
上面一个是column vector(列向量)
下面一个是row vector(行向量)
但是有时,如果在代码中做了很多操作,所以并不确定一个向量的具体维度是多少时,需要用assert()这样一个声明,来输出异常
确保这是一个向量,assert()运行很快,所以不用担心提高成本。
如果因为某种原因得到了一个秩为1的数组,可以使用reshape来进行转换
a = a.reshape((5,1))
得以更好的进行预测。
有时候很多问题可能都来自于秩为1的数组,通过消除代码中秩为1的数组,可以让代码变得更简单。
逻辑回归的损失函数的说明
- logistic regression cost function
ŷ = σ(wT+b) when σ ( z ) = 1 1 + e − z \sigma (z) = \frac{1}{ {1 + {e^{ - z}}}} σ(z)=1+e−z1
interpret ŷ = p(y=1|x) ,即ŷ使给定训练样本下y=1的概率
If y = 1 : p(y|x) = ŷ
If y = 0 : p(y|x) = 1 - ŷ , 1-ŷ表示y=0的概率
这两个式子可以合并成
p(y|x) = ŷy(1-ŷ)(1-y)
因为:
(1)情况一,假设y=1,那么上面这个式子解出来就是 p(y|x) = ŷ
(2)情况二,假设y=0,那么上面这个式子解出来就是 p(y|x) = 1 - ŷ
由于log函数是严格单调递增的函数,最大化log(p(y|x))等价于
log(p(y|x)) = logŷy(1-ŷ)(1-y) = ylogŷ + (1-y)log(1-ŷ) = - L(ŷ,y)
得到了之前推导出的损失函数的负值
有负号的原因是,当训练学习算法时,希望算法输出值得概率是最大的,然而在logistic回归中,需要的是最小化损失函数,因此最小化损失函数就是最大化log(p(y|x))。
- the overall cost function
计算在m个样本下的成本函数
整个训练集中标签的概率(假设所有的训练样本服从同一分布且相互独立,所有这些样本的联合概率,就是每个样本概率的乘积)
p ( l a b e l s i n t r a i n i n g s e t ) = ∏ i = 1 m p ( y ( i ) ∣ x ( i ) ) {\rm{p(labels in training set) = }}\prod\limits_{i = 1}^m {p({y^{(i)}}|{x^{(i)}})} p(labelsintrainingset)=i=1∏mp(y(i)∣x(i))
如果要做最大似然估计,那么需要寻找一组参数,使得规定样本的观测值概率最大,即等价于令其对数最大化。
在等式两边取对数,即得
log p ( l a b e l s i n t r a i n i n g s e t ) = ∑ i = 1 m log p ( y ( i ) ∣ x ( i ) ) \log {\rm{p(labels in training set) = }}\sum\limits_{i = 1}^m {\log p({y^{(i)}}|{x^{(i)}})} logp(labelsintrainingset)=i=1∑mlogp(y(i)∣x(i))
其中
log p ( y ( i ) ∣ x ( i ) ) = − L ( y ^ ( i ) , y ( i ) ) {\log p({y^{(i)}}|{x^{(i)}})}=-L(\hat{y}^{(i)},y^{(i)}) logp(y(i)∣x(i))=−L(y^(i),y(i))
极大似然估计maximum likelihood estimation
即求出一组参数,是这个式子取最大值
在这个式子就是求
− ∑ i = 1 m L ( y ^ ( i ) , y ( i ) ) -{\rm{ }}\sum\limits_{i = 1}^m {L(\hat{y}^{(i)},y^{(i)})} −i=1∑mL(y^(i),y(i))的最大值,
这样就推导出了前面给出的logistic回归的成本函数J(w,b)
C o s t : J ( w , b ) = 1 m ∑ i = 1 m L ( y ^ ( i ) , y ( i ) ) Cost:J(w,b)=\frac{1}{m}{\rm{ }}\sum\limits_{i = 1}^m {L(\hat{y}^{(i)},y^{(i)})} Cost:J(w,b)=m1i=1∑mL(y^(i),y(i))
由于训练模型时,目标是让成本函数最小化,所以不直接用最大似然概率,需要去掉前面的符号,最后为了方便对成本函数进行适当的缩放,就在式子前面加一个额外的常数因子(1/m)
课后作业
测试
- 测试中的知识点
Numpy基于元素的乘法和矩阵乘法的区别
编程作业
【问题一】
plt.imshow()显示不出图片
【解决】
法一:在plt.imshow()后加plt.show()
法二:开头加载模块 import pylab() 并在plt.imshow()后加pylab.show()
【问题二】
train_set_x_orig.reshape(train_set_x_orig.shape[0],-1)其中reshape的参数是-1,代表什么意思
【解决】
数组新的shape属性应该要与原来的配套,如果等于-1的话,Numpy会根据剩下的维度计算出数组的另一个shape属性值。
【问题三】
正向传播、反向传播
【解决】
一文弄懂神经网络中的反向传播法——BackPropagation
【问题四】
什么是偏置
【解决】
神经网络中偏置的作用
【问题五】
什么是bias
【解决】
浅谈神经网络中的bias
【索引】
深度学习(二)——浅层神经网络
深度学习(三)——深层神经网络