PyTorch流水账与基于Torch的Waifu2x代码分析

开始

1.nn.PixelShuffle这个函数从名字上看,和ShufflePlanes好像。(https://github.com/XuecaiHu/Meta-SR-Pytorch/blob/master/model/common.py)

2.字面上,bias是偏差的意思。

bias(tensor) - 卷积的偏置系数,大小是(out_channel

3.现在的libtorch模型读入文件已经解决,而Torch模型的Json与t7的关系虽尚未明白,但具体内容人类可读,已经看了大概。

现在的任务是明白网络内容,网络结构保存了什么信息。

模型保存的内容

  • 网络的结构和模型参数
  • 只保存网络的模型参数

在waifu2x的appendix/arch/cunet.txt中是网络结构的描述。虽然我还不知道这仅仅是个文档性能的描述,还是确是导入了代码中…看上去只是一个描述(我不觉得会专门写一段代码,去匹配这样的文字``->`)。

扫盲

4.Waifu2x中vgg_7 -> cunet?

5.话说waifu-caffe中的cNet是代表什么啊,莫不就是cunet?

6.一个灵魂发问,这些代码,抛开实用化的接口,不就是在搭网络吗?

所以我现在学这些代码,除了我耽误之急要用的模型和前向传播相关,余下的核心,不就是怎么搭网络吗。

7.Torch的函数

  • SpatialZeroPadding()

waifu2x 项目结构分析

  • appendix (附录 -> 所以cunet.txt果然只是说明文件)

    • arch: descripte network for torch (only has two files for cunet)

    • caffe_prototxt: prototxt is for caffee, and has a .py file for making cunet.

      Generate prototxt of waifu2x’s cunet/upcunet arch. Training is not possible.

    • 其余是markdown说明和.sh文件

  • assets

    看名字是和网站相关的,里面的文件也是html、css、js三剑客,不用管

  • cache

    顾名思义,里面也没有内容

  • data

    同样没有内容,不知道这是什么套路

  • image_generators

    • dots (字面上是点)

    Only has a gen.lua file, which has this code. So it’s for generating images. However, I can’t understand the meanings of dots.

    But ever, this is for cmd…So…I can ignore it now?

    1
    2
    cmd:text("dot image generator")
    image.save(path.join(opt.o, i .. ".png"), img)
  • images

    Using for description, although some images aren’t used in readme, yet they all seems to used to show the networks.

    • layer_outputs folder

    • Other images and .sh file

  • lib

    Seem to build the newtwork, such as srcnn.lua, which is decripted the SRCNN?

    看了一下w2nn.Lua,感觉Lua这门语言,有点…简单得过分了,调用其他文件,用类似这样的写法,还是在代码的结尾

    1
    require 'Print'
  • models

    models

  • tools

    在这里看到了export_model.Lua,这应该能解答我对模型内容的疑惑。

    emmm,export_model.Lua开篇第一句就是

    1
    -- adapted from https://github.com/marcan/cl-waifu2x

    这是什么意思,cl-waifu2x明明是建立在waifu2x基础上的OpenCL支持项目。(其实..在Lua里这是注释的意思)

    在代码结尾有好看的东西

    1
    2
    cmd:option("-i", "input.t7", 'Specify the input torch model')
    cmd:option("-o", "output.json", 'Specify the output json file')

    这话说的是,进去t7,出来json。依此分析,文件名export的含义,并不是把Torch用的模型输出成t7,而是把导出的t7模型转换成json。也就是说,t7和json的内容,是一致的。

    (顺带一提,看这Lua写的命令行构建代码,真是简洁啊。之前看av1的rust命令行构建代码,虽然不能说比C++更复杂,但也挺长的。)

  • webgen

    For web app, can ignore it.

  • Single Files

    • convert_data.lua -> 似乎是图片预处理的过程
    • install_lua_modules.sh -> 安装依赖
    • train.lua
    • waifu2x.lua
    • web.lua
    • Dockerfile
    • Other Files

综上分析,与核心处理相关的代码,位于lib文件夹(描述网络)和主文件(调用)下,核心代码并不是很多,甚至让我觉得,比Caffe版还要简洁一点。

回到保存的模型

由上面的代码分析,并且去看了历史提交,发现json版的模型文件在初始提交中并没有,而是稍晚时添加的,同时添加了上面的export_model.lua。(虽然初始代码还没有像现在这样构建命令行,但意思是一样的)

1
io.write(cjson.encode(jmodules))

所以先前的判断是没错的,json模型和t7模型就是一致的。json模型是为了“跨框架”而准备的,使预测/前向传播不限于Torch(+CUDA)的框架。

当然,json模型下那一堆小数(与t7模型中整齐的模型参数形成了对比),应该是转换过程中近似计算导致的。这应该很好理解,在Torch下的函数别的地方没有,那只能把数值算出来,用类似查表的方式提供给其他框架。

比如Waifu2x-convert,在modelHandler.hpp/.cpp就用下面的语句读取json模型的内容(借助picojson)

1
picojson::array &wOutputPlane = jsonObj["weight"].get<picojson::array>();

所以可以推测,用json模型会比用t7模型(以及直接由t7转向其他框架模型,如由t7转向pt)精度低?

所以延伸一下,我不能偷懒(或者说瞎折腾),把json模型喂给PyTorch,而还是要借助低版本PyTorch完成从t7到pt的模型转换。但忘了在哪看到了,说PyTorch的C++前端没有明显提速、甚至慢于Python前端,很大程度是因为读取pt模型拖慢了速度。那我能否使用json模型实现精度换速度?

…有想法,但我目前还是按套路出牌吧…

进一步说模型

各版本模型情况

版本 主体文件 辅助文件 hash一致
Waifu2x json/t7 /
Waifu2x-caffe json prototxt
VapourSynth-Waifu2x-caffe json.caffemodel protobin ×

关于t7转pt

这个别想了,用目前查到的convert_torch.py,因为模型结构的原因,没法转cunet的模型,其他的没试(其实在两天前,周五的时候,就在某篇博文上读到过,convert_torch.py不是万能的,今天更是在Github issues上看到了作者类似的回复)。所以Waifu2x-caffe直接用的json模型。

不过话说回来,json模型是怎么转成caffe的caffemodel的?(这样转是为了提高读入速度吗?)

而我从来没注意过Waifu2x-caffe和VapourSynth版代码的区别,读这两种不同格式的模型(json/caffemodel),代码上总归得有点区别吧。

下一步的模型转换计划

所以对于写libtorch,要么想办法手动读入json模型,要么…onnx?

Waifu2x-PyTorch版中,作者自定义了函数load_pre_train_weights()用以加载json模型,所以我可以直接拿来用了?

但Waifu2x-PyTorch的Readme中有句话很让人在意。

Model inference (32 fp only) can run in cpu only.

像只做预测的VapourSynth-Waifu2x-caffe、ncnn版是在GPU中运行的。这里只能在CPU中运行,这是一个可改进的地方。

Whatever,现在情况已经明了了,基于不重复造轮子的原则和我什么不会的实际情况,我完全可以在现有Waifu2x-PyTorch的基础上,去写libtorch的前向计算。至于是写出独立项目,还是基于VapourSynth,这个可以后续再考虑。