老饼讲解-深度学习 机器学习 神经网络 深度学习
CNN入门教程

【代码】pytorch实现BP神经网络-类别预测

作者 : 老饼 发表日期 : 2024-01-28 20:00:27 更新日期 : 2024-03-01 14:13:04
本站原创文章,转载请说明来自《老饼讲解-深度学习》www.bbbdata.com



本文展示一个BP神经网络用于类别预测的例子,并用pytorch进行实现与训练

通过本文可以具体了解如何使用BP神经网络进行类别预测以及pytorch的代码实现




   01. BP神经网络类别预测-例子   



本节展示BP神经网络实现类别预测例子中的数据说明与模型设置




     BP神经网络类别预测-数据说明    


本节展示如何使用BP神经网络来预测类别,为方便理解,不妨采用以下的简单数据:
  
其中,x1,x2是样本的输入变量,y是样本的类别标签




      BP神经网络类别预测-模型结构设置      


由于样本较为简单,因此本文只采用常规的三层BP神经网络、4个隐节点进行拟合,
 整体BP神经网络模型结构如下:
  
设置好以上的模型之后,将交叉熵作为损失函数,使用梯度下降法对其进行训练即可






   02. BP神经网络类别预测-pytroch代码实现   



本节展示如何通过pytorch来实现BP神经网络的类别预测



     pytorch实现BP神经网络-类别预测     


在pytorch中可以使用深度学习的相关框架来实现BP神经网络
本文为了更具体了解BP神经网络,尽量不使用pytorch的框架,而仅利用pytorch的自动求导功能

使用pytorch实现BP神经网络进行类别预测的代码如下:
import torch
import matplotlib.pyplot as plt 
import numpy as np
torch.manual_seed(99)      # 设定随机种子,使得每次运行结果一样

# -----------计算网络输出:前馈式计算---------------
def forward(w1,b1,w2,b2,x):                                   
    return torch.nn.Softmax(dim=0)(w2@torch.tanh(w1@x+b1)+b2)                    

# -----------计算损失函数: 使用交叉熵(在这里作为学习材料,我们自行手算,而不调用torch的交叉熵损失函数)--------------
def loss(y,py):
    loss = 0                                                                        # 初始化损失值
    class_num,sample_num = y.shape                                                  # 类别个数与样本个数
    for i in range(class_num):                                                      # 累计每一类别的损失值
        loss = loss -torch.log(py[i,y[i,:]==1]).sum()/sample_num                    # loss = loss-sum(ln(p))/m
    return loss                                                                    
																			                                                         
# ------生成训练数据----------------                                                   
X = np.array([[2.5, 1.3, 6.2, 1.3, 5.4, 6 ,4.3, 8.2]                               
                ,[-1.2,2.5,3.6,4,3.4,2.3,7.2,3.9]])                                # 样本的输入数据
Y = np.array([[1,1,0,1,0,0,0,0],[0,0,1,0,1,1,1,1]])                                # 样本的标签,one-hot格式
x = torch.tensor(X).float()                                                        # 将训练数据X转为tensor
y = torch.tensor(Y).float()                                                        # 将训练数据y转为tensor

#-----------训练模型------------------------
in_num  = x.shape[0]                                                               # 输入个数
out_num = y.shape[0]                                                               # 输出个数
hn  = 4                                                                            # 隐节点个数
w1  = torch.randn([hn,in_num],requires_grad=True)                                  # 初始化输入层到隐层的权重w1
b1  = torch.randn([hn,1],requires_grad=True)                                       # 初始化隐层的阈值b1
w2  = torch.randn([out_num,hn],requires_grad=True)                                 # 初始化隐层到输出层的权重w2
b2  = torch.randn([out_num,1],requires_grad=True)                                  # 初始化输出层的阈值b2
															                      
lr = 0.01                                                                          # 学习率
for i in range(5000):                                                              # 训练5000步
    py = forward(w1,b1,w2,b2,x)                                                    # 计算网络的输出
    L = loss(y,py)                                                                 # 计算损失函数
    print('第',str(i),'轮损失函数值:',L)                                          # 打印当前损失函数值
    L.backward()                                                                   # 用损失函数更新模型参数的梯度
    w1.data=w1.data-w1.grad*lr                                                     # 更新模型系数w1
    b1.data=b1.data-b1.grad*lr                                                     # 更新模型系数b1
    w2.data=w2.data-w2.grad*lr                                                     # 更新模型系数w2
    b2.data=b2.data-b2.grad*lr                                                     # 更新模型系数b2
    w1.grad.zero_()                                                                # 清空w1梯度,以便下次backward
    b1.grad.zero_()                                                                # 清空b1梯度,以便下次backward
    w2.grad.zero_()                                                                # 清空w2梯度,以便下次backward
    b2.grad.zero_()                                                                # 清空b2梯度,以便下次backward
															                      
# -------打印模型训练结果----------                                                              
labels   = torch.argmax(y, dim=0)                                                  # 将one-hot转为类别标签
py       = forward(w1,b1,w2,b2,x)                                                  # 计算网络的预测值
p_labels = torch.argmax(py, dim=0)                                                 # 将网络的预测转为类别标签
print('准确率:' ,((labels==p_labels).sum()/p_labels.numel()).numpy()*100,'%')      # 计算准确率 
# 绘制预测结果                                                                    
colors = ['red','g']                                                               # 定义0类的颜色为red,1类样本的颜色为green
labels_color   = [ colors[i] for i in labels]                                      # 各个样本真实对应的颜色  
p_labels_color = [ colors[i] for i in p_labels]                                    # 各个样本预测对应的颜色 
plt.scatter(X[0,:], X[1,:],c=labels_color,s=20)                                    # 绘制真实样本
plt.scatter(X[0,:], X[1,:],marker='o',c='none',edgecolors=p_labels_color,s=80)     # 绘制预测样本
plt.legend(['true label','predict label'])                                         # 显示图例




     运行结果    


运行结果如下:
....                                                        
第 4995 轮损失函数值: tensor(0.0127, grad_fn=<SubBackward0>)
第 4996 轮损失函数值: tensor(0.0127, grad_fn=<SubBackward0>)
第 4997 轮损失函数值: tensor(0.0127, grad_fn=<SubBackward0>)
第 4998 轮损失函数值: tensor(0.0127, grad_fn=<SubBackward0>)
第 4999 轮损失函数值: tensor(0.0127, grad_fn=<SubBackward0>)
准确率: 100.0 %                                               
 
 
实心点的颜色是样本的真实类别,圆圈的颜色是样本的预测类别
可以看到,模型对所有样本的类别预测都是准确的





好了,以上就是在pytorch上实现BP神经网络类别预测的代码例子了~








 End 







联系老饼