自从前天我学会BP算法的思想,我就一直在想如何用python实现监督性学习,也就是说对测试集进行预测,然后观测误差,查看过拟合的情况,因为我们知道过拟合的定义是说,如果在训练集准确率较高,但是在测试集上准确率较低,就说明这个模型是过拟合的。
我使用了一个比较直接的方法,也就是直接用得到的权重来计算测试集上面y的值。我将已有数据按0.3比例分成训练集和测试集。然后进行实验,通过迭代次数不同来看一下实验结果。
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
df = pd.read_excel('C:/Users/Dell/Desktop/郑佳重要/不确定理论/liuhuigui.xlsx')
x = df[['x1','x2','x3']]
y = df[['y']]
x_scaler = MinMaxScaler(feature_range=(-1,1))
y_scaler = MinMaxScaler(feature_range=(-1,1))
x = x_scaler.fit_transform(x)
y = y_scaler.fit_transform(y)
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3)
#归一化处理
#对样本数据进行转置
sample_in = x_train.T
sample_out = y_train.T
#网络参数bp
max_epochs = 1000 #迭代次数
learn_rate = 0.035
mse_final = 6.5e-4 #结束条件
sample_number = x_train.shape[0]
input_number = 3
output_number = 1
hidden_unit_number = 3 #隐层神经元个数,可更改
#学习 训练 超级参数
#3*3矩阵
w1 = 0.5 * np.random.rand(hidden_unit_number,input_number) - 0.1
#1*3矩阵
w2 = 0.5 * np.random.rand(output_number,input_number) - 0.1
#3*1矩阵
b1 = 0.5 * np.random.rand(hidden_unit_number,1) - 0.1
#1*1矩阵
b2 = 0.5 * np.random.rand(output_number,1) - 0.1
def sigmoid(z):
return 1.0/(1 + np.exp(-z))
#计算误差
mse_history = []
for i in range(max_epochs):
#隐层输出,就是前文里面的outh1
hidden_out = sigmoid(np.dot(w1, sample_in) + b1)
#前文的y
network_out = np.dot(w2, hidden_out) + b2
#误差
err = sample_out - network_out
mse = np.average(np.square(err))
mse_history.append(mse)
if mse < mse_final:
break
#bp反向传播,求偏导的过程
delta2 = -err
delta1 = np.dot(w2.transpose(), delta2) * hidden_out * (1 - hidden_out)
delta_w2 = np.dot(delta2, hidden_out.transpose())
delta_b2 = np.dot(delta2, np.ones((sample_number, 1)))
delta_w1 = np.dot(delta1, sample_in.transpose())
delta_b1 = np.dot(delta1, np.ones((sample_number,1)))
w2 -= learn_rate * delta_w2
b2 -= learn_rate * delta_b2
w1 -= learn_rate * delta_w1
b1 -= learn_rate * delta_b1
#预测值和真实值对比图
#隐层输出
hidden_out = sigmoid((np.dot(w1, sample_in) + b1))
#输出层输出
network_out = np.dot(w2, hidden_out) + b2
#反转获取实际值
network_out = y_scaler.inverse_transform(network_out.T)
sample_out = y_scaler.inverse_transform(y_train)
#plt.plot(network_out, color="r", label="预测值")
#plt.plot(sample_out, color="blue", label="真实值")
#plt.rcParams['font.sans-serif']=['SimHei'] #显示中文标签
#plt.rcParams['axes.unicode_minus']=False
#plt.legend()
#plt.show()
y_pre = np.dot(w2, sigmoid(np.dot(w1, x_test.T)+b1))+b2
y_pre = y_scaler.inverse_transform(y_pre.T)
y_out = y_scaler.inverse_transform(y_test)
plt.plot(y_pre, color="r", label="预测值")
plt.plot(y_out, color="blue", label="真实值")
plt.rcParams['font.sans-serif']=['SimHei'] #显示中文标签
plt.rcParams['axes.unicode_minus']=False
plt.legend()
plt.show()
迭代1000次,第一个图是训练集,第二个图是测试集
可以很明显看出存在过拟合现象,就需要对bp算法进行优化,或者是换一个样本量大的数据集试一下。我这个数据样本量确实太小了。