用Caffe+python如何训练一个手写体数字数别模型

1.train.csv数据转化为lmdb格式存储

Panda读取数据,由于.csv内的数据是以字符串形式存储,因此在读取完所有数据后,还需要将读取的数据转换成uint8形式,此时刚好可以存放一个像素值。具体操作如下:

np.fromstring(data, dtype=np.uint8)

然后从数据中分别提取图像信息和对应的标签信息

labels = data[:, 0]
images = data[:, 1:]

将images转换成batch_size*channel*height*width形式

images = images.reshape((len(images), 1, 28, 28))
将数据分成训练集和验证集,训练集用来训练模型,验证集用来验证模型的正确性。打开lmdb数据库lmdb_env,并且获取数据库操作的句柄lmdv_txn,同时生成一个Datum数据项datum ,后面要用datum 来整合数据和标签信息。

lmdb_env = lmdb.open(train_file, map_size=int(1e12))
lmdb_txn = lmdb_env.begin(write=True)
datum = caffe_pb2.Datum()
将每一个图像数据和标签信息通过上面的datum整合为一个数据项;用于lmdb中的每个数据项都是由键值对构成,因此生成一个用递增顺序排列的定长的唯一的key值keystr;然后再通过lmdb数据库操作句柄将datum和对应的key值keystr暂时存放到内存。

datum = caffe.io.array_to_datum(images_train[x], labels_train[x])
keystr = '{:0>8d}'.format(item_id)
lmdb_txn.put( keystr, datum.SerializeToString() )
在进行完上面的操作后,最后还需要将存放到内存的数据写到磁盘,即将数据写到lmdb数据库文件中,才能将转化后的数据保存。如果是一条一条数据的处理,则速度就会很慢,所以采用批处理的方式,这里设置的是没batch_size=1000时,才进行一次写入磁盘操作;由于在写入磁盘操作完成后,lmdb数据库操作句柄就失效,因此需要重新生成一个数据库操作句柄。

lmdb_txn.commit()
lmdb_txn = lmdb_env.begin(write=True)
所有出具均处理完后,还要进行数据库关闭操作。否则如果后面,还有对其它数据文件的读写操作,则会打开新的数据库文件失败。

lmdb_env.close()
2.训练模型

模型就直接使用caffe中提供的LeNet网络模型,不过网络定义中的源文件路径就要改成自己的lmdb数据库文件路径。

3.使用test.csv测试模型

test.csv读取数据的操作和从train.csv读取数据的操作一样,只不过现在不用进行提取标签的操作。将读取后的数据转换成特定格式。

data = data.reshape((len(data), 28, 28, 1))
此时还需要先对数据做归一化处理,否则后面预测的时候会报错。由于每个像素点的值都是从0~255,所以操作如下。

data = data / 255.
然后就是构建网络模型,并导入网络参数。

net = caffe.Classifier(CAFFE_SOLVER, CAFFE_MODEL)
预测部分:

iter_k = 0
labels = []
while True:
    result = net.predict([data[iter_k]])
    labels.append(result[0].argmax())
    iter_k = iter_k + 1
    if iter_k == testNum:
        Break
结果输出到result.csv

logger.info('Save result to %s', OUTPUT)
if os.path.exists(OUTPUT):
    os.remove(OUTPUT)
 
with open(OUTPUT, 'w') as fd:
    fd.write('ImageId,Label\n')
    for idx, label in enumerate(labels):
        fd.write(str(idx+1))
        fd.write(',')
        fd.write(str(label))
        fd.write('\n')
在测试的时候,网络的定义部分需要一些改动。网络最开始的两层“TRAIN”和“TEST”注释掉,然后添加一层输入层,用来输入测试数据,如下:

layer{
name: "data"
type: "Input"
top: "data"
input_param{shape: {dim:1 dim:1 dim:28 dim:28}}
}
再转到网络最后两部分,将训练时用来计算softmax分类损失和用验证集测试网络模型时计算准确率这两层注释掉,然后再加入一层softmax层,这是用来直接将预测结果输出的。

layer{
name: "prob"
type: "Softmax"
bottom: "ip2"
top: "prob"
}


 

你可能感兴趣的:(Caffe,Deep,Learning)