下面是对于“torch.optim优化算法理解之optim.Adam()解读”的完整攻略。
1. 优化算法概述
在神经网络训练的过程中,我们需要选择一个好的优化算法来更新模型中的参数,这个过程就是优化算法。优化算法可以通过最小化损失函数来更新参数,以便更好地拟合数据。
目前常用的优化算法有SGD、Adam、RMSprop等,每个算法都有自己的优缺点,选用不同的算法会对训练效果产生不同的影响。
2. Adam算法介绍
Adam算法是一种自适应优化算法,可以根据每个参数的历史梯度和动量对学习率进行自适应调整,同时避免了梯度下降中的局部最小值问题。
Adam算法的更新公式如下:
$v_t=\beta_1v_{t-1}+(1-\beta_1)g_t$
$s_t=\beta_2s_{t-1}+(1-\beta_2)g_t^2$
$\hat{v}_t=\frac{v_t}{1-\beta_1^t}$
$\hat{s}_t=\frac{s_t}{1-\beta_2^t}$
$\theta_{t+1}=\theta_t-\frac{\alpha\hat{v}_t}{\sqrt{\hat{s}_t}+\epsilon}$
其中,$g_t$为梯度,$\theta_t$为当前参数,$\alpha$为学习率,$\beta_1$和$\beta_2$为两个可调参数,$v_t$和$s_t$是梯度的一阶矩估计和二阶矩估计,通过对这两个估计的校正可以减小偏差,防止梯度估计的不准确。$\epsilon$是为了防止分母为0而添加的一个极小常数。
3. optim.Adam()函数用法
在Pytorch中,可以使用torch.optim中的Adam函数来实现Adam算法的优化器。Adam函数的定义如下:
torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0, amsgrad=False)
其中,params是需要优化的参数,lr为学习率,betas是计算一阶和二阶矩估计的指数衰减率,eps是分母中的极小常数,用于避免除数为0的情况,weight_decay是L2正则化项的权重,amsgrad是一种变体Adam算法,可以减小训练过程中的波动。
4. 案例说明
在下面的两个案例中,我们将使用optim.Adam()来优化两个不同的模型。
案例1:手写数字识别
在这个案例中,我们将使用Pytorch内置的手写数字数据集来训练一个简单的卷积神经网络。我们的目标是优化模型的准确率。
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.datasets as datasets
import torchvision.transforms as transforms
# 定义模型
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
self.dropout = nn.Dropout()
self.fc1 = nn.Linear(320, 50)
self.fc2 = nn.Linear(50, 10)
def forward(self, x):
x = nn.functional.relu(nn.functional.max_pool2d(self.conv1(x), 2))
x = nn.functional.relu(nn.functional.max_pool2d(self.dropout(self.conv2(x)), 2))
x = x.view(-1, 320)
x = nn.functional.relu(self.fc1(x))
x = self.fc2(x)
return nn.functional.log_softmax(x, dim=1)
# 数据预处理
train_transforms = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))])
# 加载数据集
train_dataset = datasets.MNIST(root='./data', train=True, transform=train_transforms, download=True)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True)
# 设置优化器和损失函数
model = Net()
optimizer = optim.Adam(model.parameters(), lr=0.001)
criterion = nn.NLLLoss()
# 训练模型
for epoch in range(10):
running_loss = 0.0
for i, data in enumerate(train_loader):
inputs, labels = data
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 100 == 99:
print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 100))
running_loss = 0.0
在上面的代码中,我们定义了一个简单的卷积神经网络,使用Adam优化器进行模型训练。最终的结果可以达到95%左右的准确率。
案例2:LSTM情感分析
在这个案例中,我们使用LSTM对IMDb情感分析数据集进行分类,从而比较SGD和Adam两种优化算法的差异。
import torch
import torch.nn as nn
import torch.optim as optim
import torchtext.datasets as datasets
import torchtext.data as data
# 定义LSTM模型
class LSTM(nn.Module):
def __init__(self, input_dim, embedding_dim, hidden_dim, output_dim):
super().__init__()
self.embedding = nn.Embedding(input_dim, embedding_dim)
self.rnn = nn.LSTM(embedding_dim, hidden_dim, num_layers=2, bidirectional=True)
self.fc = nn.Linear(hidden_dim * 2, output_dim)
def forward(self, text):
# text: [sent len, batch size]
embedded = self.embedding(text)
# embedded: [sent len, batch size, emb dim]
output, (hidden, cell) = self.rnn(embedded)
# output: [sent len, batch size, hid dim * num directions]
# hidden: [num layers * num directions, batch size, hid dim]
# cell: [num layers * num directions, batch size, hid dim]
hidden = torch.cat((hidden[-2,:,:], hidden[-1,:,:]), dim=1)
# hidden: [batch size, hid dim * num directions]
return self.fc(hidden)
# 加载数据集
TEXT = data.Field(tokenize='spacy')
LABEL = data.LabelField(dtype=torch.float)
train_data, test_data = datasets.IMDB.splits(TEXT, LABEL)
TEXT.build_vocab(train_data, max_size=25000, vectors="glove.6B.100d")
LABEL.build_vocab(train_data)
train_loader, test_loader = data.BucketIterator.splits((train_data, test_data), batch_size=32)
# 定义模型和优化器
input_dim = len(TEXT.vocab)
embedding_dim = 100
hidden_dim = 256
output_dim = 1
model = LSTM(input_dim, embedding_dim, hidden_dim, output_dim)
optimizer1 = optim.Adam(model.parameters(), lr=1e-3)
optimizer2 = optim.SGD(model.parameters(), lr=1e-3)
# 定义损失函数
criterion = nn.BCEWithLogitsLoss()
# 训练模型
for epoch in range(5):
train_loss1, train_loss2, train_acc1, train_acc2 = 0.0, 0.0, 0.0, 0.0
model.train()
for batch in train_loader:
optimizer1.zero_grad()
optimizer2.zero_grad()
text, label = batch.text, batch.label
preds = model(text).squeeze(1)
loss1 = criterion(preds, label)
loss2 = criterion(preds, label)
loss1.backward()
loss2.backward()
optimizer1.step()
optimizer2.step()
train_loss1 += loss1.item()
train_loss2 += loss2.item()
train_acc1 += ((preds>0).float() == label).sum().item()
train_acc2 += ((preds>0).float() == label).sum().item()
train_loss1 /= len(train_loader)
train_loss2 /= len(train_loader)
train_acc1 /= len(train_loader)
train_acc2 /= len(train_loader)
print(f'Epoch {epoch+1}: Adam loss {train_loss1:.3f} / SGD loss {train_loss2:.3f}, Adam acc {train_acc1*100:.2f}% / SGD acc {train_acc2*100:.2f}%')
在上面的代码中,我们定义了一个LSTM模型,并使用Adam和SGD两种优化算法进行比较。最终的结果表明,Adam算法的收敛速度比较快,而SGD算法的准确率稍高。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:torch.optim优化算法理解之optim.Adam()解读 - Python技术站