用Python端對端數(shù)據(jù)分析識別機(jī)器人“僵尸粉”
導(dǎo)讀:不僅微博,在twitter中也存在大批的“僵尸粉”。Twitter中的“僵尸粉”不僅能夠在無人干預(yù)下撰寫和和發(fā)布推文的程序,并且所產(chǎn)生的推文相當(dāng)復(fù)雜。如何識別這批“僵尸粉”或者說“機(jī)器人粉絲”?下面我們將通過Python的Pandas庫、自然語言處理學(xué)習(xí)NLTK和scikit-learn創(chuàng)建分類器對Twitter機(jī)器人進(jìn)行識別。
在本文中,我想要討論一個互聯(lián)網(wǎng)現(xiàn)象:機(jī)器人,特別是Twitter機(jī)器人。
我之所以一直關(guān)注Twitter機(jī)器人主要是因為它們有趣又好玩,另外也因為Twitter提供了豐富而全面的API,讓用戶可以訪問到Twitter平臺信息并了解它們是如何運(yùn)作的。簡而言之,這讓Python強(qiáng)大的數(shù)據(jù)分析能力得到了充分地展示,但也暴露了它相對薄弱的環(huán)節(jié)。
對于那些不熟悉Twitter的人, 我們先簡單介紹一下。Twitter是一個社交媒體平臺,在該平臺上用戶可以發(fā)布140字以內(nèi)的惡搞笑話,稱之為“推文”。Twitter根本上區(qū)別于其它的社交媒體是因為推文默認(rèn)是公開的,并且在Twitter上互相關(guān)注的人實際上不一定彼此認(rèn)識。你可以認(rèn)為Twitter不單單是個人信息流,更像是一個想法交易市場,流通的貨幣則是粉絲和推文轉(zhuǎn)發(fā)。

Twitter另外一個顯著的特點(diǎn)是它自身內(nèi)容的“嵌入式能力”(見上圖的搞笑例子)。如今,將推文作為新媒體的一部分是稀疏平常的一件事。主要是因為Twitter開放式的API,這些API能讓開發(fā)者通過程序來發(fā)推文并且將時間軸視圖化。但是,開放式的API讓Twitter在互聯(lián)網(wǎng)廣泛傳播,也對一些不受歡迎的用戶開放了門戶,例如:機(jī)器人。
Twitter機(jī)器人是能夠在無人干預(yù)下撰寫和和發(fā)布推文的程序,并且所產(chǎn)生的推文相當(dāng)復(fù)雜。其中一些機(jī)器人相對不活躍,只是用來增加粉絲和收藏推文的。而另一些會借助復(fù)雜的算法來創(chuàng)建具有說服力的推文。所有的Twitter機(jī)器人都可能變得讓人討厭,因為它們的出現(xiàn)破壞了Twitter分析的可信度和商業(yè)價值,最終甚至?xí)|及底線。
那么Twitter能對這些機(jī)器人做些什么呢?首先,要做的是去識別它們,以下是我的方法。
創(chuàng)建標(biāo)簽
核心目標(biāo)是創(chuàng)建一個分類器來識別哪些賬號是屬于Twitter機(jī)器人的,我是通過監(jiān)督學(xué)習(xí)來實現(xiàn)的。“監(jiān)督”意味著我們需要已有標(biāo)注的樣本數(shù)據(jù)。例如,在最開始的時候,我們需要知道哪些賬號屬于機(jī)器人,哪些賬號屬于人類。在過去的研究中,這個費(fèi)力不討好的任務(wù)已經(jīng)被研究生的使用(和濫用)完成了。例如:Jajodia 等人通過手動檢測賬號,并且運(yùn)用Twitter版本的圖靈檢測來判斷一個賬號是否屬于機(jī)器人,判斷推文是否由機(jī)器人發(fā)布的。問題是我已經(jīng)不再是個研究生了并且時間寶貴(開玩笑)。我解決了這個問題多虧我的朋友兼同事Jim Vallandingham 提出的絕妙建議,他向我推薦了fiverr,一個花5美元就能獲取各類奇特服務(wù)的網(wǎng)站。

花了5美元,等待24小時之后,我有了5500個新粉絲。因為我知道在機(jī)器人關(guān)注之前,我的粉絲都有哪些,所以我可以有效地識別哪些是人類,哪些是一夜激增的機(jī)器人粉絲。
創(chuàng)建特征
由于Twitter有豐富的REST API(REST指一組架構(gòu)約束條件和原則,滿足約束條件和原則的應(yīng)用程序設(shè)計——譯者注),創(chuàng)建特征集是幾乎不違反服務(wù)條約的行為。我使用Python-twitter模型去查詢兩個終端指標(biāo):GET users/lookup(獲取用戶信息)和 GET statuses/user_timeline(獲取用戶狀態(tài)、時間軸信息)。獲取用戶信息的終端會返回JSON文本,這些文本中包含了你所希望得到的用戶賬號信息。例如:用戶是否使用了默認(rèn)的模板配置,關(guān)注者/被關(guān)注者的數(shù)量,發(fā)布推文的數(shù)量。從獲取的用戶時間軸信息中,我抓取了數(shù)據(jù)集中每個用戶***的200條推文。
問題是,Twitter官方不允許你直接大量地收集你所想要的數(shù)據(jù)。Twitter限制了API的調(diào)用頻率,這樣意味著你只能在需求范圍內(nèi)獲取少量的樣本數(shù)據(jù)進(jìn)行分析,因此,我使用了以下美妙的方法(blow_chunks)來獲取數(shù)據(jù):
#不要超出API的限制
如果查詢的長度大于所允許的***值,那么將查詢分塊。調(diào)用生成器.next()方式來抓取***個塊并將此需求發(fā)往API。然后暫停獲取數(shù)據(jù),兩個數(shù)據(jù)請求需要間隔16分鐘。如果所有的塊都發(fā)出了,那么生成器將會停止工作并且終止循環(huán)。
機(jī)器人是怪物
通過快速地清理和整理數(shù)據(jù),你會很快發(fā)現(xiàn)不正常的數(shù)據(jù)。通常情況下,機(jī)器人的關(guān)注量是1400,而人類的關(guān)注量是500。機(jī)器人的粉絲分布具有很大的差異性,而人類的粉絲分布差異性較小。有些人的人氣很高,有一些卻沒那么高,大多數(shù)人是介于兩者之間。相反,這些機(jī)器人的人氣非常低,平均只有28個粉絲。
將推文變成數(shù)據(jù)
當(dāng)然,這些機(jī)器人在賬號信息層面上看起來很奇怪,但是也有很多人的人氣很低,而且賬號中幾乎空蕩蕩的,只有一張頭像。那么他們發(fā)布的推文是怎樣的呢?為了將推文數(shù)據(jù)加入到分類器中,一個賬號的推文信息需要被匯總成一行數(shù)據(jù)。有一種摘要度量方式建立在詞匯多樣性之上,就是每個特定詞匯數(shù)量占文檔總詞匯數(shù)量的比例。詞匯多樣性的范圍是從0到1,其中0代表這個文檔中沒有任何詞匯,1代表該文檔中所有詞都只出現(xiàn)過一次??梢詫⒃~匯多樣性作為詞匯復(fù)雜性的度量方法。
我用Pandas 來快速優(yōu)雅地運(yùn)用歸納函數(shù),例如詞匯多樣性,對推文進(jìn)行處理。首先,我把每個用戶的所有推文放進(jìn)一個文檔,并進(jìn)行標(biāo)記,這樣我會得到一個詞匯列表。然后,我再利用NLTK(自然語言處理技術(shù))移除所有標(biāo)點(diǎn)符合和間隔詞。
通過Pandas在數(shù)據(jù)集上使用自定義函數(shù)是極其方便的。利用groupby,我通過賬戶名將推文分組,并且在這些分組推文中應(yīng)用詞匯多樣性函數(shù)。我鐘愛這個語法的簡潔和靈活,可以將任何類別的數(shù)據(jù)分組并且適用于自定義的歸納函數(shù)。舉個例子,我可以根據(jù)地理位置或者性別分類,并且僅僅根據(jù)分組的變量,計算所有組的詞匯多樣性。

同樣的,這些機(jī)器人看上去很怪異。人類用戶有著一個美得像教科書一般的正態(tài)分布,其中大部分的詞匯多樣性比例集中在0.7。而機(jī)器人的卻很極端化,詞匯多樣性接近于1。語義差異性為1,這意味著每個詞在文檔中都是獨(dú)特的,也就是說機(jī)器人要么幾乎不發(fā)推文,要么只是發(fā)隨機(jī)文字。

建模
我利用stickit-learn,Python中最重要的機(jī)器學(xué)習(xí)模塊,進(jìn)行建模和校驗。我的分析計劃差不多是這樣的,因為我主要關(guān)注預(yù)測精準(zhǔn)度,為什么不試試一些分類方法來看看哪個更好呢?Scikit-learn的一個強(qiáng)項是簡潔,同時在構(gòu)建模型與管道時與API兼容,這樣易于測試一些模型。

我試了3個分類器,分別是樸素貝葉斯、邏輯回歸和隨機(jī)森林分類器??梢钥吹竭@三種分類方法的語法是一樣的。在***行中,我擬合分類器,提供從訓(xùn)練集和標(biāo)簽為y的數(shù)據(jù)中得到的特征。然后,簡單地通過將來自測試集的特征傳入模型來預(yù)測,并且從分類報告查看精確度。

毫無疑問,隨機(jī)森林表現(xiàn)得***,整體精度為0.9,而樸素貝葉斯的是0.84,邏輯回歸的是0.87。令人驚訝的是,利用現(xiàn)有的分類器,我們識別機(jī)器人的準(zhǔn)確率可以達(dá)到90%,但是我們是否可以做得更好?答案是:可以。事實上,利用GridSearchCV可以非常容易地調(diào)試分類器。GridSearchCV采用了一種分類方法和一系列的參數(shù)設(shè)置進(jìn)行測試。其中,這一系列參數(shù)是一個鍵入了該模型配置參數(shù)的字典。GridSearchCV***的一點(diǎn)是可以像對待剛才我們看到的分類方法一樣地對待它。也就是說,我們可以使用.fit()和.predict()函數(shù)。

啊哈,更加精確了!簡單的調(diào)試步驟產(chǎn)生了一個新格局,預(yù)測的準(zhǔn)確率提高了2%。為調(diào)試過的隨機(jī)森林檢查變量重要性策略產(chǎn)生了一些驚喜。朋友數(shù)量和粉絲數(shù)量是機(jī)器人識別中最重要的變量。

但是,我們需要更好的工具來開發(fā)迭代模型
Scikit-learn還有很大的提升空間,特別是生成模型診斷和模型比較應(yīng)用上的功能性。一個說明我的意思的例子是,我想帶你走進(jìn)另一個世界,那里不用Python,而是R語言。那里也沒有scikit-learn,只有caret(Classification and Regression Training,是為了解決分類和回歸問題的數(shù)據(jù)訓(xùn)練而創(chuàng)建的一個綜合工具包——譯者注)。讓我告訴你一些caret的,在scikit-learn里可以被復(fù)制的強(qiáng)項。
以下是confusionMatrix函數(shù)的輸出結(jié)果,與scikit-learn分類報告的概念等價。你會注意到有關(guān)comfusionMatrix函數(shù)輸出的準(zhǔn)確度報告的深度。有混淆矩陣(confusion matrix)和大量將混淆矩陣作為輸入的準(zhǔn)確度測量維度。大多數(shù)時候,你也許只會使用到一個或者兩個測量維度,但是如果它們都可用是***的,這樣,可以在你所處的環(huán)境下使用效果***的,而無需增加額外代碼。

Caret***的一個優(yōu)勢是提取推理模型診斷的能力,而這在scikit-learn中是看似不可能完成的。以擬合一個回歸方法為例:你自然想看看回歸系數(shù),樣本滿意度,P值和擬合優(yōu)度。即使你僅僅對預(yù)測準(zhǔn)確性感興趣,理解模型的原理和知道模型是否滿足假設(shè)條件也是有用的。為了在Python中復(fù)制這樣的輸出,需要在與statsmodels類似的地方改裝模型,這樣會造成建模過程的浪費(fèi)和繁瑣。

但是,我認(rèn)為R語言中caret包***的特點(diǎn)是能夠容易地比較不同的模型。使用 resamples 函數(shù),可以很快地生成可視化效果來比較我選擇的指標(biāo)模型的性能。這種類型的效用函數(shù)在建模過程中是超級有用的,也讓你在不想花費(fèi)大量時間來制作圖的終稿的時候可以就早期的結(jié)果進(jìn)行交流。

對于我而言,這些功能產(chǎn)生了所有的差異,這也是R語言仍然是我建模***語言的主要原因。