【问题标题】:classification with keras: input data shape使用 keras 进行分类:输入数据形状
【发布时间】:2017-09-07 15:15:38
【问题描述】:

我正在尝试修改 keras 的 blog 中显示的分类示例,以将图像分类为 3 个不同的类别。

我有 3000 张 (3 x 1000) 的训练图像和 1200 (3 x 400) 的验证图像。 代码修改为3类。

代码如下:

import numpy as np
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Dropout, Flatten, Dense
from keras import applications

# dimensions of our images.
img_width, img_height = 150, 150

top_model_weights_path = 'bottleneck_fc_model.h5'
train_data_dir = 'data/train'
validation_data_dir = 'data/validation'
nb_train_samples = 3000
nb_validation_samples = 1200
epochs = 50
batch_size = 16

n_classes = 3


def save_bottlebeck_features():
    datagen = ImageDataGenerator(rescale=1. / 255)

    # build the VGG16 network
    model = applications.VGG16(include_top=False, weights='imagenet')

    generator = datagen.flow_from_directory(
        train_data_dir,
        target_size=(img_width, img_height),
        batch_size=batch_size,
        class_mode='categorical',
        shuffle=False)
    bottleneck_features_train = model.predict_generator(
        generator, nb_train_samples // batch_size)
    np.save(open('bottleneck_features_train.npy', 'wb'),
            bottleneck_features_train)

    generator = datagen.flow_from_directory(
        validation_data_dir,
        target_size=(img_width, img_height),
        batch_size=batch_size,
        class_mode='categorical',
        shuffle=False)
    bottleneck_features_validation = model.predict_generator(
        generator, nb_validation_samples // batch_size)
    np.save(open('bottleneck_features_validation.npy', 'wb'),
            bottleneck_features_validation)


def train_top_model():
    train_data = np.load(open('bottleneck_features_train.npy','rb'))
    train_labels = np.array([0] * (nb_train_samples // n_classes) + [1] * (nb_train_samples // n_classes) + \
                            [2] * (nb_train_samples // n_classes))

    validation_data = np.load(open('bottleneck_features_validation.npy','rb'))
    validation_labels = np.array([0] * (nb_train_samples // n_classes) + [1] * (nb_train_samples // n_classes) + \
                                 [2] * (nb_train_samples // n_classes))

    model = Sequential()
    model.add(Flatten(input_shape=train_data.shape[1:]))
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(n_classes, activation='softmax'))

    model.compile(optimizer='rmsprop',
                  loss='categorical_crossentropy', metrics=['accuracy'])

    model.fit(train_data, train_labels, epochs=epochs, batch_size=batch_size, \
              validation_data=(validation_data, validation_labels))
    model.save_weights(top_model_weights_path)

当我最终执行这两个函数时:

save_bottlebeck_features()
train_top_model()

第二个函数返回如下错误:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-143-070a6188c611> in <module>()
      4 print(validation_labels.shape)
      5 
----> 6 train_top_model()

<ipython-input-129-ea2b02024693> in train_top_model()
     64                   loss='categorical_crossentropy', metrics=['accuracy'])
     65 
---> 66     model.fit(train_data, train_labels, epochs=epochs, batch_size=batch_size,               validation_data=(validation_data, validation_labels))
     67     model.save_weights(top_model_weights_path)

~/anaconda/lib/python3.6/site-packages/keras/models.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, **kwargs)
    865                               class_weight=class_weight,
    866                               sample_weight=sample_weight,
--> 867                               initial_epoch=initial_epoch)
    868 
    869     def evaluate(self, x, y, batch_size=32, verbose=1,

~/anaconda/lib/python3.6/site-packages/keras/engine/training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, **kwargs)
   1520             class_weight=class_weight,
   1521             check_batch_axis=False,
-> 1522             batch_size=batch_size)
   1523         # Prepare validation data.
   1524         do_validation = False

~/anaconda/lib/python3.6/site-packages/keras/engine/training.py in _standardize_user_data(self, x, y, sample_weight, class_weight, check_batch_axis, batch_size)
   1380                                     output_shapes,
   1381                                     check_batch_axis=False,
-> 1382                                     exception_prefix='target')
   1383         sample_weights = _standardize_sample_weights(sample_weight,
   1384                                                      self._feed_output_names)

~/anaconda/lib/python3.6/site-packages/keras/engine/training.py in _standardize_input_data(data, names, shapes, check_batch_axis, exception_prefix)
    142                             ' to have shape ' + str(shapes[i]) +
    143                             ' but got array with shape ' +
--> 144                             str(array.shape))
    145     return arrays
    146 

ValueError: Error when checking target: expected dense_58 to have shape (None, 3) but got array with shape (3000, 1)

如果我打印数据和标签的形状,它会返回:

print(train_labels.shape)
(3000, 3)
print(train_data.shape)
(3000, 3)
print(validation_data.shape)
(1200, 4, 4, 512)
print(validation_labels.shape)
(1200,)

编辑

我正在发布完整代码以及包含我正在考虑的图像的数据库。

数据库可以下载here

代码如下:

# dimensions of our images.
img_width, img_height = 150, 150

top_model_weights_path = 'what.h5'#'bottleneck_fc_model.h5'
train_data_dir = 'data_short/train'
validation_data_dir = 'data_short/validation'
nb_train_samples = 30
nb_validation_samples = 6
epochs = 50
batch_size = 16

n_classes = 3


def save_bottlebeck_features():
    datagen = ImageDataGenerator(rescale=1. / 255)

    # build the VGG16 network
    model = applications.VGG16(include_top=False, weights='imagenet')

    generator = datagen.flow_from_directory(train_data_dir, target_size=(img_width, img_height),\
                                            batch_size=batch_size, class_mode='categorical', shuffle=False)

    bottleneck_features_train = model.predict_generator(generator, nb_train_samples // batch_size)

    np.save(open('bottleneck_features_train.npy', 'wb'), bottleneck_features_train)

    generator = datagen.flow_from_directory(validation_data_dir, target_size=(img_width, img_height),\
                                            batch_size=batch_size, class_mode='categorical', shuffle=False)

    bottleneck_features_validation = model.predict_generator(generator, nb_validation_samples // batch_size)

    np.save(open('bottleneck_features_validation.npy', 'wb'), bottleneck_features_validation)


def train_top_model():
    encoder = OneHotEncoder()
    #train_data = np.load(open('bottleneck_features_train.npy','rb'))
    train_data = np.load('bottleneck_features_train.npy')

    train_labels = np.array([0] * (nb_train_samples // n_classes) + [1] * (nb_train_samples // n_classes) + 
                            [2] * (nb_train_samples // n_classes))

    train_labels = to_categorical(train_labels)


    validation_data = np.load(open('bottleneck_features_validation.npy','rb'))
    validation_labels = np.array([0] * (nb_validation_samples // n_classes) + \
                                 [1] * (nb_validation_samples // n_classes) + \
                                 [2] * (nb_validation_samples // n_classes))

    validation_labels = to_categorical(validation_labels)

    model = Sequential()
    model.add(Flatten(input_shape=train_data.shape[1:]))
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(n_classes, activation='softmax'))

    model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

    model.fit(train_data, train_labels, epochs=epochs, batch_size=batch_size,\
              validation_data=(validation_data, validation_labels))
    model.save_weights(top_model_weights_path)

给出的错误如下:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-8-6869607a6e44> in <module>()
----> 1 train_top_model()

<ipython-input-6-933b6592c6c1> in train_top_model()
     56     model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
     57 
---> 58     model.fit(train_data, train_labels, epochs=epochs, batch_size=batch_size,              validation_data=(validation_data, validation_labels))
     59     model.save_weights(top_model_weights_path)

~/anaconda/lib/python3.6/site-packages/keras/models.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, **kwargs)
    861                               class_weight=class_weight,
    862                               sample_weight=sample_weight,
--> 863                               initial_epoch=initial_epoch)
    864 
    865     def evaluate(self, x, y, batch_size=32, verbose=1,

~/anaconda/lib/python3.6/site-packages/keras/engine/training.py in fit(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, **kwargs)
   1356             class_weight=class_weight,
   1357             check_batch_axis=False,
-> 1358             batch_size=batch_size)
   1359         # Prepare validation data.
   1360         if validation_data:

~/anaconda/lib/python3.6/site-packages/keras/engine/training.py in _standardize_user_data(self, x, y, sample_weight, class_weight, check_batch_axis, batch_size)
   1244                           for (ref, sw, cw, mode)
   1245                           in zip(y, sample_weights, class_weights, self._feed_sample_weight_modes)]
-> 1246         _check_array_lengths(x, y, sample_weights)
   1247         _check_loss_and_target_compatibility(y,
   1248                                              self._feed_loss_fns,

~/anaconda/lib/python3.6/site-packages/keras/engine/training.py in _check_array_lengths(inputs, targets, weights)
    235                          'the same number of samples as target arrays. '
    236                          'Found ' + str(list(set_x)[0]) + ' input samples '
--> 237                          'and ' + str(list(set_y)[0]) + ' target samples.')
    238     if len(set_w) > 1:
    239         raise ValueError('All sample_weight arrays should have '

ValueError: Input arrays should have the same number of samples as target arrays. Found 16 input samples and 30 target samples.

EDIT2解决办法:

我解决了这个问题,对代码进行了根本性的更改。可以看到here

【问题讨论】:

  • train_lables.shape[1] 应该是 =validation_labels.shape[1]train_data.shape[1],train_data.shape[2],train_data.shape[3] 应该等于 validation_data.shape[1],validation_data.shape[2],validation_data.shape[3],这应该很清楚,因为数据测试和数据验证之间的唯一区别是第一个维度,即您拥有的“样本”总数
  • 我认为这不是问题所在。我将系统减少为每个类 10 幅图像用于训练,2 幅图像用于验证。张量大小是正确的,它遵守您提出的规则。但是我仍然有错误。
  • ValueError:输入数组的样本数应与目标数组相同。找到 16 个输入样本和 30 个目标样本。
  • 您能否更新代码以反映这一点,现在看来您的train_data.shape[0] 不等于train_labels.shape[0]
  • 您仍然提供一个只有 1 个类的数组作为标签。错误消息现在显示您的标签形状类似于(30,1)。您创建标签的方式有问题。

标签: tensorflow keras classification


【解决方案1】:
  • 您有“输入数据”,即您的一组图像。 - 形状:(BatchSize,w,h,channels)
  • 你有“输出数据/真实值/预测”这些类。形状:(BatchSize,3)

错误消息告诉您,您提供的模型输出数据形状类似于 (BatchSize,1),不适合模型。

所以,您在创建train_labels 时肯定遇到了问题。

您必须使其形状为(3000,3)。并且与每个类相关的索引应该是1:

  • 1 类:[1,0,0]
  • 第 2 类:[0,1,0]
  • 第 3 类:[0,0,1]

您可能已经合并了课程(如果您的情况可能的话)。


使用 keras.utils.to_categorical()

但请确保train_labels.shape[0]train_data.shape[0] 完全相同。

from keras.utils import to_categorical

train_labels = np.array([0] * (nb_train_samples // n_classes) + [1] * (nb_train_samples // n_classes) + 
                        [2] * (nb_train_samples // n_classes))

train_labels = to_categorical(train_labels)

另一种创建标签的非常简单的方法:

train_labels = np.zeros((30,3))
train_labels[:10,0] = 1.
train_labels[10:20,1] = 1.
train_labels[20:,2] = 1.

【讨论】:

  • 但是当我打印张量的形状时,它说它是 3000,3。 print(train_labels.shape) (3000, 3)
  • 好吧,在调用fit 之前立即进行打印(从train_top_model() 函数内部 打印)。该模型正在接收(3000,1)
  • @Daniel,我认为最初这是问题所在,应该是公认的答案,但现在 OP 的输入数据的形状存在问题,显示 16 个样本
  • 也相信这与他的predict_generator() 函数中的steps= 参数有关,或者与来自目录的流中的batch_size 参数结合使用。对VGG16不够了解,无法运行他的代码,但我认为这是新问题
猜你喜欢
  • 1970-01-01
  • 2018-02-16
  • 2019-12-25
  • 2020-09-20
  • 2020-06-10
  • 2017-08-14
  • 2018-11-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多