简体   繁体   English

在 keras ImageDataGenerator.flow() 中使用多输出标签并使用 model.fit_generator()

[英]Using multi-output labels in keras ImageDataGenerator.flow() and using model.fit_generator()

I have a single-input,multi-output Neural Network model whose last layers are我有一个单输入、多输出的神经网络模型,它的最后一层是

out1 = Dense(168, activation = 'softmax')(dense)
out2 = Dense(11, activation = 'softmax')(dense)
out3 = Dense(7, activation = 'softmax')(dense)

model = Model(inputs=inputs, outputs=[out1,out2,out3])

the Y-labels for each image are as follows每个图像的 Y 标签如下

train
>>

              image_id    class_1   class_2  class_3    

0              Train_0         15         9        5    
1              Train_1        159         0        0
...
...
...
453651    Train_453651          0        15       34
453652    Train_453652         18         0        7

EDIT:-编辑:-

train.iloc[:,1:4].nunique()
>>
class_1        168
class_2         11
class_3          7
dtype: int64

So looking at these different range of classes, should I use categorical_crossentropy or sparse_categorical_crossentropy ?所以看看这些不同范围的类,我应该使用categorical_crossentropy还是sparse_categorical_crossentropy and how should I use the Y_labels in flow for the code given below?我应该如何在下面给出的代码中使用流中的Y_labels

imgs_arr = df.iloc[:,1:].values.reshape(df.shape[0],137,236,1)
# 32332 columns representing pixels of 137*236 and single channel images.
# converting it to (samples,w,h,c) format

Y = train.iloc[:,1:].values #need help from here

image_data_gen = ImageDataGenerator(validation_split=0.25)
train_gen = image_data_gen.flow(x=imgs_arr, y=Y, batch_size=32,subset='training')
valid_gen = image_data_gen.flow(x=imgs_arr,y=Y,subset='validation')

is this this the right way to pass Y or use Y=[y1,y2,y3] where这是传递Y或使用Y=[y1,y2,y3]的正确方法Y=[y1,y2,y3]

y1=train.iloc[:,1].values
y2=train.iloc[:,2].values
y3=train.iloc[:,3].values

Ouch....哎哟....

By the message given in your flow , you will need a single output.根据flow给出的消息,您将需要一个输出。 So you need to make the separation inside your model.因此,您需要在模型内部进行分离。 (Keras failed to follow its own standards there) (Keras 在那里没有遵循自己的标准)

This means something like:这意味着:

Y = train.iloc[:,1:].values #shape = (50210, 3)

With a single output like:使用单个输出,如:

out = Dense(168+11+7, activation='linear')(dense)

And a loss function that handles the separation:以及处理分离的损失函数:

def custom_loss(y_true, y_pred):
    true1 = y_true[:,0:1]
    true2 = y_true[:,1:2]
    true3 = y_true[:,2:3]

    out1 = y_pred[:,0:168]
    out2 = y_pred[:,168:168+11]
    out3 = y_pred[:,168+11:]

    out1 = K.softmax(out1, axis=-1)
    out2 = K.softmax(out2, axis=-1)
    out3 = K.softmax(out3, axis=-1)

    loss1 = K.sparse_categorical_crossentropy(true1, out1, from_logits=False, axis=-1)
    loss2 = K.sparse_categorical_crossentropy(true2, out2, from_logits=False, axis=-1)
    loss3 = K.sparse_categorical_crossentropy(true3, out3, from_logits=False, axis=-1)

    return loss1+loss2+loss3

Compile the model with loss=custom_loss .使用loss=custom_loss编译模型。

Then the flow should stop complaining when you do flow .那么当你flow时, flow应该停止抱怨。

Just make sure X and Y are exactly in the same order: imgs_arr[i] corresponds to Y[i] correctly.只需确保 X 和 Y 的顺序完全相同: imgs_arr[i] Y[i]正确对应于Y[i]

Another workaround is:另一种解决方法是:

  1. Make an array of tuple, then pass it to the ImageDataGenerator flow method.创建一个元组数组,然后将其传递给 ImageDataGenerator 流方法。
  2. Make an iterator method that accepts the iterator made by the previous step.制作一个接受上一步制作的迭代器的迭代器方法。 This iterator converts back the array of tuple to list of arrays.此迭代器将元组数组转换回数组列表。

Here is the methods to implement the steps above:以下是实现上述步骤的方法:

def make_array_of_tuple(tuple_of_arrays):
    array_0 = tuple_of_arrays[0]
    array_of_tuple = np.empty(array_0.shape[0], dtype=np.object)
    for i, tuple_of_array_elements in enumerate(zip(*tuple_of_arrays)):
        array_of_tuple[i] = tuple_of_array_elements
    return array_of_tuple

def convert_to_list_of_arrays(array_of_tuple):
    array_length = array_of_tuple.shape[0]
    tuple_length = len(array_of_tuple[0])
    array_list = [
        np.empty(array_length, dtype=np.uint8) for i in range(tuple_length) ]
    for i, array_element_tuple in enumerate(array_of_tuple):
        for array, tuple_element in zip(array_list, array_element_tuple):
            array[i] = tuple_element
    return array_list

def tuple_of_arrays_flow(original_flow):
    while True:
        (X, array_of_tuple) = next(original_flow)
        list_of_arrays = convert_to_list_of_arrays(array_of_tuple)
        yield X, list_of_arrays

To call the ImageDataGenerator flow() method and get the flow used for the model:要调用 ImageDataGenerator flow() 方法并获取用于模型的流:

y_train = make_array_of_tuple((y_train_1, y_train_2, y_train_3))
orig_image_flow = train_image_generator.flow(X_train, y=y_train)
train_image_flow = tuple_of_arrays_flow(orig_image_flow)

The size of y_train is the same as X_train, so it should be accepted. y_train 的大小和 X_train 一样,所以应该可以接受。 'train_image_flow' returns list of arrays that should be accepted by the Keras multi-output model. 'train_image_flow' 返回 Keras 多输出模型应接受的数组列表。

ADDED (2019/01/26)添加(2019/01/26)

One another idea, simpler than the above one:另一种想法,比上面的更简单:

  1. Pass array of indices, which contains 0, 1, 2, ..., to ImageDataGenerator.flow().将包含 0, 1, 2, ... 的索引数组传递给 ImageDataGenerator.flow()。
  2. In the iterator, select the elements in the arrays for the multiple output by using the returned indices array from the original flow.在迭代器中,使用从原始流返回的索引数组为多个输出选择数组中的元素。

Here is the implementation:这是实现:

def make_multi_output_flow(image_gen, X, y_list, batch_size):
    y_item_0 = y_list[0]
    y_indices = np.arange(y_item_0.shape[0])
    orig_flow = image_gen.flow(X, y=y_indices, batch_size=batch_size)

    while True:
        (X, y_next_i) = next(orig_flow)
        y_next = [ y_item[y_next_i] for y_item in y_list ]
        yield X, y_next

This is an example to call the method above.这是调用上述方法的示例。

y_train = [y_train_1, y_train_2, y_train_3]
multi_output_flow = make_multi_output_flow(
    image_data_generator, X_train, y_train, batch_size)

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

相关问题 Keras:使用带有model.fit_generator的多输出模型的生成器 - Keras: Using a generator for multi-output model with model.fit_generator 在 Python 中使用生成器输入 Keras model.fit_generator - Using generator in Python to feed into Keras model.fit_generator 如何在keras中使用model.fit_generator - How to use model.fit_generator in keras 使用 tf.keras.utils.Sequence 和 model.fit_generator 和 use_multiprocessing=True 生成警告 - Using tf.keras.utils.Sequence with model.fit_generator with use_multiprocessing=True generated warning 如何在不使用 model.fit_generator 的情况下对 Keras 中的图像应用旋转? - How can I apply rotation to image in Keras without using model.fit_generator? 具有color_mode的keras ImageDataGenerator.flow - keras ImageDataGenerator.flow with color_mode CNN Keras model.fit 和 model.fit_generator - CNN Keras model.fit and model.fit_generator 在多输出Keras模型中为每个输出使用不同的样本权重 - Using different sample weights for each output in a multi-output Keras model Keras上的model.compile和model.fit_generator出错 - Error with model.compile and model.fit_generator on Keras 当我在Keras中运行model.fit_generator时,控制台中此输出的含义是什么? - What is the meaning of this output in the console when I run model.fit_generator in Keras?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM