如何利用自己的数据训练一个分类网络
从零开始学会如何利用自己的数据训练一个分类网络
1、准备训练数据和测试数据
下载地址如下:
animal:
http://www.robots.ox.ac.uk/~vgg/data/pets/
flower:
http://www.robots.ox.ac.uk/~vgg/data/flowers/
plane:
http://www.robots.ox.ac.uk/~vgg/data/airplanes_side/airplanes_side.tar
house:
http://www.robots.ox.ac.uk/~vgg/data/houses/houses.tar
guitar:
http://www.robots.ox.ac.uk/~vgg/data/guitars/guitars.tar
数据文档结构如下:
1 |
|
数量:以花为例,800+的图片,测试300+,训练500张。在剩下的不包含在test和train的图片中,每一类选择2张,共计10张图片作为demon测试图片。
2、制作标签
格式:文件路径+标签
代码如下,注意修改路径: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30import os
#定义Caffe根目录
caffe_root = 'E:/Caffe-windows/caffe-windows/'
#制作训练标签数据
i = 0 #标签
with open(caffe_root + 'models/my_models_recognition/labels/train.txt','w') as train_txt:
for root,dirs,files in os.walk(caffe_root+'models/my_models_recognition/data/train/'): #遍历文件夹
for dir in dirs:
for root,dirs,files in os.walk(caffe_root+'models/my_models_recognition/data/train/'+str(dir)): #遍历每一个文件夹中的文件
for file in files:
image_file = str(dir) + '\\' + str(file)
label = image_file + ' ' + str(i) + '\n' #文件路径+空格+标签编号+换行
train_txt.writelines(label) #写入标签文件中
i+=1 #编号加1
#制作测试标签数据
i=0 #标签
with open(caffe_root + 'models/my_models_recognition/labels/test.txt','w') as test_txt:
for root,dirs,files in os.walk(caffe_root+'models/my_models_recognition/data/test/'): #遍历文件夹
for dir in dirs:
for root,dirs,files in os.walk(caffe_root+'models/my_models_recognition/data/test/'+str(dir)): #遍历每一个文件夹中的文件
for file in files:
image_file = str(dir) + '\\' + str(file)
label = image_file + ' ' + str(i) + '\n' #文件路径+空格+标签编号+换行
test_txt.writelines(label) #写入标签文件中
i+=1#编号加1
print "成功生成文件列表"
3、数据转换,将图片转为LMDB格式
参考这个博客
代码如下: 1
2
3
4
5
6
7
8
9# convert_imageset路径
# 重新修改图片的分辨率位256\*256
# 打乱图片顺序shuffle
# 设置转换为lmdb格式
# 图片路径
# 图片标签
# lmdb文件的输出路径
./build/tools/convert_imageset --resize_height=256 --resize_width=256 --shuffle --backend="lmdb" models/classification_CNN/data/train models/classification_CNN/dlabels/train.txt models/classification_CNN/lmdb/train
4、修改网络模型文件
- 修改均值文件使用方法,不使用均值文件,使用通用均值文件
1
2
3
4
5
6
7
8
9
10
11
12
13# transform_param {
# mirror: true
# crop_size: 227
# mean_file: "data/ilsvrc12/imagenet_mean.binaryproto"
# }
# mean pixel / channel-wise mean instead of mean image
transform_param {
crop_size: 227 # 传入的图片是256*256,现在在其中框出一个227*227的小图片 以此来增大训练集
mean_value: 104 # 通用均值
mean_value: 117
mean_value: 123
mirror: true # 镜像操作 扩大数据集
} - 修改数据输入层的数据来源路径以及batch_size,需要适当调小一点。
1
2
3
4
5data_param {
source: "/home/weijian/caffe/models/classification_CNN/lmdb/train"
batch_size: 100
backend: LMDB
} - 修改中间fc6、fc7这两个全连接层的特征平面数量为512,原来的4000+的特征平面数量会造成过拟合。
1 |
|
- 修改最后一个全连接层的输出为5种类型,因为设置了house、flower、animal、guitar、plane五种数据。
1 |
|
5、修改超参数文件
- 修改net(网络结构文件的位置)
1 |
|
- 修改test_iter(在测试的时候,需要迭代的次数。) test_iter = 测试图片的数量 / Test layer的batch_size
1
test_iter: 30 # 测试集一共1500张图片,Test layer的batch_size是50,则在测试的时候,需要迭代30次,即每30次完成一次对所有测试集的测试。
- 修改test_interval(每训练多少次,开始一次测试。) test_interval = 训练图片数量 / Train layer的batch_siz
1
test_interval: 250 # 一共2500张训练图片,Train_layer的batch_size是100,则每250次iterration完成一次对所有训练图片的测试。实际上,也可以随便设置,200,210都可以。
- 修改训练策略参数stepsize、max_iter、snapshot、snapshot_prefix
1
2
3
4
5
6
7
8
9
10lr_policy: "step"
gamma: 0.1
stepsize: 1000
display: 50
max_iter: 10000
momentum: 0.9
weight_decay: 0.0005
snapshot: 5000
snapshot_prefix: "/home/weijian/caffe/models/classification_CNN/caffenet_train"
solver_mode: GPU
6、训练模型
vim train.sh 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#!/usr/bin/env sh
set -e
log_path="logs/"
mkdir -p $log_path
save_model_path="caffemodel/"
mkdir -p $save_model_path
# training log
file_prefix="classification_CNN"
log_file=$(date -d "today" +"%Y-%m-%d-%H:%M:%S")
log_file=$log_path$file_prefix$log_file".log"
# caffe execute file path
caffe_bin="/home/weijian/caffe/build/tools/caffe"
# trainning
# $caffe_bin train --solver=solver.prototxt 2>&1 | tee -a $log_file
$caffe_bin train --solver=solver.prototxt 2>&1 | tee ./logs/classification_CNN.log
7、测试模型
按照labels中的test.txt和train.txt的图片分类规则在labels文件夹中编辑label.txt,在test.txt和train.txt中,animal是0,guitar是1,以此类推,得到label.txt如下所示: 1
2
3
4
5animal
guitar
flower
house
plane1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63import caffe
import numpy as np
import matplotlib.pyplot as plt
import os
import PIL
from PIL import Image
import sys
#定义Caffe根目录
caffe_root = '/home/weijian/caffe/'
#网络结构描述文件
deploy_file = caffe_root+'models/classification_CNN/deploy.prototxt'
#训练好的模型
model_file = caffe_root+'models/classification_CNN/caffenet_train/solver_iter_10000.caffemodel'
#gpu模式
caffe.set_device(0) # 如果你有多个GPU,那么选择第一个
caffe.set_mode_gpu()
# caffe.set_mode_gpu()
#定义网络模型
net = caffe.Classifier(deploy_file, #调用deploy文件
model_file, #调用模型文件
channel_swap=(2,1,0), #caffe中图片是BGR格式,而原始格式是RGB,所以要转化
raw_scale=255, #python中将图片存储为[0, 1],而caffe中将图片存储为[0, 255],所以需要一个转换
image_dims=(227, 227)) #输入模型的图片要是227*227的图片
#分类标签文件
imagenet_labels_filename = caffe_root +'models/classification_CNN/labels/label.txt'
#载入分类标签文件
labels = np.loadtxt(imagenet_labels_filename, str)
#对目标路径中的图像,遍历并分类
for root,dirs,files in os.walk(caffe_root+'models/classification_CNN/demo_test_image/'):
for file in files:
#加载要分类的图片
image_file = os.path.join(root,file)
input_image = caffe.io.load_image(image_file)
#打印图片路径及名称
image_path = os.path.join(root,file)
print(image_path)
#显示图片
img=Image.open(image_path)
plt.imshow(img)
plt.axis('off')
plt.show()
#预测图片类别
prediction = net.predict([input_image])
print 'predicted class:',prediction[0].argmax()
# 输出概率最大的前5个预测结果
top_k = prediction[0].argsort()[::-1]
for node_id in top_k:
#获取分类名称
human_string = labels[node_id]
#获取该分类的置信度
score = prediction[0][node_id]
print('%s (score = %.5f)' % (human_string, score))
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!