當前位置:
首頁 > 最新 > 如何用機器學習處理二元分類任務?

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

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

問題

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

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

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

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

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

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

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

監督

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

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

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

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

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

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

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

什麼是合適的數據呢?

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

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

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

例如給你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 ,就更慷慨了——到目前為止,一直是免費試用。

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

答疑社區在這裡:


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

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


請您繼續閱讀更多來自 機器學習 的精彩文章:

UPS如何利用AI、機器學習和大數據為第四次工業革命做好準備
AI在網路安全領域的應用:機器學習 VS.深度學習

TAG:機器學習 |