После оценки моделей классификации в последнем разделе мы решили попробовать использовать регрессию для диагностики сканов DR по шкале от 1 до 4. Первый шаг в достижении этого — убедиться, что наши изображения помечены числовыми значениями, а не одна горячая кодировка, которую мы использовали для классификации. Это можно легко сделать, изменив режим класса в Keras ImageDataGenerator.flow_from_directory на разреженный, как показано ниже.

(Если вы следовали этой серии, обязательно переместите подкаталог с нулевыми метками из каталога, переданного генератору, перед запуском кода ниже.)

data_all = ImageDataGenerator(rescale=1./255).flow_from_directory( 
        directory,
        class_mode='sparse', # changed from 'categorical'
        target_size=(224, 224), 
        batch_size = 3662, 
        seed = 123)
# sparse vs categorical comparison below (3 class example)
# Categorical:
# [[0, 1, 0]
#  [1, 0, 0]
#  [0, 0, 1]]
# Sparse equivalent:
#  [1, 0, 2]

Также необходимо убедиться, что разреженные метки совпадают с реальными метками. К счастью, текущие метки подходят для использования в регрессии. Если подкаталоги помечены как «0», «1» и т. д., то Keras должен упорядочить их, как и ожидалось, но чтобы убедиться, что это так, используйте приведенный ниже код.

data_all.class_indices
# returns {'1': 0, '2': 1, '3': 2, '4': 3}

Метки были смещены на 1, но поскольку все они сдвинуты на одинаковую величину и расположены в правильном порядке, проблем не должно возникнуть, если мы не забываем смещаться назад при последовательном объединении регрессора с моделью классификации.

Чтобы использовать Keras в регрессионной модели, мы будем использовать KerasRegressor. Если вы ищете более общую информацию об использовании Keras для регрессии, обязательно ознакомьтесь с этим руководством от machinelearningmastery.

from keras.wrappers.scikit_learn import KerasRegressor

Нам нужно написать функцию, которая создаст модель для использования KerasRegressor. Модель будет очень похожа на те, которые я построил в предыдущих сообщениях, но в последнем слое будет только один нейрон, и мы будем использовать функцию потерь mean_squared_error, чтобы использовать ее для регрессии.

def build_model():
    model = Sequential()
    model.add(layers.Conv2D(224, (3, 3),
              activation='relu',
              input_shape=(224,224,3)))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Conv2D(112, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Conv2D(56, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Flatten())
    model.add(layers.Dense(300, activation='relu'))
    model.add(layers.Dropout(0.3))
    model.add(layers.Dense(150, activation='relu'))
    model.add(Dense(1, kernel_initializer='normal'))

    model.compile(loss='mean_squared_error',
                  optimizer='adam',
                  metrics=['acc'])
    return model

Передать модель в KerasRegressor так же просто, как передать функцию в аргумент build_fn.

estimator = KerasRegressor(build_fn=build_model, epochs=50, batch_size=32, verbose=2)

И теперь мы все настроены для обучения и оценки, используя приведенный ниже код.

kfold = KFold(n_splits=5, random_state=123)
results = cross_val_score(estimator, X_train, y_train, cv=kfold)
print("Results: %.2f (%.2f) MSE" % (results.mean(), results.std()))

В следующем посте я покажу, как объединить созданные нами модели для получения классификации, соответствующей исходной постановке задачи.