中文文本分类实战--数据处理部分

之前用智源上面一个虚假新闻检测的比赛练了练手,数据集可以在比赛官网上下载task1。可以看成中文文本分类任务,之前只是跑了跑模型,没有关注词向量的训练以及多模型融合。目前我在细化,会不断和大家分享,相互学习,欢迎交流,结束后我会把代码更新github

任务介绍

虚假新闻文本检测:文本是新闻信息的主要载体,对新闻文本的研究有助于虚假新闻的有效识别。具体任务为:给定一个新闻事件的文本,判定该事件属于真实新闻还是虚假新闻。

 虚假新闻文本检测任务中,训练集共包含38,471条新闻,其中包含真实新闻19,186条,虚假新闻19,285条。初赛测试集共4,000条,复赛测试集3,902条,真假新闻比例与训练集基本一致。

数据字段:

        id:新闻id,每条文本中id均不相同,唯一表征一条新闻;

        text: 新闻的文本内容;

        label: 取值为{0,1},0表示真实新闻,1表示虚假新闻。

每支队伍在参赛期间可随时提交验证集的预测结果,将验证结果在一个文本文件中进行提交,命名为submit.csv,格式如下:

                                                 id,label

                                                 123,1

                                                 456,0

                                                 ......

其中,对于虚假文本检测任务, id是新闻id,label是该新闻文本对应的预测结果,int类型,取值范围为{0,1},虚假新闻为1,真实新闻为0;

数据集

官方给的数据集有Excel表格给出,该数据集共有38471条数据,其中19186条假新闻,19185条真新闻。每条数据由[id,text,label]三个元素组成,其中qid是每一条数据的唯一id标识,text是中文新闻文本,label是0/1,0表示真实新闻,1表示虚假新闻。测试数据集需要提交到后台判定。对数据集进行分析可以得到:

最大句子长度最小句子长度平均数据长度分词后词的个数
929050.88367861506069573915

相关库函数的载入

import time
import jieba
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer,CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn import metrics
import pandas as pd
import numpy as np

from gensim.models import Word2Vec

from keras.layers import *
from keras.models import *
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.engine.topology import Layer

from tqdm import tqdm

maxlen = 100

(一)数据处理

1.数据清洗

之前做的一个英文文本分类在数据处理上,主要做了标点符号的整理,颜文字等特殊符号的处理,大小写的转换,数字的清理,以及利用一个手写的小字典对数据的拼写错误进行检测。数据清洗后,利用keras的tokenizer接口将句子进行符号化,并padding到等长,为将来向量化做准备。

在中文数据处理上与英文有所不同,主要做了去除指定无用的符号,只保留文本中的文字,利用一个手写的list记录所有停用词,去除停用词并对文本进行分词。数据清洗后,需要将句子进行符号化,由于中文没有分词器tokenizer,我先构建了一个vocab保存所有分好的词,共有73915个单词,根据词典将句子序列化,再将句子padding到等长,为将来向量化做准备,下面上代码

数据清洗的代码:

"去除指定无用的符号,这里我们主要拿空格举例"
puncts = [' ']
def clean_text(x):
    x=x.strip()
    for punct in puncts:
        x=x.replace(punct,'')
    return x

"让文本只保留文字"
def is_chinese(xchar):
    if xchar>=u'\u4e00' and xchar<=u'\u9fa5':
        return True
    else:
        return False
def keep_chinese_text(x):
    out_str=''
    for i in x:
        if is_chinese(i):
            out_str=out_str+i
    return out_str

def seg_sentence(sentence,stopwords):
    "对句子进行分词和去除停用词"
    sentence_seged=jieba.cut(sentence)
    outstr=''
    for word in sentence_seged:
        if word not in stopwords:
                outstr+=word
                outstr+=" "
    return outstr

词典的构建以及文本序列化的代码

def build_vocab(sentences,verbose=True):
    "追踪训练词汇表,遍历所有文本对单词进行计数"
    vocab={}
    for sentence in tqdm(sentences,disable=(not verbose)):
        for word in sentence.split():
            try:
                vocab[word]+=1
            except KeyError:
                vocab[word]=1
    #vocab=sorted(vocab.items(),key=lambda d:d[1],reverse=True)   # 分词后共出现70634个单词
    # vocab=vocab[:vocab_size]
    print(len(vocab))
    return vocab

def texts_to_sequences(sentences,vocab,verbose=True):
    seq_sentences=[]
    for sentence in tqdm(sentences,disable=(not verbose)):
        seq_sentence=[]
        for word in sentence.split():
            seq_sentence.append(vocab.get(word))
        seq_sentences.append(seq_sentence)
    return seq_sentences

数据处理的全部代码

def load_and_prec():
    #文件读取
    train_df=pd.read_csv('data/news_classification_dataset.csv')

    #创建停用词列表
    stopwords = ['的', '呀', '这', '那', '就', '的话', '如果']

    train_df["text"]=train_df["text"].apply(lambda x:clean_text(x))
    train_df["text"]=train_df["text"].apply(lambda x:keep_chinese_text(x))
    train_df["text"]=train_df["text"].apply(lambda x:seg_sentence(x,stopwords))

    vocab=build_vocab(train_df["text"],True)

    # split to train and val
    train_df,val_df=train_test_split(train_df,test_size=0.1,random_state=2019)

    # print("Train shape: ",train_df.shape)   # (34623, 3)
    # print("Val shape: ",val_df.shape)   # (3848, 3)

    ## Get the input values
    train_X=train_df["text"].values
    val_X=val_df["text"].values

    ## Get the target values
    train_y=train_df["label"].values
    val_y=val_df["label"].values

    np.random.seed(2019)
    trn_idx=np.random.permutation(len(train_X))
    val_idx=np.random.permutation(len(val_X))

    train_X=train_X[trn_idx]
    val_X=val_X[val_idx]
    train_y=train_y[trn_idx]
    val_y=val_y[val_idx]

    # Tokenize the sentences
    train_X=texts_to_sequences(train_X, vocab)
    val_X=texts_to_sequences(val_X,vocab)
    # Pad the sentences
    train_X=pad_sequences(train_X,maxlen=maxlen)
    val_X=pad_sequences(val_X,maxlen=maxlen)

    return train_df,val_df,train_X,val_X,train_y,val_y,vocab

2. 词向量的训练

def word2vec_model(train_df, val_df, vocab):
    count=0
    nb_words=len(vocab)
    print(nb_words)
    start=time.clock()
    all_data=pd.concat([train_df["text"],val_df["text"]])
    file_name='data/word2vec.model'
    if not os.path.exists(file_name):
        model=Word2Vec([[word for word in sentence.split()] for sentence in all_data.values],
                       size=embed_size,window=5,iter=10,workers=11,seed=2019,min_count=2)
        model.save(file_name)
    else:
        model=Word2Vec.load(file_name)
    print("add word2vec finished...")
    end=time.clock()
    print('Running time: %s Seconds' %(end-start))

    nb_words=min(max_features,len(vocab))
    embedding_word2vec_matrix=np.zeros((nb_words,embed_size))
    for word,i in vocab.items():
        if i>max_features:continue
        embedding_vector=model[word] if word in model else None
        if embedding_vector is not None:
            count+=1
            embedding_word2vec_matrix[i]=embedding_vector
        else:
            unk_vec=np.random.random(embed_size)*0.5
            unk_vec=unk_vec-unk_vec.mean()
            embedding_word2vec_matrix[i]=unk_vec
    del model;
    gc.collect()
    return embedding_word2vec_matrix

3. 主函数中直接运行即可

if __name__ == '__main__':
    train_df, val_df, train_X, val_X, train_y, val_y, vocab=load_and_prec()
    embedding_word2vec_matrix=word2vec_model(train_df,val_df,vocab)
    print(embedding_word2vec_matrix.shape)  #(73915, 200)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值