Caffe之学习网络参数

已知条件

1)预处理好的LMDB格式的训练数据和测试数据(这里是mnist数据源)

步骤

1)准备工作

导入一些包,设置工作路径。

主函数main.py内容1:

import os
import matplotlib.pyplot as plt
import numpy as np
from tool.net_func import *      #tool为自定义包,有两个文件:
                                 #__init__.py和net_func.py,
                                 #后文会介绍。

os.chdir('/home/yekui/caffe-master/examples')#设置工作路径,之后的路径都是基于此!!

2)得到solver

这里有两个函数需要指出:

custom_net(train_net_path, LMDB, batch_size)

​ 功能:定义网络结构,并写入train_net_path。

​ LMDB:是指数据源的路径,

​ batch_size:一次训练(或测试)多少数据。

custom_solver(train_net_path,test_net_path,solver_config_path)

​ 功能:定义solver参数(用来优化),并写入solver_config_path。

​ train_net_path:训练网络路径

​ test_net_path:测试网络路径

​ solver_config_path:solver路径

主函数main.py内容2:

train_net_path = 'mnist/yk_auto_train.prototxt'         #训练网络路径
test_net_path = 'mnist/yk_auto_test.prototxt'           #测试网络路径
solver_config_path = 'mnist/yk_auto_solver.prototxt'    #solver路径

custom_net(train_net_path, 'mnist/mnist_train_lmdb', 64)#网络定义
custom_net(test_net_path, 'mnist/mnist_test_lmdb', 100) #网络定义
custom_solver(train_net_path, test_net_path, solver_config_path)#solver定义

solver = caffe.get_solver(solver_config_path) #得到solver

3)开始训练

主函数main.py内容3:

#演示一下,在训练过程中,记录一些自己想记录的数据

#设置一些参数
niter = 250  # 训练次数
test_interval = niter / 10   #隔多久(迭代次数)检验测试准确率
train_loss = np.zeros(niter) #保存每次迭代的loss值
test_acc = np.zeros(int(np.ceil(niter / test_interval))) #保存测试准确率

# 开始训练啦~
for it in range(niter):
    solver.step(1)  # 取一个batch_size的训练数据训练一下

    # 保存每次迭代的loss值
    train_loss[it] = solver.net.blobs['loss'].data

    # 计算并保存测试准确率
    if it % test_interval == 0:
        print 'Iteration', it, 'testing...'
        correct = 0
        for test_it in range(100):
            solver.test_nets[0].forward() #取一个batch_size的测试数据计算各层结果。
                                          #不像solver.step(),它没有反向传播,所以
                                          #不会改变权重,只是单纯地计算一下而已。
            correct += sum(solver.test_nets[0].blobs['score'].data.argmax(1)
                           == solver.test_nets[0].blobs['label'].data)
        test_acc[it // test_interval] = correct / 1e4 #1e4 = batch_size * 迭代次数(100)

#结果图示化,意会一下就懂了^_^
_, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.plot(np.arange(niter), train_loss)
ax2.plot(test_interval * np.arange(len(test_acc)), test_acc, 'r')
ax1.set_xlabel('iteration')
ax1.set_ylabel('train loss')
ax2.set_ylabel('test accuracy')
ax2.set_title('Custom Test Accuracy: {:.2f}'.format(test_acc[-1]))
plt.show()

显示结果为:

4)自定义包

#此文件名为net_func.py
#在tool文件夹下
#tool文件夹与main.py在相同路径下

caffe_root = '/home/yekui/caffe-master/'
import sys
sys.path.insert(0,caffe_root + 'python')
import caffe
from caffe import layers as L, params as P


def custom_net(save_path, lmdb, batch_size):
    #custom_net(train_net_path, LMDB, batch_size)
    #功能:定义网络结构,并写入train_net_path。
    #LMDB:是指数据源的路径,
    #batch_size:一次训练(或测试)多少数据。

    #定义自己的网络,可以自己修改
    #各层含义不细讲了,可以自己去官网学学

    n = caffe.NetSpec()  #结构化初始

    n.data, n.label = L.Data(batch_size=batch_size, backend=P.Data.LMDB, source=lmdb,
                             transform_param=dict(scale=1. / 255), ntop=2)
    n.conv1 = L.Convolution(n.data, kernel_size=5, num_output=20, weight_filler=dict(type='xavier'))
    n.pool1 = L.Pooling(n.conv1, kernel_size=2, stride=2, pool=P.Pooling.MAX)
    n.conv2 = L.Convolution(n.pool1, kernel_size=5, num_output=50, weight_filler=dict(type='xavier'))
    n.pool2 = L.Pooling(n.conv2, kernel_size=2, stride=2, pool=P.Pooling.MAX)
    n.fc1 = L.InnerProduct(n.pool2, num_output=500, weight_filler=dict(type='xavier'))
    n.relu1 = L.ReLU(n.fc1, in_place=True)
    n.score = L.InnerProduct(n.relu1, num_output=10, weight_filler=dict(type='xavier'))
    n.loss = L.SoftmaxWithLoss(n.score, n.label)

    with open(save_path, 'w') as f:
        f.write(str(n.to_proto()))   #n.to_proto()结构化结束


def custom_solver(train_net_path, test_net_path, solver_config_path):
    #功能:定义solver参数(用来优化),并写入solver_config_path。
    #train_net_path:训练网络路径
    #test_net_path:测试网络路径
    #solver_config_path:solver路径


    from caffe.proto import caffe_pb2
    s = caffe_pb2.SolverParameter() #结构化初始

    # 设置一个种子,这样可以重复实验
    # 这控制训练过程中的随机性
    s.random_seed = 0xCAFFE

    # 指明训练和测试网络的位置
    s.train_net = train_net_path
    s.test_net.append(test_net_path)
    s.test_interval = 500  # 500次训练迭代后,测试一下
    s.test_iter.append(100)  # 每次测试时测试100个

    s.max_iter = 10000  # 训练10000次结束


    s.type = "SGD"  # 还可以选择 "SGD"、"Adam"、"Nesterov"等


    s.base_lr = 0.01  # 初始学习率
    s.momentum = 0.9  #设置动量
    s.weight_decay = 5e-4 #设置weight decay,可预防过拟合


    s.lr_policy = 'inv'  #学习率如何变化的策略,还有'fixed'等
    s.gamma = 0.0001
    s.power = 0.75

    s.display = 1000 #每训练1000次就显示一下loss和accuracy


    s.snapshot = 250  #每训练250次就保存一下训练好的权重,
                      #这里为演示,设置有点小,一般为5000.
    s.snapshot_prefix = 'mnist/custom_net' 


    s.solver_mode = caffe_pb2.SolverParameter.GPU #设置为GPU模式

    # 将定义好的solver写入文件
    with open(solver_config_path, 'w') as f:
        f.write(str(s))

结尾

不出差错的话,你会得到一个custom_net_iter_250.caffemodel的文件,那么恭喜你,你的权重参数训练好啦~~

附录(获取已知条件)

训练数据在:http://pan.baidu.com/s/1sk8x2Dv

你可能感兴趣的:(深度学习框架)