ошибка при проверке ввода модели с использованием Functional API в Keras - PullRequest
1 голос
/ 04 ноября 2019

Я создал схему генератора данных, используя Keras, используя следующее руководство:

https://stanford.edu/~shervine/blog/keras-how-to-generate-data-on-the-fly

Мой скрипт генератора данных, кажется, правильно генерирует массивы с кучей данных. Однако, когда я делаю свою модель с использованием Functional API, я получаю следующую ошибку:

ValueError: Ошибка при проверке ввода модели: список массивов Numpy, которые вы передаете вашей модели, не соответствует размеру, который ожидала модель. Предполагается увидеть 2 массива (ов), но вместо этого получил следующий список из 1 массива:

И я, похоже, не понимаю эту ошибку. Моя модель принимает два разных входа. Он принимает матрицу (размером 7000 x 208) в качестве входных данных для слоя свертки и вектор (7000) в нейронной сети. И эти две ветви объединяются и передаются полностью связанному слою, за которым следует выходной слой. Вот как я настроил свою сеть:

ksize = 2
l2_lambda =  0.0001

i1 = Input(shape=(7000, 208))



c1 = Conv1D(128*2, kernel_size=ksize,activation='relu',kernel_regularizer=keras.regularizers.l2(l2_lambda))(i1)
c1 = Conv1D(128*2, kernel_size=ksize, activation='relu',kernel_regularizer=keras.regularizers.l2(l2_lambda))(c1)
c1 = AveragePooling1D(pool_size=ksize)(c1)
c1 = Dropout(0.2)(c1)
c1 = Flatten()(c1)

i2 = Input(shape=(7000, ))
c2 = Dense(64,  activation='relu',kernel_regularizer=keras.regularizers.l2(l2_lambda))(i2)
c2 = Dropout(0.1)(c2)

c = concatenate([c1, c2])

x = Dense(256, activation='relu', kernel_initializer='normal',kernel_regularizer=keras.regularizers.l2(l2_lambda))(c)
x = Dropout(0.25)(x)
output = Dense(5, activation='softmax')(x)

model = Model([i1, i2], [output])

model.summary()

model.compile(loss=keras.losses.categorical_crossentropy,
                  optimizer=keras.optimizers.Adam(),
                  metrics=['accuracy'])

model.fit_generator(generator=training_generator,validation_data=validation_generator)

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


class DataGenerator(keras.utils.Sequence):
    def __init__(self,list_IDs_snp,list_IDs_pos,labels,batch_size=32,n_channels=1,
                 n_classes=5,shuffle=True):
        self.batch_size = batch_size
        self.list_IDs_snp = list_IDs_snp
        self.list_IDs_pos = list_IDs_pos
        self.n_channels = n_channels
        self.n_classes = n_classes
        self.shuffle = shuffle
        self.labels = labels
        self.on_epoch_end()

    def __len__(self):
        'Denotes the number of batches per epoch'
        return int(np.floor(len(self.list_IDs_snp) / self.batch_size))

    def __getitem__(self, index):
        'Generate one batch of data'
        # Generate indexes of the batch
        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]

        # Find list of IDs
        list_IDs_temp_snp = [self.list_IDs_snp[k] for k in indexes]
        list_IDs_temp_pos = [self.list_IDs_pos[k] for k in indexes]

        # Generate data
        snp,pos,y = self.__data_generation(list_IDs_temp_snp,list_IDs_temp_pos)

        return snp,pos,y

    def on_epoch_end(self):
        self.indexes = np.arange(len(self.list_IDs_snp))
        if self.shuffle==True:
            np.random.shuffle(self.indexes)

    def __data_generation(self,list_IDs_temp_snp,list_IDs_temp_pos):
        snp = np.empty((self.batch_size,7000,208))
        pos = np.empty((self.batch_size,7000))
        y = np.empty((self.batch_size),dtype=int)

        for ID in range(len(list_IDs_temp_snp)):
            snp[ID] = np.load(list_IDs_temp_snp[ID])
            pos[ID] = np.load(list_IDs_temp_pos[ID])
            y[ID] = self.labels[list_IDs_temp_snp[ID]]
        return snp,pos,y

Эта схема генерации данных аналогична ссылке, которой я поделился в начале.

Для генерации данных я вызываю свой скрипт следующим образом:

params = {'batch_size': 3,
          'n_classes': 5,
          'n_channels': 1,
          'shuffle': True}

training_generator = DataGenerator(partition_snp['train'], partition_pos['train'],labels, **params)
validation_generator = DataGenerator(partition_snp['valid'],partition_pos['valid'], labels, **params)

Как вы думаете, проблема может быть в том, что я отправляю partition_snp и partition_pos отдельно? Partition_snp и partition_pos - это просто словари с путем к каждому из примеров. В каждом словаре есть два ключа: «train» и «valid».

Я буду очень признателен, если кто-нибудь сможет объяснить, почему я получаю ошибку, о которой упоминал выше. И во время выполнения кода я напечатал тип моей матрицы и вектора, и там написано NumPy массив. Поэтому я не знаю, почему я получаю эту ошибку. Мы будем благодарны за понимание.

1 Ответ

1 голос
/ 04 ноября 2019

Проблема в вашем методе __getitem__, вы возвращаете кортеж из трех элементов, в то время как это должен быть список входов и список выходов, как кортеж, например:

def __getitem__(self, index):
    'Generate one batch of data'
    # Generate indexes of the batch
    indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]

    # Find list of IDs
    list_IDs_temp_snp = [self.list_IDs_snp[k] for k in indexes]
    list_IDs_temp_pos = [self.list_IDs_pos[k] for k in indexes]

    # Generate data
    snp,pos,y = self.__data_generation(list_IDs_temp_snp,list_IDs_temp_pos)

    return [snp, pos], y

Поскольку у вас есть только один выход, список не нужен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...