汉字风格迁移项目Rewrite:利用神经网络学习设计汉字新字体

By 吴攀2016年11月04日 14:54

日前,Flipboard 软件工程师 Yuchen Tian 在 GitHub 上发布了用于汉字字体的神经风格迁移的项目,该项目介绍了如何通过神经网络学习设计汉字新字体的方法。机器之心授权编译发布。

项目地址:https://github.com/kaonashi-tyc/Rewrite

项目目的

创建字体是一件难事,创建汉字字体更是艰难。要做一个兼容 GBK(中国政府设定的字符集标准)的字体,设计师需要为超过 26000 个不同的汉字字符设计外观,这是一项艰巨的工作,可能需要数年时间才能完成。

可不可以让设计师仅设计其中一部分字符的字体,然后让计算机来确定剩下的字符应该是什么模样呢?毕竟,汉字是由一些被称为「偏旁部首」的基本元素构成的;在不同的汉字上,相同的偏旁部首看起来也都相当雷同。

这个项目是使用深度学习的一个探索性的应用。具体而言,整个字体设计流程可被表示成一个风格迁移问题(style transfer problem)——将标准样式字体(比如 SIMSUN 体)转换为目标风格的字体。本项目通过向一个神经网络提供配对样本的子集来训练该神经网络近似学会两种字体设计之间的转换。一旦学习完成,该神经网络就可被用来推理其它字符的外形。下面的框图大概说明了这个思想:

box_for_ideas.png

这个项目的灵感很大程度上来自于 Erik Bernhardsson 的博客《Analyzing 50k fonts using deep neural networks》和 Shumeet Baluja 的好论文《Learning Typographic Style》。

网络结构

在尝试过了各种不同的架构(包括具有残差(residuals)和去卷积(deconvolution)的更复杂的架构)之后,我最终选择了一种更为传统的自上而下的 CNN 架构,如下所示。

structure.png

注意事项:

可视化

训练中的进展

mixed_font.gif

上图展示了模型在多种字体上的训练过程中的验证集上所取得的进展。它们全都在 2000 个样本上进行了训练,层数设置为 3。看该模型如何从随机噪声收敛是很有意思的:首先获取一个字符的可识别的形状,然后获取更为细微的细节。下面是训练过程中某种字体的进展过程。

single_font_progress.gif


与 ground truth 比较

下面的图像给出了对比 ground truth 的预测结果。对于每一种字体,我们都选取了最常用的 2000 个字作为训练集,运行 3000 次迭代。另外还有一个包含 100 个字的测试集用于推理。对于所有的字体,源字体都是 SIMSUN。

predicted_vs_ground_truth.png


对于其中大部分字体,该网络都能成功做出合理的猜测。实际上其中一些还跟 ground truth 非常接近。另外值得一提的是,该网络还保留了微小的但可辨认的细节,比如偏旁部首的弯曲的端部。

但正如许多其它的神经网络所驱动的应用一样,当该网络出错时,就会错得非常离谱。对于一些字体(尤其是笔画粗的字体),它只会得到一些模糊的字迹斑点。另一方面,对于这些笔画粗的字体,它会失去让该字符可被辨认的关键的空白处细节,而只会获取到整体的轮廓。即使是在成功的案例中,偏旁部首的损失问题似乎也很常见。此外,网络似乎在宋体上可以做的更好,但在楷体上表现并不好,这主要是因为 SIMSUN 字体本身也是一种宋体。

因为空间的限制,对于每一种字体,我们从测试集中仅随机取样了一个字符。如果你想看到在更大的字符测试集上的结果,请查阅这里

需要多少字符?

2000 字也许只有 GBK 集的 10%,但也仍然很多了。这个数字是我靠直觉选择的,而且看起来这个选择在很多字体上都表现不错。但必需这么多吗?

为了搞清这一点,我选择了一种字体(在每种字体上都进行这个实验会太耗时间)进行了不同数量的训练样本的实验,数量的范围是从 500 到 2000,然后让该模型在一个常用的测试集上对字符进行渲染,下面是得到的结果。

different_training_size.png


从上到下,上图分别给出了训练集大小从 500 到 2000 增长时的不同结果。当训练集大小在 1500 到 2000 之间,表现的提升会变得更小,这表明 sweet point 就在这之间的某个地方。

使用方法

要求

要使用这个软件包,需要安装 TensorFlow(已在 0.10.0 上测试过)。其它的 Python 要求列在 requirements.txt 文件里。另外强烈推荐使用 GPU——如果你想在合理的时间内看到结果。

我的所有实验都运行在一个 Nvidia GTX 1080 上。以 16 的 batch 大小进行了 3000 次迭代,这需要小型模型计算 20 分钟、中规模模型计算 80 分钟、大模型则需要 2 小时。

样例

在训练之前,你需要运行预处理脚本为源字体和目标字体生成字符位图(character bitmap):

python preprocess.py --source_font src.ttf \
                     --target_font tgt.otf \
                     --char_list charsets/top_3000_simplified.txt \ 
                     --save_dir path_to_save_bitmap

该预处理脚本支持 TrueType 和 OpenType 字体,它会获取一个字符列表(一些常见的字符集内置于本 repo 的 charsets 目录中,比如 3000 个最常用的简体汉字字符),然后将这些字符的位图保存为 .npy 格式。对于源字体,每个字体会被默认保存为字体大小为 128 的 160×160 的尺寸,而目标字体则是字体大小为 64 的 80×80 的尺寸。这里并不需要特别的对齐,只要确保字符不被截断即可。

在预处理步骤之后,你就能得到源字体和目标字体的位图,分别是 src.npy 和 tgt.npy,然后运行以下命令开始实际的训练:

python rewrite.py --mode=train \ 
                  --model=medium \
                  --source_font=src.npy \
                  --target_font=tgt.npy \ 
                  --iter=3000 \
                  --num_examples=2100 \
                  --num_validations=100 \
                  --tv=0.0001 \
                  --keep_prob=0.9 \ 
                  --num_ckpt=10 \
                  --ckpt_dir=path_to_save_checkpoints \ 
                  --summary_dir=path_to_save_summaries\
                  --frame_dir=path_to_save_frames

这里给出了一些解释:

对于其它选择,你可以使用 -h 查看确切的使用案例。

假设我们最后完成了训练(终于完成了!),我们就可以使用前面所提到的 infer 模式了,看模型在之前从未见过的字符上表现如何。你可以在 frame_dir 中参考获取的帧来帮助你选择你最满意的模型(说明一下:通常不是误差最小的那个)。运行以下命令:

python rewrite.py --mode=infer \
                  --model=medium \
                  --source_font=src.npy \
                  --ckpt=path_to_your_favorite_model_checkpoints \
                  --bitmap_dir=path_to_save_the_inferred_output

注意这里的 source_font 可以不同于训练中所使用的那个。事实上,它甚至可以是任何其它字体。但最好选择相同或相似的字体进行推理,以得到最佳的结果。在推理之后,你将能找到所有输出字符的图像序列以及一个包含了这些推理出的字符位图的 npy 文件。

讨论&未来工作

该项目只是一个个人项目,来帮助我学习和理解 TensorFlow,但也顺利发展成了一件更为有趣的事,所以我认为值得与更多的人分享。

目前,该网络一次只能学习一种风格,如何将它扩展到一次性掌握多种风格会是一件有趣的事。2000 个字符比完整 GBK 数据集的 10% 还少,但它还是比较多的,少于 100 字符的情况下有可能学习到字体的风格吗?我的猜测是 GAN 可能会对此有所帮助。

在网络的设计上,该架构被证明在不同的字体上是有效的,但每个卷积层的数量的优化还需要搞清楚,或者一些卷积层是否有必要?

我想要探索的另一个有趣的方向是创造混合多种风格的字体。在损失函数上简单结合两种字体的表现并不好。可能我们应该为字体单独训练一个 VGG 网络,然后劫持(hijacking)特征映射?或者在网络设计上使用潜在更多的新变化,从而解决这个问题?

最后,该项目证明了更专门化的应用深度学习的可能性,CNN 帮助加速了汉字字体的设计流程。研究的结果很是振奋人心,但并非从无到有的创造新字体,这也不是该项目的内容。

感谢&有用的资料

证书

GPLv3

声明:本文由机器之心编译出品,原文来自GitHub,作者 Yuchen Tian转载请查看要求,机器之心对于违规侵权者保有法律追诉权。