Caffe源代码学习 — AlexNet(Caffenet.py)

欢迎访问我的个人Blog: zengzeyu.com

导言


源码位置:caffe/examples/pycaffe/caffenet.py
该文件源代码是经典模型AlexNet的Caffe实现,有兴趣的小伙伴去拜读一下论文: ImageNet Classification with Deep Convolutional Neural Networks.

源码解读


1. 导入模块


from __future__ import print_function
from caffe import layers as L, params as P, to_proto
from caffe.proto import caffe_pb2

2. 定义Layer函数


包括: 卷积层(Convolution Layer)、全连接层(Full Connected Layer)和池化层(Pooling Layer)

2.1 卷积层(Convolution Layer)函数

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)

1. 函数输入

  • bottom - 输入节点(blob)名
  • ks - 卷积核尺寸(kernel size
  • nout - 输出深度尺寸(number output
  • stride - 卷积核滑窗距离
  • pad - 图像边缘添加尺寸,即在图像周围一周添加尺寸为pad的空白像素
  • group - 将数据进行分开训练堆数目

2. 调用Caffe卷基层生成函数

  • conv = L.Convolution(bottom, kernel_size=ks, stride=stride,num_output=nout, pad=pad, group=group)

3. 返回参数

  • conv - 卷积层配置
  • L.ReLU(conv, in_place=True) - 卷积后的数据经过ReLU激活函数得到的数据

2.2 全连接层(Full Connected Layer)

def fc_relu(bottom, nout):
    fc = L.InnerProduct(bottom, num_output=nout)
    return fc, L.ReLU(fc, in_place=True)

1. 调用Caffe内积函数

  • fc = L.InnerProduct(bottom, num_output=nout)

2. 返回参数

  • fc, L.ReLU(fc, in_place=True) - 全连接分类之后数据通过ReLU函数

2.3 池化层(Pooling Layer)

def max_pool(bottom, ks, stride=1):
    return L.Pooling(bottom, pool=P.Pooling.MAX, kernel_size=ks, stride=stride)

调用Caffe池化层生成函数

  • L.Pooling)()
  • pool=P.Pooling.MAX - 池化类型选择MAX,即取模板内最大值输出

3. 定义网络结构


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)

1. 函数输入

  • lmdb - 文件名
  • batch_size - 每次训练输入样本数目
  • include_acc - 加速?

2. 调用Caffe数据层输入函数(Data)
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))

  • backend - 数据类型
  • ntop - 输出blob数目,因为数据层处理数据输出data和label,所以值为 2
  • transform_param - 对单个图片处理: crop_size图片剪裁大小,mean_valueRGB图像需要减去的值(目的是更好突出特征)和mirror镜像处理。
Layer Operation Output
Data crop_size:227, mean_value: [104, 117, 123], mirror: true data: 227x227x3; label: 227x227x1
1 conv1 -> relu1 -> pool1 -> norm1 27x27x96
2 conv2 -> relu2 -> pool2 -> norm2 13x13x256
3 conv3 -> relu3 11x11x384
4 conv4 -> relu4 11x11x384
5 conv5 -> relu5 -> pool5 6x6x256
6 fc6 -> relu6 -> drop6 4096
7 fc7 -> relu7 -> drop7 4096
8 fc8 -> loss 1000

3. 网络结构
此博客绘制了AlexNet网络结构图和数据流动图,方便直观理解网络结构,可移步:深度学习之图像分类模型AlexNet解读
第1-5层为卷积层,如下表所示:

Layer Operation Output
Data crop_size:227, mean_value: [104, 117, 123], mirror: true data: 227x227x3; label: 227x227x1
1 conv1 -> relu1 -> pool1 -> norm1 27x27x96
2 conv2 -> relu2 -> pool2 -> norm2 13x13x256
3 conv3 -> relu3 11x11x384
4 conv4 -> relu4 11x11x384
5 conv5 -> relu5 -> pool5 6x6x256
6 fc6 -> relu6 -> drop6 4096
7 fc7 -> relu7 -> drop7 4096
8 fc8 -> loss 1000

以第1层代码为例进行分析:

  1. 第1层 = 卷积层(conv1+relu1) + 池化层(pool1) + 归一化(norm1)

(1). 第1层 - 卷积层(conv1+relu1)
作用:提取局部特征,使用ReLU作为CNN的激活函数,并验证其效果在较深的网络超过了Sigmoid,成功解决了Sigmoid在网络较深时的梯度弥散问题。
conv1, relu1 = conv_relu(data, 11, 96, stride=4)

  • 数据:数据层输出data数据
  • 卷积核大小: 11
  • 输出节点深度: 96
  • 滑窗距离: 4

(2). 第1层 - 池化层(pool1)
作用:提取最大值,避免平均池化的模糊化效果。在AlexNet中提出让步长比池化核的尺寸小,这样池化层的输出之间会有重叠和覆盖,提升了特征的丰富性。
pool1 = max_pool(relu1, 3, stride=2)

  • 数据: relu1
  • 模板核大小: 3
  • 滑窗距离: 2

(3). 第1层 - 局部响应归一化(Local Response Normalize)(norm1)
作用:对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力
norm1 = L.LRN(pool1, local_size=5, alpha=1e-4, beta=0.75)

  • 数据: pool1
  • 取值模板尺寸: 5
  • alpha: 0.0001
  • beta: 0.75

4. 输出网络结构文件(.prototxt)


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)

5. 运行


if __name__ == '__main__':
    make_net()

总结


Caffene.py是入门Caffe较好的源代码,结合原论文看,同时能加深对网络结构的理解,补充理论知识。下面根据这个example形式构建自己的网络结构,其中第一步,也是学习深度学习最重要的一步,编写自己的数据类型接口层程序。

以上。

附:

  1. AlexNet网络总结
  2. 深度学习之图像分类模型AlexNet解读

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容