神经网络与深度学习(三)线性回归与多项式回归

目录

2.2 线性回归

2.2.1 数据集构建

2.2.2 模型构建

2.2.3 损失函数

 2.2.4 模型优化

2.2.5 模型训练

2.2.6 模型评估

2.2.7 样本数量 & 正则化系数

2.3 多项式回归

2.3.1 数据集构建

2.3.2 模型构建

2.3.3 模型训练

2.3.4 模型评估

2.4 Runner类介绍

2.5 基于线性回归的波士顿房价预测

2.5.1 数据处理

2.5.1.2 数据清洗

2.5.1.3 数据集划分

2.5.1.4 特征工程

2.5.2 模型构建

2.5.3 完善Runner类

2.5.4 模型训练 

2.5.5 模型测试

2.5.6 模型预测


2.2 线性回归

2.2.1 数据集构建

构造一个小的回归数据集:

生成 150 个带噪音的样本,其中 100 个训练样本,50 个测试样本,并打印出训练数据的可视化分布。

import torch
from matplotlib import pyplot as plt


# 真实函数的参数缺省值为 w=1.2,b=0.5
def linear_func(x, w=1.2, b=0.5):
    y = w*x + b
    return y


def create_toy_data(func, interval, sample_num, noise=0.0, add_outlier=False, outlier_ratio=0.001):
    # 均匀采样
    X = torch.rand([sample_num]) * (interval[1]-interval[0]) + interval[0]
    y = func(X)

    # 生成高斯分布的标签噪声
    epsilon = torch.normal(0, noise, y.shape)
    y = y + epsilon
    if add_outlier:     # 生成额外的异常点
        outlier_num = int(len(y)*outlier_ratio)
        if outlier_num != 0:
            outlier_idx = torch.randint(len(y), [outlier_num])
            y[outlier_idx] = y[outlier_idx] * 5
    return X, y


func = linear_func
interval = (-10, 10)
train_num = 100  # 训练样本数目
test_num = 50  # 测试样本数目
noise = 2
X_train, y_train = create_toy_data(func=func, interval=interval, sample_num=train_num, noise=noise, add_outlier=False)
X_test, y_test = create_toy_data(func=func, interval=interval, sample_num=test_num, noise=noise, add_outlier=False)

X_train_large, y_train_large = create_toy_data(func=func, interval=interval, sample_num=5000, noise=noise, add_outlier=False)


X_underlying = torch.linspace(interval[0], interval[1], train_num)
y_underlying = linear_func(X_underlying)

# 绘制数据
plt.scatter(X_train, y_train, marker='*', facecolor="none", edgecolor='red', s=50, label="train data")
plt.scatter(X_test, y_test, facecolor="none", edgecolor='blue', s=50, label="test data")
plt.plot(X_underlying, y_underlying, c='#000000', label=r"underlying distribution")
plt.legend(fontsize='x-large')  # 给图像加图例
plt.savefig('ml-vis.pdf')  # 保存图像到PDF文件中
plt.show()

运行结果:

(注:使用torch.normal(0,noise,y.shape)生成0均值,noise标准差的数据)

2.2.2 模型构建

线性模型定义为:

其中权重向量w和偏置b都是可学习的参数。

在实践中,为了提高预测样本的效率,我们通常会将N样本归为一组进行成批地预测,这样可以更好地利用GPU设备的并行计算能力。

y=Xw+b

其中X为N个样本的特征矩阵,y为N个预测值组成的列向量。

(注:在实践中,样本的矩阵X是由N个x的行向量组成。)

import torch
torch.manual_seed(11)  # 设置随机种子


# 线性算子
class Linear( ):
    def __init__(self, input_size):
        self.input_size = input_size
        # 模型参数
        self.params = {}
        self.params['w'] = torch.randn(self.input_size, 1, dtype=torch.float32)
        self.params['b'] = torch.zeros(1, dtype=torch.float32)

    def __call__(self, X):
        return self.forward(X)

    # 前向函数
    def forward(self, X):
        N, D = X.shape
        if self.input_size == 0:
            return torch.full((N, 1), self.params['b'])
        assert D == self.input_size  # 输入数据维度合法性验证
        y_pred = torch.matmul(X, self.params['w']) + self.params['b']
        return y_pred



input_size = 3
N = 2
X = torch.randn(N, input_size, dtype=torch.float32)  # 生成2个维度为3的数据
model = Linear(input_size)
y_pred = model(X)
print("y_pred:", y_pred)   # 输出结果的个数也是2个

运行结果:

2.2.3 损失函数

回归任务中常用的评估指标是均方误差,均方误差是反映估计量与被估计量之间差异程度的一种度量。(回归任务是对连续值的预测

import torch


def mean_squared_error(y_true, y_pred):
    assert y_true.shape[0] == y_pred.shape[0]
    error = torch.mean(torch.square(y_true - y_pred))
    return error


# 构造一个简单的样例进行测试:[N,1], N=2
y_true = torch.tensor([[-0.2], [4.9]], dtype=torch.float32)
y_pred = torch.tensor([[1.3], [2.5]], dtype=torch.float32)

error = mean_squared_error(y_true=y_true, y_pred=y_pred).item()
print("error:", error)

运行结果:(注:代码实现中没有除2)

思考:没有除2合理么?

合理,除以2作用是消除均方误差中平方项时存在的2的倍数,不除以2也能够在优化时进行正确计算。

 2.2.4 模型优化

经验风险即在训练集上的平均损失。

def optimizer_lsm(model, X, y, reg_lambda=0):  # 优化模型
    N, D = X.shape
    # 对输入特征数据所有特征向量求平均
    x_bar_tran = torch.mean(X, axis=0).T

    # 求标签的均值,shape=[1]
    y_bar = torch.mean(y)

    x_sub = torch.subtract(X, x_bar_tran)

    if torch.all(x_sub) == 0:
        model.params['b'] = y_bar
        model.params['w'] = torch.zeros(D)
        return model

    tmp = torch.inverse(torch.matmul(x_sub.T, x_sub) + reg_lambda * torch.eye(D))

    w = torch.matmul(torch.matmul(tmp, x_sub.T), (y - y_bar))

    b = y_bar - torch.matmul(x_bar_tran, w)

    model.params['b'] = b
    model.params['w'] = torch.squeeze(w, axis=-1)

    return model

(注:torch.eye(n,m)函数的作用为:返回一个2维张量,对角线位置全1,其它位置全0,n表示行数,m表示列数,默认等于n) 

思考1:为什么省略了不影响效果?

1/N为常数, 求偏导后不会影响收敛结果。

思考2:什么是最小二乘法?
最小二乘法是基于均方误差最小化进行模型求解的方法。

2.2.5 模型训练

在准备了数据、模型、损失函数和参数学习的实现之后,开始模型的训练。在回归任务中,模型的评价指标和损失函数一致,都为均方误差。

通过上文实现的线性回归类来拟合训练数据,并输出模型在训练集上的损失。

input_size = 1
model = Linear(input_size)
model = optimizer_lsm(model, X_train.reshape([-1, 1]), y_train.reshape([-1, 1]))
print("w_pred:", model.params['w'].item(), "b_pred: ", model.params['b'].item())
y_train_pred = model(X_train.reshape([-1, 1])).squeeze()
train_error = mean_squared_error(y_true=y_train, y_pred=y_train_pred).item()
print("train error: ", train_error)

运行结果:

 


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值