2024.01.08 线性回归

2024.01.08 线性回归

因为学习大模型的微调遇到了障碍,所以回头再快速看一遍深度学习的原理。都是一些基础内容。。。

https://zh.d2l.ai/chapter_linear-networks/linear-regression-scratch.html

线性回归原理

线性回归模型的训练过程就是最小化损失函数的过程。

1 线性回归模型

线性假设是指目标(房屋价格)可以表示为特征(面积和房龄)的加权和,如下面的式子:
price=warea⋅area+wage⋅age+b \mathrm{price}=w_{\mathrm{area}}\cdot\mathrm{area}+w_{\mathrm{age}}\cdot\mathrm{age}+b price=wareaarea+wageage+b
其中wareaw_{\mathrm{area}}wareawagew_{\mathrm{age}}wage称为权重(weight),权重决定了每个特征对我们预测值的影响。 bbb称为偏置(bias)、偏移量(offset)或截距(intercept)。给定一个数据集,我们的目标是寻找模型的权重www和偏置bbb, 使得根据模型做出的预测大体符合数据里的真实价格。

而在机器学习领域,我们通常使用的是高维数据集,建模时采用线性代数表示法会比较方便。当我们的输入包含ddd个特征时,我们将预测结果y^\hat{y}y^(通常使用“尖角”符号表示yyy的估计值)表示为:
y^=w1x1+…+wdxd+b \hat{y}=w_{1}x_{1}+\ldots+w_{d}x_{d}+b y^=w1x1++wdxd+b
将所有特征放到向量 x∈Rd\mathbf{x}\in\mathbb{R}^{d}xRd中, 并将所有权重放到向量w∈Rd\mathbf{w}\in\mathbb{R}^{d}wRd 中, 我们可以用点积形式来简洁地表达模型:
y^=w⊤x+b \hat{y}=\mathbf{w}^\top\mathbf{x}+b y^=wx+b
其中向量x\mathbf{x}x对应于单个数据样本的特征。用符号表示的矩阵X∈Rn×d\mathbf{X}\in\mathbb{R}^{n\times d}XRn×d可以很方便地引用我们整个数据集的n个样本。其中,X\mathbf{X}X的每一行是一个样本,每一列是一种特征。

对于特征集合X\mathbf{X}X,预测值y^∈Rn\hat{\mathbf{y}}\in\mathbb{R}^{n}y^Rn可以通过矩阵-向量乘法表示为:
y^=Xw+b \hat{\mathbf{y}}=\mathbf{X}\mathbf{w}+b y^=Xw+b

2 损失函数

损失函数(loss function)能够量化目标的实际值与预测值之间的差距。通常我们会选择非负数作为损失,且数值越小表示损失越小,完美预测时的损失为0。 回归问题中最常用的损失函数是平方误差函数。当样本iii的预测值为y^(i)\hat{y}^{(i)}y^(i),其相应的真实标签为y(i)y^{(i)}y(i)时, 平方误差可以定义为以下公式:
l(i)(w,b)=12(y^(i)−y(i))2 l^{(i)}(\mathbf{w},b)=\frac{1}{2}\left(\hat{y}^{(i)}-y^{(i)}\right)^2 l(i)(w,b)=21(y^(i)y(i))2
常数12\frac1221不会带来本质的差别,但这样在形式上稍微简单一些 (因为当我们对损失函数求导后常数系数为1)。

由于平方误差函数中的二次方项, 估计值y^(i)\hat{y}^{(i)}y^(i)和观测值y(i)y^{(i)}y(i)之间较大的差异将导致更大的损失。 为了度量模型在整个数据集上的质量,我们需计算在训练集n个样本上的损失均值(也等价于求和)。
L(w,b)=1n∑i=1nl(i)(w,b)=1n∑i=1n12(w⊤x(i)+b−y(i))2 L(\mathbf{w},b)=\frac1n\sum_{i=1}^nl^{(i)}(\mathbf{w},b)=\frac1n\sum_{i=1}^n\frac12\Big(\mathbf{w}^\top\mathbf{x}^{(i)}+b-y^{(i)}\Big)^2 L(w,b)=n1i=1nl(i)(w,b)=n1i=1n21(wx(i)+by(i))2
在训练模型时,我们希望寻找一组参数(w∗,b∗)\left(\mathbf{w^*}, b^*\right)(w,b), 这组参数能最小化在所有训练样本上的总损失。如下式:
w∗,b∗=argmin⁡w,bL(w,b). \mathbf{w}^{*},b^{*}=\operatorname*{argmin}_{\mathbf{w},b}L(\mathbf{w},b). w,b=w,bargminL(w,b).

3 随机梯度下降

梯度下降最简单的用法是计算损失函数(数据集中所有样本的损失均值) 关于模型参数的导数(在这里也可以称为梯度)。 但实际中的执行可能会非常慢:因为在每一次更新参数之前,我们必须遍历整个数据集。 因此,我们通常会在每次需要计算更新的时候随机抽取一小批样本, 这种变体叫做小批量随机梯度下降(minibatch stochastic gradient descent)。

在每次迭代中,我们首先随机抽样一个小批量B\mathcal{B}B, 它是由固定数量的训练样本组成的。 然后,我们计算小批量的平均损失关于模型参数的导数(也可以称为梯度)。 最后,我们将梯度乘以一个预先确定的正数η\etaη,并从当前参数的值中减掉。

我们用下面的数学公式来表示这一更新过程(∂\partial表示偏导数):
(w,b)←(w,b)−η∣B∣∑i∈B∂(w,b)l(i)(w,b) (\mathbf{w},b)\leftarrow(\mathbf{w},b)-\frac\eta{|\mathcal{B}|}\sum_{i\in\mathcal{B}}\partial_{(\mathbf{w},b)}l^{(i)}(\mathbf{w},b) (w,b)(w,b)BηiB(w,b)l(i)(w,b)
总结一下,算法的步骤如下: (1)初始化模型参数的值,如随机初始化; (2)从数据集中随机抽取小批量样本且在负梯度的方向上更新参数,并不断迭代这一步骤。 对于平方损失和仿射变换,我们可以明确地写成如下形式:
w←w−η∣B∣∑i∈B∂wl(i)(w,b)=w−η∣B∣∑i∈Bx(i)(w⊤x(i)+b−y(i)),b←b−η∣B∣∑i∈B∂bl(i)(w,b)=b−η∣B∣∑i∈B(w⊤x(i)+b−y(i)). \begin{gathered} \mathbf{w}\leftarrow\mathbf{w}-\frac{\eta}{|\mathcal{B}|}\sum_{i\in\mathcal{B}}\partial_{\mathbf{w}}l^{(i)}(\mathbf{w},b)=\mathbf{w}-\frac{\eta}{|\mathcal{B}|}\sum_{i\in\mathcal{B}}\mathbf{x}^{(i)}\left(\mathbf{w}^{\top}\mathbf{x}^{(i)}+b-y^{(i)}\right), \\ \begin{aligned}b\leftarrow b-\frac\eta{|\mathcal{B}|}\sum_{i\in\mathcal{B}}\partial_bl^{(i)}(\mathbf{w},b)=b-\frac\eta{|\mathcal{B}|}\sum_{i\in\mathcal{B}}\left(\mathbf{w}^\top\mathbf{x}^{(i)}+b-y^{(i)}\right).\end{aligned} \end{gathered} wwBηiBwl(i)(w,b)=wBηiBx(i)(wx(i)+by(i)),bbBηiBbl(i)(w,b)=bBηiB(wx(i)+by(i)).
上述公式中的w\mathbf{w}wx\mathbf{x}x都是向量。∣B∣|\mathcal{B}|B表示每个小批量中的样本数,这也称为批量大小(batch size)。η\etaη表示学习率(learning rate)。批量大小和学习率的值通常是手动预先指定,而不是通过模型训练得到的。 这些可以调整但不在训练过程中更新的参数称为超参数(hyperparameter)。 调参(hyperparameter tuning)是选择超参数的过程。 超参数通常是我们根据训练迭代结果来调整的, 而训练迭代结果是在独立的验证数据集(validation dataset)上评估得到的。

线性回归从零开始实现

1 构造数据集

构造一个y=Xw+b+噪声的数据集

def synthetic_data(w, b, num_examples):  #@save
    """生成y=Xw+b+噪声"""
    X = torch.normal(0, 1, (num_examples, len(w)))
    y = torch.matmul(X, w) + b
    y += torch.normal(0, 0.01, y.shape)
    return X, y.reshape((-1, 1))

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)
print('features:', features[0],'\nlabel:', labels[0])

输出:

features: tensor([-0.7715,  0.4212]) 
label: tensor([1.2321])

2 定义数据集的bach_size

def data_iter(batch_size, features, labels):
    num_examples = len(features)
    indices = list(range(num_examples))
    # 这些样本是随机读取的,没有特定的顺序
    random.shuffle(indices)
    for i in range(0, num_examples, batch_size):
        batch_indices = torch.tensor(
            indices[i: min(i + batch_size, num_examples)])
        yield features[batch_indices], labels[batch_indices]
batch_size = 10

for X, y in data_iter(batch_size, features, labels):
    print(X, '\n', y)
    break

输出:

tensor([[-0.5022,  0.7038],
        [-0.2006, -1.7286],
        [-0.1174,  0.8104],
        [ 1.1591,  2.5481],
        [-0.8888, -1.1390],
        [-1.7663,  0.0730],
        [-0.3518,  0.8524],
        [ 1.8939, -0.9266],
        [ 0.6197,  0.0300],
        [-0.9234, -0.1029]]) 
 tensor([[ 0.8005],
        [ 9.6945],
        [ 1.2068],
        [-2.1388],
        [ 6.2942],
        [ 0.4365],
        [ 0.5955],
        [11.1636],
        [ 5.3342],
        [ 2.7098]])

3 初始化模型参数w和b

w = torch.normal(0, 0.01, size=(2,1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)

4 定义线性回归模型

def linreg(X, w, b):
    """线性回归模型"""
    return torch.matmul(X, w) + b

5 定义损失函数

def squared_loss(y_hat, y):
    """均方损失"""
    return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2

6 定义优化算法

def sgd(params, lr, batch_size):
    """小批量随机梯度下降"""
    with torch.no_grad():
        for param in params:
            param -= lr * param.grad / batch_size
            param.grad.zero_()

7 训练

lr = 0.03
num_epochs = 3
net = linreg
loss = squared_loss

for epoch in range(num_epochs):
    for X, y in data_iter(batch_size, features, labels):
        l = loss(net(X, w, b), y)  # X和y的小批量损失
        # 因为l形状是(batch_size,1),而不是一个标量。l中的所有元素被加到一起,
        # 并以此计算关于[w,b]的梯度
        l.sum().backward()
        sgd([w, b], lr, batch_size)  # 使用参数的梯度更新参数
    with torch.no_grad():
        train_l = loss(net(features, w, b), labels)
        print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')

输出:

epoch 1, loss 0.038077
epoch 2, loss 0.000137
epoch 3, loss 0.000047

误差分析:

print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')
print(f'b的估计误差: {true_b - b}')

输出:

w的估计误差: tensor([0.0002, 0.0004], grad_fn=<SubBackward0>)
b的估计误差: tensor([-0.0002], grad_fn=<RsubBackward1>)

线性回归的简洁实现

1 构造数据集

import numpy as np
import torch
from torch.utils import data


def synthetic_data(w, b, num_examples):
    """生成y=Xw+b+噪声"""
    X = torch.normal(0, 1, (num_examples, len(w)))
    y = torch.matmul(X, w) + b
    y += torch.normal(0, 0.01, y.shape)
    return X, y.reshape((-1, 1))

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)

2 构造dataset迭代器

def load_array(data_arrays, batch_size, is_train=True):
    """构造一个PyTorch数据迭代器"""
    dataset = data.TensorDataset(*data_arrays)
    return data.DataLoader(dataset, batch_size, shuffle=is_train)

batch_size = 10
data_iter = load_array((features, labels), batch_size)

3 定义模型

from torch import nn
net = nn.Sequential(nn.Linear(2,1))

4 初始化参数

net[0].weight.data.normal_(0, 0.01)
net[0].bias.data.fill_(0)

5 定义损失函数

loss = nn.MSELoss()

6 定义优化算法

trainer = torch.optim.SGD(net.parameters(), lr=0.03)

7 训练

num_epochs = 3
for epoch in range(num_epochs):
    for X, y in data_iter:
        l = loss(net(X) ,y)
        trainer.zero_grad()
        l.backward()
        trainer.step()
    l = loss(net(features), labels)
    print(f'epoch {epoch + 1}, loss {l:f}')

输出

epoch 1, loss 0.000425
epoch 2, loss 0.000099
epoch 3, loss 0.000098
w = net[0].weight.data
print('w的估计误差:', true_w - w.reshape(true_w.shape))
b = net[0].bias.data
print('b的估计误差:', true_b - b)

输出

w的估计误差: tensor([0.0004, 0.0006])
b的估计误差: tensor([-9.5367e-06])

欢迎关注公众号

在这里插入图片描述

题目1:长沙市财政收入影响因素分析(限3人) [问题描述] 本项目旨在通过研究,发现影响长沙市目前以及未来财源建设的因素,并对其进行深入分析,提出对长沙市地方财源优化的具体建议,供政府决策参考,同时为其他经济发展较快的城市提供借鉴。 [数据抽取] 年份 地区生产总值亿元) 第一产业增加值(亿元) 第二产业增加值(亿元) 第三产业增加值(亿元) 常住人口(万人) 社会消费品零售总额(亿元) 城镇消费品零售额(亿元) 乡村消费品零售额(亿元) 固定资产投资增速 工业增加值增长速度 进出口总额(亿美元) 进口额(亿美元) 出口额(亿美元) 农林牧渔业增加值(亿元) 全年接待国内外旅游者(万人) 旅游总收入 2011年 5619.33 243.38 3151.68 2224.27 709.07 2125.91 2035.97 89.94 26.1 20.4 243.38 6013.6 543.5 2012年 6399.91 272.31 3592.52 2535.08 714.66 2454.71 2354.44 100.27 20.3 15.7 272.31 7989.18 741.13 2013年 7153.13 291.15 3946.97 2915.01 722.14 2801.97 2714.08 87.89 20.1 13.2 291.2 9485.36 958 2014年 7824.81 318.04 4245.68 3261.09 731.15 3162.07 3020.65 141.42 18.3 11.4 772.52 234.04 538.48 318.04 10487.1 1143.62 2015年 8510.13 341.78 4478.2 3690.15 743.18 3690.59 3457.38 233.21 17.1 8.8 805.8 268.22 537.58 348.31 11721.31 1351.5 2016年 9323.7 370.95 4513.23 4439.52 764.52 4117.4 3787.31 330.09 13.9 7.5 726.71 240.96 485.74 378.43 12450 1534.83 2017年 10535.51 379.45 4998.26 5157.8 791.81 4547.68 4133.32 414.36 13.1 8.1 938.02 350.13 587.89 388.43 13802.26 1770.06 2018年 11003.41 318.73 4660.19 6024.49 815.47 4765.04 4240.18 524.86 11.5 7.2 1283.34 460.19 823.15 337.21 14973.46 1808.05 2019年 11574.22 359.69 4439.32 6775.21 839.45 5247.03 4540.86 706.17 10.1 9 2002.03 605.6 1396.43 380.17 16832.61 2028.97 2020年 12142.52 423.46 4739.27 6979.79 1004.79 4469.76 3968.01 501.76 6.2 4.9 2350.46 801.74 1548.72 445.71 15194.31 1661.32 2021年 13270.7 425.56 5251.3 7593.85 1023.93 5111.57 4538.99 572.58 8.2 6.9 2780.28 802.82 1977.46 452.49 11479.3 1290.2 2022年 13966.11 451.3 5589.58 7925.24 1042.06 5235.56 4697.78 537.78 5.1 7.1 3313.9 851.4 2462.5 481.75 11994.42 1316.87 2023年 14517.55 451.89 5365.53 8514.55 1051.31 5561.67 4968.56 593.11 -6.8 5.4 2811.51 914.7 1896.81 485.63 19453.33 2193.05 [基本要求] 分析和识别影响长沙市财政收入的关键属性并预测2024年和2025年的财政收入
05-27
### 回答问题 #### 1. 数据加载与预处理 首先,我们需要将给定的数据加载到一个数据框中,并进行必要的预处理。以下是使用Python和Pandas库的代码示例: ```python import pandas as pd from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error # 创建数据框 data = { '年份': [2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023], '地区生产总值(亿元)': [5619.33, 6399.91, 7153.13, 7824.81, 8510.13, 9323.7, 10535.51, 11003.41, 11574.22, 12142.52, 13270.7, 13966.11, 14517.55], '第一产业增加值(亿元)': [243.38, 272.31, 291.15, 318.04, 341.78, 370.95, 379.45, 318.73, 359.69, 423.46, 425.56, 451.3, 451.89], '第二产业增加值(亿元)': [3151.68, 3592.52, 3946.97, 4245.68, 4478.2, 4513.23, 4998.26, 4660.19, 4439.32, 4739.27, 5251.3, 5589.58, 5365.53], '第三产业增加值(亿元)': [2224.27, 2535.08, 2915.01, 3261.09, 3690.15, 4439.52, 5157.8, 6024.49, 6775.21, 6979.79, 7593.85, 7925.24, 8514.55], '常住人口(万人)': [709.07, 714.66, 722.14, 731.15, 743.18, 764.52, 791.81, 815.47, 839.45, 1004.79, 1023.93, 1042.06, 1051.31], '社会消费品零售总额(亿元)': [2125.91, 2454.71, 2801.97, 3162.07, 3690.59, 4117.4, 4547.68, 4765.04, 5247.03, 4469.76, 5111.57, 5235.56, 5561.67], '固定资产投资增速': [26.1, 20.3, 20.1, 18.3, 17.1, 13.9, 13.1, 11.5, 10.1, 6.2, 8.2, 5.1, -6.8], '进出口总额(亿美元)': [None, None, None, 772.52, 805.8, 726.71, 938.02, 1283.34, 2002.03, 2350.46, 2780.28, 3313.9, 2811.51] } df = pd.DataFrame(data) # 填充缺失值 df.fillna(method='ffill', inplace=True) # 打印前几行数据 print(df.head()) ``` #### 2. 特征选择与模型训练 接下来,我们选择可能影响财政收入的关键属性,并使用线性回归模型进行训练。 ```python # 假设财政收入与以下特征相关 features = ['地区生产总值(亿元)', '第一产业增加值(亿元)', '第二产业增加值(亿元)', '第三产业增加值(亿元)', '常住人口(万人)', '社会消费品零售总额(亿元)', '固定资产投资增速', '进出口总额(亿美元)'] X = df[features] y = df['地区生产总值(亿元)'] # 假设地区生产总值作为财政收入的代理变量 # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 训练线性回归模型 model = LinearRegression() model.fit(X_train, y_train) # 预测并评估模型 y_pred = model.predict(X_test) mse = mean_squared_error(y_test, y_pred) print(f"Mean Squared Error: {mse}") # 输出各特征的重要性 coefficients = pd.DataFrame({'Feature': features, 'Coefficient': model.coef_}) print(coefficients) ``` #### 3. 财政收入预测 基于已有的模型,我们可以预测2024年和2025年的财政收入。假设我们已经获得了未来两年的相关特征数据: ```python # 假设2024年和2025年的特征数据 future_data = pd.DataFrame({ '地区生产总值(亿元)': [15000, 16000], '第一产业增加值(亿元)': [450, 460], '第二产业增加值(亿元)': [5500, 5700], '第三产业增加值(亿元)': [9000, 9500], '常住人口(万人)': [1060, 1070], '社会消费品零售总额(亿元)': [5800, 6000], '固定资产投资增速': [7.0, 6.5], '进出口总额(亿美元)': [3000, 3200] }) # 使用模型预测 predictions = model.predict(future_data) print(f"Predicted fiscal revenue for 2024 and 2025: {predictions}") ``` ### 给出解释 上述代码实现了从数据加载到预测的完整流程: 1. **数据加载与预处理**:我们将给定的数据加载到一个Pandas数据框中,并填充了缺失值。 2. **特征选择与模型训练**:我们选择了可能影响财政收入的关键属性,并使用线性回归模型进行训练。 3. **财政收入预测**:基于已有的模型,我们预测了2024年和2025年的财政收入。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值