import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_boston
def sigmoid(activation):
'''激活函数'''
return 1 / (1 + np.exp(-1 * activation))
def standardization(z_score):
'''标准化'''
for columns in range(z_score.shape[1]):
z_score[:,
columns] = (z_score[:, columns] - z_score[:, columns].mean()
) / z_score[:, columns].std()
return z_score
def train_test_splitting(data, target, train_size):
'''划分训练集与测试集'''
X_train = data[0:int(len(data) * train_size), :]
X_test = data[int(len(data) * train_size):, :]
y_train = target[0:int(len(data) * train_size)].reshape(-1, 1)
y_test = target[int(len(data) * train_size):].reshape(-1, 1)
return X_train, X_test, y_train, y_test
def data_geting(train_size=0.7):
'''获取数据'''
boston = load_boston()
target = boston.target.reshape(-1, 1)
data = standardization(boston.data)
data_target = np.hstack((data, target))
np.random.seed(2020)
np.random.shuffle(data_target)
data, target = data_target[:, :-2], data_target[:, -1]
X_train, X_test, y_train, y_test = train_test_splitting(
data, target, train_size)
return X_train, X_test, y_train, y_test
def batch_dividing(batch):
'''划分数据批次'''
X_train, X_test, y_train, y_test = data_geting()
X_train_batch, y_train_batch = [], []
num_batch = X_train.shape[0] // batch
for i in range(0, batch * num_batch, batch):
X_train_batch.append(X_train[i:i + batch])
y_train_batch.append(y_train[i:i + batch])
return np.array(X_train_batch), np.array(y_train_batch), X_test, y_test
def initialize_parameter(batch=6):
'''初始化参数'''
x_train, y_train, x_test, y_test = batch_dividing(batch)
weight1 = np.random.randn((x_train[0]).shape[1], 20)
weight2 = np.random.randn(20, 1)
bias1 = np.random.randn(1, 1)
bias2 = np.random.randn(1, 1)
list_parameter = [weight1, bias1, weight2, bias2]
return x_train, y_train, x_test, y_test, list_parameter
def forward_computing(x, list_parameter):
'''前向计算'''
weight1, bias1, weight2, bias2 = list_parameter
alpha1 = x @ weight1 + bias1
gamma1 = sigmoid(alpha1)
alpha2 = gamma1 @ weight2 + bias2
return alpha2, alpha1, gamma1
def loss_computing(alpha2, value):
'''损失计算'''
loss = ((value - alpha2)**2).sum()
return loss
def backward(feature, intermediate_result, list_parameter, label):
'''
后向传递
这部分比较难懂,看不懂的需自学复合函数求导的链式法则以及矩阵乘法的导数
写的时候检查一下维度防止出错
w1 n*p
x m*n
w2 p*1
'''
_, bias1, weight2, bias2 = list_parameter
alpha2, alpha1, gamma1 = intermediate_result
dloss_dsum = np.ones_like(label) # m*1
dsum_dalpha2 = -2 * (label - alpha2) # m*1
dloss_dalpha2 = dloss_dsum * dsum_dalpha2 # m*1
dalpha2_dbias2 = np.ones_like(bias2)
dloss_dbias2 = (dloss_dalpha2 * dalpha2_dbias2).sum() # m*1
dalpha2_dweight2 = np.transpose(gamma1) # p*m
dloss_dweight2 = dalpha2_dweight2 @ dloss_dalpha2 # p*1
dalpha2_dgamm1 = np.transpose(weight2) # 1*p
dloss_dgamma1 = dloss_dalpha2 @ dalpha2_dgamm1 # m*p
dgamm1_dalpha1 = sigmoid(alpha1) * (1 - sigmoid(alpha1)) # m*p
dloss_dalpha1 = dloss_dgamma1 * dgamm1_dalpha1 # m*p
dalpha1_dweight1 = np.transpose(feature) # n*m
dloss_dweight1 = dalpha1_dweight1 @ dloss_dalpha1 # n*p
dalpha1_dbias1 = np.ones_like(bias1)
dloss_dbias1 = (dloss_dalpha1 * dalpha1_dbias1).sum()
return dloss_dweight1, dloss_dbias1, dloss_dweight2, dloss_dbias2
def parameter_updating(learning_rate, list_gradient, list_parameter):
'''参数更新'''
for i in range(len(list_gradient)):
list_parameter[i] -= learning_rate * list_gradient[i]
return list_parameter
def train_and_test(learning_rate=0.001):
'''训练与测试'''
x_train, y_train, x_test, y_test, list_parameter = initialize_parameter()
for _ in range(100):
for batches in range(len(x_train)):
intermediate_result = forward_computing(x_train[batches],
list_parameter)
# loss = loss_computing(alpha2, y_train[batches])
list_gradient = backward(x_train[batches], intermediate_result,
list_parameter, y_train[batches])
list_parameter = parameter_updating(learning_rate, list_gradient,
list_parameter)
prediction, _, _ = forward_computing(x_test, list_parameter)
loss = loss_computing(prediction, y_test)
return prediction, loss, y_test
def result_showing():
'''结果展示'''
prediction, loss, y_test = train_and_test(learning_rate=0.01)
print((loss / len(y_test))**0.5)
plt.figure() # 绘制测试集效果图
plt.scatter(y_test, prediction, color='red')
plt.plot([0, 52], [0, 52], color='black', linestyle='-')
plt.plot([0, 52], [5, 57], color='black', linestyle='--')
plt.plot([0, 52], [-5, 47], color='black', linestyle='--')
plt.xlim([-0.05, 52])
plt.ylim([-0.05, 52])
plt.xlabel('true')
plt.ylabel('prediction')
plt.title('true vs prection')
plt.show()
if __name__ == "__main__":
result_showing()
均方误差:3.4311536156323803