【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
文章图片

下面是使用keras实现的FastText网络结构:
#使用keras实现FastText网络结构 from keras.models import Sequential from keras.layers import Embedding from keras.layers import GlobalAveragePooling1D from keras.layers import DenseVOCAB_SIZE = 2000 EMBEDDING_DIM = 100 MAX_WORDS = 500 CALSS_NUM = 5def 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 modelif __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'))

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

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

#分层交叉验证 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
文章图片

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

    推荐阅读