使用PyTorch构建深度神经网络
立即解锁
发布时间: 2025-09-01 01:10:28 阅读量: 8 订阅数: 15 AIGC 

### 使用 PyTorch 构建深度神经网络
在深度学习领域,使用 PyTorch 构建和训练神经网络是一项重要的技能。本文将详细介绍如何使用 PyTorch 训练一个神经网络,使其能够接收图像并预测图像的类别,同时探讨各种超参数对预测准确性的影响。
#### 训练神经网络的步骤
训练神经网络需要执行以下步骤:
1. 导入相关包。
2. 构建一个可以一次获取一个数据点的数据集。
3. 从数据集中包装 DataLoader。
4. 构建模型,然后定义损失函数和优化器。
5. 分别定义两个函数来训练和验证一批数据。
6. 定义一个函数来计算数据的准确性。
7. 根据每批数据在增加的 epoch 上执行权重更新。
#### 代码实现
##### 1. 导入相关包和 FMNIST 数据集
```python
from torch.utils.data import Dataset, DataLoader
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
device = "cuda" if torch.cuda.is_available() else "cpu"
from torchvision import datasets
data_folder = '~/data/FMNIST'
fmnist = datasets.FashionMNIST(data_folder, download=True, train=True)
tr_images = fmnist.data
tr_targets = fmnist.targets
```
##### 2. 构建一个获取数据集的类
```python
class FMNISTDataset(Dataset):
def __init__(self, x, y):
x = x.float()
x = x.view(-1,28*28)
self.x, self.y = x, y
def __getitem__(self, ix):
x, y = self.x[ix], self.y[ix]
return x.to(device), y.to(device)
def __len__(self):
return len(self.x)
```
在 `__init__` 方法中,我们将输入转换为浮点数,并将每个图像展平为 28*28 = 784 个数值(每个数值对应一个像素值)。`__len__` 方法指定了数据点的数量,这里是 `x` 的长度。`__getitem__` 方法包含了当我们请求第 `ix` 个数据点时应返回的逻辑(`ix` 是一个介于 0 和 `__len__` 之间的整数)。
##### 3. 创建一个生成训练 DataLoader 的函数
```python
def get_data():
train = FMNISTDataset(tr_images, tr_targets)
trn_dl = DataLoader(train, batch_size=32, shuffle=True)
return trn_dl
```
##### 4. 定义模型、损失函数和优化器
```python
from torch.optim import SGD
def get_model():
model = nn.Sequential(
nn.Linear(28 * 28, 1000),
nn.ReLU(),
nn.Linear(1000, 10)
).to(device)
loss_fn = nn.CrossEntropyLoss()
optimizer = SGD(model.parameters(), lr=1e-2)
return model, loss_fn, optimizer
```
模型是一个具有一个包含 1000 个神经元的隐藏层的网络。输出是一个 10 神经元层,因为有 10 个可能的类别。我们使用 `CrossEntropyLoss` 函数,因为每个图像的输出可以属于 10 个类别中的任何一个。注意,我们在神经网络中根本没有使用 "softmax",因为 `nn.CrossEntropyLoss` 实际上期望我们发送原始的 logits(即无约束的值),它会在内部执行 softmax。
##### 5. 定义一个在一批图像上训练数据集的函数
```python
def train_batch(x, y, model, opt, loss_fn):
model.train()
prediction = model(x)
batch_loss = loss_fn(prediction, y)
batch_loss.backward()
optimizer.step()
optimizer.zero_grad()
return batch_loss.item()
```
上述代码将一批图像通过模型进行前向传播,计算批次上的损失,然后通过反向传播更新权重,最后刷新梯度内存,以便不影响下一次传递中梯度的计算。
##### 6. 构建一个计算给定数据集准确性的函数
```python
@torch.no_grad()
def accuracy(x, y, model):
model.eval()
prediction = model(x)
max_values, argmaxes = prediction.max(-1)
is_correct = argmaxes == y
return is_correct.cpu().numpy().tolist()
```
我们通过 `@torch.no_grad()` 明确表示不需要计算梯度,通过将输入通过模型进行前向传播来计算预测值。然后调用 `prediction.max(-1)` 来确定每行对应的 argmax 索引,并将其与真实标签进行比较,最后返回正确预测的列表。
##### 7. 训练神经网络
```python
trn_dl = get_data()
model, loss_fn, optimizer = get_model()
losses, accuracies = [], []
for epoch in range(5):
print(epoch)
epoch_losses, epoch_accuracies = [], []
for ix, batch in enumerate(iter(trn_dl)):
x, y = batch
batch_loss = train_batch(x, y, model, optimizer, loss_fn)
epoch_losses.append(batch_loss)
epoch_loss = np.array(epoch_losses).mean()
for ix, batch in enumerate(iter(trn_dl)):
x, y = batch
is_correct = accuracy(x, y, model)
epoch_accuracies.extend(is_correct)
epoch_accuracy = np.mean(epoch_accuracies)
losses.append(epoch_loss)
accuracies.append(epoch_accuracy)
epochs = np.arange(5)+1
plt.figure(figsize=(20,5))
plt.subplot(121)
plt.title('Loss value over increasing epochs')
plt.plot(epochs, losses, label='Training Loss')
plt.legend(),
plt.subplot(122)
plt.title('Accuracy value over increasing epochs')
plt.plot(epochs, accuracies, label='Training Accuracy')
plt.gca().set_yticklabels(['{:.0f}%'.format(x*100) for x in plt.gca().get_yticks()])
plt.legend()
```
训练 5 个 epoch 后,训练准确率为 12%,损失值在增加的 epoch 上没有显著下降。这表明无论等待多长时间,模型都不太可能提供高准确率(例如,高于 80%)。这促使我们了解所使用的各种超参数如何影响神经网络的准确性。
#### 数据集缩放以提高模型准确性
缩放数据集是确保变量限制在有限范围内的过程。在本节中,我们将通过将每个输入值除以数据集中可能的最大值(即 255,对应白色像素),将自变量的值限制在 0 到 1 之间。
##### 代码实现
##### 1. 获取数据集、训练图像和目标
```python
from torchvision import datasets
from torch.utils.data import Dataset, DataLoader
import torch
import torch.nn as nn
device = "cuda" if torch.cuda.is_available() else "cpu"
import numpy as np
data_folder = '~/data/FMNIST'
fmnist = datasets.FashionMNIST(data_folder, download=True, train=True)
tr_images = fmnist.data
tr_targets = fmnist.targets
```
##### 2. 修改获取数据的 FMNISTDataset 类
```python
class FMNISTDataset(Dataset):
def __init__(self, x, y):
x = x.float()/255
x = x.view(-1,28*28)
self.x, self.y = x, y
def __getitem__(self, ix):
x, y = self.x[ix], self.y[ix]
return x.to(device), y.to(device)
def __len__(self):
return len(self.x)
```
与之前的部分相比,唯一的变化是我们将输入数据除以最大可能的像素值 255。由于像素值范围在 0 到 255 之间,将它们除以 255 将得到始终在 0 到 1 之间的值。
##### 3. 训练模型
```python
def get_data():
train = FMNISTDataset(tr_images, tr_targets)
trn_dl = DataLoader(train, batch_size=32, shuffle=True)
return trn_dl
from torch.optim import SGD
def get_model():
model = nn.Sequential(
nn.Linear(28 * 28, 1000),
nn.ReLU(),
nn.Linear(1000, 10)
).to(device)
loss_fn = n
```
0
0
复制全文
相关推荐









