BP(Back Propagation)神经网络是一种按误差逆传播算法训练的多层前馈网络,它的学习规则是使用梯度下降法通过反向传播来不断调整网络的权值和阈值,使网络的误差平方和最小。BP神经网络模型拓扑结构包括输入层(input)、隐层(hiddenlayer)和输出层(output layer)。BP网络的学习过程,由信息的正向传播和误差的反向传播两个过程组成。

BP神经网络结构

数据集

采用鸢尾花数据集:

超参数设置

lr= 0.02 # 学习率epochs= 300# 训练轮数 n_feature = 4# 输入特征(鸢尾花四个特征)n_hidden= 20 # 隐含层n_output= 3# 输出(鸢尾花三种类别)

准备数据

将数据分成训练集80%和测试集20%,并对数据进行归一化,测试集的数据归一化必须使用训练集上得到的最大最小值。最后将数据转化为Tensor类型,以便能够进行训练。

#1.准备数据iris=datasets.load_iris() #下载数据集#设置训练集数据80%,测试集20%x_train0,x_test0,y_train,y_test=train_test_split(iris.data,iris.target,test_size=0.2,random_state=22)#归一化(也就是所说的min-max标准化)通过调用sklearn库的标准化函数min_max_scaler = preprocessing.MinMaxScaler()x_train = min_max_scaler.fit_transform(x_train0)x_test = min_max_scaler.fit_transform(x_test0)#将数据类型转换为tensor方便pytorch使用x_train=torch.FloatTensor(x_train)y_train=torch.LongTensor(y_train)x_test=torch.FloatTensor(x_test)y_test=torch.LongTensor(y_test)

定义BP神经网络

#2.定义BP神经网络class BPNetModel(torch.nn.Module):def __init__(self,n_feature,n_hidden,n_output):super(BPNetModel, self).__init__()self.hiddden=torch.nn.Linear(n_feature,n_hidden)#定义隐层网络self.out=torch.nn.Linear(n_hidden,n_output)#定义输出层网络def forward(self,x):x=Fun.relu(self.hiddden(x)) #隐层激活函数采用relu()函数out=Fun.softmax(self.out(x),dim=1) #输出层采用softmax函数return out

定义优化器和损失函数

#3.定义优化器和损失函数net=BPNetModel(n_feature=n_feature,n_hidden=n_hidden,n_output=n_output) #调用网络optimizer=torch.optim.Adam(net.parameters(),lr=lr) #使用Adam优化器,并设置学习率loss_fun=torch.nn.CrossEntropyLoss() #对于多分类一般使用交叉熵损失函数

训练数据

#4.训练数据loss_steps=np.zeros(epochs) #构造一个array([ 0., 0., 0., 0., 0.])里面有epochs个0accuracy_steps=np.zeros(epochs)for epoch in range(epochs):y_pred=net(x_train) #前向传播loss=loss_fun(y_pred,y_train)#预测值和真实值对比optimizer.zero_grad() #梯度清零loss.backward() #反向传播optimizer.step() #更新梯度loss_steps[epoch]=loss.item()#保存lossrunning_loss = loss.item()print(f"第{epoch}次训练,loss={running_loss}".format(epoch,running_loss))with torch.no_grad(): #下面是没有梯度的计算,主要是测试集使用,不需要再计算梯度了y_pred=net(x_test)correct=(torch.argmax(y_pred,dim=1)==y_test).type(torch.FloatTensor)accuracy_steps[epoch]=correct.mean()print("测试鸢尾花的预测准确率", accuracy_steps[epoch])

绘制损失函数和精度函数图像

#5.绘制损失函数和精度fig_name="Iris_dataset_classify_BPNet"fontsize=15fig,(ax1,ax2)=plt.subplots(2,figsize=(15,12),sharex=True)ax1.plot(accuracy_steps)ax1.set_ylabel("test accuracy",fontsize=fontsize)ax1.set_title(fig_name,fontsize="xx-large")ax2.plot(loss_steps)ax2.set_ylabel("train lss",fontsize=fontsize)ax2.set_xlabel("epochs",fontsize=fontsize)plt.tight_layout()plt.savefig(fig_name+'.png')plt.show()

全部代码

import numpy as npimport matplotlib.pyplot as pltfrom sklearn import datasetsfrom sklearn import preprocessingfrom sklearn.model_selection import train_test_split #训练集,测试集划分函数import torchimport torch.nn.functional as Fun#设置超参数lr=0.02 #学习率epochs=300 #训练轮数n_feature=4 #输入特征n_hidden=20 #隐层节点数n_output=3 #输出(鸢尾花三种类别)#1.准备数据iris=datasets.load_iris() #下载数据集#设置训练集数据80%,测试集20%x_train0,x_test0,y_train,y_test=train_test_split(iris.data,iris.target,test_size=0.2,random_state=22)#归一化(也就是所说的min-max标准化)通过调用sklearn库的标准化函数min_max_scaler = preprocessing.MinMaxScaler()x_train = min_max_scaler.fit_transform(x_train0)x_test = min_max_scaler.fit_transform(x_test0)#将数据类型转换为tensor方便pytorch使用x_train=torch.FloatTensor(x_train)y_train=torch.LongTensor(y_train)x_test=torch.FloatTensor(x_test)y_test=torch.LongTensor(y_test)#2.定义BP神经网络class BPNetModel(torch.nn.Module):def __init__(self,n_feature,n_hidden,n_output):super(BPNetModel, self).__init__()self.hiddden=torch.nn.Linear(n_feature,n_hidden)#定义隐层网络self.out=torch.nn.Linear(n_hidden,n_output)#定义输出层网络def forward(self,x):x=Fun.relu(self.hiddden(x)) #隐层激活函数采用relu()函数out=Fun.softmax(self.out(x),dim=1) #输出层采用softmax函数return out#3.定义优化器和损失函数net=BPNetModel(n_feature=n_feature,n_hidden=n_hidden,n_output=n_output) #调用网络optimizer=torch.optim.Adam(net.parameters(),lr=lr) #使用Adam优化器,并设置学习率loss_fun=torch.nn.CrossEntropyLoss() #对于多分类一般使用交叉熵损失函数#4.训练数据loss_steps=np.zeros(epochs) #构造一个array([ 0., 0., 0., 0., 0.])里面有epochs个0accuracy_steps=np.zeros(epochs)for epoch in range(epochs):y_pred=net(x_train) #前向传播loss=loss_fun(y_pred,y_train)#预测值和真实值对比optimizer.zero_grad() #梯度清零loss.backward() #反向传播optimizer.step() #更新梯度loss_steps[epoch]=loss.item()#保存lossrunning_loss = loss.item()print(f"第{epoch}次训练,loss={running_loss}".format(epoch,running_loss))with torch.no_grad(): #下面是没有梯度的计算,主要是测试集使用,不需要再计算梯度了y_pred=net(x_test)correct=(torch.argmax(y_pred,dim=1)==y_test).type(torch.FloatTensor)accuracy_steps[epoch]=correct.mean()print("测试鸢尾花的预测准确率", accuracy_steps[epoch])#print("测试鸢尾花的预测准确率",accuracy_steps[-1])#5.绘制损失函数和精度fig_name="Iris_dataset_classify_BPNet"fontsize=15fig,(ax1,ax2)=plt.subplots(2,figsize=(15,12),sharex=True)ax1.plot(accuracy_steps)ax1.set_ylabel("test accuracy",fontsize=fontsize)ax1.set_title(fig_name,fontsize="xx-large")ax2.plot(loss_steps)ax2.set_ylabel("train lss",fontsize=fontsize)ax2.set_xlabel("epochs",fontsize=fontsize)plt.tight_layout()plt.savefig(fig_name+'.png')plt.show()

损失和精度变化图像