人工神经网络实践(手写反向传播)

本文介绍了如何将神经网络的反向传播方法应用到实际项目中,通过sklearn的医疗数据进行实验,展示了反向传播的四个基本步骤:BP1输出层误差、BP2第l层误差、BP3损失函数关于偏置b的偏导和BP4损失函数关于权值w的偏导。在实验中,作者还加入了L2正则化的损失函数,详细解释了反向传播过程中损失的变化及其对参数更新的影响。最后,对反向传播过程中的细节进行了总结,强调了损失函数的含义和预测结果的合理性分析。
摘要由CSDN通过智能技术生成

前言

上一篇文章讲了神经网络反向传播方法实现,现在我们把它具体的应用到项目中去。

代码段

  • 我们选取sklearn中的医疗数据,作为我们实验对象。
# -*- coding: utf-8 -*-
import numpy as np
from sklearn import datasets
import sklearn
import matplotlib.pyplot as plt

input_dim = 2 #
output_dim = 2 #

eplison = 0.01 #
reg_lambda = 0.01 #

#计算损失函数
def calculate_loss(model, X, y):
    '''损失函数'''

    #1.使用model中的参数
    num_examples = len(X)
    w1, b1, w2, b2, w3, b3 = model['w1'], model['b1'], model['w2'], model['b2'], model['w3'], model['b3']
    #2.使用正向传播计算预测值
    z1 = X.dot(w1) + b1
    a1 = np.tanh(z1)
    z2 = a1.dot(w2) + b2
    a2 = np.tanh(z2)
    z3 = a2.dot(w3) + b3
    exp_scores = np.exp(z3)
    probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)
    #3.计算损失函数
    corect_logrpobs = -np.log(probs[range(num_examples), y])
    data_loss = np.sum(corect_logrpobs)

    #4.对损失值进行归一化
    data_loss += reg_lambda / 2 * (np.sum(np.square(w1)) + np.sum(np.square(w2)) + np.sum(np.square(w3)))
    return 1. / num_examples * data_loss


def predict(model, X):
    '''预测函数'''

    #1.向前传播
    w1, b1, w2, b2, w3, b3 = model['w1'], model['b1'], model['w2'], model['b2'], model['w3'], model['b3']
    # 2.使用正向传播计算预测值
    z1 = X.dot(w1) + b1
    a1 = np.tanh(z1)
    z2 = a1.dot(w2) + b2
    a2 = np.tanh(z2)
    z3 = a2.dot(w3) + b3
    exp_scores = np.exp(z3)
    probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)
    #2.returen 具有最大类别概率
    return np.argmax(probs, axis=1)

def ANN_model(X, y, nn_hdim):
    '''
    人工神经网络模型函数
    :param X:
    :param y:
    :param nn_hdim: 隐层的神经元结点
    :return:
    '''
    num_indim = len(X)
    model = {
   }#模型存储定义

    #1.随机初始化网络中的权重参数w1,w2和偏置b1,b2
    np.random.seed(0)
    w1 = np.random.randn(input_dim, nn_hdim) / np.sqrt(input_dim)
    b1 = np.zeros((1, nn_hdim))
    w2 = np.random.randn(nn_hdim, nn_hdim) / np.sqrt(nn_hdim)
    b2 = np.zeros((1, nn_hdim))
    w3 = np.random.randn(nn_hdim, output_dim) / np.sqrt(nn_hdim)
    b3 = np.zeros((1, output_dim))

    num_passes = 20000 #梯度下降迭代次数
    #2.批量梯度下降算法BSGD
    for i in range(0, num_passes):
        # 2.使用正向传播计算预测值
        z1 = X.dot(w1) + b1
        a1 = np.tanh(z1)
        z2 = a1.dot(w2) + b2
        a2 = np.tanh(z2)
        z3 = a2.dot(w3) + b3
        exp_scores = np.exp(z3)
        probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)


        #4.向后传播
        delta4 = probs        #得到预测值
        delta4[range(num_indim), y] -= 1   #预测值减去实际值
        delta3 = delta4.dot(w3.T) * (1 - np.power(a2, 2))
        delta2 = delta3.dot(w2.T) * (1 - np.power(a1, 2))
        dw3 = (a2.T).dot(delta4)    #w2的导数
        db3 = np.sum(delta4, axis=0, keepdims=True) #b3 的导数
        dw2 = a1.T.dot(delta3)   #w1的导数
        db2 = np.sum(delta3, axis=0, keepdims=True) #b2 的导数
        dw1 = (X.T).dot(delta2)
        db1 = np.sum(delta2, axis=0, keepdims=True) #b1 的导数
        #5.添加正则化项
        dw1 += reg_lambda * w1
        dw2 += reg_lambda * w2
        dw3 += reg_lambda * w3

        #根据梯度下降算法更新权重
        w1 += -eplison * dw1
        b1 += -eplison * db1
        w2 += -eplison * dw2
        b2 += -eplison * db2
        w3 += -eplison * dw3
        b3 += -eplison * db3

        #把新的参数写入model字典中进行记录
        model = {
   'w1':w1, 'b1': b1, 'w2': w2, 'b2': b2, 'w3': w3, 'b3': b3}
        if i % 1000 == 0:
            print('Loss after iteration {}: {}' .format(i, calculate_loss(model, X, y)))

    return model

def plot_decision_boundary(pred_func, data, labels):
    '''绘制分类边界函数'''

    #设置最大值和最小值并增加0.5边界(0.5  padding)
    x_min, x_max = data[:, 0].min() - 0.5, data[:, 0].max() + 0.5
    y_min, y_max = data[:, 1].min() - 0.5, data[:, 1].max() + 0.5
    h = 0.01 #点阵间距

    #生成一个点阵网格,点阵间距为h
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))

    #计算分类结果
    z = pred_func(np.c_[xx.ravel(), yy.ravel()])
    z = z.reshape(xx.shape)
    #绘制分类结果z
    plt.contourf(xx, yy, z, cmap=plt.cm.Blues, alpha=0.2)
    plt.scatter(data[:, 0], data[:, 1], s=40, c=labels, cmap=plt.cm.Reds, edgecolors='black')
    plt.show()
    print('end')
print('begin')
X, y = datasets.make_moons(300, noise=0.25) #300个数据点, 噪声设定0.25
hidden_3_model = ANN_model(X, y, 3)
plot_decision_boundary(lambda x:predict(hidden_3_model, x), X, y)
plt.title('Hidden Layer size 3')

实验效果图:

在这里插入图片描述

训练数据调参过程:
在这里插入图片描述

通过训练过程的可视化展示,我们能够发现训练效果还是不错的。

之前学到过增加隐藏层结点的数量相当于是在集合空间中增加一个超几何平面,增加一层隐层相当于是在已经用平面划分好的空间中进行二次划分,以此类推。4

  • 使用中间层节点数目更多的隐藏作为人工神经网络的节点。
    使用不同的节点数目训练模型:
    效果图如下:

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

当你看到这里是不是和我一样对深度学习更加痴迷呢。
就着这个例子我在下面将给出反向传播的四个过程,我更加在意过程是怎么实现的:

方程 含义
δ L = ∇ a ⊙ f ‘ ( z L ) \delta^L=\nabla_a\odot f^{`}(z^L) δL=af(zL) BP1输出层误差
δ l = ( ( w l ) T δ l + 1 ) ⊙ ( f ‘ ( z l ) ) \delta^l=((w^l)^T\delta^{l+1})\odot(f^`(z^l)) δl=((wl)Tδl+1)(f(zl)) BP2第 l l l层误差
∂ L ∂ b i l = δ i l \frac{\partial{L}}{\partial{b_i^l}}= \delta_i^l bilL=δil BP3损失函数关于偏置的偏导
∂ L ∂ w i , j l = a j l − 1 δ i l \frac{\partial{L}}{\partial{w_{i,j}^l}}= a_{j}^{l-1}\delta_i^l wi,jlL=ajl1δil BP4损失函数关于权值的偏导
  • BP1输出层误差
    根据定义, δ i L \delta_i^L δiL为输出层误差,又因为 a l = f ( z l ) a^l=f(z^l) al=f(zl),对损失函数求导可得:
    δ i L = ∂ L ∂ z i L = ∂ L ∂ a i L ∂ a i L ∂ z i L = ∂ L ∂ a i L ∂ f ( z i L ) z i L = ∂ L ∂
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
手写神经网络是一种基于人工神经网络的模型,用于实现手写数字识别等任务。它通过模拟人脑中的神经元之间的连接关系来进行学习和预测。手写神经网络由输入层、隐藏层和输出层组成,每层都包含多个神经元,它们通过权重和偏置进行连接。输入层接收原始数据(如手写数字的像素值),隐藏层进行特征提取和转换,输出层产生最终的预测结果。 反向传播算法是训练手写神经网络的关键步骤之一。它通过计算预测结果与实际结果之间的误差,并将误差反向传播到网络的每一层,调整每个神经元的权重和偏置,以最小化误差。反向传播算法使用梯度下降法来更新网络中的参数,以逐步提升网络的准确性。 在反向传播算法中,首先需要进行前向传播,即通过网络将输入数据传递到输出层,计算网络的预测结果。然后,计算预测结果与实际结果之间的误差,并计算每个神经元的梯度。接下来,根据梯度和学习率的大小,更新每个神经元的权重和偏置。这个过程循环进行,直到达到预定的训练次数或误差达到要求。 通过反复迭代的训练,手写神经网络可以逐渐学习到输入数据的模式和特征,提高预测的准确性。反向传播算法是一种广泛应用于深度学习和神经网络训练的有效方法,它使得神经网络能够自动地从大量的数据中学习和提取有用的特征。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值