前言
学习人工智能有段日子了,一直感觉问题定义难,模型设计难,算力不足难,部署落地更难。期间掉坑无数,出坑不易。结合这段时间的心路历程,完整的记录一个AI应用,从实际问题出发到模型选型、数据收集、数据清洗、模型训练、模型调参... 一直到部署服务器端(云平台,docker,VPS)、手机端(Android,iOS,小程序)、嵌入式设备等应用落地的整个过程。浅入浅出,抛砖引玉,让AI之光照进现实,共同创造一个更美好的世界。
左右滑动查看更多
✎ Tip
如果你足够有耐心,几天内应该能收获一个类似这样完全自制的APP和一个完美无坑的开发体验,enjoy!
问题定义
一个应用是为了解决一个现实问题而生的,所谓AI应用也是一组算法在一堆数据上的一种解决方案,可以是解析解,也可以是统计解,甚至是神经网络那种黑箱解。黑猫白猫,抓到老鼠的就是好猫,这里仍然有效。
要解决的问题是什么,什么就是目标函数,而你手中已有的工具中,找到那个最接近目标函数的方法来拟合。若问题不简单的话,偏差是肯定有的,二者逼近一下,求解。如果最终结果能接受,那么恭喜你,这个应用就有了现实可行性。大多数情况下,套用成熟方案是最佳选择,垂直领域的微创新创造最大的商业价值。
在现实场景下,能解决问题的是小学生,会提问的才是博士生。不过能知道当前技术下,哪种问题可以解决,哪种问题还无解,AI的边界在哪里,可以很大程度上避受不良媒体的忽悠,也可以减少很多所谓"创新项目"的投资陷阱,更可以时刻警醒我这类“手里拿个锤子,看什么都像钉子”的开发者。
模型设计
明确目标函数以后,标准的设计流程是,选定一个目标值,然后对问题抽象化后做个归属,分类还是回归的,CV的还是NLP的,有监督还是无监督,再围绕着目标找领域专家,找原始数据集,提取出一堆特征,然后拿出你的工具箱,制定一堆行业领域规则,用上机器学习,深度学习或是增强学习一通猛算….
每一类领域里有一组算法模型,每一个模型还有无数个超参数,何况你无法保证输入数据是信息完备的。有时候幸福只在于能有选择,而当有无数选择又没能力一一尝试的时候,也会陷入迷茫。要知道模型错了,后续的一切都没有意义了。
✎ Tip
i. 行业规则比算法好用,越朴素的算法泛化性能越好。
i. 比赛的经验在工程上大概率不起作用。
i. 有时候找专家聊比不上一线操作人工可提取的信息多。
i. 直接去业务场景里体验比看需求表有用。
i. 要忘记贪心算法或是动态规划,现实中的问题远不是空间换时间这么容易解决。
动手实践
这里我们先绕过前期枯燥高难的模型定义、数学抽象化这类科学家工作。挑一个最近刚开源比较火的AnimeGAN作为引子,提高些兴趣,不至于直接从入门到放弃。AnimeGAN的主要功能是可以将漫画风格提取出来迁移到现实场景中,目标函数是明确的:就是生成一张形状轮廓像现实的,风格带有漫画的图片。自从StyleGan发布以后,这个领域一直百花齐放着。
相关的论文和源码可以在这里下载。https://github.com/TachibanaYoshino/AnimeGAN
论文解读
AnimeGAN相对于CartoonGAN更进了一步,采用Gram矩阵来保存灰度图以保留更多的风格特征,训练时也无须成对数据。除了常规的对抗loss外,另外设计了3个新的loss,分别计算灰度风格损失、色彩重建损失和灰度对抗损失,判别器中还增加了一个边缘提升对抗损失用于保留清晰的边缘。
生成器先下采样倍增通道数到256,然后通过8个反向残差模块(IRB模块)来提取特征,再上采样输出图片。估计为了保留更多的风格,实际代码最后一组上采样时扩展为128通道,与论文略有差别。判别器则采用比较常规的边卷积边归一化,逐步缩小尺寸,一直到做出真假判断。
论文作者考虑到动画更多表现在线条上,所以提取了灰度纹理作为一组输入。损失函数则由4个部分组成,分别代表假图片和真图片的差异(权重300),内容差异(权重1.5),灰度风格的纹理差异(权重3)和色彩重建的差异(权重10)。
对比CartoonGAN, ComixGAN 和 AnimeGAN 参数量,推理速度和最终效果的差异,的确取得了一定程度的改善。
接着就进入玄学领域了,这是一组不同权重值效果的对比,如果说这些loss函数定义出来还可以理解,这些权重值则有点玄学了。虽然作者说是实验而来,但这相差这么大数量级,还是需要设计者拥有很多的先验知识,再配合大量的实验。
环境配置
好了,理论知识足够了,华丽开干吧。出发前,我们先对一下表… 哦,不,是对一下环境配置。被太多的python版本,tensorflow版本,cuda驱动版本迫害的有心理阴影了。实际上这个项目环境友好,大多数版本都能顺利运行。
操作系统:ubuntu 18.04 (或windows 10)
Python 3.7(3.6)
Tensorflow-gpu1.13.1
CUDA 10.1
先安装anaconda,创建虚拟环境
conda create –n tensorflow python=3.7
conda activate tensorflow
pip install tensorflow-gpu=1.13.1
pip install opencv-python
pip install tqdm
pip install numpy
pip install argparse
将项目克隆回来
git clone https://github.com/TachibanaYoshino/AnimeGAN
下载Vgg19权重
https://github.com/TachibanaYoshino/AnimeGAN/releases/download/vgg16%2F19.npy/vgg19.npy
初始训练权重
https://github.com/TachibanaYoshino/AnimeGAN/releases/download/Haoyao-style_V1.0/Haoyao-style-initial-checkpoint.zip
训练到60个epoch的权重
https://github.com/TachibanaYoshino/AnimeGAN/releases/download/Haoyao-style_V1.0/Haoyao-style.zip
下载数据集
https://github.com/TachibanaYoshino/AnimeGAN/releases/download/dataset-1/dataset.zip
✎ Tip
嫌弃github上速度太慢的,也可以直接到我网盘中下载。
链接:https://pan.baidu.com/s/1cJdURE6wXWQiDW5jvfSdog
提取码:llpx
准备训练
将dataset.zip 解压到dataset目录下;
将Haoyao-style.zip 解压到 ;
将vgg19.npy的权重放置在vgg19_weight目录下;
将Haoyao-style-initial-checkpoint.zip 解压到checkpoint /AnimeGAN_Hayao_lsgan_300_300_1_3_10 目录下。
万事俱备,先确保一下tensorflow的gpu环境正常,用CPU训练的速度是不能忍的。
import tensorflow as tf
sess =tf.Session(config=tf.ConfigProto(log_device_placement=True))
指定训练集的位置,batch size默认为4,我这里设置到6加快训练速度(TITAN X),可以根据显存大小调整,初始epoch为1,从头开始训练用以复现论文。
python main.py--phase train --dataset Hayao --batch_size6 --epoch 131 --init_epoch 1
✎ Tip
记把 os.environ["CUDA_VISIBLE_DEVICES"]= "1" 改为自己显卡对应的位置。
从原始数据集出发,训练了3天左右,我们可以发现50个epoch之后,生成器已趋于饱和,效果不在有明显的提升。100个epoch之后,判别器被训练的非常强大,loss值一直在1左右,生成图像已接近于原图,完全处于过拟合状态了。
模型收敛的速度非常快,越靠前的epoch越偏向于漫画感,越靠后的则贴近于现实图。欠拟合状态下生成的图片,容易在色彩集中的位置出现噪点,感觉是色彩重建的部分还没有训练好引起的。
原图
EPOCH=30
EPOCH=50
EPOCH=100
生成漫画
结合测试集的效果和生成器的趋势,我们可以在sample目录下查看各个epoch生成图片的效果,选择epoch=50的那个最优结果。打开checkpoint 文件,将第一行改为 model_checkpoint_path:"AnimeGAN.model-50"。
pythontest.py --checkpoint_dir checkpoint/AnimeGAN_Hayao_lsgan_300_300_1_3_10--test_dir dataset/test/real --style_name H
将准备好的现实图片放入 dataset/test/real 目录下,然后就能在 results/H 目录下看到生成的漫画图片了。
✎ Tip
训练的过程比较漫长,如果迫切想看到效果,也可以用论文作者提供的训练完成后的checkpoint做图像生成。Haoyao-style.zip
原图
生成图
原图
生成图
原图
生成图
原图
生成图
生成速度取决于输入图片的尺寸和放入目录的文件数量,转换还蛮快的,能达到6.24it/s。再优化一下,可以用于实时动画生成了。
可以看到,该模型风景转换的效果比较好,人脸的涂抹感比较重。一来是训练数据中人像的比较少,二来用Canny做边缘提取的时,小尺寸图片对人脸进行了涂抹,丢失了一些细节信息,大尺寸图片又保留太多细节,丧失了漫画感。
下一篇
我们聊一下自定义数据集,
来尝试解决这个问题,
顺便生成自己想要的风格的漫画。
待续...