fetch_20newsgroups数据集包含了20个主题的新闻文本数据
分类任务
解题步骤
-
数据导入和描述
- news.keys()查看有哪些数据字段
- 数据集大小,两种统计方法
- 每个分类的个数统计from collections import Counter
- 特征的分布情况,画图sns.histplot()
-
数据清洗和文本向量化处理
- 分割成每个单词string.split()
- 只保留文字:设置函数,对每个word. string.isalpha()
- 合并处理后的数据成列表
- 每个单词:词形还原处理from nltk.stem import WordNetLemmatizer
- 文本向量化CountVectorizer
-
分类模型
- kmeans
- 贝叶斯分类
1.1 数据导入和描述
- 导入数据
import pandas as pd
import numpy as np
import pymysql
from sqlalchemy import create_engine
from sklearn.datasets import fetch_20newsgroups
# 选择部分数据,
categories = ['alt.atheism', 'talk.religion.misc','comp.graphics', 'sci.space']
news=fetch_20newsgroups(subset='all',categories=categories)
- 查看数据
#查看数据
print(f"数据有哪些字段:{news.keys()}")
print(f"数据集大小:{len(news.data)}") #len:对list的大小判断
print(f"数据集大小:{np.array(news.data).shape}") #array.shape,对数组的大小判断
print(f"多少个类别特征:{len(news.target_names)}")
print(f"特征名称:\n{news.target_names}") #特征名称
result:
数据有哪些字段:dict_keys([‘data’, ‘filenames’, ‘target_names’, ‘target’, ‘DESCR’])
数据集大小:3834
数据集大小:(3834,)
多少个类别特征:4
特征名称:
[‘sci.space’, ‘soc.religion.christian’, ‘talk.politics.guns’, ‘talk.politics.mideast’]
- 查看特征分布情况
# 查看特征分布情况
import seaborn as sns
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = ['sans-serif'] # 显示中文问题
plt.rcParams['font.sans-serif'] = ['SimHei'] # 显示中文问题
#%matplotlib inline #不显示图形的时候加这行
targets=[news.target_names[target] for target in news.target] # 特征名称
fig,ax=plt.subplots(figsize=(8,3)) # 创建画图区域和图表
sns.histplot(targets, bins = 20) # 直方图
# 添加其它图表信息
plt.xlabel("分类")
plt.ylabel("分类计数")
plt.title("分类分布情况")
plt.tight_layout() #紧密排版,自动调整间距
plt.show()
result:
1.2 数据清洗和向量化处理
1. 分割成每个单词string.split()
2. 只保留文字:设置函数,对每个word. string.isalpha()
3. 合并处理后的数据成列表
4. 每个单词:词形还原处理from nltk.stem import WordNetLemmatizer
5. 文本向量化CountVectorizer
数据清洗和特征处理是做好模型的前提和关键。
1.2.1 数据清洗
解题思路:
- 对总数据news.data里的每个邮件post做单词的分割,分割成每一个word;
- 最后通过循环语句
for post in news.data
,对整个数据集做同样的处理。
post=news.data[0]
for post in news.data:
写出post的单词分割程序:
[word for word in post.split()] # 用列表表达式分割好每个单词
添加到一个列表
cleaned=[]
cleaned.append(' '.join(
[word for word in post.split()]
)
)
添加限制条件:只保留文字:设置函数,对每个word. string.isalpha()
# 只保留文字函数
def letter_only(string):
return string.isalpha()
cleaned=[]
cleaned.append(' '.join(
[word for word in post.split()
if letter_only(word)]
)
)
词形还原处理
from nltk.stem import WordNetLemmatizer
lemmatizer=WordNetLemmatizer()
lemmatizer.lemmatize(word)
这里会遇到下载nltk错误的问题,要手动下载数据包到电脑,可以参考这篇文章:
Resource wordnet not found. Please use the NLTK Downloader to obtain the resource
添加词形还原后的数据清洗程序
# 对所有的post进行处理后,加到列表后面
cleaned=[]
for post in news.data:
cleaned.append(' '.join(
[lemmatizer.lemmatize(word.lower())#word.lower(),小写化处理
for word in post.split()
if letter_only(word)])
)
查看结果
#查看列表长度
print(f"原始数据长度:{len(news.data)}")
print(f"清洗后的数据长度:{len(cleaned)}")
#print(f"清洗后的数据维度:{np.array(news.data).shape}")
result:
原始数据长度:3387
清洗后的数据长度:3387
1.2.2 文本向量化处理
文本向量化作用是使得文本数据可以变为可以进行分类处理的数据
采用CountVectorizer,还可以使用TfidfVectorizer
# 使用CountVectorizer进行文本向量化处理
from sklearn.feature_extraction.text import CountVectorizer
cv=CountVectorizer() #stop_words='english', max_features=500
news_cv=cv.fit_transform(cleaned) # 文本向量化
# 查看向量化数据
news_cv.toarray()
注意:
- CountVectorize(text_data)
- text_data是一个包含文本文档的列表或数组。
1.3 Kmeans分类
from sklearn.cluster import KMeans
from sklearn.model_selection import train_test_split #分割测试集和训练集
#拟合数据
km=KMeans(n_clusters=4)
km.fit(news_cv)
# 查看中心点
#查看中心点
km.cluster_centers_
1.4 贝叶斯分类
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score,f1_score
from sklearn.model_selection import train_test_split #分割数据集
分割数据集
# 分割测试集和训练集
x,y=news_cv.toarray(),news.target
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=42)
注意:news_cv要转换为news_cv.toarray(),变为数组,不然出错,
做题的时候,最好用下面的代码查看下数据,会发现一些问题,找到解决问题的思路,查看数据的数据类型是否是正确的
## 查看数据信息
# news.target.reshape(-1,1).shape
# news.target
# news_cv.toarray()
# news.target
# len(news.target)
# cleaned[0]
# news_cv.shape
# type(news_cv)
# model
clf=GaussianNB()
#fit
#clf.fit(news_cv.toarray(),news.target)
clf.fit(x_train,y_train)
# predict
y_pred=clf.predict(x_test)
#评测
print(f"f1_score:{f1_score(y_test,y_pred,average='macro'):.2%}")
print(f"accuracy_score:{accuracy_score(y_test,y_pred):.2%}")
result:
accuracy_score:94.92%
f1_score:94.87%