pytorch中参数更新过程 (实例讲解)

我们知道在pytorch中更新参数只需要三步

optimizer.zero_grad() //清空梯度防止累积
loss.backward()  //计算梯度
optimizer.step() //更新参数

但是随着我们学习的深入,我感到只会写这三步大致知道它的意思是不够的,而是必须知道参数更新在机器学习里面究竟是如何做的,在pytorch里面又是如何实现的。
为此,我们举一个简单的例子。
现在有一个西瓜分类任务,输入 x = [ x 1 , x 2 , x 3 ] . x=[x_1,x_2,x_3]. x=[x1,x2,x3].有三维,分别代表西瓜的三个特征,输出
y = [ y 1 , y 2 ] y=[y_1,y_2] y=[y1,y2]有两维,代表分别属于两个类别的概率。
为了实验的简单,假设我们的预测函数为: y 1 = w 1 x 1 + w 2 x 2 + w 3 x 3 + b y_1=w_1 x_1 + w_2x_2 + w_3x_3 +b y1=w1x1+w2x2+w3x3+b。(这里只写出 y 1 y_1 y1的预测函数, y 2 y_2 y2同理)
要学习的参数有 w 1 , w 2 , w 3 , b w_1,w_2,w_3,b w1,w2,w3,b共四个。
我们只需要定义 l o s s = F u n ( y l , y p ) loss=Fun(y_l,y_p) loss=Fun(yl,yp)( y l y_l yl为标签, y p y_p yp为预测值),loss分别对三个参数求导得到梯度g,要让loss变小,所以参数应该要这样更新(朝梯度的反方向更新):
w 1 = w 1 − l r ∗ ∂ L ∂ w 1 w_1=w_1 -lr* \frac{\partial L}{\partial w_1} w1=w1lrw1L
w 2 = w 2 − l r ∗ ∂ L ∂ w 2 w_2=w_2 -lr* \frac{\partial L}{\partial w_2} w2=w2lrw2L
w 3 = w 3 − l r ∗ ∂ L ∂ w 3 w_3=w_3 -lr* \frac{\partial L}{\partial w_3} w3=w3lrw3L
b = b − l r ∗ ∂ L ∂ b b=b -lr* \frac{\partial L}{\partial b} b=blrbL
其中lr为学习率,决定了参数更新的速度。
下面我们看看这个过程在pytorch里面是如何进行的。
首先(根据公式)定义一个简单的模型。

import torch
from torch import  nn
import torch.nn.functional as F
class test_model(nn.Module):
    def __init__(self):
        super(test_model, self).__init__()
        self.fc1 = nn.Linear(3, 2)

    def forward(self, x):

        return self.fc1(x)

然后再定义optimizer(选用Adam),这里loss并不采用常见的交叉熵损失函数,而是自定义了一个loss为的是方便验证梯度的计算。

net = test_model()
optimizer = torch.optim.Adam(net.parameters(), lr=1.0)

input = torch.randn((1,3))
label = torch.tensor([1])

out = net(input)
loss = 1 - torch.sigmoid(out)[0][1]
for n, p in net.named_parameters():
    if n=="fc1.bias":
        print("原始bias:", p)
optimizer.zero_grad()
loss.backward()
optimizer.step()
for n, p in net.named_parameters():
    if n=="fc1.bias":
        print("fc1.bias的梯度",p.grad)
        print("更新之后的bias:", p)

输出结果如下:

原始bias: Parameter containing:
tensor([0.2146, 0.5020], requires_grad=True)
fc1.bias的梯度 tensor([ 0.0000, -0.1826])
更新之后的bias: Parameter containing:
tensor([0.2146, 1.5020], requires_grad=True)

回答几个可能有疑问的点:
问:按照公式,当前lr=1.0,为什么0.5020+0.1826 != 1.5020?
答:因为使用了Adam,它会动态地改变学习率,大致原理是梯度大的时候要让学习率小一点,梯度小的时候要让学习率大一点,所以lr会改变,自然上述等式就不成立。

问:为什么bias1的梯度为0 ,值没有改变?
答:你看一下损失函数的计算,根本没有涉及 y 1 y_1 y1的,所以什么bias1的梯度为0 ,值不会改变。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PyTorch的LSTM模型是一种递归神经网络,常用于处理序列数据,例如文本、音频和视频。在本篇文章,我们将深入了解PyTorchLSTM模型的各种参数,并提供实例进行讲解。 ### LSTM模型参数 PyTorchLSTM模型的主要参数如下: - **input_size**:输入数据的特征维度。 - **hidden_size**:LSTM层隐藏状态的维度。 - **num_layers**:LSTM层数。 - **bias**:是否使用偏置。 - **batch_first**:如果为True,则输入和输出张量的形状将是(batch_size, seq_length, feature_dim)。 - **dropout**:设置dropout概率。 - **bidirectional**:如果为True,则使用双向LSTM。 ### LSTM模型实例 下面我们将通过一个实例来详细讲解LSTM模型参数的使用。 首先,我们需要导入所需的库和数据集。在这里,我们将使用PyTorch内置的IMDB电影评论数据集。 ```python import torch import torch.nn as nn import torch.optim as optim from torchtext.datasets import IMDB from torchtext.data import Field, LabelField, BucketIterator # 定义字段 text = Field(tokenize='spacy', tokenizer_language='en_core_web_sm') label = LabelField(dtype=torch.float) # 加载数据集 train_data, test_data = IMDB.splits(text, label) # 构建词汇表 text.build_vocab(train_data, max_size=10000, vectors="glove.6B.100d") label.build_vocab(train_data) # 创建iterators batch_size = 64 train_iterator, test_iterator = BucketIterator.splits( (train_data, test_data), batch_size=batch_size, device=torch.device('cuda')) ``` 接下来,我们将定义LSTM模型。在这里,我们将使用单层LSTM和batch_first=True。 ```python class LSTMModel(nn.Module): def __init__(self, input_dim, hidden_dim, output_dim): super().__init__() self.hidden_dim = hidden_dim self.lstm = nn.LSTM(input_dim, hidden_dim, batch_first=True) self.fc = nn.Linear(hidden_dim, output_dim) def forward(self, x): h0 = torch.zeros(1, x.size(0), self.hidden_dim).to(device) c0 = torch.zeros(1, x.size(0), self.hidden_dim).to(device) out, (hn, cn) = self.lstm(x, (h0, c0)) out = self.fc(out[:, -1, :]) return out ``` 在这里,我们将输入维度指定为100,隐藏状态维度指定为128,输出维度指定为1。我们还指定了初始隐藏状态和记忆单元。 接下来,我们将定义优化器和损失函数: ```python device = torch.device('cuda') model = LSTMModel(input_dim=100, hidden_dim=128, output_dim=1).to(device) optimizer = optim.Adam(model.parameters(), lr=1e-3) criterion = nn.BCEWithLogitsLoss().to(device) ``` 在这里,我们使用Adam优化器和二元交叉熵损失函数。 最后,我们将训练模型: ```python def train(model, iterator, optimizer, criterion): epoch_loss = 0 epoch_acc = 0 model.train() for batch in iterator: optimizer.zero_grad() text, text_lengths = batch.text predictions = model(text).squeeze(1) loss = criterion(predictions, batch.label) acc = binary_accuracy(predictions, batch.label) loss.backward() optimizer.step() epoch_loss += loss.item() epoch_acc += acc.item() return epoch_loss / len(iterator), epoch_acc / len(iterator) def evaluate(model, iterator, criterion): epoch_loss = 0 epoch_acc = 0 model.eval() with torch.no_grad(): for batch in iterator: text, text_lengths = batch.text predictions = model(text).squeeze(1) loss = criterion(predictions, batch.label) acc = binary_accuracy(predictions, batch.label) epoch_loss += loss.item() epoch_acc += acc.item() return epoch_loss / len(iterator), epoch_acc / len(iterator) def binary_accuracy(preds, y): rounded_preds = torch.round(torch.sigmoid(preds)) correct = (rounded_preds == y).float() acc = correct.sum() / len(correct) return acc N_EPOCHS = 5 for epoch in range(N_EPOCHS): train_loss, train_acc = train(model, train_iterator, optimizer, criterion) valid_loss, valid_acc = evaluate(model, test_iterator, criterion) print(f'Epoch: {epoch+1:02}') print(f'\tTrain Loss: {train_loss:.3f} | Train Acc: {train_acc*100:.2f}%') print(f'\t Val. Loss: {valid_loss:.3f} | Val. Acc: {valid_acc*100:.2f}%') ``` 在这里,我们训练了5个epoch,并计算了训练和测试集上的损失和准确率。 ### 总结 在本篇文章,我们深入了解了PyTorchLSTM模型的各种参数,并通过一个实例进行了讲解

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值