Первоначально я делал описанные здесь изменения, которые я буду здесь Keras UNET реализация прогнозирует очень плохие
После того, как я внес изменения (убрал деление на 255 для слоя Lambda), я увидел значительное улучшение Модель прогнозов (Изменение 1). Итак, рабочая версия кода выглядела так:
Обучение
import tensorflow as tf
import os
import random
import numpy as np
from tqdm import tqdm
import cv2
from keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau
from skimage.io import imread, imshow
from skimage.transform import resize
import matplotlib.pyplot as plt
os.environ['KERAS_BACKEND'] = 'tensorflow'
seed = 42
np.random.seed = seed
IMAGE_HEIGHT = 256
IMAGE_WIDTH = 256
IMAGE_CHANELS = 1
trainImageFolderPath = os.path.join(os.path.dirname(__file__), 'Bright Dunes Groups')
train_ids = next(os.walk(trainImageFolderPath))[1]
X_train = np.zeros((len(train_ids), IMAGE_HEIGHT, IMAGE_WIDTH, IMAGE_CHANELS), dtype=np.uint8)
Y_train = np.zeros((len(train_ids), IMAGE_HEIGHT, IMAGE_WIDTH, 1), dtype=np.bool)
print('Building training set...')
for n, id_ in tqdm(enumerate(train_ids), total=len(train_ids)):
path = os.path.join(trainImageFolderPath, id_)
imagePath = os.path.join(path, id_ + '.jpg')
img = imread(imagePath)
img = resize(img, (IMAGE_HEIGHT, IMAGE_WIDTH), mode='constant', preserve_range=True)
img = np.expand_dims(img, axis=-1)
X_train[n] = img
mask = np.zeros((IMAGE_HEIGHT, IMAGE_WIDTH, 1), dtype=np.bool)
for mask_file in next(os.walk(os.path.join(path, 'masks')))[2]:
maskPath = os.path.join(path, 'masks', mask_file)
mask_ = imread(maskPath)
mask_ = resize(mask_, (IMAGE_HEIGHT, IMAGE_WIDTH), mode='constant', preserve_range=True)
mask_ = np.expand_dims(mask_, axis=-1)
mask = np.maximum(mask, mask_)
Y_train[n] = mask
inputs = tf.keras.layers.Input((IMAGE_HEIGHT, IMAGE_WIDTH, IMAGE_CHANELS))
s = tf.keras.layers.Lambda(lambda x: x)(inputs)
c1 = tf.keras.layers.Conv2D(16, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(s)
c1 = tf.keras.layers.Dropout(0.1)(c1)
c1 = tf.keras.layers.Conv2D(16, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(c1)
p1 = tf.keras.layers.MaxPooling2D((2,2))(c1)
c2 = tf.keras.layers.Conv2D(32, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(p1)
c2 = tf.keras.layers.Dropout(0.1)(c2)
c2 = tf.keras.layers.Conv2D(32, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(c2)
p2 = tf.keras.layers.MaxPooling2D((2,2))(c2)
c3 = tf.keras.layers.Conv2D(64, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(p2)
c3 = tf.keras.layers.Dropout(0.2)(c3)
c3 = tf.keras.layers.Conv2D(64, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(c3)
p3 = tf.keras.layers.MaxPooling2D((2,2))(c3)
c4 = tf.keras.layers.Conv2D(128, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(p3)
c4 = tf.keras.layers.Dropout(0.2)(c4)
c4 = tf.keras.layers.Conv2D(128, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(c4)
p4 = tf.keras.layers.MaxPooling2D((2,2))(c4)
c5 = tf.keras.layers.Conv2D(256, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(p4)
c5 = tf.keras.layers.Dropout(0.3)(c5)
c5 = tf.keras.layers.Conv2D(256, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(c5)
u6 = tf.keras.layers.Conv2DTranspose(128, (2,2), strides=(2,2), padding='same')(c5)
u6 = tf.keras.layers.concatenate([u6, c4])
c6 = tf.keras.layers.Conv2D(128, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(u6)
c6 = tf.keras.layers.Dropout(0.2)(c6)
c6 = tf.keras.layers.Conv2D(128, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(c6)
u7 = tf.keras.layers.Conv2DTranspose(64, (2,2), strides=(2,2), padding='same')(c6)
u7 = tf.keras.layers.concatenate([u7, c3])
c7 = tf.keras.layers.Conv2D(64, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(u7)
c7 = tf.keras.layers.Dropout(0.2)(c7)
c7 = tf.keras.layers.Conv2D(64, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(c7)
u8 = tf.keras.layers.Conv2DTranspose(32, (2,2), strides=(2,2), padding='same')(c7)
u8 = tf.keras.layers.concatenate([u8, c2])
c8 = tf.keras.layers.Conv2D(32, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(u8)
c8 = tf.keras.layers.Dropout(0.1)(c8)
c8 = tf.keras.layers.Conv2D(32, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(c8)
u9 = tf.keras.layers.Conv2DTranspose(16, (2,2), strides=(2,2), padding='same')(c8)
u9 = tf.keras.layers.concatenate([u9, c1], axis=3)
c9 = tf.keras.layers.Conv2D(16, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(u9)
c9 = tf.keras.layers.Dropout(0.1)(c9)
c9 = tf.keras.layers.Conv2D(16, (3,3), activation='relu', kernel_initializer='he_normal', padding='same')(c9)
outputs = tf.keras.layers.Conv2D(1, (1,1), activation='sigmoid')(c9)
model = tf.keras.Model(inputs=[inputs], outputs=[outputs])
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
model.summary()
######################################################################################################
callbacks = [
EarlyStopping(patience=5, verbose=1),
ReduceLROnPlateau(factor=0.2, patience=3, min_lr=0.001, verbose=1),
ModelCheckpoint('bright_Dunes_Groups_model.h5', verbose=1, save_best_only=True)
]
######################################################################################################
results = model.fit(X_train,
Y_train,
validation_split=0.25,
batch_size=16,
epochs=80,
callbacks = callbacks)
idx = random.randint(0, len(X_train))
predictions_train = model.predict(X_train[:int(X_train.shape[0]*0.9)], verbose=1)
predictions_value = model.predict(X_train[int(X_train.shape[0]*0.9):], verbose=1)
predictions_train_t = (predictions_train > 0.5).astype(np.uint8)
predictions_value_t = (predictions_value > 0.5).astype(np.uint8)
###### random training sample
ix = random.randint(0, len(predictions_train_t))
###################################################################
imshow(X_train[ix])
###################################################################
plt.show()
imshow(np.squeeze(Y_train[ix]))
plt.show()
imshow(np.squeeze(predictions_train_t[ix]))
plt.show()
###### random validation sample
ix = random.randint(0, len(predictions_value_t))
imshow(X_train[int(X_train.shape[0]*0.9):][ix])
plt.show()
imshow(np.squeeze(Y_train[int(Y_train.shape[0]*0.9):][ix]))
plt.show()
imshow(np.squeeze(predictions_value_t[ix]))
plt.show()
Тестирование
import tensorflow as tf
import os
import random
import numpy as np
from tqdm import tqdm
import cv2
from skimage.io import imread, imshow
from skimage.transform import resize
import matplotlib.pyplot as plt
os.environ['KERAS_BACKEND'] = 'tensorflow'
IMAGE_HEIGHT = 256
IMAGE_WIDTH = 256
IMAGE_CHANELS = 1
modelFilePath = 'bright_Dunes_Groups_model.h5'
model = tf.keras.models.load_model(modelFilePath)
testImageFolderPath = os.path.join(os.path.dirname(__file__), 'TestDunes')
test_ids = next(os.walk(testImageFolderPath))[2]
for n, id_ in tqdm(enumerate(test_ids), total=len(test_ids)):
imagePath = os.path.join(testImageFolderPath, id_)
img = imread(imagePath)
img = resize(img, (IMAGE_HEIGHT, IMAGE_WIDTH), mode='constant', preserve_range=True)
imshow(img)
plt.show()
img = np.expand_dims(img, axis=0)
img = np.expand_dims(img, axis=-1)
predictions = model.predict(img, verbose=1)
predictions_value_t = (predictions > 0.6).astype(np.uint8)
imshow(np.squeeze(predictions_value_t))
plt.show()
Все было хорошо.
Тогда я решил изменить размеры изображения кода для изменения размера с 256 * 256 до 512 * 512 (изменение 2).
Итак, я изменил как в обучении, так и в тестировании
IMAGE_HEIGHT = 256
IMAGE_WIDTH = 256
на
IMAGE_HEIGHT = 512
IMAGE_WIDTH = 512
Я попробовал это и увидел, что предсказания стали хуже, поэтому я вернулся к своему изменились размеры до 256 и добавлено около 50 новых изображений в X_train и соответствующие маски для расширения набора обучающих данных.
Затем я попытался снова начать тренировку. И к моему удивлению это снова не работает (предсказания снова плохи). Код точно такой же, как и тогда, когда все было хорошо, но я не вижу ожидаемых результатов. Кто-нибудь может объяснить, что может go не так с этой реализацией Keras UNET? Я уверен, что это не может быть добавлено 50 новых изображений и масок. Они выглядят точно так же, как и другие изображения. Я уверен, что это неправильные предопределения не могут быть, потому что я сначала внес изменения, а затем отменил их обратно, потому что после кода возврата точно такой же, как это было, когда предсказания были в порядке.