ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-10-16 21:02:56  阅读:275  来源: 互联网

标签:函数 -- 学习 神经网络 dz logistic np import numpy


首先是第一周的概论:

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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有