Part3文本聚類
分類和聚類算法,都是數據挖掘中最常接觸到的算法,分類聚類算法分別有很多種。可以看下下面兩篇文章對常見的分類聚類算法的簡介:
分類算法:http://blog.csdn.net/chl033/article/details/5204220
聚類算法:http://blog.chinaunix.net/uid-10289334-id-3758310.html
文本分類聚類會要用到這些算法去實現,暫時不用深究算法細節,R中已經有成熟的可以直接調用的這些算法了。大概說下分類和聚類的差異,照我的理解,分類算法和聚類算法最后實現的效果是相同的,都是給一個集合划分成幾個類別。不同的是分類算法是根據已知的確定類別去做划分,所以分類需要訓練集,有訓練、測試、預測這個過程;而聚類則未規定類別,它是基於給定集合的里面的內容,根據內容的相似度去給集合划分成指定的幾個類(你可以指定划分成多少個類,而不是指定有哪些類),這些相似度的測量就是聚類算法的核心,這個度量標准可以是歐幾里得距離、是曼哈頓距離、是切比雪夫距離等等。它們分別叫做有監督分類和無監督分類。
還是用Part2里面的例子。做聚類不需要訓練集,將文本內容做完分詞處理,也就是Part2里面2.對某品牌官微做分詞,這里處理完得到的結果hlzjTemp,用這個做接下來的聚類工作。下圖(圖片來源:玩玩文本挖掘)是一個文本挖掘的過程,不管是分類還是聚類,都要經歷前面一個過程將文本轉為為Tem-Document Matrix。然后再做后續分析Analysis,及分類或者聚類。另一個參考:R語言進行中文分詞和聚類
聚類算法是針對數值型變量的,先要將文本數據轉換為matrix—數據矩陣。過程如下,這里需要用到tm軟件包,先安裝該軟件包並加載。tm包中的Corpus()方法就是用來將文本轉換為語料庫的方法。DocumentTermMatrix()方法,顯然就是將語料庫轉換為文檔-詞條矩陣,然后再將文檔-詞條矩陣轉換為普通矩陣,過程如下:
>library(tm)
載入需要的程輯包:NLP
>corpus <-Corpus(VectorSource(hlzjTemp))
> hlzj.dtm<- DocumentTermMatrix(corpus,control=list(wordLengths=c(1,Inf)))
>hlzj.matrix <- as.matrix(hlzj.dtm)
補充說明:這個過程可能會遇到很多問題,沒有詳細的說明,附上兩個參考:用tm進行文本挖掘、R語言文本挖掘。
接下來就是做聚類了,聚類算法有很多,常見的幾種做聚類的方法
1. kmeans()
方法的介紹參考:http://blog.sina.com.cn/s/blog_4ac9f56e0101h8xp.html。運行結果kmeansRes是一個list,names方法可以查看到kmeansRes的所有維度或者說組件,其中第一個cluster就是對應的分類結果,我們可以查看到前三十個聚類的結果,第一排對應着行號,第二排對應着聚類的結果1-5分別代表1-5類。然后我們可以將原始微博和聚類結果賦值給一個新的list變量,這樣我們就能看到聚類結果和每條微博對應的關系了。最后將這個新的list變量hlzj.kmeansRes導出到本地,就能很方便地查看到聚類結果了。當然我們也可以通過fix()方法查看hlzj.kmeansRes的內容,如圖所示,content是原微博內容,type是聚類結果。每個類別對應的文本數據的特點就要靠我們自己來總結了,這是聚類的一個不足的地方。
> k <- 5
> kmeansRes <- kmeans(hlzj.matrix,k) #k是聚類數
> mode(kmeansRes)#kmeansRes的內容
[1]"list"
> names(kmeansRes)
[1]"cluster" "centers" "totss" "withinss"
[5]"tot.withinss" "betweenss" "size" "iter"
[9]"ifault"
> head(kmeansRes$cluster,10)
1 2 3 4 5 6 7 8 9 10
1 1 1 2 1 5 2 1 1 5
> kmeansRes$size #每個類別下有多少條數據
[1] 327 1159 63 63 27
>hlzj.kmeansRes <- list(content=hlzj,type=kmeansRes$cluster)
> write.csv(hlzj.kmeansRes,"hlzj_kmeansRes.csv")
> fix(hlzj.kmeansRes)
2. hclust()。
方法詳細介紹,過程不再細說http://blog.sina.com.cn/s/blog_615770bd01018dnj.html,這個方法可以用plot()來查看聚類結果圖,但是在數據量挺多的時候,圖的上面的內容都擠在一起看不清楚了,這種情況下,還是直接查看聚類結果比較好。同樣,將原始數據hlzj和分類結果放在一起hlzj.hclustRes來看。可以看出類跟kmeans的聚類結果有些接近,說明微博的特征還是挺明顯的。
> d <- dist(hlzj.matrix,method="euclidean")
> hclustRes <- hclust(d,method="complete")
> hclustRes.type <- cutree(hclustRes,k=5) #按聚類結果分5個類別
> length(hclustRes.type)
[1] 1639
> hclustRes.type[1:10]
1 2 3 4 5 6 7 8 9 10
1 1 1 2 1 2 3 1 1 2
> hlzj.hclustRes <- list(content=hlzj,type=hclustRes.type)
> hlzj.hclustRes <- as.data.frame(hlzj.hclustRes)
>fix(hlzj.hclustRes)
3. kernel聚類,方法specc()
軟件包kernlab中的specc()方法可以實現kernel聚類算法。查看這個包的說明文檔,見鏈接http://127.0.0.1:25210/library/kernlab/doc/kernlab.pdf,這是本機的幫助文檔,不知道大家的地址是不是都一致的,也可以輸入??kernel查看幫助文檔能看到。網上能夠找到的翻譯后的方法說明http://www.biostatistic.net/thread-49108-1-1.html。這個聚類結果五個分類的統計如下,第四個類別有1402個,其他分類分別是135,55,24和23,所以截圖中看到前面23個都是4類下,用這個聚類可能效果不是很理想。具體實現過程如下:
> stringkern <-stringdot(type="string")
> kernelRes <-specc(hlzj.matrix,centers=5,kernel=stringkern)
> mode(kernelRes)
[1] "numeric"
> length(kernelRes)
[1] 1639
> kernelRes[1:10]
1 2 3 4 5 6 7 8 9 10
4 4 4 4 4 4 4 4 4 4
> table(kernelRes)
kernelRes
1 2 3 4 5
135 55 24 1402 23
>temp <-t(kernelRes) #行列轉換
> hlzj.kernelRes<-list(cotent=hlzj,type=temp[1:1639]
> hlzj.kernelRes <-as.data.frame(hlzj.kernelRes)
> fix(hlzj. kernelRes)
4. 除此之外。
fpc軟件包中的dbscan()方法可以實現dbscan聚類,還有其他的聚類方法,就不一一介紹了,優劣取舍要在實際應用中去控制了。