關於人肉工程,包括業務知識、領域知識,經驗等,在實際的機器學習問題中的應用,是一個屢見不鮮的話題,典型的有苦逼的數據清洗、人肉特征工程等。大家都想把盡可能多的過程由機器自動完成,但是目前的狀態是,大部分機器學習問題中,最困難也最重要的部分,還是依靠人的經驗來生成特征。那么人的經驗為什么重要,能否用機器完成這個過程,本文試作一簡單分析。
機器和人看待數據的區別
首先要看一下,從機器的角度看,機器學習是怎樣一個問題?在機器看來,機器學習的問題通常是在一組特征上,最大化某個目標函數。注意,對於這組特征而言,機器是理解不了它的含義的。舉例來說,下面一組數據(第一列是targe)
0, 1, 1, 0
1, 0, 1, 1
1, 0, 0, 1
…
你能看出這組數據是什么含義嗎?顯然不能。但是完全可以用它訓練一個分類模型,比如logistic regression。
然后查看一下關於這組數據的描述,知道這是關於某個班某次考試的結果,第一列表示物理是否及格,后面三個特征分別是性別、文理科班、數學是否及格,那么現在我知道這組數據的含義了。這樣又可以訓練一個logistic regression模型。問題來了,這兩個模型有區別嗎?顯然沒有。也就是說,人是如何理解數據含義的,對於算法並沒有任何影響。因為從機器的角度看,這都是一堆數字而已。
現在看另一個例子,這里有一個特征是這樣的
1, …, 1431174193, …
1, …, 1431087793, …
0, …, 1431001393, …
1, …, 1430914993, …
0, …, 1430828593, …
…
能看出這個特征是什么嗎?如果你猜測這是時間(timestamp)——那么,你已經開始使用領域知識了。對於機器來說,這只是一個整數序列而已。如果我們把這組數據代入一個線性模型,那么意味着默認預測目標和特征之間是線性關系。也就是說,學習算法的假設空間僅包含timestamp的線性函數。
機器能否通過“學習”達到和人的知識相同的效果
現在,我們既然知道這是日期,就可以增加特征,比如從日期中提取月份、星期、小時等。假設增加“小時”這么一個特征,注意,這個變換是非線性的,這里使用了人的知識。對於機器而言,沒有這樣的知識。如果要求機器能自動提取出這個特征,那么學習算法的假設空間至少應該覆蓋timestamp到小時的轉換函數,類似於(timestamp/3600)%24。這會增加假設空間的維度。如果知道函數的形式也還好,比如知道(timestamp/a)%b, 這樣只需要擬合a、b兩個參數。但是實際問題往往是,我怎么知道特征的轉換函數是怎樣的?也許是log(sin(a x)) / (exp(x) + x^2),如果要求假設空間涵蓋各種可能的函數形式,那必然大大增加假設空間的維度,很容易導致過擬合。比如神經網絡,三層網絡就可以逼近任意函數(有個什么連續性還是可導條件,忘了),但是太容易過擬合了,而且存在局部最優的問題。
所以,人的知識的作用在於特征變換。更進一步說,如果人的知識可以給出有效的特征變換,那么可以大大降低搜索空間的維度。對於線性模型而言,模型本身可以處理所有線性的情況,如果人的知識所產生的特征變換也是線性的,那么對於模型沒有任何提升,只有非線性的變換才對模型有影響。而如果要求模型能夠自動的學習出相同的非線性變換,則會造成模型的特征空間維度大大提高。
而人類的知識是千萬年間積累下來的,其中包含了很多復雜的變換,而且知識之間相互依賴,如果要理解一個概念,往往需要首先理解其他的很多概念,所以,從這個意義上將,要求機器學習出人類的知識結構是不太現實的。當然,機器不必模仿人類的知識,可以學習出另外的特征變換,只要最后的模型是有效的。所以為什么現在的deep learning這么火,因為它在控制過擬合的前提下,能夠在一定程度上學習出特征變換的形式,也就是在一定程度上完成了人肉特征工程的工作,目前大概也只有deep learning能做到這一點。不過,從目前的實踐情況來看,人的知識仍然在具體問題中起着重要的作用。
“算法工程師”的角色和職責
基於此,可以把典型的機器學習建模過程分成三個階段:
數據清洗、預處理、特征變換 -> 代入標准機器學習算法 -> 將結果應用到業務問題
其中,只有中間的部分是標准化的(所以一般大家都是調用現成的軟件包),而兩頭的,則需要由人工完成,也就是把數據解釋、變換成機器要求的形式,以及對結果的含義做出解釋。因為機器理解不了數據的含義。
如果從這個角度看待“算法工程師”,或者“數據科學家”之類的角色,這種職業的作用在於解釋數據,而不是算法研究或者編程。機器學習算法將會越來越標准化、平台化,使用門檻降低,數據科學家將不再需要處理大量的編程細節,而是越來越類似傳統的醫療或金融行業的數據分析師,重在理解業務和數據。算法的研究由科研人員負責,而工程細節由通用的(分布式)平台解決。算法工程師的重點在於數據的預處理、特征生成以及模型選擇和參數優化,這也是和現實情況相符的。
目前機器學習的應用還處於粗放階段,要搭建一個系統,必須應付大量的編程細節。比如一個使用LR進行CTR預測的系統,即使使用開源的模塊搭建,也往往要處理許多接口、測試和訓練集划分、甚至數據存儲的細節。然而,這些細節都和問題的本質無關。將來,這些技術細節將被屏蔽。例如,用一種類似SQL的語言執行模型訓練過程,類似於
CLASSIFY click
RELATE TO time, pos, user_id, ad_id
FROM ad_show_dataset
WHERE '2015-07-01' <= time <= '2015-07-31'
USING logistic_regression
CROSS VALIDATION TRAIN 40% random TEST else
EVALUATE WITH auc;
EXPORT MODEL file_path FORMAT PRML;
這段代碼比較接近自然語言了,意思是以click為目標,以time, pos, user_id, ad_id為特征,ad_show_dataset中2015-07-01到2015-07-31之間的數據為樣本,訓練logistic regression模型,其中隨機選擇40%作為訓練集,其他作為測試集。模型以auc為評估指標。最后將訓練出的模型以PRML格式導出到file_path。(如果你看了上面的代碼后不明白,還要看這段解釋,說明我的語法設計的不好。)
從更廣的范圍來說,計算機技術的發展過程,就是一個不斷降低人們使用計算機門檻的過程,用Brooks大神的話說,是“消除軟件領域的非本質性困難”。最初的程序員,需要寫匯編代碼、直接處理CPU與內存。C語言和操作系統出現以后,編程門檻降低了,但是仍然免不了處理底層細節。而Java、python、php等語言出現后,編程門檻進一步降低,只要稍微經過一些培訓的人,都可以寫代碼。而有關進程調度、內存管理、IO、緩存一致性等底層細節,被少數專業化的制作編譯器、操作系統、虛擬機等的程序員掩蓋。而大部分程序員的職責,是把業務邏輯“翻譯”成計算機聽得懂的語言。
機器學習和分布式系統也將沿着這個路線發展。少數專業化程度很高的程序員負責平台開發,屏蔽技術細節,消除“非本質性困難”,使得算法工程師或數據科學家可以專注於業務邏輯和數據含義。這個職業的性質將越來越接近產品經理,而不是工程師。工程師的技術是通用的,比如一個音樂網站的php工程師,到一個互聯網金融公司寫php,技術上沒什么區別。而產品經理就不一樣了,因為音樂和金融的業務、用戶、商業模式有很大不同。
結論
所以,直白的說,算法工程師的本質就是數據解釋、清洗、預處理、人肉特征工程、參數調優等。究其根本原因,在於計算機理解不了數據的含義。如果有一天計算機能夠理解數據含義了,那就像計算機能聽懂自然語言一樣,大部分程序員可以下崗了。
