吴恩达深度学习(一)之神经网络和深度学习

第一周 深度学习概论

结构化与非结构化数据

结构化数据: 结构化数据意味着数据的基本数据库,即x(特征)和y都有一个很好的定义
非结构化数据: 比如音频,原始音频或者你想要识别的图像或文本中的内容。这里的特征可能是图像中的像素值或文本中的单个单词。(特征没有明确的定义)

深度学习快速发展的三大原因

1.更快的计算能力
2.更多的数据
3.更好的算法

联系方式

Contact us: feedback@deeplearning.ai

Companies: enterprise@deeplearning.ai

Universities: academic@deeplearning.ai

第二周 神经网络基础

神经网络矩阵设计准则

𝑥:表示一个𝑛𝑥维数据,为输入数据,维度为(𝑛𝑥, 1);
w:表示一个𝑛𝑥维数据,为参数数据,维度为(𝑛𝑥, 1)
𝑦:表示输出结果,取值为(0,1);
(𝑥(𝑖), 𝑦(𝑖)):表示第𝑖组数据,可能是训练数据,也可能是测试数据,此处默认为训练数
据;
𝑋 = [𝑥(1), 𝑥(2), . . . , 𝑥(𝑚)]:表示所有的训练数据集的输入值,放在一个 𝑛𝑥 × 𝑚的矩阵中,其中𝑚表示样本数目;
𝑌 = [𝑦(1), 𝑦(2), . . . , 𝑦(𝑚)]:对应表示所有训练数据集的输出值,维度为1 × 𝑚。
在这里插入图片描述

逻辑回归

定义法则

该课程用右侧定义法则,不用左侧的
在这里插入图片描述

代价函数

在这里插入图片描述

梯度下降运作机制

在这里插入图片描述
最低点左边的斜率<0,右边>0,注意自动迭代到最低点后就会停止迭代。红色部分代表代码中的表示准则

利用计算图计算逻辑回归的梯度下降

注意:计算图中的前向传播与反向传播都需要一步一步来,其实反向传播就是求导的链式法则
公式回顾:
在这里插入图片描述
a = σ ( z ) = 1 1 + e − z a = \sigma (z) = \frac{1}{{1 + {e^{ - z}}}} a=σ(z)=1+ez1
∂ σ ( z ) ∂ z = − ( − e ( − z ) ) ( 1 + e − z ) 2 = 1 1 + e − z × e ( − z ) 1 + e − z = a × ( 1 − a ) \frac{{\partial \sigma (z)}}{{\partial z}} = - \frac{{( - {e^{( - z)}})}}{{{{(1 + {e^{ - z}})}^2}}} = \frac{1}{{1 + {e^{ - z}}}} \times \frac{{{e^{( - z)}}}}{{1 + {e^{ - z}}}} = a \times (1 - a) zσ(z)=(1+ez)2(e(z))=1+ez1×1+eze(z)=a×(1a)

单个训练样本

在这里插入图片描述

多个训练样本
非向量化(循环,能用向量就不用)

在这里插入图片描述

在这里插入图片描述
两重循环,第一重遍历每个输入(1:m),第二层,在每个输入中,都要更新所有参数的dw1,…,dwn,db(1:nx+1)

向量化(要远快于循环)

对比上文的循环
#迭代一千次
#维度说明:dw,db,Y,A,Z,W:(nx,1),X:(x(1),…,x(m)),
x(i) :(nx,1)

for iterator in range(1000):
𝑍 = 𝑤T𝑋 + 𝑏 = 𝑛𝑝. 𝑑𝑜𝑡(𝑤. 𝑇, 𝑋) + 𝑏
𝐴 = 𝜎(𝑍)
𝑑𝑍 = 𝐴 − 𝑌
𝑑𝑤 =1/𝑚∗ 𝑋 ∗ 𝑑z𝑇
𝑑𝑏 =1/𝑚∗ 𝑛𝑝. 𝑠𝑢𝑚(𝑑𝑍)
𝑤: = 𝑤 − 𝑎 ∗ 𝑑𝑤
𝑏: = 𝑏 − 𝑎 ∗ 𝑑b

Python/Numpy 广播机制

(1,n)复制m次,(m,1)复制n次
在这里插入图片描述

在这里插入图片描述

Python/Numpy 矩阵创建与维度验证准则

在这里插入图片描述
注意:第一种是完全错误的,永远不要用,因为它在python 中的维度是(5,),这种绝对不能用,因为可能会发生未知错误,第二种,第三种是可以用的,可以用assert检验维度,发现维度错误,可以多多使用reshape(o(1),非常快)

代码

参考的dalao.
注意,图片要归一化
结果中存在一定的过拟合现象,要加入正则化,以后再说

import numpy as np
import matplotlib.pyplot as plt
from lr_utils import load_dataset

#数据准备
train_set_x,train_set_y,test_set_x,test_set_y,classes=load_dataset()
#查看数据维度
print(train_set_x.shape)
print(train_set_y.shape)
print(test_set_x.shape)
print(test_set_y.shape)
#看一个小猫
plt.imshow(test_set_x_orig[2])
plt.show()
#将输入和标签设置成为你需要的输入维度,这两句一个意思
train_set_x=train_set_x.reshape(train_set_x.shape[0],-1).T
test_set_x=test_set_x.reshape(test_set_x.shape[0],test_set_x.shape[1]*test_set_x.shape[2]*test_set_x.shape[3]).T
print(train_set_x.shape)
print(test_set_x.shape)
#归一化
train_set_x=train_set_x/255
test_set_x=test_set_x/255

#sigmoid
def sigmoid(z):
    return 1/(1+np.exp(-z))

#逻辑回归传播算法(一次迭代)
def propagate(X,Y,W,b):    
    #前向传播
    m=X.shape[1]
    A=sigmoid(np.dot(W.T,X)+b)#(1,12288)*(12288,209)->(1,209)  
    #代价函数
    cost=(-1/m)*np.sum(np.multiply(Y,np.log(A))+np.multiply((1-Y),np.log(1-A)))
    cost = np.squeeze(cost)
    #反向传播
    dz=A-Y
    dw=(1/m)*np.dot(X,dz.T)#(12288,209)*(209,1)
    db=(1/m)*np.sum(dz)    
    return dw,db,cost 

#梯度下降
def Gradient_descent(X,Y,W,b,iteration,learning_rate):
    costs=[]
    for i in range(iteration):
        dw,db,cost=propagate(X,Y,W,b)
        W=W-learning_rate*dw
        b=b-learning_rate*db
        if i%100==0:
            print("迭代{0}次,代价函数为{1}".format(i,cost))
            costs.append(cost)
    return W,b,costs    

#预测结果
def prediction():
#初始化参数都为0
    W=np.zeros((train_set_x.shape[0],1))#(12288,1)
    b=0 
    W,b,costs=Gradient_descent(train_set_x,train_set_y,W,b,2000,0.005)
    
    #展示代价变化
    fig,ax=plt.subplots(figsize=(12,8))
    ax.plot(np.arange(20), costs, 'r')
    ax.set_xlabel("iteration(per hundred)")
    ax.set_ylabel("cost")
    plt.show()
    
    #预测模型
    predict_train_y=np.zeros_like(train_set_y)
    predict_test_y=np.zeros_like(test_set_y)
    A_train=sigmoid(np.dot(W.T,train_set_x)+b)
    A_test=sigmoid(np.dot(W.T,test_set_x)+b)
    
    for i in range(train_set_x.shape[1]):
        predict_train_y[0,i]=1 if A_train[0,i]>0.5 else 0
    for i in range(test_set_x.shape[1]):
        predict_test_y[0,i]=1 if A_test[0,i]>0.5 else 0
    
    #打印训练集与测试集准确率
    print('训练集识别准确率:{0}%'.format(100-np.mean(abs(train_set_y-predict_train_y))*100))
    print('测试集识别准确率:{0}%'.format(100-np.mean(abs(test_set_y-predict_test_y))*100)) 

prediction()       

第三周 浅层神经网络

神经网络的表示

在这里插入图片描述
注意:这是一个两层神经网络,因为输入层不算(规定)

神经网络前向传播的输出

单个样本输入

注意
1.w[1],…,w[4]的维度都是(3,1),b就是ML中的那个偏执单元
2.对于w,可以理解为每一行有与输入相同数量(3个)的参数,如对于w[1][1] 便代表了w11,w21,w31因为输出有4个,所有共有4行

在这里插入图片描述
在这里插入图片描述

多样本输入

注意:
1.横向是训练样本,纵向是隐藏单元
2.z[1](i) 代表了第i个输入样本下的第一个隐藏层(未激活),so on…

在这里插入图片描述

激活函数

种类

在这里插入图片描述
规则:
1.默认选择Relu
2.sigmoid只用于二分类的输出层
3.不同的层次可以选择不同的非线性激活函数

激活函数对应的导数

1.sigmoid:
a = σ ( z ) = 1 1 + e − z a = \sigma (z) = \frac{1}{{1 + {e^{ - z}}}} a=σ(z)=1+ez1
∂ σ ( z ) ∂ z = − ( − e ( − z ) ) ( 1 + e − z ) 2 = 1 1 + e − z × e ( − z ) 1 + e − z = a × ( 1 − a ) \frac{{\partial \sigma (z)}}{{\partial z}} = - \frac{{( - {e^{( - z)}})}}{{{{(1 + {e^{ - z}})}^2}}} = \frac{1}{{1 + {e^{ - z}}}} \times \frac{{{e^{( - z)}}}}{{1 + {e^{ - z}}}} = a \times (1 - a) zσ(z)=(1+ez)2(e(z))=1+ez1×1+eze(z)=a×(1a)

2.tanh:
a = g ( z ) = tanh ⁡ ( z ) = e z − e − z e z + e − z a = g(z) = \tanh (z) = \frac{{{e^z} - {e^{ - z}}}}{{{e^z} + {e^{ - z}}}} a=g(z)=tanh(z)=ez+ezezez
∂ g ( z ) ∂ z = 1 − a 2 \frac{{\partial g(z)}}{{\partial z}} = 1 - {a^2} zg(z)=1a2

3.Relu:
a = g ( z ) = m a x ( 0 , z ) a = g(z) = max(0,z) a=g(z)=max(0,z)
∂ g ( z ) ∂ z = { 0 , i f z < 0 1 , i f z ≥ 0 \frac{{\partial g(z)}}{{\partial z}} = \left\{ \begin{array}{l} 0{\rm{ , if z < 0}}\\ 1{\rm{ }},{\rm{ if z}} \ge {\rm{0 }} \end{array} \right. zg(z)={0,ifz<01,ifz0

4.Leaky Relu:
a = g ( z ) = m a x ( 0.01 z , z ) a = g(z) = max(0.01z,z) a=g(z)=max(0.01z,z)
∂ g ( z ) ∂ z = { 0.01 , i f z < 0 1 , i f z ≥ 0 \frac{{\partial g(z)}}{{\partial z}} = \left\{ \begin{array}{l} 0.01{\rm{ , if z < 0}}\\ 1{\rm{ }},{\rm{ if z}} \ge {\rm{0 }} \end{array} \right. zg(z)={0.01,ifz<01,ifz0

选择非线性激活函数的原因

来看看下图右边的推导:
在这里插入图片描述
我们可以发现,如果选择线性激活函数,那么最后的输出其实就是多个参数矩阵的线性组合,那么不如不要激活函数。
只有在一种情况下,神经元可以使用线性激活函数(g(z)=z):即回归问题里的输出层(如房价预测)

反向传播公式及其推导

这是个两层神经网络,n[0],n[1],n[2]=1分别代表输入层,隐藏层,输出层神经元个数
在这里插入图片描述
注意:反向传播一定要保证维度相同,然后只有符合计算图,自己调整维度,就不会有错
(1个输入样本的)维度,:
x,a[0]:(n[0],1)
dW[1],W[1]:(n[1],n[0]) ; db[1] ,b[1]:(n[1],1)
dz[1],z[1]:(n[1],1) ; da[1],a[1]:(n[1],1)
dW[2],W[2]:(n[2],n[1]) ; db[2] ,b[2]:(n[2],1)
dz[2],z[2]:(n[2],1) ; da[2],a[2],y:(n[2],1)

开始计算
L ( a [ 2 ] , y ) = − y ∗ log ⁡ ( a [ 2 ] ) − ( 1 − y ) ∗ log ⁡ ( 1 − a [ 2 ] ) d a [ 2 ] = ∂ L ( a [ 2 ] , y ) ∂ a [ 2 ] = ( − y a [ 2 ] + y 1 − a [ 2 ] ) d z [ 2 ] = ∂ a [ 2 ] ∂ z [ 2 ] ∗ ∂ L ( a [ 2 ] , Y ) ∂ a [ 2 ] = a [ 2 ] ( 1 − a [ 2 ] ) ∗ ( − y a [ 2 ] + y 1 − a [ 2 ] ) = a [ 2 ] − y d W [ 2 ] = ∂ z [ 2 ] ∂ W [ 2 ] ∗ d z [ 2 ] = d z [ 2 ] a [ 1 ] T d b [ 2 ] = ∂ z [ 2 ] ∂ b [ 2 ] ∗ d z [ 2 ] = d z [ 2 ] d a [ 1 ] = ∂ z [ 2 ] ∂ a [ 1 ] ∗ d z [ 2 ] = W [ 2 ] T ∗ d z [ 2 ] d z [ 1 ] = ∂ a [ 1 ] ∂ z [ 1 ] ∗ d a [ 1 ] = W [ 2 ] T ∗ d z [ 2 ] ∗ g [ 1 ] ′ ( z [ 1 ] ) d W [ 1 ] = ∂ z [ 1 ] ∂ W [ 1 ] ∗ d z [ 1 ] = x T ∗ d z [ 1 ] d b [ 1 ] = ∂ z [ 1 ] ∂ b [ 1 ] ∗ d z [ 1 ] = d z [ 1 ] \begin{array}{l} L({a^{[2]}},y) = - y*\log ({a^{[2]}}) - (1 - y)*\log (1 - {a^{[2]}})\\ d{a^{[2]}} = \frac{{\partial L({a^{[2]}},y)}}{{\partial {a^{[2]}}}} = ( - \frac{y}{{{a^{[2]}}}} + \frac{y}{{1 - {a^{[2]}}}})\\ d{z^{[2]}} = \frac{{\partial {a^{[2]}}}}{{\partial {z^{[2]}}}} * \frac{{\partial L({a^{[2]}},Y)}}{{\partial {a^{[2]}}}} = {a^{[2]}}(1 - {a^{[2]}})*( - \frac{y}{{{a^{[2]}}}} + \frac{y}{{1 - {a^{[2]}}}}) = {a^{[2]}} - y\\ {\rm{d}}{W^{[2]}} = \frac{{\partial {z^{[2]}}}}{{\partial {W^{[2]}}}}*d{z^{[2]}} = d{z^{[2]}}{a^{{{[1]}^T}}}\\ {\rm{d}}{{\rm{b}}^{[2]}} = \frac{{\partial {z^{[2]}}}}{{\partial {b^{[2]}}}}*d{z^{[2]}} = d{z^{[2]}}\\ d{a^{[1]}} = \frac{{\partial {z^{[2]}}}}{{\partial {a^{[1]}}}}*d{z^{[2]}} = {W^{{{[2]}^T}}}*d{z^{[2]}}\\ d{z^{[1]}} = \frac{{\partial {a^{[1]}}}}{{\partial {z^{[1]}}}} * d{a^{[1]}} = {W^{{{[2]}^T}}}*d{z^{[2]}}*{g^{[1]'}}({z^{[1]}})\\ d{W^{[1]}} = \frac{{\partial {z^{[1]}}}}{{\partial {W^{[1]}}}}*d{z^{[1]}} = x^T*d{z^{[1]}}\\ d{b^{[1]}} = \frac{{\partial {z^{[1]}}}}{{\partial {b^{[1]}}}}*d{z^{[1]}} = d{z^{[1]}} \end{array} L(a[2],y)=ylog(a[2])(1y)log(1a[2])da[2]=a[2]L(a[2],y)=(a[2]y+1a[2]y)dz[2]=z[2]a[2]a[2]L(a[2],Y)=a[2](1a[2])(a[2]y+1a[2]y)=a[2]ydW[2]=W[2]z[2]dz[2]=dz[2]a[1]Tdb[2]=b[2]z[2]dz[2]=dz[2]da[1]=a[1]z[2]dz[2]=W[2]Tdz[2]dz[1]=z[1]a[1]da[1]=W[2]Tdz[2]g[1](z[1])dW[1]=W[1]z[1]dz[1]=xTdz[1]db[1]=b[1]z[1]dz[1]=dz[1]
接下来看m个输入样本(结合梯度下降思考)时
X,A[0]:(n[0],m)
dW[1],W[1]:(n[1],n[0]) ; db[1] ,b[1]:(n[1],m)
dZ[1],Z[1]:(n[1],m) ; dA[1],A[1]:(n[1],m)
dW[2],W[2]:(n[2],n[1]) ; db[2] ,b[2]:(n[2],m)
dZ[2],Z[2]:(n[2],m) ; dA[2],A[2],Y:(n[2],m)**
在这里插入图片描述
注意;不用keepdims也可以用reshape

神经网络参数随机初始化的原因

结合上图,如果所有的W都为0,那么所有的A也都为0,那么同一层的dZ将会相同,导致对应得dW里得数都相同,所有参数下降同样的步骤,非常不可取

因此,会有
W2=np.random.randn((n2,n1))*0.01
b2=np.zeros(n2,1)

注意,在神经网络中,如果你使用sigmoid 或者 tahn激活函数,那么W过大会导致Z过大,Z过大会导致激活函数梯度下降很慢(除了最后一层,dZ中有激活函数的导数),影响下降能力。

代码

对一朵画的二元分类,一个隐藏层

import matplotlib.pyplot as plt
import numpy as np
from planar_utils import load_planar_dataset,plot_decision_boundary,sigmoid

#加载并观察数据
X,Y=load_planar_dataset()
print(X.shape,Y.shape)
fig,ax=plt.subplots(figsize=(12,8))
ax.scatter(X[0,:], X[1,:] , c=np.squeeze(Y))#c=np.squeeze(Y),把Y的维度降至(400,)
ax.set_xlabel("x1")
ax.set_ylabel("x2")
plt.show()

初始化参数
def initialization(X,Y,h_number):
    #X:(nx,m),Y;(1,m)
    nx=X.shape[0]#每个输入的特征数
    m=X.shape[1]#一共输入的样本数
    
    n0,n1,n2=nx,h_number,1#神经元维度(nx,h_number,1)
    
    #参数的随机初始化
    np.random.seed(2)
    W1=np.random.randn(n1,n0)*0.01#randn返回相应维度的标态分布
    b1=np.zeros((n1,1))
    W2=np.random.randn(n2,n1)*0.01
    b2=np.zeros((n2,1))
    return W1,b1,W2,b2,m

#传播(包含代价函数计算)
def propagate(X,Y,W1,b1,W2,b2,m):
    #前向传播
    A1=np.tanh(np.dot(W1,X)+b1)#(n1,m)
    A2=sigmoid(np.dot(W2,A1)+b2)#(n2,m),二元分布时输出层可以使用sigmoid
    
    #代价计算
    cost= (-1/m)*np.sum(np.multiply(Y,np.log(A2))+np.multiply((1-Y),np.log(1-A2)))
    
    #反向传播
    dz2=A2-Y#(n2,m)
    dw2=(1/m)*np.dot(dz2,A1.T)#(n2,m)*(m,n1)->(n2,n1)
    db2=(1/m)*np.sum(dz2,axis=1,keepdims=True)#(n2,1),axis=1表示按行合并
    dz1=np.multiply(np.dot(W2.T,dz2),1-(A1**2))#(n1,n2)*(n2,m)->(n1,m)
    dw1=(1/m)*np.dot(dz1,X.T)
    db1=(1/m)*np.sum(dz1,axis=1,keepdims=True)#(n1,1)
    return dw2,db2,dw1,db1,cost

#构建nn模型
def nn_model(X,Y,h_number,learning_rate,iteration):
    W1,b1,W2,b2,m=initialization(X,Y,h_number)
    
    for i in range(1,iteration+1):
        dw2,db2,dw1,db1,cost=propagate(X,Y,W1,b1,W2,b2,m)
        W2=W2-learning_rate*dw2
        b2=b2-learning_rate*db2
        W1=W1-learning_rate*dw1
        b1=b1-learning_rate*db1
        #if i%1000==0:
            #print('第{0}轮次的代价为{1}'.format(i,cost))
            
    return W1,b1,W2,b2

#对数据进行预测
def predict(X,W1,b1,W2,b2):
    A1=np.tanh(np.dot(W1,X)+b1)#(n1,m)
    A2=sigmoid(np.dot(W2,A1)+b2)#(n2,m)
    
    prediction=np.round(A2)#4舍5入,大于0.5为1,小于0.5为0
    return prediction

#变换隐藏层来看看效果
plt.figure(figsize=(16, 32))
hidden=[4,7,9,50,78,100]
for i,e in enumerate(hidden):
    W1,b1,W2,b2=nn_model(X,Y,e,0.5,10000)
    #绘制边界
    plt.subplot(5,2,i+1)
    plt.title("Decision Boundary for hidden layer size " + str(e))
    plot_decision_boundary(lambda x: predict(x.T,W1,b1,W2,b2), X, np.squeeze(Y))
    pre_y=predict(X,W1,b1,W2,b2)
    accuracy=np.squeeze((np.dot(Y,pre_y.T)+np.dot(1-Y,1-pre_y.T))/Y.shape[1]*100)
    print('隐藏层数为{0}时,准确率为{1}%'.format(e,accuracy))

二元分类的边界代码:

二元分类代码精雕
def plot_decision_boundary(model, X, y):
    # Set min and max values and give it some padding
    x_min, x_max = X[0, :].min() - 1, X[0, :].max() + 1
    y_min, y_max = X[1, :].min() - 1, X[1, :].max() + 1
    h = 0.01
    # Generate a grid of points with distance h between them,绘制出网格图,网格取小,因为更光滑
    #若x为[1,2,3],y为[4,5],那么就会绘制出(1,4),(2,4),(3,4),(1,5),(2,5),(3,5),即xx=[[1,2,3],[1,2,3]],yy=[[4,4,4],[5,5,5]]
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
    # Predict the function value for the whole grid,np.c_:按列合并
    Z = model(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    # Plot the contour and training examples,针对每个输入的xx,yy,Z代表对应得高度,不同高度下会显示出不同得颜色
    plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)
    plt.ylabel('x2')
    plt.xlabel('x1')
    plt.scatter(X[0, :], X[1, :], c=y, cmap=plt.cm.Spectral)

第四周 深层神经网络

多层神经网络的传播算法及其各种参数的矩阵维度规则

在这里插入图片描述
参数规则
n[0]=2 , n[1]=3 , n[2]=5 , n[3]=4 , n[4]=2 , n[5]=1
l=for i in range(1,6),m:set of input
dW[l],W[l]:(n[l],n[l-1])
db[l],b[l]:(n[l],1)
dA[l],A[l]:(n[l],m)
dZ[l],Z[l]:(n[l],m)
前向传播规则
输入A[l],输出A[l]
Z[l]=np.dot(W[l],A[l-1])+b[l]
A[l]=g[l](Z[l])
将输出可以保存至一个缓存中,后续继续使用
反向传播规则
时刻想计算图,就不会错
对于逻辑回归,使用交叉熵代价函数时
L:代表最后一层的层次,例如有3个隐藏层时,L=4
dA[L]即在代价函数中,对每一个a[L](i)求偏导
dA[L]=dL(Y,A[L])/dA[L]=(da[L](1),…,da[L](m)
da[L](1)=-y(1)/a[L](1)+(1-y(1))/(1-a[L](1)),依次。。。

就是说不同的代价函数时下你要自己算dA[L]
对于输出层时sigmoid激活函数的dZ[L]=A[L]-Y
推导:dZ[L]=np.multiply(dA[L],g[L]’(Z[L]))
da[L](1) * a[L](1)*(1-a[L](1)),…,da[L] * a[L](m) * (1-a[L](m))=( a[L](1) - y(1)),…,a[L](m) - y(m))

输入dA[l],输出dA[l-1]
dZ[l]=np.multiply(dA[l],g[l]’(Z[l]))
dW[l]=(1/m)*np.dot(dZ[l],A[l-1].T)
db[l]=(1/m)*np.sum(dZ[l],axis=1,keepdim=True)
dA[l-1]=np.dot(W[l].T,dZ[l])
如图所示:
在这里插入图片描述

代码(随机NN)

手写一个设计隐藏层列表,就可训练的NN(多层神经网络),识别小猫猫

#加载数据与预处理
import numpy as np
import matplotlib.pyplot as plt
from lr_utils import load_dataset

train_set_x, train_set_y, test_set_x, test_set_y, classes=load_dataset()
print(train_set_x.shape)
print(train_set_y.shape)
print(test_set_x.shape)
print(test_set_y.shape)
#print(test_set_y)

plt.imshow(test_set_x[2])
plt.show()

#我们输入数据,转化为合适的矩阵
train_set_x=train_set_x.reshape(train_set_x.shape[0],-1).T
test_set_x=test_set_x.reshape(test_set_x.shape[0],-1).T
print(train_set_x.shape)
print(test_set_x.shape)

#归一化
train_set_x=train_set_x / 255
test_set_x=test_set_x / 255

#为多个隐藏层的神经网络初始化参数
def initialization(X,Y,hidden_dim):
    np.random.seed(3)
    parameters={}
    n=len(hidden_dim)
    
    parameters['n0']=X.shape[0]
    for i in range(1,n+1):
        parameters['n'+str(i)]=hidden_dim[i-1]
        parameters['W'+str(i)]=np.random.randn(parameters['n'+str(i)],parameters['n'+str(i-1)])/np.sqrt(parameters['n'+str(i-1)])
        parameters['b'+str(i)]=np.zeros((parameters['n'+str(i)],1))
    #输出层只有一个元素
    parameters['n'+str(n+1)]=Y.shape[0]
    parameters['W'+str(n+1)]=np.random.randn(parameters['n'+str(n+1)],parameters['n'+str(n)])/np.sqrt(parameters['n'+str(n)])
    parameters['b'+str(n+1)]=np.zeros((parameters['n'+str(n+1)],1))
    
    return parameters,n

#sigmoid激活函数
def sigmoid(x):
    return 1/(1+np.exp(-x))

#Rele激活函数:
def relu(z):
    return np.maximum(0,z)
     
#前向传播(计算代价函数),除了输出层以外(因为是二元分类,所以输出层可以用sidmoid),一律使用Relu激活单元
def forward_propogate(X,Y,hidden_dim,parameters,n):
    cache={}
    cache['A0']=X
    for i in range(1,n+2):
        cache['Z'+str(i)]=np.dot(parameters['W'+str(i)],cache['A'+str(i-1)])+parameters['b'+str(i)]
        if i==n+1:
            cache['A'+str(i)]=sigmoid(cache['Z'+str(i)])
        else:
            cache['A'+str(i)]=relu(cache['Z'+str(i)])
    #交叉熵代价函数
    cost=(-1/Y.shape[1])*np.sum(np.multiply(Y,np.log(cache['A'+str(n+1)]))+np.multiply((1-Y),np.log(1-cache['A'+str(n+1)])))
    cost=np.squeeze(cost)
    return cache,cost,parameters,n   

#反向传播
def backward_propogate(X,Y,hidden_dim,parameters,n):
    cache,cost,parameters,n=forward_propogate(X,Y,hidden_dim,parameters,n)
    #注意:要倒序,reversed()一下
    for i in reversed(range(1,n+2)):
        if i==n+1:
            cache['dA'+str(i)]=cache['A'+str(i)]-Y
            cache['dZ'+str(i)]=np.multiply(cache['dA'+str(i)],np.multiply(cache['A'+str(i)],(1-cache['A'+str(i)])))
            cache['dW'+str(i)]=(1/Y.shape[1])*np.dot(cache['dZ'+str(i)],cache['A'+str(i-1)].T)
            cache['db'+str(i)]=(1/Y.shape[1])*np.sum(cache['dZ'+str(i)],axis=1,keepdims=True)
            cache['dA'+str(i-1)]=np.dot(parameters['W'+str(i)].T,cache['dZ'+str(i)])
        #不用求dA0
        if i==1:
            cache['dZ'+str(i)]=np.array(cache['dA'+str(i)],copy=True)
            cache['dZ'+str(i)][cache['Z'+str(i)] <= 0]=0
            cache['dW'+str(i)]=(1/Y.shape[1])*np.dot(cache['dZ'+str(i)],cache['A'+str(i-1)].T)
            cache['db'+str(i)]=(1/Y.shape[1])*np.sum(cache['dZ'+str(i)],axis=1,keepdims=True)
        else:
            cache['dZ'+str(i)]=np.array(cache['dA'+str(i)],copy=True)
            cache['dZ'+str(i)][cache['Z'+str(i)]<=0]=0
            cache['dW'+str(i)]=(1/Y.shape[1])*np.dot(cache['dZ'+str(i)],cache['A'+str(i-1)].T)
            cache['db'+str(i)]=(1/Y.shape[1])*np.sum(cache['dZ'+str(i)],axis=1,keepdims=True)
            cache['dA'+str(i-1)]=np.dot(parameters['W'+str(i)].T,cache['dZ'+str(i)])
    
    return cache,cost,parameters,n  

#拥有了前向与反向传播算法,现在构建一个可以更新参数的函数
def update(X,Y,hidden_dim,learning_rate,parameters,n):
    cache,cost,parameters,n=backward_propogate(X,Y,hidden_dim,parameters,n)
    for i in range(1,n+2):
        parameters['W'+str(i)]=parameters['W'+str(i)]-learning_rate*cache['dW'+str(i)]
        parameters['b'+str(i)]=parameters['b'+str(i)]-learning_rate*cache['db'+str(i)]
    return cache,cost,parameters,n

#ok,开始构建万能NN网络模型
def model_random_nn(X,Y,hidden_dim,learning_rate,iteration):
    parameters,n=initialization(X,Y,hidden_dim)
    for i in range(1,iteration+1):
        cache,cost,parameters,n=update(X,Y,hidden_dim,learning_rate,parameters,n)
        if i%100==0:
            print('第{0}次迭代的代价为{1}'.format(i,cost))
    return parameters,n

#模型构建好后,返回了梯度下降以后的参数,开始预测模型:
def predict(X,Y,hidden_dim,parameters,n):
    cache,cost,parameters,n=forward_propogate(X,Y,hidden_dim,parameters,n)
    pre_y=np.zeros_like(cache['A'+str(n+1)])
    pre_y[cache['A'+str(n+1)]>0.5]=1
    pre_y[cache['A'+str(n+1)]<=0.5]=0
    precision=(np.sum(np.multiply(Y,pre_y))+np.sum(np.multiply((1-Y),(1-pre_y))))/Y.shape[1]
    print('识别准确率为{0}%'.format(precision*100))

#开始干活吧![12,7]
hidden_dim=[29,9,7]
learning_rate=0.0075
iteration=2500
parameters,n=model_random_nn(train_set_x,train_set_y,hidden_dim,learning_rate,iteration)
predict(test_set_x,test_set_y,hidden_dim,parameters,n)
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值