【吴恩达-神经网络与深度学习】第二周:神经网络基础

目录

二分分类

一些符号

logistic回归

logistic回归损失函数(Logistic Regression Cost Function)

梯度下降法

梯度下降法的形象化说明

梯度下降法的细节说明

导数

更多导数的例子

计算图

计算图的导数计算

logistic回归中的梯度下降法

m个样本的梯度下降

向量化

向量化的更多例子

向量化logistic回归

向量化logistic回归的梯度输出

python中的广播

广播机制的一般原则

关于 python _ numpy 向量的说明

(选修)logistic 损失函数的解释

单个样例

在m个训练样本的整个训练集中


例如有一个包含个样本的训练集,你很可能习惯于用一个for循环来遍历训练集中的每个样本,但是当实现一个神经网络的时候,我们通常不直接使用for循环来遍历整个训练集,所以在这周的课程中你将学会如何处理训练集。

神经网络的计算过程中,通常有一个正向过程,叫做正向传播过程,接着又一个反向过程,叫做反向传播步骤

二分分类

图像的表示为RGB矩阵,要将其转换为一个输入的特征向量x,按照RGB的顺序存储在x中;若图片大小为64*64,则x的维度n=64*64*3。

判断一个图片是否是猫,若是,则输出y为1;否则为0

一些符号

 

python中,X.shape=(n_x,m)

 

logistic回归

是一个二元分类问题,用于监督学习;其实是求\^{y}=1的概率

logistic回归的参数w和b,w实际上是特征权重,维度与特征向量相同;b是一个实数,表示偏差

图中的预测函数是线性函数

给出输入x以及参数w和b之后,我们希望输出的\^{y}在0~1之间,所以使用了sigmod函数将输出映射到0~1

 

logistic回归损失函数(Logistic Regression Cost Function)

为了训练参数w和b,需要定义一个成本函数

逻辑回归的输出函数:

为了让模型通过学习调整参数,你需要给予一个m样本的训练集,这会让你在训练集上找到参数w和参数b,,来得到你的输出。

上标(i)来指明数据表示x或者y或者z或者其他数据的第i个训练样本

 

损失函数/误差函数:衡量算法的运行情况

一般我们用预测值和实际值的平方差或者它们平方差的一半,但是通常在逻辑回归中我们不这么做,因为当我们在学习逻辑回归参数的时候,会发现我们的优化目标不是凸优化,只能找到多个局部最优值,梯度下降法很可能找不到全局最优值,虽然平方差是一个不错的损失函数,但是我们在逻辑回归模型中会定义另外一个损失函数。

在逻辑回归中用到的损失函数是:

对于这个逻辑回归损失函数,我们也想让它尽可能地小

损失函数是在单个训练样本中定义的,它衡量的是算法在单个训练样本中表现如何,为了衡量算法在全部训练样本上的表现如何,我们需要定义一个算法的代价函数,它衡量在全体样本上的表现:

损失函数(loss function)只适用于像L(\^{y},y)这样的单个训练样本,而代价函数(cost function)是参数的总代价。

所以在训练逻辑回归模型时候,我们需要找到合适的w和b,来让代价函数J的总代价降到最低。

逻辑回归可以看做是一个非常小的神经网络。

 

梯度下降法

logistic回归算法及其代价函数(成本函数):

代价函数衡量了参数w和b在训练集上的效果。

梯度下降法的形象化说明

为便于画图,这里w是一个实数;代价函数J是一个凸函数

为了找到更好的参数值w和b,首先用某初始值初始化w和b;在logistic回归中,各种初始化值都是有效的。因为函数是凸函数,无论在哪里初始化,应该达到同一点或大致相同的点。

这里使用下图中的小红点作为初始值:

朝最陡的下坡方向走一步,不断地迭代,直到走到全局最优解或者接近全局最优解的地方

梯度下降法的细节说明

这里只用了一个参数,用一维曲线代替多维曲线

迭代就是不断重复做如图的公式::其中\alpha​​​​​​是学习率​(learning rate),即梯度下降法中的步长;\frac{dJ(w)}{dw}就是函数J(w)对w求导(derivative),在代码中我们会使用dw表示这个结果

导数的定义:是函数在某个点的斜率,而函数的斜率是高除以宽

假设我们以如图点为初始化点,该点处的斜率的符号是正的,即\frac{dJ(w)}{dw}>0,所以接下来会向左走一步。整个梯度下降法的迭代过程就是不断地向左走,直至逼近最小值点。

假设我们以如图左上方点为初始化点,该点处的斜率的符号是负的,即\frac{dJ(w)}{dw}<0,所以接下来会向右走一步。整个梯度下降法的迭代过程就是不断地向右走,即朝着最小值点方向走。

在logistic回归的代价函数中,含有两个参数:

 

导数

斜率slope,也就是导数derivative

表示方法:

直线的导数固定不变

 

更多导数的例子

一个例子:不同的位置导数值不同

其他例子:

 

导数就是斜率

 

计算图

一个神经网络的计算都是按照前向或反向传播过程实现的,首先计算神经网络的输出,接着进行一个反向传输操作。后者我们用来计算出对应的梯度或导数。

从左到右的过程,可以计算出J的值;从右到左的过程可以用来计算导数

 

计算图的导数计算

链式法则

python中,你可以写一个很长的变量名,比如dFinalOutputvar\_dvar,但这个变量名有点长,就用dJ\_var.这里要介绍一个新符号,在代码里,我们就使用变量名dvar,来表示那个量,即在程序中dvar表示导数

 

logistic回归中的梯度下降法

求导:

 

m个样本的梯度下降

损失函数J(w,b)的定义:

一次迭代:

对应的代码流程:

J=0;dw1=0;dw2=0;db=0;
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);
    db += dz(i);
J/= m;
dw1/= m;
dw2/= m;
db/= m;
w=w-alpha*dw
b=b-alpha*db

以上是一次梯度下降的过程

避免使用for循环,用到了向量化

 

向量化

逻辑回归中需要计算z=w^{T}x+b,w、x是列向量,所以如果使用非向量化方法去计算w^{T}x,你需要用如下方式:

z=0
​
for i in range(n_x)
​
    z+=w[i]*x[i]
​
z+=b

而向量化计算的方式如下:

z=np.dot(w,x)+b

用python代码比较两种方式的运行时间:(以下为教授在他的Jupyter notebook上写的Python代码)

import numpy as np #导入numpy库
a = np.array([1,2,3,4]) #创建一个数组a
print(a)
# [1 2 3 4]

import time #导入时间库
a = np.random.rand(1000000)
b = np.random.rand(1000000) #通过round随机得到两个一百万维度的数组
tic = time.time() #现在测量一下当前时间
#向量化的版本
c = np.dot(a,b)
toc = time.time()
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:” + str(1000*(toc-tic)) + “ms”)#打印for循环的版本的时间

结果如下:

你可能听过很多类似如下的话,“大规模的深度学习使用了GPU或者图像处理单元实现”,但是我做的所有的案例都是在jupyter notebook上面实现,这里只有CPU

CPUGPU都有并行化的指令,也叫做SIMD指令,这个代表了一个单独流多数据流,这个的基础意义是,如果你使用了像np.function或者并不要求你实现循环的函数,它可以让python的充分利用并行化计算。

GPU更加擅长SIMD计算,但是CPU事实上也不是太差,可能没有GPU那么擅长吧。

 

向量化的更多例子

尽量不用for循环

使用python时,numpy库有很多向量函数。比如u=np.log是计算对数函数()、np.abs()是计算数据的绝对值、np.maximum()计算元素中的最大值,也可以用 np.maximum(v,0) ;v**2代表元素每个值平方、  \frac{1}{v}获取元素的倒数等等。所以当需要写循环的时候,首先检查numpy是否存在类似的内置函数,从而避免使用循环(loop)方式。

之前的逻辑回归计算也可以优化为:

 

向量化logistic回归

logisitic的正向传播过程:

 

向量化logistic回归的梯度输出

反向传播:

逻辑回归的一次梯度下降:

 

python中的广播

jupyter notebook中输入如下代码,按shift+Enter运行,输出如下:

使用如下代码计算每列的和,可以看到输出是每种食物(100g)的卡路里总和:

其中sum的参数axis=0表示求和运算按列执行。

接下来计算百分比,这条指令将 的矩阵除以一个的矩阵,得到了一个 的结果矩阵,这个结果矩阵就是我们要求的百分比含量:

A.sum(axis = 0)中的参数axisaxis用来指明将要进行的运算是沿着哪个轴执行,在numpy中,0轴是垂直的,也就是列,而1轴是水平的,也就是行。

而第二个A/cal.reshape(1,4)指令则调用了numpy中的广播机制。这里使用3*4的矩阵除以1*4的矩阵cal。技术上来讲,其实并不需要再将矩阵cal reshape(重塑)成1*44,因为矩阵本身已经是1*4了。但是当我们写代码时不确定矩阵维度的时候,通常会对矩阵进行重塑来确保得到我们想要的列向量或行向量。重塑操作reshape是一个常量时间的操作,时间复杂度是O(1),它的调用代价极低。

 

在numpy中,当一个4*1的列向量与一个常数做加法时,实际上会将常数扩展为一个4*1的列向量,然后两者做逐元素加法。结果就是右边的这个向量。这种广播机制对于行向量和列向量均可以使用。

 

用一个2*3的矩阵和一个1*3的矩阵相加,其泛化形式是m*n的矩阵和1*n的矩阵相加。在执行加法操作时,其实是将1*n的矩阵复制成为m*n的矩阵,然后两者做逐元素加法得到结果。针对这个具体例子,相当于在矩阵的第一列加100,第二列加200,第三列加300。

 

下面这个例子,相当于是一个m*n的矩阵加上一个 m*1的矩阵。在进行运算时,会先将m*1矩阵水平复制 n次,变成一个 m*n的矩阵,然后再执行逐元素加法。

 

广播机制的一般原则

 

关于 python _ numpy 向量的说明

一种可能的错误:

实际编程中最好指明行列数

如果不确定一个向量的维度(dimension),可以使用一个断言语句(assertion statement):

 

(选修)logistic 损失函数的解释

单个样例

逻辑回归(二分分类)中,需要预测的结果\^y为:

将这两个式子合并为一个:

由于 log 函数是严格单调递增的函数,最大化 log(p(y|x))等价于最大化 p(y|x) 。

损失函数前面有一个负号的原因是:当训练学习算法时需要算法输出值的概率是最大的(以最大的概率预测这个值),然而在逻辑回归中我们需要最小化损失函数,因此最小化损失函数与最大化条件概率的对数log(p(y|x))关联起来了,因此这就是单个训练样本的损失函数表达式。

 

在m个训练样本的整个训练集中

假设所有的训练样本服从同一分布且相互独立,也即独立同分布的,所有这些样本的联合概率就是每个样本概率的乘积:

最大似然估计,即求出一组参数,使这个式子取最大值

由于训练模型时,目标是让成本函数最小化,所以我们不是直接用最大似然概率,要去掉这里的负号,最后为了方便,可以对成本函数进行适当的缩放,我们就在前面加一个额外的常数因子\frac{1}{m}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值