人工智能-作业2:例题程序复现


实验内容

复现课上说的代码,不使用PyTorch,自己手写代码实现反向传播和梯度下降。


一、简单神经网络模型和反向传播

实现的模型为:
在这里插入图片描述
变量和名词说明:
第一层(图中红框1):输入层
第二层(图中红框2):隐藏层
第三层(图中红框3):输出层
图中红框4:损失函数

权重向量:[w1,w2,w3,w4,w5,w6,w7,w8],是每轮迭代要改变的量,求解神经网络模型的本质就是求解一个符合目标的权重向量

Sigmoid函数:非线性变化函数,输入线性内容,输出非线性结果,这是由于生活中的许多数据都是非线性的,为了获得更好的模型,需要将输出数据进行非线性变换;
 sigmoid的表达式:Sigmoid(x) = 1/1+e^{-x}
 sigmoid函数的图像:
来着百度图片
损失函数-Loss():损失函数有多种计算方法,但本质上要表达的是模型预测结果与实际结果的差距。损失函数也是确定不同权重梯度值从而更新权重值的依据,机器学习模型的最终目标就是获得一个损失函数值较小的模型。

MSE函数:一个损失函数,其中Yi标识预测值,Yi-hat表示实际值,损失函数的值就是所有样本预测值与实际值的平方差的和再取平均值,因此也称为均方误差。
在这里插入图片描述

二、代码实现

1.函数和变量代码实现和解释

反向传播求损失函数值对传播路径上每个权重的偏导值
前向传播计算损失函数值

in_h1 = w1 * x1 + w3 * x2
out_h1 = sigmoid(in_h1)

in_h2 = w2 * x1 + w4 * x2
out_h2 = sigmoid(in_h2)

in_o1 = w5 * out_h1 + w7 * out_h2
out_o1 = sigmoid(in_o1)

in_o2 = w6 * out_h1 + w8 * out_h2
out_o2 = sigmoid(in_o2)

损失函数-均方误差MSE()

error = (1 / 2) * (out_o1 - y1) ** 2 + (1 / 2) * (out_o2 - y2) ** 2

激活函数-Sigmoid()

def sigmoid(z):
    a = 1 / (1 + np.exp(-z))
    return a

计算模型中损失函数对所有权重的偏导数

    d_w5 = d_o1 * out_o1 * (1 - out_o1) * out_h1
    d_w7 = d_o1 * out_o1 * (1 - out_o1) * out_h2
    d_w6 = d_o2 * out_o2 * (1 - out_o2) * out_h1
    d_w8 = d_o2 * out_o2 * (1 - out_o2) * out_h2

    d_w1 = (d_o1 * out_h1 * (1 - out_h1) * w5 + d_o2 * out_o2 * (1 - out_o2) * w6) * out_h1 * (1 - out_h1) * x1
    d_w3 = (d_o1 * out_h1 * (1 - out_h1) * w5 + d_o2 * out_o2 * (1 - out_o2) * w6) * out_h1 * (1 - out_h1) * x2
    d_w2 = (d_o1 * out_h1 * (1 - out_h1) * w7 + d_o2 * out_o2 * (1 - out_o2) * w8) * out_h2 * (1 - out_h2) * x1
    d_w4 = (d_o1 * out_h1 * (1 - out_h1) * w7 + d_o2 * out_o2 * (1 - out_o2) * w8) * out_h2 * (1 - out_h2) * x2

2.代码实现

完整代码如下(示例):

import numpy as np
import matplotlib.pyplot as plt


def sigmoid(z):
    a = 1 / (1 + np.exp(-z))
    return a


def forward_propagate(x1, x2, y1, y2, w1, w2, w3, w4, w5, w6, w7, w8): # 正向传播
    in_h1 = w1 * x1 + w3 * x2
    out_h1 = sigmoid(in_h1)
    in_h2 = w2 * x1 + w4 * x2
    out_h2 = sigmoid(in_h2)

    in_o1 = w5 * out_h1 + w7 * out_h2
    out_o1 = sigmoid(in_o1)
    in_o2 = w6 * out_h1 + w8 * out_h2
    out_o2 = sigmoid(in_o2)

    error = (1 / 2) * (out_o1 - y1) ** 2 + (1 / 2) * (out_o2 - y2) ** 2

    return out_o1, out_o2, out_h1, out_h2, error


def back_propagate(out_o1, out_o2, out_h1, out_h2):    # 反向传播
    d_o1 = out_o1 - y1
    d_o2 = out_o2 - y2

    d_w5 = d_o1 * out_o1 * (1 - out_o1) * out_h1
    d_w7 = d_o1 * out_o1 * (1 - out_o1) * out_h2
    d_w6 = d_o2 * out_o2 * (1 - out_o2) * out_h1
    d_w8 = d_o2 * out_o2 * (1 - out_o2) * out_h2

    d_w1 = (d_w5 + d_w6) * out_h1 * (1 - out_h1) * x1
    d_w3 = (d_w5 + d_w6) * out_h1 * (1 - out_h1) * x2
    d_w2 = (d_w7 + d_w8) * out_h2 * (1 - out_h2) * x1
    d_w4 = (d_w7 + d_w8) * out_h2 * (1 - out_h2) * x2

    return d_w1, d_w2, d_w3, d_w4, d_w5, d_w6, d_w7, d_w8


def update_w(step,w1, w2, w3, w4, w5, w6, w7, w8):    #梯度下降,更新权值
    w1 = w1 - step * d_w1
    w2 = w2 - step * d_w2
    w3 = w3 - step * d_w3
    w4 = w4 - step * d_w4
    w5 = w5 - step * d_w5
    w6 = w6 - step * d_w6
    w7 = w7 - step * d_w7
    w8 = w8 - step * d_w8
    return w1, w2, w3, w4, w5, w6, w7, w8


if __name__ == "__main__":
    w1, w2, w3, w4, w5, w6, w7, w8 = 0.2, -0.4, 0.5, 0.6, 0.1, -0.5, -0.3, 0.8 # 可以给随机值,为配合PPT,给的指定值
    x1, x2 = 0.5, 0.3   # 输入值
    y1, y2 = 0.23, -0.07 # 正数可以准确收敛;负数不行。why? 因为用sigmoid输出,y1, y2 在 (0,1)范围内。
    N = 10             # 迭代次数
    step = 10           # 步长

    print("输入值:x1, x2;",x1, x2, "输出值:y1, y2:", y1, y2)
    eli = []
    lli = []
    for i in range(N):
        print("=====第" + str(i) + "轮=====")
        # 正向传播
        out_o1, out_o2, out_h1, out_h2, error = forward_propagate(x1, x2, y1, y2, w1, w2, w3, w4, w5, w6, w7, w8)
        print("正向传播:", round(out_o1, 5), round(out_o2, 5))
        print("损失函数:", round(error, 2))
        # 反向传播
        d_w1, d_w2, d_w3, d_w4, d_w5, d_w6, d_w7, d_w8 = back_propagate(out_o1, out_o2, out_h1, out_h2)
        # 梯度下降,更新权值
        w1, w2, w3, w4, w5, w6, w7, w8 = update_w(step,w1, w2, w3, w4, w5, w6, w7, w8)
        eli.append(i)
        lli.append(error)


    plt.plot(eli, lli)
    plt.ylabel('Loss')
    plt.xlabel('w')
    plt.show()

随机生成初始权重向量

 #w1, w2, w3, w4, w5, w6, w7, w8 = 0.2, -0.4, 0.5, 0.6, 0.1, -0.5, -0.3, 0.8 # 可以给随机值,为配合PPT,给的指定值
    w1 = round(random.random(),1)
    w2 = round(random.random(),1)
    w3 = round(random.random(),1)
    w4 = round(random.random(),1)
    w5 = round(random.random(),1)
    w6 = round(random.random(),1)
    w7 = round(random.random(),1)
    w8 = round(random.random(),1)
    print("初始权重向量:",w1,w2,w3,w4,w5,w6,w7,w8)

运行结果
在这里插入图片描述
在这里插入图片描述

参考的文章

通俗易懂讲解均方误差 (MSE) - haltakov
【人工智能导论:模型与算法】MOOC 8.3 误差后向传播(BP) 例题 编程验证

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值