核範數與規則項引數選擇
機器學習中的範數規則化之(二)核範數與規則項引數選擇
上一篇博文,我們聊到了L0,L1和L2範數,這篇我們絮叨絮叨下核範數和規則項引數選擇。知識有限,以下都是我一些淺顯的看法,如果理解存在錯誤,希望大家不吝指正。謝謝。
三、核範數
核範數||W||*是指矩陣奇異值的和,英文稱呼叫Nuclear Norm。這個相對於上面火熱的L1和L2來說,可能大家就會陌生點。那它是幹嘛用的呢?霸氣登場:約束Low-Rank(低秩)。OK,OK,那我們得知道Low-Rank是啥?用來幹啥的?
我們先來回憶下線性代數裡面“秩”到底是啥?舉個簡單的例子吧:
對上面的線性方程組,第一個方程和第二個方程有不同的解,而第2個方程和第3個方程的解完全相同。從這個意義上說,第3個方程是“多餘”的,因為它沒有帶來任何的資訊量,把它去掉,所得的方程組與原來的方程組同解。為了從方程組中去掉多餘的方程,自然就匯出了“矩陣的秩”這一概念。
還記得我們怎麼手工求矩陣的秩嗎?為了求矩陣A的秩,我們是通過矩陣初等變換把A化為階梯型矩陣,若該階梯型矩陣有r個非零行,那A的秩rank(A)就等於r。從物理意義上講,矩陣的秩度量的就是矩陣的行列之間的相關性。如果矩陣的各行或列是線性無關的,矩陣就是滿秩的,也就是秩等於行數。回到上面線性方程組來說吧,因為線性方程組可以用矩陣描述嘛。秩就表示了有多少個有用的方程了。上面的方程組有3個方程,實際上只有2個是有用的,一個是多餘的,所以對應的矩陣的秩就是2了。
OK。既然秩可以度量相關性,而矩陣的相關性實際上有帶有了矩陣的結構資訊。如果矩陣之間各行的相關性很強,那麼就表示這個矩陣實際可以投影到更低維的線性子空間,也就是用幾個向量就可以完全表達了,它就是低秩的。所以我們總結的一點就是:如果矩陣表達的是結構性資訊,例如影像、使用者-推薦表等等,那麼這個矩陣各行之間存在這一定的相關性,那這個矩陣一般就是低秩的。
如果X是一個m行n列的數值矩陣,rank(X)是X的秩,假如rank (X)遠小於m和n,則我們稱X是低秩矩陣。低秩矩陣每行或每列都可以用其他的行或列線性表出,可見它包含大量的冗餘資訊。利用這種冗餘資訊,可以對缺失資料進行恢復,也可以對資料進行特徵提取。
好了,低秩有了,那約束低秩只是約束rank(w)呀,和我們這節的核範數有什麼關係呢?他們的關係和L0與L1的關係一樣。因為rank()是非凸的,在優化問題裡面很難求解,那麼就需要尋找它的凸近似來近似它了。對,你沒猜錯,rank(w)的凸近似就是核範數||W||*。
好了,到這裡,我也沒什麼好說的了,因為我也是稍微翻看了下這個東西,所以也還沒有深入去看它。但我發現了這玩意還有很多很有意思的應用,下面我們舉幾個典型的吧。
1)矩陣填充(Matrix Completion):
我們首先說說矩陣填充用在哪。一個主流的應用是在推薦系統裡面。我們知道,推薦系統有一種方法是通過分析使用者的歷史記錄來給使用者推薦的。例如我們在看一部電影的時候,如果喜歡看,就會給它打個分,例如3顆星。然後系統,例如Netflix等知名網站就會分析這些資料,看看到底每部影片的題材到底是怎樣的?針對每個人,喜歡怎樣的電影,然後會給對應的使用者推薦相似題材的電影。但有一個問題是:我們的網站上面有非常多的使用者,也有非常多的影片,不是所有的使用者都看過說有的電影,不是所有看過某電影的使用者都會給它評分。假設我們用一個“使用者-影片”的矩陣來描述這些記錄,例如下圖,可以看到,會有很多空白的地方。如果這些空白的地方存在,我們是很難對這個矩陣進行分析的,所以在分析之前,一般需要先對其進行補全。也叫矩陣填充。
那到底怎麼填呢?如何才能無中生有呢?每個空白的地方的資訊是否蘊含在其他已有的資訊之上了呢?如果有,怎麼提取出來呢?Yeah,這就是低秩生效的地方了。這叫低秩矩陣重構問題,它可以用如下的模型表述:已知資料是一個給定的m*n矩陣A,如果其中一些元素因為某種原因丟失了,我們能否根據其他行和列的元素,將這些元素恢復?當然,如果沒有其他的參考條件,想要確定這些資料很困難。但如果我們已知A的秩rank(A)<<m且rank(A)<<n,那麼我們可以通過矩陣各行(列)之間的線性相關將丟失的元素求出。你會問,這種假定我們要恢復的矩陣是低秩的,合理嗎?實際上是十分合理的,比如一個使用者對某電影評分是其他使用者對這部電影評分的線性組合。所以,通過低秩重構就可以預測使用者對其未評價過的視訊的喜好程度。從而對矩陣進行填充。
2)魯棒PCA:
主成分分析,這種方法可以有效的找出資料中最“主要"的元素和結構,去除噪音和冗餘,將原有的複雜資料降維,揭示隱藏在複雜資料背後的簡單結構。我們知道,最簡單的主成分分析方法就是PCA了。從線性代數的角度看,PCA的目標就是使用另一組基去重新描述得到的資料空間。希望在這組新的基下,能儘量揭示原有的資料間的關係。這個維度即最重要的“主元"。PCA的目標就是找到這樣的“主元”,最大程度的去除冗餘和噪音的干擾。
魯棒主成分分析(Robust PCA)考慮的是這樣一個問題:一般我們的資料矩陣X會包含結構資訊,也包含噪聲。那麼我們可以將這個矩陣分解為兩個矩陣相加,一個是低秩的(由於內部有一定的結構資訊,造成各行或列間是線性相關的),另一個是稀疏的(由於含有噪聲,而噪聲是稀疏的),則魯棒主成分分析可以寫成以下的優化問題:
與經典PCA問題一樣,魯棒PCA本質上也是尋找資料在低維空間上的最佳投影問題。對於低秩資料觀測矩陣X,假如X受到隨機(稀疏)噪聲的影響,則X的低秩性就會破壞,使X變成滿秩的。所以我們就需要將X分解成包含其真實結構的低秩矩陣和稀疏噪聲矩陣之和。找到了低秩矩陣,實際上就找到了資料的本質低維空間。那有了PCA,為什麼還有這個Robust PCA呢?Robust在哪?因為PCA假設我們的資料的噪聲是高斯的,對於大的噪聲或者嚴重的離群點,PCA會被它影響,導致無法正常工作。而Robust PCA則不存在這個假設。它只是假設它的噪聲是稀疏的,而不管噪聲的強弱如何。
由於rank和L0範數在優化上存在非凸和非光滑特性,所以我們一般將它轉換成求解以下一個鬆弛的凸優化問題:
說個應用吧。考慮同一副人臉的多幅影像,如果將每一副人臉影像看成是一個行向量,並將這些向量組成一個矩陣的話,那麼可以肯定,理論上,這個矩陣應當是低秩的。但是,由於在實際操作中,每幅影像會受到一定程度的影響,例如遮擋,噪聲,光照變化,平移等。這些干擾因素的作用可以看做是一個噪聲矩陣的作用。所以我們可以把我們的同一個人臉的多個不同情況下的圖片各自拉長一列,然後擺成一個矩陣,對這個矩陣進行低秩和稀疏的分解,就可以得到乾淨的人臉影像(低秩矩陣)和噪聲的矩陣了(稀疏矩陣),例如光照,遮擋等等。至於這個的用途,你懂得。
3)背景建模:
背景建模的最簡單情形是從固定攝相機拍攝的視訊中分離背景和前景。我們將視訊影像序列的每一幀影像畫素值拉成一個列向量,那麼多個幀也就是多個列向量就組成了一個觀測矩陣。由於背景比較穩定,影像序列幀與幀之間具有極大的相似性,所以僅由背景畫素組成的矩陣具有低秩特性;同時由於前景是移動的物體,佔據畫素比例較低,故前景畫素組成的矩陣具有稀疏特性。視訊觀測矩陣就是這兩種特性矩陣的疊加,因此,可以說視訊背景建模實現的過程就是低秩矩陣恢復的過程。
4)變換不變低秩紋理(TILT):
以上章節所介紹的針對影像的低秩逼近演算法,僅僅考慮影像樣本之間畫素的相似性,卻沒有考慮到影像作為二維的畫素集合,其本身所具有的規律性。事實上,對於未加旋轉的影像,由於影像的對稱性與自相似性,我們可以將其看做是一個帶噪聲的低秩矩陣。當影像由端正發生旋轉時,影像的對稱性和規律性就會被破壞,也就是說各行畫素間的線性相關性被破壞,因此矩陣的秩就會增加。
低秩紋理對映演算法(TransformInvariant Low-rank Textures,TILT)是一種用低秩性與噪聲的稀疏性進行低秩紋理恢復的演算法。它的思想是通過幾何變換τ把D所代表的影像區域校正成正則的區域,如具有橫平豎直、對稱等特性,這些特性可以通過低秩性來進行刻畫。
低秩的應用非常多,大家有興趣的可以去找些資料深入瞭解下。
四、規則化引數的選擇
現在我們回過頭來看看我們的目標函式:
裡面除了loss和規則項兩塊外,還有一個引數λ。它也有個霸氣的名字,叫hyper-parameters(超參)。你不要看它勢單力薄的,它非常重要。它的取值很大時候會決定我們的模型的效能,事關模型生死。它主要是平衡loss和規則項這兩項的,λ越大,就表示規則項要比模型訓練誤差更重要,也就是相比於要模型擬合我們的資料,我們更希望我們的模型能滿足我們約束的Ω(w)的特性。反之亦然。舉個極端情況,例如λ=0時,就沒有後面那一項,代價函式的最小化全部取決於第一項,也就是集全力使得輸出和期待輸出差別最小,那什麼時候差別最小啊,當然是我們的函式或者曲線可以經過所有的點了,這時候誤差就接近0,也就是過擬合了。它可以複雜的代表或者記憶所有這些樣本,但對於一個新來的樣本泛化能力就不行了。畢竟新的樣本會和訓練樣本有差別的嘛。
那我們真正需要什麼呢?我們希望我們的模型既可以擬合我們的資料,又具有我們約束它的特性。只有它們兩者的完美結合,才能讓我們的模型在我們的任務上發揮強大的效能。所以如何討好它,是非常重要。在這點上,大家可能深有體會。還記得你復現了很多論文,然後復現出來的程式碼跑出來的準確率沒有論文說的那麼高,甚至還差之萬里。這時候,你就會懷疑,到底是論文的問題,還是你實現的問題?實際上,除了這兩個問題,我們還需要深入思考另一個問題:論文提出的模型是否具有hyper-parameters?論文給出了它們的實驗取值了嗎?經驗取值還是經過交叉驗證的取值?這個問題是逃不掉的,因為幾乎任何一個問題或者模型都會具有hyper-parameters,只是有時候它是隱藏著的,你看不到而已,但一旦你發現了,證明你倆有緣,那請試著去修改下它吧,有可能有“奇蹟”發生哦。
OK,回到問題本身。我們選擇引數λ的目標是什麼?我們希望模型的訓練誤差和泛化能力都很強。這時候,你有可能還反映過來,這不是說我們的泛化效能是我們的引數λ的函式嗎?那我們為什麼按優化那一套,選擇能最大化泛化效能的λ呢?Oh,sorry to tell you that,因為泛化效能並不是λ的簡單的函式!它具有很多的區域性最大值!而且它的搜尋空間很大。所以大家確定引數的時候,一是嘗試很多的經驗值,這和那些在這個領域摸爬打滾的大師是沒得比的。當然了,對於某些模型,大師們也整理了些調參經驗給我們。例如Hinton大哥的那篇A Practical Guide to Training RestrictedBoltzmann Machines等等。還有一種方法是通過分析我們的模型來選擇。怎麼做呢?就是在訓練之前,我們大概計算下這時候的loss項的值是多少?Ω(w)的值是多少?然後針對他們的比例來確定我們的λ,這種啟發式的方法會縮小我們的搜尋空間。另外一種最常見的方法就是交叉驗證Cross validation了。先把我們的訓練資料庫分成幾份,然後取一部分做訓練集,一部分做測試集,然後選擇不同的λ用這個訓練集來訓練N個模型,然後用這個測試集來測試我們的模型,取N模型裡面的測試誤差最小對應的λ來作為我們最終的λ。如果我們的模型一次訓練時間就很長了,那麼很明顯在有限的時間內,我們只能測試非常少的λ。例如假設我們的模型需要訓練1天,這在深度學習裡面是家常便飯了,然後我們有一個星期,那我們只能測試7個不同的λ。這就讓你遇到最好的λ那是上輩子積下來的福氣了。那有什麼方法呢?兩種:一是儘量測試7個比較靠譜的λ,或者說λ的搜尋空間我們儘量廣點,所以一般對λ的搜尋空間的選擇一般就是2的多少次方了,從-10到10啊什麼的。但這種方法還是不大靠譜,最好的方法還是儘量讓我們的模型訓練的時間減少。例如假設我們優化了我們的模型訓練,使得我們的訓練時間減少到2個小時。那麼一個星期我們就可以對模型訓練7*24/2=84次,也就是說,我們可以在84個λ裡面尋找最好的λ。這讓你遇見最好的λ的概率就大多了吧。這就是為什麼我們要選擇優化也就是收斂速度快的演算法,為什麼要用GPU、多核、叢集等來進行模型訓練、為什麼具有強大計算機資源的工業界能做很多學術界也做不了的事情(當然了,大資料也是一個原因)的原因了。
努力做個“調參”高手吧!祝願大家都能“調得一手好參”!
五、參考資料
[1] http://fastml.com/large-scale-l1-feature-selection-with-vowpal-wabbit/
[2] http://www.stat.purdue.edu/~vishy/introml/notes/Optimization.pdf
[3] http://www.stanford.edu/~boyd/cvxbook/bv_cvxbook.pdf
[4] GradientDescent, Wolfe's Condition and Logistic Regression
[5] http://nm.mathforcollege.com/mws/gen/04sle/mws_gen_sle_spe_adequacy.pdf
相關文章
- beego 前後端引數規範Go後端
- 4. 環境引數規範
- API介面通訊引數規範API
- API介面通訊引數規範(2)API
- JSR規範,系統引數測試大全JS
- CSS 選擇器命名規範CSS
- 卷積核大小選擇、網路層數問題卷積
- Flask-sqlalchemy中 backref lazy的引數例項解釋和選擇FlaskSQL
- .net core Web API引數繫結規則WebAPI
- 機器學習中的範數規則化之(一)L0、L1與L2範數機器學習
- nslookup命令模式及引數選項有哪些?Linux學習規劃如何模式Linux
- Mysql-基本的規則與規範MySql
- Shell程式設計規範與變數程式設計變數
- MySQL索引選擇及規則整理MySql索引
- 正則特殊引數
- 【版本更新】PerfDog新增幫助引導,規範化CPU利用率與效能引數命名
- jenkins 實現二級聯動選擇引數Jenkins
- ASEMI整流橋DB207的導通時間與引數選擇DB2
- 01 shell程式設計規範與變數程式設計變數
- JsonPath:針對json的強大的規則解析與引數查詢工具JSON
- 正則化與模型選擇模型
- 數倉命名規範大全!
- hadoop中文版本下載選擇與平臺監控引數介紹Hadoop
- 編碼規範:不要用引數控制程式碼邏輯
- CSS 選擇器優先順序規則CSS
- python變數命名規則Python變數
- 變數名命名規則變數
- iOS倒數計時的探究與選擇iOS
- 可變引數例項
- input檔案選擇框檔案過濾引數accept
- [C++]變數宣告與定義的規則C++變數
- 設計模式 基本規範與基本原則設計模式
- http params規範中,允許一個引數多次出現嗎?HTTP
- TypeScript 函式可選引數和預設引數TypeScript函式
- 如何根據寶塔皮膚引數選擇伺服器伺服器
- $.ajax(),$.get(),$.post()的區別,以及一些引數注意規則
- c# 方法引數(傳值,傳引用,ref,out,params,可選引數,命名引數)C#
- 前端工程程式碼規範(一)——命名規則與工程約定前端