专栏首页文武兼修ing——机器学习与IC设计基于gluon的Inception结构Inception结构代码

基于gluon的Inception结构Inception结构代码

Inception结构

初级Inception

结构

初级Inception结构如下所示:

inception_naive.png

其前向传播分为4个部分:

  • 通过1x1卷积
  • 通过3x3卷积,padding为1(不改变图片大小)
  • 通过5x5卷积,padding为2(不改变图片大小)
  • 通过3x3池化,为了保证图片大小与以上相同,stride应为1,padding应为1

最后,将以上四个部分在feature这一维度堆叠起来,即获得最终输出

分析

假设输入feature,每个层(卷积和池化)输出feature分别为$N_i,N_o$(即最终输出feature为$4 \times N_o$);输入图片的尺寸为WxL,对于每一层,有:

  • 1x1卷积层:有参数$1 \times 1 \times N_i \times N_o = N_iN_o$,需要进行计算的次数为$N_o \times W \times L \times 1 \times 1 \times N_i = WLN_iN_o$
  • 3x3卷积层:有参数$3 \times 3 \times N_i \times N_o = 9N_iN_o$,需要计算次数为$N_o \times W \times L \times 3 \times 3 \times N_i = 9WLN_iN_o$
  • 5x5卷积层,同上,参数为$25N_iN_o$,需要计算次数为$25WLN_iN_o$

因此,总的参数量为$(1+9+25)N_iN_o = 35N_iN_o$,需要的运算量为$(1+9+25)WLN_iN_o = 35WLN_iN_o$。考虑一个输入输出相同尺寸的3x3卷积,需要的参数量为$3 \times 3 \times N_i \times 4N_o = 36N_iN_o$,需要的运算量是$4N_o \times W \times L \times 3 \times 3 \times N_i = 36WLN_iN_o$,可以发现该结构在运算量和参数量近乎不变的情况下实现了多种感受野的连接。

改进Inception结构

结构

改进的Inception结构如下图所示

inception.png

同样具有四条前向传播通路,如下所示:

  • 1x1卷积
  • 先通过1x1卷积降维,再通过3x3卷积
  • 先通过1x1卷积降维,再通过5x5卷积
  • 先通过3x3maxpool,再通过1x1调整维度

最后,将以上四个部分在feature这一维度堆叠起来,即获得最终输出

分析

假设同上一部分,假设每个降维将降维降到原来维度的一半,对每一部分有如下所示:

  • 每个降维的1x1层,需要的参数量是$\cfrac{1}{2}N_i2$,运算参数量$\cfrac{1}{2}WLN_i2$
  • 1x1卷积层:有参数$1 \times 1 \times \cfrac{1}{2}N_i \times N_o = \cfrac{1}{2}N_iN_o$,需要进行计算的次数为$N_o \times W \times L \times 1 \times 1 \times \cfrac{1}{2}N_i = \cfrac{1}{2}WLN_iN_o$
  • 3x3卷积层:有参数$3 \times 3 \times \cfrac{1}{2}N_i \times N_o = 9N_iN_o$,需要计算次数为$N_o \times W \times L \times 3 \times 3 \times \cfrac{1}{2}N_i = \cfrac{9}{2}WLN_iN_o$
  • 5x5卷积层,同上,参数为$\cfrac{25}{2}N_iN_o$,需要计算次数为$\cfrac{25}{2}WLN_iN_o$

假设$N_i = N_o$,参数量一共是$3 \times \cfrac{1}{2}N_i^2 + \cfrac{35}{2}N_i^2 = 19N_i2$,需要运算的数量为$19WLN_i2$。可以发现无论是运算量还是参数量都小于原结构

代码

import mxnet as mx
import numpy as np

Inception结构搭建

Inception结构

class inception(mx.gluon.Block):
    def __init__(self,out_channel):
        super(inception,self).__init__()
        with self.name_scope():
            self.conv1 = mx.gluon.nn.Conv2D(out_channel,1,activation='relu')
            self.conv3_pre = mx.gluon.nn.Conv2D(out_channel//2,1)
            self.conv3 = mx.gluon.nn.Conv2D(out_channel,3,activation='relu',padding=1)
            self.conv5_pre = mx.gluon.nn.Conv2D(out_channel//2,1)            
            self.conv5 = mx.gluon.nn.Conv2D(out_channel,5,activation='relu',padding=2)
            self.pool_post = mx.gluon.nn.Conv2D(out_channel,1,activation='relu')
            self.pool = mx.gluon.nn.MaxPool2D(pool_size=3,strides=1,padding=1)
            
    def forward(self,x):
        result = [
            self.conv1(x),
            self.conv3(self.conv3_pre(x)),
            self.conv5(self.conv5_pre(x)),
            self.pool_post(self.pool(x))]
        return mx.ndarray.concat(dim=1,*result)

Inception结构测试

inception_model = inception(10)
print(inception_model)
inception_model.collect_params().initialize(mx.init.Normal(sigma=.1), ctx=mx.gpu())
inception(
  (pool_post): Conv2D(None -> 10, kernel_size=(1, 1), stride=(1, 1))
  (pool): MaxPool2D(size=(3, 3), stride=(1, 1), padding=(1, 1), ceil_mode=False)
  (conv1): Conv2D(None -> 10, kernel_size=(1, 1), stride=(1, 1))
  (conv3): Conv2D(None -> 10, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (conv5_pre): Conv2D(None -> 5, kernel_size=(1, 1), stride=(1, 1))
  (conv5): Conv2D(None -> 10, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
  (conv3_pre): Conv2D(None -> 5, kernel_size=(1, 1), stride=(1, 1))
)
indata = mx.ndarray.zeros((1,5,10,10),mx.gpu())
inception_model(indata).shape
(1, 40, 10, 10)

整体网络结构

class network(mx.gluon.Block):
    def __init__(self):
        super(network,self).__init__()
        with self.name_scope():
            self.conv1 = mx.gluon.nn.Conv2D(channels=8,kernel_size=3,padding=1)
            self.conv2 = inception(8)
            self.conv3 = inception(16)
            self.conv4 = inception(16)
            self.fc = mx.gluon.nn.Dense(10)
            self.pool = mx.gluon.nn.MaxPool2D(pool_size=3,strides=2)
            
    def forward(self,x):
        x = self.conv2(self.conv1(x))
        x = self.conv3(self.pool(x))
        x = self.conv4(self.pool(x))
        return self.fc(x)
model = network()
print(model)
model.collect_params().initialize(mx.init.Normal(sigma=.1), ctx=mx.gpu())
network(
  (pool): MaxPool2D(size=(3, 3), stride=(2, 2), padding=(0, 0), ceil_mode=False)
  (conv1): Conv2D(None -> 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (conv3): inception(
    (pool_post): Conv2D(None -> 16, kernel_size=(1, 1), stride=(1, 1))
    (pool): MaxPool2D(size=(3, 3), stride=(1, 1), padding=(1, 1), ceil_mode=False)
    (conv1): Conv2D(None -> 16, kernel_size=(1, 1), stride=(1, 1))
    (conv3): Conv2D(None -> 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (conv5_pre): Conv2D(None -> 8, kernel_size=(1, 1), stride=(1, 1))
    (conv5): Conv2D(None -> 16, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (conv3_pre): Conv2D(None -> 8, kernel_size=(1, 1), stride=(1, 1))
  )
  (conv2): inception(
    (pool_post): Conv2D(None -> 8, kernel_size=(1, 1), stride=(1, 1))
    (pool): MaxPool2D(size=(3, 3), stride=(1, 1), padding=(1, 1), ceil_mode=False)
    (conv1): Conv2D(None -> 8, kernel_size=(1, 1), stride=(1, 1))
    (conv3): Conv2D(None -> 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (conv5_pre): Conv2D(None -> 4, kernel_size=(1, 1), stride=(1, 1))
    (conv5): Conv2D(None -> 8, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (conv3_pre): Conv2D(None -> 4, kernel_size=(1, 1), stride=(1, 1))
  )
  (fc): Dense(None -> 10, linear)
  (conv4): inception(
    (pool_post): Conv2D(None -> 16, kernel_size=(1, 1), stride=(1, 1))
    (pool): MaxPool2D(size=(3, 3), stride=(1, 1), padding=(1, 1), ceil_mode=False)
    (conv1): Conv2D(None -> 16, kernel_size=(1, 1), stride=(1, 1))
    (conv3): Conv2D(None -> 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (conv5_pre): Conv2D(None -> 8, kernel_size=(1, 1), stride=(1, 1))
    (conv5): Conv2D(None -> 16, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (conv3_pre): Conv2D(None -> 8, kernel_size=(1, 1), stride=(1, 1))
  )
)
​```python
indata = mx.ndarray.zeros((1,1,28,28),mx.gpu())
model(indata).shape
(1, 10)

训练准备

数据集——MNIST数据集

def transform(data, label):
    return mx.nd.transpose(data,axes=(2,0,1)).astype(np.float32)/255, label.astype(np.float32)
gluon_train_data = mx.gluon.data.DataLoader(mx.gluon.data.vision.MNIST(train=True, transform=transform),100, shuffle=True)
gluon_test_data = mx.gluon.data.DataLoader(mx.gluon.data.vision.MNIST(train=False, transform=transform),100, shuffle=False)

代价函数——交叉熵

softmax_cross_entropy = mx.gluon.loss.SoftmaxCrossEntropyLoss()

优化器——sgd

trainer = mx.gluon.Trainer(model.collect_params(), 'sgd', {'learning_rate': .1})

准确率计算

def evaluate_accuracy(model):
    acc = mx.metric.Accuracy()
    for i, (data, lable) in enumerate(gluon_test_data):
        data = data.as_in_context(mx.gpu())
        lable = lable.as_in_context(mx.gpu())
        output = model(data)
        predictions = mx.nd.argmax(output, axis=1)
        acc.update(preds=predictions, labels=lable)
    return acc.get()[1]
evaluate_accuracy(model)
0.050200000000000002

训练

for _ in range(2):
    for i,(data,lable) in enumerate(gluon_train_data):
        data = data.as_in_context(mx.gpu())
        lable = lable.as_in_context(mx.gpu())
        with mx.autograd.record():
            outputs = model(data)
            loss = softmax_cross_entropy(outputs,lable)
        loss.backward()
        trainer.step(data.shape[0])
        if i % 100 == 1:
            print(i,loss.mean().asnumpy()[0])
1 0.16968
101 0.104242
201 0.093354
301 0.07079
401 0.123301
501 0.086882
1 0.0325385
101 0.0510763
201 0.0242231
301 0.0454984
401 0.0788167
501 0.0591589
evaluate_accuracy(model)
0.98829999999999996

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 宇宙法则

    聊下AI。 ? 还是先从游戏开始吧。 有一条『常识』需要先抛出来,大部分人都承认,网络游戏的游戏性不如单机。 『胡扯!我觉得网游比单机好玩多了。』 『好,本文到...

    沙因Sign
  • K-Means算法的10个有趣用例

    源 | AI Zone K-means算法具有悠久的历史,并且也是最常用的聚类算法之一。K-means算法实施起来非常简单,因此,它非常适用于机器学习新手爱好者...

    昱良
  • 用C# (.NET Core) 实现抽象工厂设计模式

    本文的概念性内容来自深入浅出设计模式一书. 上一篇文章讲了简单工厂和工厂方法设计模式 http://www.cnblogs.com/cgzl/p/8760250...

    solenovex
  • 『AI』人工智能 - 禁忌的人体炼成

    很久以前,人工智能和AI被一部分人当作两种不同的东西。他们认为,应用在科技或生活的机器人身上的那些才配叫『人工智能』,而应用在游戏里的只配叫『AI』。 至于『很...

    沙因Sign
  • “没有IoT我就睡不着!”:医疗保健领域的物联网

    我不太清楚IoT技术在我们的日常生活中渗透到多快和多深,直到我的朋友告诉我有关他的打鼾和他失眠的夜。

    Thunder Kevin
  • 叫醒你的观众

    台上的主持人慷慨激昂,台下的观众却昏昏欲睡;“麦霸”们互相争夺着话筒不肯撒手,听众却一脸惬意的玩弄着自己的手机;每当主持人提问时,原本人声嘈杂的会议室,仿佛是被...

    ThoughtWorks
  • Caffe源码---Blob基本使用

    看到这个的时候,估计你也在学习caffe,嘿嘿!Blob在内存中表示4维数组,维度从低到高为(width_,height_,channels_,num_)。Bl...

    计算机视觉战队
  • 论文阅读——Selective Search for Object Recognition

    今天认真把Selective Search for Object Recognition这篇文章阅读完,想来写写自己的见解与想法。如果有错,希望得到大牛们的指点...

    计算机视觉战队
  • 月千之夜

    这个是2012年做的一个游戏。 ======== 主角的控制方式: 右键移动, 按Q键角色会朝鼠标方向冲刺,冲刺位移距离大,但是冲刺过程不是无敌的,且伤害一般...

    沙因Sign
  • (三)Lua脚本语言入门

    又要找工作了,变的忧虑了,唯有学习才让内心变得踏实,今天玩了一下午的王者荣耀,正事都忘了...... 如果认为所谓的毅力是每分每秒的“艰苦忍耐”式的奋斗,那这是...

    杨奉武

扫码关注云+社区

领取腾讯云代金券