Skip to content

Instantly share code, notes, and snippets.

@yaofahua
Created September 5, 2022 07:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yaofahua/b39b897c8e0f267d7739d6edfa04b7a6 to your computer and use it in GitHub Desktop.
Save yaofahua/b39b897c8e0f267d7739d6edfa04b7a6 to your computer and use it in GitHub Desktop.
Caffe训练MNIST #Caffe #MNIST

Train and Use LeNet on MNIST dataset with docker Caffe

创建cpu版本的docker caffe

docker run -v /root/data:/root/data --name caffe --hostname caffe rastasheep/ubuntu-sshd:18.04
docker exec -it caffe /bin/bash
更改ubuntu软件包源
apt install caffe-cpu

Train LeNet

创建工作目录

 docker exec -it caffe /bin/bash
 mkdir -p /root/data/caffe/mnist
 cd /root/data/caffe/mnist

下载MNIST图片 (都是手写的数字)

 wget --no-check-certificate <nowiki>http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz</nowiki> <nowiki>http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz</nowiki> <nowiki>http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz</nowiki> <nowiki>http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz</nowiki> 
 gunzip train-images-idx3-ubyte.gz train-labels-idx1-ubyte.gz t10k-images-idx3-ubyte.gz t10k-labels-idx1-ubyte.gz 

创建caffe能够识别的lmdb数据库

 convert_mnist_data ./train-images-idx3-ubyte ./train-labels-idx1-ubyte ./mnist_train_lmdb --backend=lmdb
 convert_mnist_data ./t10k-images-idx3-ubyte ./t10k-labels-idx1-ubyte ./mnist_test_lmdb --backend=lmdb

下载lenet神经网络定义文件和solver文件并修改路径

 # 下载
 wget <nowiki>https://www.3531563811.site/code/caffe-master/examples/mnist/lenet_train_test.prototxt</nowiki>
 wget <nowiki>https://www.3531563811.site/code/caffe-master/examples/mnist/lenet_solver.prototxt</nowiki>
  
 # 修改lenet神经网络定义文件中的lmdb路径
 sed -i 's/examples\/mnist\/mnist_train_lmdb/.\/mnist_train_lmdb/gi' lenet_train_test.prototxt
 sed -i 's/examples\/mnist\/mnist_test_lmdb/.\/mnist_test_lmdb/gi' lenet_train_test.prototxt
  
 # 修改solver文件中神经网络文件路径、生成的caffemodel文件路径、solver模式改为cpu
 sed -i 's/examples\/mnist\/lenet_train_test.prototxt/.\/lenet_train_test.prototxt/gi' lenet_solver.prototxt
 sed -i 's/examples\/mnist\/lenet/.\/lenet/gi' lenet_solver.prototxt
 sed -i 's/solver_mode: GPU/solver_mode: CPU/gi' lenet_solver.prototxt

正式开始train

 nohup caffe train --solver=./lenet_solver.prototxt 2>&1 > caffe_train_mnist_log.txt &

train结果(caffe model文件)

 root@stock:~/data/caffe/mnist# ll -h ./lenet_iter_10000.caffemodel
 -rw-r--r-- 1 root root 1.7M May  3 22:38 ./lenet_iter_10000.caffemodel

train日志

 https://www.3531563811.site/files/caffe_train_mnist_log.txt

其它:lenet_solver.prototxt文件内容

 # The train/test net protocol buffer definition
 net: "examples/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/mnist/lenet"
 # solver mode: CPU or GPU
 solver_mode: GPU

其它:lenet_train_test.prototxt文件内容 (Lenet网络定义文件)

 name: "LeNet"
 layer {
   name: "mnist"
   type: "Data"
   top: "data"
   top: "label"
   include {
     phase: TRAIN
   }
   transform_param {
     scale: 0.00390625
   }
   data_param {
     source: "examples/mnist/mnist_train_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: "examples/mnist/mnist_test_lmdb"
     batch_size: 100
     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: "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"
 }

参考

Use LeNet

训练生成的examples/mnist/lenet_iter_10000.caffemodel文件不能直接使用,需要做一定的修改(主要是修改数据输入和数据输出层的定义)。

 cd /root/data/caffe/mnist
 cp lenet_train_test.prototxt deploy.prototxt
 cp lenet_iter_10000.caffemodel deploy.caffemodel

根据https://github.com/BVLC/caffe/wiki/Using-a-Trained-Network:-Deploy#deploying-this-network提到的方法,修改deploy.prototxt文件,修改后的内容如下

 name: "LeNet"
 layer {
     name: "data"
     type: "Input"
     top: "data"
     input_param { shape: { dim: 1 dim: 1 dim: 28 dim: 28 } }
 }
 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: "loss"
   type: "Softmax"
   bottom: "ip2"
   top: "loss"
 }

直观图:https://www.3531563811.site/files/deploy.prototxt_20200508.png

测试

数字2:https://www.3531563811.site/files/handwrite_letter_2_28x28.png

字母k:https://www.3531563811.site/files/handwrite_letter_k_28x28.png

http://3531563811.site:31188/lab/tree/root/data/src/ipynb/mnist_handwrite_number.ipynb

 import caffe
 import skimage
 
 # model and weights files
 model = '/root/data/caffe/mnist/deploy.prototxt'
 weights = '/root/data/caffe/mnist/deploy.caffemodel'
 
 # create caffe net
 caffe.set_mode_cpu()
 net = caffe.Net(model, weights, caffe.TEST)
 
 ### Process k character ###
 # read image as gray
 image = skimage.io.imread('/root/data/www/files/handwrite_letter_k_28x28.png', as_grey=True)
 # print(image.shape, image.dtype, image)
 
 # convert image to fit forward function
 imageConvert = 1 - image.reshape((1,1,28,28))
 # print(imageConvert.shape, imageConvert.dtype, imageConvert)
 
 # forward image data
 res = net.forward_all(data=imageConvert)
 # print(res)
 
 # print result
 print("Real is k\nPredict is ")
 for i in range(0,10,1):
     print("{} {:.2f}%".format(i, res["loss"][0][i]*100))
 
 ### Process 2 character ###
 # read image as gray
 image = skimage.io.imread('/root/data/www/files/handwrite_letter_2_28x28.png', as_grey=True)
 # print(image.shape, image.dtype, image)
 
 # convert image to fit forward function
 imageConvert = 1 - image.reshape((1,1,28,28))
 # print(imageConvert.shape, imageConvert.dtype, imageConvert)
 
 # forward image data
 res = net.forward_all(data=imageConvert)
 # print(res)
 
 # print result
 print("Real is 2\nPredict is ")
 for i in range(0,10,1):
     print("{} {:.2f}%".format(i, res["loss"][0][i]*100))

结果

 Real is k
 Predict is 
 0 0.00%
 1 0.02%
 2 1.81%
 3 0.00%
 4 3.68%
 5 10.21%
 6 8.86%
 7 0.00%
 8 75.42%
 9 0.00%
 Real is 2
 Predict is 
 0 0.00%
 1 0.00%
 2 100.00%
 3 0.00%
 4 0.00%
 5 0.00%
 6 0.00%
 7 0.00%
 8 0.00%
 9 0.00%

其它:测试1

http://3531563811.site:31188/lab/tree/root/data/src/ipynb/mnist_handwrite_number_2.ipynb
 import sys
 import caffe
 import cv2
 import matplotlib
 matplotlib.rcParams['backend'] = "Qt4Agg"
 import numpy as np
 import lmdb
 
 MODEL_FILE = '/root/data/www/code/caffe-1.0/examples/mnist/lenet.prototxt'
 PRETRAINED = '/root/data/caffe/mnist/lenet_iter_10000.caffemodel'
 
 net = caffe.Net(MODEL_FILE, PRETRAINED,caffe.TEST)
 caffe.set_mode_cpu()
 
 ### Test mnist test image
 db_path = '/root/data/caffe/mnist/mnist_test_lmdb'
 lmdb_env = lmdb.open(db_path)
 lmdb_txn = lmdb_env.begin()
 lmdb_cursor = lmdb_txn.cursor()
 
 # Test the 100th image
 count = 100
 for key, value in lmdb_cursor:
     count = count -1
     if (count ## 0):
         datum = caffe.proto.caffe_pb2.Datum()
         datum.ParseFromString(value)
         
         label = int(datum.label)
         image = caffe.io.datum_to_array(datum)
         # print(image.shape, image.dtype, image)
         
         out = net.forward_all(data=np.asarray([image]))
         
         # print result
         print("Real is {}\nPredict is ".format(label))
         for i in range(0,10,1):
             print("{} {:.2f}%".format(i, out["prob"][0][i]*100))
         
         break

 Real is 9
 Predict is 
 0 0.00%
 1 0.00%
 2 0.00%
 3 0.00%
 4 0.00%
 5 0.00%
 6 0.00%
 7 0.00%
 8 0.00%
 9 100.00%

其它:测试2

http://3531563811.site:31188/lab/tree/root/data/src/ipynb/mnist_handwrite_number_2.ipynb
 import sys
 import caffe
 import cv2
 import matplotlib
 matplotlib.rcParams['backend'] = "Qt4Agg"
 import numpy as np
 import lmdb
 
 MODEL_FILE = '/root/data/www/code/caffe-1.0/examples/mnist/lenet.prototxt'
 PRETRAINED = '/root/data/caffe/mnist/lenet_iter_10000.caffemodel'
 
 net = caffe.Net(MODEL_FILE, PRETRAINED,caffe.TEST)
 caffe.set_mode_cpu()
 
 ### Test self-made image
 # Load image
 img = caffe.io.load_image('/root/data/www/files/handwrite_letter_2_28x28.png', color=False)
 
 # Convert image
 img2 = 255 - img.astype(np.uint8) * 255
 img3 = img2.transpose(2,0,1)
 
 # Go net
 out = net.forward_all(data=np.asarray([img3]))
 
 # print result
 print("Real is 2\nPredict is ")
 for i in range(0,10,1):
     print("{} {:.2f}%".format(i, out["prob"][0][i]*100))

 Real is 2
 Predict is 
 0 0.00%
 1 0.00%
 2 100.00%
 3 0.00%
 4 0.00%
 5 0.00%
 6 0.00%
 7 0.00%
 8 0.00%
 9 0.00%

参考

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment