Pytorch实现线性回归

1.训练数据的准备

登录Kaggle平台,搜索house price,选择Datasets数据集标签,选择House price prediction这份数据下载下来。

这份数据中,删除与房价预测无关和过于稀疏的列,(包括data、waterfront、view、street、country),最后会保留12个标签和一个price标签。

数据处理

python 复制代码
import pandas as pd  # 用于处理表格

# 读取数据文件,得到data对象
data = pd.read_csv('E:/LearningBio/archive/data.csv')
# 使用drop函数,输出data、waterfront、view、street、country这五列
data = data.drop(columns=['date', 'waterfront', 'view', 'street', 'country'])

# 因为city和statazip这两列是tag特征
# 所以需要使用cat.codes,将他们转为整数形式
data['city'] = data['city'].astype('category').cat.codes
data['statezip'] = data['statezip'].astype('category').cat.codes

# 获取除了price剩下的12列的特征
features = data.columns.difference(['price'])
# 对所有特征进行标准化处理
data[features] = (data[features] - data[features].mean()) / data[features].std()

# 将房价price缩小10000倍,使用万作为价格单元
data['price'] = data['price'] / 10000

++部分解释:++

1.在 Pandas 中,cat.codes 用于将分类数据(categorical data)转换为整数编码

2.在 Python 的 Pandas 库中,mean() 函数用于计算均值。data[features].mean() :计算 3.features 列中每一列的均值。结果是一个包含各列均值的 Series,每列的均值会用于该列数据的标准化。

4.data[features].std() :计算 features 列中每一列的标准差,得到一个包含各列标准差的 Series

5 .(data[features] - data[features].mean()) / data[features].std():将中心化的每列数据除以对应列的标准差,使每列数据的标准差为1。

6.特征缩放使用均值标准化:

拆分数据

python 复制代码
from sklearn.model_selection import train_test_split

# 使用train_test_split函数
# 将数据data拆分成训练数据train_data和test_data
train_data, test_data = train_test_split(data, test_size=0.15, random_state=42)

# 使用to_excel将两份数据保存到文件中
train_data.to_excel('E:/LearningBio/archive/train.xlsx', index=False)
test_data.to_excel('E:/LearningBio/archive/text.xlsx', index=False)

2.多元线性回归模型的设计

设计一个多元线性回归模型,用于房价预测,包括12个特征。

线性层的大小由输入数据的个数和输出数据个数所决定。

模型设计

python 复制代码
import torch
from torch import nn

# 定义模型类LinearRegression,他继承了Pytorch的nn.Module类
# nn.Module是所有模型的基类,它包括模型的基本功能
class LinearRegression(nn.Module):
    # init函数用于初始化模型的结构参数
    def __init__(self):
        super().__init__()
        # 对于房价预测这个问题,有12个输入特征和一个输出结果
        self.layer = nn.Linear(12, 1)

    # forward函数用于定义模型前向传播的计算逻辑
    def forward(self, x):
        # 输入的特征向量是x,将x传入至layer进行计算
        # 这个过程相当于计算线性回归的方程h(x)
        return self.layer(x)

测试代码

python 复制代码
if __name__ == '__main__':
    model = LinearRegression()  # 创建模型
    print(model)  # 打印model,可以看到模型的结构
    print("")

    # 使用循环,遍历模型中的参数
    for name, param in model.named_parameters():
        # 打印参数名称和初始值
        # 他们就是线性回归模型中12个w参数,和一个b参数
        print(f"{name} : {param.data}")

    # 定义一个100*12大小的张量
    # 代表100个数据,每个数据有12个特征值
    x = torch.zeros(100, 12)
    h = model(x)  # 将x输入值模型model,得到预测结果h
    print(f"x:{x.shape}")
    print(f"h:{h.shape}")

运行结果

python 复制代码
LinearRegression(
  (layer): Linear(in_features=12, out_features=1, bias=True)
)

layer.weight : tensor([[ 0.0191,  0.1262, -0.0705,  0.0321,  0.1766, 
            -0.1595,  0.1702,  0.0083, 0.1219,  0.2356, -0.1838, 
             0.0656]])
layer.bias : tensor([0.2869])
x:torch.Size([100, 12])
h:torch.Size([100, 1])

++部分解释:++

1.nn 是 PyTorch 中专门用于构建和定义神经网络的模块,其中包含各种神经网络层、激活函数、损失函数等工具,帮助用户方便地创建深度学习模型。

2.在 PyTorch 中,named_parameters() 方法用于获取模型中所有参数的名称和值。模型的初始参数(权重和偏置)是在定义模型时自动初始化的

3.forward 是 PyTorch 中定义神经网络模型时的一个关键方法,用于定义模型的前向传播过程。它规定了输入数据如何经过各层得到最终输出。前向传播是指数据从输入层经过各神经网络层到输出层的传递过程。

forward 方法的用法

定义模型结构 :在定义神经网络模型时,需要继承 nn.Module 类,并重写 forward 方法。

  1. 输入参数forward 方法通常接收一个输入张量 x

  2. 输出forward 方法返回网络的输出结果。

3.模型的训练和测试

训练代码

对训练集中的样本,分别转化为两组张量

python 复制代码
 # 模型训练代码
    import pandas as pd
    from sklearn.metrics import mean_squared_error
    from sklearn.metrics import mean_absolute_error
    from sklearn.metrics import r2_score

    if __name__ == '__main__':
        # 使用read.excel,读取训练数据train.xlsx
        df = pd.read_excel("E:/LearningBio/archive/train.xlsx")
        # 获取训练数据的特征
        features_names = [col for col in df.columns if col not in ['price']]
        # 打印特征的数量
        print(f'Features num: {len(features_names)}')
        # 将输入特征,转换为张量x
        x = torch.Tensor(df[features_names].values)
        # 训练标签,转换为张量y
        y = torch.Tensor(df['price'].values).unsqueeze(1)
        # 打印训练数据的张量
        print(f'Training samples: {len(x)}')

++运行结果++

Features num: 12

Training samples: 3910

++部分解释:++

  • df.columns :获取 DataFrame df 的所有列名,返回一个包含所有列名的索引对象。

  • 列表推导式[col for col in df.columns if col not in ['price']] 是一种Python语法,用于创建一个新列表。它会遍历 df.columns 中的每一个列名 col

  • 条件判断if col not in ['price'] 过滤条件,用于排除 price 列。也就是说,只有当 col 不在 ['price'] 中时,它才会被包含在新列表中。

  • 在 PyTorch 中,unsqueeze(1) 是用于增加张量维度的方法。具体来说,unsqueeze 方法会在指定的位置插入一个维度。这里将一维张量转换为二维张量,方便在进行计算时与其他二维张量(如特征矩阵)进行操作,比如用于线性回归模型的输入。

创建对象

训练模型时需要创建对象,包括这三个必须的步骤:

1.模型本身

2.优化器优化参数

3.损失函数

python 复制代码
 # 在使用Pytorch训练模型时,需要创建三个对象
        # 第一个是模型本身model,他就是我们设计的线性回归模型
        model = LinearRegression()
        # 第二个是优化器optimizer,它用来优化模型中的参数
        # 最常使用的时Adam优化器
        optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
        # 第三个是损失函数criterion,对于回归问题,使用MSELoss,均方误差
        criterion = nn.MSELoss()

批量梯度下降

使用批量梯度下降算法,循环迭代得到训练的参数12个w参数和1个b参数,使模型收敛,循环包括以下五个步骤,这5个步骤是pytorch框架训练模型的定式:

1.计算模型预测值

2.计算预测值和样本y之间的损失

3.使用backward计算梯度

4.使用optimizer.step更新参数

5.将梯度清零

python 复制代码
# 进入模型的迭代循环,使用的是批量梯度下降算法
        # 每次迭代,都会基于全部样本计算损失值,执行梯度下降
        # 这里循环的轮数为2万,可以是模型达到收敛
        for epoch in range(20000):
            # 在循环中,包括5个步骤
            h = model(x)  # 1.计算模型的预测值
            loss = criterion(h, y)  # 2.计算预测值和标签y之间的损失loss
            loss.backward()  # 3.使用backward计算梯度
            optimizer.step()  # 4.使用optimizer.step更新参数
            optimizer.zero_grad()  # 5.将梯度清空
            # 这5步是使用pytorch框架训练模型的定式

            # 每迭代1000次打印一次模型的损失,用于观察训练过程
            if (epoch + 1) % 1000 == 0:
                # 打印迭代轮数和损失
                print(f'After{epoch + 1} iterations, Train Loss: {loss.item():.3f}')
                h_np = h.detach().numpy()
                y_np = y.detach().numpy()

                # 打印MSE、MAE和R2这三个回归指标
                mse = mean_squared_error(y_np, h_np)
                mae = mean_absolute_error(y_np, h_np)
                r2 = r2_score(y_np, h_np)
                print(f'\tMean squared error: {mse:.3f}')
                print(f'\tMean absolute error: {mae:.3f}')
                print(f'\tR2 score: {r2:.3f}')

        # 打印模型训练出的参数
        print(model.state_dict())
        # 将模型参数保存到文件lr.pth中
        # model..pth就是我们最终训练得到的模型
        torch.save(model.state_dict(), 'E:/LearningBio/archive/model.pth')

++部分解释:++

  • h_np = h.detach().numpy()y_np = y.detach().numpy() 这两行代码将模型的输出 h 和真实标签 y 转换为 NumPy 数组,方便后续处理或可视化。
  • MSE:均方误差是预测值与真实值之间差的平方的平均值。它可以反映模型预测的准确性,越小越好。
  • MAE:平均绝对误差是预测值与真实值之间差的绝对值的平均值,表示预测值的偏差程度。(一元线性回归中有提及)
  • 分数:也称为决定系数,衡量模型解释的方差比例。值域在0到1之间,越接近1表示模型对数据的解释能力越强。为负值时,表示模型的表现比简单的平均值还要差。

其中是第i个样本的真实值,是第i个样本的预测值 , 是所有样本真实值的均值。

分子:表示真实值与预测值之间的平方差,反映模型的误差。

分母:表示真实值与均值之间的平方差,反映真实数据的整体变异性。

  • model.state_dict() 是 PyTorch 中用于获取模型参数和缓冲区的一个方法。它返回一个包含模型所有可学习参数(如权重和偏置)以及一些其他状态信息(如 BatchNorm 的均值和方差)的字典。 返回的字典中,键是参数的名称(通常是层的名称),值是对应的参数张量。

++运行结果++

python 复制代码
After1000 iterations, Train Loss: 4564.342
	Mean squared error: 4564.342
	Mean absolute error: 46.080
	R2 score: -0.457
After2000 iterations, Train Loss: 3783.479
	Mean squared error: 3783.479
	Mean absolute error: 37.779
	R2 score: -0.207
......
After20000 iterations, Train Loss: 2447.281
	Mean squared error: 2447.281
	Mean absolute error: 16.772
	R2 score: 0.219
OrderedDict([('layer.weight', tensor([[-6.1492,  3.9196, 12.1156, -2.1037,  2.6352,  2.6877, 13.4887,  7.3559,
         -7.3652,  0.8103,  3.4043, -2.8637]])), ('layer.bias', tensor([54.9326]))])

测试代码

与训练代码差不多,包括测试集的读取,定义回归模型、将测试集中的特征向量x输入到model模型中,得到结果,打印回归指标。

python 复制代码
# 对模型进行测试
    if __name__ == '__main__':
        # 测试的流程和训练差不多
        # 首先读取测试集test.xlsx
        df = pd.read_excel("E:/LearningBio/archive/text.xlsx")
        features_names = [col for col in df.columns if col not in ['price']]
        x = torch.Tensor(df[features_names].values)
        y = torch.Tensor(df['price'].values).unsqueeze(1)

        # 包括了690个样本
        print(f"Testing samples: {len(x)}")

        #定义线性回归模型
        model=LinearRegression()
        #加载刚刚训练好的模型文件model.path
        model.load_state_dict(torch.load('E:/LearningBio/archive/model.pth'))
        #将特征向量x输入到model中,得到预测结果h
        h=model(x)

        h_np=h.detach().numpy()
        y_np = y.detach().numpy()
        #计算h和y之间的MSE、MAE和R2
        mse = mean_squared_error(y_np, h_np)
        mae = mean_absolute_error(y_np, h_np)
        r2 = r2_score(y_np, h_np)
        print(f'\tMean squared error: {mse:.3f}')
        print(f'\tMean absolute error: {mae:.3f}')
        print(f'\tR2 score: {r2:.3f}')

由测试集指标和训练集指标可以看出,两个集合中的三个指标相差不多,模型符合预期。

python 复制代码
Testing samples: 690
	Mean squared error: 2847.840
	Mean absolute error: 18.482
	R2 score: 0.170
相关推荐
qq_529025291 小时前
Torch.gather
python·深度学习·机器学习
IT古董2 小时前
【漫话机器学习系列】017.大O算法(Big-O Notation)
人工智能·机器学习
海棠AI实验室2 小时前
AI的进阶之路:从机器学习到深度学习的演变(三)
人工智能·深度学习·机器学习
古希腊掌管学习的神4 小时前
[搜广推]王树森推荐系统——矩阵补充&最近邻查找
python·算法·机器学习·矩阵
martian6654 小时前
【人工智能数学基础篇】——深入详解多变量微积分:在机器学习模型中优化损失函数时应用
人工智能·机器学习·微积分·数学基础
人机与认知实验室5 小时前
人、机、环境中各有其神经网络系统
人工智能·深度学习·神经网络·机器学习
古希腊掌管学习的神9 小时前
[机器学习]XGBoost(3)——确定树的结构
人工智能·机器学习
海棠AI实验室11 小时前
AI的进阶之路:从机器学习到深度学习的演变(一)
人工智能·深度学习·机器学习