Я читал учебник «Практическое машинное обучение» (2-е издание) Аурелиана Жерона ( веб-страница издателя учебника здесь ). Я попал в контент, который применяет CNN к изображениям. В разделе под названием Реализация Tensorflow главы 14 они вручную создают фильтры, которые передаются в tf.nn.conv2d
и применяются к изображению для создания набора карт объектов. После этих примеров ручного фильтра в книге говорится:
в реальном CNN вы обычно определяете фильтры как обучаемые переменные ... Вместо того, чтобы создавать переменные вручную, используйте слой keras.layers.Conv2D
.
Приведенная выше цитата подразумевает для меня, что при одинаковых входных данных (и эквивалентных инициализациях) мы должны иметь возможность получать идентичные выходные данные из tf.nn.conv2d
и keras.layers.Conv2D
. Чтобы проверить эту идею, я посмотрел, были ли две функции эквивалентны. В соответствии с , на который ранее отвечал SO сообщение , для свертки, две функции одинаковы .
Я намеревался выполнить простой тест на их эквивалентность. Я создал сверточный слой, состоящий из одной карты объектов, используя фильтр 7x7 (он же: сверточное ядро ) всех нулей , который был реализован отдельно для tf.nn.conv2d
и keras.layers.Conv2D
. Как и ожидалось, после суммирования всех значений пикселей в разности обоих изображений этот фильтр заставил выходные изображения иметь нулевое значение для каждого значения пикселя. Эта нулевая разница означает, что выходные изображения идентичны.
Затем я решил создать тот же фильтр 7x7, но со всеми на этот раз. В идеале обе функции должны давать одинаковый вывод, поэтому разница в двух выходных изображениях должна быть равна нулю. К сожалению, когда я проверяю разницу в выходных изображениях (и суммирую различия в каждом пикселе), я получаю ненулевое значение суммы. При построении изображений и их различий становится очевидным, что они не являются одним и тем же изображением (хотя они выглядят очень похожими с первого взгляда).
После прочтения документации для обеих функций Я считаю, что я даю им эквивалентные материалы. Что я мог сделать / предположить неправильно, что мешает обеим функциям производить идентичные выходные данные?
Я приложил свой код и информацию о версиях ниже для справки. В коде в качестве входных данных используется образец изображения china.jpg
scikit-learn и matplotlib.pyplot.imshow
для визуализации выходных изображений и их различий.
TF Версия: 2.2.0-dev20200229
Версия Keras: 2.3.1
Версия Scikit-Learn: 0.22.1
Matplotlib Версия: 3.1.3
Numpy Версия: 1.18.1
from sklearn.datasets import load_sample_image
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow import keras
import numpy as np
# Get the feature map as a result of tf.nn.conv2d
def featureMap1(batch):
# Extract the channels
batch_size, height, width, channels = batch.shape
# Make a (7,7,3,1) filter set (one set of a 7x7 filter per channel)
# of just ones.
filters = np.ones(shape=(7, 7, channels, 1), dtype=np.float32)
# Run the conv2d with stride of 1 (i.e: in.shape = out.shape)
# Generate one feature map for this conv layer
fmaps = tf.nn.conv2d(batch, filters,
strides=1, padding='SAME',
data_format='NHWC')
# Return the feature map
return fmaps
# Get the feature map as a result of keras.layers.Conv2D
def featureMap2(batch):
# Create the input layer with the shape of the images
inputLayer = keras.layers.Input(shape=batch.shape[1:])
# Create the convLayer which should apply the filter of all ones
convLayer = keras.layers.Conv2D(filters=1, kernel_size=7,
strides=1, padding='SAME',
kernel_initializer='ones',
data_format='channels_last',
activation='linear')
# Create the ouput layer
outputLayer = convLayer(inputLayer)
# Set up the model
model = keras.Model(inputs=inputLayer,
outputs=outputLayer)
# Perform a prediction, no model fitting or compiling
fmaps = model.predict(batch)
return fmaps
def main():
# Get the image and scale the RGB values to [0, 1]
china = load_sample_image('china.jpg') / 255
# Build a batch of just one image
batch = np.array([china])
# Get the feature maps and extract
# the images within them
img1 = featureMap1(batch)[0, :, :, 0]
img2 = featureMap2(batch)[0, :, :, 0]
# Calculate the difference in the images
# Ideally, this should be all zeros...
diffImage = np.abs(img1 - img2)
# Add up all the pixels in the diffImage,
# we expect a value of 0 if the images are
# identical
print('Differences value: ', diffImage.sum())
# Plot the images as a set of 4
figsize = 10
f, axarr = plt.subplots(2, 2, figsize=(figsize,figsize))
axarr[0,0].set_title('Original Image')
axarr[0,0].imshow(batch[0], cmap='gray')
axarr[1,0].set_title('Conv2D through tf.nn.conv2d')
axarr[1,0].imshow(img1, cmap='gray')
axarr[1,1].set_title('Conv2D through keras.layers.Conv2D')
axarr[1,1].imshow(img2, cmap='gray')
axarr[0,1].set_title('Diff')
axarr[0,1].imshow(diffImage, cmap='gray')
plt.show()
return
main()