训练多输出Keras模型 [英] training a multi-output keras model

查看:143
本文介绍了训练多输出Keras模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有10,000张图片,每张图片都贴有20个标签.对于每个图像,标签为true或false.我正在尝试训练一种多输出模型,以便通过一个网络执行所有这20种二进制分类.

I have 10,000 images, each of which are labeled with 20 tags. For each image, the tag is either true or false. I'm trying to train a multi-output model to perform all these 20 binary classifications with one network.

该网络是残留网络.在扁平化层之后,网络分支为20个分支.每个分支具有2个完全连接的层,每个层之后是一个退出层.最后是一个只有一个节点并最终被乙状结肠激活的致密层.

The network is a Residual Network. After the flatten layer, the network branches out into 20 branches. Each branch has 2 fully connected layers, each of which are followed by a drop out layer. And finally a dense layer with one node and sigmoid activation in the end.

每个图像的标签和图像名称都存储在文本文件中,用于训练集和验证集.像这样: 1.jpg 1 -1 1 -1 -1 1 -1 .........

The labels for each image and the image name are stored in a text file, for both train and validation set. Like this: 1.jpg 1 -1 1 -1 -1 1 -1.........

我编写了自己的生成器,但无法使它们工作.我不断收到此错误:

I wrote my own generator, but I can't get them to work. I keep getting this error:

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_generatorvalidation_generator生成大小为32的批次,将其输入模型.

Function explanations: get_input function reads an image and resizes it. get_output prepares the labels for each image. The labels are stored in a list and returned in the end. preprocess_input performs preprocessing and converting images into arrays. train_generator and validation_generator generate batches with size 32 to be fed to the model.

这是我的代码:

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)

一个简单的问题.此循环与答案中的循环有什么区别?

One quick question. What's the difference between this loop and the one in your answer:

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

yield(x_batch, ys)

推荐答案

如果模型有20个输出,则必须提供20个数组的列表作为目标.一种方法是修改生成器(用于训练和验证):

If your model has 20 outputs then you must provide a list of 20 arrays as target. One way of doing this is to modify the generator (for both training and validation):

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

yield(x_batch, ys)

作为旁注,您提到每个样本有20个标签,然后为什么在输入形状中指定40个标签?

As a side note, you mentioned that you have 20 tags per sample then why have you specified 40 in the input shape?

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

此外,我不知道您正在处理的特定问题,但是或者,您只能有一个20号输出,而不是20个1号输出.

Further, I don't know about the specific problem you are working on but alternatively you could only have one output of size 20 instead of 20 outputs with size one.

这篇关于训练多输出Keras模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆