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
相关推荐
彩云回5 小时前
多维尺度分析法(MDS)
人工智能·机器学习·1024程序员节
FL16238631295 小时前
智慧交通红绿灯检测数据集VOC+YOLO格式1215张3类别
深度学习·yolo·机器学习
10岁的博客7 小时前
PyTorch快速搭建CV模型实战
人工智能·pytorch·python
兩尛7 小时前
神经网络补充知识
人工智能·神经网络·机器学习
电鱼智能的电小鱼8 小时前
基于电鱼 ARM 工控机的煤矿主控系统高可靠运行方案——让井下控制系统告别“死机与重启”
arm开发·人工智能·嵌入式硬件·深度学习·机器学习
长桥夜波9 小时前
机器学习日报09
人工智能·机器学习
TGITCIC9 小时前
通过神经网络手搓一个带finetune功能的手写数字识别来学习“深度神经网络”
人工智能·深度学习·机器学习·卷积神经网络·dnn·文字识别·识别数字
Geoking.10 小时前
PyTorch torch.unique() 基础与实战
人工智能·pytorch·python
yumgpkpm12 小时前
CMP(类ClouderaCDP7.3(404次编译) )完全支持华为鲲鹏Aarch64(ARM)使用 AI 优化库存水平、配送路线的具体案例及说明
大数据·人工智能·hive·hadoop·机器学习·zookeeper·cloudera