接上回制作lmdb开始,我们把数据都分好了,现在开始制作lmdb即可。
首先制作train.txt 和 val.txt,参照教程深度学习caffe平台–制作自己.lmdb格式数据集及分类标签文件
制作数据集和标签
# coding=utf-8
def checkDir(dirName):
import os
if os.path.exists(dirName) == False:
os.mkdir(dirName)
def checkFile(dirFile):
import os
if os.path.exists(dirFile) == True:
os.remove(dirFile)
# copy form fileName to copyName
def copy(fileName, copyName):
f = open(fileName, 'rb')
checkFile(copyName)
c = open(copyName, 'wb')
line = f.read(8196)
while line:
c.write(line)
line = f.read(8196)
f.close()
c.close()
n = [0 for x in range(0, 10)];
def makeTrain(numberArray):
import random
import os
checkDir('mnist_test/train')
for i in range(0, 10):
checkDir('mnist_test/train/%d' % i)
for i in range(0, 5000):
number = random.choice(numberArray)
fileName = '%d/train_%d.bmp' % (number, n[number])
if os.path.exists('./mnist_test/%s' % fileName):
copy('./mnist_test/%s' % fileName, './mnist_test/train/%s' % fileName)
n[number] += 1;
def makeVal(numberArray):
import random
import os
checkDir('mnist_test/val')
for i in range(0, 10):
checkDir('mnist_test/val/%d' % i)
for i in range(0, 5000):
number = random.choice(numberArray)
fileName = '%d/train_%d.bmp' % (number, n[number])
if os.path.exists('./mnist_test/%s' % fileName):
copy('./mnist_test/%s' % fileName, './mnist_test/val/%s' % fileName)
n[number] += 1;
def makeTrainTxT(numberArray):
import os
n = []
for i in range(0, 10):
n.append(os.listdir('./mnist_test/train/%d' % i))
checkFile('./mnist_test/train.txt')
f = open('./mnist_test/train.txt', 'wb')
import random
m = numberArray
while len(m) != 0:
number = random.choice(m)
i = m.index(number)
f.write('train/%d/%s %d\n' % (number, n[number][0], number))
del n[number][0]
if len(n[number]) == 1:
del m[i]
f.close()
def makeValTxT(numberArray):
import os
n = []
for i in range(0, 10):
n.append(os.listdir('./mnist_test/val/%d' % i))
checkFile('./mnist_test/val.txt')
f = open('./mnist_test/val.txt', 'wb')
import random
m = numberArray
while len(m) != 0:
number = random.choice(m)
i = m.index(number)
f.write('val/%d/%s %d\n' % (number, n[number][0], number))
del n[number][0]
if len(n[number]) == 1:
del m[i]
f.close()
m = [0, 1, 2]
makeTrain(m)
m = [0, 1, 2]
makeVal(m)
m = [0, 1, 2]
makeTrainTxT(m)
m = [0, 1, 2]
makeValTxT(m)
运行完可以使用tree看看(也可以用可视化的看)。
tree ./train
可以看到只有0, 1, 2文件夹里有图片,其他的都没有。
运行create_imagenet
接着将caffe/examples/imagenet/create_imagenet.sh移动到mnist_test目录下
cp ../examples/imagenet/create_imagenet.sh ./create_imagenet.sh
我的目录结构如下:
接着编辑create_imagenet.sh
sudo vim ./create_imagenet.sh
编辑成如下形式
#!/usr/bin/env sh
# Create the imagenet lmdb inputs
# N.B. set the path to the imagenet train + val data dirs
set -e
EXAMPLE=./ # 当前目录,就是lmdb要在哪里
DATA=./ # txt文件放在哪里
TOOLS=../caffe/build/tools
TRAIN_DATA_ROOT=./ # 就是train.txt表中的路径的根目录
VAL_DATA_ROOT=./ # 就是val.txt表中的路径的根目录
# Set RESIZE=true to resize the images to 256x256. Leave as false if images have
# already been resized using another tool.
RESIZE=false
if $RESIZE; then
RESIZE_HEIGHT=256
RESIZE_WIDTH=256
else
RESIZE_HEIGHT=0
RESIZE_WIDTH=0
fi
if [ ! -d "$TRAIN_DATA_ROOT" ]; then
echo "Error: TRAIN_DATA_ROOT is not a path to a directory: $TRAIN_DATA_ROOT"
echo "Set the TRAIN_DATA_ROOT variable in create_imagenet.sh to the path" \
"where the ImageNet training data is stored."
exit 1
fi
if [ ! -d "$VAL_DATA_ROOT" ]; then
echo "Error: VAL_DATA_ROOT is not a path to a directory: $VAL_DATA_ROOT"
echo "Set the VAL_DATA_ROOT variable in create_imagenet.sh to the path" \
"where the ImageNet validation data is stored."
exit 1
fi
echo "Creating train lmdb..."
# 删除上一次残留的文件
rm -rf $EXAMPLE/train_lmdb
rm -rf $EXAMPLE/val_lmdb
# 这里一定要加上-gray=true
GLOG_logtostderr=1 $TOOLS/convert_imageset -gray=true \
--resize_height=$RESIZE_HEIGHT \
--resize_width=$RESIZE_WIDTH \
--shuffle \
$TRAIN_DATA_ROOT \
$DATA/train.txt \ # 这里是train.txt的名字
$EXAMPLE/train_lmdb # 这里是生成的名字,根据上面删除的进行更改即可
echo "Creating val lmdb..."
# 这里一定要加上-gray=true
GLOG_logtostderr=1 $TOOLS/convert_imageset -gray=true \
--resize_height=$RESIZE_HEIGHT \
--resize_width=$RESIZE_WIDTH \
--shuffle \
$VAL_DATA_ROOT \
$DATA/val.txt \ # 这里是val.txt的名字
$EXAMPLE/val_lmdb # 这里是生成的名字,根据上面删除的进行更改即可
echo "Done."
保存后运行
./create_imagenet.sh
使用caffe的convert_imageset生成lmdb文件
训练
首先,我们需要把训练用的网格(lenet_train_test.prototxt)、运行参数(lenet_solver.prototxt)、运行脚本(train_lenet.sh)复制过来。
具体复制过程就不讲了,很简单。
主要我们需要改这三个文件的内容,与我们训练的数据集进行配对。
lenet_train_test.prototxt,只需要更改Data就行。
layer {
name: "mnist"
type: "Data" # 数据
top: "data"
top: "label"
include {
phase: TRAIN # 用于Train阶段
}
transform_param {
scale: 0.00390625
}
data_param {
source: "train_lmdb" # 这里需要些lmdb文件夹路径,在哪里运行就怎么写,这里的当前路径运行,所以直接写名字即可
batch_size: 64 # 一次用多少个
backend: LMDB # 什么格式的数据(后缀)
}
}
layer {
name: "mnist"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param {
scale: 0.00390625
}
data_param {
source: "val_lmdb" # 这里需要些lmdb文件夹路径,在哪里运行就怎么写
batch_size: 64 # 一次用多少个
backend: LMDB # 什么格式的数据(后缀)
}
}
lenet_solver.prototxt
# The train/test net protocol buffer definition
net: "lenet_train_test.prototxt" # 网格信息在哪里就写上面
# test_iter specifies how many forward passes the test should carry out.
# In the case of MNIST, we have test batch size 100 and 100 test iterations,
# covering the full 10,000 testing images.
test_iter: 30 # 测试阶段迭代次数
# Carry out testing every 500 training iterations.
test_interval: 500 # 每迭代多少次进行测试
# The base learning rate, momentum and the weight decay of the network.
base_lr: 0.001 # 学习速率
momentum: 0.9
weight_decay: 0.0005
# The learning rate policy
lr_policy: "inv"
gamma: 0.0001
power: 0.75
# Display every 100 iterations
display: 100 # 每次迭代100次输出信息
# The maximum number of iterations
max_iter: 200 # 迭代多少次
# snapshot intermediate results
snapshot: 5000 # 迭代5000次弄一次快照
snapshot_prefix: "lenet" # 结果出来的路径和名字
# solver mode: CPU or GPU
solver_mode: CPU
train_lenet.sh
#!/usr/bin/env sh
set -e
../caffe/build/tools/caffe train --solver=./lenet_solver.prototxt $@
# 这里只需要找到caffe路径即可。
运行即可。
./train_lenet.sh
测试一下
../caffe/build/tools/caffe test -model ./lenet_train_test.prototxt -weights ./lenet_iter_200.caffemodel -iterations 10
ok, 成功了,记住这个数据集里没有3,我们拿具体图片进行测试一下。
# coding=utf-8
def getNumber(IMAGE_FILE, flag):
import os
import sys
import Image
import numpy as np
from scipy.misc import imread, imresize
import matplotlib.pyplot as plt
caffe_root = './caffe/'
sys.path.insert(0, caffe_root + "python")
import caffe
MODEL_FILE = './mnist_test/lenet.prototxt' # 网络信息
PRETRAINED = './mnist_test/lenet_iter_200.caffemodel' # 训练后的结果
input_image = caffe.io.load_image(IMAGE_FILE, color=False)
net = caffe.Classifier(MODEL_FILE, PRETRAINED, raw_scale=255, image_dims=(28, 28)) # 载入分类器
prediction = net.predict([input_image]) # 对图片进行预测,分类
caffe.set_mode_cpu() # 使用CPU模式
if (flag):
img = imread(IMAGE_FILE)
plt.imshow(img)
plt.title(prediction[0].argmax())
plt.show()
return prediction[0].argmax()
print(getNumber('./mnist_test/2/train_1.bmp', True))
试试看数字3,即没有学习的数字
接下来进行Fine-tuning,加入3试试看。
利用上面的,制作0, 1, 2, 3的lmdb。
m = [0, 1, 2, 3]
makeTrain(m)
m = [0, 1, 2, 3]
makeVal(m)
m = [0, 1, 2, 3]
makeTrainTxT(m)
m = [0, 1, 2, 3]
makeValTxT(m)
接着执行,也可以修稿lenet_solver.prototxt的相关属性,我这里之前那个是迭代500次,这次是迭代200次
sudo ./create_imagenet.sh
sudo ../caffe/build/tools/caffe train --solver ./lenet_solver.prototxt --weights ./lenet_iter_500.caffemodel
测试函数跟上面的一样,只需要改点东西即可。