https://cloud.tencent.com/developer/news/240669python
你必定據說過『神經網絡絡能夠擬合任意連續函數』這句話。數組
沒錯,經過增長網絡的隱藏層數量和隱藏層大小,你能夠獲得強大的學習網絡,不管是二次三次函數,仍是正弦餘弦,均可以用你的網絡進行無限逼近。網絡
好了,打住,今天我不是來教你逼近這種簡單函數的(這種內容應該在學習深度學習的第一天就已經解決了)。讓咱們來考慮這個狀況——當咱們要擬合的『函數』,不止有一個值會怎樣?函數
嚴格來講,『多值函數』不是嚴謹的定義,良好定義的『函數』在其定義域內的每一個輸入都對應一個輸出,並且只對應一個輸出[1]。然而實際上咱們常常要處理一些多值問題,好比反三角函數(arcsin, arccos 等等),因此如今問題來了,當咱們但願擬合的函數有多個輸出值的時候,咱們的神經網絡模型應該怎麼定義呢?學習
第一個任務:單值函數擬合測試
讓咱們先回憶單值函數是怎麼擬合的,下面我將用 tensorflow 來演示一個超簡單的網絡擬合。咱們首先要設計一個函數,以產生點集,用於後面的擬合,咱們選用的是正弦函數:.net
f(x) = 7.0sin(0.75x) + 0.5x設計
在生成數據的時候,還會加入一些隨機的噪聲。orm
這些數據點可視化的結果是這樣的:blog
如今咱們設計一個具備一個隱藏層的簡單網絡進行擬合,咱們但願用神經網絡模型設計一個函數 y = f'(x),在必定區間上能夠達處處處 |f'(x) - f(x)|
如今咱們看一下結果,其中藍色是訓練數據,紅色是網絡的輸出值,能夠看到,紅色的點幾乎完美地排成了一條階段上升的曲線。
交換座標軸
如今咱們進一步,將數據點的 x 軸與 y 軸交換,這樣咱們就有了一個多值函數的輸入。在 python 中,交換兩個軸的數據很是簡單:
如今咱們的 x 可能會對應多個 y,若是再套用之前的方法,結果就不那麼理想了。
是的,咱們原來的模型已經失效了,不管增長多少層,增大多少節點數,都不能擬合多值函數曲線。因此,如今咱們應該怎麼辦?
混合密度網絡:薛定諤的貓
在前面的代碼中,咱們對於多值函數的預測走入了一個誤區:咱們的神經網絡最後的輸出是一個肯定值,然而實際上咱們須要的是多個『可能』的值。你也許會想,用神經網絡輸出多個值並不難呀,只要定義最後的輸出層節點數大於 1 就能夠了。是的,你能夠定義一個多輸出的網絡(好比 3),而後每次輸出 3 個預測值,然而這個網絡的效果確定是很是差的(你能夠本身思考一下爲何)。
如今咱們換一種思路——假如咱們輸出的不是一個值,而是目標值的一個『可能分佈』,好比當 x=1 時,咱們獲得 y 有兩個取值 { 1, -1 },而且每一個取值的機率都是 0.5。這就像薛定諤的那隻量子疊加態的貓同樣,咱們獲得的結果是一個機率分佈,只有當咱們進行一次『觀察』時,纔會獲得一個具體結果!
使用這個思想設計的網絡就叫混合密度網絡(Mixture Density Network),用處至關大。
你也許會問,機率究竟應該怎麼表示呢,難道是輸出一個相似 one-hot 表示的數組嗎?顯然咱們不能使用 one-hot 來表示這個機率分佈,由於咱們輸出的值域是連續的浮點數,咱們不可能用有限的數組來表達。這裏就要引入一個統計學裏面的很常見的概念了,就是高斯分佈。
高斯分佈的機率密度曲線表示爲:
這裏面的參數只有兩個,一個是均值 mu,一個是標準差 simga,經過改變這兩個量,咱們能夠獲得多樣的機率分佈曲線。
而經過組合多個高斯機率分佈,理論上咱們能夠逼近任意機率分佈。好比將上面的三個分佈按機率 1: 1: 1,混合爲一個分佈:
因此咱們的思路就比較清晰了:咱們要設計這麼一個網絡,輸入 x ,輸出一個混合機率分佈(即多個 mu 和 sigma 的組合值),而咱們須要獲取真正的預測值的時候,就從這麼個混合機率分佈中產生一個隨機值,屢次取隨機值則能夠獲得全部 y 的可能值。混合機率網絡的實現也很簡單,咱們設計一個具備兩個隱藏層的網絡,輸出層節點數爲 12 * 3 個,能夠表示爲 12 個高斯分佈的疊加,咱們用前 12 個節點表示 12 個高斯分佈疊加時各自的權重,而中間 12 個表示平均數 mu,最後 12 個表示標準差 sigma。
咱們的 loss 函數不能是和以前同樣的平方差來表示,咱們但願最大化真實的 y 值在混合機率密度中的機率,將通過標準化的 y_normal 與機率權重相乘,並取對數相加後取相反數,這個結果就是機率聯合分佈的最大似然函數。
運行咱們的網絡:
生成數據測試一下。
注意,因爲咱們獲得的是一個機率分佈,因此還須要根據預測出的聯合機率密度來隨機生成具體的點。在測試中,咱們對於每個輸入 x 都成生 10 個隨機點。最終獲得的生成圖像以下:
wow!完美,咱們的混合密度網絡真的擬合了這個多值函數,雖然有一點小瑕疵,實際上我本身經過增長節點數或者隱藏層後,生成的圖像很是好,你也能夠動手試試。
[1]https://zh.wikipedia.org/wiki/%E5%A4%9A%E5%80%BC%E5%87%BD%E6%95%B0
[2]http://blog.otoro.net/2015/11/24/mixture-density-networks-with-tensorflow/