使用PyTorch构建深度神经网络
立即解锁
发布时间: 2025-09-01 01:57:30 阅读量: 3 订阅数: 12 AIGC 

### 使用 PyTorch 构建深度神经网络
在深度学习中,训练深度神经网络时会遇到各种问题,如输入值范围对训练的影响、过拟合等。本文将探讨批量归一化、Dropout 和正则化等技术如何解决这些问题。
#### 批量归一化的作用
通过从批量均值中减去每个数据点,然后除以批量方差,我们可以将节点处批量的所有数据点归一化到一个固定范围。引入 γ 和 β 参数,能让网络确定最佳的归一化参数。为了理解批量归一化的作用,我们将在以下两种场景下观察训练和验证数据集的损失和准确率值,以及隐藏层值的分布:
1. 无批量归一化的极小输入值
2. 有批量归一化的极小输入值
##### 无批量归一化的极小输入值
通常,我们会将输入数据缩放到 0 到 1 之间。在本节中,我们将进一步将其缩放到 0 到 0.0001 之间,以了解数据缩放的影响。小输入值即使权重值有很大变化,也无法改变 Sigmoid 值。
为了将输入数据集缩放到极小值,我们修改 `FMNISTDataset` 类中的缩放方式:
```python
class FMNISTDataset(Dataset):
def __init__(self, x, y):
x = x.float()/(255*10000) # 仅用于理解批量归一化的影响
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)
```
在上述代码中,我们通过将输入像素值除以 10000 来缩小其范围。
接下来,我们重新定义 `get_model` 函数,以便获取模型的预测值和隐藏层的值:
```python
def get_model():
class neuralnet(nn.Module):
def __init__(self):
super().__init__()
self.input_to_hidden_layer = nn.Linear(784,1000)
self.hidden_layer_activation = nn.ReLU()
self.hidden_to_output_layer = nn.Linear(1000,10)
def forward(self, x):
x = self.input_to_hidden_layer(x)
x1 = self.hidden_layer_activation(x)
x2= self.hidden_to_output_layer(x1)
return x2, x1
model = neuralnet().to(device)
loss_fn = nn.CrossEntropyLoss()
optimizer = Adam(model.parameters(), lr=1e-3)
return model, loss_fn, optimizer
```
由于 `get_model` 函数现在返回两个输出,我们需要修改 `train_batch` 和 `accuracy` 函数,只获取输出层的值:
```python
def train_batch(x, y, model, opt, loss_fn):
model.train()
prediction = model(x)[0]
batch_loss = loss_fn(prediction, y)
batch_loss.backward()
optimizer.step()
optimizer.zero_grad()
return batch_loss.item()
def accuracy(x, y, model):
model.eval()
with torch.no_grad():
prediction = model(x)[0]
max_values, argmaxes = prediction.max(-1)
is_correct = argmaxes == y
return is_correct.cpu().numpy().tolist()
```
运行代码后,我们发现该模型即使经过 100 个 epoch 也训练得不好,验证准确率仅为 ~85%,而之前在 10 个 epoch 内验证准确率可达 ~90%。通过探索隐藏值的分布和参数分布,我们发现隐藏层值的范围非常小,输入和隐藏层值范围小导致权重需要有很大的变化。
##### 有批量归一化的极小输入值
在本小节中,我们只对前面的代码做一处修改,即在定义模型架构时添加批量归一化。修改后的 `get_model` 函数如下:
```python
def get_model():
class neuralnet(nn.Module):
def __init__(self):
super().__init__()
self.input_to_hidden_layer = nn.Linear(784,1000)
self.batch_norm = nn.BatchNorm1d(1000)
self.hidden_layer_activation = nn.ReLU()
self.hidden_to_output_layer = nn.Linear(1000,10)
def forward(self, x):
x = self.input_to_hidden_layer(x)
x0 = self.batch_norm(x)
x1 = self.hidden_layer_activation(x0)
```
0
0
复制全文
相关推荐










