上节,我已经展示了如何通过反向传播为前馈神经网络实现这些计算,让我们看看与 NumPy 相比,PyTorch 为我们节省了多少时间。
其中一件看起来比它应该更复杂或更难理解的事情是使用 PyTorch 加载数据集。首先定义数据的转换,指定它应该是一个张量,并且应该对其进行规范化。然后,将 in 与数据集结合使用来加载数据集。这就是您所需要的。稍后将了解如何从这些加载程序中解压缩值。
DataLoader``import
import torch
from torchvision import datasets, transforms
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
train_loader = torch.utils.data.DataLoader(
datasets.MNIST('data', train=True, download=True, transform=transform))
test_loader = torch.utils.data.DataLoader(
datasets.MNIST('data', train=False, transform=transform))
我定义了一个名为类似于之前用 NumPy 编写的类的类。这个类有一些相同的方法,但你可以清楚地看到,我不需要考虑初始化网络参数,也不需要考虑PyTorch中的向后传递,因为这些函数和计算精度的函数都消失了。
Net``DeepNeuralNetwork
import time
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self, epochs=10):
super(Net, self).__init__()
self.linear1 = nn.Linear(784, 128)
self.linear2 = nn.Linear(128, 64)
self.linear3 = nn.Linear(64, 10)
self.epochs = epochs
def forward_pass(self, x):
x = self.linear1(x)
x = torch.sigmoid(x)
x = self.linear2(x)
x = torch.sigmoid(x)
x = self.linear3(x)
x = torch.softmax(x, dim=0)
return x
def one_hot_encode(self, y):
encoded = torch.zeros([10], dtype=torch.float64)
encoded[y[0]] = 1.
return encoded
def train(self, train_loader, optimizer, criterion):
start_time = time.time()
loss = None
for iteration in range(self.epochs):
for x,y in train_loader:
y = self.one_hot_encode(y)
optimizer.zero_grad()
output = self.forward_pass(torch.flatten(x))
loss = criterion(output, y)
loss.backward()
optimizer.step()
print('Epoch: {0}, Time Spent: {1:.2f}s, Loss: {2}'.format(
iteration+1, time.time() - start_time, loss
))
在阅读本类时,请注意 PyTorch 已经为我们实现了所有相关的激活函数,以及不同类型的层。你甚至不必考虑它。您可以只定义一些图层,例如全连接图层。nn.Linear()
我之前已经导入了优化器,现在我指定了要使用的优化器,以及损失的标准。我将优化器和标准都传递到训练函数中,PyTorch 开始运行示例,就像在 NumPy 中一样。我甚至可以包括一个衡量准确性的指标,但为了衡量损失而忽略了这一点。
model = Net()
optimizer = optim.SGD(model.parameters(), lr=0.001)
criterion = nn.BCEWithLogitsLoss()
model.train(train_loader, optimizer, criterion)
对于神经网络的 TensorFlow/Keras 版本,我选择使用一种简单的方法,最大限度地减少代码行数。这意味着我没有定义任何类,而是使用 Keras 的高级 API 来制作一个仅用几行代码的神经网络。如果你刚刚开始学习神经网络,你会发现使用 Keras 时进入门槛最低。因此,我推荐它。
我首先导入以后需要的所有函数。
import tensorflow as tf
from tensorflow.keras.datasets import mnist
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.layers import Flatten, Dense
from tensorflow.keras.losses import BinaryCrossentropy
我只需这几行代码即可加载数据集并对其进行预处理。请注意,我只对训练数据进行预处理,因为我不打算将验证数据用于此方法。稍后,我将解释如何使用验证数据。
(x_train, y_train), (x_val, y_val) = mnist.load_data()
x_train = x_train.astype('float32') / 255
y_train = to_categorical(y_train)
下一步是定义模型。在 Keras 中,在知道要将哪些图层应用于数据后,这非常简单。在本例中,我将使用完全连接的层,如 NumPy 示例所示。在 Keras 中,这是由函数完成的。Dense()
定义模型的层后,我将编译模型并定义优化器、损失函数和度量。最后,我可以告诉 Keras 拟合 10 个 epoch 的训练数据,就像在其他示例中一样。
model = tf.keras.Sequential([
Flatten(input_shape=(28, 28)),
Dense(128, activation='sigmoid'),
Dense(64, activation='sigmoid'),
Dense(10)
])
model.compile(optimizer='SGD',
loss=BinaryCrossentropy(),
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=10)
如果要使用验证数据,可以使用 fit 函数的参数传入:
validation_data
model.fit(x_train, y_train, epochs=10, validation_data=(x_val, y_val))