我试图在keras中构建一个卷积自动编码器,但它似乎无法正常工作。首先,这是代码:
from keras.models import Sequential
from keras.layers import Reshape
from keras.layers import Flatten
from keras.layers import Dense
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import UpSampling2D
from keras.optimizers import RMSprop
from keras.losses import categorical_crossentropy
import numpy as np
import matplotlib.pyplot as plt
import scipy
import h5py
import random
from glob import glob
from tqdm import tqdm
from os import getcwd
learning_rate = 0.001
epochs = 10000
batch_size = 200
data_len = 400
training_data = []
for filename in tqdm(glob('D:/AI/Celeba/*.jpg')[0:data_len],desc='loading images'):
im = scipy.misc.imread(filename)
im = scipy.misc.imresize(im,(128,128))
training_data.append(im)
training_data = np.array(training_data)
example = random.choice(training_data)
autoencoder = Sequential()
autoencoder.add(Conv2D(32,5,activation='relu',input_shape=(128,128,3)))
autoencoder.add(MaxPooling2D())
autoencoder.add(Conv2D(16,5,activation='relu'))
autoencoder.add(MaxPooling2D())
autoencoder.add(Conv2D(8,5,activation='relu'))
autoencoder.add(MaxPooling2D())
autoencoder.add(Conv2D(4,5,activation='relu'))
autoencoder.add(MaxPooling2D())
autoencoder.add(Conv2D(2,3,activation='relu'))
autoencoder.add(MaxPooling2D())
autoencoder.add(Flatten())
autoencoder.add(Dense(32,activation='sigmoid'))
autoencoder.add(Dense(32,activation='sigmoid'))
autoencoder.add(Reshape((4,4,2)))
autoencoder.add(Conv2D(2,3,activation='relu'))
autoencoder.add(UpSampling2D())
autoencoder.add(Conv2D(4,5,activation='relu'))
autoencoder.add(UpSampling2D())
autoencoder.add(Conv2D(8,5,activation='relu'))
autoencoder.add(UpSampling2D())
autoencoder.add(Conv2D(16,5,activation='relu'))
autoencoder.add(UpSampling2D())
autoencoder.add(Conv2D(32,5,activation='relu'))
autoencoder.add(UpSampling2D())
autoencoder.add(Conv2D(3,5,activation='relu'))
autoencoder.compile(optimizer=RMSprop(lr=learning_rate),loss=categorical_crossentropy)
for epoch in range(epochs):
autoencoder.fit(x=training_data,y=training_data,batch_size=batch_size,epochs=1)
output = autoencoder.predict(np.array([example]))[0]
fig = plt.figure()
fig.suptitle('training step: {}'.format(epoch+1))
a=fig.add_subplot(1,2,1)
imgplot = plt.imshow(example)
a.set_title('Original')
a=fig.add_subplot(1,2,2)
imgplot = plt.imshow(output)
imgplot.set_clim(0.0,0.7)
a.set_title('Reconstruction')
plt.savefig(getcwd()+'/training/{}.png'.format(epoch))
if (epoch+1)%10 == 0:
autoencoder.save(getcwd()+'/saved/model.h5')
所以我的问题是模型输出了错误的形状。输出形状为[batch_size, 2, 2, 3]
,而它应该为[batch_size, 128, 128, 3]
。我做了一些调试,找出了模型输出错误维度的一些可能原因:
UpSampling2D
层没有执行任何操作- 由于某种原因,最后一个
Conv2D
层将图像的大小减小了2
有人知道我该怎么解决吗?
PS。在写这篇文章的时候,我意识到我的调试结果可以用另一种方式来解释:
UpSampling2D
层工作良好- 所有
Conv2D
层都将图像的大小缩小了2,因此图像始终保持2*2高
在Conv2D层中,您正在减小输入的大小。
在卷积中,如果您拍摄32乘32的图像,并应用5x5的内核。输出图像的大小为28乘28。
3乘3的Kernel会得到30乘30的图像,4乘4会得到29乘29的图像。
如果你想防止卷积的大小减少,你可以添加填充。
这提供了一个很好的资源来了解是否要填充。
此外,当大小是奇数时,最好知道下采样是向下还是向上取整,这可能会对你以后有所帮助。我相信它是向下取整的。
我还强烈建议您执行autoencoder.summary((,这将为您提供有关每层维度的信息。有了这个,你可以弄清楚每一层发生了什么。