上一节,介绍了R语言,和本人做文本分类时运用的几个包,还有个小例子。
这一节就用代码来简单介绍下我做文本分类的过程。
我的分类很简单,就是给你一段文字,你将它分类到特定的类别。当然,这是前提是需要大量的语料库,且已经分好类。可以理解为运用监督学习的方法吧。不过我的类别较多,不是二元分类,但是目前的分类器都是二元的,二元的可以改造成多元分类器。有One to One 和 One to the other分类。所幸,R语言里的maxent包,本身就已经帮你做好了,且它会根据类别近似度打分,你可以得到该文档在各类别下的分数,得到排名,从而得出与之相近的多个类别。无疑是非常有用的。
1、我的文本数据在经过一些处理后格式就是:
文本标题(Title) | 文本描述(Description) | 类别(Type) |
---|---|---|
…… | …… | A |
…… | …… | B |
…… | …… | C |
我是以词类作为特征的,暂时将标题也作为特征。所以先将标题和描述合并。
可通过如下函数:
BindData <- function(data)
{
#将标题和描述合并为一个表
temp <- data.frame(des=NULL,typ=NULL)
#x <- NULL
for(i in 1:dim(data)[1])
{
x <- paste(data[i,1],data[i,2],sep=",") #合并标题和描述
tempx <- data.frame(des=x) #创建临时数据框用于合并
y <- as.character(data[i,3])
tempy <- data.frame(typ=y)
tempxy <- cbind(tempx,tempy)
temp <- rbind(temp,tempxy)
print(i)
}
return (temp)
}
完成后:
文本(Des) | 类别(Type) |
---|---|
…… | A |
…… | B |
…… | C |
可以算作“初始”语料库。
2、继续制作语料库。
主要步骤(采用比较简单的步骤):
代码如下:
library(tm)
library(rJava)
library(Rwordseg)
#读取刚刚的“初始”语料库。
text= read.table("maxent_10.txt",header = TRUE,row.names=1,fileEncoding = "UTF-8")
#读取停用词,stopwords_CN可在网上下载到。
data_stw <- readLines("stopwords_CN.txt",encoding = "UTF-8")
#去停用词的函数,将分词后的词项,如有符合停用词的,则去掉。这个函数在后面讲会调用
removeStopWords<-function(x,words){
ret<-character(0)
index<-1
it_max<-length(x)
while(index<=it_max){
if(length(words[words==x[index]])<1)ret<-c(ret,x[index])
index<-index+1
}
ret
}
#新建列表,用于存放去停用词后的,各文档词项。
doc_CN <- list()
for(j in 1:dim(text)[1])
{
x <- c(segmentCN(as.character(text[j,1])),nosymbol=TRUE) #对文档分词
doc_CN[[j]] <- removeStopWords(x,data_stw) #去停用词
}
kvid <- Corpus(VectorSource(doc_CN)) #调用tm包中的函数,生成语料库格式文档。
kvid <- tm_map(kvid,stripWhitespace)#去除文档中因去停用词导致的空白词。
#生成词项-文档矩阵(TDM)
control=list(removePunctuation=T,minDocFreq=1,wordLengths = c(1, Inf))
#默认的加权方式是TF-IDF,removePunctution,去除标点,
#minDocFreq = 1表示至少词项至少出现了1次,wordLengths则表示词的长度。
**有个特别说明这边也可以用DocumentTermMatrix(kvid,control)——文档-词项矩阵
**这样就是我最适合的模型了。后面有介绍。
tdm=TermDocumentMatrix(kvid,control)#词项-文档矩阵
#length(tdm$dimnames$Terms),用于查看当前的维度
tdm_removed=removeSparseTerms(tdm, 0.99) #一般词类做特征,维度都非常大,故需要降维。
#length(tdm_removed$dimnames$Terms)
###tdm_removed可以用inspect(tdm_removed[1:524,1:5])查看,1:524表示1到524行,1:5表示1到5行。
#读取类别和其对应的数量。为的是在词项文档矩阵后加入类别,便于后来的分类。
#这段代码很随意,只是针对我自己的文档来做的。
typ_text = read.table("部门类别及数量.txt",sep='\t',header = TRUE,row.names=1,fileEncoding = "UTF-8")
n=1
#我的文档有10个类别,因此生成10个文本,每个文本都是文档词项矩阵和对应类别,且我是按次序排好的
for(i in 1:10)
{
m <- n + typ_text[i,2]
ts <- inspect(tdm_removed[1:length(tdm_removed$dimnames$Terms),n:m-1])
#这是转置,先前没考虑那么多所以用了TermDocumentMatrix(kvid,control)。
#如果用了DocumentTermMatrix(kvid,control),就不需要转置了。
tk <- t(ts)
type <- data.frame(tp=rep(typ_text[i,1],dim(tk)[1]))
tm <- cbind(tk,type) #加入类别
filename <- paste(i,'.txt',sep = "")
write.table(tm,filename,sep = "\t", col.names = NA,fileEncoding = "UTF-8")
n <- typ_text[i,2] + n
}
到这,就生成了我所需要的语料库了。各人情况不同,可互相参考。
文档-词项矩阵:
文本编号\词项 | 词项1 | 词项2 | 词项3 | 词项4 |
---|---|---|---|---|
001 | 1 | 1 | 1 | 1 |
002 | 1 | 1 | 1 | 1 |
003 | 1 | 1 | 1 | 1 |
词项-文档矩阵:
文本编号\词项 | 001 | 002 | 003 | 004 |
---|---|---|---|---|
词项1 | 1 | 1 | 1 | 1 |
词项2 | 1 | 1 | 1 | 1 |
词项3 | 1 | 1 | 1 | 1 |
明显,文档-词项矩阵符合我的要求。