吴恩达Course1课后编程作业第四周-搭建多层神经网络

模型的搭建按照自己的想法设计的,源码共7个.py文件,如下图:
在这里插入图片描述
按照创建先后顺序,分别是:data.pylayer.pynetwork.pyactivation.pyloss.pytrain.pyevaluate.py。data.py用于获取数据并对数据进行预处理,layer.py创建了一个Layer类,用来表示第L层,network.py抽象了一个网络类,将传入的若干层通过计算输入输出连接起来,组成一个网络,data.py用来读取数据,loss.py明确了交叉熵损失函数和其导数,activation.py分别写了激活函数relu和sigmoid以及其导函数,train.py创建了层次并组成网络,然后对数据进行训练并保存模型,最后evaluate.py用于对测试集进行测试。
网络分为2大块,正向传播和反向传播:
在这里插入图片描述
但是不管是正向还是反向,网络中的每一层都可以抽象出来,因此创建一个layer类:
正向传播的L层:
在这里插入图片描述
反向传播的L层:
在这里插入图片描述
在写代码之前,最重要的是确定每个变量和参数的维度:
正向传播:
注意:n[L]表示当前层(即第L层)中的神经元个数,n[L-1]表示前一层(即L-1层)的神经元个数,例如在本次程序中,n[0]=12288,n[1]=1000,n[2]=500,n[3]=1
在这里插入图片描述
反向传播:
在这里插入图片描述
1. data.py

# coding: utf-8
# 2019/7/20 18:59

import h5py
import numpy as np
def get_train():
    f = h5py.File('dataset/train_catvnoncat.h5','r')
    x_train = np.array(f['train_set_x'])#训练集数据  将数据转化为np.array
    y_train = np.array(f['train_set_y'])#训练集标签 
    return x_train,y_train
def get_test():
    f = h5py.File('dataset/test_catvnoncat.h5', 'r')
    x_test = np.array(f['test_set_x'])#测试集数据  将数据转化为np.array
    y_test = np.array(f['test_set_y'])#测试集标签 
    return x_test,y_test

def preprocess(X):
    #将X标准化,从0-255变成0-1
    # X =X / 255
    #将数据从(m,64,64,3)变成(m,12288)
    X = X.reshape([X.shape[0], X.shape[1]*X.shape[2]*X.shape[3]]).T
    return X


if __name__ == '__main__':
    x1,y1 = get_train()
    x2,y2 = get_test()
    print(x1.shape,y1.shape)
    print(x2.shape,y2.shape)

    from matplotlib import  pyplot as plt
    plt.figure()
    for i in range(1,16):
        plt.subplot(3,5,i)
        plt.imshow(x1[i])
        print(y1[i])
    plt.show()

2. layer.py

# coding: utf-8
# 2019/7/21 9:22
import  numpy as np
class Layer:
    def __init__(self,nL,nL_1,activ,activ_deri, learning_rate):
        #参数分别表示:当前层神经元个数,前一层神经元个数,激活函数,激活函数的导函数,学习率
        self.nL = nL
        self.nL_1 = nL_1
        self.g = activ
        self.g_d = activ_deri
        self.alpha = learning_rate
        self.W = np.random.randn(nL,nL_1)*0.01
        self.b = np.random.randn(nL,1)*0.01

    #正向传播:
    #1、计算Z=WX+b
    #2、计算A=g(Z)
    def forward(self,AL_1):
        self.AL_1 = AL_1
        assert (AL_1.shape[0] == self.nL_1)
        self.Z = np.dot(self.W,AL_1)+self.b
        assert (self.Z.shape[0] == self.nL)
        AL = self.g(self.Z)
        return AL

    #反向传播:
    #1、m表示样本个数
    #2、计算dZ,dW,db,dAL_1
    #3、梯度下降,更新W和b
    def backward(self,dAL):
        assert (dAL.shape[0] == self.nL)
        m = dAL.shape[1]
        dZ = np.multiply(dAL,self.g_d(self.Z))
        assert (dZ.shape[0] == self.nL)
        dW = np.dot(dZ,self.AL_1.T)/m
        assert (dW.shape == (self.nL,self.nL_1))
        db = np.mean(dZ,axis=1,keepdims=True)
        assert (db.shape == (self.nL,1))
        dAL_1 = np.dot(self.W.T,dZ)
        assert (dAL_1.shape[0] == self.nL_1)
        #梯度下降
        self.W -= self.alpha*dW
        self.b -= self.alpha*db
        return dAL_1

3. network.py

# coding: utf-8
# 2019/7/21 10:45
import numpy as np

class Network:
    def __init__(self,layers,loss,loss_der):
        self.layers = layers
        self.loss = loss
        self.loss_der = loss_der

    #根据输入的数据来调用正向传播函数,不断更新A,最后得到预测结果
    def predict(self,X):
        A = X
        for layer in self.layers:
            A = layer.forward(A)
        return A

    #连接每个层组建网络:
    #1、根据输入的数据进行正向传播,得到预测结果Y_predict
    #2、根据Y_predict和真实值Y,通过损失函数来计算成本值J
    #3、根据J来计算反向传播的输入值dA
    #4、调用反向传播函数来更新dA
    def train(self,X,Y,epochs=10):
        for i in range(epochs):
            Y_predict = self.predict(X)
            J = np.mean(self.loss(Y, Y_predict))
            print('epoch %d:loss=%f'%(i,J))
            dA = self.loss_der(Y,Y_predict)
            for layer in reversed(self.layers):
                #更新dA
                dA= layer.backward(dA)

4. loss.py

# coding: utf-8
# 2019/7/21 11:34
import numpy as np

#交叉熵损失函数
def cross_entropy(y, y_predict):
    y_predict = np.clip(y_predict,1e-10,1-1e-10) #防止0*log(0)出现。导致计算结果变为NaN
    return -(y * np.log(y_predict) + (1 - y) * np.log(1 - y_predict))

#交叉熵损失函数的导函数
def cross_entropy_der(y,y_predict):
    return -y/y_predict+(1-y)/(1-y_predict)

5. activation.py

# coding: utf-8
# 2019/7/21 9:49
import numpy as np
def sigmoid(z):
    return 1 / (1 + np.exp(-z))

#sigmoid导函数
def sigmoid_der(z):
    x = np.exp(-z)
    return x/((1+x)**2)

def relu(z):
    return np.maximum(0,z)

#relu导函数
def relu_der(z):
    return (z>=0).astype(np.float64)

6. train.py

# coding: utf-8
# 2019/7/21 12:13
import data,layer,loss,network,activation
import pickle,time

#对数据集进行训练并保存模型
#1、搭建3层网络层
#2、将3个层组建成网络
#3、获取训练集数据
#4、对输入值X进行预处理
#5、将数据输入网络进行训练,epochs为1000
#6、将整个模型保存

if __name__ == '__main__':
    learning_rate = 0.01
    L1 = layer.Layer(1000,64*64*3, activation.relu, activation.relu_der, learning_rate)
    L2 = layer.Layer(500,1000,activation.relu, activation.relu_der, learning_rate)
    L3 = layer.Layer(1,500, activation.sigmoid, activation.sigmoid_der, learning_rate)
    net = network.Network([L1,L2,L3], loss.cross_entropy, loss.cross_entropy_der)

    X,Y = data.get_train()
    X = data.preprocess(X)
    net.train(X,Y,1000)

    with open('models/model_%s.pickle'%(time.asctime().replace(':','_').replace(' ','-')),'wb') as f:
        pickle.dump(net,f)

7. evaluate.py

# coding: utf-8
# 2019/7/21 14:17
import data
import pickle
import numpy as np

if __name__ == '__main__':
    model_name = 'model_Sun-Jul-21-14_41_42-2019.pickle'
    #导入模型
    with open('models/'+model_name,'rb') as f:
        net = pickle.load(f)
    #获取测试数据集
    X,Y = data.get_test()
    X = data.preprocess(X)
    #根据输入数据X进行预测
    Y_predict = net.predict(X)
    Y_pred_float = (Y_predict>0.5).astype(np.float64)
    #计算精确度
    accuracy = np.sum(np.equal(Y_pred_float,Y).astype(np.int))/Y.shape[0]
    print('accuracy:',accuracy)

结果
在这里插入图片描述
由于初次搭建深度神经网络,各参数也没有优化,等学完Course2再来改进~

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值