(1)第一强烈推荐使用Netscope,是一个可视化网络结构的在线工具。当写完一个网络结果文件的时候,将文本粘贴到左侧,按shift+enter就可以看到网络结构图了。
用过的都说好!没用过的赶紧Mark起来。
http://ethereon.github.io/netscope/#/editor
(2)强烈推荐使用PYTHON定义网络结构文件。
在初期,我们可能都是使用别人写好的网络模型,觉得直接在对文本进行修改也很简单,但是!!也要学习如何使用PYTHON脚本去优雅地生成一个网络文件,不能老是重复劳动啊。
a) 写出每一层的结构(初级选手,可以看出还是非常冗余的写法,觉得low的略过,直接看一个写法)
# -*- coding: utf-8 -*-
import caffe
from caffe import layers as L,params as P,to_proto
path='/home/yang/deep/Demo/Demo04/' #保存数据和配置文件的路径
train_lmdb=path+'/lfw/lfw_train_lmdb' #训练数据LMDB文件的位置
val_lmdb=path+'lfw/lfw_val_lmdb' #验证数据LMDB文件的位置
mean_file=path+'lfw/lfw_mean.binaryproto' #均值文件的位置
train_proto=path+'tool/lfw_alexnet_train.prototxt' #生成的训练配置文件保存的位置
val_proto=path+'tool/lfw_alexnet_val.prototxt' #生成的验证配置文件保存的位置
#编写一个函数,用于生成网络
def create_net(lmdb,batch_size,include_acc=False):
#创建第一层:数据层。向上传递两类数据:图片数据和对应的标签
data, label = L.Data(source=lmdb, backend=P.Data.LMDB, batch_size=batch_size, ntop=2,
transform_param=dict(crop_size=227,mean_file=mean_file,mirror=True))
#创建第二屋:卷积层 conv1-5
conv1=L.Convolution(data, kernel_size=11, stride=4,num_output=96,pad=0,param=[dict(name=weight_name,lr_mult=1, decay_mult=1), dict(name=bias_name,lr_mult=2, decay_mult=0)],weight_filler=dict(type='xavier'),bias_filter=dict(type='constant'),value=0.1))
#创建BN+scale层
if include_acc
bn_con1=L.BatchNorm(conv1,use_global_stats=True,in_place=True)
else
bn_con1=L.BatchNorm(conv1,use_global_stats=False,in_place=True)
# scale bias_term ?? true false
scale_conv1=L.Scale(conv1, scale_param=dict(bias_term=True), in_place=True)
#创建激活函数层 relu1
relu1=L.ReLU(conv1, in_place=True)
#创建池化层 pool1
pool1=L.Pooling(relu1, pool=P.Pooling.MAX, kernel_size=3, stride=2)
# conv2
conv2=L.Convolution(pool1, kernel_size=5, stride=1,num_output=256, pad=2,param=[dict(name=weight_name,lr_mult=1, decay_mult=1), dict(name=bias_name,lr_mult=2, decay_mult=0)],weight_filler=dict(type='xavier'),bias_filter=dict(type='constant'),value=0.1))
if include_acc
bn_con2=L.BatchNorm(conv2,use_global_stats=True,in_place=True)
else
bn_con2=L.BatchNorm(conv2,use_global_stats=False,in_place=True)
# scale bias_term ?? true false
scale_conv2=L.Scale(conv2, scale_param=dict(bias_term=True), in_place=True)
relu2=L.ReLU(conv2, in_place=True)
pool2=L.Pooling(relu2, pool=P.Pooling.MAX, kernel_size=3, stride=2)
#conv3
conv3=L.Convolution(pool2, kernel_size=3, stride=1,num_output=384, pad=1,param=[dict(name=weight_name,lr_mult=1, decay_mult=1), dict(name=bias_name,lr_mult=2, decay_mult=0)],weight_filler=dict(type='xavier'),bias_filter=dict(type='constant'),value=0))
relu3=L.ReLU(conv3, in_place=True)
#conv4
conv4=L.Convolution(relu3, kernel_size=3, stride=1,num_output=384, pad=1,param=[dict(name=weight_name,lr_mult=1, decay_mult=1), dict(name=bias_name,lr_mult=2, decay_mult=0)],weight_filler=dict(type='xavier'),bias_filter=dict(type='constant'),value=0.1))
relu4=L.ReLU(conv4, in_place=True)
#conv5
conv5=L.Convolution(relu4, kernel_size=3, stride=1,num_output=256, pad=1,param=[dict(name=weight_name,lr_mult=1, decay_mult=1), dict(name=bias_name,lr_mult=2, decay_mult=0)],weight_filler=dict(type='xavier'),bias_filter=dict(type='constant'),value=0.1))
relu5=L.ReLU(conv5, in_place=True)
pool5=L.Pooling(relu5, pool=P.Pooling.MAX, kernel_size=3, stride=2)
#创建一个全连接层 fc6
fc6=L.InnerProduct(pool5, num_output=4096,param=[dict(name=weight_name,lr_mult=1, decay_mult=1), dict(name=bias_name,lr_mult=2, decay_mult=0)],weight_filler=dict(type='xavier'),bias_filter=dict(type='constant'),value=0.1))
relu6=L.ReLU(fc6, in_place=True)
#创建一个dropout层 drop6
drop6 = L.Dropout(relu6, in_place=True, dropout_param=dict(dropout_ratio=0.5))
#fc7
fc7=L.InnerProduct(drop6, num_output=4096,param=[dict(name=weight_name,lr_mult=1, decay_mult=1), dict(name=bias_name,lr_mult=2, decay_mult=0)],weight_filler=dict(type='xavier'),bias_filter=dict(type='constant'),value=0.1))
relu7=L.ReLU(fc7, in_place=True)
drop7 = L.Dropout(relu7, in_place=True, dropout_param=dict(dropout_ratio=0.5))
#fc8 ->5749
fc8 = L.InnerProduct(drop7, num_output=5749,param=[dict(name=weight_name,lr_mult=1, decay_mult=1), dict(name=bias_name,lr_mult=2, decay_mult=0)],weight_filler=dict(type='xavier'),bias_filter=dict(type='constant'),value=0))
#创建一个softmax层
loss = L.SoftmaxWithLoss(fc8, label)
if include_acc: #在训练阶段,不需要accuracy层,但是在验证阶段,是需要的
acc = L.Accuracy(fc, label)
return to_proto(loss, acc)
else:
return to_proto(loss)
def write_net():
#将以上的设置写入到prototxt文件
with open(train_proto, 'w') as f:
f.write(str(create_net(train_lmdb,batch_size=64)))
#写入配置文件
with open(val_proto, 'w') as f:
f.write(str(create_net(val_lmdb,batch_size=32, include_acc=True)))
if __name__ == '__main__':
write_net()
b)今天发现在caffe的example下面pycaffe给了一个自动生成网络文件的demo。相比于上面的写法更加简练了,有点像抽象函数的啊哈哈哈,不知道是不是这个说法.
把不同类型层的操作封装在不同的函数里面了。很好!可以根据需要自已扩充一些层的写法,比如BN层。
https://github.com/BVLC/caffe/blob/master/examples/pycaffe/caffenet.py
from __future__ import print_function
from caffe import layers as L, params as P, to_proto
from caffe.proto import caffe_pb2
# helper function for common structures
def conv_relu(bottom, ks, nout, stride=1, pad=0, group=1):
conv = L.Convolution(bottom, kernel_size=ks, stride=stride,
num_output=nout, pad=pad, group=group)
return conv, L.ReLU(conv, in_place=True)
def fc_relu(bottom, nout):
fc = L.InnerProduct(bottom, num_output=nout)
return fc, L.ReLU(fc, in_place=True)
def max_pool(bottom, ks, stride=1):
return L.Pooling(bottom, pool=P.Pooling.MAX, kernel_size=ks, stride=stride)
def caffenet(lmdb, batch_size=256, include_acc=False):
data, label = L.Data(source=lmdb, backend=P.Data.LMDB, batch_size=batch_size, ntop=2,
transform_param=dict(crop_size=227, mean_value=[104, 117, 123], mirror=True))
# the net itself
conv1, relu1 = conv_relu(data, 11, 96, stride=4)
pool1 = max_pool(relu1, 3, stride=2)
norm1 = L.LRN(pool1, local_size=5, alpha=1e-4, beta=0.75)
conv2, relu2 = conv_relu(norm1, 5, 256, pad=2, group=2)
pool2 = max_pool(relu2, 3, stride=2)
norm2 = L.LRN(pool2, local_size=5, alpha=1e-4, beta=0.75)
conv3, relu3 = conv_relu(norm2, 3, 384, pad=1)
conv4, relu4 = conv_relu(relu3, 3, 384, pad=1, group=2)
conv5, relu5 = conv_relu(relu4, 3, 256, pad=1, group=2)
pool5 = max_pool(relu5, 3, stride=2)
fc6, relu6 = fc_relu(pool5, 4096)
drop6 = L.Dropout(relu6, in_place=True)
fc7, relu7 = fc_relu(drop6, 4096)
drop7 = L.Dropout(relu7, in_place=True)
fc8 = L.InnerProduct(drop7, num_output=1000)
loss = L.SoftmaxWithLoss(fc8, label)
if include_acc:
acc = L.Accuracy(fc8, label)
return to_proto(loss, acc)
else:
return to_proto(loss)
def make_net():
with open('train.prototxt', 'w') as f:
print(caffenet('/path/to/caffe-train-lmdb'), file=f)
with open('test.prototxt', 'w') as f:
print(caffenet('/path/to/caffe-val-lmdb', batch_size=50, include_acc=True), file=f)
if __name__ == '__main__':
make_net()
(3)使用caffe 训练模型,生成训练日志后,绘制精度和损失。
1.在训练脚本前面加上:
- GLOG_logtostderr=0 GLOG_log_dir=path/to/your/Log/ \
2.
./parse_log.sh caffe.CYang.yang.log #以log结尾的日志文件
#得到类似train和test的文件如下:
./plot_training_log.py.example 0 test_acc.png caffe.CYang.yang.log #关于测试精度
./plot_training_log.py.example 2 test_loss.png caffe.CYang.yang.log #关于测试损失
./plot_training_log.py.example 6 train_loss.png caffe.CYang.yang.log #关于训练损失
下面这个渣渣的训练情况大家忽略,因为我的网络还有很多问题。
(4)每次都面对小黑框,是不是视觉疲劳了。连隔壁的小伙伴都看不下去了。
强烈推荐第3波。Anaconda和spyder
便捷的PYTHON工具。说明,不用修改caffe的任何配置。
安装anaconda后,在Terminal输入Spyder就会出现下面的界面,左边是编辑界面,右边是命令窗口。
下面给了一个安装Anaconda的脚本,一键解决。
链接: https://pan.baidu.com/s/1nuAiYpz 密码: r3q4