基于朴素贝叶斯模型的中文文本分类

这里只介绍主要实现过程,主要思想会在后面的博客中写出来,因为现在自己也是一知半解

数据集介绍

朴素贝叶斯模型是有监督分类模型,因此需要采用预处理好的训练数据集,我采用的是“复旦大学计算机信息与技术国际数据库中心自然语言处理小组”提供的小样本中文文本分类语料

有能力的也可以自己写爬虫爬取文本数据。

中文分词

因为是中文文本分类,所以需要进行中文分词,本文采用python 的 jieba 分词。以下以简单的一段文本为例来说明 jieba 分词:

import jieba

content = "中文文本分类是文本处理中的一个基本问题。"

seg_list1 = jieba.cut(content,cut_all=False)
print("默认切分模式")
print(" ".join(seg_list1))

seg_list2 = jieba.cut(content,cut_all=True)
print("全切分模式")
print(" ".join(seg_list2))

seg_list3 = jieba.cut_for_search(content)
print("搜索引擎分词模式")
print(" ".join(seg_list3))

统计文本词频并计算TF-IDF

通过分词后的结果,对文本中的单词进行词频统计。
如果将文本看做一个对象,那么分词结果就是这个对象的特征,某个词的词频数量越大,说明这个特征越具有代表性(简单理解)。
但是你可能会问,像“的”,“是”,这样的常用词哪里具有代表性?
因此,我们需要降低这类普遍出现具有较低意义的词的特殊性,这类词的特性就是在大量的文本集合中都有出现,不论是这类文本具有什么样的主题。
TF-IDF值就是针对这一问题进行词频统计的。
TF是指某一给定词语该文档中的出现次数。
IDF是指含有某一指定词在文档集合中出现的次数的倒数再取对数,越多的文档包含该词,值越接近0。
TF-IDF值就是 TF*IDF。

示例:

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
# 分类好的语料
corpus = ["中文 文本 分类 是 自然语言 处理 中 的 一个 基本 问题",
          "我 爱 自然语言 处理",
          "这 是 一个 问题 以前 我 从来 没有 遇到 过"]
# 词频统计
vectorizer = CountVectorizer()
# 计算TF-IDF
transformer = TfidfTransformer()

tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus))

word = vectorizer.get_feature_names()
for i in word:
    print(i)

weight = tfidf.toarray()
print(weight)

for i in range(len(weight)):
    print("第{}篇文档的词语TF-IDF权重:".format(i))
    for j in range(len(word)):
        print(word[j]+":"+str(weight[i][j]))

模型训练和模型评估

python 的 sklearn 工具提供了各种模型,包括了朴素贝叶斯模型:

#这里是假设有训练文本和对应的类别标签的代码,仅供参考,无法运行
from sklearn.cross_validation import train_test_split
# 数据集7/3分
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.3)
from sklearn.naive_bayes import MultinomialNB
from sklearn import metrics
# 训练
bayes_clf = MultinomialNB(alpha=0.01,fit_prior=True)
bayes_clf.fit(X_train,y_train)
# 预测
y_pred = bayes_clf.predict(X_test)
y_predprob = bayes_clf.predict_proba(X_test)[:,1]
# 测试集验证模型
precision = metrics.precision_score(y_test,y_pred)
recall = metrics.recall_score(y_test,y_pred)
F1 = metrics.f1_score(y_test,y_pred)
# 交叉验证
from sklearn.cross_validation import cross_val_score
cross_result = cross_val_score(bayes_clf,X_test,y_test,cv=5)

print("模型在测试集上的预测情况如下:")
print("准确率:%0.6f".format(cross_result))
print("查全率:%0.6f".format(precision))
print("查准率:%0.6f".format(recall))
print("F1值:%0.6f".format(F1))

针对复旦大学数据集的完整程序实现

采用的数据集是前文提到。提供了下载链接…

#coding = utf-8
import os
import jieba
from numpy.lib.function_base import vectorize

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.model_selection import train_test_split
from sklearn import metrics
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import cross_val_score
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix

def readfile(path):
    with open(path,'r',encoding='utf8',errors="ignore") as f:
        return f.read()

def processData(corpus_path):
    train_corpus = []
    train_label = []  
    cate_list = os.listdir(corpus_path)
    for mydir in cate_list:
        class_path = corpus_path+mydir+"/"
        file_list = os.listdir(class_path)
        for file_path in file_list:
            fullname = class_path+file_path
            content = readfile(fullname)
            # 对文本进行处理
            content.strip()
            content.replace('\r\n','').strip()
            content_seg = jieba.cut(content)
            train_corpus.append(" ".join(content_seg))
            train_label.append(mydir)
    print("分词结束...")
    return train_corpus,train_label

def train(train_corpus,train_label,stpwrdlst):
    vectorizer = CountVectorizer(stop_words=stpwrdlst,max_df=0.5)
    transformer = TfidfTransformer()
    tfidf = transformer.fit_transform(vectorizer.fit_transform(train_corpus))
    weight = tfidf.toarray()
    print(weight)
    print("生成TF-IDF矩阵结束...")

    # 7/3分划分为训练集和验证集
    X_train,X_test,y_train,y_test = train_test_split(tfidf,train_label,test_size=0.3)
    # 训练
    bayse_clf = MultinomialNB(alpha=0.01,fit_prior=True)
    bayse_clf.fit(X_train,y_train)
    print("模型训练结束...")
    print("在验证集上的预测情况如下:")
    y_pred = bayse_clf.predict(X_test)
    print("交叉验证:")
    print(cross_val_score(bayse_clf,X_test,y_test,cv=5))
    print(classification_report(y_test,y_pred,target_names=None))
    print("混淆矩阵:")
    print(confusion_matrix(y_test,y_pred))


if __name__ == "__main__":
    # 数据处理
    corpus_path = "./中文文本分类项目数据集/train_corpus/"
    train_corpus,train_label = processData(corpus_path)
    # 读取停用词
    stopword_path = "./中文文本分类项目数据集/hlt_stop_words.txt"
    stpwrdlst = readfile(stopword_path).splitlines()
    # 开始训练
    train(train_corpus,train_label,stpwrdlst)

结束了 binggo

其实还可以针对数据集中的test_corpus进行预测,但是意义不大,有需要请留言…