无脑入门pytorch系列(三)—— nn.Linear

本系列教程适用于没有任何pytorch的同学(简单的python语法还是要的),从代码的表层出发挖掘代码的深层含义,理解具体的意思和内涵。pytorch的很多函数看着非常简单,但是其中包含了很多内容,不了解其中的意思就只能【看懂代码】,无法【理解代码】。

官方定义

nn.Linear 是 PyTorch 中用于创建线性层的类。线性层也被称为全连接层,它将输入与权重矩阵相乘并加上偏置,然后通过激活函数进行非线性变换。

官方的文档如下,torch.nn.Linear:

image-20230811162434032

demo1

下面是一个官方文档给出的例子:

m = nn.Linear(20, 30)
input = torch.randn(128, 20)
output = m(input)
print(output.size())

输出的结果:

image-20230811162456557

首先,输出[128, 20]的张量,经过一个[20, 30]的线性层,变成[128, 30]的张量。
可以理解为矩阵的乘法,也就是矩阵的"外积",矩阵的叉乘,第一个矩阵的行数与第二个矩阵的列数相同。

demo2

input_data = torch.Tensor([[1, 2, 3], [4, 5, 6]]) # [2, 3] 
m = nn.Linear(3, 2)
output = m(input_data)
print(output) # [2, 2]

输出:

image-20230811162529522

可以看看nn.Linear(3, 2)的参数:

for param in m.parameters():
    print(param)

输出:

image-20230811162606663

结合参数,其实本身它们的计算就是矩阵的乘法:

image-20230811162640687

输入X为[n, i]的矩阵,经过W为[i,0]的矩阵,加上b的偏置得到Y为[n,o]的矩阵。

计算的思路也比较简单:
output[0][0] = [1, 2, 3] * [0.2888, -0.4596, -0,4896] + 0.3740 = -1.7253
output[0][1] = [1, 2, 3] * [0.4730, -0.4033, -0.4739] + 0.3182 = -1.4370
output[1][0] = [4, 5, 6] * [0.2888, -0.4596, -0,4896] + 0.3740 = -3.7066
output[1][1] = [4, 5, 6] * [0.4730, -0.4033, -0.4739] + 0.3182 = -2.6495

通过input和param的对比,我们可以很轻松地理解实际上就是矩阵的乘法操作。而模型在训练过程中就是不断调整param的参数使得输出的张量符合训练集的需求。

### PyTorch 入门教程 #### 加载库并准备数据集 为了开始使用 PyTorch 进行机器学习模型训练,加载必要的库是第一步。这包括 `torch` 及其子模块 `nn`(神经网络),以及用于获取标准图像分类数据集的 `datasets` 和转换工具 `ToTensor`。 ```python import torch from torch import nn from torch.utils.data import DataLoader from torchvision import datasets, transforms ``` 接着定义如何预处理输入图片的数据变换链——这里仅简单地将其转成张量形式: ```python transform = transforms.ToTensor() ``` 创建一个实例化后的 Dataset 对象来存储样本及其对应标签,并通过指定根目录、是否作为测试集以及其他参数完成初始化工作;最后利用 DataLoader 来封装这个自定义或内置的数据源类以便后续取用批次化的训练/验证数据[^1]。 ```python training_data = datasets.FashionMNIST( root="data", train=True, download=True, transform=ToTensor(), ) test_data = datasets.FashionMNIST( root="data", train=False, download=True, transform=ToTensor(), ) ``` 构建好上述组件之后就可以轻松获得批量大小为 64 的迭代器了: ```python train_dataloader = DataLoader(training_data, batch_size=64) test_dataloader = DataLoader(test_data, batch_size=64) ``` #### 定义模型结构 接下来要做的就是设计具体的网络架构,在此以简单的全连接层为例展示基本操作方法。当然实际应用中可能还会涉及到卷积核池化等更复杂的运算单元组合方式。 ```python class NeuralNetwork(nn.Module): def __init__(self): super(NeuralNetwork, self).__init__() self.flatten = nn.Flatten() # 展平多维特征向量 self.linear_relu_stack = nn.Sequential( # 构建线性层序列 nn.Linear(28*28, 512), nn.ReLU(), # 非线性激活函数 nn.Linear(512, 512), nn.ReLU(), nn.Linear(512, 10), # 输出维度等于类别数 ) def forward(self, x): # 正向传播过程描述 x = self.flatten(x) logits = self.linear_relu_stack(x) return logits model = NeuralNetwork().to('cuda' if torch.cuda.is_available() else 'cpu') print(model) # 打印查看当前设备上的模型配置详情 ``` 这段代码实现了两件事:一是继承基类 `Module` 并重写构造函数与前馈计算逻辑;二是根据硬件条件自动选择运行平台从而提高效率。 #### 训练循环设置 有了前面几步打下的基础,现在可以着手编写完整的训练流程啦! ```python loss_fn = nn.CrossEntropyLoss() # 设置损失函数类型 optimizer = torch.optim.SGD(model.parameters(), lr=1e-3) def train(dataloader, model, loss_fn, optimizer): size = len(dataloader.dataset) for batch, (X, y) in enumerate(dataloader): X, y = X.to(device), y.to(device) pred = model(X) # 调用模型预测输出 loss = loss_fn(pred, y) # 计算误差值 optimizer.zero_grad() # 清除梯度缓存区中的旧记录以免累积影响新一次更新 loss.backward() # 自动求导机制反传误差信号调整权重参数 optimizer.step() if batch % 100 == 0: current = batch * len(X) print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]") device = 'cuda' if torch.cuda.is_available() else 'cpu' for t in range(epochs): print(f"Epoch {t+1}\n-------------------------------") train(train_dataloader, model, loss_fn, optimizer) print("Done!") ``` 以上部分展示了怎样设定优化算法超参选项并通过遍历 epoch 数目实现多次迭代直至收敛稳定状态为止的过程。 #### 测试评估性能指标 当所有准备工作都完成后自然少不了检验成果好坏的重要环节咯~下面给出了一种简易版的方法供参考借鉴: ```python def test(dataloader, model, loss_fn): size = len(dataloader.dataset) num_batches = len(dataloader) model.eval() test_loss, correct = 0, 0 with torch.no_grad(): for X, y in dataloader: X, y = X.to(device), y.to(device) pred = model(X) test_loss += loss_fn(pred, y).item() correct += (pred.argmax(1)==y).type(torch.float).sum().item() test_loss /= num_batches correct /= size print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n") test(test_dataloader, model, loss_fn) ``` 该片段主要围绕着关闭 dropout 等随机因素干扰的前提下统计正确率和平均交叉熵得分来进行最终评判。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暗夜无风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值