【问题标题】:Python Keras - Custom Labels in ImageDataGeneratorPython Keras - ImageDataGenerator 中的自定义标签
【发布时间】:2020-02-16 16:09:02
【问题描述】:

我目前正在创建一个 CNN 模型,用于对字体是否为 ArialVerdanaTimes New RomanGeorgia 进行分类。总而言之,有16 类,因为我还考虑检测字体是regularbolditalics 还是bold italics。所以4 fonts * 4 styles = 16 classes

我在训练中使用的数据如下:

Training data set : 800 image patches of 256 * 256 dimension (50 for each class)
Validation data set : 320 image patches of 256 * 256 dimension (20 for each class)
Testing data set : 160 image patches of 256 * 256 dimension (10 for each class)

下面是我的初始代码:

import numpy as np
import keras
from keras import backend as K
from keras.models import Sequential
from keras.layers import Activation
from keras.layers.core import Dense, Flatten
from keras.optimizers import Adam
from keras.metrics import categorical_crossentropy
from keras.preprocessing.image import ImageDataGenerator
from keras.layers.normalization import BatchNormalization
from keras.layers.convolutional import *
from matplotlib import pyplot as plt
import itertools
import matplotlib.pyplot as plt
import pickle


 image_width = 256
 image_height = 256

 train_path = 'font_model_data/train'
 valid_path =  'font_model_data/valid'
 test_path = 'font_model_data/test'


  train_batches = ImageDataGenerator().flow_from_directory(train_path, target_size=(image_width, image_height), classes=['1','2','3','4', '5', '6', '7', '8', '9', '10', '11', '12','13', '14', '15', '16'], batch_size = 16)
 valid_batches = ImageDataGenerator().flow_from_directory(valid_path, target_size=(image_width, image_height), classes=['1','2','3','4', '5', '6', '7', '8', '9', '10', '11', '12','13', '14', '15', '16'], batch_size = 16)
 test_batches = ImageDataGenerator().flow_from_directory(test_path, target_size=(image_width, 
 image_height), classes=['1','2','3','4', '5', '6', '7', '8', '9', '10', '11', '12','13', '14', '15', '16'], batch_size = 160)


 imgs, labels = next(train_batches)
 print(labels)

#CNN model
model = Sequential([
    Conv2D(32, (3,3), activation='relu', input_shape=(image_width, image_height, 3)),
    Flatten(),
    Dense(**16**, activation='softmax'), # I want to make it 4
])

我计划在网络中有 4 个输出节点:

4 Output Nodes (4 bits):
Class 01 - 0000
Class 02 - 0001
Class 03 - 0010
Class 04 - 0011
Class 05 - 0100
Class 06 - 0101
Class 07 - 0110
Class 08 - 0111
Class 09 - 1000
Class 10 - 1001
Class 11 - 1010
Class 12 - 1011
Class 13 - 1100
Class 14 - 1101
Class 15 - 1110
Class 16 - 1111

但是ImageDataGenerator生成的标签是16 bits标签

[[0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]]

如何为我的课程分配自定义标签?我希望我的标签是:

 labels = [[0,0,0,0],
 [0,0,0,1],
 [0,0,1,0],
 [0,0,1,1],
 [0,1,0,0],
 [0,1,0,1],
 [0,1,1,0],
 [0,1,1,1],
 [1,0,0,0],
 [1,0,0,1],
 [1,0,1,0],
 [1,0,1,1],
 [1,1,0,0],
 [1,1,0,1],
 [1,1,1,0],
 [1,1,1,1]]

它的目的是使我的网络的输出节点/最后一个密集层从164 节点,因此,架构不那么复杂。

【问题讨论】:

  • 我不确定我是否理解您的问题。您想将 1 和 0 的数组转换为标签列表,例如[1101, 1011, 1001, 1111]?
  • @NicolasGervais - 是的。查看我更新的帖子:)
  • 由于 one-hot-encoding 和您的标签之间存在 1-1 映射,您不能创建一个映射来执行此操作吗?

标签: python machine-learning keras neural-network imagedata


【解决方案1】:

这是你已经拥有的:

custom_labels = ['0000',  '0001', '0010', '0011', '0100', '0101', '0110', '0111',
                 '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111']

output = [[0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
            [0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
            [0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
            [1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
            [0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
            [0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
            [0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
            [0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
            [0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
            [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]]

您需要获取1 的索引:

import numpy as np

column = np.argmax(output, axis=1)
Out[10]: array([ 1,  2,  3,  0,  2,  9,  7,  4,  2, 15], dtype=int64)

这样就可以选择对应的自定义标签了:

array(['0001', '0010', '0011', '0000', '0010', '1001', '0111', '0100',
       '0010', '1111'], dtype='<U4')

但你想要的是这些列表,但作为单独的整数:

final_labels = np.array([list(i) for i in np.array(custom_labels)[column]]).astype(int)
array([[0, 0, 0, 1],
       [0, 0, 1, 0],
       [0, 0, 1, 1],
       [0, 0, 0, 0],
       [0, 0, 1, 0],
       [1, 0, 0, 1],
       [0, 1, 1, 1],
       [0, 1, 0, 0],
       [0, 0, 1, 0],
       [1, 1, 1, 1]])

【讨论】:

  • 感谢您的解释,我从您那里学到了一些东西。但是我要更改标签的目的是使网络的最后一个密集层有 4 个节点而不是 16 个节点。但是,每当我输入 4 而不是 16 时,它都会抛出一个错误。所以我在想如果我可以改变标签的编码方式,我可以让它发生。
【解决方案2】:

我的回答是没有办法做到这一点。您不能将输出层变为仅 4 个单位,因为您有 16 个类要分类。如果您想简化网络,只需尝试减少隐藏单元的数量即可查看网络是否欠拟合或过拟合。如果它过拟合,您可以降低网络的复杂性。如果不合适的话。它表明您需要更复杂的网络。如果你真的想减少输出层的单元数量。也许我能想到的一种方法是,您可以首先对字体进行分类。这需要 4 个单位。然后检测是什么风格。这需要其他 4 个单位。然后结合两个输出的概率。我不确定这是否可行。你可以试试看。

【讨论】:

    猜你喜欢
    • 2020-10-21
    • 2017-06-18
    • 2019-05-29
    • 1970-01-01
    • 2019-02-08
    • 1970-01-01
    • 2019-04-01
    • 1970-01-01
    • 2017-04-25
    相关资源
    最近更新 更多