繁体   English   中英

训练多输出Keras模型

[英]training a multi-output keras model

我有10,000张图片,每张图片都标有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_generatorvalidation_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)

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

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

yield(x_batch, ys)

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

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

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

您可以测试初始化​​发电机的发电机输出尺寸,并调用函数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))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM