文本分類是NLP領域非常常見的應用場景芽淡,在現實生活中有著非常多的應用,例如輿情監(jiān)測豆赏、新聞分類等等挣菲。在文本分類中,常見的分類算法有SVM掷邦、KNN白胀、決策樹、神經網絡等等抚岗。本文簡單介紹了中文文本分類的應用實踐或杠。
現有的文本分類方法主要分為兩大類,分別是基于傳統(tǒng)機器學習的方法和基于深度學習的方法宣蔚⊥⒍唬基于傳統(tǒng)機器學習的文本分類方法主要是是對文本進行預處理、特征提取件已,然后將處理后的文本向量化笋额,最后通過常見的機器學習分類算法來對訓練數據集進行建模,傳統(tǒng)的文本分類方法中篷扩,對文本的特征提取質量對文本分類的精度有很大的影響兄猩。基于深度學習的方法則是通過例如CNN、LSTM等深度學習模型來對數據進行訓練枢冤,無需人工的對數據進行特征抽取鸠姨,對文本分類精度影響更多的是數據量以及訓練的迭代次數。本文主要介紹一下傳統(tǒng)機器學習算法在中文文本分類中的應用。
新聞數據獲取
本文中的數據集來源于網易新聞,數據通過爬蟲獲取上祈,共包括體育靠胜、健康假褪、軍事娛樂等類別在內的9大類,每類2000篇,總計18000篇新聞數據。
這里簡單介紹一下爬蟲的方法祟峦,以網易科技類新聞為例,我們要獲取科技新聞數據的第一步就是要知道新聞的url是什么徙鱼,那么我們如何去獲取每一篇新聞的url呢宅楞?首先點開網易新聞的科技類首頁,在進入科技新聞首頁之后袱吆,我們會發(fā)現位于網頁中間有一塊下拉刷新的新聞展示位:
可以猜測在我們執(zhí)行下拉操作的時候厌衙,瀏覽器會向服務器發(fā)送一次請求數據的操作,在獲取到數據之后展示在頁面上绞绒。如果我們可以模擬瀏覽器向服務器發(fā)送請求數據的操作婶希,就能獲取到新聞數據的鏈接,抱著這樣的想法处铛,我們按F12查看瀏覽器獲取到的數據饲趋,我們需要尋找的是一條包含刷新新聞數據的請求:
然后我們如愿的找到了這么一條請求拐揭,返回的數據是一個json類型的list撤蟆,里面包含了需要刷新的新聞的title、url堂污、時間等信息家肯,這條請求的url是http://tech.163.com/special/00097UHL/tech_datalist_02.js?callback=data_callback,通過觀察這條url我們可以發(fā)現一些規(guī)律盟猖,tech表示這是科技新聞的請求操作讨衣,02表示這是請求的第二頁數據,抱著這樣的猜想我們繼續(xù)對頁面進行下拉操作式镐,可以獲得第三頁的請求數據:
第三頁的請求url為http://tech.163.com/special/00097UHL/tech_datalist_03.js?callback=data_callback反镇,我們發(fā)現如上述的猜想一致,可以通過在url中修改類別參數和頁碼參數方便地獲取到數據的真實url地址娘汞。
爬取新聞文本的最后一步就是根據新聞的url地址將新聞的文本內容內容提取出來保存文件歹茶,這里通過分析網頁的結構:
可以發(fā)現新聞的文本內容裝在post_text節(jié)點中,標題和新聞文本均post_text節(jié)點的p子節(jié)點中,這里我們可以通過BeautifulSoup來解析html文檔數惊豺,并輕易的獲取新聞文本燎孟,解析代碼如下:
req = requests.get(url,headers)
soup = BeautifulSoup(req.text,"html.parser")
title = soup.title.string
content = soup.find('div', class_='post_text').text.strip()
由于不同的類別的新聞頁面的網頁結構有所差別,所以在進行文本提取的時候需要根據頁面結構的真實情況去具體分析尸昧。通過上述的爬蟲操作揩页,最后我們獲得了9大類的新聞文本數據:
文本特征提取
文本特征的抽取是文本挖掘的一個基本問題,它是從文本數據中抽取出能夠體現文本信息特征的單元烹俗,從而將其從無結構的文本數據轉換為計算機可以識別的結構化數據爆侣。在文本挖掘中用于表達文本的基本單元叫特征項,特征項具有如下的特點:
1.?????特征項要具有表達文本信息的能力
2.?????特征項要具有區(qū)分文本的能力
3.?????特征項的數量不能太多
在文本挖掘中常常使用字衷蜓、詞累提、短語作為特征項。而詞與字相比磁浇,具有更加強大的表達能力斋陪,同時詞與短語相比,切分難度又要相對小很多置吓,因此在實際應用中大多使用詞作為特征項无虚,也稱為特征詞。特征詞可以用來標識文檔衍锚,計算文檔與文檔之間的相似性友题。文本的特征抽取在對文檔進行分類、聚類戴质,提取文檔的關鍵詞等方面有著非常重要的作用《然拢現有的一些常見的文本特征提取算法有TF-IDF、TextRank告匠,卡方檢驗等戈抄。這里簡單介紹一下TF-IDF,其他的算法有興趣的同學可以自行查閱相關資料后专。
TF-IDF?是一種基于統(tǒng)計的特征抽取方法划鸽,可以計算一個詞語對于文檔庫中的一篇文檔的重要性程度。?TF-IDF的核心思想是:一個詞如果在一篇文檔中出現的頻次很高戚哎,那么從一定程度上可以說明這個詞在這篇文檔中具有比較重要的作用裸诽,可以表達文檔的特征。同時一個詞如果在其他文章數出現的次數較少型凳,說明這個詞在文檔中具有很好的區(qū)分度丈冬,這也滿足了上述特征項特點中的前兩條。
TF是指詞頻甘畅,表示一個詞在文檔中出現的頻次埂蕊,為了防止不同文檔長度對于詞頻的影響实夹,這里的?TF?是經過歸一化的,用公式可以表示為:$tf_{i,j}=\frac{n_{i,j}}{\sum_kn_{k,j}}$,式子中的$n_{i,j}$表示$t_i$在文件$d_j$中出現的次數粒梦,$\sum_kn_{k,j}$表示文件$d_j$中所有詞出現的總次數亮航。
IDF(inverse document frequency)?是指逆向文件頻率,這個指標用于衡量一個詞的普遍重要性程度匀们,由總文件數目比上包含該詞的文件數目缴淋,然后在對這個值求對數得到,具體公式表示為:$idf_i=\log\frac{left| D right|}{left| {j:t_i \in d_j right|}}$,式中$left| D right|$表示總文檔數,${j:t_i \in d_j right|}$表示包含該詞語的文件數,最后將TF與IDF相乘就可以得到TF-IDF值泄朴。
TF-IDF算法手動實現起來也很簡單重抖,但python下還是提供了一些現成的實現方法,比如方法jieba.analyse.extract_tags祖灰,我們可以通過如下的代碼輕易的提取出文本中最重要的前N個詞:
Import jieba.analyse
#以上對Context進行分詞操作
keywords = jieba.analyse.extract_tags(context,topK=N)
for word in keywords:
? ? print word
在了解了通過TF-IDF算法或者TextRank等其他算法來提取文本關鍵詞的方法之后钟沛,我們怎么來提取與類別相關的關鍵詞呢?我們這里提供了一種比較簡單有效的方法局扶,首先恨统,依次對每個類別中的每篇新聞提取關鍵詞,將每篇新聞中權重最高的N個詞放入一個map中三妈,如果map中已經出現過該詞畜埋,則對其權重加1,遍歷完該類別所有的新聞之后畴蒲,我們就可以得到一個<k,v>鍵值對悠鞍,k是詞語,v是關鍵詞出現的次數模燥,然后我們對這個鍵值對按value從高到低排序咖祭,取出value值最大的M個詞放入關鍵詞集中。當遍歷完所有類別的新聞之后蔫骂,我們就可以得到一個由多個類別的關鍵詞構成的特征詞集么翰。
在通過上述處理之后,我們可以通過這個特征詞集去對一篇未分類的新聞文本進行特征詞提取纠吴,第一步是通過特征提取算法提取出權重最高的N個特征詞硬鞍,然后通過上文中得到的特征詞集對這N個特征詞進行過濾慧瘤,只保留在特征詞集中出現過的特征詞戴已。
詞向量化
詞向量化是將詞從符號型的文本數據轉換為向量的過程,常見的詞向量化方法有離散表示以及分布式表示兩種锅减。
離散表示?(One-hot Representation)?本質上就是使用一個高維的向量來表示一個詞糖儡,向量的維度等于詞典的大小,每個向量只有一個維度的值是?1怔匣,其他維度的值均為?0握联,向量中值為?1?的那個位置即是詞語在詞典中的位置桦沉。例如:
南京”表示為?[0 0 0 1 0 0 0 0 0 0 0…]
北京”表示為?[1 0 0 0 0 0 0 0 0 0 0…]
這種詞向量化的方法屬于稀疏表達方式,這種表達方式最大的好處就是簡單金闽,但是它也有兩個非常明顯的缺點:
1.?容易造成維度災難纯露,因為每個詞的向量維度等于詞典大小,即每個詞向量化之后長度以萬計代芜,而這會大大地增加計算的復雜度埠褪,對效率造成很大的負面影響,同時也需要浪費很多的存儲資源挤庇。
2.?不能體現出詞向量與詞向量之間的相關性钞速,丟失了很多重要的信息,例如“北京”嫡秕、“南京”渴语、“可樂”這些詞,“北京”與“南京”之間的相似度要比“北京”與“可樂”之間的相似度更高昆咽,但是在離散表示方法中無法體現出這樣的關系驾凶。
分布式表達的核心思想是對語言進行建模,將語言中的每個詞映射到一個固定長度的向量空間中掷酗,這里的長度要遠遠小于離散表達向量的維度規(guī)模狭郑。每一個詞向量都對應了向量空間中的一個點,而且在這個向量空間中引入了距離的概念汇在,向量空間中兩個點之間的距離表示兩個詞之間的相似度『踩現在業(yè)內比較流行的分布式表達方式是google2013年開源的word2vec工具,Word2vec?簡單來說就是對給定的語料數據建立一個神經網絡語言模型糕殉,而詞向量作為神經網絡的輸入亩鬼,是通過神經網絡學習語言模型時產生的副產品,詞向量在訓練過程中隨著神經網絡的更新不斷調整直到收斂阿蝶。
Genism.models是Python下非常好用的word2vec工具雳锋,我們可以通過如下的代碼來實現對文本的建模以及詞向量化:
from gensim.models import word2vec
#對文本進行建模
model = word2vec.Word2Vec(train_data,min_count=1,size=100)
model.save('model/News2vec_model')? #存儲模型
#將詞轉換為詞向量
model = gensim.models.Word2Vec.load(model_path)
wordvec = model[word]
上述兩種向量化方法均可以將新聞文本轉換為文本特征項向量,采用離散表達方式時羡洁,特征向量的維度等于特征詞集的大小玷过,即如果一篇文章中有第i個詞,則將向量中第i個詞置1筑煮,如果沒有這個詞則置0辛蚊;而采用分布式表達時,我們可以簡單的將所有詞的詞向量做加權均值來作為新聞的文本特征向量真仲,這種方法看起來很簡單卻又非常有效袋马。
模型訓練及分類
常見的機器學習方法有線性模型、決策樹秸应、神經網絡虑凛、支持向量機碑宴、強化學習以及最近熱度非常高的深度學習等,本文主要簡單介紹一下KNN和支持向量機在文本分類中的應用桑谍。
K?近鄰算法?(KNN) [24]?是一種典型的非參數模型算法延柠,這是一種非常基本的機器學習方法锣披。該算法的基本思想就是在一個訓練集大小為?N?的樣本集中捕仔,求待分類樣本與訓練集中樣本之間距離,并統(tǒng)計與待分類點距離最近的?K?個樣本點的類別盈罐,最后將待分類點的類別劃分為?K?個樣本點所屬類別最多的那個類別榜跌。當?K?= 1?時,該算法即為最近鄰算法盅粪。下面直接給出使用KNN進行模型訓練及分類的代碼:
import numpy as np
from sklearn import neighbors
traindata,trainlabel=loadTraindata(i)
testdata,testlabel= loadTestdata(i)
# 訓練模型
# clftree = tree.DecisionTreeClassifier(max_depth=7) #可限制最大深度
clf = neighbors.KNeighborsClassifier()
# 擬合模型
clf.fit(traindata, trainlabel)
#測試集上的預測
result=clf.predict(testdata)
count=0
for i in range(len(result)):
if(result[i]!=testlabel[i]):
count++
print("準確率:" + count/len(result))
9大類的分類效果如下:
我們可以發(fā)現KNN在模型訓練上耗時非常的少钓葫,且在絕大部分類別上的分類準確率都可以達到不錯的效果。
支持向量機(SVM)是一種非常重要且應用廣泛的傳統(tǒng)機器學習方法票顾,最早是由?Vladimir N. Vapnik?于?1963?年提出础浮,現在流行的版本是由?Corinna Cortes?和Vapnik?于?1993?年提出。在深度學習方法流行起來之前奠骄,?SVM?通常被認為是近十幾年來最有效最成功的機器學習算法之一豆同。假設存在訓練樣本數據集$T={(x_1,y_1),(x_2,y_2,...,(x_3,y_3)},y_i \in {-1,1}$,樣本$(x_i,y_i)$?散落在樣本空間中,SVM?要解決的問題就是在樣本空間中找到一個最優(yōu)的超平面來將正負兩類樣本劃分開,效果如圖所示:
關于這個最優(yōu)的超平面如何求解含鳞,感興趣的同學可以去學習一下原理并試著自己推導一下公式影锈,我們這里直接給出相關的代碼
import numpy as np
from sklearn.svm import SVC
traindata,trainlabel=loadTraindata(i)
testdata,testlabel= loadTestdata(i)
# 訓練模型
# clftree = tree.DecisionTreeClassifier(max_depth=7) #可限制最大深度
clf = SVC(C=1.0,kernel="rbf")
# 擬合模型
clf.fit(data, label)
#測試集上的預測
result=clf.predict(testdata)
count=0
for i in range(len(result)):
if(result[i]!=testlabel[i]):
count++
print("準確率:" + count/len(result))
9大類的分類結果如下
和KNN相比,SVM在模型訓練上更加耗時蝉绷,但是預測速度和分類的效果都要更勝一籌鸭廷。
總結
本文簡單介紹了傳統(tǒng)機器學習在中文文本分類上的應用,包括了數據的爬取熔吗、預處理以及模型訓練和預測辆床,限于篇幅,很多概念原理和公式推理都沒有給出桅狠,感興趣的同學可以自行查閱讼载。除了上述介紹的基于傳統(tǒng)機器學習的方法,現在得益于數據量的大規(guī)模增漲以及計算能力的提升中跌,深度學習在文本處理上也有了廣泛的應用咨堤,且有著非常好的效果,比如CNN晒他、LSTM等吱型。但是不同算法之間各有優(yōu)勢逸贾,我們需要根據問題的具體應用場景和規(guī)模陨仅,來選擇合適的方法來解決問題津滞。