一部分的内容在
2017年1月18日Facebook发行的PyTorch相比TensorFlow、MXNet有何优势? – 罗若天的回答 – 知乎 已有。
主要内容已经在英文博客发布,My first attempt on Pytorch。
第一部分: pytorch和tensorflow比较
1. 分支和循环:tf的循环和分支首先写起来非常恶心,不知道你们怎么觉得,我是写的要哭。(而且会有莫名其妙bug,比如双重分支。。)而pytorch中的循环和分支就是普通的循环和分支,跟python一毛一样的。
2. 在pytorch你可以随时打印中间结果。完全是过程式编程。(tf也可以打印。。但是。。。呵呵)
3. 你不用过多的去考虑怎么构建一个图。图在你进行forward时候自动就造好了。(当然啦,如果要做更fancy的事情的话,还是需要想着中间怎么stop gradient之类的)
4. 很容易就去分开graph和graph外的操作可以放到一起,而且可以完美融合。举个例子你们大概就懂我是什么意思了。
比如说作beam search。tf的做法是,每一步session run一下,获得了prob和state,然后在numpy下排序整理,然后在到session run下一步。第一个缺点是,这样很丑。第二个缺点时,明明可以用cuda的算法排序,但是这里因为在session外面,只能使用numpy。
而pytorch下就很简单,图内的用variable,图外的用tensor,图内的结果要传到图外计算,就直接v.data,图外的结果要扔到图内,就Variable(t). 非常简单。
5. 在tf下使用vgg和resnet我都用的是非官方的code。虽然官方提供了model zoo,但官方models里没有使用这两个模型的样例,只有inception。。然后我由于蠢笨,至今没使官方的model work过。。。。。然而pytorch下,就是一行代码。。。摊手
第二部分:pytorch的一点经验:
1. 如果你想一个tensor在graph中,就把他转化成Variable就可以。如果你希望做一些计算,而这些内容不希望被求导,就直接用torch.Tensor就可以了(比如说你在greedy decoding的时候,作argmax,你这时候就直接在用torch.Tensor就可以了。对computational graph来说,这些内容都是常数。)
2. 如果你想对一个variable做stop_gradient,你可以用,v.detach() 或者Variable(v.data)。目前detach函数还不是很work(forum上说的),但是后者是可以用的。后者的意思,使用原来变量的数据新建一个Variable。这样的话,在计算图中,新的Variable和v其实是不连接的。
3. 另一种方法是,如果你知道某个Variable一定不要做backprop,你可以用定义Variable的时候用Variable(xxx, requires_grad=False) 。比如说,你可以对那些输入变量用这个。但是这个只能在定义的时候用,如果是中间结果,你只能用2中的方法。
4. 如果你做多次forward,而不进行backward,你很容易碰到our of state的问题。因为所有的中间变量都会被保存,而且不会被覆盖。(每次forward都是在保留原本的图的同时,新建一个图)一个方法是你可以detach所有的变量。中间变量则因此不会被保存,因为只有在backward中需要的变量才会被保存。第二种方法是,你可以使用volatile来创建Variable。如果volatile是True,则中间变量不会被保存。注意的是,volatile是会被传染的。对一个operation来说,如果有一个输入时volatile的,则输出是volatile的。这个option经常用在inference,因为通常你不需要记得中间状态来做inference。
5. 如果你不做backward,所有的中间变量会被保存,但是如果你做了一次backward,这些中间变量都会被删除。如果你仍旧想要这些变量,比如说,来再做一次backward,你需要使用 retain_variables=True,作为backward的option。
注意,这里我说中间变量很广义,包括layer中的参数。比如说对全连接层,如果你想获得W的梯度,这一层的输入变量就得保存下来。而如果,你要只做inference,输入变量就可以直接扔掉。
以上观点都是个人愚见,可能有误,欢迎指责。