我本次对4类文本进行分类((所有截图代码和数据集最后附带免费下载地址))
主要步骤:
1.各种读文件,写文件
2.使用jieba分词将中文文本切割
3.对处理之后的文本开始用TF-IDF算法进行单词权值的计算
4.去掉停用词
5.贝叶斯预测种类
文本预处理:
除去噪声,如:格式转换,去掉符号,整体规范化
遍历的读取一个文件下的每个文本
中文分词
中文分词就是将一句话拆分为各个词语,因为中文分词在不同的语境中歧义较大,所以分词极其重要。
原型:我今天中午吃的小面。
分词:我、今天、中午、吃、的、小面。
其中 我、的 两个分词属于停用词(停用词后面讲)
我们本次才用jieba分词来进行辅助,那么jieba分词有这么几个类型
1.精确模式,试图将句子最精确的起开,适合文本分析。
2.全模式,把句子中所有的可以成词的词语都扫描出来,速度非常快,但是不能解决歧义。
3.搜索引擎模式,再将却模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词
#精确模式: 我/ 去过/ 清华大学/ 和/ 北京大学/ 。
#全模式: 我/ 去过/ 清华/ 清华大学/ 华大/ 大学/ 和/ 北京/ 北京大学/ 大学/ /
#搜索引擎模式: 我/ 去过/ 清华/ 华大/ 大学/ 清华大学/ 和/ 北京/ 大学/ 北京大学/ 。
本程序使用的是(默认)精准模式,当然jieba还有很多种模式,大家可以自行查阅
TF-IDF逆文本频率指数
概念:是一种统计方法,用以评估一个词对于一个语料库中一份文件的重要程度。词的重要性随着在文件中出现 的次数正比增加,同时随着它在语料库其他文件中出现的频率反比下降。
就是说一个词在某一文档中出现次数比较多,其他文档没有出现,说明该词对该文档分类很重要。
然而如果其他文档也出现比较多,说明该词区分性不大,就用IDF来降低该词的权重。
数学算法:
TF-IDF与一个词在文档中的出现次数成正比,与该词在整个语言中的出现次数成反比
TF-IDF = TF (词频) * IDF(逆文档频率)
词频:TF = 词在文档中出现的次数 / 文档中总词数
逆文档频率:IDF = log(语料库中文档总数 / 包含该词的文档数 +1 )
避开停用词:
贝叶斯分类
朴素贝叶斯分类算法核心:
表达形式:
测试集
我手动打乱了里面的分类,这样看他能不能预测出来
代码实现:
#!D:/workplace/python # -*- coding: utf-8 -*- # @File : homework3.py # @Author: WangYe # @Date : 2018/4/22 # @Software: PyCharm # 微博文字的性别识别 import jieba import os import pickle # 持久化 from numpy import * from sklearn import feature_extraction from sklearn.feature_extraction.text import TfidfTransformer # TF-IDF向量转换类 from sklearn.feature_extraction.text import TfidfVectorizer # TF_IDF向量生成类 from sklearn.datasets.base import Bunch from sklearn.naive_bayes import MultinomialNB # 多项式贝叶斯算法 def readFile(path): with open(path, 'r', errors='ignore') as file: # 文档中编码有些问题,所有用errors过滤错误 content = file.read() return content def saveFile(path, result): with open(path, 'w', errors='ignore') as file: file.write(result) def segText(inputPath, resultPath): fatherLists = os.listdir(inputPath) # 主目录 for eachDir in fatherLists: # 遍历主目录中各个文件夹 eachPath = inputPath + eachDir + "/" # 保存主目录中每个文件夹目录,便于遍历二级文件 each_resultPath = resultPath + eachDir + "/" # 分词结果文件存入的目录 if not os.path.exists(each_resultPath): os.makedirs(each_resultPath) childLists = os.listdir(eachPath) # 获取每个文件夹中的各个文件 for eachFile in childLists: # 遍历每个文件夹中的子文件 eachPathFile = eachPath + eachFile # 获得每个文件路径 # print(eachFile) content = readFile(eachPathFile) # 调用上面函数读取内容 # content = str(content) result = (str(content)).replace("\r\n", "").strip() # 删除多余空行与空格 # result = content.replace("\r\n","").strip() cutResult = jieba.cut(result) # 默认方式分词,分词结果用空格隔开 saveFile(each_resultPath + eachFile, " ".join(cutResult)) # 调用上面函数保存文件 def bunchSave(inputFile, outputFile): catelist = os.listdir(inputFile) bunch = Bunch(target_name=[], label=[], filenames=[], contents=[]) bunch.target_name.extend(catelist) # 将类别保存到Bunch对象中 for eachDir in catelist: eachPath = inputFile + eachDir + "/" fileList = os.listdir(eachPath) for eachFile in fileList: # 二级目录中的每个子文件 fullName = eachPath + eachFile # 二级目录子文件全路径 bunch.label.append(eachDir) # 当前分类标签 bunch.filenames.append(fullName) # 保存当前文件的路径 bunch.contents.append(readFile(fullName).strip()) # 保存文件词向量 with open(outputFile, 'wb') as file_obj: # 持久化必须用二进制访问模式打开 pickle.dump(bunch, file_obj) #pickle.dump(obj, file, [,protocol])函数的功能:将obj对象序列化存入已经打开的file中。 #obj:想要序列化的obj对象。 #file:文件名称。 #protocol:序列化使用的协议。如果该项省略,则默认为0。如果为负值或HIGHEST_PROTOCOL,则使用最高的协议版本 def readBunch(path): with open(path, 'rb') as file: bunch = pickle.load(file) #pickle.load(file) #函数的功能:将file中的对象序列化读出。 return bunch def writeBunch(path, bunchFile): with open(path, 'wb') as file: pickle.dump(bunchFile, file) def getStopWord(inputFile): stopWordList = readFile(inputFile).splitlines() return stopWordList def getTFIDFMat(inputPath, stopWordList, outputPath): # 求得TF-IDF向量 bunch = readBunch(inputPath) tfidfspace = Bunch(target_name=bunch.target_name,label=bunch.label, filenames=bunch.filenames, tdm=[], vocabulary={}) # 初始化向量空间 vectorizer = TfidfVectorizer(stop_words=stopWordList, sublinear_tf=True, max_df=0.5) transformer = TfidfTransformer() # 该类会统计每个词语的TF-IDF权值 # 文本转化为词频矩阵,单独保存字典文件 tfidfspace.tdm = vectorizer.fit_transform(bunch.contents) tfidfspace.vocabulary = vectorizer.vocabulary_ #获取词汇 writeBunch(outputPath, tfidfspace) def getTestSpace(testSetPath, trainSpacePath, stopWordList, testSpacePath): bunch = readBunch(testSetPath) # 构建测试集TF-IDF向量空间 testSpace = Bunch(target_name=bunch.target_name, label=bunch.label, filenames=bunch.filenames, tdm=[], vocabulary={}) # 导入训练集的词袋 trainbunch = readBunch(trainSpacePath) # 使用TfidfVectorizer初始化向量空间模型 使用训练集词袋向量 vectorizer = TfidfVectorizer(stop_words=stopWordList, sublinear_tf=True, max_df=0.5, vocabulary=trainbunch.vocabulary) transformer = TfidfTransformer() testSpace.tdm = vectorizer.fit_transform(bunch.contents) testSpace.vocabulary = trainbunch.vocabulary # 持久化 writeBunch(testSpacePath, testSpace) def bayesAlgorithm(trainPath, testPath): trainSet = readBunch(trainPath) testSet = readBunch(testPath) clf = MultinomialNB(alpha=0.001).fit(trainSet.tdm, trainSet.label) #alpha:0.001 alpha 越小,迭代次数越多,精度越高 #print(shape(trainSet.tdm)) #输出单词矩阵的类型 #print(shape(testSet.tdm)) predicted = clf.predict(testSet.tdm) total = len(predicted) rate = 0 for flabel, fileName, expct_cate in zip(testSet.label, testSet.filenames, predicted): if flabel != expct_cate: rate += 1 print(fileName, ":实际类别:", flabel, "-->预测类别:", expct_cate) print("erroe rate:", float(rate) * 100 / float(total), "%") # 分词,第一个是分词输入,第二个参数是结果保存的路径 segText("C:/Users/wy/Desktop/data/", "C:/Users/wy/Desktop/segResult/") bunchSave("C:/Users/wy/Desktop/segResult/", "C:/Users/wy/Desktop/train_set.dat") # 输入分词,输出分词向量 stopWordList = getStopWord("C:/Users/wy/Desktop/stop/stopword.txt") # 获取停用词 getTFIDFMat("C:/Users/wy/Desktop/train_set.dat", stopWordList, "C:/Users/wy/Desktop/tfidfspace.dat") # 输入词向量,输出特征空间 # 训练集 segText("C:/Users/wy/Desktop/test1/", "C:/Users/wy/Desktop/test_segResult/") # 分词 bunchSave("C:/Users/wy/Desktop/test_segResult/", "C:/Users/wy/Desktop/test_set.dat") getTestSpace("C:/Users/wy/Desktop/test_set.dat", "C:/Users/wy/Desktop/tfidfspace.dat", stopWordList, "C:/Users/wy/Desktop/testspace.dat") bayesAlgorithm("C:/Users/wy/Desktop/tfidfspace.dat", "C:/Users/wy/Desktop/testspace.dat")
结果截图:
从结果看出,手动添加的错误都预测出来了,谢谢大家~
参考文献:https://www.jianshu.com/p/915b0ab166e5
数据集+代码百度云:链接:链接:https://pan.baidu.com/s/1jyTis9z9D8FNU7khO7k0VA 密码:rgy5
我也是菜鸟一个,如果数据集或者代码有什么问题欢迎留言~