【超详细】【吴恩达课后作业】Course 1-神经网络与深度学习-第四周编程作业

前言

       最近在学习吴恩达的深度学习课程,关于《神经网络和深度学习》已经学习完,刚编写完最后一周的作业,这次任务主要是设计一个L层网络,每次网络的节点数也可以自己设置,现附上整个设计过程,供大家学习讨论!若有不对的地方,希望大家不吝赐教,谢谢!

      

一、整个流程

1、处理数据

先下载数据:点这里,提取码:smqn

提取数据,得到训练集,训练标签,测试集,测试标签,类别

import numpy as np
import h5py #与H5文件中存储的数据集进行交互的常用软件包


def load_dataset():
    train_dataset=h5py.File('datasets/train_catvnoncat.h5','r')
    train_set_x_orig=np.array(train_dataset['train_set_x'][:])
    train_set_y_orig=np.array(train_dataset['train_set_y'][:])
    
    test_dataset=h5py.File('datasets/test_catvnoncat.h5','r')
    test_set_x_orig=np.array(test_dataset['test_set_x'][:])
    test_set_y_orig=np.array(test_dataset['test_set_y'][:])
    
    classes=np.array(test_dataset['list_classes'][:])
    
    train_set_y_orig=train_set_y_orig.reshape((1,train_set_y_orig.shape[0]))
    test_set_y_orig=test_set_y_orig.reshape((1,test_set_y_orig.shape[0]))
    
    return train_set_x_orig,train_set_y_orig,test_set_x_orig,test_set_y_orig,classes

处理数据

train_x,train_y,test_x,test_y,classes=load_dataset()

train_m=train_y.shape[1]
test_m=test_y.shape[1]
picture_size=train_x.shape[1]

print('训练集的大小:'+str(train_m))
print('测试集的大小:'+str(test_m))
print('训练集的维数:'+str(train_x.shape))
print('测试集的维数:'+str(test_x.shape))
print('训练集标签的维数:'+str(train_y.shape))
print('测试集标签的维数:'+str(test_y.shape))

train_set_x_flatten=train_x.reshape(train_x.shape[0],-1).T
test_set_x_flatten=test_x.reshape(test_x.shape[0],-1).T

train_x=train_set_x_flatten/255
test_x=test_set_x_flatten/255

print('训练集的维数:'+str(train_x.shape))
print('测试集的维数:'+str(test_x.shape))

 对训练集和测试集数据做简单的处理,进行平铺和归一化

可以得到如下信息:

训练集的大小:209
测试集的大小:50
训练集的维数:(209, 64, 64, 3)
测试集的维数:(50, 64, 64, 3)
训练集标签的维数:(1, 209)
测试集标签的维数:(1, 50)
训练集的维数:(12288, 209)
测试集的维数:(12288, 50)

扫描二维码关注公众号,回复: 6513669 查看本文章

2、设计网络大小

设计L层网络,注意网络层不包括输入层,只包括隐藏层和输出层,并设计每层的节点数,在这里我们把输入层记为第0层。

#得到网络的层数和每一层的单元节点数
def net_size(l,X,n):
    
    net_dims={}
    net_dims[0]=X.shape[0]
    
    for i in range(1,l+1):
        net_dims[i]=n[i-1]
    
    print('一共有:%d层网络' % l)
    print('每一层分别对应多少节点如下:')
    print(net_dims)
    
    return l,net_dims
#测试下
l=3
n=[4,3,1]
l,net_dims=net_size(l,train_x,n)

结果如下:

一共有:3层网络
每一层分别对应多少节点如下:
{0: 12288, 1: 4, 2: 3, 3: 1}

3、激活函数

关于隐藏层采取Relu激活函数,输出层采取sigmoid函数

#定义隐藏层的激活函数
def relu(z):
    
    s=np.maximum(0,z)
    
    return s

#定义输出层的激活函数
def sigmoid(z):
    
    s=1/(1+np.exp(-z))
    
    return s

4、初始化w和b

在对变量进行初始化时,一定要注意变量的维度

w^{[l]}:(n^{[l]},n^{[l-1]})b^{[l]}:(n^{[l]},1)

#初始化w和b
def init_w_b(l,net_dims):
    
    parms={}
    np.random.seed(1)
    
    for i in range(1,l+1):
        
        str1='w'+str(i)
        parms[str1]=np.random.rand(net_dims[i],net_dims[i-1])*0.01
        ch='b'+str(i)
        parms[ch]=np.zeros(shape=(net_dims[i],1))
        
        assert(parms[str1].shape==(net_dims[i],net_dims[i-1]))
        assert(parms[ch].shape==(net_dims[i],1))
    

    return parms

5、前向传播

Z^{[l]}:(n^{[l]},m)A^{[l]}:(n^{[l]},m)

Z^{[l]}=W^{[l]}A^{[l-1]}+b^{[l]}

A^{[l]}=g^{[l]}(Z^{[l]})

在这里有两点需要注意:(1)除了输出层激活函数是sigmoid,前面的激活函数是relu。(2)Z^{[1]}=W^{[1]}X+b^{[1]}在这里得单独出来计算,带入X代替A^{[0]}

#前向传播
def forward(l,parms,X,Y,net_dims):
    
    A={}
    Z={}
    
    for i in range(1,l+1):
        
        A[i]=np.zeros(shape=(net_dims[i],Y.shape[1]))
        Z[i]=np.zeros(shape=(net_dims[i],Y.shape[1]))
    
    Z[1]=np.dot(parms['w1'],X)+parms['b1']
    A[1]=relu(Z[1])
    
    
    for i in range(2,l):
        
        Z[i]=np.dot(parms['w'+str(i)],A[i-1])+parms['b'+str(i)]
        A[i]=relu(Z[i])
        
    Z[l]=np.dot(parms['w'+str(l)],A[l-1])+parms['b'+str(l)]
    A[l]=sigmoid(Z[l])
    
    A_Z={'A':A,
         'Z':Z}
    
    return A_Z

6、损失函数

J=-\frac{1}{m}\sum_{i=0}^{m}(Y^{(i)}log(A^{[l](i)})+(1-Y^{(i)})log(1-A^{[l](i)}))

#定义损失函数
def cost_function(Y,A_Z,l):
    
    m=Y.shape[1]
    
    A=A_Z['A']
    A_last=A[l]
    
    cost=(-1/m)*(np.sum(Y*(np.log(A_last))+(1-Y)*(np.log(1-A_last))))
    
    return cost

7、反向传播

dZ^{[l]}:(n^{[l]},m)dW^{[l]}:(n^{[l]},n^{[l-1]})db^{[l]}:(n^{[l]},1)

(1) l=L

dZ^{[l]}=A^{[l]}-Y

dW^{[l]}=\frac{1}{m}dZ^{[l]}(A^{[l-1]})^{T}

db^{[l]}=\frac{1}{m}np.sum(dZ^{[l]},axis=1,keepdims=True)

(2) l从L-1到2循环:

dZ^{[l]}=(dW^{[l+1]})^{T}dZ^{[l+1]}*g^{'[l]}(Z^{[l]})

dW^{[l]}=\frac{1}{m}dZ^{[l]}(A^{[l-1]})^{T}

db^{[l]}=\frac{1}{m}np.sum(dZ^{[l]},axis=1,keepdims=True)

注意这里的g^{'[l]}(Z^{[l]})=relu(Z^{[l]})

(3) l=1时

dZ^{[1]}=(dW^{[2]})^{T}dZ^{[2]}*g^{'[1]}(Z^{[1]})

dW^{[1]}=\frac{1}{m}dZ^{[1]}X^{T}(这里是X,所以单独处理)

db^{[1]}=\frac{1}{m}np.sum(dZ^{[1]},axis=1,keepdims=True)

#定义后向传播
def backward(A_Z,Y,l,net_dims,parms,X):
    
    A=A_Z['A']
    Z=A_Z['Z']
    m=Y.shape[1]
    dZ={}
    dw={}
    db={}
    g={}
    
    #初始化
    for i in range(1,l+1):
        
        dZ[i]=np.zeros(shape=(net_dims[i],Y.shape[1]))
        dw[i]=np.zeros(shape=(net_dims[i],net_dims[i-1]))
        db[i]=np.zeros(shape=(net_dims[i],1))
        g[i]=np.zeros(shape=(net_dims[i],Y.shape[1]))
        
    dZ[l]=A[l]-Y
    
    while(l):
        
        dw[l]=(1/m)*(np.dot(dZ[l],A[l-1].T))
        db[l]=(1/m)*(np.sum(dZ[l],axis=1,keepdims=True))
        l-=1
        
        if l==1:
            break
        
        g[l]=relu(Z[l])
        dZ[l]=np.dot((parms['w'+str(l+1)]).T,dZ[l+1])*g[l]
        
    g[1]=relu(Z[1])
    dZ[1]=np.dot((parms['w2']).T,dZ[2])*g[1]
    dw[1]=(1/m)*(np.dot(dZ[1],X.T))
    db[1]=(1/m)*(np.sum(dZ[1],axis=1,keepdims=True))
    
    grads={'dw':dw,
           'db':db}
    
    return grads

8、优化

W^{[l]}=W^{[l]}-\alpha*dW^{[l]}

b^{[l]}=b^{[l]}-\alpha *db^{[l]}

#优化
def optimize(parms,l,net_dims,X,Y,iterations=2000,learning_rate=0.5,print_flag=False):
   
    costs=[]
    
    for j in range(iterations):
        
        A_Z=forward(l,parms,X,Y,net_dims)
        cost=cost_function(Y,A_Z,l)
        grads=backward(A_Z,Y,l,net_dims,parms,X)
        
        for i in range(1,l+1):
            parms['w'+str(i)]=parms['w'+str(i)]-learning_rate*grads['dw'][i]
            parms['b'+str(i)]=parms['b'+str(i)]-learning_rate*grads['db'][i]
            
        if j%100==0:
            costs.append(cost)
            
        if (print_flag) and (j%100==0):
            print('迭代次数:%d,损失值:%f' % (j,cost))
            
    return parms,grads,costs

9、预测

\left\{\begin{matrix} abs(A-Y)>0.5 &predict=1 \\ else & predict=0 \end{matrix}\right.

#预测
def predict(parms,X,l,Y,net_dims):
    
    A_Z=forward(l,parms,X,Y,net_dims)
    y_predict=np.zeros(shape=(1,Y.shape[1]))
    
    A=A_Z['A']
    for i in range(Y.shape[1]):
        
        if (A[l][0,i]-Y[0,i])>0.5:
            
            y_predict[0,i]=1
        
        else:
            
            y_predict[0,i]=0
            
    return y_predict

10、构建整个模型

设置网络大小\rightarrow初始化w和b\rightarrow对w和b进行优化\rightarrow用优化后的w和b进行预测

#构建整个模型
def modle(train_x,train_y,test_x,test_y,iterations=2000,learning_rate=0.5,print_flag=False):
    
    l=3 #一共3层
    n=[4,3,1] #每一层节点数分别是:4,3,1
    
    l,net_dims=net_size(l,train_x,n)
    parms=init_w_b(l,net_dims)
    parms,grads,costs=optimize(parms,l,net_dims,train_x,train_y,iterations,learning_rate,print_flag)
    y_predict_train=predict(parms,train_x,l,train_y,net_dims)
    y_predict_test=predict(parms,test_x,l,test_y,net_dims)
    
    print('训练集的准确性:',format(100-np.mean(np.abs(train_y-y_predict_train))),'%')
    print('测试集的准确性:',format(100-np.mean(np.abs(test_y- y_predict_test))),'%')
    
    res={'cost':costs,
         'parms':parms,
         'y_predict_train':y_predict_train,
         'y_predict_test':y_predict_test,
         'iterations':iterations,
         'learning_rate':learning_rate}
    
    return res

11、进行测试,对结果进行绘图

res=modle(train_x,train_y,test_x,test_y,iterations=5000,learning_rate=0.005,print_flag=True)

#绘制图
costs = np.squeeze(res['cost'])
plt.plot(costs)
plt.ylabel('cost')
plt.xlabel('iterations (per hundreds)')
plt.title("Learning rate =" + str(res["learning_rate"]))
plt.show()

12、查看结果

训练集的大小:209
测试集的大小:50
训练集的维数:(209, 64, 64, 3)
测试集的维数:(50, 64, 64, 3)
训练集标签的维数:(1, 209)
测试集标签的维数:(1, 50)
训练集的维数:(12288, 209)
测试集的维数:(12288, 50)
一共有:3层网络
每一层分别对应多少节点如下:
{0: 12288, 1: 4, 2: 3, 3: 1}
迭代次数:0,损失值:0.694434
迭代次数:100,损失值:0.655321
迭代次数:200,损失值:0.646017
迭代次数:300,损失值:0.644177
迭代次数:400,损失值:0.643994
迭代次数:500,损失值:0.643976
迭代次数:600,损失值:0.643974
迭代次数:700,损失值:0.643974
迭代次数:800,损失值:0.643974
迭代次数:900,损失值:0.643974
迭代次数:1000,损失值:0.643974
迭代次数:1100,损失值:0.643974
迭代次数:1200,损失值:0.643974
迭代次数:1300,损失值:0.643974
迭代次数:1400,损失值:0.643974
迭代次数:1500,损失值:0.643974
迭代次数:1600,损失值:0.643974
迭代次数:1700,损失值:0.643974
迭代次数:1800,损失值:0.643974
迭代次数:1900,损失值:0.643974
训练集的准确性: 99.6555023923445 %
测试集的准确性: 99.34 %

 总结:以上即是整个流程,强调下,在计算每个变量值时,一定要注意维度的问题,所以我在进行编写程序前都会计算下每个变量的维度,最后在检查程序出错问题时,也需要特别关注这点,若需要整个工程程序可以留言,或有不懂的也可以留言。

猜你喜欢

转载自blog.csdn.net/qq_36417014/article/details/92379785