中文文本分类-新闻分类[数据挖掘]

对新闻文本(10类)进行文本分类,通过准确率、召回率、 f1-score 等指标对分类结果进行分析。

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下好像与python3.7版本会出现版本不兼容的问题,我在linux下使用3.7正常,windows下出现“DLL load failed”,所以换用3.6

对数据源选取数据规模

大家可以选择网上现有的数据源,然后选出自己需要数量的数据。我的数据是我自行爬取的,所以在爬取的时候就做了相应的数据预处理。所以我选取的数据是已经去空行、去重去掉一些乱七八糟的信息之后的数据。
1、读取数据源

#读取数据源,注释掉的是拼接数据的部分,有需要的可以参考
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

2、按类别,分别选出前n条
实验之前做的是100w条数据,但是在这里为了重复方便,我将每类数据缩减为1000条,这样比较快~

#分组选行
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可以用来统计某些词出现的频率,依据这个来修改停用词表stopwords。下图是我按照自己的词频统计,去掉了一些不合理的高频词后出现的结果。
在这里插入图片描述
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)

6、开始训练
因为现在的数据内容是以‘,’分隔开的,所以需要去掉将词与词之间用‘ ’连接起来。

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,这个分类结果不是很理想。。。可以通过调参提高分类结果准确率。

猜你喜欢

转载自blog.csdn.net/Iv_zzy/article/details/107556489