傳統的機器學習,即在深度學習流行之前的問題的一般處理流程通常是「預處理->特徵變換->分類/回歸」。即便現在深度學習似乎要統治業界,但要轉換成這樣的步驟,也不過是將「特徵變換」與「分類/回歸」合二為一而已,該做的預處理往往還是要做。《深度學習(deep learning book)》裡提過一種對深度學習的詮釋思路——深度表示學習,與之類似。
但放到現實問題中來看,機器學習只不過是整個問題解決過程中乙個很小的組成部分。比如在公司做業務,你要收集資料、清洗資料、建立合適的資料結構,對大規模資料可能還要順便把大規模分布式問題解決一下。等費勁千辛萬苦拿到「乾淨」的資料之後,才進入機器學習/模式識別問題的一般步驟。
而實際上,至少七成時間花在了準備資料的階段。很多人學機器學習往往只重視演算法或者模型,學深度學習的只看網路結構和調參方法,但不要忘了,這是因為有人為你準備好了資料集和評測流程、方法。對於實際問題,這一整套框架都要根據實際情況去設計、改進,使之貼近業務,提供更好的服務。
做科研有做科研的方法,做實際業務是另一套模式。業界需要的大量的演算法工程師,往往是做這些看似瑣碎的無趣的活,這樣看來程式設計師轉演算法工程師其實是比較容易的。
啊哀嘆一下為什麼我程式設計這麼菜……
扯淡結束。這篇博文要記錄的內容,與資料集的製作與劃分有關。
本文還是以大白話寫就,您讀著也省勁,我寫得也輕鬆。
part 1. 例項: 乙個訊號處理問題
就從實際問題的背景開始,由導師的專案說起吧。
專案需要完成乙個系統,我負責實驗設計、總體設計和訊號處理+識別。這個專案的訊號或者說資料是按時間取樣得到的,比如說取樣率是500hz每秒就能得到500個點。一次採集在一分鐘以上,只需要其中的不到三十秒的資料。
所以問題就來了:得到一組資料需要至少一分鐘,而且這個採集過程不能長時間執行,一次實驗最多採三十組資料;更尷尬的是,實驗比較特殊,不是想做幾組就做幾組的。
也就是說,我們必須要用比較少的採集組數得到資料集,還要訓練乙個比較可靠的模型,用來做訊號的識別/分類。
一開始我想得很簡單——少就少唄,無非是個小樣本學習的問題。找乙個魯棒性比較好的特徵變換方法,用簡單點兒的分類模型,分分鐘解決問題,反正設計指標也不高。
但說歸說,只有十幾二十個樣本,誰能保證訓出來的模型能用啊。
查了一些文獻,又結合系統的要求,最後選擇用滑動窗分割的方法來增廣資料集,即設定乙個固定時長的滑動窗在時域訊號上滑動,重疊時長為0,這樣把乙個樣本切割成幾十份樣本,資料集擴增了幾十倍。瞬間就把樣本不足的問題解決了。
採取這種方式,一是有人一直在這麼做,二是系統實際工作時處理過程也與之類似——總不能後台默默跑一分鐘才告訴你乙個結果吧?最好是幾秒鐘就顯示乙個結果,讓甲方知道我們的系統在幹活,而不只是琢磨著怎麼把他們的錢忽悠走。
離線測試效果奔波兒灞,不是,倍兒棒,正確率直接奔著95%去了。老實說當時我是有點懷疑的,但稍微動了一下腦子,感覺最多也就是線上比離線差點兒,總不能太糟吧。
怕啥來啥。線上測試二分類正確率50%。
當時我就蒙了。接著回爐重造,想到乙個比較特殊的情況,改模型再訓,嚯!99%!心想這回總不至於那麼差吧,一上線還是完蛋。
那幾天是真煩,實在想不清楚怎麼就完蛋了。
過了大概大半星期,忽然產生了乙個念頭——是不是資料集有問題?
眾所周知,我們一般做機器學習要在資料集上 shuffle,然後按比例劃分訓練、驗證和測試集。這個系統模型比較簡單沒幾個超參,樣本又少,出於僥倖心理乾脆就省略了驗證集。
但問題在於,這個資料集是怎麼得到的?是從大約二十組訊號上「片」出來的。
我隱約察覺問題在哪兒了。然後就實驗驗證唄。
從時間的角度考慮,系統需要用「過去」的資料去**「未來」。所以這一回我先劃分了訓練和測試集資料,然後再做切片。其實在這裡,資料根本不需要 shuffle ——分類器是 linear classifier 或 svm,訓練過程是一次把所有資料喂進去。shuffle 沒有任何意義。
這回的測試結果看起來比較「正常」了——在50%和60%之間浮動。好嘛問題終於是定位到了,但新的問題是,這樣一來我用的訊號處理方法對分類根本沒效果,簡直一夜回到解放前。
後來我對一些小細節做了一點調整,最近參與的三個人差不多把全新的系統除錯完了,具體效果……我猜設計要求的70%還是能達到吧。不再細說。
part 2. 資料集的製作與劃分,方法要根據問題而定
所以說,通過這一課我學到了什麼?
shuffle 不要亂用
演算法一定要貼在具體業務上
為什麼我的模型會線下99%、線上50%?
顯然是對線下模型過擬合了。但我明明做了訓練集和測試集啊?問題就出在這兒:
我增廣之後,先 shuffle、再劃分。對學術界的很多資料集,這麼做可能完全沒影響,但沒影響不代表它是對的。kaggle 、天池之類的資料競賽,訓練集和測試集都是提前劃分好的,有沒有想過其中的道理?
打個比方,我的錯誤操作,就像中學時候不會做的題目抄答案,但每次只看一半,理由是「只要給個思路我就會做了」。當然,這純粹是自己騙自己。
先 shuffle 再劃分,就相當於「答案只看一半」——「過去」的資料和「現在」的資料混到了一起,模型既學到了「過去」的模式,又學到了「現在」的模式,準確率自然可觀;而「未來」的資料是不可見的,模型顯然學不到「未來」的模式。
所以正確的方法是先劃分。shuffle 可以不用。因為 shuffle 的作用體現在 mini-batch learning 的時候。一次性訓練的分類器使用 shuffle 並沒有什麼意義。
第二點體會就結合我的方向來說了。去年去北京聽課,天津大學的一位博后在講實驗設計和訊號處理方法的時候提到,我們這個領域多年來已經遇到了瓶頸,具體體現在演算法的提公升作用越來越小,實驗設計反倒比處理方法重要得多。
我非常贊同。
深度學習火起來之後,領域內不少人也研究過基於深度學習的處理方法,但經得起考驗的成果不多。一方面深度學習不是萬能的,另一方面,多年來進展緩慢,側面說明我們這個領域可能真地存在這麼乙個天花板。我覺得具體問題就在訊號採集的方式和裝置上面——這個話題不展開討論——結果就是,受制於「硬體」限制,在實驗設計上出成果比在演算法上出成果要容易。
這就是說,對很多實際問題來說,演算法並不是關鍵。按照 andrew ng. 和國外很多部落格的觀點,圍繞你的目標設計乙個好的 pipeline,包括如何對資料的建模、乙個衡量模型好壞的基準等等,然後不斷改進,這才是使用機器學習的有效方式,而不是只針對其中演算法的部分嘗試各種分類/回歸器,或者想用深度學習調參搞定一切。這正是 nfl 定理的意義:如果不考慮具體問題,所有的演算法都是隨機猜測,沒有好壞之分。
深度學習打亂資料的方法
在深度學習中,我們對資料集進行處理,放到神經網路之前,往往需要先打亂資料集,如果資料集是ndarray numpy 資料,屬性 features 和標籤 labels 在同乙個array的話,也就是labels是在資料的最後乙個維度,前幾個維度均為資料的屬性,這樣我們可以通過numpy來打亂資料集。...
深度學習中的資料增強
關於計算機視覺領域資料增強的一些常用的方法一般而言,比較成功的神經網路需要大量的引數,許許多多的神經網路的引數都是數以百萬計,而使得這些引數可以正確工作則需要大量的資料進行訓練,而實際情況中資料並沒有我們想象中的那麼多 增加訓練的資料量,提高模型的泛化能力 增加雜訊資料,提公升模型的魯棒性 如何獲得...
使用random 隨機打亂 list 中的資料
首先建立乙個有序的集合 list list new arraylist list.add 1 list.add 2 list.add 3 list.add 4 list.add 5 list.add 6 list.add 7 list.add 8 list.add 9 list.add 10 sys...