NLP入门--T4基于深度学习的文本分类-1
在之前学习使用传统机器学习模型来解决文本分类问题,从本章开始学习使用深度学习方法。
【学习目标:】
- 学习FastText的使用和基础原理
- 学会使用验证集进行调参
4 基于深度学习的文本分类
与传统机器学习不同,深度学习既能提供也正提取功能,也可以完成分类的功能。
4.1 文本表示方法
4.1.1 上章节文本表示
在之前学习几种文本表示方法:
- One-hot
- Bag of Words
- N-gram
- TF-IDF
也通过sklearn包进行了相应的实践;但都存在的问题:1. 转换得到的向量维度很高,需要较长的训练实践。 2. 没有考虑单词与单词之间的关系,只是进行了统计。
4.1.2 深度学习文本表示
与上述表示方法不同,深度学习也可以用于文本表示,还可以将其映射到一个低维空间。其中典型的方法:FastText、Word2Vec和Bert。在本章我们将介绍FastText,将在后面的内容介绍Word2Vec和Bert.
4.2 FastText文本表示
FastText是一种典型的深度学习词向量的表示方法,通过Embedding层将单词映射到稠密空间,然后将句子中所有的单词在Embedding空间中进行平均,进而完成分类操作。
所以FastText是一个三层的神经网络:输入层、隐含层和输出层。
下图是使用Keras框架实现的FastText神经网络结构:
# coding: utf-8
form __futur__ import unicode_literals
from keras.models import Sequential
from keras.layers import Embedding
from keras.layers import GlobelAveragePooling1D
from keras.layers import Dense
# 名词参数
VOCAB_SIZE=2000
EMBEDDING_DIM=100
MAX_WORDS=500
CLASS_NLM=5
def build_fastText():
model=Sequential()
# 通过Embedding层,我们将词汇映射成EMBEDDING_DIM维向量
model.add(Embedding(VOCAB_SIZE,EMBEDDING_DIM,input_length=MAX_WORDS))
# 通过GlobalAveragePooling1D,我们平均了文档中所有词的Embedding
model.add(GlobalAveragePooling1D())
# 通过输出层Softmax分类(真实的fastText这里是分层Softmax)得到类别概率分布
model.add(Dense(LASS_NLM,activation='softmax'))
# 定义损失函数、优化器、分类度量指标
model.compile(loss='categoriacl_crossentropy',optimizer='SGD',metrics=['accuracy'])
return model
if __name__=='__main__':
model = build_fastText()
print(moedl.summary())
FastText在文本分类任务上,是优于TF-IDF的:
- FastText用单词的Embedding叠加获得的文档向量,将相似的句子分为一类
- FastText学习到的Embedding空间维度比较低,可以快速进行训练
FastText在NLP上的应用完整论文:https://arxiv.org/abs/1607.01759
4.2.1 基于FastText的文本分类
FastText可以使用在CPU上进行训练(省去GPU),最好的实践方法就是官方开源的版本。
https://github.com/facebookresearch/fastText/tree/master/python
- pip安装
pip install fasttext - 源码安装
git clone https://github.com/facebookreserach/fastText.git
cd fastText
sudo pip install
两种安装方法,初学者优先考虑使用pip安装 - 分类模型
import pandas as pd
from sklearn.metrics import f1_score
# 转换为FastText需要的格式
train_df = pd.read_csv('../input/train_set.csv',sep='\t',nrows=15000)
train_df['label_ft']='__label__' + train_df['label'].astype(str)
train_df[['text','label_ft']].iloc[:-5000].to_csv('train,csv',index=None,header=None,sep='\t')
import fasttext
model=fasttext.train_supervised('train.csv',lr=1.0,wordNgrams=2,verbose=2,minCount=1,epoch=25,loss='hs')
val_pred =[moedl.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'))
# 0.82
是因为现在的数据集量较小得分为0.82,当不断增加训练集数量时,FastText的精度也会不断增加,当达到5W条样本时,验证集分数达到0.89-0.90。
4.2.2 使用验证集调参
在使用TF-IDF和FatText中,有一些模型的参数需要选择,这些参数会在一定程度上影响模型的精度,那么如何选择这些参数呢?
- 首先要通过阅读文档,要弄清楚这些参数的大致含义,那些参数会在增加模型的复杂度
- 通过验证集上进行验证模型精度,知道模型现在是否过拟合还是欠拟合
这里我们使用10折交叉验证,每折使用9/10的数据进行训练,剩余1/10作为验证集检验模型的效果。这里需要注意每折的划分必须保证标签的分布与整个数据集的分布一致。
label2id = {}
for i in range(total):
label=str(all_labels[i])
if label not in label2id:
label2id[label] =[i]
else:
label2id[label].apped(i)
通过10折划分,一共得到10折分布一致的数据,索引分别为0-9,每次通过将一份数据作为验证集,剩余数据作为验证集,获得了所有数据的10种分割。不失一般性,我们选择最后一份完成剩余的实验,即索引为9的一份做为验证集,索引为0-8的作为训练集,然后基于验证集的结果调整超参数,使得模型性能更优。
4.3 小结和作业
本章介绍了FastText的原理和基础使用,并进行相应的实践。然后介绍了通过10折交叉验证划分数据集。
【作业】
- 阅读FastText的文档,尝试修改参数,得到更好的分数
- 基于验证集的结果调整超参数,使得模型性能调优