co
上面几节都是自定义了很多东西,比如模型的权重,偏置的大小,学习率,损失函数等等,但是实际上pytorch有很多内置的函数以及默认的参数可以对我们的模型部分进行替换,效果也是非常好的,今天我们就来试试使用PyTorch的内置功能和默认参数来构建和训练一个简单的线性模型
-
模型定义:使用
nn.Linear(1, 1)
定义了一个简单的线性模型,这意味着输入特征数量和输出特征数量都是1。这是一个非常基本的模型,非常适合入门级的线性回归任务。 -
优化器:使用了
optim.SGD
作为优化器,这是随机梯度下降的一个实现,适用于大多数优化问题。设置学习率为1e-2
,这是一个相对较大的学习率,但在这种情况下可能仍然适用,因数据量和模型都很简单。 -
损失函数:选择了
nn.MSELoss()
作为损失函数,即均方误差损失,这是回归问题中最常用的损失函数之一。 -
内存(RAM)使用:
- PyTorch在默认情况下会管理内存使用,包括自动梯度计算所需的内存。当调用
.backward()
时,PyTorch会自动计算所有需要梯度的张量的梯度,并存储在内存中。 - 在训练循环中,内存使用可能会随着数据批次的大小和模型复杂度的增加而增加。然而,由于数据和模型都非常简单,内存使用应该保持在较低水平。
- PyTorch在默认情况下会管理内存使用,包括自动梯度计算所需的内存。当调用
-
默认参数:
- PyTorch中的许多函数和类都有默认参数,这些参数在大多数情况下都是合理的起点。例如,在
nn.Linear
中,默认不使用偏置项(但可以通过设置bias=True
来启用),在optim.SGD
中,默认学习率、动量等参数可以根据需要进行调整。 - 在我的代码中,已经明确设置了学习率,但没有修改其他默认参数,这在大多数情况下是可行的。
- PyTorch中的许多函数和类都有默认参数,这些参数在大多数情况下都是合理的起点。例如,在
-
训练循环:
- 训练循环,包括前向传播、计算损失、梯度归零、反向传播和参数更新。
- 注意,在每次迭代时,对整个训练集进行了训练,这被称为批量梯度下降(Batch Gradient Descent)。在大数据集上,这可能会导致训练速度非常慢,因为每次迭代都需要计算整个数据集的梯度。然而,在数据集很小的情况下,这是可以接受的
大致的思想有了小编说一下这次的模型和之前模型的不同点
linear_model = nn.Linear(1, 1)
nn.Linear(1, 1)
是PyTorch中的一个线性层(全连接层),用于执行线性变换。具体来说,它将输入数据从一维空间映射到另一维空间。
参数解释
1, 1
:这两个参数分别表示输入特征的数量和输出特征的数量。在这个例子中,输入和输出特征的数量都是1。
功能
- 线性变换:
nn.Linear(1, 1)
执行的线性变换可以表示为 y=wx+b,其中 w 是权重,b 是偏置,x 是输入,y 是输出。 - 权重和偏置:这个层会自动初始化权重 w 和偏置 b,并在训练过程中通过反向传播进行调整。
应用场景
- 简单回归问题:在简单的线性回归问题中,可以使用
nn.Linear(1, 1)
来拟合一个输入和一个输出之间的关系。 - 神经网络的一部分:在更复杂的神经网络中,
nn.Linear(1, 1)
可以作为网络的一个层,用于处理输入optimizer = optim.SGD( # 构建随机梯度下降(SGD)优化器 linear_model.parameters(), lr=1e-2) # linear_model.parameters(): # 这是一个生成器,返回线性模型中所有需要优化的参数
定义了一个优化器,具体来说是使用随机梯度下降(SGD)优化器来优化一个线性模型的参数。
linear_model.parameters()
: 这是一个生成器,返回线性模型中所有需要优化的参数。这些参数在训练过程中会根据损失函数的梯度进行更新 -
如果大家好奇这个默认的params的参数到底是什么呢,不妨运行一下下面的代码试试
-
print(list(linear_model.parameters()))
最后的改变就是原来我们的损失函数是自己定义的函数,现在我们使用自带的函数进行替换,计算的结果是一样的
-
loss_fn = nn.MSELoss()
综上所述,我们整合一下代码
-
import numpy as np import torch import torch.optim as optim torch.set_printoptions(edgeitems=2, linewidth=75) t_c = [0.5, 14.0, 15.0, 28.0, 11.0, 8.0, 3.0, -4.0, 6.0, 13.0, 21.0] t_u = [35.7, 55.9, 58.2, 81.9, 56.3, 48.9, 33.9, 21.8, 48.4, 60.4, 68.4] print(torch.tensor(t_c).shape) t_c = torch.tensor(t_c).unsqueeze(1) # 为每个张量增加一个维度 t_u = torch.tensor(t_u).unsqueeze(1) # print(t_u) n_samples = t_u.shape[0] n_val = int(0.2 * n_samples) shuffled_indices = torch.randperm(n_samples) train_indices = shuffled_indices[:-n_val] val_indices = shuffled_indices[-n_val:] t_u_train = t_u[train_indices] t_c_train = t_c[train_indices] t_u_val = t_u[val_indices] t_c_val = t_c[val_indices] t_un_train = 0.1 * t_u_train t_un_val = 0.1 * t_u_val import torch.nn as nn linear_model = nn.Linear(1, 1) # 定义了一个简单的线性模型。nn.Linear是一个全连接层,用于实现线性变换 linear_model(t_un_val) x = torch.ones(10, 1) linear_model(x) optimizer = optim.SGD( # 构建随机梯度下降(SGD)优化器 linear_model.parameters(), lr=1e-2) # linear_model.parameters(): 这是一个生成器,返回线性模型中所有需要优化的参数 print(list(linear_model.parameters())) def training_loop(n_epochs, optimizer, model, loss_fn, t_u_train, t_u_val, t_c_train, t_c_val): for epoch in range(1, n_epochs + 1): t_p_train = model(t_u_train) loss_train = loss_fn(t_p_train, t_c_train) t_p_val = model(t_u_val) loss_val = loss_fn(t_p_val, t_c_val) optimizer.zero_grad() loss_train.backward() optimizer.step() # 根据梯度和学习率等参数来更新模型的参数 if epoch == 1 or epoch % 1000 == 0: print(f"Epoch {epoch}, Training loss {loss_train.item():.4f}," f" Validation loss {loss_val.item():.4f}") training_loop( n_epochs = 3000, optimizer = optimizer, model = linear_model, loss_fn = nn.MSELoss(), # PyTorch 中用于计算均方误差(Mean Squared Error, MSE)的损失函数 t_u_train = t_un_train, t_u_val = t_un_val, t_c_train = t_c_train, t_c_val = t_c_val)
从结果来看,效果还是很好的