Written by
iaalm
on
on
Bye Torch
Torch停止更新已经是几月之前的事情了。这两天仍旧还在改进一些历史遗留的Torch代码。在修了好几个bug之后的感觉torch确实有太多的问题了。鉴于我研究生阶段的大部分deep learning代码都是用torch写的,我觉得我还是有足够的发言权,今天来黑一黑torch的。
顶层设计
Torch主要的问题其实来源于库之间的不一致,这一点上,略微缺乏远见的顶层设计起到了推波助澜的恶作用。
nn.Module
我们从位于模块最顶层的 nn.Module 说起。这个类可以认为是所有层需要遵循的接口,主要需要实现的是以下几个函数
- updateOutput(input) —-前传
- updateGradInput(input, gradOutput) —反传 输出input的梯度
- accGradParameters(input, gradOutput, scale) —-反传 更新内部参数的梯度
- parameters() —-获取参数
- training()
- evaluate() 至于大家常用的forward, backward, getParameter等参数,则是对上面函数的进一步封装。这里显得有点鸡肋的是,官方文档建议我们对updateOutput,updateGradInput,accGradParameters而不是对forward等进行重载。这么做,本意是为了为后续的改进提供空间,但是实际上,很多非官方的库还是选择对forward,backward进行重载,在用户使用时造成很多潜在的不统一性。而对updateGradInput,accGradParameters的划分,本身缺少一些合理性。适合很多人都在updateGradInput中完成实际的工作,而accGradParameters什么都不做,甚至变相鼓励了用户重载backward。这一点在新的pytorch上,还是得到了很多的改进的。
weight和gradWeight
torch官方库中,通常把参数都放在weight和bias两个变量中,而将对应的梯度存放在gradWeight和gradBias中。随意在很多代码中我们可以看到layer:clone(‘weight’,’bias’,’gradWeight’,’gradBias’)来实现共享参数。然而,这样的设计并没有得到贯彻。在一些不使用weight存放参数的库中,使用上面的方法共享参数就会造成无法训练的问题。而这样的问题并不会在执行中产生异常,所以经常让初学者轻易以为自己的想法不work。
缺少broadcast
lua
lua是一个相当优秀的语言,但是将它用于深度学习,还是造成了很多困难。很多lua的语言特性比如:
- 不支持continue
- 不支持try-catch
- 线程模型比较简陋 使得完成的代码可维护性比较差。比如深度学习中数据有小错误很正常,但是没有异常处理机制,无法忽视异常,容易导致程序崩溃。使得torch的代码一般比较依赖前置的预处理程序(通常是别的语言写的)。而一些workaround会使代码中存在大量的工具函数,可读性比较差。另外,还有一个纯粹个人喜好问题,下标从1开始,使得与很多其他语言交互时要花比较多的时间去确认+1-1的问题。