Использование собственного DataGenerator для предварительно обученных моделей и применение fit_generator к Keras Functional API - PullRequest
0 голосов
/ 14 июля 2020

У меня проблема с классификацией изображений, и я хочу использовать предварительно обученную модель EfficicentNetB0 (приложения keras: https://keras.io/api/applications/efficientnet/#efficientnetb0 -функция и бумага: https://arxiv.org/abs/1905.11946) с веса от ImageNet для этой задачи классификации.

Я загрузил и импортировал модель и ее веса следующим образом:

!pip install git+https://github.com/qubvel/segmentation_models
import efficientnet.keras as efn
efnB0_model = efn.EfficientNetB0(include_top=False, weights="imagenet", input_shape=(224, 224, 3))
efnB0_model.trainable = False

Я не буду включать верхнюю часть этой модели, потому что она не соответствует проблеме, которую я анализирую, поэтому я установил include_top на False. Более того, я не хочу обучать параметры Efficien tNet, поэтому efnB0_model.trainable = False.

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

Следовательно, Я создал DataGenerator_X.

class DataGenerator_X(Sequence):

    def __init__(self, x_set, batch_size):
        self.x = x_set
        self.batch_size = batch_size

    def __len__(self):
        return math.ceil(len(self.x) / self.batch_size)

    def __getitem__(self, idx):
        batch_x = self.x[idx*self.batch_size : (idx + 1)*self.batch_size]
        batch_x = [imread(file_name) for file_name in batch_x]
        batch_x = np.array(batch_x)
        batch_x = batch_x * 1./255
        

        return batch_x

Этот DataGenerator_X создает пакеты и делит их на 255 (что предпочитает Efficicen tNet).

После этого я применяю это * От 1030 * до X_train (путь к файлу к моим изображениям).

training_generator = DataGenerator_X(X_train, batch_size=32)

Первый вопрос: нужно ли мне применять этот генератор и для проверочных данных X_val?

И затем я предсказываю значения X_train после запуска на них нижней части модели Efficien tNet -B0 (X_after_efn), чтобы не делать это каждую эпоху снова, потому что нижняя часть все слои модели заморожены. Я делаю это с помощью этого кода:

X_after_efn = efnB0_model.predict(training_generator, verbose=1)

А затем я создал верх модели, используя этот код:

def top_of_model(input_shape = (7, 7, 1280)):
    input_img = Input(shape=input_shape)
    backbone = Flatten(input_shape(7, 7, 1280)) (input_img)

    branches = []
    for i in range(8):
            branches.append(backbone)
            branches[i] = Dense(16000, activation = "relu", name="branch_"+str(i)+"_Dense_16000")(branches[i])
            branches[i] = Dense(128, activation = "relu", name="branch_"+str(i)+"_Dense_128")(branches[i])
            branches[i] = Dense(36, activation = "softmax", name="branch_"+str(i)+"_output")(branches[i])
        
    output = Concatenate(axis=1)(branches)
    output = Reshape((8, 36))(output)
    model = Model(input_img, output)

    return model

До этого момента, я думаю, все, что я закодировал, будет работай. Теперь пришло время, о котором я немного споткнулся.

Второй вопрос: поскольку мне приходится загружать данные из-за их размера партиями, могу ли я теперь взять следующий DataGenerator_X&Y, чтобы получить данные для top_of_model?

class DataGenerator_X&Y(Sequence):

    def __init__(self, x_set, y_set, batch_size):
        self.x, self.y = x_set, y_set
        self.batch_size = batch_size

    def __len__(self):
        return math.ceil(len(self.x) / self.batch_size)

    def __getitem__(self, idx):
        batch_x = self.x[idx*self.batch_size : (idx + 1)*self.batch_size]
        batch_x = [imread(file_name) for file_name in batch_x]
        batch_x = np.array(batch_x)
        batch_x = batch_x * 1./255
        batch_y = self.y[idx*self.batch_size : (idx + 1)*self.batch_size]
        batch_y = np.array(batch_y)

        return batch_x, batch_y

На мой взгляд, этот Генератор не случайным образом сопоставляет X и Y.

Третий вопрос: это означает, что я могу применить его таким образом, не мог бы я?

training_generator = DataGenerator(X_after_efn, y_train, batch_size=32)
validation_generator = DataGenerator(X_val, y_val, batch_size=32)

Четвертый вопрос: как я могу теперь применить функцию top_of_model к training_generator и validation_generator после этого?

Я хотел бы использовать model.fit_generator и сделать что-то вроде этого:

model.fit_generator(generator=training_generator,
                    validation_data=validation_generator,
                    steps_per_epoch = num_train_samples // 32,
                    validation_steps = num_val_samples // 32,
                    epochs = 10, workers=6, use_multiprocessing=True)
...