使用python创建一个使用归一化、Xavier初始化、正则化方法和MSGD的BP网络,该网络有8个输入1个输出1层隐藏层。要求代码分为两个模块(py文件),且一个是BP网络,另一个是主函数,尽量在每句代码后添加注释。并且能够输出各输入的权重。尝试在main模块中实现将训练后的BP网络模型输出为一个文件,绘制R2图来说明模型的拟合度,并且输出MAE、MSE、预测值和真实值之间的相对误差平均百分比,绘制测试集的各输入对应的实际输出和预测输出的拟合折线图,且R2图和折线图中使用的数据均为未变换数据。 整体主要实现对8个输入1个输出1层隐藏层的BP网络的训练,且能够在训练后,将测试数据输入后得出比较符合的输出值。 假设训练集数据存于xlsx表格前3000行中,测试集为其之后的40行,且均为float类型,训练后模型不会出现shape类报错。
时间: 2023-11-27 10:50:14 浏览: 93
BP网络模块:
```python
import numpy as np
import pandas as pd
class BP:
def __init__(self, input_size, hidden_size, output_size):
# 初始化网络
self.input_size = input_size
self.hidden_size = hidden_size
self.output_size = output_size
self.lr = 0.01 # 学习率
self.reg_lambda = 0.01 # 正则化强度
self.W1 = np.random.randn(self.input_size, self.hidden_size) / np.sqrt(self.input_size) # Xavier初始化
self.b1 = np.zeros((1, self.hidden_size))
self.W2 = np.random.randn(self.hidden_size, self.output_size) / np.sqrt(self.hidden_size) # Xavier初始化
self.b2 = np.zeros((1, self.output_size))
def sigmoid(self, z):
# 激活函数
return 1 / (1 + np.exp(-z))
def sigmoid_gradient(self, z):
# 激活函数的导数
return self.sigmoid(z) * (1 - self.sigmoid(z))
def normalize(self, X):
# 归一化
return (X - np.mean(X, axis=0)) / np.std(X, axis=0)
def regularization(self):
# 正则化
return (self.reg_lambda / 2) * (np.sum(np.square(self.W1)) + np.sum(np.square(self.W2)))
def forward(self, X):
# 前向传播
self.z1 = np.dot(X, self.W1) + self.b1
self.a1 = self.sigmoid(self.z1)
self.z2 = np.dot(self.a1, self.W2) + self.b2
self.y_pred = self.z2
def backward(self, X, y):
# 反向传播
delta3 = self.y_pred - y
dW2 = np.dot(self.a1.T, delta3)
db2 = np.sum(delta3, axis=0, keepdims=True)
delta2 = np.dot(delta3, self.W2.T) * self.sigmoid_gradient(self.z1)
dW1 = np.dot(X.T, delta2)
db1 = np.sum(delta2, axis=0)
dW2 += self.reg_lambda * self.W2 # 正则化项的梯度
dW1 += self.reg_lambda * self.W1 # 正则化项的梯度
self.W1 -= self.lr * dW1
self.b1 -= self.lr * db1
self.W2 -= self.lr * dW2
self.b2 -= self.lr * db2
def train(self, X_train, y_train, epochs):
# 训练网络
for i in range(epochs):
self.forward(X_train)
self.backward(X_train, y_train)
cost = np.mean(np.square(self.y_pred - y_train)) + self.regularization() # 加上正则化项的损失函数
if i % 100 == 0:
print("Epoch:", i, "Cost:", cost)
def predict(self, X_test):
# 预测
self.forward(X_test)
return self.y_pred
```
主函数模块:
```python
from bp import BP
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 读取数据
data = pd.read_excel('data.xlsx', nrows=3040)
X = data.iloc[:3000, :-1].values
y = data.iloc[:3000, -1].values.reshape(-1, 1)
X_test = data.iloc[3000:, :-1].values
y_test = data.iloc[3000:, -1].values.reshape(-1, 1)
# 归一化
X = BP().normalize(X)
X_test = BP().normalize(X_test)
# 创建BP网络
bp = BP(input_size=8, hidden_size=10, output_size=1)
# 训练BP网络
bp.train(X, y, epochs=1000)
# 输出各输入的权重
print("W1:", bp.W1)
print("W2:", bp.W2)
# 将训练后的BP网络模型输出为一个文件
np.save('model.npy', (bp.W1, bp.b1, bp.W2, bp.b2))
# 预测
y_pred = bp.predict(X_test)
# 绘制R2图
from sklearn.metrics import r2_score
r2 = r2_score(y_test, y_pred)
print("R2:", r2)
plt.scatter(y_test, y_pred)
plt.plot(y_test, y_test, color='red')
plt.xlabel('True Values')
plt.ylabel('Predictions')
plt.show()
# 计算MAE、MSE、预测值和真实值之间的相对误差平均百分比
from sklearn.metrics import mean_absolute_error, mean_squared_error
mae = mean_absolute_error(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
relative_error = np.mean(np.abs((y_test - y_pred) / y_test)) * 100
print("MAE:", mae)
print("MSE:", mse)
print("Relative Error (%):", relative_error)
# 绘制测试集的各输入对应的实际输出和预测输出的拟合折线图
plt.plot(y_test, label='True Values')
plt.plot(y_pred, label='Predictions')
plt.legend()
plt.show()
```
注意事项:
1. 在读取数据时,需要使用pandas库读取excel文件,且需要指定读取的行数。
2. 在归一化时,需要将训练集和测试集分别进行归一化。
3. 在训练网络时,需要加上正则化项的损失函数。
4. 在输出各输入的权重时,需要在BP网络模块中添加方法,返回各层的权重。
5. 在将训练后的BP网络模型输出为一个文件时,可以使用numpy库的save方法将权重保存到.npy文件中。
6. 在绘制R2图时,需要使用sklearn.metrics库的r2_score方法计算R2值,并使用matplotlib库绘制散点图和拟合直线。
7. 在计算MAE、MSE、预测值和真实值之间的相对误差平均百分比时,需要使用sklearn.metrics库的mean_absolute_error和mean_squared_error方法。
8. 在绘制测试集的各输入对应的实际输出和预测输出的拟合折线图时,需要使用matplotlib库绘制。
阅读全文