Caffe aprende desde cero la rutina de reconocimiento de números escritos a mano de 2 min

Prefacio

El artículo anterior explicó el tutorial de instalación de caffe en la máquina virtual ubuntu16.04. Este artículo usará la arquitectura de caffe para aprender las rutinas de reconocimiento de números escritas a mano de mnist incorporadas y aprender el uso específico de caffe.

Descargar datos

Primero, hay un archivo de script en el directorio data / mnist: get_mnist.sh, cuyo código fuente es el siguiente:

#!/usr/bin/env sh
# This scripts downloads the mnist data and unzips it.

DIR="$( cd "$(dirname "$0")" ; pwd -P )"
cd "$DIR"

echo "Downloading..."

for fname in train-images-idx3-ubyte train-labels-idx1-ubyte t10k-images-idx3-ubyte t10k-labels-idx1-ubyte
do
    if [ ! -e $fname ]; then
        wget --no-check-certificate http://yann.lecun.com/exdb/mnist/${fname}.gz
        gunzip ${fname}.gz
    fi
done

Puede ver que este script descarga principalmente 4 archivos,

    train-images-idx3-ubyte  //训练用的图像文件
    train-labels-idx1-ubyte//训练用的标签文件
    t10k-images-idx3-ubyte//测试用的图像文件
    t10k-labels-idx1-ubyte//测试用的标签文件

Ejecute el siguiente comando para descargar

cd ~/caffe/data/mnist
./get_mnist.sh

Descarga completa
Inserte la descripción de la imagen aquí

Procesamiento de datos

Hay un script create_mnist.sh en el directorio raíz de Caffe examples / mnist /, que es un script para la conversión de datos:

!/usr/bin/env sh
# This script converts the mnist data into lmdb/leveldb format,
# depending on the value assigned to $BACKEND.
set -e

EXAMPLE=examples/mnist
DATA=data/mnist
BUILD=build/examples/mnist

BACKEND="lmdb"

echo "Creating ${BACKEND}..."

rm -rf $EXAMPLE/mnist_train_${BACKEND}
rm -rf $EXAMPLE/mnist_test_${BACKEND}

$BUILD/convert_mnist_data.bin $DATA/train-images-idx3-ubyte \
  $DATA/train-labels-idx1-ubyte $EXAMPLE/mnist_train_${BACKEND} --backend=${BACKEND}
$BUILD/convert_mnist_data.bin $DATA/t10k-images-idx3-ubyte \
  $DATA/t10k-labels-idx1-ubyte $EXAMPLE/mnist_test_${BACKEND} --backend=${BACKEND}

echo "Done."

Utilice principalmente el archivo de imagen y el archivo de etiqueta para generar dos archivos en formato lmdb, la ejecución es la siguiente:

./examples/mnist/create_mnist.sh

Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

Entrenar

vim ./examples/mnist/train_lenet.sh

El código fuente del script de entrenamiento es el siguiente:

#!/usr/bin/env sh
set -e

./build/tools/caffe train --solver=examples/mnist/lenet_solver.prototxt $@

set -e, esta declaración le dice a bash que si el resultado de la ejecución de cualquier declaración no es verdadero, debería salir. La ventaja de esto es evitar que el error se convierta en una bola de nieve y conduzca a un error fatal que debería haberse tratado antes. Si desea aumentar la legibilidad, puede usar set -o errexit, que tiene el mismo efecto que set -e.

Linux脚本中$#、$0、$1、$@、$*、$$、$?这个几个参数的意义:

  $#:传入脚本的参数个数;

  $0:  脚本自身的名称;  

  $1:  传入脚本的第一个参数;

  $2:  传入脚本的第二个参数;

  $@: 传入脚本的所有参数;

  $*:传入脚本的所有参数;

  $$:  脚本执行的进程id;

  $?:  上一条命令执行后的状态,结果为0表示执行正常,结果为1表示执行异常;

    其中$@与$*正常情况下一样,当在脚本中将$*加上双引号作为“$*”引用时,此时将输入的所有参数当做一个整体字符串对待。比如输入参数有a b c三个参数,则“$*”表示“a b c”一个字符串。

Continúe verificando el archivo lenet_solver.prototxt en el script, consulte las notas para conocer el significado de cada parámetro:

# 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   #迭代多少个样本数,例如有5000个样本,一次测试要跑完这5000个样本,test_iter * batch需要等于5000
# Carry out testing every 500 training iterations.
test_interval: 500  #测试间隔,每训练500次,就进行一次测试
# The base learning rate, momentum and the weight decay of the network.
base_lr: 0.01  #基础学习率,其他层的最终学习率是lr_   * base_lr
momentum: 0.9   #动量,常用的都是0.9
weight_decay: 0.0005
# The learning rate policy
lr_policy: "inv"  #学习策略
gamma: 0.0001   #inv学习策略的参数
power: 0.75		#inv学习策略的参数
# Display every 100 iterations
display: 100   #每训练100次显示一次,设置为0,不显示
# The maximum number of iterations
max_iter: 10000  #最大的迭代次数,10000次就停止了
# snapshot intermediate results
snapshot: 5000
snapshot_prefix: "examples/mnist/lenet"
# solver mode: CPU or GPU
solver_mode: CPU

                

Inserte la descripción de la imagen aquí
Dado que el entrenamiento se realiza con una máquina virtual, la última línea de GPU se cambia a CPU.
Continúe viendo el archivo lenet_train_test.prototxt en el archivo lenet_solver.prototxt. Los parámetros en el archivo han sido comentados en detalle, vea las notas:

name: "LeNet" 
layer {
  name: "mnist"
  type: "Data"
  top: "data"   #输出
  top: "label"  #输出,一般data层输出有两个,data和label
  include {
    phase: TRAIN #include内部,训练阶段使用,若没写include,数据既用于训练,又用于测试
  }
  transform_param {
    scale: 0.00390625 #1/256,归一化
  }
  data_param {
    source: "examples/mnist/mnist_train_lmdb"  #数据源
    batch_size: 64 #每次批处理的个数,一般使用2的n次方,如64,128
    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
  }
}


# lr_mult:1 weight learn rate
# lr_mult:2 bias learn rate
# 输入:n*c0*w0*h0
# 输出:n*c1*w1*h1
# 其中,c1是参数中的num_output, 即生成的特征图个数
# w1=(w0+2*pad-kernel_size)/stride+1
# h1=(h0+2*pad-kernel_size)/stride+1
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  param {
    lr_mult: 1	#学习率系数,最终的学习率是这个数乘以solver.prototxt配置文件中国的base_lr。
  }
  param {
    lr_mult: 2	#如果有两个lr_mult,则第一个是权值的学习率,第二个是偏置项的学习率,一般偏置项学习率是权值学习率的两倍。
  }
  convolution_param {
    num_output: 20  #卷积核(filter)的个数
    kernel_size: 5	#卷积核的大小,h x w x d,hxw是5x5大小,d是深度(隐含的),和前一层的深度数值一样,例如,前一层若是data层有rgb3个通道即深度是3,那么本层深度也是d=3,又比如前一层是卷积层,有20个特征图,深度是20,那么本层深度d=20
    stride: 1		#卷积核的步长,默认是1
    weight_filler {
      type: "xavier" #权重的初始化,默认为consatant, 值都是0。很多时候我们选用"xavier"泽维尔算法来初始化,也可以设置为"gussian"
    }
    bias_filler {
      type: "constant" #偏置项的初始化,一般为consatant, 值都是0
    }
  }
}


#pooling层的运算方法和卷积层是一样的
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1"
  top: "pool1"
  pooling_param {
    pool: MAX #池化方法,默认是MAX(固定区域内,例如对一个2x2的区域进行pooling运算,只保留4个值中最大的值)。 目前可用的方法有MAX,AVE(取平均)
    kernel_size: 2 #池化核的大小
    stride: 2 #池化的步长,默认是1。一般我们设置为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"  #输入IP2预测分类和label标签
  top: "accuracy"  #输出准确率
  include {
    phase: TEST
  }
}

#SoftmaxWithLoss,输出loss值
#Softmax,输出似然值,准确率值
layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "ip2"
  bottom: "label"
  top: "loss"
}

Empezar a entrenar

./examples/mnist/train_lenet.sh

Inserte la descripción de la imagen aquí
Después del entrenamiento, se generará el archivo de peso lenet_iter_10000.caffemodel.
Inserte la descripción de la imagen aquí

prueba

llevado a cabo:

./build/tools/caffe.bin test \
-model examples/mnist/lenet_train_test.prototxt \
-weights examples/mnist/lenet_iter_10000.caffemodel \
-iterations 100

Resultados de la prueba:
Ver resultados de previsión

Dibujar diagrama de red

La rutina mnist se ha entrenado y probado anteriormente, y también se pueden ver los resultados de la prueba. La estructura de red de esta rutina es relativamente simple y parece un dolor de cabeza comparar ese tipo de archivos de red tan complicados.
¿Hay alguna forma de ver los archivos de red de manera más conveniente?
¡La respuesta ciertamente está ahí!
Aprendamos a dibujar un diagrama de red.
Instale las bibliotecas dependientes primero

apt-get install graphviz

pip install pydot

Ejecute los siguientes comandos para dibujar un diagrama de red:

python ./python/draw_net.py  ./examples/mnist/lenet_train_test.prototxt ./caffe_png/mnist.png --rankdir=LR

Inserte la descripción de la imagen aquí

eog mnist.png 

Inserte la descripción de la imagen aquí
Como se muestra en la imagen de arriba, este tipo de diagrama de red es mucho más hermoso ~~~~

Supongo que te gusta

Origin blog.csdn.net/u014470361/article/details/99340261
Recomendado
Clasificación