其他分享
首页 > 其他分享> > 神经网络与深度学习--学习笔记一

神经网络与深度学习--学习笔记一

作者:互联网

首先是第一周的概论:

1、什么是神经网络:

神经网络是一种受大脑思考方式启发而诞生出的强大的学习算法。

吴老师举了一个例子来进行解释:

如果仅仅用房屋面积去预测房价,预测房价的函数就是许多文献经常出现的函数,简称ReLU函数,全称是“修正线性单元” 。

这是一个很小的单一神经元网络,大的神经网络通过堆叠小网络形成。

而如果出现了房屋的其他特征:

                                

 那么每一个圆圈都可能是一个修正线性函数,只需要提供足够多的x和y作为训练样本,神经网络就会自动进行学习,也就是深度学习。

2、用神经网络进行监督学习

       监督学习是从标记的训练数据来推断一个功能的机器学习任务。我们可以输入一个对象(矢量)和一个期望的输出值(监督信号),通过一组实验数据来训练机器的相应性能。以下是一个例子:

        我们的输入与输出是机器最终能够应用到日常生活中。这种用二维表结构来逻辑表达的数据为结构性数据,他的数据每一个特征都有着清晰的定义,相反,图像和文本的内容就是非结构性数据,如图:

        与结构化数据相比,计算机理解起来更复杂,但正是深度学习令人着迷,吸引人去改进更新技术的地方,不仅能创造短期经济价值,更能使人们的生活变得更加丰富多彩。

3、 为什么深度学习会兴起?

 

 用一个图就能解决问题

       运用神经网络所能达到的表现 能够超过传统算法的表现,并且数据越大效果越好。

而要在神经网络上获得更好的表现,无非是训练更大的神经网络,或者提供更多的数据。

因此在深度学习崛起的初期,是数据和计算规模的发展,而最近这几年则是算法的发展。

即从斜率变缓的sigmoid函数转变为梯度恒定不变的ReLU函数。

第二周、神经网络基础

2.1二分分类

拟用此章节来引出“logistic“回归算法。

以猫猫的图片为例

                是猫猫则输出“1”,非猫则输出“0” 。用y来作为该输出的结果标签。

                                        那么计算机是怎么做到识别一张图片的呢?

计算机保存一张图片,就是保存三个独立矩阵:

 分别表示红绿蓝三原色(三矩阵大小相同),数字的大小表示色素的强度。

        最终用一个很长的特征向量x把所有色素的强度表示出来,现排红色,再依次排绿色、蓝色。

如果矩阵是64*64大小的,那么x的维度是64*64*3,表示三个矩阵的元素数量,用n_x来表示特征向量的维度,为了简洁,可以写作n。

        二分分类问题的目标是训练出一个分类器,它以特征向量x作为输入,以标签y(0或1)作为输出,        而我们负责提供m个训练样本,有时为了强调或区分,用m_train表示训练样本的个数,用m_test表示测试集的样本个数。

        最后,用更紧凑的符号表示训练集,我们定义为矩阵X,将向量x作为行向量堆叠:

        X是一个n_x*m 矩阵,表示以特征向量的维度为行,以训练样本的个数为列的矩阵。注意:

一个训练样本可能有多个x,所以行列不一定相等。用Python实现时,是一个X.shape命令,X.shape=(n_x,m).

        接下来把标签y放入另一个矩阵Y中作为行向量堆叠,Y是一个1*m矩阵,同样,

Y.shape=(1,m)。

2.2logistic回归算法

        logistic是一个学习算法,用于监督学习问题中输出标签y是0或1时。

依然以猫猫举例,你需要一个算法去给出一个预测值来判断一张图片是不是猫图,你更希望这个预测值是一个概率,因此有了“y帽”:

 使当x满足条件时,y的输出为1。

        假设logistic的参数为w,也是一个n_x维向量,b是一个实数。

        已知参数w,b和输入x,如何求出预测值“y帽”呢?首先我们用线性函数来尝试:

 但这不可行,因为“y帽”作为概率值应该介于0和1之间,而w和b可能非常大,或为负值,那么“y帽”就没有意义了。所以在logistic回归中,我们引入一个sigmoid函数:

                                              图像:

方程:

 当z趋于正无穷时,sigmoid(z)趋于1;当z趋于负无穷时,sigmoid(z)趋于0;当z=0时,sigmoid(z)=0.5.“y帽”就变成

这样:

                                 使得“y帽”始终介于0和1之间。

2.3logistic回归损失函数

 符号规定:用上标^(i)表示x或y或z与第i个训练样本有关。

定义损失(误差)函数:L(“y帽”,y)来衡量y的预测值和实际值有多接近,该函数为:


 

 他有着和

相似的作用 ,但更利于后续凸的优化。

解释:当y=1时,L(“y帽”,y)=-y*log(“y帽”),要使损失尽量小,则“y帽”应尽量大,而“y帽”介于1和0之间,故使“y帽”为1,与y差距最小,当y=0时同理。

损失函数是在单个样本中定义的,他衡量了计算机在单个训练样本中的表现。

而成本函数则是计算机在全体训练样本的表现。定义成本函数:

即所有损失函数的平均值。我们要做的是找到合适的参数w和b,使得成本函数J尽量小。

2.4梯度下降法

承接上文,我们要找到w和b,使得成本函数尽量小。

         横轴就是w和b,曲面的高度代表J在不同的w和b中所对应的值。最下面的红点就是合适的w和b所对应的J的最小值。可以看到,成本函数J是一个凸函数,无论从哪个点开始都能找到J的最低点,凸函数的性质就是我们利用logistic回归算法的重要原因之一。

        梯度下降法所做的就是,从初始点开始,从最陡的下坡方向走一步,停一下,重新确定方向,这是梯度下降的一次迭代,经过多次迭代,很有希望收敛到全局的最优解,就是达到最低点所需的最少步骤。

        为了方便画,先忽略b 。使用“:=”表示更新w。        w:=w-α*dJ(w)/dw

α表示机器的学习率,dJ(w)/dw即为导数,就是对w的更新和变化率。开始编写代码时,会用符号规定,用dw表示整个导数,即:w:=w-α*dw。

        证明他的可行性,从右边取一点,当w很大时倒数很大,w减少,点左移;

        从左边取一点,当w很小时导数为负值,w增加,点右移。

        既然可行,代入b,     w:=w-α*dJ(w,b)/dw       b:=w-α*dJ(w,b)/db

        这就是梯度下降法的公式及应用。

2.5导数

        f(a)的导数f '(a)=df(a)/da.结束了。。。。。。

2.6更多倒数的例子

        1、导数就是斜率

        2、导数公式

 

 2.7计算图

流程图是用蓝色箭头画出来的,从左到右的计算,而要求导数,则要通过红色箭头从右到左。

2.8计算图的导数计算 

 同上。

2.9logistic回归中的梯度下降法

回想一下logistic回归的公式:

 

 假设只有两个训练样本x_1,x_2,则z=w_1*x_1+w_2*x_2+b。流程图可以写成:

损失函数L(a,y)的导数“da”=dL(a,y)/da =-y/a+(1-y)/(1-a)。算出“da”后,可以向前一步,算出“dz”

“dz”=dL/dz=a-y,然后再向前一步,算出“dw1”=dL/dw1=x1*dz,"dw2"=dL/dw2=x2*dz,"db"=dz。

然后更新w1:=w1-α*"dw1",w2=w2-α*"dw2",b=b-α*"db"。

2.10m个样本的梯度下降(终于讲到代码了!!!!)

 J=0;dw1=0;dw2=0;db=0

For i=1 to m       #m为输入样本数

        z^i=w^T*x^i+b                #对应为第i个样本

        a^i=sigmoid(z^i)

        J+=-[y^i*loga^i+(1-y^i)log(1-a^i)]

        dz^i=a^i-y^i

        dw1+=x1^i*dz^i

        ......     

        dwn+=xn^i*dz^i                #n为特征数,即x的维度

        db+=dz^i

J/=m                                        #得到总和后,计算平均值

dw1/=m;...dwn/=m;                                   #应用梯度下降法

“dw1”=dJ/dw1 ... "dwn"=dJ/dwn

w1:=w1-α*dw1

...

wn:=wn-α*dwn

b:=b-α*db

2.11向量化

python代码的向量化能十分有效的缩短程序运行的时间,当代码变得复杂时,这种差距会更加明显。这是向量化的版本:

import time                           #导入time库
import numpy as np                    #导入numpy库
a=np.random.rand(1000000)             #创建两个1000000维度的数组
b=np.random.rand(1000000)
tic=time.time()                       #记录所用时间
c=np.dot(a,b)
toc=time.time()
print(str(1000*(toc-tic))+"ms")       #输出所用时间

输出结果为(我的输出比老师慢好多):

这是非向量化的版本:

import time
import numpy as np
a=np.random.rand(1000000)
b=np.random.rand(1000000)
c=0
tic=time.time()    
for i in range(1000000):            #用循环来增加
    c+=a[i]*b[i]
toc=time.time()
print(str(1000*(toc-tic))+"ms")

输出结果为:

虽然慢好多,但还是得出向量化更加省时间的结论了。 

2.12向量化的更多例子

如果可以,尽量避免for循环,如果可以找到一个内置函数,或者找出其他方法计算循环,通常比直接for循环要快。

np.zeros函数——一维:

import numpy as np
a=np.zeros(3)            #创建一维数组,含有三个0
print(a)

输出结果为:[0. 0. 0.]。

二维:

import numpy as np
a=np.zeros((2,3))            #表示2行3列
print(a)

输出结果为:[[0. 0. 0.]

                       [0. 0. 0.]] 。

若不注明数据类型,默认为浮点型,若想设置其他数据类型:

import numpy as np
a=np.zeros((2,3),dtype=int)        #运用dtype转换
print(a)

输出结果为:[[0 0 0]

                       [0 0 0]]。

要实现如图效果:

用非向量化的版本:

import numpy as np
u=np.zeros((n,1))
for i in range(n)
    u=math.exp(v[i])

用向量化的版本:

import numpy as np
u=np.exp(v)

 np.exp(v)是把数组中每一个数n变成e^n;np.abs(v)是取绝对值;

np.log(v)是取对数;np.maximum(v,0)是将v中所有元素与0比较,输出最大值;

np.v**2是v中所有元素的平方;np.1/v就是每个元素求倒数。

非向量化的版本:

for i in range(n)
    dwi=0
for i in range(n)
    dwi+=x^i*dz^i
for i in range(n)
    dwi/=m

向量化的版本:
 

import numpy as np
dw=np.zeros((n,1))
dw+=x^i*dz^i
dw/=m

2.13向量化logistic回归

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

2.14向量化logistic回归的梯度下降

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

A=sigmoid(Z),

dZ=A-Y,

dw=1/m*X*dZ.T,

db=1/m*np.sum(dz),

w:=w-α*dw,

b:=b-α*db.

2.15Python中的广播

这是一个计算卡路里百分比的例子:

import numpy as np
A=np.array([[54.0,12.0,24.0],
            [36.0,45.0,76.0],
            [0.0, 22.0,35.0]])
cal=A.sum(axis=0)                    #axis=0表示列运算,同理axis=1表示行运算
percentage=100*A/cal
print(percentage)

这样就可以输出每一列中的数占这一列总和的百分数。

再举一个广播的例子:

import numpy as np
A=np.array([[1],
            [2],
            [3],
            [4]])
B=A+100
print(B)

输出的结果是[[101]

                       [102]

                       [103]

                       [104]],

代码中的100就是之前的参数b,它能自动转化为与前者相同格式的矩阵。

如果是一个m*n的矩阵加上一个1*n的矩阵,它会将后者复制m次,然后再将它们相加,

不是倍数你就失败了。。所以上方的100就可以看作1*1的矩阵。

2.16关于python/numpy向量的说明

        调试bug的技巧:a=np.random.randn(5)得到的a是一个秩为1的数组。suo

        而:a=np.random.randn(5,1)得到的a是一个5*1的矩阵。输出结果上,两者也有所不同:

前者只有一对中括号,而后者有两对;前者的a.shape得到的是(5,),后者的a.shape得到的是(5,1);

前者的转置是他本身,而后者的转置则为1*5的矩阵。

ps:要简化代码,不要使用秩为1的数组。可以随意插入assert(a.shape==(m,n))的声明,来仔细检查数组和矩阵的维度。

2.17Jupyter/Ipython笔记本的快速指南

        "run cell"可以运行一个单元格,用coursera打开后,要注意代码写在START CODE和END CODE之间。用"shift"+"enter"可以直接执行单元格。如果出现意外导致内核宕机,点击"kernel--restart"可以重启内核。

*2.18logistic损失函数的解释*

        约定”y帽“=P(y=1|x)(在给定的x条件下,y=1的概率为”y帽“),反过来说,y=0的概率为1-”y帽“,可以将两个公式合成一个:P(y|x)=”y帽“^y*(1-"y帽")^(1-y)。又因为log函数是严格单调递增的函数,log(P(y|x))=log(”y帽“^y*(1-"y帽")^(1-y))=y*log"y帽"+(1-y)*log(1-"y帽"),这是因为我们需要最小化损失函数,故往前加个负号,最小化损失函数就是log(y|x)的最大值。

        对于m个样本,所有样本的联合概率等于这些样本概率的乘积,即:P(labels in traing set)=Π(i=1 to m)(P(y^i|x^i)),两边同取对数,等式不变,化为log(P(labels in traing set))=

log(∑(i=1 to m)P(y^i|x^i))=    -∑(i=1 to m)L(y^i|x^i),也就得到了成本函数J,由于我们需要最小化成本函数,不使用最大似然概率,因此去掉负号,为了方便,对J进行缩放,故

J=1/m*∑(i=1 to m)L(y^i|x^i)。

                

标签:函数,--,学习,神经网络,dz,logistic,np,import,numpy
来源: https://blog.csdn.net/zbrmyyds/article/details/120730645