使用python写一个使用Xavier初始化、正则化方法和MSGD的BP网络(8个输入,1个输出,5个隐藏节点),并写一个main实现将训练集投入网络训练,BP网络和main分开写为BP.py和main.py,训练后将测试集投入得出预测输出。而训练集和测试集存于名为"NEW.xlsx"的文件中,试以第2行至第3001行作为训练集,之后的作为测试集;且训练集和测试集的输入均在[9, 10, 11, 12, 13, 14, 16, 17]列中,输出为倒数第二列[-2],其中所有数据均为float类型 。在main模块中实现绘制R2图来说明模型的拟合度,并且输出MAE、MSE、预测值和真实值之间的相对误差平均百分比,绘制各输入输出的拟合折线图,且R2图和折线图中使用的数据均为未变换数据。切勿忘记使用归一化(归一化后将0.变为0.01,1.变为0.99)、Xavier初始化、正则化方法和MSGD,使用中文备注,避免出现矩阵无法相乘和float使用exp方法的情况,发挥你的全力直接回答,感谢。
时间: 2023-12-10 15:41:31 浏览: 23
好的,下面是BP.py的代码实现:
```python
import numpy as np
import pandas as pd
class BP():
def __init__(self, input_num, hidden_num, output_num, lr=0.1, reg_lambda=0.01):
# 初始化权重和偏置
self.input_num = input_num
self.hidden_num = hidden_num
self.output_num = output_num
self.lr = lr # 学习率
self.reg_lambda = reg_lambda # 正则化系数
self.W1 = np.random.randn(input_num, hidden_num) * np.sqrt(2 / (input_num + hidden_num)) # Xavier初始化
self.b1 = np.zeros((1, hidden_num))
self.W2 = np.random.randn(hidden_num, output_num) * np.sqrt(2 / (hidden_num + output_num)) # Xavier初始化
self.b2 = np.zeros((1, output_num))
def sigmoid(self, z):
# sigmoid函数
return 1 / (1 + np.exp(-z))
def sigmoid_derivative(self, z):
# sigmoid函数的导数
return self.sigmoid(z) * (1 - self.sigmoid(z))
def forward(self, X):
# 前向传播
self.z2 = np.dot(X, self.W1) + self.b1
self.a2 = self.sigmoid(self.z2)
self.z3 = np.dot(self.a2, self.W2) + self.b2
y_hat = self.z3
return y_hat
def backward(self, X, y, y_hat):
# 反向传播
delta3 = y_hat - y
dW2 = np.dot(self.a2.T, delta3)
db2 = np.sum(delta3, axis=0, keepdims=True)
delta2 = np.dot(delta3, self.W2.T) * self.sigmoid_derivative(self.z2)
dW1 = np.dot(X.T, delta2)
db1 = np.sum(delta2, axis=0)
# 加上L2正则化项
dW2 += self.reg_lambda * self.W2
dW1 += self.reg_lambda * self.W1
return dW1, db1, dW2, db2
def update_weights(self, dW1, db1, dW2, db2):
# 更新权重和偏置
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, epoch):
# 训练模型
for i in range(epoch):
y_hat = self.forward(X_train)
dW1, db1, dW2, db2 = self.backward(X_train, y_train, y_hat)
self.update_weights(dW1, db1, dW2, db2)
def predict(self, X_test):
# 预测
y_hat = self.forward(X_test)
return y_hat
```
下面是main.py的代码实现:
```python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from BP import BP
# 读取数据
data = pd.read_excel('NEW.xlsx', header=None)
X_train = data.iloc[1:3001, [9, 10, 11, 12, 13, 14, 16, 17]].values
y_train = data.iloc[1:3001, -2].values.reshape(-1, 1)
X_test = data.iloc[3001:, [9, 10, 11, 12, 13, 14, 16, 17]].values
y_test = data.iloc[3001:, -2].values.reshape(-1, 1)
# 归一化
X_train = (X_train - np.min(X_train)) / (np.max(X_train) - np.min(X_train)) * 0.98 + 0.01
y_train = (y_train - np.min(y_train)) / (np.max(y_train) - np.min(y_train)) * 0.98 + 0.01
X_test = (X_test - np.min(X_test)) / (np.max(X_test) - np.min(X_test)) * 0.98 + 0.01
y_test = (y_test - np.min(y_test)) / (np.max(y_test) - np.min(y_test)) * 0.98 + 0.01
# 初始化BP网络
bp = BP(input_num=8, hidden_num=5, output_num=1, lr=0.1, reg_lambda=0.01)
# 训练模型
bp.train(X_train, y_train, epoch=1000)
# 预测
y_pred = bp.predict(X_test)
# 反归一化
X_train = (X_train - 0.01) / 0.98 * (np.max(X_train) - np.min(X_train)) + np.min(X_train)
y_train = (y_train - 0.01) / 0.98 * (np.max(y_train) - np.min(y_train)) + np.min(y_train)
X_test = (X_test - 0.01) / 0.98 * (np.max(X_test) - np.min(X_test)) + np.min(X_test)
y_test = (y_test - 0.01) / 0.98 * (np.max(y_test) - np.min(y_test)) + np.min(y_test)
y_pred = (y_pred - 0.01) / 0.98 * (np.max(y_test) - np.min(y_test)) + np.min(y_test)
# 计算MAE、MSE和R2
MAE = np.mean(np.abs(y_pred - y_test))
MSE = np.mean((y_pred - y_test) ** 2)
R2 = 1 - MSE / np.var(y_test)
print('MAE:', MAE)
print('MSE:', MSE)
print('R2:', R2)
# 计算预测值和真实值之间的相对误差平均百分比
error = np.mean(np.abs((y_test - y_pred) / y_test)) * 100
print('相对误差平均百分比:', error)
# 绘制R2图
plt.figure(figsize=(6, 4))
plt.scatter(y_test, y_pred, c='r', marker='o')
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'k--', lw=3)
plt.xlabel('True value')
plt.ylabel('Predicted value')
plt.title('R2={:.4f}'.format(R2))
plt.show()
# 绘制各输入输出的拟合折线图
plt.figure(figsize=(16, 10))
for i in range(8):
plt.subplot(2, 4, i+1)
plt.scatter(X_test[:, i], y_test, c='b', marker='o')
plt.scatter(X_test[:, i], y_pred, c='r', marker='o')
plt.xlabel('X{}'.format(i+1))
plt.ylabel('y')
plt.legend(['True value', 'Predicted value'])
plt.show()
```
注意:在计算MAE、MSE和R2前需要先将预测值和真实值反归一化。