Keras CNN для двоичного семанти c сегментация
Я использую для l oop, чтобы перебрать различные разделы обучения-проверки, и, похоже, он работает на первом проходе через l oop, но перерывы на второй проход. Когда model.fit () выполняется, я получаю ошибку значения
ValueError: Невозможно интерпретировать metri c идентификатор функции: 0.752065122127533
Я думаю, что это, вероятно, связано с пользовательскими метриками, которые я использую. не имеет значения, какой пользовательский метри c я пытаюсь, (dice_loss, F1), кажется, он сломается, если я просто не использую стандартную (точность) метри c, но из-за дисбаланса класса это не очень хороший показатель c для моя проблема.
Я пытался удалять модель после каждой итерации, но это тоже не решает.
Также странно, что она запускается без проблем в первый раз, выполняя все 5 сгибов, но все Последующая попытка не работает.
%tensorflow_version 2.x
import tensorflow as tf
from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, UpSampling2D, BatchNormalization
from tensorflow.keras.layers import Concatenate, Conv2DTranspose, Flatten, Activation, Add
from tensorflow.keras.models import Model
from tensorflow.keras.callbacks import ReduceLROnPlateau, EarlyStopping, ModelCheckpoint
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, Conv2DTranspose
from tensorflow.keras.constraints import max_norm
from tensorflow.keras import backend as K
from statistics import mean
import sklearn.metrics
from sklearn.model_selection import train_test_split, KFold
import numpy as np
import matplotlib.pyplot as plt
import os
from PIL import Image
import random
import cv2
from random import shuffle
from glob import glob
from imageio import imread, imwrite
import datetime
x = sorted(os.listdir(image_dir))
y = sorted(os.listdir(label_dir))
# create lists with full paths
X = []
Y = []
for image in x:
full_path = os.path.join(image_dir + os.sep + image)
X.append(full_path)
for label in y:
full_path = os.path.join(label_dir + os.sep + label)
Y.append(full_path)
# train- test split
train_images, TEST_images, train_labels, TEST_labels = train_test_split(X,Y,train_size = .8, random_state = 2)
train_images = np.array(train_images)
TEST_images = np.array(TEST_images)
train_labels = np.array(train_labels)
TEST_labels = np.array(TEST_labels)
ct = datetime.datetime.now() # current time
date = str(ct.month) +"_" + str(ct.day) + "_" +str(ct.year)
sz = (128,128)
batch_size = 5
epochs = 10
optimizer = 'adam'
model_name = 'unet'
filepath = model_name + '.h5'
run_name = date +"_" + model_name +"_" +optimizer
print(f"This is model run: {run_name}")
def image_generator(image_files, label_files ,batch_size, sz):
while True:
batch_index = np.random.choice(len(image_files), size = batch_size, replace = False)
batch_x = []
batch_y = []
for i in batch_index:
mask = Image.open(glob(label_files[i])[0])
mask = np.array(mask.resize(sz))
mask[mask == 0 ] = 0
mask[mask > 0] = 1
batch_y.append(mask)
#preprocess the raw images
raw = Image.open(image_files[i])
raw = raw.resize(sz)
raw = np.array(raw)
#check the number of channels because some of the images are RGBA or GRAY
if len(raw.shape) == 2:
raw = np.stack((raw,)*3, axis=-1)
else:
raw = raw[:,:,0:3]
#raw = ((raw - np.mean(raw))/np.std(raw))#.astype('uint8')
batch_x.append(raw/255.)
#preprocess a batch of images and masks
batch_x = np.array(batch_x)#/255.
batch_y = np.array(batch_y)
batch_y = np.expand_dims(batch_y,3)#/255.
yield (batch_x, batch_y)
test_generator = image_generator(TEST_images,TEST_labels,batch_size = batch_size,sz = sz)
# custom metric
smooth = 1.
def dice_coef(y_true, y_pred):
y_true_f = tf.reshape(tf.dtypes.cast(y_true, tf.float32), [-1])
y_pred_f = tf.reshape(tf.dtypes.cast(y_pred, tf.float32), [-1])
intersection = tf.reduce_sum(y_true_f * y_pred_f)
return (2. * intersection + smooth) / (tf.reduce_sum(y_true_f) + tf.reduce_sum(y_pred_f) + smooth)
def dice_coef_loss(y_true, y_pred):
return 1.0 - dice_coef(y_true, y_pred)
def build_callbacks(filepath):
checkpointer = ModelCheckpoint(filepath=filepath, verbose=2, save_best_only=True, save_weights_only=True)
callbacks = [checkpointer, PlotLearning()]
callbacks = [PlotLearning()]
return callbacks
# inheritance for training process plot
class PlotLearning(tf.keras.callbacks.Callback):
def on_train_begin(self, logs={}):
self.i = 0
self.x = []
self.losses = []
self.val_losses = []
self.acc = []
self.val_acc = []
#self.fig = plt.figure()
self.logs = []
def on_epoch_end(self, epoch, logs={}):
self.logs.append(logs)
self.x.append(self.i)
self.losses.append(logs.get('loss'))
self.val_losses.append(logs.get('val_loss'))
self.acc.append(logs.get('dice_coef'))
self.val_acc.append(logs.get('val_dice_coef'))
self.i += 1
print('i=',self.i,'loss=',logs.get('loss'),'val_loss=',logs.get('val_loss'),'dice_coef=',logs.get('dice_coef'),'val_dice_coef=',logs.get('val_dice_coef'))
#choose a random test image and preprocess
path = np.random.choice(VAL_images)
raw = Image.open(path) # open image
raw = np.array(raw.resize(sz[:2]))/255.
raw = raw[:,:,0:3]
#predict the mask
pred = model.predict(np.expand_dims(raw, 0))
#mask post-processing
msk = pred.squeeze()
msk = np.stack((msk,)*3, axis=-1)
msk = msk*25
msk[msk >= 0.5] = 1
msk[msk < 0.5] = 0
#show the mask and the segmented image
combined = np.concatenate([raw, msk, raw* msk], axis = 1)
plt.axis('off')
plt.imshow(combined)
plt.show()
def unet(sz):
inputs = Input(sz)
_ = inputs
f = 8
layers = []
for i in range(0, 6):
_ = Conv2D(f, 3, activation='relu', padding='same') (_) # c1
_ = Conv2D(f, 3, activation='relu', padding='same') (_) # c1
layers.append(_)
_ = MaxPooling2D() (_) # p1
f = f*2
ff2 = 64
j = len(layers) - 1
_ = Conv2D(f, 3, activation='relu', padding='same') (_) # c2
_ = Conv2D(f, 3, activation='relu', padding='same') (_) # c2
_ = Conv2DTranspose(ff2, 2, strides=(2, 2), padding='same') (_) # ?
_ = Concatenate(axis=3)([_, layers[j]]) # ?
j = j -1
for i in range(0, 5):
ff2 = ff2//2
f = f // 2
_ = Conv2D(f, 3, activation='relu', padding='same') (_) # u3
_ = Conv2D(f, 3, activation='relu', padding='same') (_) # u3
_ = Conv2DTranspose(ff2, 2, strides=(2, 2), padding='same') (_) # u3
_ = Concatenate(axis=3)([_, layers[j]]) # u3
j = j -1
_ = Conv2D(f, 3, activation='relu', padding='same') (_) #?
_ = Conv2D(f, 3, activation='relu', padding='same') (_) #?
outputs = Conv2D(1, 1, activation='sigmoid') (_) #?
model = Model(inputs=[inputs], outputs=[outputs])
return model
kf = KFold(5)
fold = 0
for train, val in kf.split(train_images):
fold+=1
nfilepath = '_'+str(fold)+'_' + filepath
print(f"Fold #{fold}")
run_name_fold = run_name + 'fold' + str(fold)
TRAIN_images = train_images[train]
TRAIN_labels = train_labels[train]
VAL_images = train_images[val]
VAL_labels = train_labels[val]
train_generator = image_generator(TRAIN_images,TRAIN_labels, batch_size=batch_size, sz = sz)
val_generator = image_generator(VAL_images,VAL_labels, batch_size=batch_size, sz = sz)
model = unet(sz=sz + (3,))
model.compile(optimizer = optimizer, loss = 'binary_crossentropy', metrics = [dice_coef ,'acc'])
train_steps = len(TRAIN_images) //batch_size # note // is floor division, and thus provides no remainder
val_steps = len(VAL_images) //batch_size
history = model.fit(train_generator, epochs = epochs, steps_per_epoch=train_steps,
validation_data=val_generator, validation_steps=val_steps,
callbacks= build_callbacks(filepath = nfilepath),
verbose = 2)
plot_name = 'Fig_' + run_name_fold + '.PNG'
print(plot_name)
#plot 1
plt.figure(figsize=(12,4))
plt.subplot(121)
plt.plot(history.history['dice_coef'])
plt.plot(history.history['acc'])
plt.title('training set')
plt.xlabel('epoch')
plt.legend(['dice loss','Accuracy'])
plt.subplot(122)
plt.plot(history.history['val_dice_coef'])
plt.plot(history.history['val_acc'])
plt.title('validation set')
plt.xlabel('epoch')
plt.legend(['dice loss','Accuracy'])
plt.savefig(plot_name)
test_steps = len(TEST_images) //batch_size
loss, dice_coef, acc = model.evaluate(test_generator, batch_size=batch_size, steps = test_steps, verbose = 2)
print(f"Model loss:{loss} - fold {fold}")
print(f"Dice-loss coefficent:{dice_coef} - fold {fold}")
print(f"Accuracy: {acc} - fold {fold}")
ValueError Traceback (последний последний вызов) в () 19 validation_data = val_generator, validation_steps = val_steps, 20 callbacks = build_callbacks (filepath = nfilepath), ---> 21 verbose = 2 ) 22 plot_name = 'Fig_' + run_name_fold + '.PNG' 23 print (plot_name)
10 кадров /usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/ func_graph.py в оболочке (* args, ** kwargs) 966 за исключением Исключения как e: # pylint: disable = broad-кроме 967, если hasattr (e, "ag_error_metadata"): -> 968 поднять e.ag_error_metadata.to_exception (e ) 969 остальное: 970 повышение
ValueError: в коде пользователя:
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:505 train_function *
outputs = self.distribute_strategy.run(
/usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:951 run **
return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:2290 call_for_each_replica
return self._call_for_each_replica(fn, args, kwargs)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/distribute/distribute_lib.py:2649 _call_for_each_replica
return fn(*args, **kwargs)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training.py:477 train_step **
self.compiled_metrics.update_state(y, y_pred, sample_weight)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/compile_utils.py:386 update_state
self._build(y_pred, y_true)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/compile_utils.py:317 _build
self._metrics, y_true, y_pred)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/nest.py:1118 map_structure_up_to
**kwargs)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/nest.py:1214 map_structure_with_tuple_paths_up_to
*flat_value_lists)]
/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/nest.py:1213 <listcomp>
results = [func(*args, **kwargs) for args in zip(flat_path_list,
/usr/local/lib/python3.6/dist-packages/tensorflow/python/util/nest.py:1116 <lambda>
lambda _, *values: func(*values), # Discards the path arg.
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/compile_utils.py:416 _get_metric_objects
return [self._get_metric_object(m, y_t, y_p) for m in metrics]
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/compile_utils.py:416 <listcomp>
return [self._get_metric_object(m, y_t, y_p) for m in metrics]
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/compile_utils.py:435 _get_metric_object
metric_obj = metrics_mod.get(metric)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/metrics.py:3364 get
raise ValueError(error_msg)
ValueError: Could not interpret metric function identifier: 0.7213095426559448