人工智能作业3例题复现

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

学习pytorch相关知识,掌握 实际运用能力。

一、使用pytorch复现例题

在这里插入图片描述
相关代码:
import torch

x1, x2 = torch.Tensor([0.5]), torch.Tensor([0.3])
y1, y2 = torch.Tensor([0.23]), torch.Tensor([-0.07])
print(“=输入值:x1, x2;真实输出值:y1, y2=”)
print(x1, x2, y1, y2)
w1, w2, w3, w4, w5, w6, w7, w8 = torch.Tensor([0.2]), torch.Tensor([-0.4]), torch.Tensor([0.5]), torch.Tensor(
[0.6]), torch.Tensor([0.1]), torch.Tensor([-0.5]), torch.Tensor([-0.3]), torch.Tensor([0.8]) # 权重初始值
w1.requires_grad = True
w2.requires_grad = True
w3.requires_grad = True
w4.requires_grad = True
w5.requires_grad = True
w6.requires_grad = True
w7.requires_grad = True
w8.requires_grad = True

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

def forward_propagate(x1, x2):
in_h1 = w1 * x1 + w3 * x2
out_h1 = sigmoid(in_h1) # out_h1 = torch.sigmoid(in_h1)
in_h2 = w2 * x1 + w4 * x2
out_h2 = sigmoid(in_h2) # out_h2 = torch.sigmoid(in_h2)

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

print("正向计算:o1 ,o2")
print(out_o1.data, out_o2.data)

return out_o1, out_o2

def loss_fuction(x1, x2, y1, y2): # 损失函数
y1_pred, y2_pred = forward_propagate(x1, x2) # 前向传播
loss = (1 / 2) * (y1_pred - y1) ** 2 + (1 / 2) * (y2_pred - y2) ** 2 # 考虑 : t.nn.MSELoss()
print(“损失函数(均方误差):”, loss.item())
return loss

def update_w(w1, w2, w3, w4, w5, w6, w7, w8):
# 步长
step = 1
w1.data = w1.data - step * w1.grad.data
w2.data = w2.data - step * w2.grad.data
w3.data = w3.data - step * w3.grad.data
w4.data = w4.data - step * w4.grad.data
w5.data = w5.data - step * w5.grad.data
w6.data = w6.data - step * w6.grad.data
w7.data = w7.data - step * w7.grad.data
w8.data = w8.data - step * w8.grad.data
w1.grad.data.zero_() # 注意:将w中所有梯度清零
w2.grad.data.zero_()
w3.grad.data.zero_()
w4.grad.data.zero_()
w5.grad.data.zero_()
w6.grad.data.zero_()
w7.grad.data.zero_()
w8.grad.data.zero_()
return w1, w2, w3, w4, w5, w6, w7, w8

if name == “main”:

print("=====更新前的权值=====")
print(w1.data, w2.data, w3.data, w4.data, w5.data, w6.data, w7.data, w8.data)

for i in range(1):
    print("=====第" + str(i) + "轮=====")
    L = loss_fuction(x1, x2, y1, y2)  # 前向传播,求 Loss,构建计算图
    L.backward()  # 自动求梯度,不需要人工编程实现。反向传播,求出计算图中所有梯度存入w中
    print("\tgrad W: ", round(w1.grad.item(), 2), round(w2.grad.item(), 2), round(w3.grad.item(), 2),
          round(w4.grad.item(), 2), round(w5.grad.item(), 2), round(w6.grad.item(), 2), round(w7.grad.item(), 2),
          round(w8.grad.item(), 2))
    w1, w2, w3, w4, w5, w6, w7, w8 = update_w(w1, w2, w3, w4, w5, w6, w7, w8)

print("更新后的权值")
print(w1.data, w2.data, w3.data, w4.data, w5.data, w6.data, w7.data, w8.data)

在这里插入图片描述

二、对比作业2和作业3 的程序

1.作业2结果

##更新之前
print(“更新前的权值”)
print(w1, w2, w3, w4, w5, w6, w7, w8)
##反向传播back_propagate之后
print("\tgrad W: ", round(d_w1, 2), round(d_w2, 2),round(d_w3, 2),round(d_w4, 2),round(d_w5, 2),round(d_w6, 2),round(d_w7,2),
round(d_w8, 2))
##更新完值后
print(“更新后的权值”)
print(round(w1,4), round(w2,4),round(w3,4),round(w4,4),round(w5,4),round(w6,4),round(w7,4),round(w8,4))

结果显示
1:正向传播与损失函数一致结果。
2:反向传播得到的梯度与更新权值不一致。
在这里插入图片描述
其中反向传播的推导公示错误
在这里插入图片描述
在这里插入图片描述
运行结果:
在这里插入图片描述

#三、作业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 * w5 / out_h1 + d_w6 * w6 / out_h1) * out_h1 * (1 - out_h1) * x1
d_w3 = (d_w5 * w5 / out_h1 + d_w6 * w6 / out_h1) * out_h1 * (1 - out_h1) * x2
d_w2 = (d_w7 * w7 / out_h2 + d_w8 * w8 / out_h2) * out_h2 * (1 - out_h2) * x1
d_w4 = (d_w7 * w7 / out_h2 + d_w8 * w8 / out_h2) * 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 = 1 # 迭代次数
step = 1 # 步长

print("输入值:x1, x2;",x1, x2, "输出值:y1, y2:", y1, y2)
print("更新前的权值")
print(w1, w2, w3, w4, w5, w6, w7, w8)

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, 4))
    # 反向传播
    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)
    print("\tgrad W: ", round(d_w1, 2), round(d_w2, 2),round(d_w3, 2),round(d_w4, 2),round(d_w5, 2),round(d_w6, 2),round(d_w7,2),
          round(d_w8, 2))
    # 梯度下降,更新权值
    w1, w2, w3, w4, w5, w6, w7, w8 = update_w(step,w1, w2, w3, w4, w5, w6, w7, w8)
    print("更新后的权值")
    print(round(w1,4), round(w2,4),round(w3,4),round(w4,4),round(w5,4),round(w6,4),round(w7,4),round(w8,4))
    eli.append(i)
    lli.append(error)


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

四、对比作业2和作业3 的反向传播实现方法

手算与调用库,作业3采用tensor,求loss,通过backword()求梯度。尽量使用库函数

五、激活函数Sigmoid用PyTorch自带函数torch.sigmoid()总结

差别不大

六、激活函数Sigmoid改变为Relu总结

def sigmoid(z):
a = torch.relu(z)
return a
更新前的结果:
在这里插入图片描述

relu函数定义为:f(x) = max(0,x),更改之后运行结果
在这里插入图片描述
对比一下损失函数relu之后明显优秀,变为0.004.

七、损失函数MSE用PyTorch自带函数 t.nn.MSELoss()替代总结

在这里插入图片描述
torch.nn.MSELoss()如下:
在这里插入图片描述

八、损失函数MSE改变为交叉熵总结

在这里插入图片描述
结果:
在这里插入图片描述

九、.改变步长,训练次数

在合适的范围之内,增加步长或者迭代轮数都可以使损失函数减少。

不过当步长过大的时候,多轮执行,损失函数反而会变大,且会稳定在一个固定的值。
从更新过程就可以看出,过大的步长导致对参数的修改过大,当然这和激活函数也有关系。

十、权值w1-w8初始值换为随机数,对比【作业2】指定权值结果

#随机函数
w=torch.rand(1)
指定数100轮:
在这里插入图片描述

随机数100论:
在这里插入图片描述

十一、总结反向传播原理和编码实现

反向传播算法的功能就是,给输入和输出,经过输入层,隐藏层和输出层,不断进行反向传播修改参数,得到输出结果。激活函数可以增加神经网络的学习功能,损失函数是我们进行反向传播的关键因素之一,损失函数是反向传播中计算梯度计算的基础,使修改参数的依据,不同的损失函数相同的步长和初值训练的效率很可能是不同的,损失函数的选取很重要。同时利用梯度的特性和链式法则,是反向传播的数学基础。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值