1.深度学习概述
1.1 所有课程学习内容简介
- Neural Networks and Deep Learning
- Improving Deep Neural Networks: Hyperparametertuning, Regularization and Optimization
- Structuring your Machine Learning project
- Convolutional Neural Networks
- Natural Language Processing: Building sequence models
- 第一课:神经网络与深度学习基础,学习如何建立神经网络,如何在数据上训练。
- 第二课:深度学习方面的实践,学习严密的构建神经网络,超参数调整,正则化诊断偏差和方差,高级优化算法等。
- 第三课:学习如何结构化机器学习工程,构建机器学习系统的策略,端到端深度学习等。
- 第四课:卷积神经网络(CNN),常用于图像领域,将学习如何搭建该模型。
- 第五课:序列模型,学习如何应用于自然语言处理以及其他问题;该模型包含循环神经网络(RNN),长短期记忆网络模型(LSTM)。
1.2 什么是神经网络?
“深度学习”指的是训练神经网络;指通过构建和训练包含多个隐藏层的模型,自动从数据中提取特征。与传统的机器学习方法依赖于手工设计的特征不同,深度学习能够从原始数据中自动学习出有用的特征表示。
以房价预测为例,假设有一个六间房屋的数据集,将房屋size作自变量x,房屋价格作因变量y,根据x,y和数据集,可得一个拟合函数 y=f(x) 预测房价,该函数可看成一个简单的神经网络,房屋size作为该神经网络的输入x,通过神经网络结点,输出价格y。(如下图)
一般情况下,房屋价格不会为负数,所有拟合函数直线使其结束为0,该模型就可以看成是一个神经网络,几乎是一个最简单的神经网络。我们把该房价预测用一个最简单的神经网络模型来表示(如下图),图中小圆圈就是一个独立的神经元,该神经元做的就是输入面积,完成线性运算,取不小于0的值,最后输出最终预测价格。在神经网络的文献中,经常看到一个函数一开始是零,然后就是一条直线,这个函数称为ReLU函数,称修正线性单元。
上面是一个单神经元网络,x房屋size的一个因素,规模很小的,大一些的神经网络是把这些单个神经元堆叠起来形成的。现在除了考虑房屋size之外,还考虑卧室数目,这两点与家庭成员的个数挂钩,考虑房屋的邮政编码与可步行性挂钩,另外,还有可能邮政编码和地区财富水平共同影响了房屋所在地区的学校质量。(如下图)
上述例子是真正的神经网络模型结构。它有四个输入,分别是size,#bedrooms,zip code和wealth。在给定这四个输入后,神经网络所做的就是输出房屋的预测价格y。图中,三个神经元所在的位置称之为中间层或者隐藏层,x所在的称之为输入层,y所在的称之为输出层,每个神经元与所有的输入x都有关联。
1.3 用神经网络进行监督学习?
机器学习主要包括监督学习、半监督学习、无监督学习和强化学习。
- 有监督学习就是根据有标签的数据集学习一个由输入到输出的映射;
- 无监督学习是学习一个没有标签的数据集,是基于数据之间的相似性进行聚类分析学习;
- 半监督学习是介于监督学习和无监督学之间的学习方式;
- 强化学习是根据奖惩函数的反馈来调节参数并不断循环这一过程使目标最大化的学习过程。
上图是几个监督式学习在神经网络中应用的例子,第一个是房屋价格预测,第二个是线上广告,对于前面两个一般的监督式学习,我们只要使用标准的神经网络模型就可以了;第三个是图像识别,对于图像识别处理问题,我们则要使用卷积神经网络(CNN);第四个是语音识别,第五个是智能翻译,对于处理类似语音这样的序列信号时,则要使用循环神经网络(RNN);第六个是自动驾驶,这样的复杂问题则需要更加复杂的混合神经网络模型。
机器学习应用于结构化数据和非结构化数据。
结构化数据是数据的数据库,意味着每个特征都有清晰的定义。
非结构化数据(Unstructrued Data),通常指抽象的数据,比如音频、原始音频、图像、文本,特征一般为图片像素值,单词等。
1.4 课程小结
通过第一章课程的学习,我初步了解了深度学习的概念和应用,通过房屋预测的例子明白了神经网络的定义,并知道了一些常用神经网络模型在各个领域的应用。
2.逻辑回归(Logistic Regression)和向量化
2.1 二分分类
- 实现一个神经网络并不需要使用for循环进行。
- 神经网络的计算过程可以分为前向传播和反向传播。
- logistoc回归是一个用于二分分类的算法,二分类就是输出结果y只有0和1两个标签(也有-1和1的情况)。以一个图像识别为例,例如识别猫,1代表猫,0代表不是猫。用y表示输出的结果标签。
在二分类问题中,目标是训练一个分类器,它以图片的特征向量x为输入,预测输出的结果标签y是0还是1。
用一对(x,y)表示一个单独的样本,其中x是n_x维的特征向量,y为0或者1;训练集大小为m,train为训练集,test为测试集。
定义一个矩阵X,矩阵有m列,n_x行,这里矩阵X的行n_x代表了每个样本x的特征个数,列m代表了样本个数。有时候矩阵X的定义是训练样本作为行向量堆叠,而不是这样列向量堆叠。在神经网络中,一般用列向量。X是一个n_x*m的矩阵。当你用python 实现时,X.shape=(n_x,m)
Y是一个1*m的矩阵,同样Y.shape=(1,m)。
2.2 logistic回归
表示y为1的概率,取值范围是(0,1)之间。
已知:特征输入向量x是n_x维度,logistic回归的参数w是n_x维的向量,b为实数,计算输出预测y帽?(y应介于0-1之间)。若使用线性模型,引入参数w和b(权数w的维度是n_x,b为常数项),逻辑回归的线性预测输出如下:
但上式的线性输出区间为整个实数范围,而逻辑回归要求输出范围在[0,1]之间,于是引入Sigmiod函数,让输出限定在[0,1]之间。
Sigmiod函数是一种非线性的S型函数,输出范围是[0,1],通常在神经网络中当激活函数。表达式及曲线图如下:
从曲线及公式可知,当z很大时,函数值趋于1;当z很小时,函数值趋于0;且当z=0时,函数值为0.5。
完整逻辑回归的预测输出式,输出转换为[0,1]之间:
2.3 logistic回归损失函数
损失函数( Loss(error) function):用来衡量算法的运行情况。可定义损失函数为y帽和y的差的平方,或者它们差的平方的1/2,但在logistic回归中,我们偏向研究凸函数问题,我们会定义一个不同的损失函数(如下图),有和误差平方相似的作用,也会给我们一个凸的优化问题。
对于这个损失函数,我们也想让它尽可能的小;
- y=1时,L= - log(y^)想要足够小,y^就要足够大,最大最大不能超过1;
- y=0时,L=- log(1-y^)想要足够小,(1-y^)要足够大,y^就要足够小,最小不能小于0。
损失函数是在单个训练样本中定义的,它衡量了在单个训练样本上的表现。
成本函数(cost function):衡量的在全体训练样本上的表现。成本函数J是根据之前得到的两个参数w和b,J(w,b)=损失函数求和/m.,即所有m个训练样本的损失函数和的平均。在训练模型时,要找到合适的w和b,让成本函数J尽可能的小。
2.4 梯度下降法
logistic回归函数:
找使成本函数J(w,b)尽可能小的w和b:
凸函数的局部优化特性是logistic回归使用这个成本函数J的重要原因之一;使用梯度下降法很快地收敛到局部最优解或者全局最优解。
由于J(w,b)是凸函数,梯度下降算法(Gradient Descent)是先随机选组一组参数w和b值,然后每次迭代的过程中分别沿着w和b的梯度(偏导数)的反方向前进一小步,不断修正w和b。每次迭代更新w和b后,都能让J(w,b)更接近全局最小值。
梯度下降算法每次迭代更新,w和b的修正表达式为:
alpha是学习因子(learning rate),表示梯度下降的步进长度,其值越大,w和b每次更新的“步伐”更大一些;越小,更新“步伐”更小一些。在程序代码中,我们通常使用dw来表示。梯度下降算法能够保证每次迭代w和b都能向着J(w,b)全局最小化的方向进行。
2.5 计算图
神经网络的计算过程是通过正向传播和反向传播过程来实现的,首先计算出神经网络的输出,紧接着进行一个反向传输操作,后者我们用来计算出对应的梯度或者函数。如下为例:
令a=5,b=3,c=2,则u=bc=6,v=a+u=11,J=3v=33。计算图中,这种从左到右,从输入到输出的过程就对应着神经网络或者逻辑回归中输入与权重经过运算计算得到Cost function的正向过程。
2.6 计算图的导数计算
反向过程:
计算J对参数a的偏导数:
计算J对参数b的偏导数:
J对参数c的偏导数:
2.7 logistic回归中的梯度下降
单个样本的逻辑回归损失函数(Loss function)表达式:
逻辑回归的正向传播过程:根据上述公式,例如输入样本x有两个特征(x1,x2),相应的权重w维度也是2,即(w1,w2),则z=w1x1+w2x2+b;
逻辑回归的反向传播过程:由损失函数(Loss function)计算参数w和b的偏导数;
求出dz之后,对w1,w2和b进行求导;
梯度下降算法:更新w1为w1减去学习率乘以dw1;更新w2为w2减去学习率乘以dw2;更新b为b减去学习率乘以db。这就是单个样本实例的一次梯度更新步骤。
2.8 m个样本的梯度下降
损失函数是用于对单个样本求偏导和梯度下降,成本函数是用于对m个样本求偏导和梯度下降,成本函数表达式如下:
关于w和b的偏导数:
每次迭代中w和b的梯度有m个训练样本计算平均值得到(python代码如下):
#1.初始化
J=0; dw1=0; dw2=0; db=0;
#2.for循环遍历训练集,并且计算相应的每个训练样本的导数
for i = 1 to m
z(i) = wx(i)+b;
a(i) = sigmoid(z(i));
J += -[y(i)log(a(i))+(1-y(i))log(1-a(i));
dz(i) = a(i)-y(i);
dw1 += x1(i)dz(i);
dw2 += x2(i)dz(i);#n=2,两个特征w1,w2
db += dz(i);
#3.最终对所有的m个训练样本都进行了这个计算,你还需要除以m,计算平均值
J /= m;
dw1 /= m;
dw2 /= m;
db /= m;
这样经过n次迭代后,整个梯度下降算法就完成了。
2.9 向量化
向量化可以消除你代码中显式的for循环,加快代码运行速度。
如上图所示,左侧为非向量化,右侧为向量化。
示例:
import time
a=np.random.rand(1000000)
b=np.random.rand(1000000)
tic = time.time()
c = np.dot(a,b)
toc = time.time()
print(c)
print("Vectorized version:" + str(1000*(toc-tic)) + "ms")
c = 0
tic = time.time()
for i in range(1000000):
c += a[i]*b[i]
toc = time.time()
print(c)
print("For loop version:" + str(1000*(toc-tic)) + "ms")
上述运行结果看出向量化之后,运行速度会大幅上升,该例子使用for循环运行时间是使用向量计算运行时间的300多倍。
- GPU也叫图像处理单元;
- CPU和GPU都有并行化(parallelization)的指令,也会叫SIMD指令,意指单指令流多数据流;
- np.function或者其他能让你去掉显式for循环的函数;
- 相对而言,GPU更擅长SIMD计算,但CPU事实上也不是太差。
向量化的更多例子:
1.已经矩阵A和向量v,想求乘积,我们通常使用u = np.dot(A,v)函数来进行矩阵乘积;
2.已经向量v,想做指数运算,作用到向量v的每一个元素。使用u = np.exp(v),v作为输入向量,u作为输出向量。这样代码会快很多。
numpy库有很多向量值函数,例如np.log()会逐个元素计算log;np.abs()会计算绝对值;np.maxinum计算所有元素中的最大值;v**就是v中每个元素的平方;1/v就是每个元素求倒数。所以当你想使用for循环时,应该考虑调用numpy的内置函数替代。
#1.初始化
J=0; dw1=0; dw2=0; db=0;
#2.for循环遍历训练集,并且计算相应的每个训练样本的导数
#循环1
for i = 1 to m
z(i) = wx(i)+b;
a(i) = sigmoid(z(i));
J += -[y(i)log(a(i))+(1-y(i))log(1-a(i));
dz(i) = a(i)-y(i);
#循环2 for j = 1 to n_x
dw1 += x1(i)dz(i);
dw2 += x2(i)dz(i);#n_x=2,两个特征w1,w2
db += dz(i);
#3.最终对所有的m个训练样本都进行了这个计算,你还需要除以m,计算平均值
J /= m;
dw1 /= m;
dw2 /= m;
db /= m;12345678910111213
上述代码可使用向量化简化:
J = 0,dw = np.zeros(n_x,1)
#上面代码的11,12行改为:
dw += X(i)dz(i)
#上面代码的16,17行改为:
dw /=m
#现在值剩下一个循环,对单独的训练例子循环
2.10 向量化logistic回归
logistic回归的正向传播对前三个样本预测计算(m个训练样本):
以此类推,你需要循环做m次。结果表明要进行正向传播,需要对m个训练样本都计算预测结果。
不使用显式for循环实现方法:先构建一个1*m的矩阵Z来作为你的训练输出,w^T是一个1*n_x的矩阵,转置之后的维度是(1,n_x)。b是一个常数值,维度为(1,m)。
python代码:
import numpy as np
Z = np.dot(w.T,X) + b #w.T表示w的转置,b为1*1,Z为1*m矩阵
#python中自动扩展为一个1*m的行向量,这个操作在python中叫做广播(broadcasting)
A = sigmoid(Z)
2.11 向量化logistic回归的梯度输出*
logistic回归实现步骤:
我们已经去掉了Z的循环,但仍有一个遍历训练集的循环,我们使用dw=0将dw初始化为0向量;
db可写成:
python代码:
db = 1/m*np.sum(dZ)
dw可写成:
db = 1/m*np.sum(dZ)
整个logistic回归向量化:
Z = np.dot(w.T,X) + b
A = sigmoid(Z)
dZ = A-Y
dw = 1/m*np.dot(X,dZ.T)
db = 1/m*np.sum(dZ)
w = w - alpha*dw
b = b - alpha*db
其中,alpha是学习因子,决定w和b的更新速度;上述代码只是对单次训练更新而言的,外层还需要一个for循环,表示迭代次数。
2.12 python中的广播
广播是可以让你的代码更快的一种手段。
计算苹果中的碳水化合物卡路里百分比含量;对于其他食物,计算方法类似。
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)
#[[ 56. 0. 4.4 68. ]
# [ 1.2 104. 52. 8. ]
# [ 1.8 135. 99. 0.9]]
cal = A.sum(axis=0) #axis=0意味着竖直轴相加,而水平轴是1
print(cal)
#[ 59. 239. 155.4 76.9]
percentage = 100*A/cal.reshape(1,4) #其实也可以不调用reshape(),但是使用会更保险,时间复杂度为o(1),调用成本极低
print(percentage)
#[[94.91525424 0. 2.83140283 88.42652796]
# [ 2.03389831 43.51464435 33.46203346 10.40312094]
# [ 3.05084746 56.48535565 63.70656371 1.17035111]]
其他例子:
由于python的广播,python中可以对不同维度的矩阵进行四则混合运算,会进行灵活拓展,至少保证有一个维度是相同的; 如:(m,n)与(1,n)进行运算,就是把(1,n)复制m次,变成(m,n)后再进行运算;也可以使用reshape()函数来对矩阵设定所需的维度。
2.13 关于python numpy 向量的说明
python的numpy程序语言一些编程技巧:
import numpy as np a = np.random.randn(5)
#生成5个随机高斯变量,储存在数组a中
a的维度是(5,),这是所谓的python中秩为1的数组,称为rank 1 array,它既不是行向量也不是列向量 ,这导致它会出现一些不便—转置后和原数组看起来一样。
所以定义(5,1)的列向量,尽量使用代码:
a = np.random.randn(5,1) print(a)
#[[-1.04511918] [-0.74705054] [-0.53671784] [ 0.66077854] [ 1.57372222]]
输出转置和內积:
还可使用assert语句对向量或数组的维度进行判断,assert会对内嵌语句进行判断,即判断a的维度是不是(5,1)的,如果不是,则程序在此处停止 :
assert(a.shape == (5,1))
#执行起来很快,也可以看成是代码的文档
可以用reshape转换成5*1数组:
a.reshape((5,1))
2.14 logistic成本函数的解释
logistic回归的成本函数的证明过程:
(1)预测输出y帽;
(2)y帽可以看成是给定训练样本x条件下y=1的概率;
整合得;
对两边同时取对数;
上述概率P越大越好,加上负号就是单个成本的损失函数(越小越好)如下:
假设所有m个训练样本服从同一分布且相互独立,即独立同分布。所有这些样本的联合概率就是每个样本概率的乘积(极大似然概率), 总的概率越大越好;
引入log函数,加上负号,转换为成本函数:
1/m表示对m个样本的损失函数求平均,为缩放因子。
2.15 课程小结
本节课主要介绍了神经网络的基础,介绍了二分类问题,以图片为例,将多维输入x转化为特征向量,输出y只有{0,1}两个离散值;介绍了逻辑回归及其对应的成本函数形式、梯度下降算法,并使用计算图的方式来讲述神经网络的正向传播和反向传播过程;还介绍了在深度学习程序中,使用向量化和矩阵运算的方法能够大大提高运行速度,节省时间;在本节课程的学习中,由于是第一次学习这方面知识,感觉有些知识点的用法及功能有点模糊,希望后续通过深入学习会有新的领悟。
3.神经网络基础
3.1 神经网络概述
可以把多个sigmoid单元的堆叠构成一个神经网络,神经网络的结构与逻辑回归类似,但神经网络的层数比逻辑回归多一层,多出来的中间那层称为隐藏层或中间层。从计算上来看,神经网络的正向传播和反向传播比logistic回归多了一次重复的计算。正向传播过程分成两层:第一层是输入层到隐藏层,用上标[1]来表示,第二层是隐藏层到输出层,用上标[2]来表示;反向传播过程也分成两层,第一层是输出层到隐藏层,第二层是隐藏层到输入层。
3.2 神经网络表示
- 输入特征x1,x2,x3竖向堆叠起来,这是神经网络的输入层(input layer);
- 中间四个一层的圆圈,称之为神经网络的隐藏层(hidden layer);
- 最后一个圆圈是输出层(output layer),只有一个节点,它负责输出预测值y帽。
一个神经网络中,当你使用监督学习训练它时,训练集包含了输入x,还有目标输出y。“隐藏层”的含义是在训练集中这些中间节点的真实数值我们是不知道的,看不到它们的数值。
向量x表示输入特征,也可以用a^[0],且a也表示激活,它意味着网络中不同层的值会传递给后面的。把隐藏层输出记为a^[1],上标从0开始。用下标表示第几个神经元,注意下标从1开始。例如a^[1]_1表示隐藏层第1个神经元。在python中,隐藏层有4个神经元就可以写成下面矩阵的形式:
最后的输出层会产生某个数值a^[2],是个实数。
当我们在计算网络的层数时,隐藏层是第1层,输出层是第2层,约定的符号中将输入层称为第0层。所以上图是“三层”的神经网络,因为它有输入层、隐藏层和输出层。但在论文中,一般称上图为双层神经网络,因为我们不把输入层看作一个标准的层。此外,须知隐藏层和输出层是带有参数的,这里隐藏层有两个相关参数W和b,使用上标[1]表示这些参数。
关于隐藏层对应参数W^[1]和常数项b^[1]:
- W^[1]的纬度是(4,3),4对应着隐藏层神经元个数,3对应输入层特征向量x的元素个数;
- 常数项b^[1]的纬度是(4,1),4也对应着隐藏层神经元个数。
输出层对应参数W^[2]和常数项b^[2]:
- W^[2]的纬度是(1,4),这里1对应着输出层神经元个数,4对应隐藏层特征向量x的元素个数;
- 常数项b^[2]的纬度是(1,1),因为输出只有1个神经元。
总结:第i层的权重W^[i]维度的行等于i层神经元的个数,列等于i-1层神经元的个数;第i层常数项b^[i]的行等于第i层神经元的个数,列始终为1。
3.3 计算神经网络的输出
神经网络到底在计算什么?
单个logistic回归单元的两个传播计算过程;
两层神经网络本质上是多次logistic回归单元计算,从输入层到隐藏层的逻辑回归和从隐藏层到输出层的逻辑回归,计算是从a1[1]到ai[i];下图右侧即左侧四个神经元的计算公式。
将上述的计算进行向量化,可提高计算效率:
向量化法则:当我们一层中有不同的结点,进行纵向堆叠;如下W^[1]的维度是(4,3),b^[1]的维度是(4,1),W^[2]的维度是(1,4),b^[2]的维度是(1,1)。(如下图)
说明:此文章为学习笔记,如果错误欢迎指正!(此为第一周的主要学习笔记,后续笔记接下周。)