<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 七、遷移學習 遷移學習的作用恰如其名。 這個想法是將從一項任務中學到的東西遷移到另一項任務上。 為什么? 實際上,每次都從頭開始訓練整個模型的效率很低,其成功取決于許多因素。 另一個重要原因是,對于某些應用,公開可用的數據集不夠大,無法訓練出像 AlexNet 或 ResNet 這樣的深層架構而又不會過擬合,這意味著無法推廣。 示例應用可以從用戶給出的一些示例中進行在線學習,也可以是細粒度的分類,其中類別之間的差異很小。 一個非常有趣的觀察結果是,由于您凍結了所有其余部分(無論是檢測還是分類),最終的層可以用于完成不同的任務,最終權重看起來非常相似。 這導致了遷移學習的想法。 這意味著在大量數據上訓練的深度架構(例如 ImageNet)可以很好地概括化,以至于其卷積權重可以充當特征提取器,類似于常規的視覺表示,并且可以用于為各種任務訓練線性分類器。 本章旨在教讀者如何在 TensorFlow 中采用現成的訓練有素的模型,更改其結構以及為特定任務重新訓練某些層。 我們將看到遷移學習將如何幫助改善結果并加快訓練時間。 本章涵蓋的主要主題如下: * 使用來自另一個訓練過的模型的權重預先初始化一個模型 * 在需要時使用 TensorFlow 加載模型并凍結/解凍層 # 什么時候? 研究表明,在 ImageNet 上訓練的卷積網絡權重中的特征提取優于常規特征提取方法,例如 SURF,可變形部分描述符(**DPD**),**直方圖定向梯度**(**HOG**)和**詞袋**(**BoW**)。 這意味著無論常規視覺表示如何工作,卷積特征都可以同樣好地使用,唯一的缺點是更深的架構可能需要更長的時間來提取特征。 當在 ImageNet 上訓練深層卷積神經網絡時,第一層中的卷積過濾器的可視化(請參見下圖)顯示,他們學習了*低層*特征,類似于邊檢測過濾器,而卷積過濾器在最后一層學習*高級*功能,這些功能捕獲特定于類的信息。 因此,如果我們在第一個池化層之后提取 ImageNet 的特征并將其嵌入 2D 空間(例如,使用 t-SNE),則可視化將顯示數據中存在一些無中心狀態,而如果在全連接層上執行相同操作,我們將注意到具有相同語義信息的數據被組織成簇。 這意味著網絡可以在更高層次上很好地概括,并且有可能將這種知識遷移到看不見的類別中。 ![](https://img.kancloud.cn/a1/cc/a1cc8c6f8f4bb4a1e15b14a2b596ea1e_783x331.png) 根據對與 ImageNet 相似度較小的數據集進行的實驗,在以下任務上,基于 ImageNet 訓練的基于卷積神經網絡權重的特征比常規特征提取方法的表現更好: * **對象識別**:此 CNN 特征提取器可以成功地對其他類別不可見的數據集執行分類任務。 * **域適應**:這是當訓練和測試數據來自不同的分布,而標簽和類別數相同時。 不同的域可以考慮使用不同的設備或在不同的設置和環境條件下捕獲的圖像。 具有 CNN 功能的線性分類器可以在不同域中成功地將具有相同語義信息的圖像聚類,而 SURF 功能則可以針對特定領域的特征進行過擬合。 * **精細分類**:這是我們要在同一高級類中的子類之間進行分類的時候。 例如,我們可以對鳥類進行分類。 盡管沒有對細粒度數據進行訓練,但 CNN 功能以及邏輯回歸功能的表現優于基線方法。 * **場景識別**:在這里,我們需要對整個圖像的場景進行分類。 在對象分類數據庫上經過訓練的 CNN 特征提取器,頂部帶有一個簡單的線性分類器,其表現優于應用于識別數據的傳統特征提取器的復雜學習算法。 這里提到的某些任務與圖像分類沒有直接關系,圖像分類是 ImageNet 訓練的主要目標,因此有人希望 CNN 功能無法推廣到看不見的場景。 但是,這些功能與簡單的線性分類器相結合,表現優于手工制作的功能。 這意味著 CNN 的學習權重是可重用的。 那么什么時候應該使用遷移學習呢? 當我們有一個任務時,由于問題的性質,可用數據集很小(例如對螞蟻/蜜蜂進行分類)。 在這種情況下,我們可以在包含相似語義信息的較大數據集上訓練我們的模型,然后用較小的數據集僅訓練最后一層(線性分類器)。 如果我們只有足夠的可用數據,并且有一個更大的相似數據集,則對該相似數據集進行預訓練可能會導致模型更健壯。 通常情況下,我們使用隨機初始化的權重來訓練模型,在這種情況下,將使用在其他數據集上訓練過的權重來初始化模型。 這將有助于網絡更快地融合并更好地推廣。 在這種情況下,僅微調模型頂端的幾層是有意義的。 經驗法則是,從網絡頂部開始,可用數據越多,可以訓練的層就越多。 通過預訓練(例如在 ImageNet 上)模型初始化模型權重。 # 怎么樣? 概述 我們應該如何使用轉學? 有兩種典型的解決方法。 第一種不太及時的方法是使用所謂的預訓練模型,即預先在大型數據集(例如 ImageNet 數據集)上訓練過的模型。 這些經過預先訓練的模型可以在不同的深度學習框架中輕松獲得,并且通常被稱為“模型動物園”。 預訓練模型的選擇在很大程度上取決于當前要解決的任務是什么,以及數據集的大小。 選擇模型后,我們可以使用全部或部分模型作為要解決的實際任務的初始化模型。 深度學習的另一種不太常見的方式是自己預先訓練模型。 當可用的預訓練網絡不適合解決特定問題時,通常會發生這種情況,我們必須自己設計網絡架構。 顯然,這需要更多的時間和精力來設計模型和準備數據集。 在某些情況下,用于進行網絡預訓練的數據集甚至可以是合成的,可以從計算機圖形引擎(例如 3D Studio Max 或 Unity)或其他卷積神經網絡(例如 GAN)生成。 可以對虛擬數據進行預訓練的模型在真實數據上進行微調,并且可以與僅對真實數據進行訓練的模型一起很好地工作。 例如,如果我們想區分貓和狗,而我們沒有足夠的數據,則可以從“模型動物園”下載在 ImageNet 上訓練的網絡,并使用除最后一層以外的所有層的權重。 最后一層必須調整為具有與類數量相同的大小,在本例中為兩個,并且權重需要重新初始化和訓練。 這樣,通過將這些層的學習率設置為零或非常小的值(請參見下圖),我們將凍結那些不需訓練的層。 如果有更大的數據集,我們可以訓練最后三個全連接層。 有時,預訓練網絡只能用于初始化權重,然后再進行正常訓練。 遷移學習之所以有效,是因為在初始層計算出的特征更通用并且看起來很相似。 在頂層提取的特征對于我們要解決的問題變得更加具體。 為了進一步研究如何使用遷移學習,以及對該主題的更深刻理解,讓我們看一下代碼。 ![](https://img.kancloud.cn/f6/6f/f66f0e29c073557f1863ef1b5e8bdc77_677x521.png) # 怎么樣? 代碼示例 在本節中,我們將學習在 TensorFlow 中進行遷移學習所需的實用技能。 更具體地說,我們將學習如何從檢查點選擇要加載的層,以及如何指示我們的求解器僅優化特定的層而凍結其他層。 # TensorFlow 有用的元素 由于遷移學習是關于訓練一個網絡的權重,而該網絡已從另一個訓練后的模型中獲取了權重,因此我們將需要找到一個。 在我們的示例中,我們將使用預訓練卷積自編碼器的編碼部分,該部分在第 6 章中進行了說明。 使用自編碼器的優點是我們不需要標記的數據,也就是說,可以完全不受監督地對其進行訓練。 # 沒有解碼器的自編碼器 包含兩個卷積層和一個完全連接層的編碼器(不帶解碼器部分的自編碼器)如下所示。 父自編碼器在 MNIST 數據集上進行了訓練。 因此,網絡將大小為`28x28x1`的圖像作為輸入,并在潛在空間將其編碼為 10 維向量,每個類別一維: ```py # Only half of the autoencoder changed for classification class CAE_CNN_Encoder(object): ...... def build_graph(self, img_size=28): self.__x = tf.placeholder(tf.float32, shape=[None, img_size * img_size], name='IMAGE_IN') self.__x_image = tf.reshape(self.__x, [-1, img_size, img_size, 1]) self.__y_ = tf.placeholder("float", shape=[None, 10], name='Y') with tf.name_scope('ENCODER'): ##### ENCODER # CONV1: Input 28x28x1 after CONV 5x5 P:2 S:2 H_out: 1 + (28+4-5)/2 = 14, # W_out= 1 + (28+4-5)/2 = 14 self.__conv1_act = tf.layers.conv2d(inputs=self.__x_image, strides=(2, 2), name='conv1', filters=16, kernel_size=[5, 5], padding="same", activation=tf.nn.relu) # CONV2: Input 14x14x16 after CONV 5x5 P:0 S:2 H_out: 1 + (14+4-5)/2 = 7, # W_out= 1 + (14+4-5)/2 = 7 self.__conv2_act = tf.layers.conv2d(inputs=self.__conv1_act, strides=(2, 2), name='conv2', filters=32, kernel_size=[5, 5], padding="same", activation=tf.nn.relu) with tf.name_scope('LATENT'): # Reshape: Input 7x7x32 after [7x7x32] self.__enc_out = tf.layers.flatten(self.__conv2_act, name='flatten_conv2') self.__dense = tf.layers.dense(inputs=self.__enc_out, units=200, activation=tf.nn.relu, name='fc1') self.__logits = tf.layers.dense(inputs=self.__dense, units=10, name='logits') def __init__(self, img_size=28): if CAE_CNN_Encoder.__instance is None: self.build_graph(img_size) @property def output(self): return self.__logits @property def labels(self): return self.__y_ @property def input(self): return self.__x @property def image_in(self): return self.__x_image ``` # 選擇層 一旦定義了模型`model = CAE_CNN_Encoder` `()`,選擇將要使用預訓練權重初始化的層就很重要。 請注意,兩個網絡的結構(要初始化的網絡和提供訓練后的權重的網絡)必須相同。 因此,例如,以下代碼片段將選擇名稱為`convs`為`fc`的所有層: ```py from models import CAE_CNN_Encoder model = CAE_CNN_Encoder() list_convs = [v for v in tf.global_variables() if "conv" in v.name] list_fc_linear = [v for v in tf.global_variables() if "fc" in v.name or "output" in v.name] ``` 請注意,這些列表是從`tf.global_variables()`填充的; 如果選擇打印其內容,則可能會發現它包含所有模型變量,如下所示: ```py [<tf.Variable 'conv1/kernel:0' shape=(5, 5, 1, 16) dtype=float32_ref>, <tf.Variable 'conv1/bias:0' shape=(16,) dtype=float32_ref>, <tf.Variable 'conv2/kernel:0' shape=(5, 5, 16, 32) dtype=float32_ref>, <tf.Variable 'conv2/bias:0' shape=(32,) dtype=float32_ref>, <tf.Variable 'fc1/kernel:0' shape=(1568, 200) dtype=float32_ref>, <tf.Variable 'fc1/bias:0' shape=(200,) dtype=float32_ref>, <tf.Variable 'logits/kernel:0' shape=(200, 10) dtype=float32_ref>, <tf.Variable 'logits/bias:0' shape=(10,) dtype=float32_ref>] ``` 將定義圖的層分為卷積和完全連接兩個列表后,您將使用`tf.Train.Saver`加載所需的權重。 首先,我們需要創建一個保存器對象,將要從檢查點加載的變量列表作為輸入,如下所示: ```py # Define the saver object to load only the conv variables saver_load_autoencoder = tf.train.Saver(var_list=list_convs) ``` 除了`saver_load_autoencoder`,我們還需要創建另一個`saver`對象,該對象將允許我們將要訓練的網絡的所有變量存儲到檢查點中。 ```py # Define saver object to save all the variables during training saver = tf.train.Saver() ``` 然后,在使用`init = tf.global_variables_initializer()`初始化圖并創建會話之后,我們可以使用`saver_load_autoencoder`從檢查點恢復卷積層,如下所示: ```py # Restore only the weights (From AutoEncoder) saver_load_autoencoder.restore(sess, "../tmp/cae_cnn/model.ckpt-34") ``` 請注意,調用`restore`會覆蓋`global_variables_initializer`,所有選定的權重都將替換為檢查點的權重。 # 僅訓練一些層 遷移學習的另一個重要部分是凍結不需要訓練的層的權重,同時允許對某些層(通常是最后一層)進行訓練。 在 TensorFlow 中,我們可以僅將要優化的層傳遞給求解器(在此示例中,僅將 FC 層傳遞給): ```py train_step = tf.train.AdamOptimizer(learning_rate).minimize(loss, var_list=list_fc_linear) ``` # 完整代碼 在此示例中,我們將從 MNIST 卷積自編碼器示例中加載權重。 我們將僅恢復編碼器部分的權重,凍結卷積層,并訓練 FC 層以執行數字分類: ```py import tensorflow as tf import numpy as np import os from models import CAE_CNN_Encoder SAVE_FOLDER='/tmp/cae_cnn_transfer' from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/", one_hot=True) model = CAE_CNN_Encoder(latent_size = 20) model_in = model.input model_out = model.output labels_in = model.labels # Get all convs weights list_convs = [v for v in tf.global_variables() if "conv" in v.name] # Get fc1 and logits list_fc_layers = [v for v in tf.global_variables() if "fc" in v.name or "logits" in v.name] # Define the saver object to load only the conv variables saver_load_autoencoder = tf.train.Saver(var_list=list_convs) # Define saver object to save all the variables during training saver = tf.train.Saver() # Define loss for classification with tf.name_scope("LOSS"): loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=model_out, labels=labels_in)) correct_prediction = tf.equal(tf.argmax(model_out,1), tf.argmax(labels_in,1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) # Solver configuration with tf.name_scope("Solver"): train_step = tf.train.AdamOptimizer(1e-4).minimize(loss, var_list=list_fc_layers) # Initialize variables init = tf.global_variables_initializer() # Avoid allocating the whole memory gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.200) sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options)) sess.run(init) # Restore only the CONV weights (From AutoEncoder) saver_load_autoencoder.restore(sess, "/tmp/cae_cnn/model.ckpt-34") # Add some tensors to observe on tensorboad tf.summary.image("input_image", model.image_in, 4) tf.summary.scalar("loss", loss) merged_summary = tf.summary.merge_all() writer = tf.summary.FileWriter(SAVE_FOLDER) writer.add_graph(sess.graph) #####Train###### num_epoch = 200 batch_size = 10 for epoch in range(num_epoch): for i in range(int(mnist.train.num_examples / batch_size)): # Get batch of 50 images batch = mnist.train.next_batch(batch_size) # Dump summary if i % 5000 == 0: # Other summaries s = sess.run(merged_summary, feed_dict={model_in:batch[0], labels_in:batch[1]}) writer.add_summary(s,i) # Train actually here (Also get loss value) _, val_loss, t_acc = sess.run((train_step, loss, accuracy), feed_dict={model_in:batch[0], labels_in:batch[1]}) print('Epoch: %d/%d loss:%d' % (epoch, num_epoch, val_loss)) print('Save model:', epoch) saver.save(sess, os.path.join(SAVE_FOLDER, "model.ckpt"), epoch) ``` # 總結 在本章中,我們學習了如何,何時以及為什么使用遷移學習。 這被認為是一個非常強大的工具,因為它使我們能夠使用從其他領域學到的功能來以較少的數據很好地概括。 我們看了一些示例,現在應該清楚如何在自己的任務中實現遷移學習。 在下一章中,我們將看到如何組織我們的數據以及如何擴展 CNN 架構,以構建準確而實用的機器學習系統。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看