用数据说话:把自拍照变成毕加索名画 哪种算法最高效?

    xiaoxiao2021-04-15  241

    提起前段时间红遍朋友圈的 Prisma,可能许多朋友都还记忆犹新:输入一张自己的照片,再选一个 Prisma 内置的名画滤镜,几秒之后就能得到一张名画风的新照片。

    绝大部分用户可能只是通过 Prisma 过了一把当画家的瘾,但对于程序猿们来说,仅仅得到一张风格迥异的新照片似乎还远远不够。

    近日,有位外国开发者根据 fast.ai 平台开设的深度学习代码实践课程,亲手实现了一个照片风格转换器,并对几种常见的优化算法的性能进行了综合对比,最终以图表加博客的方式记录下来。

    下面就让我们跟随作者的脚步,一起看看究竟哪种算法最高效(程序猿是怎么玩坏 Prisma 的)。原文来自 medium.com ,雷锋网(公众号:雷锋网)编译。文中相关的代码开源地址和原博客地址见文末。

      什么是照片风格转换器?它是怎么工作的?

    问题1:什么是风格转换器(style transfer)?

    所谓照片风格转换器,就是类似 Prisma 的,转换照片风格的软件 App。他们抽取 A 照片的风格特征(一般都是一张名画),然后将这种特征应用到 B 照片的内容上,从而生成了全新的照片 C。

    问题2:怎样分隔一张照片的风格和内容?

    使用卷积神经网络(CNN)。由于 AlexNet 已经成功地将 CNN 应用于目标识别(即确定图像中的主体内容),并且在 2012 年主导了最流行的计算机视觉竞赛,因此 CNN 是目前用于图像目标识别的最流行和有效的方法。

    简单说,CNN 是通过学习构建在先前图层上的各个过滤器层来识别对象的。例如,第一层通常用来学习识别简单的图案,例如物体的边缘和棱角。中间层可能用来识别更复杂的图案,例如人物的眼镜、汽车的轮胎等。Jason Yosinski 大神曾在下面这个视频中详细介绍了 CNN 的相关内容。

    https://www.youtube.com/watch?v=AgkfIQ4IGaM 

    事实证明,CNN 第一层中的过滤器对应于一张照片的风格,包括画笔描边、纹理等。靠后的图层中的过滤器对应于识别图像中的主体,例如狗,建筑物或一座山等。

    例如,将一幅毕加索的画作输入 CNN,并分析第一层(样式层)有多少过滤器被激活,就可以得到该画作的样式表示。同样,通过最后一层(内容层)的分析,我们也可以得到画作内容的表示。

    问题3:怎样将风格和内容融合在一起?

    这一步很有意思。由于两张照片的风格大不相同,因此它们的样式层中激活的过滤器也就不同,通过分析两个样式层中的过滤器,就能获得两张照片的样式之间的差别。同样,对内容层中过滤器的分析,也能得到两张照片内容的差别。

    例如,如图所示,我们想把一张自拍照和毕加索的画作融合。融合后的图像首先以图示中的噪声图像为起点,然后将这张图像输入 CNN ,它会激活样式层和内容层中的一些特定的过滤器。按照上述的方法,通过对比融合照片和毕加索画作的风格层,就可以得到风格损失(style loss);通过对比融合照片和自拍照的内容层,就可以得到内容损失(content loss),将两种损失相加,就得到了总损失。

    下面的任务就很清楚了:通过优化算法的介入,我们想办法将这个总损失最小化,最终就得到了一张毕加索风格的自拍照了。

    问题4:有哪些常见的优化算法?

    到目前为止,我遇到了两种类型的优化算法:一阶的和二阶的。

    一阶方法通过梯度(gradient)将目标函数最小化(或者最大化)。应用最广泛的就是梯度下降法(Gradient Descent)及其各种变体,详情见如下链接:

    http://sebastianruder.com/optimizing-gradient-descent/ 

    二阶方法是通过二阶导数将目标函数最小化(或者最大化)。由于二阶导数的计算成本很高,因此这里所讨论的二阶算法 L-BFGS(Limited-memory Broyden–Fletcher–Goldfarb–Shanno) 使用了 Hessian 矩阵近似。

      哪种优化算法最高效?

    由于我们在以下试验中处理的照片颜色灰度都介于 0-255 之间,因此将各算法的学习率(learning rate)都设置为 10,这看起来可能有点大,但效果还可以接受。算法的其他超参数(hyperparameters)都保持默认。测试的硬件环境是:Amazon P2 实例上的单片 K80 GPU。

    实验1:100 次循环,300 x 300 像素

    如图所示,我们输入了两张 300 x 300 像素的照片,并运行整个优化循环 100 次。虽然 100 次并不足以生成一个效果很好的融合照片,但对我们分析各个优化算法的性能已经足够了。

    如图所示,由于学习率设置的略大,因此梯度下降(Gradient Descent)、Adadelta 和 RMSProp 在整个循环中都处于不断的震荡状态,并没有显示出明显的收敛趋势。反观 Adam 和 L-BFGS 算法则能够快速收敛,并且误差也基本相同。

    实验2:100 次循环,600 x 600 像素

    当参数增多时,L-BFGS 算法应该表现的更好。为此,我们在试验2中增大了图像,并切换了素材。

    如图所示,虽然学习率的设置还是略大,但梯度下降和 Adadelta 算法在面对大数据量时显得更稳定,RMSProp 还是始终处于震荡状态。

    另外,Adam 算法一开始收敛很快,但后期被 L-BFGS 反超。不知道是不是和循环次数有关,下面我们试着增加循环次数。

    实验3:1000 次循环,300 x 300 像素

    在实验3中,我们增加了循环次数,依然使用实验2中的照片素材,但像素变为 300 x 300。

    如图所示,在略大的学习率设置下,梯度下降、Adadelta 和 RMSProp 始终处于震荡状态无法收敛。但 Adam、Adagrad 和 L-BFGS 三种算法的收敛情况则相对较好,其中效果最好的 L-BFGS 大约比 Adam 的优化效果好 50% ,并且速度也更快。

    从最终生成的融合照片的成像效果也能看出来,L-BFGS、Adam 和 Adagrad 的效果要好一些。

    实验4:不同的学习率,100 次循环,300 x 300 像素

    有说法称过大的学习率可能会导致梯度下降、Adadelta 和 RMSProp 三种算法不收敛,因此在实验 4 中我们减小这三种算法的学习率。

    可以看到,所有算法最终都收敛了。可能是得益于较低的学习速率,梯度下降的最终表现要优于 Adadelta 算法。另外,较高的学习率虽然在一开始时帮助 Adam LR 10 取得了较快的收敛速度,但最终效果并不好。而 Adam LR 1 虽然收敛缓慢,但表现很稳定。那么问题来了,如果增加循环次数,Adam LR 1 的表现是否会超过 Adam LR 10 呢?

    实验5:不同的学习率,500 次循环,300 x 300 像素

    增加循环次数之后,即便在学习速率较小的情况下,梯度下降、Adadelta 和 RMSProp 三种算法也还是出现了震荡。

    有趣的是,Adam LR 1 最终果然反超了 Adam LR 10,甚至有超过 L-BFGS 的趋势。

    实验6:1000 次循环,300 x 300 像素

    这一次我们仅仅对 Adam LR 1 和 L-BFGS 进行了对比,通过进一步增加循环次数,可以看到,Adam LR 1 最终的表现并没有超过 L-BFGS。

      总结

    从上述试验可以发现:在较大的学习率设置下,梯度下降、Adadelta 和 RMSProp 三种算法不容易收敛,但增大数据量,前两种会有所好转。总体上,L-BFGS 算法的收敛效果最好,速度也最快。

    改变学习率。Adam 在学习率较小时,收敛情况提升明显,随着循环次数的增大,收敛效果几乎与 L-BFGS 算法相当,但收敛情况最好的依然是 L-BFGS 算法。

    最后作者表示,以上实验只是从参数设置、数据量和迭代次数等方面入手简单探索了几种常见算法的特性,目的只是帮助大家在开发中更好地使用它们。虽然试验结果显示 L-BFGS 算法的收敛速度最快,效果最好,但按照个人习惯,他用 Adam 算法的情况反而更多。另外,究竟哪种算法效果最好,也不能一概而论,还是要根据数据类型和项目要求灵活选择。

    源码地址:https://github.com/slavivanov/Style-Tranfer 

    本文作者:恒亮 本文转自雷锋网禁止二次转载, 原文链接 相关资源:七夕情人节表白HTML源码(两款)

    最新回复(0)