• 【机器学习】文本多分类


    声明:这只是浅显的一个小试验,且借助了AI。使用的是jupyter notebook,所以代码是一块一块,从上往下执行的

    知识点:正则删除除数字和字母外的所有字符、高频词云、混淆矩阵

    参考:使用python和sklearn的中文文本多分类实战开发_文本多标签分类 用二分类器做 python 数据集中文_-派神-的博客-CSDN博客


    数据【免费】初步的文本多分类小实验资源-CSDN文库

    数据介绍:训练集train.csv中有120000条数据,测试集test.csv中有7600条数据。两个文件中记录的是新闻,均只有3列,第1列记录了新闻的种类(world,sports,sci/Tech,Business,记录与class.txt中),总共有4类[3,4,2,1],且每一类的占比均为25%;第2列记录了新闻标题,第3列记录了新闻的大致内容。

    数据总体情况

    1. import numpy as np
    2. import pandas as pd
    3. import matplotlib.pyplot as plt
    4. import re # 正则匹配
    5. plt.rcParams['font.sans-serif'] = ['STKaiTi']
    6. plt.rcParams['axes.unicode_minus']=False
    7. # 数据的情况
    8. dfTrain = pd.read_csv('train.csv',header = None)
    9. dfTest = pd.read_csv('test.csv',header = None)
    10. print(f'训练集数据量:{len(dfTrain)}')
    11. print(f'测试集数据量:{len(dfTest)}')
    12. print(f'数据:{dfTrain.head(4)}')

    数据预处理

    空值与重复值

    没有空值与重复值

    1. # 检查是否有空值
    2. print(f'数据情况{dfTrain.info()}')
    3. print(f'第1列空值:{dfTrain.iloc[0].isnull().sum()}')
    4. print(f'第2列空值:{dfTrain.iloc[1].isnull().sum()}')
    5. print(f'第3列空值:{dfTrain.iloc[2].isnull().sum()}')
    6. # 重复值分析与处理
    7. print(f'重复值:{dfTrain.duplicated(keep=False).sum()}')

    重命名列名

    由于数据中没有列名,所以,读取的时候header=None(见第一段pd.read_csv),为了操作的方便,添加列名['category','title','content']。

    1. # 列重命名
    2. dfTrain.columns = ['category','title','content']
    3. dfTest.columns = ['category','title','content']

    删除除数字和英文的所有字符

    为了展示出高频词的词云以及后续的处理,这里使用正则表达式删除数据中第2、3列中除数字和字母外的所有字符,且各词汇之间采用空格切分。

    1. # 在a-z A-Z 0-9范围外的字符替换为空格字符
    2. def remove_punctuation(text):
    3. cleaned_text = re.sub(r'[^a-zA-Z0-9]', ' ', text)
    4. return cleaned_text
    5. # 删除除数字和英文的所有字符
    6. dfTrain['title'] = dfTrain['title'].apply(remove_punctuation)
    7. dfTest['title'] = dfTest['title'].apply(remove_punctuation)
    8. dfTrain['content'] = dfTrain['content'].apply(remove_punctuation)
    9. dfTest['content'] = dfTest['content'].apply(remove_punctuation)

    补充

    我这个试验只采用了第2列title的内容,没有用第3列content 里的内容,预测精度会有所下降。

    这里呢其实还是可以有其他操作的。比如将第2列和第3列合并成新的一列,然后用新的一列作为输入。还可以删除英文里面的停用词,减少无意义的高频词。

    不同分类对数据进行可视化

    1. # 训练集种类
    2. print(f'种类:{dfTrain.iloc[:,0].unique()}')
    3. # 训练集各类别数据量
    4. d= {'类别':dfTrain['category'].value_counts().index,'数量':dfTrain['category'].value_counts()}
    5. Num = pd.DataFrame(data = d).reset_index(drop = True)
    6. # 柱状图
    7. plt.figure(1,figsize = (10,6),dpi = 400)
    8. plt.title('训练集类别数据量',fontsize = 15) # 标题
    9. labels = ['World','Sports','Business','Sci/Tech']
    10. colors = ['skyblue', 'green', 'orange','red']
    11. plt.bar(labels,Num['数量'], width=0.6,color=colors)
    12. # 添加数据标签
    13. for i in range(len(Num)):
    14. plt.text(labels[i], Num['数量'][i]+0.01, f'{Num["数量"][i]}', ha='center',rotation = 0,fontsize = 15)
    15. plt.xlabel('种类',fontsize = 15)
    16. plt.ylabel('数量',fontsize = 15)
    17. plt.show()
    18. # 测试集种类
    19. print(f'种类:{dfTest.iloc[:,0].unique()}')
    20. # 测试集各类别数据量
    21. d2= {'类别':dfTest['category'].value_counts().index,'数量':dfTest['category'].value_counts()}
    22. Num2 = pd.DataFrame(data = d2).reset_index(drop = True)
    23. # 柱状图
    24. plt.figure(2,figsize = (10,6),dpi = 400)
    25. plt.title('测试集类别数据量',fontsize = 15) # 标题
    26. labels = ['World','Sports','Business','Sci/Tech']
    27. colors = ['skyblue', 'green', 'orange','red']
    28. plt.bar(labels,Num2['数量'], width=0.6,color=colors)
    29. # plt.xlabel(Num['类别'])
    30. # 添加数据标签
    31. for i in range(len(Num2)):
    32. plt.text(labels[i], Num2['数量'][i]+0.05, f'{Num2["数量"][i]}', ha='center',rotation = 0,fontsize = 15)
    33. plt.xlabel('种类',fontsize = 15)
    34. plt.ylabel('数量',fontsize = 15)
    35. plt.show()

    高频词词云

     画出训练集中,4种分类的新闻标题的top10的高频词云,需要借助wordcloud库

    1. import pandas as pd
    2. import matplotlib.pyplot as plt
    3. from wordcloud import WordCloud
    4. from collections import defaultdict
    5. # 创建一个存储每个类别文本的字典
    6. category_text = defaultdict(str)
    7. # 将每个类别的文本合并到对应的字典项中
    8. for category, sentence in zip(dfTrain['category'], dfTrain['title']):
    9. category_text[category] += sentence + ' '
    10. # 生成词云图像并绘制
    11. for category, text in category_text.items():
    12. wordcloud = WordCloud(width=800, height=400,max_words=10, background_color="white").generate(text)
    13. plt.figure(figsize=(10, 5))
    14. plt.imshow(wordcloud, interpolation="bilinear")
    15. plt.title(f'Word Cloud for Category {category}',fontsize = 30)
    16. plt.axis("off")
    17. plt.show()

     

             根据我们事先的得知的数字与类别的对应关系:1-World,2-Sports,3-Business,4-Sci/Tech,观察每种类别的高频词云图,可以看出对于world,常出现诸如Iraq、US等国家名称,对于Sports类,常出现Win,Game等相关词汇,对于Business类,常出现deal,oil,price等相关词汇,对于Sci/Tech类,常出现MicroSoft,Intel等相关词汇。因此,每一类的高频词云是符合当前类的特征的。

    模型预测

    思路:为了能使模型能够对文本进行预测,首先需要使用TF-IDF向量化器进行文本特征提取(至于原理什么的,我不知道,AI生成的)。然后再次基础上借助预测模型进行多分类预测,在训练集中训练,测试集中测试

    使用朴素贝叶斯

    1. import pandas as pd
    2. from sklearn.model_selection import train_test_split
    3. from sklearn.feature_extraction.text import CountVectorizer
    4. from sklearn.naive_bayes import MultinomialNB
    5. from sklearn.metrics import accuracy_score, classification_report
    6. # 划分x,y
    7. X_train = dfTrain['title']
    8. X_test = dfTest['title']
    9. y_train = dfTrain['category']
    10. y_test = dfTest['category']
    11. # 文本特征提取,使用词袋模型
    12. vectorizer = CountVectorizer()
    13. X_train_vec = vectorizer.fit_transform(X_train)
    14. X_test_vec = vectorizer.transform(X_test)
    15. # 训练朴素贝叶斯分类器
    16. clf = MultinomialNB()
    17. clf.fit(X_train_vec, y_train)
    18. # 预测
    19. y_pred = clf.predict(X_test_vec)
    20. # 评估模型性能
    21. accuracy = accuracy_score(y_test, y_pred)
    22. print(f'Accuracy: {accuracy:.2f}')
    23. # 输出分类报告
    24. print(classification_report(y_test, y_pred))

    下图为朴素贝叶斯的预测结果,总体的预测准确率为0.87。但是对于不同类别的预测效果也不同,可以看出朴素贝叶斯对类别2的预测效果最好的,精确度、召回率、f1分数均能达到0.9以上 

    画出混淆矩阵 

    1. from sklearn.metrics import confusion_matrix
    2. import seaborn as sns
    3. # 计算混淆矩阵
    4. conf_matrix = confusion_matrix(y_test, y_pred)
    5. # 绘制混淆矩阵
    6. plt.figure(figsize=(8, 6),dpi = 400)
    7. sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues', xticklabels=clf.classes_, yticklabels=clf.classes_)
    8. plt.xlabel('预测')
    9. plt.ylabel('实际')
    10. plt.title('混淆矩阵')
    11. plt.show()

    下图为朴素贝叶斯预测的混淆矩阵。可以看出对于朴素贝叶斯模型来说,容易将第1类错误预测为第3类,第2类错误预测为第1类,第3类错误预测为第1、4类,第4类错误预测为第3类。 

  • 相关阅读:
    mysql5.6.50物理迁移后root登录不显示mysql库和业务库
    (二)Ansible-主机定义
    【基础知识】~ 数据位宽转换器
    从 1.5 开始搭建一个微服务框架——日志追踪 traceId
    XML详解--语法、DTD、schema
    Linux 入门
    循环神经网络-简洁实现
    机器学习的概念和类型
    [Java Framework] [Spring] Spring中RestTemplate中几种常见的请求方式
    Flutter 最有用的 5 个优秀的依赖包
  • 原文地址:https://blog.csdn.net/m0_67173953/article/details/132925279