caffe提供了很多深度学习网络,例如Lenet,Imagenet,Alenet.但是最重要的我们会利用这些网络训练自己的数据集以及调参数,甚至发明自己net.本篇博文主要是记录利用caffe中的Lenet训练kaggle中的手写体数据集.
mnist数据集
首先需要关注一下kaggle mnist数据比赛的数据格式信息:
kaggle 手写体比赛
大家可以从上面网站下载到本地,考虑到下载慢,这里百度云分享链接:
kaggle mnist百度云链接
Lenet数据处理和网络构建
为了与现有的caffe例子相融合,保存caffe源码的风格,有如下配置
数据
在caffe/data目录下新建文件夹kaggle_mnist,并且将下载好的train.csv,test.csv,保存在此.
训练文件
首先在caffe/examples目录下新建文件夹kaggle_mnist.
1.csv数据转HDF5
首先声明caffe不止可以接收HDF5数据,欲知更多,移步官网.
以下python脚本实现数据转换的功能,并按caffe example风格放置各个文件.该文件命名为create_mnist.py,放置在examples/kaggle_mnist文件夹下,这里提醒一下,训练只用到train.csv中的数据,代码中test准确的表达应该是validation.这里只是把train.csv中的数据分为两部分了 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 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| from __future__ import print_function import os import logging import numpy as np import pandas as pd import h5py DATA_ROOT = '../../data/kaggle_mnist' os.mkdir('mnist_train_hdf5') os.mkdir('mnist_test_hdf5') join = os.path.join TRAIN = join(DATA_ROOT, 'train.csv') DIR_TRAIN='mnist_train_hdf5' DIR_TEST='mnist_test_hdf5' train_file = join(DIR_TRAIN, 'mnist_train.h5') test_file = join(DIR_TEST, 'mnist_test.h5') train_file_txt = join(DIR_TRAIN, 'mnist_train.txt') test_file_txt = join(DIR_TEST, 'mnist_test.txt') logger = logging.getLogger() logger.setLevel(logging.DEBUG) sh = logging.StreamHandler() sh.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') sh.setFormatter(formatter) logger.addHandler(sh) logger.info('Load data from %s', TRAIN) df = pd.read_csv(TRAIN) data = df.values logger.info('Get %d Rows in dataset', len(data)) np.random.shuffle(data) labels = data[:, 0] images = data[:, 1:] images = images.reshape((len(images), 1, 28, 28)) images = images / 255. trainset = len(labels) * 3 / 4 labels_train = labels[:trainset] images_train = images[:trainset] labels_test = labels[trainset:] images_test = images[trainset:] if os.path.exists(train_file): os.remove(train_file) if os.path.exists(test_file): os.remove(test_file) logger.info('Write train dataset to %s', train_file) with h5py.File(train_file, 'w') as f: f['label'] = labels_train.astype(np.float32) f['data'] = images_train.astype(np.float32) train_file = join('examples/kaggle_mnist/', train_file) with open(train_file_txt, 'w') as f: print(train_file, file = f) logger.info('Write test dataset to %s', test_file) with h5py.File(test_file, 'w') as f: f['label'] = labels_test.astype(np.float32) f['data'] = images_test.astype(np.float32) test_file = join('examples/kaggle_mnist/', test_file) with open(test_file_txt, 'w') as f: print(test_file, file = f) logger.info('Done')
|
2.lenet网路配置
从/examples/mnist复制lenet_train_test.prototxt到/examples/kaggle_mnist,并修改数据层的内容,整个文件如下:
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 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
| name: "LeNet" layer { name: "mnist" type: "HDF5Data" top: "data" top: "label" include { phase: TRAIN } hdf5_data_param { source: "examples/kaggle_mnist/mnist_train_hdf5/mnist_train.txt" batch_size: 64 } } layer { name: "mnist" type: "HDF5Data" top: "data" top: "label" include { phase: TEST } hdf5_data_param { source: "examples/kaggle_mnist/mnist_test_hdf5/mnist_test.txt" batch_size: 100 } } 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: "pool1" type: "Pooling" bottom: "conv1" top: "pool1" pooling_param { pool: MAX kernel_size: 2 stride: 2 } } layer { name: "conv2" type: "Convolution" bottom: "pool1" top: "conv2" param { lr_mult: 1 } param { lr_mult: 2 } convolution_param { num_output: 50 kernel_size: 5 stride: 1 weight_filler { type: "xavier" } bias_filler { type: "constant" } } } layer { name: "pool2" type: "Pooling" bottom: "conv2" top: "pool2" pooling_param { pool: MAX kernel_size: 2 stride: 2 } } layer { name: "ip1" type: "InnerProduct" bottom: "pool2" top: "ip1" param { lr_mult: 1 } param { lr_mult: 2 } inner_product_param { num_output: 500 weight_filler { type: "xavier" } bias_filler { type: "constant" } } } layer { name: "relu1" type: "ReLU" bottom: "ip1" top: "ip1" } layer { name: "ip2" type: "InnerProduct" bottom: "ip1" top: "ip2" param { lr_mult: 1 } param { lr_mult: 2 } inner_product_param { num_output: 10 weight_filler { type: "xavier" } bias_filler { type: "constant" } } } layer { name: "accuracy" type: "Accuracy" bottom: "ip2" bottom: "label" top: "accuracy" include { phase: TEST } } layer { name: "loss" type: "SoftmaxWithLoss" bottom: "ip2" bottom: "label" top: "loss" }
|
3.solver配置
同样从/examples/mnist复制到lenet_solver.prototxt到/examples/kaggle_mnist,只要将net处修改即可,所有类容如下:
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
| # The train/test net protocol buffer definition net: "examples/kaggle_mnist/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: 100 # 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.01 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 # The maximum number of iterations max_iter: 10000 # snapshot intermediate results snapshot: 5000 snapshot_prefix: "examples/kaggle_mnist/lenet" # solver mode: CPU or GPU solver_mode: CPU
|
4.训练文件
在examples/kaggle_mnist下新建train_lenet.sh,内容如下:
1 2 3 4
| #!/usr/bin/env sh set -e ./build/tools/caffe train -solver=examples/kaggle_mnist/lenet_solver.prototxt -weights examples/mnist/lenet_iter_10000.caffemodel $@
|
值得注意的是,这里其实是在fine tunning,因为这里用到了caffe自带mnist训练出来的模型,也就是这一句:
1
| -weights examples/mnist/lenet_iter_10000.caffemodel
|
Lenet训练
这一步很简单,只要在caffe根目录下执行:
1
| ./examples/kaggle_mnist/train_lenet.sh
|
我的机器大概用了10分钟,最后就出来带.caffemodel后缀的model.
kaggle数据测试
为了上传数据到kaggle,我们必须用最后训练出来的model预测一下test.csv中的数据.这里用caffe的python接口做的预测,完整的代码如下:
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 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
| import os import logging import numpy as np import pandas as pd import caffe DATA_ROOT = '../../data/kaggle_mnist' MODEL_ROOT = './' join = os.path.join TEST = join(DATA_ROOT, 'test.csv') OUTPUT = join(DATA_ROOT, 'result.csv') CAFFE_MODEL = join(MODEL_ROOT, 'lenet_iter_10000.caffemodel') CAFFE_SOLVER = join(MODEL_ROOT, 'deploy.prototxt') logger = logging.getLogger() logger.setLevel(logging.DEBUG) sh = logging.StreamHandler() sh.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') sh.setFormatter(formatter) logger.addHandler(sh) logger.info('Load test dataset from %s', TEST) df = pd.read_csv(TEST) data = df.values data = data.reshape((len(data), 28, 28, 1)) data = data / 255. net = caffe.Classifier(CAFFE_SOLVER, CAFFE_MODEL) logger.info('Start predict') BATCH_SIZE = 100 iter_k = 0 labels = [] while True: logger.info('ITER %d', iter_k) batch = data[iter_k*BATCH_SIZE: (iter_k+1)*BATCH_SIZE] if batch.size == 0: break result = net.predict(batch) for label in np.argmax(result, 1): labels.append(label) iter_k = iter_k + 1 logger.info('Prediction Done') 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')
|
最后出来的预测结果保存在caffe/data/kaggle_mnist/result.csv中,只要将该文件上传到kaggle上就可以知道你的预测的准确率了.