神经网络预测波士顿房价——纯Numpy实现

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

syphomn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值