TensorFlow之slim

slim就是TensorFlow的简洁版。本篇就是介绍如何使用slim,因为自己也是刚开始接触TensorFlow,slim更是用得少,因此,本篇就当做是slim的学习记录,后面会不断更新。
先贴出slim的github,这里更详细
https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/slim

首先,导入,在安装TensorFlow时,slim包也一起安装了,因此不需要再安装。

import tensorflow.contrib.slim as slim

基础操作
slim是TensorFlow的简洁版,因此在实际操作过程中要简单得多。
原生TensorFlow的一个卷积层:

inputs = ...
    ####conv1
    with tf.variable_scope('conv1') as scope:
        weights = tf.get_variable(scope.name+'_w1',
                               [3,3,3,16],
                               dtype=tf.float32,
                               initializer=tf.truncated_normal_initializer(stddev=0.1, dtype=tf.float32))
        biases = tf.get_variable(scope.name+'_b1',
                               [16],
                               dtype=tf.float32,
                               initializer=tf.constant_initializer(0.1))

        conv = tf.nn.conv2d(inputs,weights,strides=[1,1,1,1],padding='SAME')
        pre_activation = tf.nn.bias_add(conv,biases)
        conv1 = tf.nn.relu(pre_activation,name=scope.name)

在slim中:

inputs = ...
net = slim.conv2d(inputs,16,[3,3],scope='conv1')

inputs就是网络输入;
16是输出神经元个数;
[3,3]是该层卷积核大小

很简单!!更简单的是,Slim也提供了两个元运算符----repeat和stack,允许用户可以重复地使用相同的运算符。

net = ...
net = slim.conv2d(net,16,[3,3],scope='conv1')
net = slim.conv2d(net,16,[3,3],scope='conv1')
net = slim.conv2d(net,16,[3,3],scope='conv1')

上面可以替换为:

net = ...
net = slim.repeat(net,3,slim.conv2d,16,[3,3],scope='conv1')

这就是slim.repeat的作用。
解释:3表示重复slim.conv2d这个操作3次,每次输出神经元个数都是16,卷积核都是3*3;
那么,要用不同的参数怎么办?
可以用slim.stack:
输出神经元个数不同:

# Verbose way:  
x = slim.fully_connected(x, 32, scope='fc/fc_1')  
x = slim.fully_connected(x, 64, scope='fc/fc_2')  
x = slim.fully_connected(x, 128, scope='fc/fc_3')  
  
# Equivalent, TF-Slim way using slim.stack:  
slim.stack(x, slim.fully_connected, [32, 64, 128], scope='fc')

每层网络的输出神经元个数和卷积核都不同:

# Verbose way:  
x = slim.conv2d(x, 32, [3, 3], scope='core/core_1')  
x = slim.conv2d(x, 32, [1, 1], scope='core/core_2')  
x = slim.conv2d(x, 64, [3, 3], scope='core/core_3')  
x = slim.conv2d(x, 64, [1, 1], scope='core/core_4')  
  
# Using stack:  
slim.stack(x, slim.conv2d, [(32, [3, 3]), (32, [1, 1]), (64, [3, 3]), (64, [1, 1])], scope='core')

scope
除了tensorflow中自带的scope机制类型(name_scope, variable_scope)外, TF-Slim添加了一种叫做arg_scope的scope机制。这种scope允许用户在arg_scope中指定若干操作符以及一批参数,这些参数会传给前面所有的操作符中。如果后面不需要这种参数,可以重写,覆盖。
原始繁琐的操作:

net = slim.conv2d(inputs, 64, [11, 11], 4, padding='SAME',  
                  weights_initializer=tf.truncated_normal_initializer(stddev=0.01),  
                  weights_regularizer=slim.l2_regularizer(0.0005), scope='conv1')  
net = slim.conv2d(net, 128, [11, 11], padding='VALID',  
                  weights_initializer=tf.truncated_normal_initializer(stddev=0.01),  
                  weights_regularizer=slim.l2_regularizer(0.0005), scope='conv2')  
net = slim.conv2d(net, 256, [11, 11], padding='SAME',  
                  weights_initializer=tf.truncated_normal_initializer(stddev=0.01),  
                  weights_regularizer=slim.l2_regularizer(0.0005), scope='conv3')

简单操作:

with slim.arg_scope([slim.conv2d], padding='SAME',  
                      weights_initializer=tf.truncated_normal_initializer(stddev=0.01)  
                      weights_regularizer=slim.l2_regularizer(0.0005)):  
    net = slim.conv2d(inputs, 64, [11, 11], scope='conv1')  
    net = slim.conv2d(net, 128, [11, 11], padding='VALID', scope='conv2')    ##这里的padding='VALID'会覆盖原来默认的padding='SAME'
    net = slim.conv2d(net, 256, [11, 11], scope='conv3')

嵌套操作:
这里最外面的一层scope包含slim.conv2d和slim.fully_connected两个共有参数,里面一层scope则只包括slim.conv2d的参数。

with slim.arg_scope([slim.conv2d, slim.fully_connected],  
                      activation_fn=tf.nn.relu,  
                      weights_initializer=tf.truncated_normal_initializer(stddev=0.01),  
                      weights_regularizer=slim.l2_regularizer(0.0005)):  
  with slim.arg_scope([slim.conv2d], stride=1, padding='SAME'):  
    net = slim.conv2d(inputs, 64, [11, 11], 4, padding='VALID', scope='conv1')  
    net = slim.conv2d(net, 256, [5, 5],  
                      weights_initializer=tf.truncated_normal_initializer(stddev=0.03),  
                      scope='conv2')  
    net = slim.fully_connected(net, 1000, activation_fn=None, scope='fc') 

下面来一个slim写的例子,vgg16的实现:

def vgg16(inputs):  
  with slim.arg_scope([slim.conv2d, slim.fully_connected],  
                      activation_fn=tf.nn.relu,  
                      weights_initializer=tf.truncated_normal_initializer(0.0, 0.01),  
                      weights_regularizer=slim.l2_regularizer(0.0005)):  
    net = slim.repeat(inputs, 2, slim.conv2d, 64, [3, 3], scope='conv1')  
    net = slim.max_pool2d(net, [2, 2], scope='pool1')  
    net = slim.repeat(net, 2, slim.conv2d, 128, [3, 3], scope='conv2')  
    net = slim.max_pool2d(net, [2, 2], scope='pool2')  
    net = slim.repeat(net, 3, slim.conv2d, 256, [3, 3], scope='conv3')  
    net = slim.max_pool2d(net, [2, 2], scope='pool3')  
    net = slim.repeat(net, 3, slim.conv2d, 512, [3, 3], scope='conv4')  
    net = slim.max_pool2d(net, [2, 2], scope='pool4')  
    net = slim.repeat(net, 3, slim.conv2d, 512, [3, 3], scope='conv5')  
    net = slim.max_pool2d(net, [2, 2], scope='pool5')  
    net = slim.fully_connected(net, 4096, scope='fc6')  
    net = slim.dropout(net, 0.5, scope='dropout6')  
    net = slim.fully_connected(net, 4096, scope='fc7')  
    net = slim.dropout(net, 0.5, scope='dropout7')  
    net = slim.fully_connected(net, 1000, activation_fn=None, scope='fc8')  
  return net 

是不是特别精简?但其中包含的东西却很多,需要细细体会,还好之前走过原生TensorFlow的路。
这里特别要注意:
在最后一个全连接层中activation_fn=None,因为最后一层不需激活函数,而slim.fully_connected()是默认使用激活函数tf.nn.relu的,因此在网络模型最后一层中要添加activation_fn=None。

上面的这个vgg16网络就是slim内已经实现的网络,里面还有很多,可以直接拿来用,最好还是自己写一下,等有空了一定要全部自己重写一遍,先贴这里https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/slim/python/slim/nets

目前我接触的就这些,后面还会碰到,等自己理解了再来更新吧!!

参考文章:
原po写得更多更详细,学习了
http://blog.csdn.net/guvcolie/article/details/77686555

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

推荐阅读更多精彩内容