當前位置:
首頁 > 知識 > 一個項目的經驗教訓:關於打亂和拆分數據

一個項目的經驗教訓:關於打亂和拆分數據

最近因為某事要準備一點材料,剛好前段時間給導師做項目的時候遇到一個大坑,浪費了很多時間,所以就著這個問題順便做點總結。

傳統的機器學習,即在深度學習流行之前的問題的一般處理流程通常是「預處理->特徵變換->分類/回歸」。即便現在深度學習似乎要統治業界,但要轉換成這樣的步驟,也不過是將「特徵變換」與「分類/回歸」合二為一而已,該做的預處理往往還是要做。《深度學習(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 定理的意義:如果不考慮具體問題,所有的演算法都是隨機猜測,沒有好壞之分。


Part 3. 另一個案例: Google MLCC 十八世紀文學

因為一些緣故不太想把我的方向說太細,結果剛好前幾天把 Google 新出的機器學習課程 MLCC 過了一遍,發現最後有個案例跟我遇到的問題簡直一模一樣,在這裡簡單介紹一下吧。

課程頁面見 https://developers.google.com/machine-learning/crash-course/ ,顯然需要翻~牆。課程自帶中文、中文字幕和機器配音(非常帶感,建議體驗一下)。案例在 https://developers.google.com/machine-learning/crash-course/18th-century-literature。

Google 工程師與一位研究十八世紀文學的教授合作,開發了一個「心靈隱喻(the metaphors to the mind)」資料庫,記錄了十八世紀所有的文學作品中關於「心靈」的隱喻的句子,比如「心靈是一座花園」「心靈是一塊白板」。這位教授想了解是否能從這些作者使用的隱喻中得知他們的政治派別。

把數據集劃分、訓練之後,發現準確率非常高。他們覺得這裡面肯定有問題。

這是他們最開始劃分數據集的方式:

逐句拆分樣本。某位作者的句子在訓練、驗證和測試集中均存在。這樣一來,模型不僅學到了隱喻,還學到了這位作者寫作語言的特點,即模型記憶了關於作者的額外信息。

發現這個問題後,他們重新劃分數據集,把某位作者的作品僅放在訓練或測試或驗證集中,即:

現在準確率大幅下降,而且很難得到比較高的準確率,即僅根據隱喻來判斷政治派別,是一件非常困難的事情。

講師最後總結說,這個案例說明:在隨機打亂數據和拆分數據之前,需要考慮數據本身的意義。


Update

寫完發出去才反應過來:

正在跑著的程序,一篇 AAAI-18 上本領域的文章,我順著作者找到了他們沒有公開的 Github 地址。當時看到 paper 就懷疑他們結果有問題,準確率未免太高了。

看了一下代碼,發現跟上面講過的一樣,也是把所有數據拿出來打亂再劃分。唉,簡直是……特么的在逗我。

一葉知秋,可見頂會 paper 也未必靠譜。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 AI研習社 的精彩文章:

資源 Python學習材料
除了掌握深度學習框架,AI 工程師還需要哪些技能?

TAG:AI研習社 |