iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 5
0

剛接觸 tensorflow 時,某次想查的 convolution 的呼叫方式,不查還好...一查發現怎麼有這麼多呼叫法...,當時搞得我好亂啊,但後來某次決定專心實驗這幾種差異,才發現其實用起大同小異,那我們這邊就一次把多種方式寫一遍,再從 graph 上觀察。
這邊分別會介紹 tf.nn、tf.layers、slim、keras 共四種方式。

程式碼 main 的部分,我先宣告 placeholder,然後有四個不同 method 分別用部不同方式產生 conv,最後我丟入 ithome 的logo圖片進去,印出最後節點的 shape。

if __name__ == '__main__':
    node = tf.placeholder(shape=[None, 100, 100, 3], dtype=tf.float32)

    nn_out = nn(node)  # 第一種方式
    layer_out = layer(node)  # 第二種方式
    slim_out = slim(node)  # 第三種方式
    keras_out = keras(node)  # 第四種方式

    tf.summary.FileWriter(OUTPUT_PATH, graph=tf.get_default_graph())

    image = cv2.imread('ithome.jpg')
    image = np.expand_dims(image, 0)

    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        sess.run(tf.local_variables_initializer())

        nn_result, layer_result, slim_result, keras_result = \
            sess.run([nn_out, layer_out, slim_out, keras_out], feed_dict={node: image})

        print(f'nn shape: {nn_result.shape}')  # 第一種方式shape
        print(f'layer shape: {layer_result.shape}')  # 第二種方式shape
        print(f'slim shape: {slim_result.shape}')  # 第三種方式shape
        print(f'keras shape: {keras_result.shape}')  # 第四種方式shape

第一種: tf.nn

def nn(input_node):
    with tf.variable_scope('nn'):
        w = tf.get_variable(
            name='weight',
            shape=[FILTER_SIZE[0], FILTER_SIZE[1], 3, NUM_FILTERS], dtype=tf.float32)
        b = tf.get_variable(
            name='bias',
            shape=[NUM_FILTERS],
            dtype=tf.float32)
        out = tf.nn.conv2d(input_node, filter=w, strides=(1, 1), padding='SAME')
        out = out + b
        
    return out

tf.nn 其實是我最常使用的實作方式,但是他非常的底層,所以很多人因此排斥它,你要自己宣告 variable,然後用 tf.nn.conv2d 合併。雖然它最麻煩,但是有時你想高度客製化時,就會需要它,而且其實用久就會習慣了XD

第二種: tf.layers

def layer(input_node):
    out = tf.layers.conv2d(
        input_node,
        NUM_FILTERS, 
        FILTER_SIZE, 
        strides=STRIDES, 
        padding='same', 
        name='layer')
    
    return out

這算是比 tf.nn 簡單的用法,就一行直接套入,有時如果想架個簡單網路跑實驗,我就會使用這支 API 來實作。

第三種: slim

def slim(input_node):
    out = tf.contrib.slim.conv2d(
        input_node, 
        NUM_FILTERS, 
        FILTER_SIZE, 
        stride=STRIDES, 
        padding='SAME',
        activation_fn=None, 
        scope='slim')
    
    return out

slim 是 google 出的一個高階API,但是我自己其實沒什麼用過 slim,所以這邊就簡單寫個範例給大家當參考,但要注意的是,目前 slim 似乎漸漸被淡化,新版的 tensorflow 2.0 建議你使用 keras 這高階的API來實作。

第四種: keras

def keras(input_node):
    model = tf.keras.Sequential([
        tf.keras.layers.Conv2D(
            NUM_FILTERS, FILTER_SIZE, strides=STRIDES, padding='same')
    ], name='keras')
    
    return model(input_node)

Tensorflow 2.0 的新星,但我好像底層有點寫久了,用起來不太習慣,所以這邊我用了 tf.keras.Sequential 來把這單獨一層 conv 包裝起來,其實我也不確定這樣的寫法好不好,單純想 demo 這樣包起來後的 graph 會長怎樣。

我們把四種方式都輸出成graph檢視,就可以看到這些API 的細節啦!
https://ithelp.ithome.com.tw/upload/images/20190913/20107299ffAE1JvxFt.png

tf.nn 和 layers 細部圖:
https://ithelp.ithome.com.tw/upload/images/20190913/20107299g95IHHGPXV.png

slim 和 keras 細部圖:
https://ithelp.ithome.com.tw/upload/images/20190913/20107299PZWCNbcPd5.png

真的建議大家善用 tfevent 檢視你自己的網路,我覺得這是個很棒的 debug 工具。

github原始碼


上一篇
【04】tensorflow 到底該用 name scope 還是 variable scope
下一篇
【06】 tensorflow 細看存檔:checkpoint 篇
系列文
How to Train Your Model 訓模高手:我的 Tensorflow 個人使用經驗系列文31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言