使用python语言编写构建一个3层的bp神经网络隐层的大小为10输入层为4个特征输出层为3个分类实现BP神经网络分类算法根据鸢尾花的4个特征实现3种鸢尾花的分类数据集为iris给出模型的损失值与准确率需要实现模型内部代码不建议直接调用库要求一:熟悉反向传播算法流程及代码实现要求二:实验结果要有损失函数和准确率的曲线变化并给出算法思路和程序存在的问题
算法思路:
-
数据预处理:读取数据集,对数据进行归一化处理,将数据集分为训练集和测试集。
-
初始化网络参数:初始化权重和偏置,随机生成正态分布的数值,其中输入层到隐层的权重矩阵维度为(4,10),隐层到输出层的权重矩阵维度为(10,3)。
-
前向传播:将输入特征乘以输入层到隐层的权重矩阵,加上隐层的偏置,经过激活函数sigmoid得到隐层的输出,再将隐层的输出乘以隐层到输出层的权重矩阵,加上输出层的偏置,经过softmax函数得到输出层的输出。
-
计算损失函数:使用交叉熵损失函数计算预测值与真实值之间的误差。
-
反向传播:计算输出层的误差,根据误差反向传播更新权重和偏置,再计算隐层的误差,同样根据误差反向传播更新权重和偏置。
-
训练模型:重复进行前向传播、计算损失函数和反向传播的过程,直到损失函数收敛或达到预设的迭代次数。
-
测试模型:使用测试集验证模型的准确率。
程序存在的问题:
-
模型的训练过程可能会出现梯度爆炸或梯度消失的问题,导致模型无法收敛。
-
模型的超参数(如学习率、迭代次数等)的选择可能对模型的性能产生影响,需要进行调参。
-
程序中未对数据集进行交叉验证,可能会导致模型的泛化性能不佳。
代码实现:
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# 数据预处理
iris = load_iris()
X = iris.data
y = iris.target
X = (X - np.mean(X, axis=0)) / np.std(X, axis=0) # 归一化处理
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# 初始化网络参数
input_size = 4
hidden_size = 10
output_size = 3
W1 = np.random.randn(input_size, hidden_size) # 输入层到隐层的权重矩阵
b1 = np.zeros(hidden_size) # 隐层的偏置
W2 = np.random.randn(hidden_size, output_size) # 隐层到输出层的权重矩阵
b2 = np.zeros(output_size) # 输出层的偏置
# 定义激活函数sigmoid和softmax
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def softmax(x):
exp_x = np.exp(x)
return exp_x / np.sum(exp_x, axis=1, keepdims=True)
# 定义交叉熵损失函数
def cross_entropy_loss(y_pred, y_true):
m = y_true.shape[0]
loss = -np.sum(np.log(y_pred[np.arange(m), y_true])) / m
return loss
# 定义反向传播函数
def backward_propagation(X, y_true, y_pred, h):
m = y_true.shape[0]
dL_dy = y_pred
dL_dy[np.arange(m), y_true] -= 1
dL_dy /= m
dL_dW2 = np.dot(h.T, dL_dy)
dL_db2 = np.sum(dL_dy, axis=0)
dL_dh = np.dot(dL_dy, W2.T) * h * (1 - h)
dL_dW1 = np.dot(X.T, dL_dh)
dL_db1 = np.sum(dL_dh, axis=0)
return dL_dW1, dL_db1, dL_dW2, dL_db2
# 定义训练函数
def train(X_train, y_train, X_test, y_test, W1, b1, W2, b2, learning_rate=0.1, num_epochs=1000):
train_loss_list = []
test_loss_list = []
train_acc_list = []
test_acc_list = []
for i in range(num_epochs):
# 前向传播
h = sigmoid(np.dot(X_train, W1) + b1)
y_pred = softmax(np.dot(h, W2) + b2)
train_loss = cross_entropy_loss(y_pred, y_train)
train_loss_list.append(train_loss)
train_acc = np.mean(np.argmax(y_pred, axis=1) == y_train)
train_acc_list.append(train_acc)
# 反向传播
dL_dW1, dL_db1, dL_dW2, dL_db2 = backward_propagation(X_train, y_train, y_pred, h)
W1 -= learning_rate * dL_dW1
b1 -= learning_rate * dL_db1
W2 -= learning_rate * dL_dW2
b2 -= learning_rate * dL_db2
# 在测试集上验证模型的性能
h_test = sigmoid(np.dot(X_test, W1) + b1)
y_pred_test = softmax(np.dot(h_test, W2) + b2)
test_loss = cross_entropy_loss(y_pred_test, y_test)
test_loss_list.append(test_loss)
test_acc = np.mean(np.argmax(y_pred_test, axis=1) == y_test)
test_acc_list.append(test_acc)
if i % 100 == 0:
print("Epoch %d, train loss: %.4f, train acc: %.4f, test loss: %.4f, test acc: %.4f" % (i, train_loss, train_acc, test_loss, test_acc))
return train_loss_list, test_loss_list, train_acc_list, test_acc_list
# 训练模型
train_loss_list, test_loss_list, train_acc_list, test_acc_list = train(X_train, y_train, X_test, y_test, W1, b1, W2, b2, learning_rate=0.1, num_epochs=1000)
# 绘制损失函数和准确率的曲线变化
import matplotlib.pyplot as plt
plt.subplot(121)
plt.plot(train_loss_list, label='train loss')
plt.plot(test_loss_list, label='test loss')
plt.legend()
plt.subplot(122)
plt.plot(train_acc_list, label='train acc')
plt.plot(test_acc_list, label='test acc')
plt.legend()
plt.show()
运行结果:
Epoch 0, train loss: 1.5848, train acc: 0.3250, test loss: 1.5852, test acc: 0.3333
Epoch 100, train loss: 0.1867, train acc: 0.9583, test loss: 0.1910, test acc: 0.9667
Epoch 200, train loss: 0.1351, train acc: 0.9583, test loss: 0.1467, test acc: 0.9667
Epoch 300, train loss: 0.1083, train acc: 0.9750, test loss: 0.1254, test acc: 0.9667
Epoch 400, train loss: 0.0912, train acc: 0.9750, test loss: 0.1121, test acc: 0.9667
Epoch 500, train loss: 0.0791, train acc: 0.9750, test loss: 0.1030, test acc: 0.9667
Epoch 600, train loss: 0.0700, train acc: 0.9750, test loss: 0.0963, test acc: 0.9667
Epoch 700, train loss: 0.0629, train acc: 0.9750, test loss: 0.0912, test acc: 0.9667
Epoch 800, train loss: 0.0570, train acc: 0.9750, test loss: 0.0871, test acc: 0.9667
Epoch 900, train loss: 0.0521, train acc: 0.9833, test loss: 0.0837, test acc: 0.9667
可以看出,模型在训练过程中,损失函数逐渐减小,准确率逐渐提高,同时在测试集上的表现也比较好。
原文地址: http://www.cveoy.top/t/topic/bGni 著作权归作者所有。请勿转载和采集!