使用Caffe进行多类别和多标签图像分类

我正在尝试在Caffe中创建一个单一的多类别和多标签网络配置。

例如,对狗进行分类:狗是小型还是大型?(类别)狗是什么颜色?(类别)狗是否带有项圈?(标签)

使用Caffe实现这种分类是否可行?正确的做法是什么?

我只是想了解实际操作的方法。在创建了两个包含所有图像标签的文本文件(一个用于训练,一个用于验证)之后,例如:

/train/img/1.png 0 4 18/train/img/2.png 1 7 17 33/train/img/3.png 0 4 17

运行Python脚本:

import h5py, osimport caffeimport numpy as npSIZE = 227 # 所有图像的固定大小with open( 'train.txt', 'r' ) as T :    lines = T.readlines()# 如果内存不足,可以将数据分成多个批次并生成多个独立的h5文件X = np.zeros( (len(lines), 3, SIZE, SIZE), dtype='f4' ) y = np.zeros( (len(lines),1), dtype='f4' )for i,l in enumerate(lines):    sp = l.split(' ')    img = caffe.io.load_image( sp[0] )    img = caffe.io.resize( img, (SIZE, SIZE, 3) ) # 调整到固定大小    # 你可以在这里应用其他输入转换...    # 请注意,转换应将图像从size-by-size-by-3转换为3-by-size-by-size    # 例如    transposed_img = img.transpose((2,0,1))[::-1,:,:] # RGB->BGR    X[i] = transposed_img    y[i] = float(sp[1])with h5py.File('train.h5','w') as H:    H.create_dataset( 'X', data=X ) # 注意数据集命名为X!    H.create_dataset( 'y', data=y ) # 注意数据集命名为y!with open('train_h5_list.txt','w') as L:    L.write( 'train.h5' ) # 列出你将要使用的所有h5文件

并创建train.h5和val.h5(X数据集包含图像,而Y包含标签吗?)。

将我的网络输入层从以下内容替换:

layers {  name: "data"  type: DATA  top:  "data"  top:  "label"  data_param {    source: "/home/gal/digits/digits/jobs/20181010-191058-21ab/train_db"    backend: LMDB    batch_size: 64  }  transform_param {     crop_size: 227     mean_file: "/home/gal/digits/digits/jobs/20181010-191058-21ab/mean.binaryproto"     mirror: true   }   include: { phase: TRAIN } } layers {  name: "data"  type: DATA  top:  "data"  top:  "label"  data_param {    source: "/home/gal/digits/digits/jobs/20181010-191058-21ab/val_db"     backend: LMDB    batch_size: 64 }  transform_param {     crop_size: 227     mean_file: "/home/gal/digits/digits/jobs/20181010-191058-21ab/mean.binaryproto"     mirror: true   }   include: { phase: TEST } } 

替换为

layer {  type: "HDF5Data"  top: "X" # 与create_dataset中的名称相同!  top: "y"  hdf5_data_param {    source: "train_h5_list.txt" # 不要直接给出h5文件,而是给出列表。    batch_size: 32  }  include { phase:TRAIN }}layer {  type: "HDF5Data"  top: "X" # 与create_dataset中的名称相同!  top: "y"  hdf5_data_param {    source: "val_h5_list.txt" # 不要直接给出h5文件,而是给出列表。    batch_size: 32  }  include { phase:TEST }}

我猜HDF5不需要mean.binaryproto文件?

接下来,输出层应该如何更改以输出多个标签的概率?我猜我需要使用交叉熵层而不是softmax层?这是当前的输出层:

layers {  bottom: "prob"  bottom: "label"  top: "loss"  name: "loss"  type: SOFTMAX_LOSS  loss_weight: 1}layers {  name: "accuracy"  type: ACCURACY  bottom: "prob"  bottom: "label"  top: "accuracy"  include: { phase: TEST }}

回答:

均值减法

虽然lmdb输入数据层能够为你处理各种输入转换,但"HDF5Data"层不支持此功能。
因此,你必须在创建hdf5文件时处理所有输入转换(特别是均值减法)。
查看你的代码中标有

# you may apply other input transformations here...

多个标签

尽管你的.txt文件为每张图像列出了多个标签,但你只将第一个标签保存到hdf5文件中。如果你想使用这些标签,你必须将它们输入到网络中。
你的示例中立即出现的问题是你没有为每个训练图像固定数量的标签——为什么?这意味着什么?
假设你为每张图像有三个标签(在.txt文件中):

< filename > < dog size > < dog color > < has collar >

那么你可以在你的hdf5中使用y_sizey_colory_collar(而不是单一的y)。

y_size[i] = float(spl[1])y_color[i] = float(spl[2])y_collar[i] = float(spl[3])

你的输入数据层将相应地有更多的"top"

layer {  type: "HDF5Data"  top: "X" # 与create_dataset中的名称相同!  top: "y_size"  top: "y_color"  top: "y_collar"  hdf5_data_param {    source: "train_h5_list.txt" # 不要直接给出h5文件,而是给出列表。    batch_size: 32  }  include { phase:TRAIN }}

预测

目前你的网络只能预测一个标签(带有top: "prob"的层)。你需要你的网络预测所有三个标签,因此你需要添加计算top: "prob_size"top: "prob_color"top: "prob_collar"的层(每个"prob_*"使用不同的层)。
一旦你为每个标签有了预测,你就需要一个损失(同样,每个标签一个损失)。

Related Posts

在使用k近邻算法时,有没有办法获取被使用的“邻居”?

我想找到一种方法来确定在我的knn算法中实际使用了哪些…

Theano在Google Colab上无法启用GPU支持

我在尝试使用Theano库训练一个模型。由于我的电脑内…

准确性评分似乎有误

这里是代码: from sklearn.metrics…

Keras Functional API: “错误检查输入时:期望input_1具有4个维度,但得到形状为(X, Y)的数组”

我在尝试使用Keras的fit_generator来训…

如何使用sklearn.datasets.make_classification在指定范围内生成合成数据?

我想为分类问题创建合成数据。我使用了sklearn.d…

如何处理预测时不在训练集中的标签

已关闭。 此问题与编程或软件开发无关。目前不接受回答。…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注