1. 程式人生 > >多工學習與深度學習

多工學習與深度學習

作者:chen_h
微訊號 & QQ:862251340
微信公眾號:coderpai

多工學習是機器學習的一個子領域,學習的目標是同事執行多個相關任務。比如,系統會同時執行學習兩項任務,以便這兩項任務都有助於別的任務的學習。這是模仿人類智慧的一種方式,即人類如何同時執行多項任務。例如,當你看到一條狗的時候,你可以立即區分出這是一隻狗,而不是別的動物。如果你知道狗的品種,你也可以馬上說出這隻狗的品種來。我們再來換一個例子,假設我們看到一輛車子,我們可以馬上識別出這是一輛汽車,三輪車,還是一輛自行車,並且識別出這輛車的牌子是什麼,而這些識別都不用藉助外在的事物。而這就是多工學習。我們平時寫的模型都是隻能去識別一類事物,比如只能識別出這是一輛車,但是模型並不能告訴你這輛車是什麼牌子的。在多工中,我們可以同時去學習識別當前事物是不是一輛車,還能同時識別這輛車是什麼牌子的。

這一切識別都是發生在我們複雜的大腦中,數十億個神經元相互連在一起,互相作用並一起啟用,從而執行這種非常複雜的分類和識別任務。很早以前,腦科學研究人員一直試圖通過模擬這種方式,在計算機視覺方面取得成功,指導最近深度學習的興起,才有了一點點的突破。隨著神經網路研究工作的進步和在單任務上面取得的卓越成果,使得研究人員也開始大力在多工上面進行研究和學習。因為多工學習是一個非常有泛化性質的工作,比如我們想同時來預測股市的波動和輿情政策的關係,那麼多工學習就會更有幫助,因為它有助於跨任務的資源和引數共享,並且還可以減少單獨訓練兩個模型的訓練時間。

在這篇文章中,我們將分享如何執行 “深度學習中任務學習的步驟”。我們在這裡將使用 TensorFlow 的 Slim API 執行這個任務。如果你不知道 TensorFlow ,那麼你可以去網上先簡單的瞭解以下這個框架的使用方法。

執行多工學習的步驟

  1. 建立資料集
  2. 建立網路架構
  3. 定義多工的損失函式
  4. 訓練模型

問題描述

為了來更清楚的說明這個多工學習,讓我們先來假設一個簡單的問題陳述。假設你想要預測一朵花的型別(玫瑰或者雛菊)以及它的顏色(紅色,粉色或者白色)。這個問題完全符合多工學習的問題,因為我們想要使用同一個網路模型來同時執行兩件事情(當然,如果你想要讓問題更加複雜,你還可以去預測花的形狀之類的問題)。當我們訓練好這個模型的時候,我們就可以得到兩個類別,一個是花的型別(滅鬼或者雛菊)和它的顏色(紅色,粉色或者白色)。

接下來,讓我們開始吧!

1)建立資料集

對於任何的訓練任務,首先的任務都是去建立一個數據集。我們需要資料來訓練我們的神經網路。由於這是一個有監督的學習任務,我們的資料還會包含每張圖片的正確標籤。

對於每一張圖片,我們需要具有兩個任務的標籤,花的型別和花的顏色。我們從谷歌圖片上面下載了很多的圖片資料,花的型別是玫瑰和雛菊,花的顏色是紅色,粉色和白色。最後,我有三種不同顏色的玫瑰和雛菊的 3200 張圖片資料。

在這一步驟之後,我們需要將這個資料集分成訓練集,驗證集和測試集。我們選擇將 60% 的影象作為我們的訓練集合,25% 的影象作為我們的驗證集,最後的 15% 的影象作為我們的測試集。我們可以建立三個獨立的檔案來儲存這三個資訊(影象的地址,花的型別標籤,花的顏色標籤)。比如,在花的型別中,我們設定玫瑰的標籤是 0,設定雛菊的標籤是 1,在花的顏色型別中,我們設定紅色的標籤是 0,設定粉色的標籤是 1,設定白色的標籤是 2。

所以最後我們的資料檔案 train.txt,val.txt 和 test.txt 看起來就是下面這個樣子:

/data/img1.jpg, 0, 1
/data/img2.jpg, 1, 2
/data/img3.jpg, 1, 2
/data/img4.jpg, 0, 0
/data/img5.jpg, 0, 1
/data/img6.jpg, 1, 1
.
.
.

一旦我們有了這些資料檔案,我們就可以轉向下一步驟了,來建立我們的網路架構。

2)建立網路架構

在定義網路結構之前,必須能夠將其視覺化,我們的網路看起來就是如下的網路結構:

在上圖中我們有隱藏層節點,我們稱之為 “共享層”,因為這些層的權重對於這兩個任務都是通用的。然後,我們有每個任務特定的層,稱之為 “任務特定層” ,這些層之間的引數是獨立計算的,不參與跨層共享。在這些特定任務層中,網路學習特定於任務的資訊。每個這些獨立的任務層都會生成一個單獨的輸出結果。具體在我們的例子中,就是來預測花的類別是玫瑰還是雛菊,花的顏色是紅色,粉色還是白色。

(...previous network)
net = fire_module(net, 48, 192, scope='fire7')
net = fire_module(net, 64, 256, scope='fire8')
net = slim.max_pool2d(net, [3, 3], stride=2, scope='maxpool8')
## splitting network here
## ------------------ Network 1 - flower classification ------------
type_net = fire_module(net, 64, 256, scope='type_fire9')
type_net = slim.conv2d(type_net, 2, [1, 1], stride=1, padding=”VALID”, scope='type_conv10')
type_net = slim.avg_pool2d(type_net, [10, 10], padding="VALID", scope='type_avgpool10')
flower_type = tf.squeeze(type_net, [1, 2], name='flower_type')
## ------------------ Network 2 - color classification -------------
color_net = fire_module(net, 64, 256, scope='color_fire9')
color_net = slim.conv2d(color_net, 3, [1, 1], stride=1, padding=”VALID”, scope='color_conv10')
color_net = slim.avg_pool2d(color_net, [10, 10], scope='color_avgpool10')
flower_color = tf.squeeze(color_type, [1, 2], name='color_type')

建立多工學習的網路是非常容易的。我們在這裡使用 Squeezenet 來作為基礎模型,為什麼選用這個模型,是因為我已經熟悉它的架構和網路引數除錯,並且非常熟悉它的效能。所以在這個模型之上,來構建我們的多工模型是非常容易的一件事了。

3)定義多工損失函式

在實際開始訓練我們的網路之前,我們需要定義每個任務的損失函式。我們每個任務的損失函式看起來如下:

flower_type_loss = slim.losses.softmax_cross_entropy(predicted_flower_type, original_flower_type)   
flower_color_loss = slim.losses.softmax_cross_entropy(predicted_flower_color, original_flower_color)

現在,在分別為這些任務定義損失函式之後,我們需要對此進行優化以訓練我們的神經網路。有兩種方法可以做到這一點:

  1. 定義這兩個任務的損失函式,並且分別進行優化。
  2. 定義這兩個任務的損失函式,並且共同優化它們。

第一種方法適用於想要分批進行訓練的資料,我們可以對任務一的資料和任務二的資料進行交替訓練,然後交替優化訓練器。

第二種方法是,如果你想要同事進行學習,那麼聯合學習是更加適合的。你只需要新增損失函式來聯合優化這種損失。這保留了各種單獨任務在同一時間進行訓練的功能。

因為我想對不同任務進行同時訓練,所以我採用了第二種方法。

total_loss = flower_type_loss + flower_color_loss
train = optimizer.minimize(total_loss)

現在,我們不是分別優化兩個損失函式,而是優化單個聯合損失函式。我們定義了我們的優化器函式,它負責最小化我們的聯合損失值 total_loss

4)訓練

一旦我們定義了我們的網路結構,那麼就到了我們去訓練它的時候。請記住,我們已經對我們的資料建立了三個資料檔案,train.txxval.txttest.txt。因此,我們的第一個任務就是將這些資料檔案讀入到我們的訓練模型之中,一旦讀入成功之後,我們就可以開始訓練我們的多工模型了。

總結

在這篇部落格穩重中,我們通過使用非常簡單的問題進行了深度學習的多工學習。它可以推廣到更復雜的問題中去,比如識別面部表情和確定人臉屬性。當你想要使用同一網路執行類似任務時,那麼多工學習是非常有用的。與使用良好總不同模型進行預測相比,這不僅減少了訓練時間,還同事減少了需要推理的工作量。這類模型的最佳應用場景是在移動裝置中,我們需要對其進行優化,以獲得執行時記憶體,電池利用率和 CPU 利用率。