如何使用我的分类网络检测多个物体?

时间:2019-04-19 06:07:42

标签: python tensorflow keras computer-vision conv-neural-network

我使用tensorflow附带的keras创建了一个简单的卷积网络。我已经训练了模型,准确性看起来不错。

我已经在10个不同的班级上对网络进行了培训。该网络能够以0.93的精度区分10个类别中的每个类别。

现在,同一图像中很可能存在多个类。有没有一种方法可以使用受过训练的网络检测同一图像中的多个对象?最好的办法是获取检测到的对象周围的坐标/边界框,以便于测试/可视化。

这是我写网络的方式:

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.BatchNormalization(input_shape=x_train.shape[1:]))
model.add(tf.keras.layers.Conv2D(64, (5, 5), padding='same', activation='elu'))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2,2)))
model.add(tf.keras.layers.Dropout(0.25))

model.add(tf.keras.layers.BatchNormalization(input_shape=x_train.shape[1:]))
model.add(tf.keras.layers.Conv2D(128, (5, 5), padding='same', activation='elu'))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2)))
model.add(tf.keras.layers.Dropout(0.25))

model.add(tf.keras.layers.BatchNormalization(input_shape=x_train.shape[1:]))
model.add(tf.keras.layers.Conv2D(256, (5, 5), padding='same', activation='elu'))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2,2)))
model.add(tf.keras.layers.Dropout(0.25))

model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(256))
model.add(tf.keras.layers.Activation('elu'))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(10))
model.add(tf.keras.layers.Activation('softmax'))

model.compile(
    optimizer=tf.train.AdamOptimizer(learning_rate=1e-3, ),
    loss=tf.keras.losses.sparse_categorical_crossentropy,
    metrics=['sparse_categorical_accuracy']
)

def train_gen(batch_size):
 while True:
    offset = np.random.randint(0, x_train.shape[0] - batch_size)
    yield x_train[offset:offset+batch_size], y_train[offset:offset + batch_size]


model.fit_generator(
    train_gen(512),
    epochs=15,
    steps_per_epoch=100,
    validation_data=(x_valid, y_valid)
)

这很好。如何使用该网络从10个类别中检测多个对象?我会以某种方式重新训练网络吗?

1 个答案:

答案 0 :(得分:0)

为了教您的模型每个图像检测一个以上的类,您将需要对模型和数据进行一些更改,然后对其进行重新训练。

  • 您现在最终的激活将需要是S型的,因为您将不再预测单个类别的概率分布。现在,您希望每个输出神经元预测一个介于0到1之间的值,并且不止一个神经元可能具有接近1的值。
  • 您的损失函数现在应为binary_crossentropy,因为您会将每个输出神经元视为一个独立的预测,并将其与真实标签进行比较。
  • 据我所知,您一直在使用sparse_categorical_crossentropy,我假设您的标签是整数。您现在想将标签编码更改为一键式样式,每个标签的len等于num_classes,并且在图像具有该类的那些位置仅包含1,其余为0 。

有了这些更改,您现在可以重新训练模型以学习预测每个图像不止一个类别。

对于预测对象周围的边界框,这是一个非常不同且更具挑战性的任务。诸如YOLO或CRNN之类的高级模型可以做到这一点,但是它们的结构要复杂得多。