使用python创建一个使用归一化、Xavier初始化、正则化方法和MSGD的BP网络,该网络有8个输入1个输出1层隐藏层,要求分为两个模块(py文件,一个BPNN.py,一个main.py),且该BP网络可以在训练一个通过iloc读取数据的训练集后可以将同类型(同列数)的测试集作为输入得出预测值。 在main模块中实现绘制R2图来说明模型的拟合度,并且输出MAE、MSE、预测值和真实值之间的相对误差平均百分比,绘制各输入输出的拟合折线图,且R2图和折线图中使用的数据均为未变换数据。
时间: 2023-11-27 07:50:57 浏览: 211
为方便起见,我们假设训练集和测试集的数据都已经被处理,且已经将它们分别存储在train.csv和test.csv文件中。其中,每行代表一个数据样本,每列代表一个输入特征或输出。
首先,我们需要在BPNN.py中实现BP神经网络。
```python
import numpy as np
class BPNN:
def __init__(self, n_input, n_hidden, n_output):
self.n_input = n_input
self.n_hidden = n_hidden
self.n_output = n_output
# 初始化权重和偏置
self.W1 = np.random.randn(n_hidden, n_input) * np.sqrt(1 / n_input)
self.b1 = np.zeros((n_hidden, 1))
self.W2 = np.random.randn(n_output, n_hidden) * np.sqrt(1 / n_hidden)
self.b2 = np.zeros((n_output, 1))
# 初始化动量项
self.vW1 = np.zeros((n_hidden, n_input))
self.vb1 = np.zeros((n_hidden, 1))
self.vW2 = np.zeros((n_output, n_hidden))
self.vb2 = np.zeros((n_output, 1))
def sigmoid(self, z):
return 1 / (1 + np.exp(-z))
def softmax(self, z):
exp_z = np.exp(z)
return exp_z / np.sum(exp_z, axis=0, keepdims=True)
def forward(self, X):
Z1 = np.dot(self.W1, X) + self.b1
A1 = self.sigmoid(Z1)
Z2 = np.dot(self.W2, A1) + self.b2
A2 = self.softmax(Z2)
return A2, A1
def backward(self, X, Y, A2, A1, alpha, lmbda):
m = X.shape[1]
# 计算输出层的误差
dZ2 = A2 - Y
dW2 = 1 / m * np.dot(dZ2, A1.T) + lmbda / m * self.W2
db2 = 1 / m * np.sum(dZ2, axis=1, keepdims=True)
# 计算隐藏层的误差
dZ1 = np.dot(self.W2.T, dZ2) * A1 * (1 - A1)
dW1 = 1 / m * np.dot(dZ1, X.T) + lmbda / m * self.W1
db1 = 1 / m * np.sum(dZ1, axis=1, keepdims=True)
# 更新权重和偏置
self.vW1 = alpha * self.vW1 + (1 - alpha) * dW1
self.vb1 = alpha * self.vb1 + (1 - alpha) * db1
self.vW2 = alpha * self.vW2 + (1 - alpha) * dW2
self.vb2 = alpha * self.vb2 + (1 - alpha) * db2
self.W1 -= self.vW1
self.b1 -= self.vb1
self.W2 -= self.vW2
self.b2 -= self.vb2
def train(self, X, Y, alpha=0.9, lmbda=0, epochs=1000):
for i in range(epochs):
A2, A1 = self.forward(X)
self.backward(X, Y, A2, A1, alpha, lmbda)
def predict(self, X):
A2, _ = self.forward(X)
return A2
```
上述代码中,我们使用了sigmoid函数作为激活函数和softmax函数作为输出层的激活函数。同时,我们实现了前向传播和反向传播的方法,并且在反向传播时加入了L2正则化和MSGD优化算法。
接下来,我们需要在main.py中实现读取数据、归一化、Xavier初始化、正则化、训练模型、绘制图表等功能。
```python
import pandas as pd
import matplotlib.pyplot as plt
from BPNN import BPNN
# 读取数据
train_data = pd.read_csv('train.csv')
test_data = pd.read_csv('test.csv')
# 归一化
train_mean = train_data.mean()
train_std = train_data.std()
train_data = (train_data - train_mean) / train_std
test_data = (test_data - train_mean) / train_std
# Xavier初始化
n_input = 8
n_hidden = 4
n_output = 1
bpnn = BPNN(n_input, n_hidden, n_output)
# 正则化
lmbda = 0.01
# 训练模型
X_train = train_data.iloc[:, :n_input].values.T
Y_train = train_data.iloc[:, n_input:].values.T
bpnn.train(X_train, Y_train, lmbda=lmbda)
# 预测
X_test = test_data.iloc[:, :n_input].values.T
Y_test = test_data.iloc[:, n_input:].values.T
Y_pred = bpnn.predict(X_test)
# 计算误差
MAE = np.mean(np.abs(Y_pred - Y_test))
MSE = np.mean((Y_pred - Y_test) ** 2)
relative_error = np.mean(np.abs(Y_pred - Y_test) / Y_test) * 100
# 绘制R2图
plt.scatter(Y_test, Y_pred)
plt.plot([Y_test.min(), Y_test.max()], [Y_test.min(), Y_test.max()], 'k--', lw=3)
plt.xlabel('Measured')
plt.ylabel('Predicted')
plt.title('R2')
plt.show()
# 绘制拟合折线图
for i in range(n_input):
plt.figure()
plt.plot(test_data.iloc[:, i], label='actual')
plt.plot(Y_pred[:, 0], label='predicted')
plt.legend()
plt.title(f'Fit for Input Feature {i+1}')
plt.show()
# 输出误差和相对误差
print(f'MAE: {MAE:.4f}')
print(f'MSE: {MSE:.4f}')
print(f'Relative Error: {relative_error:.2f}%')
```
上述代码中,我们首先读取数据并进行归一化。然后,我们使用Xavier初始化方法初始化BP神经网络,并且在训练模型时加入L2正则化和MSGD优化算法。接着,我们根据训练好的模型对测试集进行预测,并计算出MAE、MSE和相对误差。最后,我们绘制R2图和各输入输出的拟合折线图。
需要注意的是,上述代码中的绘图部分可能需要根据具体数据的特点进行修改。
阅读全文