2021SC@SDUSC软件工程应用与实践06----前向传播反向传播代码实现

2021SC@SDUSC

第一部分:背景

  为了优化原实验,本周开始研究底层原理和代码实现,这里主要分享一下前向传播和反向传播的代码实现。

第二部分:结合代码讲解

神经元本质是一个函数,用于拟合一些点

对于输入的特征个数,我们可设定函数为

y_pre = w1x1+w2x2+w3x3+...wixi+b

我们这里以i=1为例,对于实际情况,要使用多少层以及每层几个神经元都要根据集体数据集而定,我们在这里以三个神经元为例,每个神经元选用sigmoid函数作为激活函数

,其导数为,引入该函数一来可以保证曲线非线性利于梯度下降,而来整体形式便于二分,对于不同问题采用的激活函数不同

从数据集中取出X,Y,并用numpy将初始的函数参数设置成随机值,这样的模型更便于训练,这里有个细节就是所有参数都是全局变量,既便于训练,训练后模型也可以直接用。

m = 100
X,Y = dataset.get_beans(m)
plot_utils.show_scatter(X,Y)

w11_1 = np.random.rand()
b1_1 = np.random.rand()
w12_1 = np.random.rand()
b2_1 = np.random.rand()
w11_2 = np.random.rand()
w21_2 = np.random.rand()
b1_2 = np.random.rand()

将sigmoid函数和前向传播封装起来,前向传播的本质就是按照函数的定义一层一层的向后计算,将计算的结果作为函数的计算结果。

def sigmoid(z): # 封装sigmoid方法
    a = 1/(1+np.exp(-z))
    return a

def forward_progration(x):  # 把前向传播封装起来
    z1_1 = w11_1*x+b1_1
    a1_1 = sigmoid(z1_1)
    z2_1 = w12_1*x+b2_1
    a2_1 = sigmoid(z2_1)
    z1_2 = w11_2*a1_1+w21_2*a2_1+b1_2
    a1_2 = sigmoid(z1_2)
    return a1_2,z1_2,a2_1,z2_1,a1_1,z1_1

这里对所用所有点训练一次作为一轮,设定训练500轮,并用最小二乘法作为损失函数。

for _ in range(500):
    for i in range(m):
        x = X[i]
        y = Y[i]
        a1_2,z1_2,a2_1,z2_1,a1_1,z1_1 = forward_progration(x)
        e = (y-a1_2)**2

这里一次从e开始,利用链式求导法则,依次求到dedw11_2,dedw21_2,dedb1_2,dedw11_1,

dedb1_1,dedw12_1,dedb2_1,用于反向传播。

        deda1_2 =(-2)*(y-a1_2)
        da1_2dz1_2 = a1_2*(1-a1_2)

        dz1_2dw11_2 = a1_1
        dz1_2dw21_2 = a2_1
        dz1_2db1_2 = 1

        dedw11_2 =deda1_2*da1_2dz1_2*dz1_2dw11_2
        dedw21_2 = deda1_2*da1_2dz1_2*dz1_2dw21_2
        dedb1_2 =deda1_2*da1_2dz1_2*dz1_2db1_2

        dz1_2da1_1 = w11_2
        da1_1dz1_1 = a1_1*(1-a1_1)
        dz1_1dw11_1 = x
        dz1_1db1_1 = 1
        dedw11_1 = deda1_2+da1_2dz1_2*dz1_2da1_1*da1_1dz1_1*dz1_1dw11_1
        dedb1_1 = deda1_2+da1_2dz1_2*dz1_2da1_1*da1_1dz1_1*dz1_1db1_1

        dz1_2da2_1 = w21_2
        da1_1dz2_1 = a2_1 * (1 - a2_1)
        dz2_1dw12_1 = x
        dz2_1db2_1 = 1
        dedw12_1 = deda1_2+da1_2dz1_2*dz1_2da2_1*da1_1dz2_1*dz2_1dw12_1
        dedb2_1 = deda1_2+da1_2dz1_2*dz1_2da2_1*da1_1dz2_1*dz2_1db2_1

引入学习率alpha,这个值根据经验自己定,决定了模型训练的速度和效果。

# 反向传播
        alpha = 0.01
        w11_2 = w11_2 - alpha*dedw11_2
        w21_2 = w21_2 - alpha*dedw21_2
        b1_2 = b1_2 - alpha*dedb1_2
        w11_1 = w11_1 - alpha*dedw11_1
        b1_1 = b1_1 - alpha*dedb1_1
        w12_1 = w12_1 - alpha*dedw12_1
        b2_1 = b2_1 - alpha*dedb2_1

低端反向传播原理就是如此,我们可以看到,求导的过程相当简单但繁琐,对于更多神经元,以及更多层数,这个工作量将难以手动敲代码去实现,因此,接下来将介绍通过keras框架来实现上述代码。

第三部分:Keras框架

简介:Keras是基于Theano的一个深度学习框架,它的设计参考了Torch,用Python语言编写,是一个高度模块化的神经网络库,支持GPU和CPU。依赖了Tensorflow框架。

在下好tensorflow和Keras之后,引入相关的包

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from keras.models import Sequential#导入keras

同样取出X,Y

m = 100
X,Y = dataset.get_beans(m)

plot_utils.show_scatter(X,Y)

生成一个model

model = Sequential()

添加第一层,并指定神经元个数为2,使用sigmoid作为激活函数,输入的特征数为1

添加第二层作为输出层,指定神经元为一个和sigmoid激活函数

model.add(Dense(units=2,activation='sigmoid',input_dim=1))
model.add(Dense(units=1,activation='sigmoid'))

设定最小二乘法作为损失函数,并设定学习率为0.05,metrics表示将打印的损失表示方法

model.compile(loss='mean_squared_error',optimizer=SGD(lr=0.05),metrics=['accuracy'])

开始训练,指定训练500轮,每一批为m个

model.fit(X,Y,epochs=500,batch_size=m)

用训练好的模型预测并作图

pres = model.predict(X)
plot_utils.show_scatter_surface(X,Y,model)

我们可以看到,之前花了几十行,和大量繁琐数学运算的反向传播计算,现在仅用简单的几行便可以完成,非常舒服

第四部分:总结

本周主要学习的底层前向传播和反向传播的基础,也是机器学习的本质之一,同时也学习了方便的Keras框架进行模型的构建和训练,在接下来的研究,也会采用框架来进行模型构建与训练,以上代码和注释皆为本人所写,如有问题,欢迎指正!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

见到我请过去学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值