【NLP】天池新闻文本分类(四)——基于深度学习的文本分类1

【NLP】天池新闻文本分类(四)——基于深度学习的文本分类1

  • 前言
  • 深度学习之FastText介绍
  • 基于FastText的文本分类
  • 采用分层交叉验证集调参

前言

本文是NLP之新闻文本分类挑战赛(赛题链接)。
的第四篇:基于深度学习得文本分类1。上一篇是基于机器学习的文本分类,使用的是传统机器学习算法来实现新闻分类建模:介绍了几种文本的表示方法,如One-hot、Bag of words、N-gram、TF-IDF,并且通过sklearn分别实现了Count Vectors + RidgeClassifier、TF-IDF + RidgeClassifier、TF-IDF + LogisticRegression三种组合方法的建模和预测。但是上述方法存在几点思考:转换得到的向量维度很高,从而需要较长的训练时间;没有考虑文本单词之间的关系,只是进行了单词统计等。基于以上,下面介绍深度学习的文本分类,可以将其映射到一个低维度空间,比较典型的方法有:FastText、Word2Vec和Bert。本篇文章将介绍FastText,同时将在后续文章介绍Word2Vec和Bert。

深度学习之FastText介绍

FastText是一种典型的深度学习词向量的表示方法,它非常简单通过Embedding层将单词映射到稠密空间,然后将句子中所有的单词在Embedding空间中进行平均,进而完成分类操作。
FastText是一个三层的神经网络,输入层、隐含层和输出层,如下图所示:
【NLP】天池新闻文本分类(四)——基于深度学习的文本分类1_第1张图片
下面是使用keras实现的FastText网络结构:

#使用keras实现FastText网络结构
from keras.models import Sequential
from keras.layers import Embedding
from keras.layers import GlobalAveragePooling1D
from keras.layers import Dense

VOCAB_SIZE = 2000
EMBEDDING_DIM = 100
MAX_WORDS = 500
CALSS_NUM = 5

def build_fastText():
    model = Sequential()
    # 通过Emdedding层,将词汇映射成EMBEDDING_DIM维向量
    model.add(Embedding(VOCAB_SIZE, EMBEDDING_DIM, input_length=MAX_WORDS))
    # 通过GlobalAveragePooling1D,平均文档中所有词的embedding
    model.add(GlobalAveragePooling1D())
    # 通过输出层Softmax分类(这里用的是带激活函数为softmax的全连接Dense,真实的fastText是Softmax层,),得到类别概率分布
    model.add(Dense(CALSS_NUM,activation='softmax'))
    # 定义损失函数、优化器、分类度量指标
    model.compile(loss='categorical_crossentropy',optimizer='SGD',metrics=['accuracy'])
    return model

if __name__ == '__main__':
    model = build_fastText()
    print(model.summary())

FastText在文本分类任务上,是优于TF-IDF的:
1.FastText用单词的Embdedding叠加获得的文档向量,将相似的句子分为一类;
2.FastText学习到的Embedding空间维度比较低,可以快速进行训练。

基于FastText的文本分类

#分类模型
import pandas as pd
from sklearn.metrics import f1_score

#转换为FastText需要的格式
train_df = pd.read_csv('./data/训练集数据/train_set.csv',sep='\t',nrows=50000)
train_df['label_ft'] = '__label__' + train_df['label'].astype(str)
train_df[['text','label_ft']].iloc[:-5000].to_csv('./data/train_fasttext.csv',index=None,header=None,sep='\t')

import fasttext
model = fasttext.train_supervised('./data/train_fasttext.csv',lr=1.0,wordNgrams=2,verbose=2,minCount=1,epoch=25,loss='hs')
val_pred = [model.predict(x)[0][0].split('__')[-1] for x in train_df.iloc[-5000:]['text']]
print(f1_score(train_df['label'].values[-5000:].astype(str),val_pred,average='macro'))

在这里插入图片描述

采用分层交叉验证集调参

将训练集划分为训练集和验证集,通过在验证集上进行验证模型精度,找到模型是否过拟合还是欠拟合。如下是进行10折交叉验证,每折使用9/10的数据进行训练,剩余1/10作为验证集检验模型的效果。需要注意每折的划分必须保证标签的分布与整个数据集的分布一致。
【NLP】天池新闻文本分类(四)——基于深度学习的文本分类1_第2张图片

#分层交叉验证
import pandas as pd
from sklearn.metrics import f1_score
from sklearn.model_selection import StratifiedKFold
import fasttext
import warnings
warnings.filterwarnings('ignore')

#转换为FastText需要的格式
train_df = pd.read_csv('./data/训练集数据/train_set.csv',sep='\t',nrows=15000)
train_df['label_ft'] = '__label__' + train_df['label'].astype(str)
X = train_df['text']
y = train_df['label_ft']

sKFolder = StratifiedKFold(n_splits=10, random_state=0, shuffle=False)
f1_scores = []
for i, (train_index, validation_index) in enumerate(sKFolder.split(X,y)):
    filename = './data/train_fasttext_' + str(i) + '.csv'
    train_df[['text','label_ft']].iloc[train_index].to_csv(filename,index=None,header=None,sep='\t')

    model = fasttext.train_supervised(filename,lr=1.0,wordNgrams=2,verbose=2,minCount=1,epoch=25,loss='hs')
    val_pred = [model.predict(x)[0][0].split('__')[-1] for x in train_df.iloc[validation_index]['text']]
    score = f1_score(train_df['label'].values[validation_index].astype(str),val_pred,average='macro')
    print("第{}折交叉验证的f1_score is : ".format(i),score)
    f1_scores.append(score)
print("10折交叉验证的f1_score平均分为:", np.mean(f1_scores))    

【NLP】天池新闻文本分类(四)——基于深度学习的文本分类1_第3张图片

以上介绍了基于sklearn的StratifiedKFold分层交叉验证的代码实现。(如上代码是在本地机器运行,为了节省时间,仅读取了1.5w数据,当不断增加训练数据集数量时,精度也会不断增加,如上面建模时采用的5w条训练数据时,验证集得分可以到0.89~0.90左右)。

你可能感兴趣的:(【NLP】天池新闻文本分类(四)——基于深度学习的文本分类1)