Pytorch摘要
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)相当于进行转置。