版权声明:本文为原创文章,未经博主允许不得用于商业用途。
\qquad 最基本的AutoEncode是由三层网络组成的,即输入层,输出层和编码层,这里拓展为深度模型则将Encoder和Decoder都变为一个深度网络,如下图:
优化目标为使得输入和输出尽可能相似,而中间的Code即为降维后的结果。
\qquad 相比于PCA或者LDA,DAE的多层网络结构使得其为非线性模型,因此可以更好的还原输入。
\qquad 数据集使用了李宏毅老师提供的宝可梦数据集,链接如下:
原始图片
编码后数组
colormap
共包含792种宝可梦的彩色图片,每张图片大小为20*20,已经经过预处理将颜色空间从256*256*256映射到常用的167种颜色并重新按需编码储存。
\qquad 本来这样应该可以降低输入的维度从而减少网络的复杂程度,但是在真正训练时发现由于167种颜色之间没有线性关系,因此如果直接将数据集作为输入则很容易出现小的偏差造成输出图片上的巨大差异,如输出从7.3到7.6,则在绘图时会从7号颜色(如白色)变为8号颜色(如黑色),因此只能将每一个像素映射为167维的01向量,将原来的线性预测模型变为20*20个分类器,输入维度变为20*20*167。
\qquad 由于我目前在用新笔记本,没有独显,只能用CPU跑,所以在训练时只选择了其中的110个宝可梦作为数据集。
\qquad 我直接使用了五个全连接层作为encoder和decoder,最后使用Sigmoid映射到0,1,代码如下:
class ATE(nn.Module):
def __init__(self):
super(ATE,self).__init__()
self.encoder = nn.Sequential(
nn.Linear(400*167,400),
nn.Linear(400,128),
nn.Linear(128,64),
nn.Linear(64,12),
nn.Linear(12,5),
)
self.decoder = nn.Sequential(
nn.Linear(5,12),
nn.Linear(12,64),
nn.Linear(64,128),
nn.Linear(128,400),
nn.Linear(400,400*167),
nn.Sigmoid(),
)
def forward(self,x):
x=self.encoder(x)
x=self.decoder(x)
return x
训练时采用BCE误差,Adam优化器,效果如下:
其中左侧为输入数据,右侧为经过DAE编码-解码后的输出,从颜色和形状来看很好的还原了原来的特征。
我尝试使用DAE产生一些中间图片。
\qquad 之前听说过DAE无法很好的产生新的数据,这是由于训练时无法保证编码空间里样本点周围的点都可以有效解码,且和样本相关联。
\qquad 我选择了比较相似的宝可梦之间的向量作为生成码,具体即将两个样本之间的高维空间线段等分后进行解码。
上方是从皮丘进化到皮卡丘的过程,可以看到中间几张图都完全看不出形象并且失去了原来的颜色。下方是从鬼斯进化到鬼斯通,信息保留比较好,不过中间的都不像是新的宝可梦。
源码见github