中文文本分类-新闻分类[数据挖掘]
以10种新闻类型为基础开展文本分类工作,并基于准确率、召回率以及F1值等指标对分类效果展开评估。
python版本:python 3.6
分类方法:朴素贝叶斯
需导入的相关库
import os
import time
import numpy as np
import pandas as pd
import jieba
from jieba import analyse
from sklearn.utils import shuffle
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import CountVectorizer,TfidfVectorizer #词集转换成向量
from sklearn.naive_bayes import MultinomialNB #朴素贝叶斯多分类
from sklearn.metrics import classification_report
import gensim #自然语言处理库
from gensim import corpora,models,similarities
上述某些库源 在Windows环境下似乎与Python 3.7版本之间存在版本不兼容的问题,在Linux系统上能够顺利运行并无此类困扰。基于此原因 我们决定转而采用Python 3.6作为替代方案
对数据源选取数据规模
大家可以从现有网络资源中选择所需的数据集,并从中筛选出所需数量的数据样本作为研究依据。我的研究数据集是通过自建爬虫完成获取的,在获取过程中进行了必要的预处理工作以保证数据质量。经过清洗处理后得到的数据集已经去除了空行、重复项以及杂乱无章的信息等杂质
第一步:获取原始数据
#读取数据源,注释掉的是拼接数据的部分,有需要的可以参考
def con_data():
# df1 = pd.read_csv('chinanews00.csv',names=['category','theme','URL','content'])
# df2 = pd.read_csv('chinanews11.csv',names=['category','theme','URL','content'])
# data = pd.concat([df1,df2],axis=0,ignore_index=True) #拼接表格
data = pd.read_csv('chinanews.csv',names=['category','theme','URL','content'])
df = data.groupby('category').count()#展示数据规模
print(df)
# print(data.shape)
return data
在实验阶段时处理了大量数据;然而,在当前情境下出于便于重复使用的目的,我们将各类数据规模缩减至1,000条;这样的操作相对快捷
在实验阶段时处理了大量数据;然而,在当前情境下出于便于重复使用的目的,我们将各类数据规模缩减至1, 但又不完全等于 万的数据量;这样的操作相对快捷
#分组选行
def group(data,amount,file_path):
df = data.groupby('category').head(amount)
df.to_csv(file_path,mode='a',header=None, index=False, encoding="utf-8-sig")
于是就有了目标数据 eg: test.csv
文本分类
1、读入待分类数据
def read_file():
data = pd.read_csv('test.csv',names=['category','theme','URL','content'])
df = data.groupby('category').count()#展示数据规模
print(df)
return data
数据规模:

样本长这样:

2、对数据进行切割
这一过程并非必须执行,原因在于不同类型的新闻文章长度存在显著差异:有些较长且详细丰富,有些则较短且信息精炼。因此,在理论上,则需剔除那些过于冗长或过于简短的内容(即所谓的过长或过短的文章),使所有新闻文本的长度趋于一致。如果不进行剔除处理,则可能会影响分类效果。
3、jieba分词并去停用词
def separate_words(data):
content = data.content.values.tolist() #将文本内容转换为list格式
#读入停用词表
stopwords = pd.read_csv("stopwords.txt",index_col=False,sep="\t",quoting=3,names=['stopword'], encoding='utf-8') #list
stopwords = stopwords.stopword.values.tolist()
print("正在分词,请耐心等候......")
contents_clean = []
all_words = []
for line in content:
current_segment = jieba.lcut(line) #jieba分词
current_segment = [x.strip() for x in current_segment if x.strip()!=''] #去掉分词后出现的大量空字符串
if len(current_segment) > 1 and current_segment != "\r\n":
line_clean = []
for word in current_segment:
if word in stopwords:
continue
line_clean.append(word)
all_words.append(str(word))
contents_clean.append(line_clean)
print('------------分词完成-----------')
return contents_clean, all_words
结果是这样的:

在其中,在我的研究过程中会遇到很多需要处理的数据词语组合中,“all_words”这一概念具有重要的研究价值,在这种情况下就可以通过它来进行一些特定的数据处理工作 在这种情况下 我会根据我的词频分析结果绘制一张图表 这张图表展示了剔除了一些不符合实际的高频词汇后生成的内容

4、标签转换
中文标签改为数字标签,便于分类
转换之前的标签:

#标签转换
label_mappping = {'汽车':1,'财经':2, '法治':3, '社会':4, '体育':5, '国际':6, '文化':7, '军事':8, '娱乐':9, '台湾':0}
df_train["label"] = df_train["label"].map(label_mappping)
print(df_train.head())
print("--------------------------------------3------------------------------------------")
转换之后的结果:

5、切分数据集
按1:1切分
#切分数据集
x_train,x_test,y_train,y_test = train_test_split(df_train["contents_clean"].values,df_train["label"].values,test_size=0.5)
启动训练流程 因为当前的数据内容被逗号分隔开 所以需要移除非必要使用空格连接的词之间
def format_transform(x): #x是数据集(训练集或者测试集)
words =[]
for line_index in range(len(x)):
try:
words.append(" ".join(x[line_index]))
except:
print("数据格式有问题")
return words
#训练
words_train = format_transform(x_train)
vectorizer = TfidfVectorizer(analyzer='word', max_features=4000,ngram_range=(1, 3),lowercase = False)
vectorizer.fit(words_train)#转为向量格式
classifier = MultinomialNB()
classifier.fit(vectorizer.transform(words_train), y_train)
7、测试,并查看相关结果
words_test = format_transform(x_test)
score = classifier.score(vectorizer.transform(words_test), y_test)
print("----------------------------------分类结果报告-----------------------------------------")
print("分类准确率:" + str(score))
print("训练时间:" + str(round((end_1-start_1), 2)) + '秒')
print("测试时间:" + str(round((end_2-start_2), 2)) + '秒')
y_predict=classifier.predict(vectorizer.transform(words_test))
print(classification_report(y_test,y_predict))
出来的结果是这样的:

emmmm,这个分类结果不是很理想。。。可以通过调参提高分类结果准确率。
