为什么我的 CNN returns 总是一样的结果?
Why my CNN returns always the same result?
我正在尝试构建一个 CNN,将对象分为 3 个主要 classes.The 三个对象,包括兰博基尼、汽缸盖和一架飞机。我的数据集由 6580 张图片组成,每个 class.You 几乎有 2200 张图片可以在 google 驱动器 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 fully connected layers.. 下面的代码是架构规范:
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
现在,当我部署模型时,它不会 return 相同的概率向量。但是,有一个问题,当我加载模型并在 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用于学习。
你能给我一些解决问题的建议吗?
谢谢!
我想我看到了两个截然不同的问题,不同形式的过拟合。 6580 张图像中有 85% 用于训练,您有 5593 张用于训练,987 张用于测试。
一个
40000 次迭代 * (256 images/iteration) * (1 epoch/5593 图像) ~= 1831 个时期。
在 ILSVRC 数据集(1.28M 图像)上,AlexNet 仅训练 40-50 个时期(取决于横向扩展)。
您的模型最终损失为 0,并且在整个测试集中只有 1 张照片出错。
两个
AlexNet 的宽度(每层过滤器)针对 ILSVRC 数据集的 1000 类 和无数特征进行了调整。你还没有为你的数据缩小它。第 5 层扩展到 4096 个过滤器:几乎每个图像一个。 ILSVRC 训练 Alexnet 识别诸如猫脸、轮式车辆的一侧等特征的地方——你的模型将训练以从前方 30 度角、高于水平面 8 度、有草的角度识别深蓝色兰博基尼在背景中,在驾驶员侧的背景中是一棵白杨树。
换句话说,您经过训练的 AlexNet 像浇注塑料一样适合训练数据集 shell。它不会适合 任何东西 除了初始数据集。
我有点惊讶它在其他汽车、其他气缸盖和飞机零件上的表现并没有 一点点。但是,我已经看到足够多的过度拟合模型具有有效的随机输出。
首先,减少训练时长。其次,尝试减少每层的 num_output 大小。
在 OP 的评论后编辑 5 月 11 日
是的,你必须减少每一层的kernels/filters/outputs个数。第 5 层尤其具有 4K 滤镜,这意味着网络可以为数据集中的每张照片分配近 1 个滤镜。这不会带来有效的学习:您拥有 1000 多个过滤器,而不是学习垫圈特征的少量过滤器,每个过滤器学习特定垫圈照片的一个非常具体的特征。
AlexNet、GoogleNet、ResNet、VGG 等都是针对静态图像在各种对象上的一般辨别问题而构建和调整的。您当然可以使用一般概念,但它们 不是 好的拓扑结构,无法用于更小且定义更明确的问题。
我正在尝试构建一个 CNN,将对象分为 3 个主要 classes.The 三个对象,包括兰博基尼、汽缸盖和一架飞机。我的数据集由 6580 张图片组成,每个 class.You 几乎有 2200 张图片可以在 google 驱动器 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 fully connected layers.. 下面的代码是架构规范:
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
现在,当我部署模型时,它不会 return 相同的概率向量。但是,有一个问题,当我加载模型并在 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用于学习。 你能给我一些解决问题的建议吗?
谢谢!
我想我看到了两个截然不同的问题,不同形式的过拟合。 6580 张图像中有 85% 用于训练,您有 5593 张用于训练,987 张用于测试。
一个
40000 次迭代 * (256 images/iteration) * (1 epoch/5593 图像) ~= 1831 个时期。 在 ILSVRC 数据集(1.28M 图像)上,AlexNet 仅训练 40-50 个时期(取决于横向扩展)。 您的模型最终损失为 0,并且在整个测试集中只有 1 张照片出错。
两个
AlexNet 的宽度(每层过滤器)针对 ILSVRC 数据集的 1000 类 和无数特征进行了调整。你还没有为你的数据缩小它。第 5 层扩展到 4096 个过滤器:几乎每个图像一个。 ILSVRC 训练 Alexnet 识别诸如猫脸、轮式车辆的一侧等特征的地方——你的模型将训练以从前方 30 度角、高于水平面 8 度、有草的角度识别深蓝色兰博基尼在背景中,在驾驶员侧的背景中是一棵白杨树。
换句话说,您经过训练的 AlexNet 像浇注塑料一样适合训练数据集 shell。它不会适合 任何东西 除了初始数据集。
我有点惊讶它在其他汽车、其他气缸盖和飞机零件上的表现并没有 一点点。但是,我已经看到足够多的过度拟合模型具有有效的随机输出。
首先,减少训练时长。其次,尝试减少每层的 num_output 大小。
在 OP 的评论后编辑 5 月 11 日
是的,你必须减少每一层的kernels/filters/outputs个数。第 5 层尤其具有 4K 滤镜,这意味着网络可以为数据集中的每张照片分配近 1 个滤镜。这不会带来有效的学习:您拥有 1000 多个过滤器,而不是学习垫圈特征的少量过滤器,每个过滤器学习特定垫圈照片的一个非常具体的特征。
AlexNet、GoogleNet、ResNet、VGG 等都是针对静态图像在各种对象上的一般辨别问题而构建和调整的。您当然可以使用一般概念,但它们 不是 好的拓扑结构,无法用于更小且定义更明确的问题。