21丨朴素贝叶斯分类(下):如何对文档进行分类?
21丨朴素贝叶斯分类(下):如何对文档进行分类?
讲述:陈旸
时长14:22大小13.17M
sklearn 机器学习包
什么是 TF-IDF 值呢?
TF-IDF 如何计算
TfidfVectorizer 类的创建:
如何对文档进行分类
数据挖掘神器 sklearn
练习题
赞 9
提建议
精选留言(60)
- szm置顶2019-01-30需要完整代码,不然看不明白!
编辑回复: 完整代码已上传到 https://github.com/cystanford/text_classification 你也可以参考下专栏评论中其他人写的代码
共 3 条评论37 - 北方置顶2019-02-14#!/usr/bin/env python # -*- coding:utf8 -*- # __author__ = '北方姆Q' # __datetime__ = 2019/2/14 14:04 import os import jieba from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.naive_bayes import MultinomialNB from sklearn import metrics LABEL_MAP = {'体育': 0, '女性': 1, '文学': 2, '校园': 3} # 加载停用词 with open('./text classification/stop/stopword.txt', 'rb') as f: STOP_WORDS = [line.strip() for line in f.readlines()] def load_data(base_path): """ :param base_path: 基础路径 :return: 分词列表,标签列表 """ documents = [] labels = [] for root, dirs, files in os.walk(base_path): # 循环所有文件并进行分词打标 for file in files: label = root.split('\\')[-1] # 因为windows上路径符号自动转成\了,所以要转义下 labels.append(label) filename = os.path.join(root, file) with open(filename, 'rb') as f: # 因为字符集问题因此直接用二进制方式读取 content = f.read() word_list = list(jieba.cut(content)) words = [wl for wl in word_list] documents.append(' '.join(words)) return documents, labels def train_fun(td, tl, testd, testl): """ 构造模型并计算测试集准确率,字数限制变量名简写 :param td: 训练集数据 :param tl: 训练集标签 :param testd: 测试集数据 :param testl: 测试集标签 :return: 测试集准确率 """ # 计算矩阵 tt = TfidfVectorizer(stop_words=STOP_WORDS, max_df=0.5) tf = tt.fit_transform(td) # 训练模型 clf = MultinomialNB(alpha=0.001).fit(tf, tl) # 模型预测 test_tf = TfidfVectorizer(stop_words=STOP_WORDS, max_df=0.5, vocabulary=tt.vocabulary_) test_features = test_tf.fit_transform(testd) predicted_labels = clf.predict(test_features) # 获取结果 x = metrics.accuracy_score(testl, predicted_labels) return x # text classification与代码同目录下 train_documents, train_labels = load_data('./text classification/train') test_documents, test_labels = load_data('./text classification/test') x = train_fun(train_documents, train_labels, test_documents, test_labels) print(x)展开
编辑回复: 正确,大家可以看下这份代码 通过load_data加载数据,得到documents, labels 通过train_fun进行训练和预测,得到测试集的准确率。
共 2 条评论31 - Python置顶2019-01-30老师,能不能在答疑的时候给这道题的完整代码看看
编辑回复: 已上传到 https://github.com/cystanford/text_classification 也有同学自己写出来了,你可以都运行一下。
17 - 姜戈2019-01-30看过很多朴素贝叶斯原理和分类的讲解文章,很少能像前辈这样既有理论,又有实战的讲解,让大家既了解了理论知识,又有相应实际的操作经验可学,真的好棒,这个专栏,必须多多点赞,为老师加油!!!
作者回复: 多谢姜戈,一起加油!
16 - 听妈妈的话2019-03-21# 由于评论不支持markdown,代码放在https://pastebin.com/kqjXgy0c train_contents=[] train_labels=[] test_contents=[] test_labels=[] # 导入文件 import os import io start=os.listdir(r'text classification/train') for item in start: test_path='text classification/test/'+item+'/' train_path='text classification/train/'+item+'/' for file in os.listdir(test_path): with open(test_path+file,encoding="GBK") as f: test_contents.append(f.readline()) #print(test_contents) test_labels.append(item) for file in os.listdir(train_path): with open(train_path+file,encoding='gb18030', errors='ignore') as f: train_contents.append(f.readline()) train_labels.append(item) print(len(train_contents),len(test_contents)) # 导入stop word import jieba from sklearn import metrics from sklearn.naive_bayes import MultinomialNB stop_words = [line.strip() for line in io.open('text classification/stop/stopword.txt').readlines()] # 分词方式使用jieba,计算单词的权重 tf = TfidfVectorizer(tokenizer=jieba.cut,stop_words=stop_words, max_df=0.5) train_features = tf.fit_transform(train_contents) print(train_features.shape) 模块 4:生成朴素贝叶斯分类器 # 多项式贝叶斯分类器 clf = MultinomialNB(alpha=0.001).fit(train_features, train_labels) 模块 5:使用生成的分类器做预测 test_tf = TfidfVectorizer(tokenizer=jieba.cut,stop_words=stop_words, max_df=0.5, vocabulary=tf.vocabulary_) test_features=test_tf.fit_transform(test_contents) print(test_features.shape) predicted_labels=clf.predict(test_features) print(metrics.accuracy_score(test_labels, predicted_labels)) # 最终结果0.925展开5
- 池边的树2019-02-12https://github.com/yourSprite/AnalysisExcercise/tree/master/%E6%9C%B4%E7%B4%A0%E8%B4%9D%E5%8F%B6%E6%96%AF%E6%96%87%E6%9C%AC%E5%88%86%E7%B1%BB
作者回复: Good Job
5 - 上官2019-01-31print('不重复的词:', tfidf_vec.get_feature_names()) 运行结果: 不重复的词: ['and', 'bayes', 'document', 'is', 'one', 'second', 'the', 'third', 'this'] 这明明就是打印所有词啊,有重复的啊共 2 条评论4
- 几何2019-09-08老师,弱弱的说一句,代码感觉能看明白,但是不明白的是模型是如何使用的, 比如上一节和本节,都是只知道了准确率,但是对于有新的要处理的数据,如何做,怎么做好总是感觉差一点点东西。
作者回复: 我们做的大部分工作都是数据预处理,使用模型到是不复杂,这些分类模型使用的方式都差不多。 你可以多做练习,先针对一个数据集,采用不同的分类算法看下准确率。这样就会理解,当数据确定的情况下,如何使用不同的分类算法。 然后再针对不同的数据集,进行数据预处理:数据加载,数据探索,数据规范化等。数据预处理的技巧比较多,需要遇到不同的数据集,多做练习
4 - 滨滨2019-03-02适合用高斯朴素贝叶斯。因为身高、体重、鞋码是连续变量。 停用词的作用是去除无关词,减少重复计算。3
- Jack2019-02-14#!/usr/bin/env python # coding: utf-8 import os import jieba import pandas as pd from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.naive_bayes import MultinomialNB # 1. 加载数据 # 加载停用词表 l_stopWords = set() with open('./text_classification/text_classification/stop/stopword.txt', 'r') as l_f: for l_line in l_f: l_stopWords.add(l_line.strip()) l_labelMap = {'体育': 0, '女性': 1, '文学': 2, '校园': 3} # 加载训练数据和测试数据 def LoadData(filepath): l_documents = [] l_labels = [] for root, dirs, files in os.walk(filepath): for l_file in files: l_label = root.split('/')[-1] l_filename = os.path.join(root, l_file) with open(l_filename, 'r') as l_f: l_content = l_f.read() l_wordlist = list(jieba.cut(l_content)) l_words = [item for item in l_wordlist if item not in l_stopWords] l_documents.append(' '.join(l_words)) l_labels.append(l_labelMap[l_label]) return l_documents, l_labels l_trainDocuments, l_trainLabels = LoadData('./text_classification/text_classification/train') l_testDocuments, l_testLabels = LoadData('./text_classification/text_classification/test') # # 2. 计算权重矩阵 l_tfidfVec = TfidfVectorizer(max_df=0.5) l_tfidfMatrix = l_tfidfVec.fit_transform(l_trainDocuments) # for item in l_tfidfVec.get_feature_names(): # print item # print l_tfidfVec.get_feature_names() # print l_tfidfVec.vocabulary_ print l_tfidfMatrix.toarray().shape # # 3. 朴素贝叶斯模型 # ## 3.1 模型训练 l_clf = MultinomialNB(alpha=0.001) l_clf.fit(l_tfidfMatrix, l_trainLabels) # ## 3.2 模型预测 l_testTfidf = TfidfVectorizer(max_df=0.5, vocabulary=l_tfidfVec.vocabulary_) l_testFeature = l_testTfidf.fit_transform(l_testDocuments) l_hats = l_clf.predict(l_testFeature) # ## 3.3 模型评估 from sklearn.metrics import accuracy_score print accuracy_score(l_hats, l_testLabels)展开
作者回复: Good Job
3 - Jasmine2020-11-16老师,我想请教一下,计算单词权重时,为什么train_features用的fit_transform方法,而test_feature用的是transform
作者回复: fit_transform()是先调用fit()方法拟合模型,然后再调用transform()方法进行特征转换。如果在测试集上继续使用fit_transform(),将会再次调用fit重新拟合模型,这样可能会导致转换后的训练集和测试集出现差异。
共 2 条评论2 - 滢2019-04-17最后面的代码太乱,很多都不知道从哪里来的,无法顺着看下去~~~
作者回复: take it easy
共 2 条评论2 - 王彬成2019-04-05# -*- coding:utf8 -*- # 系统:mac # 1. 加载数据 # 加载停用词表 l_stopWords = [line.strip() for line in open('./text_classification-master/text classification/stop/stopword.txt', 'r', encoding='utf-8').readlines()] l_labelMap = {'体育': 0, '女性': 1, '文学': 2, '校园': 3} # 加载训练数据和测试数据 def LoadData(filepath): l_documents = [] l_labels = [] for root, dirs, files in os.walk(filepath): for l_file in files: if l_file=='.DS_Store': continue l_label = root.split('/')[-1] l_filename = os.path.join(root, l_file) with open(l_filename, 'r',encoding='gbk') as l_f: try: l_content = l_f.read() except Exception as err: print(err) print(l_filename) continue generator = jieba.cut(l_content) words = ' '.join(generator) l_wordlist=words.split(' ') l_words = [item for item in l_wordlist if item not in l_stopWords] l_documents.append(' '.join(l_words)) l_labels.append(l_labelMap[l_label]) return l_documents, l_labels l_trainDocuments, l_trainLabels = LoadData('./text_classification-master/text classification/train') l_testDocuments, l_testLabels = LoadData('./text_classification-master/text classification/test') # # 2. 计算权重矩阵 l_tfidfVec = TfidfVectorizer(max_df=0.5) l_tfidfMatrix = l_tfidfVec.fit_transform(l_trainDocuments) print (l_tfidfMatrix.toarray().shape) # # 3. 朴素贝叶斯模型 # ## 3.1 模型训练 l_clf = MultinomialNB(alpha=0.001) l_clf.fit(l_tfidfMatrix, l_trainLabels) # ## 3.2 模型预测 l_testTfidf = TfidfVectorizer(max_df=0.5, vocabulary=l_tfidfVec.vocabulary_) l_testFeature = l_testTfidf.fit_transform(l_testDocuments) l_hats = l_clf.predict(l_testFeature) # ## 3.3 模型评估 from sklearn.metrics import accuracy_score print (accuracy_score(l_hats, l_testLabels))展开
作者回复: Good Job
2 - wzhan3662019-02-06建议 大家先做英文版本,因为中文的unicode encode和decode不是很好弄,不利于中间步骤的可视化。如果对代码有疑惑,可以试试这个pipeline, sklearn 的。 不过,这个没有用NTLK。
作者回复: 嗯 英文不会有编码问题
2 - 王小王2019-02-02能不能讲解下本堂课的练习题?2
- 黄争辉2020-09-10这里百思不得解, 训练集中,(4个文件的词混在一起)每个词的 TF-IDF值和分类都混在一起了,是如何实现分类器的呢?
作者回复: tfidf_vec.get_feature_names() 返回的是所有单词的单词列表,每个单词在该列表中的索引和tfidf_vec.vocabulary_返回的字典中每个单词的value一致。 希望可以帮到你
1 - Jonathan2020-03-26老师,想请教一下文中计算TF-IDF的例子,从公式上看tfIdf_Matrix=tf*idf。我能准确计算出idf值,然后再依据tf公式计算出来的结果,怎么算也算不出例子中所给出的矩阵结果。所以,我的问题是ft是怎么算出来的。谢谢。共 1 条评论1
- 叮当猫2019-03-16#-coding=utf-8 import os import pandas as pd import jieba from sklearn import metrics from sklearn.naive_bayes import MultinomialNB from sklearn.feature_extraction.text import TfidfVectorizer def load_data(path): l_labels = [] l_documents = [] #os.walk返回三元组(root, dirs, files) #root指的是当前正在遍历的这个文件夹本身的地址 #dirs是一个list,内容是该文件夹中所有的目录的名字 #files是一个list,内容是该文件夹中所有的文件,不包含子目录 for root, dirs, files in os.walk(path): print root, dirs, files for l_file in files: l_label = root.split('/')[-1] l_filepath = os.path.join(root, l_file) with open(l_filepath, 'r') as l_f: l_content = l_f.read() l_words = ' '.join(list(jieba.cut(l_content)) ) l_labels.append(l_label) l_documents.append(l_words) return l_documents, l_labels #第一步:对文档进行分词 train_documents, train_labels = load_data('./text classification/train/') test_documents, test_labels = load_data('./text classification/test/') #第二步:加载停用词 STOP_WORDS = [line.strip() for line in open('./text classification/stop/stopword.txt' ,'r').readlines()] #第三步:计算单词的权重 tf = TfidfVectorizer(stop_words=STOP_WORDS, max_df=0.5) train_features = tf.fit_transform(train_documents) #第四步:生成朴素贝叶斯分类器 clf = MultinomialNB(alpha=0.001).fit(train_features, train_labels) #第五步:使用生成的分类器做预测 test_tf = TfidfVectorizer(stop_words=STOP_WORDS, max_df=0.5, vocabulary=tf.vocabulary_) test_features = test_tf.fit_transform(test_documents) predict_labels = clf.predict(test_features) #第六步:计算准确率 print metrics.accuracy_score(test_labels, predict_labels)展开1
- 堂吉诃德2019-01-31test_tf = TfidfVectorizer(stop_words=stop_words, max_df=0.5, vocabulary=train_vocabulary) test_features=test_tf.fit_transform(test_contents) 老师你好! 我之前按照文章的方法把训练集和测试集分开计算特征矩阵,之后用多项式NB模型训练后预测时报错:维度不匹配(dimension mismatch). 目前我是先把训练集和测试集都分词完毕后把两边的数据都放在一起(共3306+200=3506条)使用一个TfidfVectorizer拟合后得到features再用切片分成两部分,之后能正常使用贝叶斯模型预测。当然这样测试集也损失了自身的特征。 请问要使用什么方法能让模型正常预测呢?如果现在我想使用模型预测一个文本必须要把这个文本分词后转为和trian_features相同的长度。 我开始复制的代码里TfidfVectorizer有一个vocabulary=train_vocabulary参数我没懂,请问下是使用这个参数保持长度相同吗?我试了传tf.vacabulary_进去没有作用。 请老师指教。展开1
- Viola2019-01-31有大量代码实现的 ,能否将github地址贴一下
作者回复: https://github.com/cystanford/text_classification
1