《TensorFlow實戰》—讀書筆記


  我主要用pytorch,但是導師和師兄都用TensorFlow,並且許多論文也是用TensorFlow來復現,出於交流和學習需要看了《TensorFlow實戰》的部分章節,以對TensorFlow有基礎的認識,記錄於此。


 

目錄:

  1 TensorFlow基礎

    1.1 TensorFlow概要

    1.2 TensorFlow編程模型簡介

  2 TensorFlow和其他深度學習框架的對比

  3 TensorFlow第一步

    3.1 TensorFlow的編譯及安裝

    3.2 TensorFlow實現Softmax Regression識別手寫數字

  4 TensorFlow實現自編碼器及多層感知機

    4.1 自編碼器簡介

    4.2 TensorFlow實現自編碼器

    4.3 多層感知機簡

    4.4 TensorFlow實現多層感知機

  5 TensorFlow實現卷積神經網絡

    5.1 卷積神經網絡簡介

    5.2 TensorFLow實現簡單的卷積網絡

    5.3 TensorFlow實現進階的卷積網絡

  6 TensorFlow實現經典卷積神經網絡

    6.1 TensorFlow實現AlexNet

    6.2 TensorFlow實現VGGNet

    6.3 TensorFlow實現Google Inception Net  

    6.4 TensorFlow實現ResNet 

 


 

 

1 TensorFlow基礎

  1.1 TensorFlow概要

  • TensorFlow使用數據流式圖規划計算流程,它可以將計算映射到不同的硬件和操作系統平台。

  1.2 TensorFlow編程模型簡介

  • TensorFlow中的計算可表示為一個有向圖(計算圖),其中每個運算操作為一個節點,每個節點可有任意多個輸入和輸出;
  • 在計算圖的邊中流動(flow)的數據被稱為張量(tensor),tensor在計算圖中flow,故命名為TensorFlow;
  • Session是用戶使用TensorFlow的交互式接口,可通過Session的Extend方法添加新的節點和邊;
  • 反復執行計算圖時一般的tensor不會被持續保留,Variable中的數據tensor會被保存。

 【回到頂部】

2 TensorFlow和其他深度學習框架的對比

 【回到頂部】

3 TensorFlow第一步

  3.1 TensorFlow的編譯及安裝

  3.2 TensorFlow實現Softmax Regression識別手寫數字

  • 載入MNIST數據集
    from tensorflow.examples.tutorials.mnist import input_data
    import tensorflow as tf
    mnist = input_data.read_data_sets("Mnist_data/", one_hot=True)
  • 創建placeholder用以輸入數據
    x = tf.placeholder(tf.float32, [None, 784])
    y_ = tf.placeholder(tf.float32, [None, 784])
    #None代表不限條數的輸入
  • 給模型中的weights和biases創建Variable對象,以存儲模型參數(其他的tensor將不保存)
    W = tf.Variable(tf.zeros([784, 10]))
    b = tf.Variable(tf.zeros([10]))
  • 構建計算公式
    y = softmax(Wx + b)
  • 定義Loss,確定優化器
    cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
    train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
  • 初始化變量,執行計算
    tf.global_variables_initializer().run()
    
    for i in range(1000):
        batch_xs, batch_ys = mnist.train.next_batch(100)
        train_step.run({x: batch_xs, y_: batch_ys})

 【回到頂部】

4 TensorFlow實現自編碼器及多層感知機

  4.1 自編碼器簡介

  • 自編碼器,即可以使用自身的高階特征編碼自己;
  • 特征的稀疏表達:使用少量的基本特征組合拼裝得到更高層抽象的特征;
  • 為防止簡單的映射,加入幾種限制:1. 讓中間隱含層節點數量小於輸入、輸出節點數量,相當於降維  2. 給輸入數據加入噪聲

  4.2 TensorFlow實現自編碼器

  • 用到xavier參數初始化方法
    def xavier_init(fan_in, fan_out, constant = 1):
        low = - constant * np.sqrt(6.0 / (fan_in + fan_out))
        high = constant * np.sqrt(6.0 / (fan_in + fan_out))
        return tf.random_uniform((fan_in, fan_out),
                                                minval=;ow, maxval=high,
                                                dtype=tf.float32)
  • 參數初始化函數_initial_weights(創建一個名為all_weights的字典dict,將w1、b1、w2、b2全部存入其中)
    def _initialize_weights(self):
        all_weights = dict()
        all_weights['w1'] = tf.Variable(xavier_init(self.n_input, self.n_hidden))
        all_weights['b1'] = tf.Variable(tf.zeros([self.n_hidden], dtype=tf.float32))
        all_weights['w2'] = tf.Variable(xavier_init([self.n_hidden,
                                                     self.n_input], dtype=tf.float32))
        all_weights['b2'] = tf.Variable(tf.zeros([self.n_input],
                                                  dtype=tf.float32))
        return all_weights

  4.3 多層感知機簡介

  • Dropout是在訓練時將神經網絡某一層的輸出節點數據隨機丟棄一部分(訓練時小於1,預測時等於1),這等於創造出了很多新的隨機樣本,也算是一種bagging
  • Dropout是在訓練時將神經網絡某一層的輸出節點數據隨機丟棄一部分(訓練時小於1,預測時等於1),這等於創造出了很多新的隨機樣本,也算是一種bagging

    1. 單側抑制

    2. 相對寬闊的興奮邊界

    3. 稀疏激活性

  4.4 TensorFlow實現多層感知機

  • ReLU層權重可以用截斷正態分布進行初始化,偏置可以用一些小的非零值來初始化以避免dead neuron.Sigmoid層權重偏置則都初始化為0即可
  • 使用ReLU作為隱藏層,並添加dropout,就實現了多層感知機

 【回到頂部】

5 TensorFlow實現卷積神經網絡

  5.1 卷積神經網絡簡介

  • CNN最初是為解決圖像識別問題設計,現在也可用於時間序列信號如音頻、文本;
  • CNN要點:局部連接、權值共享、池化層降采樣

    1. 局部連接和權值共享降低了參數量,減輕過擬合

    2. 池化層降采樣進一步降低輸出參數量

  • 只要卷積核數量足夠多,能提取出各種方向的邊或各種形態的點,就可以讓采卷積層抽象出有效而豐富的高階特征;
  • CNN參數量只與卷積核尺寸和個數有關

  5.2 TensorFlow實現簡單的卷積網絡

  • 首先載入MNIST數據集
  • 這個CNN會有很多權重和偏置需要創建,因此先定義初始化函數以便后續重復使用
    def weight_variable(shape):
        initial = tf.truncated_normal(shape, stddev=0.1)
        return tf.Variable(initial)
    
    def bias_variable(shape):
        initial = tf.constant(0.1, shape=shape)
        return tf.Variable(initial)
  • 卷積層、池化層也需重復使用,這里分別定義創建函數
    def conv2d(x, W):
        return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
    
    def max_pool_2x2(x):
        return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
  • 定義輸入:x是特征,y_是真實的label
    x = tf.placeholder(tf.float32, [None, 784])
    y_ = tf.placeholder(tf.float32, [NOne, 10])
    x_image = tf.reshape(x, [-1, 28, 28, 1])
  • 第一個卷積層
    W_conv1 = weight_variable([5, 5, 1, 32])
    b_conv1 = bias_variable([32])
    h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
    h_pool1 = max_pool_2x2(h_conv1)
  • 第二個卷積層
    W_conv2 = weight_variable([5, 5, 32, 64])
    b_conv2 = bias_variable([64])
    h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
    h_pool2 = max_pool_2x2(h_conv2)
  • 第一個全連接層,后接dropout
    W_fc1 = weight_variable([7*7*64, 1024])
    b_fc1 = bias_variable([1024])
    h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
    h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
    
    keep_prob = tf.placeholder(tf.float32)
    h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
  • 第二個全連接層,后接softmax
    W_fc2 = weight_variable([1024, 10])
    b_fc2 = bias_variable([10])
    y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
  • 定義損失函數cross entropy,優化器使用Adam,學習速率1e-4
    cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y_conv), reductioin_indices=[1]))
    train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
  • inference完成后,開始訓練
    tf.global_variables_initializer().run()
    for i in range(20000):
        batch = mnist.train.next_batch(50)
        train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

  5.3 TensorFlow實現進階的卷積網絡

  • 定義初始化weight函數

    1. 這里給weight加一個L2的loss,相當於做了一個L2正則化處理

    2. tf.multiply讓L2 loss與wl(weight loss)相乘,即用wl控制L2 loss的大小(tf.mutmul矩陣乘法、tf.multiply點乘)

    3. 使用tf.add_to_collection把weight loss同意存到名為“losses"的列表中(tf.get_colletion("name")獲取列表)

def variable_with_weight_loss(shape, stddev, wl):
    var = tf.Variable(tf.truncated_normal(shape, stddev=stddev))
    if wl is not None:
        weight_loss = tf.multiply(tf.nn.l2_loss(var), wl, name='weight_loss')
        tf.add_to_collection('losses', weight_loss)
    return var
  • 第一個卷積層
    weight1 = variable_with_weight_loss(shape=[5, 5, 3, 64], stddev=5e-2, wl=0.0)
    kernel1 = tf.nn.conv2d(image_input, weight1, [1, 1, 1, 1], padding='SAME')
    bias = tf.Variable(tf.constant(0.0, shape[64]))
    conv1 = tf.nn.relu(tf.nn.bias_add(kernel1, bias1))
    pool1 = tf.nn.max_pool(conv1, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='SAME')
    norm1 = tf.nn.lrn(pool1, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75)
  • 數據增強(Data Augmentation):對圖片進行翻轉、隨機剪切,制造更多樣本

 【回到頂部】

6 TensorFLow實現經典卷積神經網絡

  6.1 TensorFlow實現AlexNet

  • 使用ReLu,在較深的網絡中效果好於Sigmoid,解決了Sigmoid在深層網絡中梯度彌散問題
  • 使用Dropout,避免模型過擬合
  • 提出LRN
  • 使用CUDA加速訓練
  • 數據增強
    def inference(images):
        parameters = []
        
        with tf.nn.name_scope('conv1') as scope:
            kernel = tf.Variable(tf.truncated_normal([11, 11, 3, 64], 
                                         dtype=tf.float32, stddev=1e-1), name='weights')
            conv = tf.nn.con2d(images, kernel, [1, 4, 4, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[64], dtype=tf.float32),
                                         trainable=True, name='biases')
            bias = tf.nn.bias_add(conv, biases)
            conv1 = tf.nn.relu(bias, name=scope)
            print_activation(conv1)
            parameters += [kernel, biases]
    
            lrn1 = tf.nn.lrn(conv1, 4, bias=1.0, alpha=0.001/9, beta=0.75, name='lrn1')
            pool1 = tf.nn.max_pool(lrn1, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1],
                                                padding='VALID', name='pool1')
            print_activations(pool1)

    6.2 TensorFlow實現VGGNet

     

  •  卷積核都為3x3,池化層都為2x2
  • 3個3x3卷積層串聯相當於1個7x7卷積層(感受野相同),參數為后者55%
  • 使用數據增強
  • vgg16包含很多層,先創建函數conv_op、fc_op和mpool_op
    def conv_op(input_op, name, kh, kw, n_out, dh, dw, p):
        n_in = input_op.get_shape()[-1].value
        
        with tf.name_scope(name) as scope:
            kernel = tf.get_variable(scope+"w", shape=[kh, kw, n_in, n_out], dtype=tf.float32,
                                                initializer=tf.contrib.layers.xavier_initializer_conv2d())
            conv = tf.nn.conv2d(input_op, kernel, (1, dh, dw, 1), padding='SAME')
            bias_init_val = tf.constant(0.0, shape=[n_out], dtype=tf.float32)
            biases = tf.Variable(bias_init_val, trainable=True, name='b')
            z = tf.nn.bias_add(conv, biases)
            activation = tf.nn.relu(z, name=scope)
            p += [kernel, biases]
            return activation
    
    def fc_op(input_op, name, n_out, p):
        n_in = input_op.get_shape()[-1].value
    
        with tf.name_scope(name) as scope:
            kernel = tf.get_variable(scope+"w", shape=[n_in, n_out], dtype=tf.float32,
                                                initializer=tf.contrib.layers.xavier_initializer())
            biases = tf.Variable(tf.constant(0.1, shape=[n_out], dtype=tf.float32), name='b')
            activation = tf.nn.relu_layer(input_op, kernel, biases, name=scope)
            p += [kernel, biases]
            return activation
    
    def mpool_op(input_op, name, kh, kw, dh, dw):
        return tf.nn.max_pool(input_op, ksize=[1, kh, kw, 1], strides=[1, dh, dw, 1],
                                         padding='SAME', name=name)

     

  •  完成創建函數,開始構建VGG16網絡結構
    def inference_op(input_op, keep_prob):
        p = []
        
        conv1_1 = conv_op(input_op, name="conv1_1", kh=3, kw=3, n_out=64, dh=1, dw=1,
                                        p=p)
        conv1_2 = conv_op(conv1_1, name="conv1_2", kh=3,pool1",w=3, n_out=64, dh=1, dw=1,
                                        p=p)
        pool1 = mpool_op(conv1_2, name="pool1", kh=2, kw=2, dw=2, dh=2)
        ...

 

  6.3 TensorFlow實現Google Inception Net

  •  Inception V1去除最后的全連接層,用全局平均池化層代替。(模型訓練更快且減輕了過擬合)
  • 1x1卷積可以跨通道組織信息,提高網絡表達能力,且可以對輸出通道升維、降維
  • 1x1卷積的性價比很高,用很小的計算量就能增加一層特征變化和非線性化
  • 1x1卷積可很自然地把相關性很高的、在同一個空間位置但是不同通道的特征連接在一起
  • 靠后的Inception Module中大面積的卷積核占比更多,以捕捉更高階的抽象特征
  • 用到輔助分類節點(auxiliary classifiers),在Inception Net中間一層的輸出用作分類,並按一個較小權重(0.3)加到最終分類結果中
  • Inception V2提出了Batch Normalization
  • 定義inception_v3_arg_scope用來生成網絡中經常用到的函數的默認參數
    def inception_v3_arg_scope(weight_decay=0.00004, stddev=0.1,
                                                batch_norm_var_collectioin='moving_vars'):
        batch_norm_params = {
            'decay': 0.9997,
            'epsilon': 0.001,
            'updates_collections': tf.GraphKeys.UPDATE_OPS,
            'variables_collections': {
                'beta': None,
                'gamma': None,
                'moving_mean': [batch_norm_var_collectioin],
                'moving_variance': [batch_norm_var_collection],
            }
        }
    with slim.arg_scope([slim.conv2d, slim.fully_connected],
                                    weights_regularizer=slim.l2_regularizer(weight_decay)):
        with slim.arg_scope([slim.conv2d],
                                        weights_initializer=tf.truncated_normal_initializer(stddev=stddev),
                                        activation_fn=tf.nn.relu,
                                        normalizer_fn=slim.batch_norm,
                                        normalizer_params=batch_norm_params) as sc:
            return sc
  • 定義inception_v3_base用來生成Inception V3網絡的卷積部分
    def inception_v3_base(inputs, scope=None):
        end_points = {}
        with tf.variable_scope(scope, 'InceptionV3', [inputs]):
            #前面的卷積層
            with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d],
                                            stride=1, padding='VALID'):
                net = slim.conv2d(inputs, 32, [3, 3], stride=2, scope='Conv2d_1a_3x3')
                net = slim.conv2d(net, 32, [3, 3], scope='Conv2d_2a_3x3')
                ...
            #接着是三個Inception
            #inception 1
            with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d],
                                            stride=1, padding='SAME'):
                
                  #inception 1中的第一個inception module
                 with tf.variable_scope('Mixed_5b'):
                    with tf.variable_scope('Branch_0'):
                        branch_0 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')
                    with tf.variable_scope('Branch_1'):
                        branch_1 = slim.conv2d(net, 48, [1, 1], scope='Conv2d_0a_1x1')
                        branch_1 = slim.conv2d(branch_1, 64, [5, 5], scope='Conv2d_0b_5x5')    
                ...

    6.4 TensorFlow實現ResNet

  • ResNet的殘差學習單元(Residual Unit)不再學習一個完整的輸出H(x),而是學習殘差H(x)-x.ResNet有很多支線將輸入直接連到后面的層,使得后面的層可以直接學習殘差,這種結構被稱為shortcut
  • 兩層的殘差學習單元包含兩個相同輸出通道數的3x3卷積,三層的殘差學習單元則是1x1卷積,3x3卷積,1x1卷積,並且先降維再升維

 

【回到頂部】


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM