概述
本文主要记录个人学习Pytorch的过程,因为最近在尝试用Pytorch搭建神经网络,但是对Pytorch缺少整体的了解,导致在使用过程中存在这样或者那样的问题。记录主要分为三个部分。
-
结合
pytorch
官网上的60分钟示例,对pytorch
的使用有个整体的认识。 -
使用
tensorboard
可视化网络模型。 -
torchaudio
使用。
Pytorch初体验
利用Pytorch训练神经网络的步骤比较简单,主要分为以下几个步骤:
-
加载数据集。
-
定义网络结构
-
定义损失函数以及优化器
-
保存模型
加载数据集
Pytorch中和数据集相关的两个模块是DataSet和DataLoader,其中DataSet里定义了数据和标签的获得方式,而DataLoader能让我们以迭代的方式处理DataSet。加载Pytorch自带的数据集时,可以直接使用如下代码。
training_data = datasets.FashionMNIST(
root='data',
train=True,
download=True,
transform=ToTensor()
)
test_data = datasets.FashionMNIST(
root='data',
train=False,
download=True,
transform=ToTensor()
)
但是实际中一般会重写Dataset类来操作自己的数据集。重写DataSet类必须实现三个方法:__init__,__len__以及__getitem__,其它的方法可根据需要实现。
class CustomImageData(Dataset):
# 初始化
def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):
self.img_labels = pd.read_csv(annotations_file)
self.img_dir = img_dir
self.transform = transform
self.target_transform = target_transform
# 数据集大小
def __len__(self):
return len(self.img_labels)
# 得到数据和标签
def __getitem__(self, idx):
img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0])
image = read_image(img_path)
label = self.img_labels.iloc[idx, 1]
if self.transform:
image = self.transform(image)
if self.target_transform:
label = self.target_transform(label)
sample = {"image": image, "label": label}
return sample
然后再使用DataLoader,可以转成可迭代对象。
batch_size = 64
train_dataloader = DataLoader(training_data, batch_size=batch_size, shuffle=True)
test_dataloader = DataLoader(test_data, batch_size=batch_size, shuffle=True)
这样就可以直接访问该数据了。
train_features, train_labels = next(iter(train_dataloader))
print(f"Feature batch shape: {train_features.size()}")
print(f"Labels batch shape: {train_labels.size()}")
定义网络结构
数据搞定以后,就要定义神经网络结构了。Pytorch定义网络结构也很方便。通过创建一个继承自nn.Module的类,在__init__中定义网络中的模块,然后在forward()函数中定义数据的流通方向。一个简单的例子如下
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),
nn.ReLU()
)
def forward(self, x):
x = self.flatten(x)
logits = self.linear_relu_stack(x)
return logits
另外为了加速神经网络的运算速度,可以将其放到GPU进行计算。
# 设备是否支持cuda
device = "cuda" if torch.cuda.is_available() else "cpu"
print("Using {} device".format(device))
# 创建NeuralNetwork实例并将其放到gpu上
model = NeuralNetwork().to(device)
print(model)
定义损失函数和优化器
神经网络结构定义完成后,接下来就需要定义损失函数以及优化器了。Pytorch中包含了大多数的损失函数,比如NLLLoss,GaussianNLLLoss,MSELoss等等。如果Pytorch中没有所需要的损失函数,那么就需要自己定义了。
loss_fn = nn.CrossEntropyLoss()
另外Pytorch中在torch.optim中定义了大量的优化器,比如SGD, Adam,RMSprop等等,这些优化器可以直接使用。
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:
loss, current = loss.item(), batch * len(X)
print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]")
# test
def test(dataloader, model):
size = len(dataloader.dataset)
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 /= size
correct /= correct
print(f"Test Error: \n Accuracy: {(100 * correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
# 网络训练
epoch = 1
for t in range(epoch):
print(f"Epoch {t + 1}\n-------------------------------")
train(train_dataloader, model, loss_fn, optimizer)
test(test_dataloader, model)
print("Done")
网络训练完成后,需要将模型进行保存,Pytorch中使用torch.save()来保存所训练的模型。
# 保存模型
torch.save(model.state_dict(), "model.pth")
print("Saved PyTorch Model State to model.pth")
# 加载模型
# 先定义网络
model = NeuralNetwork()
# 然后加载网络模型权重
model.load_state_dict(torch.load("model.pth"))
另外也可以查看模型中具体层的参数
model1 = NeuralNetwork()
model1.load_state_dict(torch.load('model.pth'))
print("model1 is load successfully")
print("Model structure: ", model1, "\n\n")
for name, param in model1.named_parameters():
print(f"Layer: {name} | Size: {param.size()} | Values : {param[:2]} \n")
这样使用Pytorch
训练神经网络的基本过程已经介绍完了,流程上还是很清晰的。实际使用中,网络结构,数据集,损失函数可能需要自己重新定义。
总结
使用Pytorch的一般流程总结如下。
-
加载数据集
-
若数据集
Pytorch
中已有,可以直接加载数据集 -
如果数据集
Pytorch
中没有,需要重写DataSet
类,并实现__init__
,__len__
以及__getitem__
这三个方法。
-
-
定义网络结构
-
定义损失函数和优化器
-
Pytorch
中包含了大量的损失函数,可以直接使用。如果需要自定义损失函数,需要继承nn.Module
并实现forward
函数。
-
-
保存和加载模型
-
保存模型:
torch.save(model.parameters(),'')
-
记载模型:
model1.load_state_dict(torch.load('model.pth'))
https://mp.weixin.qq.com/s/vgDxz6JwkUKLbnzn4eewNw
-