Pytorch

不同于Tensorflow(not include eager execution)这种基于静态计算图的深度学习框架,Pytorch是基于动态图的。首先要理解什么是静态/动态图:静态图是一次性定义好计算图框架,然后将数据批量地输入进行训练,评估;动态图是每次计算都是一个计算图。

这两种设计模式上的区别就导致了Tensorflow在某些场景下有点捉襟见肘。while循环是一个经典的应用场景,在tensorflow里只能使用tf.while_loop来定义while循环的条件和运行内容, 而pytorch的话可以直接使用python内置的while语句。更进一步,tensorflow在定义RNN传入的数据[batch_size, time_step, inputs]不能同时将batch_size和time_step设置为-1。当每个训练样本的time step长度不一致时,一般的处理方式是进行padding,补成相同的长度。如果要实现真正意义上的不同time step,需要将batch_size固定,使用dynamic rnn传入time step为-1。而在pytorch中batch_size和time_step可以都不确定。

常用操作

  • torch.autograd.Variable
    是pytorch的核心类,它包装了张量,当对其调用backward()方法是,会自动进行梯度计算。Variable包含几个属性:data(返回原始张量), 所有的梯度回累计到grad属性上(grad本身也是一个Variabl )

  • model.train() / model.eval() 在训练模型/评估模型的开始调用上述语句,切换模式,用于区分train/evaluation阶段的drop out/固定batch normalizaiton值等操作。

  • with torch.no_grad():
    一种context-manager,下文的内容均取消梯度计算的操作,如果确定下文内容不会调用Tensor.backward()则可以加入该操作,用以减少计算梯度带来的内存消耗, 因此一般用于evaluation阶段。

  • torch.Tensor.detach()
    截断反向传播的梯度流, returns a new Variable, detached form the current graph. 将某个node转为不需要梯度的Variable, 当反向传播经过该node时,梯度不会再往前传播。一种使用场景用于RNN模型,在不同的batch之间截断c_t和h_t

  • torch.mm.Module.zero_grad()
    将缓冲区所有变量参数设置为0。zero the parameter gradients。经常和Tensor.detach()搭配使用。

  • backward()
    对于loss,调用backward()用以计算梯度。如果Variable是表量(包含一个元素)可以直接调用backward, 如果是有多个元素需要指定gradient参数,其shape与输入的shape一致。

  • tensor.cuda()
    使用.cuda方法将tensors在GPU上运行

if torch.cuda.is_available():
    x = x.cuda()
    y = y.cuda()
    c = x + y

tensor运算

  • tensor.narrow(dim, start, size)
    从原始向量的第dim维上从start开始索引size个。dim为0按行,dim为1按列。一般用于截取子tensor。

  • tensor.t()
    将向量0,1维度做转置,相当于tensor.transpose(o, 1)

  • tf.nn.embedding(num_embeddings, embedding_dim)(input)
    对模型输入embedding, 比如输入tf.nn.embedding(10, 3)([[1, 2, 3, 4], [4, 5, 6, 9]])会输出shape为(2, 4, 3)

  • torch.stack(seq, dim=0, out=None)
    将tensor的list进行concatenation, dim=0时,将一个原始list(存有10个长度为5的tensor), 按行level拼接成一个shape为10, 5的tensor。

  • tensor.squeeze()
    将所有维度为1的删除掉。比如input原始shape为1015, 删除后为10*5。

  • tensor.div(value)
    对原tensor中每一个元素都除以一个值value.

  • tensor.operator_
    y.add_(x), x.t_()等操作函数后加一个下划线,都是直接改变原张量。

  • tensor与numpy的转换
    通过tensor.numpy()将张量转为numpy, 两者共享一个内存空间。 通过torch.from_num(np.zeros(5))将numpy转化为tensor, 同样共享内存。

a = tensor.ones(5)
b = a.numpy()
a.add_(1) # (2, 2, 2, 2, 2)
b #(2, 2, 2, 2, 2)
  • tensor.permute(*dims)

交换数据维度,如果对二维矩阵进行tensor.permute(1, 0)相当于进行转置。