PyTorch

PyTorch的核心是两个主要特征:张量和自动求导

张量(Tensor):

类似于numpy.nrray,但是np.nrray不能放入GPU计算,而Tensor可以

自动求导(autograd):

创建一个张量,设置requires_grad=True来跟踪与它相关的计算

x = torch.ones(2,2,requires_grad=True)  # 一会儿会对x进行求导
print(x)
y = x+2
print(y.grad_fn)  #输出True 说明运算被追踪了
z = y*y*3
out = z.mean()

out.backward()  #求梯度
print(x.grad) #打印梯度 d(out)/dx

再看一个雅可比向量积的例子:

x = torch.randn(3,requires_grad=True)

y = x*2

PyTorch实现神经网络

# -*- coding: utf-8 -*-
import torch

dtype = torch.float
device = torch.device("cpu")
# device = torch.device(“cuda:0”)#取消注释以在GPU上运行

# N是批量大小; D_in是输入维度;
# H是隐藏的维度; D_out是输出维度。
N, D_in, H, D_out = 64, 1000, 100, 10

# 创建随机Tensors以保持输入和输出。
# 设置requires_grad = False表示我们不需要计算渐变
x = torch.randn(N, D_in, device=device, dtype=dtype)
y = torch.randn(N, D_out, device=device, dtype=dtype)

# 为权重创建随机Tensors。
# 设置requires_grad = True表示我们想要计算渐变
w1 = torch.randn(D_in, H, device=device, dtype=dtype, requires_grad=True)
w2 = torch.randn(H, D_out, device=device, dtype=dtype, requires_grad=True)

learning_rate = 1e-6
for t in range(500):
    # 前向传播:使用tensors上的操作计算预测值y; 
      # 由于w1和w2有requires_grad=True,涉及这些张量的操作将让PyTorch构建计算图,
    # 从而允许自动计算梯度。由于我们不再手工实现反向传播,所以不需要保留中间值的引用。
    y_pred = x.mm(w1).clamp(min=0).mm(w2)

    # 使用Tensors上的操作计算和打印丢失。
    # loss是一个形状为()的张量
    # loss.item() 得到这个张量对应的python数值
    loss = (y_pred - y).pow(2).sum()
    print(t, loss.item())

    # 使用autograd计算反向传播。这个调用将计算loss对所有requires_grad=True的tensor的梯度。
    # 这次调用后,w1.grad和w2.grad将分别是loss对w1和w2的梯度张量。
    loss.backward()

    # 使用梯度下降更新权重。对于这一步,我们只想对w1和w2的值进行原地改变;不想为更新阶段构建计算图,
    # 所以我们使用torch.no_grad()上下文管理器防止PyTorch为更新构建计算图
    with torch.no_grad():
        w1 -= learning_rate * w1.grad
        w2 -= learning_rate * w2.grad

        # 反向传播后手动将梯度设置为零
        w1.grad.zero_()
        w2.grad.zero_()

nn模块

nn包含了等价于层的模块

example:用nn实现两层网络

# -*- coding: utf-8 -*-
import torch

if __name__ == '__main__':
    # N是批大小;D是输入维度
    # H是隐藏层维度;D_out是输出维度
    N, D_in, H, D_out = 64, 1000, 100, 10

    # 创建输入和输出随机张量
    x = torch.randn(N, D_in)  # 64*1000
    y = torch.randn(N, D_out)  # 64*100

    # 使用nn包将我们的模型定义为一系列的层。
    # nn.Sequential是包含其他模块的模块,并按顺序应用这些模块来产生其输出。
    # 每个线性模块使用线性函数从输入计算输出,并保存其内部的权重和偏差张量。
    # 在构造模型之后,我们使用.to()方法将其移动到所需的设备。
    model = torch.nn.Sequential(
        torch.nn.Linear(D_in, H),
        torch.nn.ReLU(),
        torch.nn.Linear(H, D_out),
    )

    # nn包还包含常用的损失函数的定义
    # 使用MSE(平均平方误差)  设置 reduction = 'sum' ,表示我们计算的是平方误差的“和”,而不是平均值
    loss_fn = torch.nn.MSELoss(reduction='sum')

    learning_rate = 1e-4
    for t in range(500):

        y_pred = model(x)
        loss = loss_fn(y_pred, y)
        print(t, loss)
        print(t, loss.item())

        # 反向传播之前清零梯度
        # pytorch每次计算梯度是累加的
        model.zero_grad()

        loss.backward()

        with torch.no_grad():
            for param in model.parameters():
                param -= learning_rate * param.grad


optim

torch.optim是一个实现了各种优化算法的库。大部分常用的方法得到支持,并且接口具备足够的通用性,使得未来能够集成更加复杂的方法。

到目前为止,我们已经通过手动改变包含可学习参数的张量来更新模型的权重。对于随机梯度下降(SGD/stochastic gradient descent)等简单的优化算法来说,这不是一个很大的负担,但在实践中,我们经常使用AdaGrad、RMSProp、Adam等更复杂的优化器来训练神经网络。

import torch

# N是批大小;D是输入维度
# H是隐藏层维度;D_out是输出维度
N, D_in, H, D_out = 64, 1000, 100, 10

# 产生随机输入和输出张量
x = torch.randn(N, D_in)
y = torch.randn(N, D_out)

# 使用nn包定义模型和损失函数
model = torch.nn.Sequential(
          torch.nn.Linear(D_in, H),
          torch.nn.ReLU(),
          torch.nn.Linear(H, D_out),
        )
loss_fn = torch.nn.MSELoss(reduction='sum')

# 使用optim包定义优化器(Optimizer)。Optimizer将会为我们更新模型的权重。
# 这里我们使用Adam优化方法;optim包还包含了许多别的优化算法。
# Adam构造函数的第一个参数告诉优化器应该更新哪些张量。
learning_rate = 1e-4
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

for t in range(500):

    # 前向传播:通过像模型输入x计算预测的y
    y_pred = model(x)

    # 计算并打印loss
    loss = loss_fn(y_pred, y)
    print(t, loss.item())

    # 在反向传播之前,使用optimizer将它要更新的所有张量的梯度清零(这些张量是模型可学习的权重)
    optimizer.zero_grad()

    # 反向传播:根据模型的参数计算loss的梯度
    loss.backward()

    # 调用Optimizer的step函数使它所有参数更新
    optimizer.step()

How to denote string

  • One-hot
    • [0,1,0,0,..]
  • Embedding
    • Word2vec
    • glove

Data type

int torch.

PyTorch     

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!