我感到惊讶的是,我实施的深度学习算法无法正常工作,因此我决定创建一个非常简单的示例,以更好地了解CNN的功能。这是我为一个非常简单的任务构造一个小的CNN的尝试,它提供了意外的结果。
我实现了一个仅带有一层滤镜的简单CNN。我创建了一个包含5000个样本的数据集,输入x是256x256仿真图像,输出y是相应的模糊图像(y = signal.convolvded2d(x,gaussian_kernel,boundary ='fill',mode ='same')) 。因此,我希望CNN学习卷积滤波器,它将原始图像转换为模糊图像。换句话说,我希望CNN恢复用于创建模糊图像的高斯滤波器。注意:由于我想“模仿”数学框架中描述的卷积过程,因此我使用的高斯滤波器的大小与我的图像相同:256x256。
在我看来,这是一项非常容易的任务,但是,CNN无法提供我期望的结果。请在下面找到我训练功能的代码和结果。
# Parameters
size_image = 256
normalization = 1
sigma = 7
n_train = 4900
ind_samples_training =np.linspace(1, n_train, n_train).astype(int)
nb_epochs = 5
minibatch_size = 5
learning_rate = np.logspace(-3,-5,nb_epochs)
tf.reset_default_graph()
tf.set_random_seed(1)
seed = 3
n_train = len(ind_samples_training)
costs = []
# Create Placeholders of the correct shape
X = tf.placeholder(tf.float64, shape=(None, size_image, size_image, 1), name = 'X')
Y_blur_true = tf.placeholder(tf.float64, shape=(None, size_image, size_image, 1), name = 'Y_true')
learning_rate_placeholder = tf.placeholder(tf.float32, shape=[])
# parameters to learn --should be an approximation of the gaussian filter
filter_to_learn = tf.get_variable('filter_to_learn',\
shape = [size_image,size_image,1,1],\
dtype = tf.float64,\
initializer = tf.contrib.layers.xavier_initializer(seed = 0),\
trainable = True)
# Forward propagation: Build the forward propagation in the tensorflow graph
Y_blur_hat = tf.nn.conv2d(X, filter_to_learn, strides = [1,1,1,1], padding = 'SAME')
# Cost function: Add cost function to tensorflow graph
cost = tf.losses.mean_squared_error(Y_blur_true,Y_blur_hat,weights=1.0)
# Backpropagation: Define the tensorflow optimizer. Use an AdamOptimizer that minimizes the cost.
opt_adam = tf.train.AdamOptimizer(learning_rate=learning_rate_placeholder)
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
with tf.control_dependencies(update_ops):
optimizer = opt_adam.minimize(cost)
# Initialize all the variables globally
init = tf.global_variables_initializer()
lr = learning_rate[0]
# Start the session to compute the tensorflow graph
with tf.Session() as sess:
# Run the initialization
sess.run(init)
# Do the training loop
for epoch in range(nb_epochs):
minibatch_cost = 0.
seed = seed + 1
permutation = list(np.random.permutation(n_train))
shuffled_ind_samples = np.array(ind_samples_training)[permutation]
# Learning rate update
if learning_rate.shape[0]>1:
lr = learning_rate[epoch]
nb_minibatches = int(np.ceil(n_train/minibatch_size))
for num_minibatch in range(nb_minibatches):
# Minibatch indices
ind_minibatch = shuffled_ind_samples[num_minibatch*minibatch_size:(num_minibatch+1)*minibatch_size]
# Loading of the original image (X) and the blurred image (Y)
minibatch_X, minibatch_Y = load_dataset_blur(ind_minibatch,size_image, normalization, sigma)
_ , temp_cost, filter_learnt = sess.run([optimizer,cost,filter_to_learn],\
feed_dict = {X:minibatch_X, Y_blur_true:minibatch_Y, learning_rate_placeholder: lr})
Run Code Online (Sandbox Code Playgroud)
我对4900个样本的5个历元进行了训练,批大小等于5。高斯核的方差为7 ^ 2 = 49。我已经尝试使用tensorflow提供的xavier initiliazer方法以及我们实际上想学习的高斯内核的真实值来初始化要学习的过滤器。在这两种情况下,所获知的滤波器的结果都与真正的高斯滤波器截然不同,因为可以在https://github.com/megalinier/Helsinki-project上的两个图像上看到它。
通过检查照片,网络似乎学习正常,因为预测图像与真实标签相差不远 - 为了获得更好的结果,您可以调整一些超参数,但事实并非如此。
我认为您缺少的是这样一个事实:不同的内核可以得到非常相似的结果,因为它是一个卷积。想想看,您正在将某个矩阵与另一个矩阵相乘,然后将所有结果相加以创建一个新像素。现在,如果真实标签总和为 10,则可能是 2.5 + 2.5 + 2.5 + 2.5 和 -10 + 10 + 10 + 0 的结果。我想说的是,你的网络可以很好地学习,但是您将在转换内核中获得与过滤器不同的值。