slim就是TensorFlow的簡(jiǎn)潔版。本篇就是介紹如何使用slim,因?yàn)樽约阂彩莿傞_(kāi)始接觸TensorFlow蕉堰,slim更是用得少,因此悲龟,本篇就當(dāng)做是slim的學(xué)習(xí)記錄屋讶,后面會(huì)不斷更新。
先貼出slim的github须教,這里更詳細(xì)
https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/slim
首先皿渗,導(dǎo)入,在安裝TensorFlow時(shí)轻腺,slim包也一起安裝了乐疆,因此不需要再安裝。
import tensorflow.contrib.slim as slim
基礎(chǔ)操作
slim是TensorFlow的簡(jiǎn)潔版贬养,因此在實(shí)際操作過(guò)程中要簡(jiǎn)單得多挤土。
原生TensorFlow的一個(gè)卷積層:
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就是網(wǎng)絡(luò)輸入;
16是輸出神經(jīng)元個(gè)數(shù)误算;
[3,3]是該層卷積核大小
很簡(jiǎn)單Q雒馈!更簡(jiǎn)單的是儿礼,Slim也提供了兩個(gè)元運(yùn)算符----repeat和stack咖杂,允許用戶(hù)可以重復(fù)地使用相同的運(yùn)算符。
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的作用蜘犁。
解釋?zhuān)?表示重復(fù)slim.conv2d這個(gè)操作3次翰苫,每次輸出神經(jīng)元個(gè)數(shù)都是16,卷積核都是3*3;
那么奏窑,要用不同的參數(shù)怎么辦导披?
可以用slim.stack:
輸出神經(jīng)元個(gè)數(shù)不同:
# 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')
每層網(wǎng)絡(luò)的輸出神經(jīng)元個(gè)數(shù)和卷積核都不同:
# 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機(jī)制類(lèi)型(name_scope, variable_scope)外, TF-Slim添加了一種叫做arg_scope的scope機(jī)制。這種scope允許用戶(hù)在arg_scope中指定若干操作符以及一批參數(shù)埃唯,這些參數(shù)會(huì)傳給前面所有的操作符中撩匕。如果后面不需要這種參數(shù),可以重寫(xiě)墨叛,覆蓋止毕。
原始繁瑣的操作:
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')
簡(jiǎn)單操作:
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'會(huì)覆蓋原來(lái)默認(rèn)的padding='SAME'
net = slim.conv2d(net, 256, [11, 11], scope='conv3')
嵌套操作:
這里最外面的一層scope包含slim.conv2d和slim.fully_connected兩個(gè)共有參數(shù),里面一層scope則只包括slim.conv2d的參數(shù)漠趁。
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')
下面來(lái)一個(gè)slim寫(xiě)的例子扁凛,vgg16的實(shí)現(xiàn):
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
是不是特別精簡(jiǎn)?但其中包含的東西卻很多闯传,需要細(xì)細(xì)體會(huì)谨朝,還好之前走過(guò)原生TensorFlow的路。
這里特別要注意:
在最后一個(gè)全連接層中activation_fn=None甥绿,因?yàn)樽詈笠粚硬恍杓せ詈瘮?shù)字币,而slim.fully_connected()是默認(rèn)使用激活函數(shù)tf.nn.relu的,因此在網(wǎng)絡(luò)模型最后一層中要添加activation_fn=None共缕。
上面的這個(gè)vgg16網(wǎng)絡(luò)就是slim內(nèi)已經(jīng)實(shí)現(xiàn)的網(wǎng)絡(luò)洗出,里面還有很多,可以直接拿來(lái)用图谷,最好還是自己寫(xiě)一下翩活,等有空了一定要全部自己重寫(xiě)一遍,先貼這里https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/slim/python/slim/nets
目前我接觸的就這些蜓萄,后面還會(huì)碰到隅茎,等自己理解了再來(lái)更新吧!嫉沽!
參考文章:
原po寫(xiě)得更多更詳細(xì)辟犀,學(xué)習(xí)了
http://blog.csdn.net/guvcolie/article/details/77686555