【问题标题】:Caffe - num_output in prototxt gives strange behaviour [duplicate]Caffe - prototxt 中的 num_output 给出了奇怪的行为[重复]
【发布时间】:2016-04-02 01:17:06
【问题描述】:

我正在做一些实验,我将 Cifar-10 数据集分成两半,这样每一半都包含五个随机类。我用bvlc_alexnet 架构训练了一半。因此,我将num_output 更改为5 并对网络进行了其他一些小调整。当我检查日志文件时,我发现损失增加到 80 左右,测试准确度为 0

但是,当我将 num_output 更改为 10 时,训练似乎正常,即损失稳步减少,测试准确率约为 70%

如何解释?

train_val.prototxt

name: "AlexNet"
layer {
  name: "data"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    mirror: true
    crop_size: 25

  }
  data_param {
    source: "/home/apples/caffe/cifar/cifarA/cifar_A_train_lmdb"
    batch_size: 256
    backend: LMDB
  }
}
layer {
  name: "data"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TEST
  }
  transform_param {
    mirror: false
    crop_size: 25

  }
  data_param {
    source: "/home/apples/caffe/cifar/cifarA/cifar_A_val_lmdb"
    batch_size: 100
    backend: LMDB
  }
}
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    num_output: 96
    kernel_size: 11
    stride: 2
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}
layer {
  name: "relu1"
  type: "ReLU"
  bottom: "conv1"
  top: "conv1"
}
layer {
  name: "norm1"
  type: "LRN"
  bottom: "conv1"
  top: "norm1"
  lrn_param {
    local_size: 5
    alpha: 0.0001
    beta: 0.75
  }
}
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "norm1"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 3
    stride: 2
  }
}
layer {
  name: "conv2"
  type: "Convolution"
  bottom: "pool1"
  top: "conv2"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    num_output: 256
    pad: 2
    kernel_size: 5
    group: 2
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0.1
    }
  }
}
layer {
  name: "relu2"
  type: "ReLU"
  bottom: "conv2"
  top: "conv2"
}
layer {
  name: "norm2"
  type: "LRN"
  bottom: "conv2"
  top: "norm2"
  lrn_param {
    local_size: 5
    alpha: 0.0001
    beta: 0.75
  }
}
layer {
  name: "pool2"
  type: "Pooling"
  bottom: "norm2"
  top: "pool2"
  pooling_param {
    pool: MAX
    kernel_size: 3
    stride: 2
  }
}
layer {
  name: "conv3"
  type: "Convolution"
  bottom: "pool2"
  top: "conv3"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    num_output: 384
    pad: 1
    kernel_size: 3
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}
layer {
  name: "relu3"
  type: "ReLU"
  bottom: "conv3"
  top: "conv3"
}
layer {
  name: "conv4"
  type: "Convolution"
  bottom: "conv3"
  top: "conv4"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    num_output: 384
    pad: 1
    kernel_size: 3
    group: 2
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0.1
    }
  }
}
layer {
  name: "relu4"
  type: "ReLU"
  bottom: "conv4"
  top: "conv4"
}
layer {
  name: "conv5"
  type: "Convolution"
  bottom: "conv4"
  top: "conv5"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    num_output: 256
    pad: 1
    kernel_size: 3
    group: 2
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0.1
    }
  }
}
layer {
  name: "relu5"
  type: "ReLU"
  bottom: "conv5"
  top: "conv5"
}
layer {
  name: "pool5"
  type: "Pooling"
  bottom: "conv5"
  top: "pool5"
  pooling_param {
    pool: MAX
    kernel_size: 3
    stride: 2
  }
}
layer {
  name: "fc6"
  type: "InnerProduct"
  bottom: "pool5"
  top: "fc6"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  inner_product_param {
    num_output: 4096
    weight_filler {
      type: "gaussian"
      std: 0.005
    }
    bias_filler {
      type: "constant"
      value: 0.1
    }
  }
}
layer {
  name: "relu6"
  type: "ReLU"
  bottom: "fc6"
  top: "fc6"
}
layer {
  name: "drop6"
  type: "Dropout"
  bottom: "fc6"
  top: "fc6"
  dropout_param {
    dropout_ratio: 0.5
  }
}
layer {
  name: "fc7"
  type: "InnerProduct"
  bottom: "fc6"
  top: "fc7"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  inner_product_param {
    num_output: 4096
    weight_filler {
      type: "gaussian"
      std: 0.005
    }
    bias_filler {
      type: "constant"
      value: 0.1
    }
  }
}
layer {
  name: "relu7"
  type: "ReLU"
  bottom: "fc7"
  top: "fc7"
}
layer {
  name: "drop7"
  type: "Dropout"
  bottom: "fc7"
  top: "fc7"
  dropout_param {
    dropout_ratio: 0.5
  }
}
layer {
  name: "fc8_mnist"
  type: "InnerProduct"
  bottom: "fc7"
  top: "fc8_mnist"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  inner_product_param {
    num_output: 5
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}
layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "fc8_mnist"
  bottom: "label"
  top: "accuracy"
  include {
    phase: TEST
  }
}
layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "fc8_mnist"
  bottom: "label"
  top: "loss"
}

此拆分包含 0、4、5、6 和 8 类。我使用 create_imagenet.sh 脚本创建了 lmdb 文件。

train.txt 示例

0/attack_aircraft_s_001759.png 0
0/propeller_plane_s_001689.png 0
4/fallow_deer_s_000021.png 4
4/alces_alces_s_000686.png 4
5/toy_spaniel_s_000327.png 5
5/toy_spaniel_s_000511.png 5
6/bufo_viridis_s_000502.png 6
6/bufo_viridis_s_001005.png 6
8/passenger_ship_s_000236.png 8
8/passenger_ship_s_000853.png 8

val.txt 示例

0/attack_aircraft_s_000002.png 0
0/propeller_plane_s_000006.png 0
4/fallow_deer_s_000001.png 4
4/alces_alces_s_000012.png 4
5/toy_spaniel_s_000020.png 5
6/bufo_viridis_s_000016.png 6
8/passenger_ship_s_000060.png 8

【问题讨论】:

  • 根据您的描述不清楚,但我认为训练分区和验证分区包含相同的 10 个类中的 5 个,对吗?如果您的分区逻辑不好,并且您有来自训练中未看到的类的验证(测试)类样本,那么您会得到一个低测试错误。如果您在分区之间进行了分类划分,则测试错误将是 100%(0 准确度)。
  • 感谢您的回复。正确,训练和验证包含相同的类。我唯一改变的是 num_output 从 5 到 10。这可能是 Caffe 中的错误吗?
  • 如果你也使用训练测试作为测试图像集,准确率是多少。
  • 对于标签5-9的分割,你是把标签改成0-4,还是保持标签不变?
  • @AnoopK.Prabhu 当我将训练数据用作测试数据时,Caffe 似乎在这一步冻结了I0401 13:03:42.787312 24045 net.cpp:411] data -> label(我同时使用了num_output 5 和 10。)

标签: machine-learning neural-network deep-learning caffe


【解决方案1】:

正如 cmets 中所指出的,Caffe 期望标签是介于 0 和 num_classes - 1 之间的整数。在您的情况下,当您将标签数量设置为 5 时,Caffe 将在最后一层创建五个输出神经元。当你要求它预测第 6 类或第 8 类时,你是在要求它最大化一个不存在的神经元的输出,这显然是 Caffe 做不到的。

现在,当您重新标记数据并将 num_classes 设置为 5 时,您做了正确的事情,因此它可以正常工作。当你将num_classes 设置为 10 时,网络仍然可以工作,因为现在它有 10 个输出神经元,足以对 5 个类别进行分类。它将知道从 5 到 9 的类从不存在,因此不应该被预测,它只会以一种总是导致这些输出神经元返回非常小的值的方式调整权重。然而,重要的是要注意,神经网络自然是随机的,所以它可能偶尔仍会返回一个从未呈现给它的类,所以我希望num_classes 大于实际类数的 NN 表现更差比 num_classes 正确的那个。

【讨论】:

  • 这非常有帮助,谢谢!文档中是否也对此进行了描述?
猜你喜欢
  • 2014-07-29
  • 2019-11-11
  • 2011-06-28
  • 2013-08-17
  • 1970-01-01
  • 2014-01-09
  • 2017-02-06
  • 2020-08-12
  • 2021-05-16
相关资源
最近更新 更多