Patchouli的機器學習系列教程六:非監督學習——『器』

Patchouli的機器學習系列教程六:非監督學習——『器』

來自專欄景略集智15 人贊了文章

到目前為止Patchouli的機器學習教程主要集中在回歸問題上,回歸問題是典型的監督式學習。 我們已經在『道』篇中考察了似然函數和目標函數之間的關係,並且展示了如何通過最大似然的方式來找到參數(相當於最小化目標函數),並且在『道』篇中我們也看到了如何用貝葉斯方法來求邊際參數。

Patchouli的機器學習系列教程六:非監督學習——『道』

現在我們將『道』篇中的潛在變數模型(Latent Variable Modelling)相關內容進行擴展,方便大家對這種思想和理念有更加深刻的理解:

潛在意味著一個變數是被隱藏的,是不可以被觀測到的變數,潛在變數的概念在人工智慧至關重要。我們每個人都是低配的福爾摩斯,當我們看到一名男子手裡拿著一個籃球走在路上,我們就可以推斷該男子正在走向籃球場。我們的觀測和推理是發生在一個極為複雜的數據空間中:這個男人穿的衣服,手中拿的籃球,走路的姿勢,手上的綁帶在我們大腦中相互混合,使我們推理出這個人可能要去籃球場。我們其實並不確切地知道這個人要去籃球場,但是我們腦內有一個複雜的世界模型,這個模型拿到這些觀測數據後告訴我們這個結果的可能性很大。

在某種程度上,潛在變數也可以被看作是對於一個非常複雜的場景的壓縮,假如我寫小說寫下這樣一句話:一名男子在到籃球場時被球砸到了。那麼在我們讀者的腦海中對於這個場景的想像會大不相同:有的人可能會想到我上面說的一個穿著背心短褲拿籃球的男子;有的人會想像到搞笑漫畫中一個人被籃球砸的很有張力的那種畫面;還有的人更悲催,他可能會根據個人的經歷想像出第一人稱的場景。

所有的這些想像都來自給予我們對周遭的世界的經驗和期望,根據個人經驗的不同,我們還會做出一些更進一步但不太合理的推測,比如這個男生被球砸是因為在思考事情,也有可能是他的朋友故意欺負他趁他不注意拿球扔他以及等等。基於我們的觀察,所有這些可能性都會增加或減損,但這些仍然是潛在變數。除非我們專門去詢問和調查那些拿球砸他的傢伙,否則我們永遠不知道真正的答案。

很明顯,假如我們想要對任何複雜系統進行推理,潛在變數必然發揮了巨大的作用。在機器人技術中,潛在變數被用來直接表示機器人的狀態:這種狀態通常包括機器人的位置(x,y)、速度以及朝向等等,有人可能要問了為什麼要用潛在變數而不用確切的數據來確定機器人的狀態。因為我們設計機器人的理念和上帝設計我們是一樣的:

耶和華上帝按照自己的形象,用地上的塵土造出了一個人,往他的鼻孔里吹了一口氣,有了靈,人就活了,能說話,能行走。

機器人要像人類一樣利用各種感測器來觀察自己周圍的物體和環境,並且拿這個觀察結果和自己硬碟里的場景地圖進行比對,分析出潛在變數,最終確定自己可能在哪。

在實驗統計學中,我們希望能對實驗內包含的所有變數大權在握,這就要用到隨機對照實驗的理念了。假如我們要研究某種肥料提高某種植物產量的效果,最簡單的就是設計一個對照實驗:一組施肥,是為實驗組;另一組不施肥,是為對照組。也許實驗結果很好,但是我們無意識的將所有實驗組放在了太陽地,而所有的對照組放在陰涼處,這些其實也是影響整個實驗的潛在變數。為了消除這些莫名其妙的影響,我們使用隨機的方式保證這些無法避免的混雜因素不能對整個實驗產生影響,這就是隨機對照實驗。

潛在變數概念的構建還解決了一直以來的一個哲學問題:古希臘的哲學家們總是在思考人類是怎麼認識這個世界的,這其中有一群人叫懷疑論者,他們認為既然你的感官有時會給你提供相互矛盾的信息,既然人類連自己感官都不能相信,他們還能相信什麼呢?於是這些哲學家進入了極端唯心的境地,他們忽視內心世界以外的一切存在。這也不能怪這些哲學家,因為那個年代還有概率學,更沒有我們今天講的潛在變數的概念,所以他們無法理解人類能通過知性和理念來把事項的概率封裝和提煉成知識與想法。

我們經常用語言以極為簡單的方式表達出一個非常複雜的事項,這就是語言對事項的壓縮。

比如:我們在銀行門口,看到一個拿著挎包的女士出來,這時候衝出來一個帶著墨鏡口罩穿著軍大衣的大哥,一把將女士的包搶走,女士見狀一邊跑一邊大喊:「快攔住那個劫匪的!」

對於上述這麼複雜的事項,我們接受記者採訪的時候估計就會用兩個字來描述上述內容:搶劫

不是嗎?

在物理學中,我們使用許多簡單的規律來描述我們的世界,這些基本原理很難直接觀察到,我們通過大量觀察不同的潛在變數的結果最終推出規律,比如牛頓從大量實驗和現象中找到了萬有引力定律。

「這種認知的不確定性使我們能夠通過對世界的觀測和我們腦內的概率分布聯繫起來,從而得出結果。」這個是支持整個狀態空間建模的核心理念,進而可以推廣到概率圖模型以及其他更廣泛的潛在變數模型。這期教程中我們將通過一個簡單的線性系統來實踐這種理念,並看看這種實踐如何與因子分析和主城成分分析相關聯。

在教程正式開始之前,我們先要對上文出現的新名詞進行解釋——因子分析(factor analysis)。這個分析方法是一群20世紀主要研究形式化思想的心理學家們發明的,他們為人類設計了一個表現潛在思維的高維向量(特徵向量),卻發現人類處理問題時只會用到這個高維向量種很有限的幾個元素(特徵),這種模型被稱為潛在特質模型,這種分析方法就叫因子分析。這種分析方法主要作用就是將高維度的個體特質根據實際情況壓縮提取成少量的、低維的潛在因素向量,很像咱們在『道』篇中提到的主成分分析。

那麼我們就可以反過來思考,既然大量的觀測結果可以被歸納成潛在變數,那麼我們不妨假設未來會出現的觀測結果是完全受到這些潛在變數左右和限制的。就好像我們通過大量觀察一個人的行為,來推斷出這個人的品質,比如謙遜|傲慢,善良|邪惡,禮貌|粗魯等等,並基於這些特質來判斷這個人未來可能做的事情。我們假設這個人的潛在變數向量是 mathbf{x} ,行為集是 mathbf{y} ,再追加一個噪音向來表達隨機因素對一個人行為的影響,那麼有以下表達:

 mathbf{y} = mathbf{f}(mathbf{x}) + oldsymbol{epsilon}

對於這個表達中的 mathbf{f(x)} ,我們可以把它簡化成一個線性結構:

mathbf{f(x)=Wx}

其中 mathbf{W} 就是我們在之前講多元線性回歸時所講的基底向量拼成的基底矩陣(是這麼叫吧?),所以 mathbf{f(x)} 的結構如下所示:

 mathbf{f}(mathbf{x}) = egin{bmatrix} f_1(mathbf{x}) \ f_2(mathbf{x}) \ vdots \ f_p(mathbf{x}) end{bmatrix}

其中p是假定和個體相關的特性的數量。假如我們對這些函數中的每一個函數都單獨進行考慮,那麼我們將會得到跟曾經的回歸模型很像的預測函數:

 f_j(mathbf{x}) = mathbf{w}_{j,:}^	op mathbf{x}

其中每個 mathbf{w}_{:,j} 是權重向量矩陣 mathbf{W} 的每一列,這是一個輸入和輸出的維度都大於1的回歸。就像在標準回歸中那樣,我們沒有辦法直接觀測函數(函數也是潛在變數的一部分),但是會有一些損壞的變數被觀測到。我們在次假設這種不精確是由於高斯雜訊產生,由此有:

 epsilon_j sim mathcal{N}(0,sigma^2_j)

這個式子可以表示行為集 mathbf{y} 中第j個元素的雜訊。

當然了,就像其他回歸問題一樣,我們的數據集中包含著不同個體的觀察結果,將這些數據儲存在矩陣 mathbf{Y} 中,每一行包括一個人的觀察值:

 mathbf{Y} = egin{bmatrix} mathbf{y}_{1,:}^	op \ mathbf{y}_{2,:}^	op \ vdots \ mathbf{y}_{n,:}^	op end{bmatrix}

n代表我們觀察的事項的數量,因此我們的數據矩陣應當有n行p列。這裡需要注意的一點是:因為每個數據的觀測在設計表現為了一個行向量(個體是列向量),所以我們的預測函數應該如下計算:

 mathbf{F} = mathbf{X}mathbf{W}^	op

其中 mathbf{F}inRe^{n	imes p}mathbf{W}inRe^{p	imes q}mathbf{X}inRe^{n	imes q} ;其中q是我們假定輸入到函數中的數量。

每個 f_{i,j} 也就是對於每個特性的預測即為:  f_j(mathbf{x}_{i,:}) = mathbf{w}_{j,:}^	op mathbf{x}_{i,:}


說完了上面這些前置知識,我們終於可以接著『道』篇的結尾——概率主成分分析(Probabilistic PCA)繼續講下去了。

上文書說到,概率主成分分析頭戴權重矩陣,身披高斯分布,墊步擰腰往外就走,在眾人面前一亮相,嚇得各路英雄好漢是囁獃獃發愣,這位名為PPCA的好漢長這樣:

 p(mathbf{Y} | mathbf{W},sigma^2) = prod_{i=1}^n mathcal{N}(mathbf{y}_{i,:} | mathbf{0},mathbf{W}mathbf{W}^	op + sigma^2 mathbf{I})

其中 mathbf{W} 是從一個特徵值問題的解得來的:  mathbf{W} = mathbf{U}mathbf{L} mathbf{R}^	op

其中 mathbf{U} 觀測值的協方差矩陣的特徵向量。

 mathbf{S} = sum_{i=1}^n (mathbf{y}_{i,:} - oldsymbol{mu})(mathbf{y}_{i,:} - oldsymbol{mu})^	op

假如說我們已經對均值歸零了,那麼 mathbf{S} 可以直接寫成:

mathbf{S} = frac{1}{n} mathbf{Y}^	opmathbf{Y}

而對角矩陣 mathbf{L} 取決於 mathbf{S} 的特徵值,也就是 mathbf{Lambda} (這些都在道篇里講了)。假如 mathbf{Lambda} 的第 i 個元素是 lambda_i ,那麼對角陣 mathbf{L} 的對應位置的元素 ell_i 即為:

 ell_i = sqrt{lambda_i - sigma^2}

其中 sigma^2 是雜訊變數,要注意 mathbf{L} 陣中不能出現負值,因此任何小於雜訊變數 sigma^2 的特徵值都將被捨棄。接下來我們看看怎麼在Python中實現概PPCA:

import numpy as npdef ppca(Y, q): Y_cent = Y - Y.mean(0) #移除均值 S = np.dot(Y_cent.T, Y_cent)/Y.shape[0] lambd, U = np.linalg.eig(S) #計算方差矩陣 sigma2 = np.sum(lambd[q:])/(Y.shape[1]-q) l = np.sqrt(lambd[:q]-sigma2) W = U[:, :q]*l[None, :] #選取特徵向量 return W, sigma2

當然了,這就是照著公式非常粗淺地實現。在實踐中,我們一般不直接計算一個協方差矩陣的特徵向量,因為整個計算過程包括了大量開方過程。我們可以通過QR分解或者奇異值分解的方式來用儘可能少的算力得到特徵向量。

在上面我們將潛在變數思想置入主成分分析之後,我們不妨為主成分分析設置一個後驗概率,用這個後驗概率來推斷給定數據的潛在變數: p(mathbf{x}_{i,:} | mathbf{y}_{i,:})

以往的後驗貝葉斯我們一般都把 mathbf{w} 放在前面,由於這次我們直接將 mathbf{x} 設置成了所謂的潛在變數,所以這次直接把 mathbf{x} 放在前面,後驗分布如下表示:

 p(mathbf{x}_{i,:} | mathbf{y}_{i,:}) propto p(mathbf{y}_{i,:} | mathbf{W},mathbf{x}_{i,:},sigma^2) p(mathbf{x}_{i,:})

在我們之前的貝葉斯線性回歸的案例中,我們一般對取對數後驗分布

log p(mathbf{x}_{i,:} | mathbf{y}_{i,:}) = log p(mathbf{y}_{i,:} | mathbf{W},mathbf{x}_{i,:},sigma^2) + log p(mathbf{x}_{i,:}) + 	ext{const}

就像中學數學中學到的湊平方一樣,我們把對數後驗分布湊成關於 mathbf{x} 的高斯分布:

 log p(mathbf{x}_{i,:} | mathbf{y}_{i,:}) = -frac{1}{2sigma^2} (mathbf{y}_{i,:} - mathbf{W}mathbf{x}_{i,:})^	op (mathbf{y}_{i,:} - mathbf{W}mathbf{x}_{i,:}) - frac{1}{2} mathbf{x}_{i,:}^	op mathbf{x}_{i,:} + 	ext{const}

一方面將 log p(mathbf{x}_{i,:} | mathbf{y}_{i,:}) = - frac{1}{2sigma^2} (mathbf{y}_{i,:} - mathbf{W}mathbf{x}_{i,:})^	op (mathbf{y}_{i,:} - mathbf{W}mathbf{x}_{i,:}) - frac{1}{2} mathbf{x}_{i,:}^	op mathbf{x}_{i,:} + 	ext{const} 中的括弧項乘出來,然後把「二次項」(mathbf{x}_{i,:}^	op mathbf{A} mathbf{x}_{i,:})和「一次項」(mathbf{B} mathbf{x}_{i,:})分好堆。

另一方面將logmathcal{N}(oldsymbol{mu}_x,mathbf{C}_x) = - frac{1}{2}(mathbf{x}_{i,:} - oldsymbol{mu}_x)^	op mathbf{C}^{-1}_x (mathbf{x}_{i,:} - oldsymbol{mu}_x) + 	ext{const}中的括弧項乘出來,然後把「二次項」和「一次項」分好堆。(實際上應該叫二次非線性項和線性項)

你把上下這麼一比對,就能得到對應的 oldsymbol{C}_xoldsymbol{mu}_x

最後結果為:

 mathbf{x}_{i,:} | mathbf{W} sim mathcal{N}(oldsymbol{mu}_x,mathbf{C}_x)

 mathbf{C}_x = left(sigma^{-2} mathbf{W}^	opmathbf{W} + mathbf{I}
ight)^{-1}

 oldsymbol{mu}_x = mathbf{C}_x sigma^{-2}mathbf{W}^	op mathbf{y}_{i,:}

接下來我們看看怎麼在python中實現後驗主成分分析:

import numpy as npimport scipy as spdef posterior(Y, W, sigma2): Y_cent = Y - Y.mean(0) #移除均值 C_x = np.linalg.inv( (1/sigma2) * np.dot( W.T, W ) + np.identity(W.shape[1]) ) mu_x = np.dot( C_x, (1/sigma2) * np.dot( W.T, Y_cent) ) #計算C_x和mu_x return mu_x, C_x

所以我們一直講機器學習代碼少不是瞎說的。

osu.csv?

pan.baidu.com

接下來我們嘗試著來用PPCA尋找人跑步時一直腳的運動軌跡的參數,結合上咱們上面用到的函數和演算法上的改進,osu.csv是對人跑步時腳動態的觀測結果:

import scipy as spimport numpy as npimport pandas as pdimport matplotlib.pyplot as plt%matplotlib inlinedef ppca(Y, q, center=True): #包括了奇異值分解 #移除均值 if center: Y_cent = Y - Y.mean(0) else: Y_cent = Y #計算奇異值 U, sqlambd, _ = sp.linalg.svd(Y_cent.T,full_matrices=False) lambd = (sqlambd**2)/Y.shape[0] #計算殘差,提取特徵向量 sigma2 = np.sum(lambd[q:])/(Y.shape[1]-q) ell = np.sqrt(lambd[:q]-sigma2) return U[:, :q], ell, sigma2def posterior(Y, U, ell, sigma2, center=True): if center: Y_cent = Y - Y.mean(0) else: Y_cent = Y C_x = np.diag(sigma2/(sigma2+ell**2)) d = ell/(sigma2+ell**2) mu_x = np.dot(Y_cent, U)*d[None, :] return mu_x, C_xY=pd.read_csv("osu.csv")q=2U,ell,sigma2=ppaca(Y,q)plt.plot(mu_x[:,0],mu_x[:,1],rx-)print(sigma2)

我們可以通過上述代碼找出一隻腳在跑步運動時的潛在變數,進而推斷出這個人以後跑步的時候這隻腳的運動軌跡。之前 @王司圖 在想法中分享了對於Van♂Darkholme的動作識別:

王司圖的想法 - zhihu.com/pin/989873250

最簡單的思路,我們可以給Van♂Darkholme後面摔♂跤時所有的肢體識別觀測結果配合上我們的概率主成分分析,推斷出Van慣用的繳械動作。

就像我寫教程時時習慣從哲學入手一樣,我們的人工智慧最終也要是為哲♂學服務,是為超然的A♂I。

以上

推薦閱讀:

從零開始,了解元學習
吳恩達機器學習第五周課後感
GitHub深度學習模型大大大集合的Model Zoo,支持按框架、按類別篩選
圖解gradient的智能與learning rate的注意事項

TAG:機器學習 | 無監督學習 |