#深度学习#浅层神经网络手动搭建-基于python

浅层神经网络搭建

数据来源: https://blog.csdn.net/u013733326/article/details/79702148
参考:https://blog.csdn.net/qq_29762941/article/details/80343185

目标:

手动建立一个基于反向传播的神经网络,包含一个隐藏层,实现一个二维平面数据分类。可以在jupyter notebook上分步进行或在pycharm上建立项目运行。

程序流程:

1.数据准备

    import numpy as np							#引入标准库
    import matplotlib.pyplot as plt
    np.random.seed(1)							#生成随机种子,保证验证结果一样

(1)创建数据集

 #创建二维分类数据集 ,直接调用,得到训练数据
 def load_planar_dataset():
     np.random.seed(1)
     m = 400 # number of examples
     N = int(m/2) # number of points per class
     D = 2 # dimensionality
     X = np.zeros((m,D)) # data matrix where each row is a single example
     Y = np.zeros((m,1), dtype='uint8') # labels vector (0 for red, 1 for blue)
     a = 4 # maximum ray of the flower
 
     for j in range(2):
         ix = range(N*j,N*(j+1))
         t = np.linspace(j*3.12,(j+1)*3.12,N) + np.random.randn(N)*0.2 # theta
         r = a*np.sin(4*t) + np.random.randn(N)*0.2 # radius
         X[ix] = np.c_[r*np.sin(t), r*np.cos(t)]
         Y[ix] = j
 
     X = X.T
     Y = Y.T
 
     return X, Y

(2)测试:

    X, Y = load_planar_dataset()
    print (X.shape, Y.shape)

得到输入数据的结构
(2, 400) (1, 400)

(3)绘制图形:

    plt.scatter(X[0, :], X[1, :], c=np.squeeze(Y), s=40, cmap=plt.cm.Spectral) #绘制散点图

#深度学习#浅层神经网络手动搭建-基于python_第1张图片

(2,400)的训练数据X, 每一列代表一个点的坐标,总共400个点。
(1,400)1行400列的为监督数据,即标定有400个。

2.搭建框架函数准备

2.1 程序流程结构设计

初始化神经网络结构:激活函数确定;确定输入层,隐藏层,输出层;

def sigmoid (Z)
def layer_sizes(X, Y)

初始化网络参数数值:传递权重w,偏置量b;

def initlalize_parameters(n_x, n_h, n_y)

神经网络前向传播:前向传播计算;成本函数计算;

def forward_propagation(X, parameters)
def compute_cost(A2,Y,parameters):

神经网络反向传播:反向传播梯度计算;反向传播参数更新;

def backward_propagation(parameters, cache, X, Y)
def uppdata_parameters(parameters,grads,learning_rate=1.2)

2.2 程序分块实现

2.2.1初始化神经网络结构

1.激活函数:激活函数是神经网络脱离线性(wX+b结构属于线性变换)进行空间扭曲的关键部分,可以选常用的sigmoid函数与双曲正切函数tanh,这里我们选sigmoid,读者可以根据自己的喜好进行尝试。

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

2.网络结构层数初始化:
输入数据是(2,400), 两行分别是坐标 (xi,yi),若以输入参数2个,即两个神经元做为输入;
每个输入对应输出数据为1个标定类别:红或蓝,即一个神经元做为输出;
隐藏层我们设计4个神经元进行训练;

    def layer_sizes(X, Y):
        n_x = X.shape[0]
        n_h = 4
        n_y = Y.shape[0]
        return (n_x, n_h, n_y)    
        #该函数返回各个层级的神经元数量,根据神经元数量来确定矩阵维度

2.2.2初始化网络参数数值

#深度学习#浅层神经网络手动搭建-基于python_第2张图片
按照上述计算,神经网络的结构为(2-4-1),为了方便计算,采用矩阵形式进行传播计算即:wx+b = y
根据矩阵相乘的维度限制确定w 与 b 矩阵的维度,方法如下:
w[4, _ ] * x[2, 1] + b[ _, _] = y1;
根据神经元数量可以完成上式,根据乘法规则,填充如下:
w[4, 2 ] * x[2, 1] + b[ 4, 1] = y1;

1.初始化参数矩阵

    def initlalize_parameters(n_x, n_h, n_y):
        np.random.seed(2)
        W1 = np.random.rand(n_h, n_x) * 0.01
        b1 = np.zeros(shape=(n_h, 1))
        W2 = np.random.rand(n_y, n_h) * 0.01
        b2 = np.zeros(shape=(n_y, 1))
        
    	#创建一个字典类型的变量parameter来存储产生的矩阵
        parameters = {"W1": W1,
                      "b1": b1,
                      "W2": W2,
                      "b2": b2}
    
        return parameters

2.2.3神经网络前向传播

1.前向传播计算
对于两层的神经网络结构我们定义
Z1 = w1x + b1;
A1 = ranh(Z1);
Z2 = w2A1 + b2;
A2 = sigmoid(Z2);

    def forward_propagation(X, parameters):
        W1 = parameters["W1"]
        b1 = parameters["b1"]
        W2 = parameters["W2"]
        b2 = parameters["b2"]
    
        Z1 = np.dot(W1, X) + b1
        A1 = np.tanh(Z1)
        Z2 = np.dot(W2, A1) + b2
        A2 = sigmoid(Z2)
   		#字典类型cache 存储前向计算中得到的结果
        cache = {"Z1": Z1,
                 "A1": A1,
                 "Z2": Z2,
                 "A2": A2}
    
        return (A2, cache)

2.成本函数计算
对于二分类问题,最常用的情况是以0.5为阈值进行判断,所以损失函数与逻辑回归一致。

    def compute_cost(A2,Y,parameters):
        m = Y.shape[1]
        W1 = parameters["W1"]
        W2 = parameters["W2"]
    
        # 计算成本
        logprobs = np.multiply(np.log(A2), Y) + np.multiply((1 - Y), np.log(1 - A2))
        cost = -np.sum(logprobs) / m
        cost = float(np.squeeze(cost))
    
        assert (isinstance(cost, float))
    
        return cost

2.2.4神经网络反向传播

1反向梯度计算:
神经网络反向推导的过程一直搞得不是很清楚,现在写下参考大佬们的一些推导理解,供自己记录与参考。
1)目标函数
在这里插入图片描述…经典代价函数
在这里插入图片描述…整体代价函数,在后面补充的为权重衰减项,为的是让模型不要变的复杂,权值尽量小,简单,提升泛化能力。

有了上述的代价函数,我们选择以梯度下降的方法优化整体代价函数,找到全局最优(理想)的W,b参数。

2)反向传播更新:
根据最优化的梯度下降算法,定义一个学习率,变量在负梯度方向上进行更新,公式如下:
在这里插入图片描述
核心问题转化为代价函数对W,b求导:
在这里插入图片描述
在这里插入图片描述
根据求导公式,将导数计算转移成两个导数的间接计算。
在这里插入图片描述
引入残差变量δ,计算过程如下:
#深度学习#浅层神经网络手动搭建-基于python_第3张图片
3)对于l = n-1,n-2…层的残差计算,可以根据之前的残差推断出来

#深度学习#浅层神经网络手动搭建-基于python_第4张图片
推导得出前一层的残差可有当前残差与前一层参数共同确定。
在这里插入图片描述
4)根据上述已知公式,我们进行推导,整体梯度结果为:
在这里插入图片描述
其中:在这里插入图片描述
在这里插入图片描述
所以:
在这里插入图片描述

    def backward_propagation(parameters, cache, X, Y):
        m = X.shape[1]
        W1 = parameters["W1"]
        W2 = parameters["W2"]
    
        A1 = cache["A1"]
        A2 = cache["A2"]
    
        # 偏差
        dZ2 = A2 - Y                        	#用做差代替残差
        dW2 = (1 / m) * np.dot(dZ2, A1.T)		#矩阵相乘就是对求和的化简
        db2 = (1 / m) * np.sum(dZ2, axis=1, keepdims=True)		#db为残差求和
        #这里激活函数如果是sigmoid,应该是用a(x)(1-a(x)) 做为激励函数倒数
        dZ1 = np.multiply(np.dot(W2.T, dZ2), 1 - np.power(A1, 2))  
         #tanh' = 1-tanh^2
        dW1 = (1 / m) * np.dot(dZ1, X.T)
        db1 = (1 / m) * np.sum(dZ1, axis=1, keepdims=True)
        grads = {"dW1": dW1,
                 "db1": db1,
                 "dW2": dW2,
                 "db2": db2}
    
        return grads

2.参数更新

    def uppdata_parameters(parameters,grads,learning_rate=1.2):
        W1,W2 = parameters["W1"],parameters["W2"]
        b1,b2 = parameters["b1"],parameters["b2"]
    
        dW1,dW2 = grads["dW1"],grads["dW2"]
        db1,db2 = grads["db1"],grads["db2"]
    
        W1 = W1 - learning_rate * dW1
        b1 = b1 - learning_rate * db1
        W2 = W2 - learning_rate * dW2
        b2 = b2 - learning_rate * db2
    
        parameters = {"W1": W1,
                      "b1": b1,
                      "W2": W2,
                      "b2": b2}
    
        return parameters

整合部分未完持续

你可能感兴趣的:(深度学习)