之前看到〈『致敬赵雷』基于TensorFlow让机器生成赵雷曲风的歌词〉這篇文章覺得非常有趣,因此一直都想自己動手試試看,中國有趙雷,那台灣要找什麼值得紀念的音樂人來作這個歌詞機器學習模型呢?我想張雨生應該會是台灣非常值得令人紀念的音樂人之一了。

程式的基礎我使用了之前在 GitHub 上有點小小貢獻的一個 Project 作為程式碼基礎,這個 Project 是 char-rnn-tf,可以用於生成一段中文文本(訓練與料是英文時也可以用於生成英文),訓練語料庫我收集了張雨生的百餘首歌詞(包含由張雨生演唱或作曲的歌詞),由於這樣的歌詞語料還是有些不足,因此也加入了林夕、其他著名歌詞、新詩作為輔助,整個語料庫大致包含 74856 個字、2612 個不重複字(其實語料庫還是不足)。

演算法基本上就是 LSTM,細節在此就不多加著墨,若有興趣可以在這篇文章了解一下,沒有時間的人,也可以看看 char-rnn-tf 這個 Project 作者所做的這張圖(見下圖),對概念了解一下。

https://github.com/hit-computer/char-rnn-tf/blob/master/model.jpg?raw=true

相關程式碼我放在這邊:Tom-Chang-Deep-Lyrics,如何安裝環境、如何訓練、如何生成歌詞,基本上都寫在 Readme 了,大家可以前往瞧瞧。


歌詞產生結果

範例一:夢想

訓練完模型之後(用 macbook air 大致上需要 1 天的時間),由於大眾對張雨生歌詞的印象應該就是「我的未來不是夢」,因此我首先使用「夢想」作為 seed,結果產生歌詞如下:

夢想會有心
我不願再區福 也不是一種把你一樣偷偷
我的心中有無奈

在我的心裡流 你的身影 你的轉身 你的沈靜 框進畫裡印象派的意

我有個朋友聽我說故舊 這一路悠揚的街長
我是天堂飄輝在天空裡
期待愛人看不同的眼睛
我等待與你身邊
你的歡念 你的灑明 在我心底都是飄逸水墨

我想你 愛過了我的一切
為你一起孤定我的美麗

產生的結果,歌詞機器學習模型先把詞補成句子「夢想會有心」,其實補得蠻好的啊!

「我不願再區福 也不是一種把你一樣偷偷 我的心中有無奈」

這邊雖有錯字,但也不至於不能理解。

「在我的心裡流 你的身影 你的轉身 你的沈靜 框進畫裡印象派的意」

這裡則結合了一首新詩,自創了歌詞。’

「我有個朋友聽我說故舊 這一路悠揚的街長」

這一句歌詞結合了張雨生的歌曲永公街的街長,說明歌詞機器學習模型的確有張雨生的影子,但悠揚的街長感覺怪怪的 XD


範例二:我的未來不是夢

從上一個範例,我們可以了解這個歌詞機器學習模型的效果還算不錯,且看起來比起〈『致敬赵雷』基于TensorFlow让机器生成赵雷曲风的歌词〉這篇所產生的歌詞還要好,仔細看趙雷歌詞產生的結果就會覺得歌詞有點不知所云,而我這邊訓練完的結果,看起來語意會比較明確一些。

接著上個範例,我們來試試看「我的未來不是夢」作為 seed。

我的未來不是夢
我只是真的勇敢

我是一棵秋天的樹 枯少的葉片顯過我
如果有愛能值得這些愁
這個世界保持安靜的距離

熱鬧容易 難得孤寂
我才捨不得問自己
從哪裡來又沒有用 感情和你的歸懷

你是我的姊妹
你是我的 BABY
讓我們的是 BAD BOY 難道我曾經默默縱容 那全是你犯的錯 喔

你贏 我不想與你再爭辯
我說你贏 我再也不想爭辯 請你轉過頭 我有哭泣的尊嚴
我是你的 BABY 我說得再多

「我的未來不是夢 我只是真的勇敢」

如果少了「只」感覺會更好一些。

「我是一棵秋天的樹 枯少的葉片顯過我 如果有愛能值得這些愁」

這邊則是致敬了張雨生的「我是一棵秋天的樹」的歌詞。

「你是我的姊妹」、「讓我們的是 BAD BOY」、「你贏 我不想與你再爭辯」

這邊則結合了「姊妹」「BAD BOY」「你贏」三首歌詞,有些地方說得通,但其實很難讓整首歌詞語意一致,這是目前這個歌詞機器學習模型需要改善的地方。


範例三:永遠不回頭

接下來試試經典歌曲「永遠不回頭」作為 seed。

永遠不回頭
我只能誠實你只能真摰 你無需幻想你無需作夢

當舞台來喝采聲星 為你的心呢的旋律
我是如此的愛 被我無深在心靈
我的愛沒有書香的清澈 我的愛沒有酒醇的狂語
我的愛沒有鑽石的雨 我是真的 人是假的唯

我要你的愛不曾衰竭 只要越來越不知道那無遲

別用你的眼 用我的心
好好一些感動

我在你心裡面看不見
我的世界裡用天地溫柔
永遠的感覺你和你

「永遠不回頭 我只能誠實你只能真摰 你無需幻想你無需作夢」

語意上蠻貼切的。

「別用你的眼 用我的心 好好一些感動」

「我在你心裡面看不見 我的世界裡用天地溫柔 永遠的感覺你和你」

這邊看不出是致敬哪首歌詞,比較像是歌詞機器學習模型自己從看過的語料中創作出來的,在字彙這麼少的情況下能夠這樣創作真的很不容易,想想自己小時候寫作文就知道這有多難,機器等於是一天學會作文。


範例四:我學會飛翔

接下來使用「我學會飛翔」作為 seed,這是範例中唯一由張雨生寫的歌詞,其他範例都是合作過的歌曲(雖然也都放在語料庫中),哎呀,真不會選範例!

我學會飛翔
深空之前如何困見 那裡有愛的人
為誰呼喚我 那一天我依稀回來
我們的愛情是迷霧 我總是深彎

我不能相信 何難自己

當風和日麗 陽春三月天
燦爛的心境 醉人的詩篇
或許紅磚上 或許小湖沿
繽紛的足跡 飛揚的笑靨
純潔的性靈 仿如剛清醒
又似蒙蔽 你的輪廓 在汗水中穿梭的角梗
吐著濃濃的煙霧恣任冥思出星
燦爛的陽光溫暖不到這樣的角落
一想到你呀 就讓我快樂
就好比蜻猴呀穿梭梭林 聚成了身邊

「我們的愛情是迷霧」

這也是歌詞機器學習模型自己創作出來的,覺得蠻厲害的。

「當風和日麗 陽春三月天 燦爛的心境 醉人的詩篇」

這邊的詞有點高水準,所以其實是 Overfitting,抄了張雨生的「三月的天真」這首歌詞。


範例五:沒有菸抽的日子

接下來試試另一首經典歌曲「沒有菸抽的日子」作為 seed。

沒有菸抽的日子 喔

蒼匆的年宴不想留念你的存在
等待那一天鐘
不能說
我不會知道該怎麼做

當秋天葉落 西風來臨後
樹靈的枯枝 曳搖千萬萬 搖積不再有不停 是否不能呼吸
你也能夠 不顧

常常常覺得對自己嗎 難道我真的更好

oh 不醉 就學不會

好男人是不是都躲在家裡
為何身邊六塊肌全對女人沒興趣
有時我真懷疑 纏綿悱惻的劇情
幸福結局 只出現在日劇
女人的心 好比 放大鏡

「沒有菸抽的日子 喔」

「oh 不醉 就學不會」

這兩句真的喔的很貼切啊!很可惜後面 Overfitting 了~


範例六:漂向北方

最後我們來試試不是張雨生的歌曲看看,刻意選了近期還蠻紅的歌曲「漂向北方」作為 seed。

漂向北方 別問我家鄉
直到昏景 等到癡邊

我期待 在我的窗中
你給我一個感覺
肯定的愛情
擁有工作我的愛 請我的愛沒有書醇的狂向
直到傻風上煙中深起
你知道我不會猜你

我的笑容隨著煦煦和風 溫暖吹襲一股月色迷濛
我的歌聲衝出節節喉嚨 騷動八方就該天地星座 快同我怒吼

大度能寬容 滄海樂悠悠 誰又不想放下身段快意自由
失意也會有 得意也會有 反正都是生不帶來死不帶走

「漂向北方 別問我家鄉 直到昏景 等到癡邊」

補完的詞還不錯,「等到癡邊」比較不能理解,但算是有趣的創作吧。

「我期待 在我的窗中 你給我一個感覺 肯定的愛情」

致敬了我期待,感覺真的有在期待的感覺。

後面好像 Overfitting 了張雨生的「門外還有愛」,但整首詞的語意還算一致,算是一個不錯的結果。


以上就是這個「基於 LSTM 深度學習方法研發而成的張雨生歌詞產生模型」的實驗結果,產生的詞算是可讀,而且有些還蠻有意思的,比較大的問題是上下文的語意可能會不一致,這樣的問題目前也有很多論文在解了,大體上就是用多層的 LSTM,可以將句子為 level 做 Encode 之後做一層 LSTM,將段落為 level 做 Encode 之後做一層 LSTM,結合原本的字詞 level 的 LSTM 模型,應該就可以做出上下文語意一致的歌詞產生模型了,如果大家有做出來,別忘了分享一下啊!

前言

本系列部落格文章將分享我在 Coursera 上台灣大學林軒田教授所教授的機器學習技法(Machine Learning Techniques)課程整理成的心得,並對照林教授的投影片作說明。若還沒有閱讀過 第 15 講 的碼農們,我建議可以先回頭去讀一下再回來喔!

範例原始碼:FukuML - 簡單易用的機器學習套件

我在分享機器學習基石課程時,也跟著把每個介紹過的機器學習演算法都實作了一遍,原始碼都放在 GitHub 上了,所以大家可以去參考看看每個演算法的實作細節,看完原始碼會對課程中的數學式更容易理解。

如果大家對實作沒有興趣,只想知道怎麼使用機器學習演算法,那 FukuML 絕對會比起其他機器學習套件簡單易用,且方法及變數都會跟林軒田教授的課程類似,有看過課程的話,說不定連文件都不用看就會使用 FukuML 了。不過我還是有寫 Tutorial 啦,之後會不定期更新,讓大家可以容易上手比較重要!

熱身回顧一下

上一講中我們學到了如何使用矩陣分解方法來解推薦問題,機器學習技法課程也到這邊告一段落了,這一講終將會總結回顧一下我們在機器學習技法中學到的所有機器學習演算法,也許還有許多算法沒有介紹到,但基本概念都可以延伸。

特徵技巧:Kernel

我們學習到了如何使用 Kernel 來表現資料特徵,使用到 Kernel 技巧的相關演算法如下:

特徵技巧:Aggregation

我們也可以使用 Aggregation 方法來結合資料特徵,藉以合成更強大的學習演算法,使用到 Aggregation 技巧的相關演算法如下:

特徵技巧:Extration

我們可以使用 Extration 技巧來取得重要的資料特徵,使用到 Extration 技巧的相關演算法如下:

特徵技巧:Low-Dim

我們也會使用降維這個特徵技巧來取得資料的重要特徵,用到降維技巧的相關演算法如下:

優化技巧:Gradient Decent

在類神經網路大量用到了 Gradient Decent 技巧來進行 Error 優化,用到 Gradient Decent 技巧的相關演算法如下:

優化技巧:Equivalent Solution

在許多困難的問題,我們很難找到優化的方法,我們會使用 Equivalent Solution 找到優化的方法,例如 Dual SVM 我們使用 covex QP、Kernel LogReg 我們用 representer、PCA 我們用 eigenproblem 來解。

未來若需要發展自己的演算法,也可以朝 Equivalent Solution 去想優化方法,只是這可能需要大量的數學推理知識。

優化技巧:Multiple Steps

有一些演算法我們會用 Multiple Steps 來一步一步進行優化,,用到 Multiple Steps 技巧的相關演算法如下:

過擬似技巧:正規化

由於演算法的能力越來越強,也因此很容易過擬似(Overfitting),所以我們必須要有方法來避免過擬似,其中一個方式就是正規化,我們大致學過的正規化方法如下:

過擬似技巧:Validation

另外我們也需要使用 Validation 方法讓我們在訓練過程就可以避免過擬似,在機器學習技法中我們學到的一些演算法有因為演算法特性而發展出來的 Valdation 方法:

機器學習叢林

林軒田老師在機器學習技法課程的一開始就有放過這樣一張投影片,我們進入的是一個機器學習的叢林,從一開始可能對這投影片的所有演算法都不了解,但在這課程的尾聲我們重新回顧,相信大家多少都已經認識了這個叢林的險惡,也了解這個叢林是個多麽有趣與豐富!

前言

本系列部落格文章將分享我在 Coursera 上台灣大學林軒田教授所教授的機器學習技法(Machine Learning Techniques)課程整理成的心得,並對照林教授的投影片作說明。若還沒有閱讀過 第 14 講 的碼農們,我建議可以先回頭去讀一下再回來喔!

範例原始碼:FukuML - 簡單易用的機器學習套件

我在分享機器學習基石課程時,也跟著把每個介紹過的機器學習演算法都實作了一遍,原始碼都放在 GitHub 上了,所以大家可以去參考看看每個演算法的實作細節,看完原始碼會對課程中的數學式更容易理解。

如果大家對實作沒有興趣,只想知道怎麼使用機器學習演算法,那 FukuML 絕對會比起其他機器學習套件簡單易用,且方法及變數都會跟林軒田教授的課程類似,有看過課程的話,說不定連文件都不用看就會使用 FukuML 了。不過我還是有寫 Tutorial 啦,之後會不定期更新,讓大家可以容易上手比較重要!

熱身回顧一下

上一講介紹了 RBF Network,基本上就是透過距離公式及中心點來對資料點進行投票的一個算法,這一講將介紹矩陣分解系列的算法。

推薦系統問題

之前的課程中曾經提到過推薦系統的問題,我們的資料集是使用者對電影的評分,希望讓機器學習算法學習到可以推薦使用者也會高評分的電影,這樣的問題 Netflix 曾經舉行過競賽。我們如何解這樣的問題呢?

類別編碼

這個問題首先會需要進行編碼,因為使用者資料可能只是一連串的使用者編號,這是類別資料,不太能用來直接用於運算(僅有 Decision Tree 可以直接用來做類別運算),所以我們會先將類別資料編碼成數值資料,編碼的方法常用 binary vector encoding,如下所示:

特徵選取

我們可以將使用者評分電影的過程視做一組特徵轉換,能夠將 X 轉換成 Y,轉換的過程如果分成兩個矩陣 Wni、Wim,那左邊的矩陣代表的意義就是使用者對電影中哪些特徵很在意,右邊的矩陣代表的意義就是電影中有哪些特徵成份。

矩陣分解

因此這個推薦問題可以寫成底下的矩陣分解,首先我們把評分做成一個 Rnm 矩陣,需要嘗試把它分解成 VT W 兩個矩陣,使用者的喜好會對映一組特徵,電影的成分也會對應到這組特徵,我們要將這組特徵萃取出來。

矩陣分解學習 Alternating Least Squares

矩陣分解學習算法如下,首先決定特徵維度 d,然後隨機初始化使用者對特徵的喜好 Vn,電影中特徵的強度 Wm,然後優化 Ein,先固定 Vn 去優化 Wm,再固定 Wm 去優化 Vn,如此重複直到收斂,這樣就可以得到與 Rnm 最相似的 Vn X Wm。

Linear Autoencoder vs 矩陣分解

之前介紹過的 Linear Autoencoder 基本上也是一種矩陣分解,但意義上有些不同。

使用隨機梯度下降法解矩陣分解

我們也可以使用隨機梯度下降法來解矩陣分解的問題,與 Alternating Least Squares 比起來,隨機梯度下降法速度較快,且比較簡單。

觀察 Error Function

隨機梯度下降是計算某個點的梯度來進行優化,所以我們可以用一個點作為範例來看看梯度優化的式子,例如我們要對 Vn 進行優化時,只要對 Vn 進行偏微分,即可得到優化的數學式,同理要對 Wm 進行優化時,也只要對 Wm 進行偏微分即可。

矩陣分解學習 SGD

因此 SGD 矩陣分解學習算法如下,首先一樣先決定特徵維度 d,然後隨機初始化使用者對特徵的喜好 Vn,電影中特徵的強度 Wm,然後隨機選取 Rnm 中的一點,計算 Rnm - WmVn,然後各自做偏微分取得新的 Vn 及 Wm 直到收斂。

矩陣分解學習 SGD 實務

林軒田老師分享了矩陣分解學習 SGD 算法在實務上的應用,由於在 KDDCup 2011 年的問題中,測試資料與訓練資料是在不同時間收集到的,因此可以說是不同的資料分布,在做訓練上可能需要將時間的因素考量進去這樣未來做預測才會準確。

使用 SGD 矩陣分解學習算法,我們可以在訓練過程中讓後半段的訓練資料都選取較新的訓練資料,因此可以將時間因素也同時考量在訓練過程中了,這樣的調整讓台大隊伍拿下了比賽的冠軍。如果了解了機器學習算法的細節,我們就可以因應不同的問題做調整。

總結

在這一講中,我們學到了如何使用矩陣分解方法來解推薦問題,矩陣分解的演算法可以使用 Alternating Least Squares 或是隨機梯度下降法,雖然目前網路上已經一大堆矩陣分解程式可以使用,但當遇到要適度調整演算法的時候,了解實作演算法細節便可以自行調整以解決真實世界會遇到的問題。

前言

本系列部落格文章將分享我在 Coursera 上台灣大學林軒田教授所教授的機器學習技法(Machine Learning Techniques)課程整理成的心得,並對照林教授的投影片作說明。若還沒有閱讀過 第 13 講 的碼農們,我建議可以先回頭去讀一下再回來喔!

範例原始碼:FukuML - 簡單易用的機器學習套件

我在分享機器學習基石課程時,也跟著把每個介紹過的機器學習演算法都實作了一遍,原始碼都放在 GitHub 上了,所以大家可以去參考看看每個演算法的實作細節,看完原始碼會對課程中的數學式更容易理解。

如果大家對實作沒有興趣,只想知道怎麼使用機器學習演算法,那 FukuML 絕對會比起其他機器學習套件簡單易用,且方法及變數都會跟林軒田教授的課程類似,有看過課程的話,說不定連文件都不用看就會使用 FukuML 了。不過我還是有寫 Tutorial 啦,之後會不定期更新,讓大家可以容易上手比較重要!

熱身回顧一下

上一講介紹了深度學習神經網路,基本上神經網路林軒田老師只說明了兩講,這一講將進入一個新的 Machine Learning 演算法 Radial Basis Function Network(我個人不太覺得這個是神經網路演算法),並延伸介紹了其中會使用到的 K-means 分群演算法。

回顧一下 Gaussian SVM

Gaussian Kernel 也稱為是 Radial Basis Function(RBF),定義一種距離關係,Gaussiam SVM 也就是使用這些 RBF 經過線性組合的預測模型。

RBF Network 的定義

RBF Network 定義是資料點與代表性中心點投票出來的結果作為預測,其中每個中心點具有代表性,資料點經過 RBF 距離公式的轉換之後(距離越小,越有影響力),再經過 beta 投票。

而 RBF Network 要學習的參數就是中心點 u 以及每個中心點距離公式的權重 beta。

Full RBF Network

了解定義之後,我們就要求出 RBF Network 最佳化的 u 及 beta,一種情況我們是將所有的資料點都當成是重要的中心點,這種情況,然後 beta 直接用 y 當成加權,這樣就是所謂的 Full RBF Network,這樣的預測模型就完全沒有訓練過程,只要將所有的點記下來,然後用 RBF 距離公式計算投票來定義新的資料點應該是屬於什麼。

Nearest Neighbor

由於每次預測都要使用所有的訓練資料點來計算預測結果很費力,我們從距離公式可以了解,投票結果大部分會受最近距離的中心點影響,所以我們其實可以只看最近一點中心點的 RBF 投票結果就好,這就是所謂的 Nearest Neighbor,如果是看最近 k 點中心點的 RBF 投票結果就是所謂的 K Nearest Neighbor。

Beta 不使用相同權重

Full RBF Network 的 Beta 使用相同權重其實就是 Nearest Neighbor,現在我們不想要讓 Beta 使用相同權重,因此要透過訓練資料來計算出最佳的 Beta 權重,最佳的 Beta 有公式解,且這個結果會讓 RBF Network 得到 Ein=0,這樣其實會有 overfitting。

使用更少的中心點來正規劃

我們從 SVM 中看到 SVM 其實只考慮了幾個點(SV)來決定胖胖的線,那 RBF Netwrok 應該也可以用同樣的概念來找出幾的重要的中心點,然後再來計算出最佳的 beta 就好,這樣就可以避免 overfitting。

中心點如何決定?

中心點如何決定並不是一個簡單的問題,我們必須要找出讓訓練資料跟各中心點距離最小,然後又要找出訓練資料最佳的分組結果,這是無法找出最佳化公式的問題。

分別最佳化(1)

其中一個方法就是做最佳化,首先假設我們已經決定了最佳的中心點,那要算出資料點應該要分在哪個中心點的分組就非常容易,就看跟哪個中心點距離最小就可以了。

分別最佳化(2)

假設現在分組已經決定了,找出最佳化的中心點也很容易,將距離公式進行微分資料就可以知道最佳的中心點就是分組所有資料點的平均。

K-Means 算法

經過以上的推導,我們可以知道 K-Means 演算法如下:

  1. 先隨意從資料點找出 k 個資料點當成是初始的中心點
  2. 計算資料點的分組
  3. 資料分完組之後,計算各組資料點的平均當成是新的中心點
  4. 重複 2 跟 3 直到中心點不再改變

RBF Network 搭配 K-means 中心點

現在我們將 RBF Netwrok 搭配 K-means 算出的中心點來做出先的 RBF Network 模型:

  1. 使用 K-means 計算出 k 個最重要的中心點(k 要設幾個要自己試,可以用 cross-validation)
  2. 將訓練資料 x 經過 k 個 RBF 距離公式進行特徵轉換
  3. 將特徵轉換後的訓練資料跑 linear model 計算最佳化的 beta
  4. 如此就得到了訓練完後具有正規化性質 RBF Network 了

K-means 的問題

K 很難決定、初始化的中心點也會影響分群的結果,這是目前無解的,我們只能透過 cross validation 來決定最好的 k 是幾個,而初始化的中心點只能多試只次來避面模型是落在局部最佳化。

總結

這一章介紹了 RBF Network,基本上就是透過距離公式及中心點來對資料點進行投票的一個算法,而中心點就是一種代表性,為了決定中心點,我們可以使用 K-means,了解 RBF Network 的核心概念之後,覺得 RBF 算是蠻簡單的,幾乎不太需要訓練,相對的,我也覺得 RBF Network 的用處比較沒那麼大。

前言

本系列部落格文章將分享我在 Coursera 上台灣大學林軒田教授所教授的機器學習技法(Machine Learning Techniques)課程整理成的心得,並對照林教授的投影片作說明。若還沒有閱讀過 第 12 講 的碼農們,我建議可以先回頭去讀一下再回來喔!

範例原始碼:FukuML - 簡單易用的機器學習套件

我在分享機器學習基石課程時,也跟著把每個介紹過的機器學習演算法都實作了一遍,原始碼都放在 GitHub 上了,所以大家可以去參考看看每個演算法的實作細節,看完原始碼會對課程中的數學式更容易理解。

如果大家對實作沒有興趣,只想知道怎麼使用機器學習演算法,那 FukuML 絕對會比起其他機器學習套件簡單易用,且方法及變數都會跟林軒田教授的課程類似,有看過課程的話,說不定連文件都不用看就會使用 FukuML 了。不過我還是有寫 Tutorial 啦,之後會不定期更新,讓大家可以容易上手比較重要!

熱身回顧一下

上一講說明了什麼是類神經網路,以及類神經網路的核心演算法 Backpropagation,及如何使用 Gradient Decent 算法來計算最佳解,這一講將介紹類神經網路的延伸 - 深度學習。

不過林軒田的課程在深度學習的介紹上只有一講,其實並不是很深入,大家有興趣可以去找李宏毅老師的課程來看看。

再看一次類神經網路

讓我們再看一次類神經網路,我們知道類神經網路中每一層的神經元就是在做一些細微的 pattern 比對,那我們應該要怎麼設計類神經網路的結構呢?主觀上,你可以設計,客觀上,我們必須對神經網路進行驗證,神經網路的結構在類神經網路這樣的領域上也是個重要的議題。

淺跟深

既然結構是個重要的議題,那淺層跟深層的神經網路有何不同呢?深層的神經網路就是我們所謂的深度學習,一般的淺層神經網路,如果有足夠多的神經元其實已經就能夠解決蠻多問題了,深層神經網路理論上會更強,相對的運算量也會比較大、容易 overfitting,但深層的神經網路是有其物理意義的,也因此深度學習在近年資料量多、運算速度變快之後開始快速發展。

深度學習的物理意義

我們知道類神經網路的每個神經元就是在做 raw data 的 pattern 比對,每個神經元只做非常細微的比對,如果我們再加上一層 layer,那這一層 layer 就是在做前一層 pattern 的 pattern 比對,比對的 pattern 會比前一層更具體,因此加上越多 layer 的話,就能夠將更具體的 pattern 找出來。

因為這樣的特性,我們會將深度學習的方法用在比較無法具體找出 feature 的訊號問題上,像是影像處理、語音處理等等,讓深度學習來幫我們找出具體 pattern。

深度學習的關鍵問題與技術

深度學習所面臨的關鍵問題與技術大概有以下幾項,第一,如何覺得結構是一個問題,有時我們會利用一些領域知識來決定神經網路的結構,比如在影像問題上,我們會使用 CNN 這種特殊結構的神經網路。

另外由於模型很複雜,我們需要更多的資料來做計算,且需要使用 regularization 方法來避免 overfitting,常用的方法有 dropout 及 denoising。

且深度學習是一個比較難最佳化的問題,可能會有很多 local minimum,因此初始的 weight 也會影響最佳化的結果,因此通常需要使用 pre-training 這樣的方法來初始一個比較好的 weight 再來進行最佳化。

林軒田老師認為深度學習近期會有最麽大的進展,regularization 跟 pre-training 的方法也是很重要的原因,在這一講也主要再講這兩個部分。

兩步最佳化深度學習

深度學習演算的架構大概就是先使用 pre-train 把每一層之間的 weight 先算一遍,然後在使用這些 weight 進行 backprop 運算微調。

能保留資訊的 Encoding

我們之後 weight 在神經網路中就是一種 featrue transform,其實就是一種 encoding,如果我們的 weights 能夠保留最多原本的資訊,那就是一種好的 encoding。

我們對每一層的 pre-train 就是要找出每一層的這種好的 encoding。

能保留資訊的神經網

我們先把神經網的每層獨立拿出來做 pre-traing,要讓這一層能夠保留最多原本的資訊,應該要怎麼做呢?其實直觀來想,只要能夠讓原本的 x 經過神經元的處理之後還是跟原來的 x 很接近,那就是一個能夠保留原本資訊的 weight 神經網了。

Autoencoder 的功效

這種 Autoencoder 對於機器學習來說有什麼作用呢?對於 Supervise Learning 來說,這種 information preserving 的神經網是一種對原始輸入合理的轉換,相當於在結構中學習了資料的表達方式,因此能夠重組成原本的資料。

對於 Unsupervise Learning 來說可以用來做 outlier detection,比如 decode 後的某一筆資料與原本很不相似,那這筆資料可能就是 outlier。

基本的 Autoencoder

基本的 Autoencoder 可以看成是單層的神經網路,輸入為 X,輸出也是 X。有了 Autoencoder 我們就可以對 Deep Learning 的每一層神經網做 per-train 了。

Deep Learning 的正規化

Deep Learning 的正規化方式可以用之前學過的概念來引用,像是加上一些限制或是做 early stopping,但這邊要介紹在 Deep Learning 這個問題上比較特別的正規化方法。

Overfitting 的原因

我們再來回想一下 Overfitting,其中一個原因就是 dataset 中有雜訊。

處理雜訊

我們要避免 Overfitting 一個方式就是去除 dataset 中的雜訊。這邊我們轉換一個想法,如果我們為原本的 dataset 加上一些雜訊,會如何呢?

會這樣做的原因,也是來自 Autoencoder 這樣的概念,如果我們將原本的 dataset 加上一些雜訊,在 Autoencoder 中也能 decode 出原本的沒有雜訊的 dataset,那這個 Autoencoder 就是比較能夠忍受雜訊的 Autoencoder,相對的也就是能夠避免 overfitting 了。

Linear Autoencoder

上面介紹的 Autoencoder 本質上是非線性的 Autoencoder,如果我們要使用 Linear Autoencoder,那是否會跟其他的 linear 最佳化問題一樣有個公式解呢?去掉原本神經網的非線性轉換後,得到 Linear Autoencoder 的表達式為:h(x)=WW’x

Linear Autoencoder Error Function

如此 Error Function 就會變成如下所示,我們要讓 X 經過轉換之後差距越小越好,我們要找到最佳的 WW’,在線性代數的特性上,WW’ 可以做 SVD 表示成 VgammaV’,我們的問題就變成了最佳化 gamma 與 V。

先最佳化 gamma

讓我們先最佳化 gamma,在這邊的特性上我們可以看出 I - gamma 越小越好,也就是 gamma 越多 1 越好,gamma 最多的 1 理論上可以到 d’ 個。

再最佳化 V

這邊說明的不是很清楚,可能需要請大家自行去看看林軒田老師的說明,結論上最佳化的 V 就是特徵值最大的 XX’ 的特徵向量。結合以上就可以找出 Linear Autoencoder 的公式解了。

PCA

PCA(主成份分析法)是另一種 Linear Autoencoder 方法,只是這邊的輸出變成是 X - Xbar 去做 Autoencoding,PCA 算是比較知名的方法。

總結

在這一講說明了什麼是 Deep Learning,及在 Deep Learning 中常常會使用到的 pre-train 方法 Autoencoder,Autoencoder 基本上是一種 unsupervise learning,我們也可以使用 Autoencoder 來避免 overfitting,在線性的 Autoencoder 我們可以使用 PCA。

前言

本系列部落格文章將分享我在 Coursera 上台灣大學林軒田教授所教授的機器學習技法(Machine Learning Techniques)課程整理成的心得,並對照林教授的投影片作說明。若還沒有閱讀過 第 11 講 的碼農們,我建議可以先回頭去讀一下再回來喔!

範例原始碼:FukuML - 簡單易用的機器學習套件

我在分享機器學習基石課程時,也跟著把每個介紹過的機器學習演算法都實作了一遍,原始碼都放在 GitHub 上了,所以大家可以去參考看看每個演算法的實作細節,看完原始碼會對課程中的數學式更容易理解。

如果大家對實作沒有興趣,只想知道怎麼使用機器學習演算法,那 FukuML 絕對會比起其他機器學習套件簡單易用,且方法及變數都會跟林軒田教授的課程類似,有看過課程的話,說不定連文件都不用看就會使用 FukuML 了。不過我還是有寫 Tutorial 啦,之後會不定期更新,讓大家可以容易上手比較重要!

熱身回顧一下

上一講我們從 Random Forest 延伸到了 AdaBoost Decision Tree,再從 AdaBoost Decision Tree 延伸到 Gradient Boosting,大家不一定要記住所有演算法的細節,但大致上對 Aggregation 的方式有些概念就可以啦!

如果要記,就要記住這個核心概念:Aggregation Model 可以避免 underfitting,讓 weak learner 結合起來也可以做複雜的預測,其實跟 feature transform 的效果很類似。Aggregation Model 也可以避免 overfitting,因為 Aggregation 會選出比較中庸的結果,這其實跟 regularization 的效果類似。所以使用了 Aggregation 也就是 Ensemble 方法通常也就代表了更好的效果。

這一講我們將開始介紹現在很紅的類神經網路機器學習演算法。

Perceptron 的線性組合

我們先看一下最簡單的類神經網路,其實可以看成是多個 Perceptron 的線性組合,如果之前學過的 Aggregation,這樣組合多個 Perceptron 就能帶來更複雜的學習效果。

單層類神經網路的限制

單層類神經網路可以透過組合越多的神經元來模擬曲線的邊界,用以解決更複雜的問題,但還是有其限制,比如 XOR 及雙曲線這樣的邊界,無論如何都無法透過單層的線性組合來做到,因此我們需要想辦法再延伸單層類神經網路。

多層類神經網路

所以就延伸出了多層類神經網路,就跟邏輯閘設計一樣,多層的架構就可以做出 XOR 這樣的邏輯,多層類神經網路就可以模擬各種各樣的邊界了,一般人家在說的類神經網路其實也就是說多層類神經網路。

在生物上的關係

類神經網路與生物上的神經網路有什麼關係呢?其實類神經網路的架構就是有想要模擬生物上的神經網路,但不完全就跟生物上的神經網路一樣,就跟飛機是模擬鳥類,但跟鳥類飛行實際如何運作並不完全一致。

類神經網路的 output

我們從這個圖探討類神經網路的 output,在 output 之前我們可以把它看成是一個對 x 資料的轉換,x 資料經過各個神經元結合轉換之後,再透過 output 層的線性組合做 voting,如果要做分類就對最後的 output 加上 sign 函數,要做迴歸就直接輸出 output 結果,如果要輸出機率值,就對最後的 output 加上 theta 函數,如此就可以用來解各種常見的 Machine Learning 問題。

特徵轉換

我們再往前看一下 x 在 output 前經過的特徵轉換層,這些轉換層是由許多神經元組成,用來計算複雜的特徵轉換,每個神經元也會做組合與輸出,這邊的組合如果是用線性組合,那在數學意義上,所有的神經網路就是單純的在做線性組合,所以並無法做到複雜的特徵轉換。

所以這邊的組合要跟邏輯閘一樣使用類似 sign 函數來組合,才能組合出複雜的邊界,但 sign 函數組合並不是一個連續函數,因此比較難優化,所以我們會永 tanh 函數來逼近 sign 函數,如此就不僅可以模擬複雜邊界,然後計算也比較容易優化。

類神經網路假設

如上述去界定類神經網路的架構後,我們可以把類神經網路畫成如下圖,我們會有 x 作為輸入,然後經過各層的 weight 計算後,再透過神經元的 tanh 組合,最後再輸出結果,如此我們只剩下如何去計算出各層的 weight 就可以訓練出類神經網路了。

神經元的物理意義解釋

這邊我們可以探討一下神經元的物理意義,我們可以看到前一層的輸出會作為後一層的輸入,如果達到一定程度神經元就會輸出結果,所以其實他就是在做兩層之間的匹配程度,越匹配就越能輸出結果,也就是每個神經元都是在學習某一種 pattern。

如何學習各層之間的 weight?

之前學過的 Gradient Boosting 可以用來解單層的類神經網路,但多層的類神經網路不容易用 Gradient Boosting 來解,這邊需要用 Stochastic Gradient Decent 來解會比較簡單一些。

Backpropagation 演算法

計算類神經網路的 Gradient Decent 需要使用到 Backpropagation 演算法,這邊我跳過了數學推導過程,想要詳細了解我另外推薦李宏毅老師的講解,演算法概觀如下:首先,需要先設定整個類神經網路的 weight value,然後 1. 隨機選取一個資料點 x,2. 計算 forward pass,3 計算 backward pass,4 調整 weight。

(forward 跟 backward pass 分別怎麼計算請看李宏毅老師的講解

通常實務上我們會重複 1 - 3 很多次之後做一個平均再去 update weight,這樣的做法叫做 mini batch。

NN 最佳化的問題

由於類神經網路非常複雜,有很多個凸點,所以很容易在學習過程中得到一個 local minimum 的結果。因此不同的起始 weight 可能會得到不同的最佳化結果,在訓練類神經網路時可以挑不同的起始 weight 來做訓練。

VC Dimension

類神將網路的 VC Dimension 為 V*D,V 是神經元數量,D 是權重的數量,所以如果神經網路的層數跟神經元多起來那 VC Dimension 就會很高,所以可能就會有 overfitting 的現象,這樣就需要做 regularization 來防止 overfitting。

Early Stopping

除了使用一般的逞罰項來做 regularization 之外,類神經網路還是用了另一個方式來做到 regularization,這個方法叫 Early Stopping,至於哪時要 stop 呢?那就要做 validation。

總結

這一講說明了什麼是類神經網路,以及類神經網路的核心演算法 Backpropagation,下一講將介紹類神經網路的延伸 - 深度學習。

前言

本系列部落格文章將分享我在 Coursera 上台灣大學林軒田教授所教授的機器學習技法(Machine Learning Techniques)課程整理成的心得,並對照林教授的投影片作說明。若還沒有閱讀過 第 10 講 的碼農們,我建議可以先回頭去讀一下再回來喔!

範例原始碼:FukuML - 簡單易用的機器學習套件

我在分享機器學習基石課程時,也跟著把每個介紹過的機器學習演算法都實作了一遍,原始碼都放在 GitHub 上了,所以大家可以去參考看看每個演算法的實作細節,看完原始碼會對課程中的數學式更容易理解。

如果大家對實作沒有興趣,只想知道怎麼使用機器學習演算法,那 FukuML 絕對會比起其他機器學習套件簡單易用,且方法及變數都會跟林軒田教授的課程類似,有看過課程的話,說不定連文件都不用看就會使用 FukuML 了。不過我還是有寫 Tutorial 啦,之後會不定期更新,讓大家可以容易上手比較重要!

熱身回顧一下

上一講的 Random Forest 演算核心主要就是利用 bootstrap data 的方式訓練出許多不同的 Decision Trees 再 uniform 結合起來。

AdaBoost Decision Tree

這一講接下來要介紹的 AdaBoost Decision Tree 其實乍看有些類似,但它的訓練資料集並不是透過 bootstrap 來打亂,而是使用之前 AdaBoost 的方式再每一輪資料計算加權 u(t) 去訓練出許多不同的 Decision Tree,最後再以 alpha(t) 的權重將所有的 Decision Tree 結合起來。

權重會影響演算法

由於 AdaBoost Decision Tree 會考慮到權重,因此應該要像之前介紹過的 AdaBoost 會將權重傳進 Decision Stump 一樣,AdaBoost Decision Tree 應該也要將權重傳進 Decision Tree 裡做訓練,但這樣就需要調整 Decision Tree 原本的演算法,我們不喜歡這樣。

轉換一個方式,也許我們可以一樣使用抽樣的方式來將訓練資料依造 u(t) 的權重做抽樣,這樣就可以直接將用權重抽樣玩的訓練資料集傳進 Decision Tree 做訓練,達到相同的效果,如此就不用改原本 Decision Tree 的演算法了。

要使用 Weak Decision Tree

另外要注意的是,如果 AdaBoost Decision Tree 使用了 fully grown 的 Decision Tree,這樣 alpha(t) 就會變得無限大,如此訓練完的 AdaBoost Decision Tree 做預測時就只會參考這個權重無限大的 Decision Tree,這樣就沒有 Aggregation Model 的效果了,我們應該要避免這個問題,所以要使用弱一點的 Decision Tree,比如透過 pruned 來避免 Decision Tree fully grown。

特例:使用 Extremely Pruned Tree

如果 AdaBoost Decision Tree 使用了 Extremely Pruned Tree,比如限制樹的高度只有 1,那這樣其實就是之前學過的 AdaBoost,這是 AdaBoost Decision Tree 中的一個特例。

Gradien Boost

這邊的數學演算太過複雜,大家可以直接觀看影片學習,我這邊直接說數學推導最後得出來的結論。

AdaBoost 透過一些數學特性的推導之後,可得出圖中的式子,代表要最佳化 binary-output Error,這個式子可以換成是要算 real-output Error,這樣就是所謂的 Gradien Boost。

由於 real-output Error 的最佳化是一個連續函數,我們可以使用跟之前的 logistic regression 一樣的方式使用 gradient decent 找出最佳的 ita 及 h(x)。

Gradien Boost 演算法

Gradien Boost 演算法的數學推導這邊也請大家去看影片,我直接講數學推導完之後得到的結論,整個演算法看起來很簡單,第一步先使用 xn 與餘數 (yn - sn) 做訓練,得出 gt,第二步再使用 gt 對 xn 做資料轉換,再使用 gt(xn) 與餘數 (yn - sn) 做 linear regression 算出 alphat,最後使用 sn + alphat * gt(xn) 得出新的 sn,重複這個過程,將各個 Decision Tree 結合起來就是 Gradien Boost Decision Tree 了!

Blending Models

課程到這邊已經介紹完了 Blending Models 的各種形式,有 uniform、non-uniform、conditional 的形式,uniform 可以帶來穩定性,non-uniform 及 conditional 可以帶來模型複雜度,但要小心 overfiting。

Aggregation Learning Model

從上述的 blending 方式,我們可以發展出不同的 Aggregation Model,如 Badding 使用 uniform vote、AdaBoost 使用 linear vote by reweighting、Decision Tree 使用 conditional vote、GradientBoost 使用 linear vote by residual(餘數) fitting。

Aggregation Model 的好處

Aggregation Model 可以避免 underfitting,讓 weak learner 結合起來也可以做複雜的預測,其實跟 feature transform 的效果很類似。Aggregation Model 也可以避免 overfitting,因為 Aggregation 會選出比較中庸的結果,這其實跟 regularization 的效果類似。所以使用了 Aggregation 也就是 Ensemble 方法通常也就代表了更好的效果。

總結

在這一講,我們從 Random Forest 延伸到了 AdaBoost Decision Tree,再從 AdaBoost Decision Tree 延伸到 Gradient Boosting,基本上對大部分的 Aggregation Model 都有一些認識了。

Fukuball

我是林志傑,網路上常用的名字是 Fukuball。我使用 PHP 及 Python,對機器學習及區塊鏈技術感到興趣。 https://www.fukuball.com

Co-Founder / Head of Engineering at OurSong

Taipei, Taiwan