如何在時間緊迫情況下進行機器學習:構建標記的新聞
譯者注:本文介紹了作者和他的三位朋友參加了編程馬拉松,開發出了一個根據Hacker News提交的文章進行分類的分類器,緊接著作者分享了比賽過程中的一些經驗。以下為譯文。
本周末,三位朋友(Chris Riederer,Nathan Gould和我的孿生兄弟Dan)和我參加了2017 TechCrunch Disrupt Hackathon。 我們以前都會去參加幾個這樣的編程馬拉松,也喜歡挑戰在短時間內開發一個可用的應用程序,同時學習一些新技術。
我們四個人中有三個是數據科學家,因此知道應該尋找一個數據驅動的項目,因為最好的編程馬拉松項目往往是可用的應用程序(而不是分析或lib庫),我們認為應該開發一個以機器學習為驅動的產品,想到了程序員社區Hacker News的分類器,它會根據文本自動分配每個提交的主題。
該項目需要下載數據,培訓機器進行學習,并在24小時內將其變成可用的網站。 在這里我分享了我們在開發過程中學到的一些經驗教訓。
(請注意,我關注的是數據方面,因為這是我負責的模塊,但是Nathan和Dan在開發和設計站點方面做了大量工作,同時為了使站點與Hacker News保持同步,他們也付出了很多心血。)
檢索Hacker News的帖子和文章
Hacker News收集了用戶提交和上傳的文章,通常是程序員社區感興趣的內容(不只是關于編程的文章)。我們的任務是檢索每篇文章的文本,并將其分類為哪一種主題。
很快我們就知道了,我們需要大量的訓練數據——也許是成千上萬篇文章——為了能夠成功地識別新文章的主題。要做到這一點,我們需要去Hacker News抓取每一篇提交的文章和對應的鏈接,然后查詢每一篇文章來檢索它的文本內容。
這里犯了一個錯誤,就是依賴Hacker News API從而一次只下載一個提交的文章,這樣的話,想獲得25,000個鏈接得需要好幾個小時,這是一個緩慢的過程。在黑客馬拉松結束后,我們了解到在Google BigQuery上有一個 Hacker News的數據集——在大約20分鐘的配置之后,我就可以下載100萬個鏈接。在比賽的壓力下,我們很難做到一直去尋找類似于這種簡單的解決方案,相反,為了最終實現可能會采用一些效率很低的解決方案(但這也是樂趣的一部分)。
一旦我們有了文章的鏈接,就需要每篇文章的文本內容。這是一種挑戰,因為這些文章來自于不同的網站,格式也各不一樣,但是設計python-goose正是為了這個目的。我們把其中的三臺電腦專門用來抓取文章,這樣每小時可以收集幾千篇。你可以在這個GitHub庫中找到我們的抓取代碼和一些結果。
通常在這樣的項目中,我們會讓抓取任務在夜間運行,但對我們來說,這并不是一個可取的選擇!當數據開始下載時,我們分成了兩組:Nathan和Dan負責建立網站,而Chris和我負責開發收集數據的機器學習算法。
開發一個受監督的培訓集
要訓練一個受監督的分類器,你需要一個標簽集:我們應該能夠知道文章的正確分類是什么。我們沒有足夠的時間手工給例子貼上標簽。那怎么得到一系列已經正確標記好的例子呢?
好吧,如果你瀏覽過幾頁Hacker News,你會發現有些文章通過標題幾乎就已經明確地告訴你主題是什么了,或者有些是通過簡單的模式匹配也可以知道。看看首頁,比如Why Amazon is eating the world就是關于亞馬遜的,Why do many math books have so much detail and so little enlightenment?是關于數學的,Don’t tell people to turn off Windows Update是關于微軟/Windows的。因此,我們決定根據文章標題通過正則表達式創建一個訓練集。
這個過程進行了一些試驗,包括一些在文章標題中對常見詞和集群的探索性分析。我最喜歡的圖形之一就是通過文字的形式創建的一個關于網絡的圖形(請參閱我們的圖書Text Mining with R的這一章節),這是一個更好地理解數據的好機會。
我們注意到詞匯中的集群,例如一個帶有“機器/深度學習”的ML集群,以及各種各樣的政治集群,如“網絡/中立性”和“trump/fbi”。這幫助我們把注意力集中在可用的話題上。
下面是我們用來訓練模型的正則表達式。當我們研究結果的分類是否正確,移除導致清除錯誤的正則表達式,并添加一些我們遺漏的部分時,這都是需要進行大量的迭代和調整。
R語言中的fuzzyjoin使得匹配這些標題變得很容易。你可以在這個存儲庫中找到代碼和一些分析程序,以及我們的機器學習工作。
最后我們得到了一個大約10,000個標記文檔的訓練集(注意不是所有的標題都匹配任何正則表達式,有些可以匹配多個)。與每一個正則表達式匹配的是:
(我們起初還有一些其他的主題,比如“Web開發”和“Javascript”,但最終基于分類的結果刪除了它們)。注意,這并不意味著這些就是站點上最流行的主題!它完全基于我們為每個主題決定的正則表達式——如果一些主題比其他主題更容易識別,或者如果這些正則表達式有一些疏漏,那么該文章將不會被反映出來。
在標題上使用正則表達式是一種非常粗糙的獲取示例的方式,而且不會完全準確(例如,關于“調整窗口大小(resizing windows)”的標題將被標記為Microsoft)。但是,它可以是一種快速有效的方法來構建一個規模龐大的訓練集,并且手工檢查的結果使我們確信它是準確的。
一旦我們在這些標題上訓練了算法,它就能夠識別出標題中沒有任何這些特征的文章。例如,在標題拒絕信( Rejection Letter)中沒有提到它的主題,所以它不在我們的訓練集里,但是因為標題包含了諸如“安全”、“勒索軟件”、“防病毒”和“蠕蟲”之類的單詞,在我們的訓練集里經常出現的單詞——這個算法很容易把它標記為“安全”。
培訓和生產ML模型
在我們用R語言來探索數據之后,我們使用Python的scikit學習包讓機器進行學習。這需要三個步驟:
- 標記化:我們把每一篇文章都變成了一組單詞,用一種“單詞袋(bag of words)”方法(我們忽略了單詞的順序和結構)。
- 維度減少:我們使用了由(gensim Python包)實現的Latent Dirichlet分配,將單詞適合于主題模型,將每個文檔轉換為長度為100的向量。每一主題都與數據相匹配,與特定的單詞組相關聯(例如,一個主題可能與“特朗普”、“科米”、“俄羅斯”有高度關聯,而另一個主題則側重于“設計”、“photoshop”、“css”)。
- 監督分類:我們使用一種監督分類器來預測。我們嘗試了兩種方法:正則化邏輯回歸和隨機森林。
我以前寫過主題建模(它在我們的《Text Mining with R》書中扮演著重要的角色)。在這里,我們不是用它來做結論,而是用它將我們數以萬計的特性(“這篇文章包含了“比特幣”這個詞,而不是“)減少到100維的數據集里。通過一些試驗,我們發現添加這個主題建模步驟(而不是直接使用文字作為特性)提高了我們對模型的準確性。
我們還發現,隨機森林在我們訓練集上的交叉驗證的AUC(ROC曲線下的區域)方面打敗了正則化邏輯回歸:
這與圍繞這些模型的普遍聲譽相吻合。邏輯回歸更快地進行了訓練,并且有了更多的解釋,但是在處理許多特性交互的情況下,它并沒有那么好。例如,它不會注意到“學習”這個詞與“大學”或“教育”這個詞的含義不同。
當然,這個訓練集的“準確性”只是意味著“可以預測文章的標題是否與我們認為的正則表達式相符”,但我們希望這將轉化為對新文章的現實預測。
生產模型
當Chris和我在建造這個模型時,Nathan和Dan已經使用Django開發好了網站,部署在Heroku上,并注冊了一個域名。它每隔十分鐘與Hacker News API同步,但作為一個占位符,它被指定為完全隨機的主題。大約凌晨2點,我和Chris有了一個訓練有素的模型,是時候把我們的努力結合起來了。
理論上,在Python中構建算法和網站應該是很簡單的,因為我們可以將它直接插入到站點中的一個函數中。我已經習慣通過與我的團隊合作將R轉換為ci來生產模型,因此,用pickle將模型序列化并直接加載到應用程序的能力當然是很方便的,并且讓我們能夠靈活地使用我們實現的模型。
但這并不意味著部署就是十分順利的!我們遇到的兩個最大的問題是:
使用nltk Heroku。最初使用nltk庫進行標記化,因為它是Python自然語言處理最強大的工具包。但是它是一個龐大而又笨重的庫,開始在Heroku上運行一些關于安裝和使用它的模糊錯誤消息。為了方便,最終切換到gensim(已經需要進行主題建模)的記號賦予器,這需要重新培訓算法。
Python 2和3之間的pickle:可以在python3上安裝這個模型,但是用來查詢文章文本的Goose,不是Python 3兼容的,我們的生產站點必須在python2中。這就是我們在Python 2和3之間遇到了bug的時候。那時是凌晨4點,修復需要一些非常不雅的黑客攻擊。
最初考慮將機器學習過程作為一個微服務(通過網站傳遞文本內容以及返回分類的獨立的服務)。它將會使機器學習算法的切換變得更加輕松(給web團隊一個API端點,而不是代碼和一個軟件包需求列表)。
交流和分享
而且,我們在taggernews.com網站上有一個實時網站。從那以后我們改變了網站,但是當我們在凌晨4點30分提交項目的時候它看起來是這樣的:
Tagger News可以自動對Hacker News的文章進行分類和排序
# HackDisrupt pic.twitter.com/2mEbrGXIce
——TechCrunch(@TechCrunch),2017年5月14日
演講結束后,TechCrunch采訪了我們,寫了一篇關于我們的項目的文章,在這些黑客馬拉松活動中,我們是第一個!黑客馬拉松結束后,我決定完成這個剩余部分,并將TechCrunch的文章提交給Hacker News,我們很高興用戶可以在社區看到并且喜歡:
我們在產品搜尋上也做得很好。
根據Google Analytics的數據,昨天Tagger News大概有6,000訪客,而且數量還在繼續增長。我們也很緊張當訪問量達到更多的時候,應用程序會如何處理——我們在凌晨4:30完成的,而且沒有足夠的時間進行測試。但是除了一些關于設計的評論和一些無意中錯誤分類的文章,反饋還是非常積極的!該網站不斷添加新故事,而且大部分內容都是正確分類的。它是一個概念的證明,但是是一個功能性的,它讓我們嘗試一個有趣的分類問題并把方法付諸實踐。