【问题标题】:Why my CNN returns always the same result?为什么我的 CNN 总是返回相同的结果?
【发布时间】:2017-09-21 11:29:34
【问题描述】:

我正在尝试构建一个 CNN,将对象分为 3 个主要类别。这三个对象由兰博基尼、气缸盖和一架飞机组成。我的数据集由 6580 张图像组成,每个类几乎 2200 张图像。您可以在 google drive dataset 上查看我的数据集。 我的 CNN 的架构是 AlexNet,但我已经将全连接层 8 的输出从 1000 修改为 3。 我已经使用这些设置进行训练

test_iter:1000
test_interval:1000
base_lr:0.001
lr_policy:"step"
gamma:0.1
stepsize:2500
max_iter:40000
momentum:0.9
weight_decay:0.0005

但是,问题是当我在训练后部署我的模型时,结果总是如下{'prob': array([[ 0.33333334, 0.33333334, 0.33333334]], dtype=float32)}

下面的代码,是我加载模型并输出概率向量的脚本。

import numpy as np
import matplotlib.pyplot as plt
import sys
import caffe
import cv2

MODEL_FILE ='deploy_ex0.prototxt'
PRETRAINED='snapshot_ex0_1_model_iter_40000.caffemodel'

caffe.set_mode_cpu()
net = caffe.Net(MODEL_FILE, PRETRAINED, caffe.TEST)

#preprocessing 

transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})

#mean substraction 

mean_file = np.array([104,117,123]) 
transformer.set_mean('data', mean_file)

transformer.set_transpose('data', (2,0,1))
transformer.set_channel_swap('data', (2,1,0))
transformer.set_raw_scale('data', 255.0)

#batch size 
net.blobs['data'].reshape(1,3,227,227)

#load image in data layer 

im=cv2.imread('test.jpg', cv2.IMREAD_COLOR)
img =cv2.resize(im, (227,227))

net.blobs['data'].data[...] = transformer.preprocess('data', img)

#compute 

out=net.forward()

print out

我想知道为什么我会得到这样的结果?你能帮我调试一下我的 CNN 吗?

另外,经过训练,我得到了这些结果

I0421 06:56:12.285953  2224 solver.cpp:317] Iteration 40000, loss = 5.06557e-05
I0421 06:56:12.286027  2224 solver.cpp:337] Iteration 40000, Testing net (#0)
I0421 06:58:32.159469  2224 solver.cpp:404]     Test net output #0: accuracy = 0.99898
I0421 06:58:32.159626  2224 solver.cpp:404]     Test net output #1: loss = 0.00183688 (* 1 = 0.00183688 loss)
I0421 06:58:32.159643  2224 solver.cpp:322] Optimization Done.
I0421 06:58:32.159654  2224 caffe.cpp:222] Optimization Done.

谢谢

5 月 11 日答复后编辑:

我使用了一个简单的模型 1 conv , 1 reul , 1 pool 和 2 全连接层。下面的代码是架构规范:

name:"CNN"
layer {
  name: "convnet"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    mirror:true
    crop_size:227
    mean_value:87.6231
    mean_value:87.6757

    mean_value:87.1677
    #mean_file:"/home/jaba/caffe/data/diota_model/mean.binaryproto"
  }
  data_param {
    source: "/home/jaba/caffe/data/diota_model/train_lmdb"
    batch_size: 32
    backend: LMDB
  }
}

layer {
  name: "convnet"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TEST
  }
  transform_param {
    mirror:true
    crop_size:227
    mean_value:87.6231
    mean_value:87.6757

    mean_value:87.1677
    #mean_file:"/home/jaba/caffe/data/diota_model/mean.binaryproto"
  }
  data_param {
    source: "/home/jaba/caffe/data/diota_model/val_lmdb"
    batch_size: 20
    backend: LMDB
  }
}

layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 20
    kernel_size: 5
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}

layer {
  name: "relu1"
  type: "ReLU"
  bottom: "conv1"
  top: "conv1"
}

layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 3
    stride: 2
  }
}

layer {
  name: "ip1"
  type: "InnerProduct"
  bottom: "pool1"
  top: "ip1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 300
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}

layer 
{
   name:"ip2"
   type:"InnerProduct"
   bottom:"ip1"
   top:"ip2"
   param
   {
    lr_mult:1
   }
   param
   {
    lr_mult:2
   }
   inner_product_param 
   {
    num_output: 3
        weight_filler {
          type: "xavier"
        }
        bias_filler {
          type: "constant"
        }
   }

}
layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "ip1"
  bottom: "label"
  top: "accuracy"
  include {
    phase: TEST
  }
}

layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "ip1"
  bottom: "label"
  top: "loss"
}

我对这个 CNN 进行了 22 个 epoch 的训练,准确率达到了 86%。对于我使用的求解器参数:

net: "/home/jaba/caffe/data/diota_model/simple_model/train_val.prototxt"
test_iter: 50
test_interval: 100
base_lr: 0.00001
momentum: 0.9
weight_decay: 0.0005
lr_policy: "inv"
gamma: 0.0001
power: 0.75
display: 100
max_iter: 3500
snapshot: 100
snapshot_prefix: "/home/jaba/caffe/data/diota_model/simple_model/snap_shot_model"
solver_mode: GPU

现在,当我部署模型时,它不会返回相同的概率向量。但是,有一个问题,当我加载模型并在validation_lmdb 文件夹上测试它时,我没有得到相同的准确度值,我得到了几乎56%。

我使用下面的脚本来计算准确性:

import os
import glob
#import cv2
import caffe
import lmdb
import numpy as np
from caffe.proto import caffe_pb2

MODEL_FILE ='deploy.prototxt'
PRETRAINED='snap_shot_model_iter_3500.caffemodel'

caffe.set_mode_cpu()
#load_model

net = caffe.Net(MODEL_FILE, PRETRAINED, caffe.TEST)

#load input and configure preprocessing



#mean_file = np.array([104,117,123])

transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
#transformer.set_mean('data', mean_file)
transformer.set_transpose('data', (2,0,1))
transformer.set_channel_swap('data', (2,1,0))
transformer.set_raw_scale('data', 255.0)


#fixing the batch size

net.blobs['data'].reshape(1,3,227,227)

lmdb_env=lmdb.open('/home/jaba/caffe/data/diota_model/val1_lmdb')

lmdb_txn=lmdb_env.begin()

lmdb_cursor=lmdb_txn.cursor()

datum=caffe_pb2.Datum()


correct_predictions=0

for key,value in lmdb_cursor:

    datum.ParseFromString(value)

    label=datum.label
    data=caffe.io.datum_to_array(datum)

    image=np.transpose(data,(1,2,0))


    net.blobs['data'].data[...]=transformer.preprocess('data',image)

    out=net.forward()
    out_put=out['prob'].argmax()
    if label==out_put:
    correct_predictions=correct_predictions+1



print 'accuracy :'
print correct_predictions/1002.0

我将数据集的大小更改为 1002 用于测试和 4998 用于学习。 你能给我一些解决问题的建议吗?

谢谢!

【问题讨论】:

  • 我非常希望这是一个错字:1000 的学习率是荒谬的。 :-)
  • 模型的批量大小是多少?另外,请发布一些输入数据的样本,或描述您的班级之间的差异;我们不会爬过 4600 张照片来查看 2 级的样子。
  • 您的测试图像类分布是什么?小损失表示它学到了一些东西。
  • 你可以检查 mean_file = np.array([104,117,123])
  • 当使用opencv加载图像时,图像加载BGR,因此尝试caffe.io.load_image并查看结果,如果使用opencv更改通道顺序时解决了

标签: python machine-learning computer-vision deep-learning caffe


【解决方案1】:

我认为我看到了两个不同的问题,不同形式的过拟合。 6580 张图片中有 85% 用于训练,其中 5593 张在训练中,987 张在测试中。

一个

40000 次迭代 * (256 图像/迭代) * (1 epoch/5593 图像) ~= 1831 epoch。 在 ILSVRC 数据集(128 万张图像)上,AlexNet 仅训练 40-50 个 epoch(取决于横向扩展)。 您的模型以实际损失为 0 结束,并且在整个测试集中只有 1 张照片错误。

两个

AlexNet 的宽度(每层过滤器)针对 ILSVRC 数据集的 1000 个类别和无数特征进行了调整。你还没有为你的数据缩小它。第 5 层扩展到 4096 个过滤器:每张图像几乎只有一个。 ILSVRC 训练 Alexnet 识别特征,例如猫科动物的脸、轮式车辆的一侧等 - 您的模型将训练识别深蓝色兰博基尼,从前方 30 度角、水平上方 8 度角和草地在背景中,在驾驶员一侧的背景中是一棵白杨树。

换句话说,您经过训练的 AlexNet 像浇注塑料外壳一样适合训练数据集。除了初始数据集之外,它不适合任何东西

我有点惊讶,它在其他汽车、其他汽缸盖和飞机部件上的表现并没有一点好。但是,我已经看到足够多的过拟合模型具有有效的随机输出。


首先,减少训练时间。其次,尝试减小每一层的 num_output 大小。


在 5 月 11 日 OP 的评论后编辑

是的,您必须减少每层中的内核/过滤器/输出的数量。尤其是第 5 层,有 4K 过滤器,这意味着网络可以为数据集中的每张照片分配几乎 1 个过滤器。这不利于有效的学习:您拥有 1000 多个过滤器,而不是少数几个学习垫圈特征的过滤器,每个过滤器都学习特定垫圈照片的一个非常具体的特征。

AlexNet、GoogleNet、ResNet、VGG 等都是针对静态图像在各种物体上的一般识别问题而构建和调整的。您当然可以使用一般概念,但它们不是用于解决更小和更好定义的问题的好拓扑。

【讨论】:

  • 我做了以下事情。我将数据集减少到 6000 张图像(5000 张用于训练,1000 张用于测试)。另外,我将全连接层 6 和全连接层 7 的 num_ouput 更改为 1000。我还更改了solver.prototxt
  • 您尚未完全描述更改,但这是一个开始。您仍然需要解决内层内核带宽的内部问题(上面的问题 TWO)。您仍在尝试使用大型拓扑解决一个小问题。
  • 很抱歉没有描述这个洞的事情。事实上,我将数据集减少到 6000(5000 用于训练,1000 用于测试)另外,我将 FC6、FC7 的 num_ouput 更改为 1000,batch_size 从 50,solver(test_iter:100;test_interval:500;max_iter:4000)。我得到了 92% 的准确率,问题是当我尝试部署模型时出现以下错误:无法从层 'fc8' 复制参数 0 权重;形状不匹配。源参数形状为 2 1000 (2000);目标参数形状为 3 1000 (3000)。要从头开始学习该层的参数,而不是从保存的网络中复制,请重命名该层
  • (1)请将突出信息编辑到原问题中; (2) 部署错误可能是一个单独的问题——您是否尝试过部署原始(非工作)模型? (3) 所以现在你只训练了 1 个 epoch??
  • (2) 我尝试部署原始模型,但对于我训练了 40 个 epoch 的第二个模型,它总是返回相同的概率向量 (3)
猜你喜欢
  • 2015-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-27
  • 1970-01-01
  • 1970-01-01
  • 2020-04-06
  • 2017-03-13
相关资源
最近更新 更多