обучение модели с несколькими выходами keras - PullRequest
0 голосов
/ 07 октября 2018

У меня есть 10000 изображений, каждое из которых помечено 20 тегами.Для каждого изображения тег имеет значение true или false.Я пытаюсь обучить модель с несколькими выходами для выполнения всех этих 20 двоичных классификаций в одной сети.

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

Метки для каждого изображения и имени изображения хранятся в текстовом файле, как для поезда, так и для набора проверки.Например: 1.jpg 1 -1 1 -1 -1 1 -1 .........

Я написал собственный генератор, но не могу заставить их работать.Я получаю эту ошибку:

Error when checking model target: the list of Numpy arrays that you are passing to your model is not the size the model expected. Expected to see 20 array(s), but instead got the following list of 1 arrays.

Объяснения функций: get_input функция читает изображение и изменяет его размер.get_output подготавливает ярлыки для каждого изображения.Метки хранятся в списке и возвращаются в конце.preprocess_input выполняет предварительную обработку и преобразование изображений в массивы.train_generator и validation_generator генерируют пакеты размером 32 для подачи на модель.

Вот мой код:

def get_input(img_name):
    path = os.path.join("images", img_name)
    img = image.load_img(path, target_size=(224, 224))

    return img


def get_output(img_name, file_path):
    data = pd.read_csv(file_path, delim_whitespace=True, header=None)

    img_id = img_name.split(".")[0]
    img_id = img_id.lstrip("0")
    img_id = int(img_id)

    labels = data.loc[img_id - 1].values
    labels = labels[1:]

    labels = list(labels)
    label_arrays = []
    for i in range(20):
        val = np.zeros((1))
        val[0] = labels[i]
        label_arrays.append(val)

    return label_arrays


def preprocess_input(img_name):
    img = get_input(img_name)
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)    
    return x

def train_generator(batch_size):
    file_path = "train.txt"
    data = pd.read_csv(file_path, delim_whitespace=True, header=None)

    while True:
        for i in range(math.floor(8000/batch_size)):
            x_batch = np.zeros(shape=(32, 224, 224, 3))
            y_batch = np.zeros(shape=(32, 20))
            for j in range(batch_size):
                img_name = data.loc[i * batch_size + j].values
                img_name = img_name[0]
                x = preprocess_input(img_name)
                y = get_output(img_name, file_path)
                x_batch[j, :, :, :] = x
                y_batch[j] = y
            yield(x_batch, y_batch)

def val_generator(batch_size):
    file_path = "val.txt"
    data = pd.read_csv(file_path, delim_whitespace=True, header=None)

    while True:
        for i in range(math.floor(2000/batch_size)):
            x_batch = np.zeros(shape=(32, 224, 224, 3))
            y_batch = np.zeros(shape=(32, 20))
            for j in range(batch_size):
                img_name = data.loc[i * batch_size + j].values
                img_name = img_name[0]
                x = preprocess_input(img_name)
                y = get_output(img_name, file_path)
                x_batch[j, :, :, :] = x
                y_batch[j] = y
            yield(x_batch, y_batch)

Редактировать: Один быстрый вопрос.В чем разница между этой петлей и той, что в вашем ответе:

ys = []
for i in range(batch_size):
    ys.append(y_batch[i, :])

yield(x_batch, ys)

Ответы [ 2 ]

0 голосов
/ 07 октября 2018

Если ваша модель имеет 20 выходов, вы должны предоставить список из 20 массивов в качестве цели.Один из способов сделать это - изменить генератор (как для обучения, так и для проверки):

ys = []
for i in range(20):
    ys.append(y_batch[:,i])

yield(x_batch, ys)

В качестве примечания вы упомянули, что у вас есть 20 тегов на выборку, тогда почему вы указали 40 во входных данныхshape?

y_batch = np.zeros(shape=(32, 40))

Кроме того, я не знаю о конкретной проблеме, над которой вы работаете, но в качестве альтернативы вы могли бы иметь только один выход размера 20 вместо 20 выходов с размером один.

0 голосов
/ 07 октября 2018

Вы можете проверить выходные размеры генератора, инициализируя генератор, и вызвать функцию next (), чтобы проверить размеры.Например, с train_generator:

train_gen = train_generator(batch_size)
x_batch, y_batch = next(train_gen)

Затем проверьте размеры x_batch и y_batch и тип данных

Я бы сделал генератор следующим образом:

def train_generator(batch_size):
    file_path = "train.txt"
    data = pd.read_csv(file_path, delim_whitespace=True, header=None)
    # Initialize empty list
    x_batch = []
    y_batch = []

    while True:
        for i in range(math.floor(8000/batch_size)):
            for j in range(batch_size):
                img_name = data.loc[i * batch_size + j].values
                img_name = img_name[0]
                x = preprocess_input(img_name)
                y = get_output(img_name, file_path)
                x_batch.append(x)
                y_batch.append(y)

            yield(np.array(x_batch), np.array(y_batch))
...