使用分类输入数据和图像输入数据进行分类

Posted

技术标签:

【中文标题】使用分类输入数据和图像输入数据进行分类【英文标题】:Classification using categorical input data and image input data 【发布时间】:2020-09-20 23:32:24 【问题描述】:

我有一个大约 300 行的小型数据集。每行有: A列:图像, B 列:分类文本输入, C列:分类文本输入, D列:分类文本输出

我能够单独对图像输入数据(A 列)使用顺序 Keras 模型来预测输出(D 列),但准确度非常糟糕(大约 40%)。如何将图像数据与分类输入数据相结合以获得更好的准确性?

以下是我正在使用的代码。我收到关于 model.fit 的错误: ValueError:无法将字符串转换为浮点数:'item1'

我使用的数据中没有数字,一切都是分类文本。我认为我需要在“y”的模型中进行一些更改,以便它知道预测是分类的而不是数字的。不过我不确定要更改什么。

drive.mount('/content/gdrive/')
train = pd.read_csv(r'gdrive/My Drive/Colab Notebooks/Fast AI/testfilled.csv')
df = pd.DataFrame(train)
df = df[['Column A', 'Column B', 'Column C', 'Column D']]

def process_categorical_attributes(df, train, test):
  zipBinarizer = LabelBinarizer().fit(df["Column B"])
  trainCategorical = zipBinarizer.transform(train["Column B"])
  testCategorical = zipBinarizer.transform(test["Column B"])

  zipBinarizer2 = LabelBinarizer().fit(df["Column C"])
  trainCategorical2 = zipBinarizer.transform(train["Column C"])
  testCategorical2 = zipBinarizer.transform(test["Column C"])

  trainX = np.hstack([trainCategorical, trainCategorical2])
  testX = np.hstack([testCategorical, testCategorical2])
  return (trainX, testX)

def load_piece_images(df):
  train_image = []
  for i in tqdm(range(train.shape[0])):
    img = image.load_img('gdrive/My Drive/Colab Notebooks/OutputDir/' + train['FileName'][i] + '.bmp',target_size=(400,400,3))
    img = image.img_to_array(img)
    img = img/255   
    train_image.append(img)
  return np.array(train_image)

def create_mlp(dim, regress=False):  
  model = Sequential()
  model.add(Dense(8, input_dim=dim, activation="relu"))
  model.add(Dense(4, activation="relu"))
  if regress:
    model.add(Dense(1, activation="linear"))
  return model

def create_cnn(width, height, depth, filters=(16, 32, 64), regress=False):
    inputShape = (height, width, depth)
    chanDim = -1
    inputs = Input(shape=inputShape)
    for (i, f) in enumerate(filters):
        if i == 0:
            x = inputs
        x = Conv2D(f, (3, 3), padding="same")(x)
        x = Activation("relu")(x)
        x = BatchNormalization(axis=chanDim)(x)
        x = MaxPooling2D(pool_size=(2, 2))(x)
    x = Flatten()(x)
    x = Dense(16)(x)
    x = Activation("relu")(x)
    x = BatchNormalization(axis=chanDim)(x)
    x = Dropout(0.5)(x)
    x = Dense(4)(x)
    x = Activation("relu")(x)
    if regress:
        x = Dense(1, activation="linear")(x)
    model = Model(inputs, x)
    return model

images = load_piece_images(df)
split = train_test_split(df, images, test_size=0.25, random_state=42)
(trainAttrX, testAttrX, trainImagesX, testImagesX) = split

trainY = trainAttrX["Column D"]
testY = testAttrX["Column D"]
(trainAttrX, testAttrX) = process_categorical_attributes(df, trainAttrX, testAttrX)

mlp = create_mlp(trainAttrX.shape[1], regress=False)
cnn = create_cnn(400, 400, 3, regress=False)
combinedInput = concatenate([mlp.output, cnn.output])
x = Dense(4, activation="relu")(combinedInput)
x = Dense(1, activation="linear")(x)
x = Dense(1, activation='sigmoid')(x)
model = Model(inputs=[mlp.input, cnn.input], outputs=x)

opt = Adam(lr=1e-3, decay=1e-3 / 200)
model.compile(loss="mean_absolute_percentage_error", optimizer=opt)
model.fit(
    [trainAttrX, trainImagesX], trainY,
    validation_data=([testAttrX, testImagesX], testY),
    epochs=20, batch_size=2)

【问题讨论】:

【参考方案1】:

本教程很好地解释了如何使用多个输入源(文本 + 图像数据):https://www.pyimagesearch.com/2019/02/04/keras-multiple-inputs-and-mixed-data/

基本上这正是您正在寻找的。​​p>

【讨论】:

感谢您的回答。我确实看过这个。但是,我无法克服两个障碍 - 1) 本教程使用一个分类变量作为输入,我需要两个。 2)这使用回归来预测数值结果 - 但我需要分类作为我的输出 - 不涉及数值。我该如何做到这一点? 简单:对于另一个分类变量,您声明另一个输入:因此您有 input_1、input_2、input_3,与教程中的其他输入完全相同。对于分类输出......您可以根据您的问题添加 Dense(1,activation='sigmoid') 或 Dense(n_classes, activation = 'softmax') 这很有帮助!我已将我的代码添加到问题中。我现在声明多个分类输入并对其进行 np.hstack 。我认为这似乎是正确的方法。但是,即使在添加 Dense(1,activation='sigmoid') 之后,我仍然在 model.fit 上收到一个错误,它说它无法将字符串转换为浮点数。你能建议我能做些什么来解决这个问题吗? 如果它解决了您最初的问题,请接受并支持我的回答。你现在问的是一个不同的问题,你通常应该把它放在一个单独的问题中。至于你的最后一个错误,确保你正确地将字符串转换为浮点数;如果这没有发生,则意味着您可能确实有一些不是数字的字符串值(另存为数字),因此转换失败。 在将数据输入模型之前,手动确保所有数据都是 numpy + float。【参考方案2】:

有时使用的另一个选项(例如在条件 GAN 和 AlphaFold 2 中)是将分类数据编码为输入图像中的额外标量特征通道。因此,例如,如果您对类别 1-hot 进行了编码,您将采用类似于 [0, 1, 0, ...] 的向量,并使用一个全为 0 的通道、另一个全为 1 的通道扩展您的 RGB 通道, 另一个全是 0, 等等。

与其他方法(将分类特征编码连接到神经嵌入)相比的优势在于神经网络本身可以看到更多特征,在某些情况下,当 RGB 通道没有足够的信息来区分类别时,这是必要的出于兴趣。缺点是它的计算或内存效率不高。

【讨论】:

以上是关于使用分类输入数据和图像输入数据进行分类的主要内容,如果未能解决你的问题,请参考以下文章

使用多层感知器(MLP)对图像及其性能进行分类

如何使用 SVM 对图像进行分类

是否应该对输入数据进行缩放以进行实时分类?

多模态特征融合:图像语音文本如何转为特征向量并进行分类

Android 垃圾分类APP垃圾分类之图像输入

softmax和分类模型