11.25Pytorch_手动构建模型实战

embedded/2024/11/30 5:12:35/

八、手动构建模型实战

我们来整一个小小的案例,帮助加深对知识点的理解~

0. 模型训练基础概念

在进行模型训练时,有三个基础的概念我们需要颗粒度对齐下:

名词定义
Epoch使用训练集的全部数据对模型进行一次完整训练,被称为“一代训练”
Batch使用训练集中的一小部分样本对模型权重进行一次反向传播的参数更新,这一小部分样本被称为“一批数据”
Iteration使用一个Batch数据对模型进行一次参数更新的过程,被称为“一次训练”

1. 数据处理这里简单的构建一批数据集

1.1 构建数据集

代码参考如下:

python">import math
import random
import torch
import numpy as np
from sklearn.datasets import make_regression
import pandas as pddef build_dataset():"""使用 sklearn 的 make_regression 方法来构建一个模拟的回归数据集。make_regression 方法的参数解释:- n_samples: 生成的样本数量,决定了数据集的规模。- n_features: 生成的特征数量,决定了数据维度。- noise: 添加到目标变量的噪声标准差,用于模拟真实世界数据的不完美。- coef: 如果为 True, 会返回生成数据的真实系数,用于了解特征与目标变量间的真实关系。- random_state: 随机数生成的种子,确保在多次运行中能够复现相同的结果。返回:- X: 生成的特征矩阵。- y: 生成的目标变量。- coef: 如果在调用时 coef 参数为 True,则还会返回真实系数。"""noise = random.randint(1, 5)X, y, coef = make_regression(n_samples=1000, n_features=5, bias=14.5, noise=noise, coef=True, random_state=0)# 数据转换为张量X = torch.tensor(X, dtype=torch.float32)y = torch.tensor(y, dtype=torch.float32)coef = torch.tensor(coef, dtype=torch.float32)return X, y, coefif __name__ == "__main__":# 构建一批数据集X, y, coef = build_dataset()# 将特征数据X转换为DataFrame,并添加列名feature_names = [f"feature_{i+1}" for i in range(X.shape[1])]X_df = pd.DataFrame(X, columns=feature_names)# 创建包含目标变量y的Seriesy_series = pd.Series(y, name="Target")# 将特征和目标变量数据合并为一个完整的数据集data_df = pd.concat([X_df, y_series], axis=1)# 显示前20行数据print("前5行数据:")print(data_df.head())# 输出生成数据的真实系数print("\n生成数据的真实系数:")print(coef)

数据集结果:

python">前5行数据:feature_1  feature_2  feature_3  feature_4  feature_5      Target
0  -1.718650   0.969624   0.196770   0.143464  -1.056957   -6.838571
1  -0.998192  -1.004323  -0.766705  -1.067742  -1.373043 -198.812241
2  -1.652804   0.174680  -1.400256   0.063896   1.065927  -25.560152
3  -0.422315   0.892474   0.555963   0.228053   0.104714   73.847435
4  -1.023173   0.177158   0.976382  -0.911881   0.106720  -61.363613生成数据的真实系数:
tensor([41.2059, 66.4995, 10.7145, 60.1951, 25.9615])

1.2 构建数据加载器

数据需要分批次加载到模型进行训练

python">import math
import random
import torch
import numpy as np
from sklearn.datasets import make_regression
import pandas as pddef build_dataset():"""使用 sklearn 的 make_regression 方法来构建一个模拟的回归数据集。make_regression 方法的参数解释:- n_samples: 生成的样本数量,决定了数据集的规模。- n_features: 生成的特征数量,决定了数据维度。- noise: 添加到目标变量的噪声标准差,用于模拟真实世界数据的不完美。- coef: 如果为 True, 会返回生成数据的真实系数,用于了解特征与目标变量间的真实关系。- random_state: 随机数生成的种子,确保在多次运行中能够复现相同的结果。返回:- X: 生成的特征矩阵。- y: 生成的目标变量。- coef: 如果在调用时 coef 参数为 True,则还会返回真实系数。"""noise = random.randint(1, 5)X, y, coef = make_regression(n_samples=1000, n_features=5, bias=14.5, noise=noise, coef=True, random_state=0)# 数据转换为张量X = torch.tensor(X, dtype=torch.float32)y = torch.tensor(y, dtype=torch.float32)coef = torch.tensor(coef, dtype=torch.float32)return X, y, coefdef data_loader(x, y, batch_size=16):"""将数据集转换为迭代器,以便在训练过程中进行批量处理。"""# 获取样本数量num_samples = x.shape[0]# 构建数据索引indices = list(range(num_samples))# 打乱数据顺序random.shuffle(indices)# 计算总的批次数量:向上取整num_batches = math.ceil(num_samples / batch_size)for i in range(num_batches):start = i * batch_sizeend = min((i + 1) * batch_size, num_samples)# 开始切片数据train_X = x[indices[start:end]]train_y = y[indices[start:end]]# 异步响应数据集yield train_X, train_yif __name__ == "__main__":# 构建一批数据集X, y, coef = build_dataset()# 分批次记载数据for x, y in data_loader(X, y):print(x, y)

2. 模型函数

参考如下

python">def linear_regression(x, w, b):return torch.matmul(x, w) + b

3. 损失函数

参考如下

python"># 构建损失函数
def mean_squared_error(y_pred, y_true):return torch.mean((y_pred - y_true) ** 2)

4. 优化器

使用梯度下降对参数进行调整…

python"># 优化器(SGD,手动实现)
def sgd(w, b, dw, db, learning_rate, batch_size):w.data -= learning_rate * dw.data / batch_sizeb.data -= learning_rate * db.data / batch_sizereturn w, b

5. 参数初始化

代码参考如下

python"># 初始化参数
def initialize_params(n_features):# 随机初始化权重w,并将偏置b初始化为0w = torch.randn(n_features, requires_grad=True, dtype=torch.float32)b = torch.tensor(0.0, requires_grad=True, dtype=torch.float32)return w, b

6. 训练函数

训练函数完成对数据的训练和参数调整等,是一个完整的功能函数~

python"># 前面的代码这里略掉......
# 训练函数
def train():# 1. 构建数据集X, y, coef = build_dataset()# 2. 初始化模型参数w, b = initialize_params(X.shape[1])# 3. 定义训练参数learning_rate = 0.01epochs = 100batch_size = 16# 4. 开始训练for epoch in range(epochs):epoch_loss = 0num_batches = 0for train_X, train_y in data_loader(X, y, batch_size):num_batches += 1# 5. 前向传播y_pred = linear_regression(train_X, w, b)# 6. 计算损失loss = mean_squared_error(y_pred, train_y)# 7. 梯度清零if w.grad is not None:w.grad.zero_()if b.grad is not None:b.grad.zero_()# 8. 反向传播:会自动计算梯度loss.backward()# 9. 更新参数w, b = sgd(w, b, w.grad, b.grad, learning_rate, batch_size)# 10. 训练批次及损失率epoch_loss += loss.item()print(f"Epoch: {epoch}, Loss: {epoch_loss / num_batches}")if __name__ == "__main__":train()

训练结果观察:

python">Epoch: 0, Loss: 9388.94959077381
Epoch: 1, Loss: 7991.849659753224
......
Epoch: 9, Loss: 2468.7975725446427
......
Epoch: 15, Loss: 1039.112812829396
......
Epoch: 19, Loss: 581.4362507169209
......
Epoch: 24, Loss: 289.2235103183323
......
Epoch: 33, Loss: 91.27824468461294
......
Epoch: 42, Loss: 36.76937197125147
......
Epoch: 53, Loss: 20.499485742478143
......
Epoch: 99, Loss: 16.240657382541233

7. 项目整合

代码整合:

python">import math
import random
import torch
import numpy as np
from sklearn.datasets import make_regression
import pandas as pddef build_dataset():"""使用 sklearn 的 make_regression 方法来构建一个模拟的回归数据集。make_regression 方法的参数解释:- n_samples: 生成的样本数量,决定了数据集的规模。- n_features: 生成的特征数量,决定了数据维度。- noise: 添加到目标变量的噪声标准差,用于模拟真实世界数据的不完美。- coef: 如果为 True, 会返回生成数据的真实系数,用于了解特征与目标变量间的真实关系。- random_state: 随机数生成的种子,确保在多次运行中能够复现相同的结果。返回:- X: 生成的特征矩阵。- y: 生成的目标变量。- coef: 如果在调用时 coef 参数为 True,则还会返回真实系数。"""noise = random.randint(1, 3)bias = 14.5X, y, coef = make_regression(n_samples=1000, n_features=5, bias=bias, noise=noise, coef=True, random_state=0)# 数据转换为张量X = torch.tensor(X, dtype=torch.float32)y = torch.tensor(y, dtype=torch.float32)coef = torch.tensor(coef, dtype=torch.float32)bias = torch.tensor(bias, dtype=torch.float32)return X, y, coef, biasdef data_loader(x, y, batch_size=16):"""将数据集转换为迭代器,以便在训练过程中进行批量处理。"""# 获取样本数量num_samples = x.shape[0]# 构建数据索引indices = list(range(num_samples))# 打乱数据顺序random.shuffle(indices)# 计算总的批次数量:向上取整num_batches = math.ceil(num_samples / batch_size)for i in range(num_batches):start = i * batch_sizeend = min((i + 1) * batch_size, num_samples)# 开始切片数据train_X = x[indices[start:end]]train_y = y[indices[start:end]]# 异步响应数据集yield train_X, train_y# 构建模型函数:权重参数和偏执参数
# 初始化参数
def initialize_params(n_features):# 随机初始化权重w,并将偏置b初始化为0w = torch.randn(n_features, requires_grad=True, dtype=torch.float32)b = torch.tensor(0.0, requires_grad=True, dtype=torch.float32)return w, bdef linear_regression(x, w, b):return torch.matmul(x, w) + b# 构建模型函数:损失函数和优化器
def mean_squared_error(y_pred, y_true):return torch.mean((y_pred - y_true) ** 2)# 优化器(SGD,手动实现)
def sgd(w, b, dw, db, learning_rate, batch_size):w.data -= learning_rate * dw.data / batch_sizeb.data -= learning_rate * db.data / batch_sizereturn w, b# 训练函数
def train():# 1. 构建数据集X, y, coef, bias = build_dataset()# 2. 初始化模型参数w, b = initialize_params(X.shape[1])# 3. 定义训练参数learning_rate = 0.01epochs = 120batch_size = 16# 4. 开始训练for epoch in range(epochs):epoch_loss = 0num_batches = 0for train_X, train_y in data_loader(X, y, batch_size):num_batches += 1# 5. 前向传播y_pred = linear_regression(train_X, w, b)# 6. 计算损失loss = mean_squared_error(y_pred, train_y)# 9. 梯度清零if w.grad is not None:w.grad.zero_()if b.grad is not None:b.grad.zero_()# 7. 反向传播:会自动计算梯度loss.backward()# 8. 更新参数w, b = sgd(w, b, w.grad, b.grad, learning_rate, batch_size)# 10. 训练批次及损失率epoch_loss += loss.item()print(f"Epoch: {epoch}, Loss: {epoch_loss / num_batches}")return coef, bias, w, bif __name__ == "__main__":coef, bias, w, b = train()print(f"真实系数: {coef}")print(f"预测系数: {w}")print(f"真实偏置: {bias}")print(f"预测偏置: {b}")

执行结果:

python">Epoch: 0, Loss: 9141.109053354414
......
Epoch: 9, Loss: 2438.3174680679563
......
Epoch: 18, Loss: 643.4502219548301
......
Epoch: 31, Loss: 100.09944831000433
......
Epoch: 48, Loss: 9.588121845608665
......
Epoch: 64, Loss: 1.8927827449071974
......
Epoch: 119, Loss: 1.006377797278147
真实系数: tensor([41.2059, 66.4995, 10.7145, 60.1951, 25.9615])
预测系数: tensor([41.1517, 66.4983, 10.7523, 60.2103, 25.9089], requires_grad=True)
真实偏置: 14.5
预测偏置: 14.50900650024414

http://www.ppmy.cn/embedded/141655.html

相关文章

整数对最小和(Java Python JS C++ C )

题目描述 给定两个整数数组array1、array2,数组元素按升序排列。 假设从array1、array2中分别取出一个元素可构成一对元素,现在需要取出k对元素, 并对取出的所有元素求和,计算和的最小值。 注意: 两对元素如果对应于array1、array2中的两个下标均相同,则视为同一对元…

MySQL 中字符类型长度为什么推荐 2 的次方数大小?

MySQL 中字符类型长度为什么推荐 2 的次方数大小? 在 MySQL 数据库中,VARCHAR 类型是一种非常灵活的字符串存储类型,它允许存储可变长度的字符串。尽管在大多数情况下,直接根据实际需求设置 VARCHAR 的长度即可,但有一…

力扣hot100-->前缀和/前缀书/LRU缓存

前缀和 1. 560. 和为 K 的子数组 中等 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1: 输入:nums [1,1,1], k 2 输出:2示例 2&#…

【UE5 C++课程系列笔记】04——创建可操控的Pawn

根据官方文档创建一个可以控制前后左右移动、旋转视角、缩放视角的Pawn 。 步骤 一、创建Pawn 1. 新建一个C类,继承Pawn类,这里命名为“PawnWithCamera” 2. 在头文件中申明弹簧臂、摄像机和静态网格体组件 3. 在源文件中引入组件所需库 在构造函数…

k8s1.30.0高可用集群部署

负载均衡 nginx负载均衡 两台nginx负载均衡 vim /etc/nginx/nginx.conf stream {upstream kube-apiserver {server 192.168.0.11:6443 max_fails3 fail_timeout30s;#server 192.168.0.12:6443 max_fails3 fail_timeout30s;#server 192.168.0.13:6443 max_fails3…

2024 java大厂面试复习总结(二)(持续更新)

10年java程序员,2024年正好35岁,2024年11月公司裁员,记录自己找工作时候复习的一些要点。 JVM 说一下 JVM 运行时数据区 程序计数器(Program Counter Register):当前线程所执行的字节码的行号指示器&…

英语知识网站开发:Spring Boot框架应用

3系统分析 3.1可行性分析 通过对本英语知识应用网站实行的目的初步调查和分析,提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本英语知识应用网站采用SSM框架,JAVA作为开发语…

.cc扩展名是什么语言?主流编程语言扩展名?C语言必须用.c为扩展名吗?为什么看到Windows好多系统文件名的扩展名不超过3字符?

.cc扩展名是什么语言? .cc是C语言使用的扩展名,一种说法是它是c with class的简写,当然C语言使用的扩展名不止.cc和.cpp, 还包含.cxx, .c, .C等,这些在不同编译器系统采用的默认设定不同,需要区分使用。当然,编译器提…