Итак, я работал над моделью с супер-разрешением и добился приличных результатов.Однако у меня остались остатки сети в выходном изображении: я не мог передать все изображение в качестве входных данных по соображениям памяти, что означало, что мне нужно было нарезать изображение на несколько меньших частей (в моем случае 128x128
).
Края этих отбивных почему-то создают линии.Мой вопрос: в чем причина и как это предотвратить?
Моя первая мысль: у сверток на краю не так много информации, как у остальных, поскольку требуется заполнениедля фильтров, размер которых превышает 1x1
, поэтому обычно и неизбежно иметь такие строки без постобработки.Каким может быть хороший подход к постобработке?
Или, в конечном итоге, решение этой проблемы решит вопрос?
Еще одна идея, которая у меня возникла, - подавать перекрывающиеся области изображения в сеть изамените края одного выходного сигнала соответствующей некраевой частью выходного перекрытия.
Вот модель, которую я использую:
def setUpModel(x_train, y_train):
filters = 256
kernel_size = 3
strides = 1
scale_fact = 4
res_blocks = 3
img_depth = 3
# Head module
input = Input(shape=(None, None, img_depth)) # None = can take inputs of different sizes
conv0 = Conv2D(filters, kernel_size, strides=strides, padding='same')(input)
# Body module
res = Conv2D(filters, kernel_size, strides=strides, padding='same')(conv0)
act = ReLU()(res)
res = Conv2D(filters, kernel_size, strides=strides, padding='same')(act)
res_rec = Add()([conv0, res])
for i in range(res_blocks):
res1 = Conv2D(filters, kernel_size, strides=strides, padding='same')(res_rec)
act = ReLU()(res1)
res2 = Conv2D(filters, kernel_size, strides=strides, padding='same')(act)
res_rec = Add()([res_rec, res2])
conv = Conv2D(filters, kernel_size, strides=strides, padding='same')(res_rec)
add = Add()([conv0, conv])
# Tail module
conv = Conv2D(filters, kernel_size, strides=strides, padding='same')(add)
act = ReLU()(conv)
up = UpSampling2D(size=scale_fact if scale_fact != 4 else 2)(act) # TODO: try "Conv2DTranspose"
# When it's a 4X factor, we want the upscale split in two procedures
if(scale_fact == 4):
conv = Conv2D(filters, kernel_size, strides=strides, padding='same')(up)
act = ReLU()(conv)
up = UpSampling2D(size=2)(act) # TODO: try "Conv2DTranspose"
output = Conv2D(filters=3,
kernel_size=1,
strides=1,
padding='same')(up)
model = Model(inputs=input, outputs=output)
return model
Вот два примера:
РЕДАКТИРОВАТЬ : По запросу, вот код train
:
def train(model, x_train, y_train):
print("Training is starting.")
if load_model == False:
print("Compiling the model since it wasn't loaded from memory.")
optimizer = Adadelta(lr=1.0,
rho=0.95,
epsilon=None,
decay=0.0)
model.compile(optimizer=optimizer,
loss='mean_squared_error')
model.fit(x_train,
y_train,
epochs=6, # TODO: is it multi-fold testing?
verbose=verbosity,
shuffle=False,
validation_split=0.1,
batch_size=7,
callbacks=get_callbacks())
Раньше у меня был batch_size
1 и будет тренироваться на сэмплах 128x128
(чем больше, тем больше моя память), но это дало мне очень много времени на тренировки.В итоге я выбрал размер пакета 7 и размер входного тренинга 64x64
.
. Набор данных был настолько большим, что мне пришлось разбить его на несколько частей, потому что я не мог загрузить все это в память.отсюда и низкое значение эпох (я вручную изменил исходную папку ввода, прежде чем снова запустить сеанс обучения на сохраненной модели).
get_callbacks()
возвращает []
, потому что некоторые обратные вызовы, которые я хотел попробовать, вызывали памятьпроблемы и слишком большое замедление времени обучения (например, TensorBoad).
Вот репо , если вы когда-нибудь захотите увидеть больше кода для понимания.