如何用機器學習處理二元分類任務?

圖像是貓還是狗?情感是正還是負?貸還是不貸?這些問題,該如何使用合適的機器學習模型來解決呢?

問題

暑假后,又有一批研究生要開題了。這幾天陸續收到他們發來的研究計劃大綱。

其中好幾個,打算使用機器學習做分類。

但是,從他們的文字描述來看,不少人對機器學習進行分類的方法,還是一知半解

考慮到之前分享機器學習處理分類問題的文章,往往針對具體的任務案例。似乎對分類問題的整體步驟與注意事項,還沒有詳細論述過。于是我決定寫這篇文章,幫他們梳理一下。

他們和你一樣,也是我專欄的讀者。

如果你對機器學習感興趣,并且實際遇到了分類任務,那我解答他們遇到的一些疑問,可能對于你同樣有用。

所以,我把這篇文章也分享給你。希望能有一些幫助。

監督

監督式機器學習任務很常見。主要模型,是分類與回歸。

就分類問題而言,二元分類是典型應用。

例如決策輔助,你利用結構化數據,判定可否貸款給某個客戶;

例如情感分析,你需要通過一段文字,來區分情感的正負極性;

例如圖像識別,你得識別出圖片是貓,還是狗。

今天咱們就先介紹一下,二元分類,這個最為簡單和常見的機器學習應用場景。

注意要做分類,你首先得有合適的數據。

什么是合適的數據呢?

這得回到我們對機器學習的大類劃分。

分類任務,屬于監督式學習。

監督式學習的特點,是要有標記。

例如給你1000張貓的圖片,1000張狗的圖片,扔在一起,沒有打標記。這樣你是做不了分類的。

雖然你可以讓機器學習不同圖片的特征,讓它把圖片區分開。

但是這叫做聚類,屬于非監督學習

天知道,機器是根據什么特征把圖片分開的。

你想得到的結果,是貓放在一類,狗放在另一類。

但是機器抓取特征的時候,也許更喜歡按照顏色區分。

結果白貓白狗放在了一個類別,黃貓黃狗放在了另一個類別。跟你想要的結果大相徑庭。

如果你對非監督學習感興趣,可以參考《如何用Python從海量文本抽取主題?》一文。

所以,要做分類,就必須有標記才行。

但是標記不是天上掉下來的。

大部分情況下,都是人打上去的。

標記

打標記(Labeling),是個專業化而繁復的勞動。

你可以自己打,可以找人幫忙,也可以利用眾包的力量。

例如亞馬遜的“土耳其機器人”(Amazon Mechanical Turk)項目

別被名字唬住,這不是什么人工智能項目,而是普通人可以利用業余時間賺外快的機會。

你可以幫別人做任務拿傭金。任務中很重要的一部分,就是人工分類,打標記。

因此如果你有原始數據,但是沒有標記,就可以把數據扔上去。

說明需求,花錢找人幫你標記。

類似的服務,國內也有很多。

建議找知名度比較高的平臺來做,這樣標記的質量會比較靠譜。

如果你還是在校學生,可能會覺得這樣的服務價格太貴,個人難以負擔。

沒關系。假如你的研究是有基金資助項目的一部分,可以正大光明地找導師申請數據采集費用。

但若你的研究屬于個人行為,就得另想辦法了。

不少學生選擇的辦法,是依靠團隊支持。

例如找低年級的研究生幫忙標記。

人家幫了忙,讓你發表了論文,順利畢業。你總得請大家吃一頓好吃的,是吧?

學習

有了標記以后,你就能夠實施監督學習,做分類了。

這里我們順帶說一下,什么叫做“機器學習”。

這個名字很時髦。

其實它做的事情,叫做“基于統計的信息表征”。

先說信息表征(representation)。

你的輸入,可能是結構化的數據,例如某個人的各項生理指標;可能是非結構化數據,例如文本、聲音甚至是圖像,但是最終機器學習模型看到的東西,都是一系列的數字。

這些數字,以某種形式排布。

可能是零維的,叫做標量(scalar);

可能是一維的,叫做向量(vector);

可能是二維的,叫做矩陣(Matrice);

可能是高維的,叫做張量(Tensor)。

但是,不論輸入的數據,究竟有多少維度,如果你的目標是做二元分類,那么經過一個或簡單、或復雜的模型,最后的輸出,一定是個標量數字。

你的模型,會設置一個閾值。例如0.5。

超出這個數字的,被分類到一處。

反之,被分類到另一處。

任務完成。

那么模型究竟在做什么呢?

它的任務,就是把輸入的數據,表征成最終的這個標量。

打個不恰當的比方,就如同高考

每一個考生,其實都是獨特的。

每個人都有自己的家庭,自己的夢想,自己的經歷,自己的故事。

但是高考這個模型,不可能完整準確表征上述全部細節。

它簡單地以考生們的試卷答題紙作為輸入,以一個最終的總成績作為輸出。

然后,劃定一個叫做錄取分數線的東西,作為閾值(判定標準)。

達到或超出了,錄取。

否則,不錄取。

這個分數,就是高考模型對每個考生的信息表征

所謂分類模型的優劣,其實就是看模型是否真的達到了預期的分類效果。

什么是好的分類效果?

大學想招收的人,錄取了(True Positive, TP);

大學不想招收的人,沒被錄取(True Negative, TN)。

什么是不好的分類效果?

大學想招收的人,沒能被錄取(False Negative, FN);

大學不想招收的人,被錄取了(False Positive, FP)。

好的模型,需要盡力增大 TP 和 TN 的比例,降低 FN 和 FP 的比例。

評判的標準,視你的類別數據平衡而定。

數據平衡,例如1000張貓照片,1000張狗照片,可以使用 ROC AUC。

數據不平衡,例如有1000張貓的照片,卻只有100張狗的照片,可以使用 Precision 和 Recall ,或者二者相結合的 F1 score。

因為有這樣明確的評估標準,所以二元分類模型不能滿足于“分了類”,而需要向著“更好的分類結果”前進。

辦法就是利用統計結果,不斷改進模型的表征方法。

所以,模型的參數需要不斷迭代。

恢復高考后的40年,高考的形式、科目、分值、大綱……包括加分政策等,一直都在變化。這也可以看作是一種模型的迭代。

“表征”+“統計”+“迭代”,這基本上就是所謂的“學習”。

結構化

看到這里,希望你的頭腦里已經有了機器學習做二元分類問題的技術路線概貌。

下面咱們針對不同的數據類型,說說具體的操作形式和注意事項。

先說最簡單的結構化數據。

例如《貸還是不貸:如何用Python和機器學習幫你決策?》一文中,我們見到過的客戶信息。

處理這樣的數據,你首先需要關注數據的規模。

如果數據量大,你可以使用復雜的模型。

如果數據量小,你就得使用簡單的模型。

為什么呢?

因為越復雜的模型,表征的信息就越多。

表征的信息多,未必是好事。

因為你抓住的,既有可能是信號,也有可能是噪聲。

如果表征信息多,可是學習過的數據不多,它可能就會對不該記住的信息,形成記憶。

在機器學習領域,這是最恐怖的結果——過擬合(overfitting)。

翻譯成人話,就是見過的數據,分類效果極好;沒見過的數據,表現很糟糕。

舉一個我自己的例子。

我上學前班后沒多久,我媽就被請了家長。

因為我漢語拼音默寫,得了0分。

老師嘴上說,是懷疑我不認真完成功課;心里想的,八成是這孩子智商余額不足。

其實我挺努力的。

每天老師讓回家默寫的內容,都默了。

但是我默寫的時候,是嚴格按照“a o e i u ……”的順序默的。

因為每天都這樣默寫,所以我記住的東西,不是每個讀音對應的符號,而是它們出現的順序。

結果上課的時候,老師是這樣念的“a b c d e ……”

我毫無懸念沒跟下來。

我的悲劇,源于自己的心智模型,實際上只反復學習了一條數據“a o e i u ……”。每天重復,導致過擬合,符號出現在順序中,才能辨識和記憶。

因此,見到了新的組合方式,就無能為力了。

看,過擬合很糟糕吧。

確定了模型的復雜度以后,你依然需要根據特征多少,選擇合適的分類模型。

上圖來自于 Scikit-learn ,我截取了其中“分類”模型部分,你可以做參考。

注意模型的效果,實際上是有等級劃分的。

例如根據 Kaggle 數據科學競賽多年的實踐結果來看,Gradient Boosting Machine 優于隨機森林,隨機森林優于決策樹。

這么比有些不厚道,因為三者的出現,也是有時間順序的。

讓爺爺跟孫子一起賽跑,公平性有待商榷。

因此,你不宜在論文中,將不同的分類模型,分別調包跑一遍,然后來個橫向對比大測評

許多情況下,這是沒有意義的。

雖然顯得工作量很大。

但假如你發現在你自己的數據集上面,決策樹的效果就是明顯優于 Gradient Boosting Machine ,那你倒是很有必要通過論文做出匯報。

盡管大部分審稿人都會認為,一定是你算錯了

另一個需要注意的事項,是特征工程(feature engineering)。

什么叫特征工程呢?

就是手動挑選特征,或者對特征(組合)進行轉化。

例如《如何用Python和深度神經網絡鎖定即將流失的客戶?》一文中,我們就對特征進行了甄別。其中三列數據,我們直接剔除掉了:

  • RowNumber:行號,這個肯定沒用,刪除
  • CustomerID:用戶編號,這個是順序發放的,刪除
  • Surname:用戶姓名,對流失沒有影響,刪除

正式學習之前,你需要把手頭掌握的全部數據分成3類:

  • 訓練集
  • 驗證集
  • 測試集

我在給期刊審稿的時候,發現許多使用機器學習模型的作者,無論中外,都似乎不能精確理解這些集合的用途。

訓練集讓你的模型學習,如何利用當前的超參數(例如神經網絡的層數、每一層的神經元個數等)組合,盡可能把表征擬合標記結果。

就像那個笑話說的一樣:

Machine Learning in a Nutshell:

Interviewer: what's you biggest strength?

Me: I'm a quick learner.

Interviewer: What's 11*11?

Me: 65.

Interviewer: Not even close. It's 121.

Me: It's 121.

而驗證集的存在,就是為了讓你對比不同的超參數選擇,哪一組更適合當前任務。它必須用訓練集沒有用過的數據。

驗證集幫你選擇了合適的超參數后,它的歷史任務也就結束了。

這時候,你可以把訓練集、驗證集合并在一起,用最終確定的超參數組合進行訓練,獲得最優模型。

這個模型表現怎么樣?

你當然需要其他的數據來評判。這就是為什么你還要劃分出另外的測試集。

圖像

Franc?ois Chollet 在自己的書中舉過一個例子,我覺得很有啟發,一并分享給你。

假如你看到了這樣的原始數據:

你該怎么做分類?

有的同學一看是圖像,立刻決定,上卷積神經網絡

別忙,想想看,真的需要“直接上大錘”嗎?

別的不說,那一圈的刻度,就對我們的模型毫無意義。

你可以利用特征工程,將其表達為這樣的坐標點:

你看,這樣處理之后,你立刻就擁有了結構化數據。

注意這個轉換過程,并不需要人工完成,完全可以自動化。

但是舉一反三的你,估計已經想到了“更好的”解決方案:

對,這樣一來,表達鐘表時間的數據,就從原先的4個數字,變成了只需要2個。

一個本來需要用復雜模型解決的問題,就是因為簡單的特征工程轉化,復雜度和難度顯著下降。

其實,曾經人們進行圖片分類,全都得用特征工程的方法。

那個時候,圖片分類問題極其繁瑣、成本很高,而且效果還不理想。

手動提取的特征,也往往不具備良好的可擴展性和可遷移性。

于是,深度卷積神經網絡就登場了。

如果你的圖片數據量足夠多的話,你就可以采用“端到端”的學習方式。

所謂“端到端”,是指不進行任何的特征工程,構造一個規模合適的神經網絡模型,扔圖片進去就可以了。

但是,現實往往是殘酷的。

你最需要了解的,是圖片不夠多的時候,怎么辦。

這時候,很容易出現過擬合。

因為深度神經網絡,屬于典型的復雜模型。

這個時候,可以嘗試以下幾個不同的方法:

首先,如果有可能,搜集更多的帶標注圖片。這是最簡單的辦法,如果成本可以接受,你應該優先采用。

其次,使用數據增強(Data Augmentation)。名字聽起來很強大,其實無非是把原始的數據進行鏡像、剪裁、旋轉、扭曲等處理。這樣“新的”圖片與老圖片的標注肯定還是一樣的。但是圖片內容發生的變化,可以有效防止模型記住過多噪聲。

第三,使用遷移學習。

所謂遷移學習,就是利用別人訓練好的模型,保留其中從輸入開始的大多數層次(凍結保留其層次數量、神經元數量等網絡結構,以及權重數值),只把最后的幾層敲掉,換上自己的幾層神經網絡,對小規模數據做訓練。

上圖同樣來自于 Franc?ois Chollet 的著作。

這種做法,用時少,成本低,效果還特別好。如果重新訓練,圖片數少,就很容易過擬合。但是用了遷移學習,過擬合的可能性就大大降低。

其原理其實很容易理解。

卷積神經網絡的層次,越是靠近輸入位置,表達的特征就越是細節;越到后面,就越宏觀。

識別貓和狗,要從形狀邊緣開始;識別哆啦a夢和瓦力,也一樣要從形狀邊緣開始。因此模型的底層,可以被拿來使用。

你訓練的,只是最后幾層表征方式。結構簡單,當然也就不需要這么多數據了。

第四,引入 Dropout, Regularization 和 Early Stopping 等常規方法。注意這些方法不僅適用于圖像數據。

以 Dropout 為例。假如一個模型因為復雜,所以記住了很多噪聲,那么訓練的時候,每次都隨機將一定比例的神經元“扔掉”(設置權重為0),那么模型的復雜度降低。而且因為隨機,又比降低層數與神經元個數的固化模型適用性更高。

文本

前面說過了,機器不認得文本,只認得數字。

所以,要對文本做二元分類,你需要把文本轉換成為數字。

這個過程,叫做向量化。

向量化的方式,有好幾種。大致上可以分成兩類:

第一類,是無意義轉換。也就是轉換的數字,只是個編號而已,本身并不攜帶其他語義信息。

這一類問題,我們在《如何用Python和機器學習訓練中文文本情感分類模型?》中,已經非常詳細地介紹過了。

你需要做的,包括分詞(如果是中文)、向量化、去除停用詞,然后丟進一個分類模型(例如樸素貝葉斯,或者神經網絡),直接獲取結果,加以評估。

但是,這個過程,顯然有大量的語義和順序信息被丟棄了。

第二類,是有意義轉換。這時候,每個語言單元(例如單詞)轉換出來的數字,往往是個高維向量。

這個向量,你可以自己通過訓練來產生。

但是這種訓練,需要對海量語料進行建模。

建模的過程,成本很高,占用龐大存儲空間,運算量極大。

因此更常見的做法,是使用別人通過大規模語料訓練后的結果。也就是我們曾經介紹過的詞嵌入預訓練模型。

具體內容,請參見《如何用Python處理自然語言?(Spacy與Word Embedding)》和《如何用 Python 和 gensim 調用中文詞嵌入預訓練模型?》。

注意如果你有多個預訓練模型可以選擇,那么盡量選擇與你要解決任務的文本更為接近的那種。

畢竟預訓練模型來自于統計結果。兩種差別很大的語料,詞語在上下文中的含義也會有顯著差異,導致語義的刻畫不夠準確。

如果你需要在分類的過程中,同時考慮語義和語言單元順序等信息,那么你可以這樣做:

第一步,利用詞嵌入預訓練模型,把你的輸入語句轉化為張量,這解決了詞語的語義問題;

第二步,采用一維卷積神經網絡(Conv1D)模型,或者循環神經網絡模型(例如 LSTM),構造分類器。

注意這一步中,雖然兩種不同的神經網絡結構,都可以應用。但是一般而言,處理二元分類問題,前者(卷積神經網絡)表現更好。

因為卷積神經網絡實際上已經充分考慮了詞語的順序問題;而循環神經網絡用在此處,有些“大炮轟蚊子”。很容易發生過擬合,導致模型效果下降。

實施

如果你了解二元分類問題的整體流程,并且做好了模型的選擇,那么實際的機器學習過程,是很簡單的。

對于大部分的普通機器學習問題,你都可以用 Scikit-learn 來調用模型。

注意其實每一個模型,都有參數設置的需要。但是對于很多問題來說,默認初始參數,就能帶來很不錯的運行結果。

Scikit-learn 雖好,可惜一直不能很好支持深度學習任務。

因而不論是圖像還是文本分類問題,你都需要挑選一個好用的深度學習框架。

注意,目前主流的深度學習框架,很難說有好壞之分。

畢竟,在深度學習領域如此動蕩激烈的競爭環境中,“壞”框架(例如功能不完善、性能低下)會很快被淘汰出局。

然而,從易用性上來說,框架之間確實有很大區別。

易用到了一種極致,便是蘋果的 Turi Create 。

從《如何用Python和深度神經網絡識別圖像?》和《如何用Python和深度神經網絡尋找近似圖片?》這兩篇文章中,你應該有體會,Turi Create 在圖像識別和相似度查詢問題上,已經易用到你自己都不知道究竟發生了什么,任務就解決了。

但是,如果你需要對于神經網絡的結構進行深度設置,那么 Turi Create 就顯得不大夠用了。

畢竟,其開發的目標,是給蘋果移動設備開發者賦能,讓他們更好地使用深度學習技術。

對于更通用的科研和實踐深度學習任務,我推薦你用 Keras 。

它已經可以把 Theano, Tensorflow 和 CNTK 作為后端。

對比上面那張深度學習框架全家福,你應該看到,Keras 覆蓋了 Google 和 微軟自家框架,幾乎占領了深度學習框架界的半壁江山。

照這勢頭發展下去,一統江湖也說不定哦。

為什么 Keras 那么厲害?

因為簡單易學。

簡單易學到,顯著拉低了深度學習的門檻。

就連 Tensorflow 的主力開發人員 Josh Gordon,也已經認為你根本沒必要去學習曾經的 Tensorflow 繁復語法了。

直接學 Keras ,用它完成任務,結束。

另外,使用深度學習,你可能需要 GPU 硬件設備的支持。這東西比較貴。建議你采用租用的方式。

如何用云端 GPU 為你的 Python 深度學習加速?》提到的 FloydHub,租賃一個小時,大概需要1美元左右。注冊賬號就贈送你2個小時;

至于《如何免費云端運行Python深度學習框架?》中提到的 Google Colab ,就更慷慨了——到目前為止,一直是免費試用。

喜歡請點贊。還可以微信關注和置頂我的公眾號“玉樹芝蘭”(nkwangshuyi)

如果你對數據科學感興趣,不妨閱讀我的系列教程索引貼《如何高效入門數據科學?》,里面還有更多的有趣問題及解法。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,179評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,444評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,948評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,185評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,717評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,794評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,414評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,750評論 2 370