学习目标学习FastText的使用和基本调优使用交叉验证提高准确率文本表示方法Part2传统文本表示方法的缺陷在上一节中描述。几种文本表示方法One-hotBagofwords(BoW)N-gramTF-IDF上面的方法在一定程度上可以很好的表示文本,但是只能挖掘出非常有限的文本信息,更注重文档中单词的统计特征,而忽略了单词之间的关系,或多或少存在维度过高的问题。另外,用上述方法训练出来的模型很难迁移到其他任务中,因为不同的任务有不同的字典,我们很难修改训练好的模型中的字典。这一节,我将介绍FastText,一种基于深度学习的方法,更加高效和表达。FastText介绍FastText是一个用于高效单词表示和句子分类的库。Fasttext提供了两种模型来计算词表示,即cbow和skip-gram。下面简单介绍一下这两种型号。在介绍之前,需要了解一个概念,WordEmbedding。因为cbow和skip-gram都是wordembedding的具体实现。Wordembedding其实和上一节的wordrepresentation方法很相似。它其实就是词的向量化表示,就像我们用RGB3值来表示一个像素点一样。那么为什么需要嵌入呢?比如在人类语言中,cat和dog这两个词都是动物,而且比较接近,那么怎么表达这两个词相似。例如,intelligent和clever都表示聪明,意思相同;这些词之间有很多语义关系。词嵌入可以量化这种语义关系来解决这个问题。在词嵌入中,我们期望同一类别的词向量在嵌入空间中比较接近,即它们之间的距离比较小;不相关的词应该相距较远等等。那么如何在考虑词与词之间的语义信息的情况下对词进行量化,这就是接下来要介绍的内容。CBOW(continuousbagofwords)CBOW也称为continuousbagofwordsmodel,它由一个3层的全连接神经网络组成,如下图所示,它以每个单词的上下文作为输入来预测单词对应上下文。例如下面的例子:HaveagreatdayWewillgreatdo作为网络的输入,尝试使用单一的上下文输入来预测目标词日。具体来说,使用输入词的one-hot向量输入,然后根据网络的输出评估目标词(day)的one-hot向量的损失。在预测目标词的one-hot向量的过程中,网络学习到目标词的向量表示(隐藏层的输出)。回到上图,上下文输入是一个大小为$V$的one-hotvector,隐藏层包含$N$个神经元,网络的输出是大小为$V$的softmax激活函数输出。整个网络只有最后一个激活函数(softmax),输入层和隐藏层之间没有激活函数。上层网络只使用一个上下文词来训练网络,下面的网络使用$C$个上下文词,$W_{V\timesN}$用于计算隐藏层的输入。句子中的每个词依次作为目标,其余词作为上下文输入。TrainingNetwork,最后可以得到所有的词向量。Skip-gram假设句子上有一个固定大小的滑动窗口,窗口中间的词作为目标,窗口中其余的词(目标左右两边的词)作为上下文词。skip-gram模型训练用于预测上下文词在给定目标(softmax输出)下的概率分布。skip-gram模型的结构如下图所示:例如,在下面的句子中,我们使用skip-gram模型来获取每个词“Themanwhopassthesentenceshouldswingthesword”的向量表示。–NedStark将窗口大小设置为5,则窗口每次移动对应的目标和上下文如下表所示Slidingwindow(size=5)TargetwordContext[Themanwho]theman,who[Themanwhopasses]manthe,who,passes[Themanwhopassedthe]whothe,man,passes,[manwhopassthesentence]passesman,who,the,sentence…………[sentenceshouldswingthesword]swing句子,should,剑[shouldswingthesword]theshould,swing,sword[swingthesword]swordswing,可以看出,skip-gram模型结构就像水平翻转的cbow模型,恰好与cbow模型结构相反。FastText安装与使用FastText推荐安装在linux或者MacOs系统上,需要C++11的支持。以下安装步骤均在linux系统下进行。#下载FastText安装包!wgethttps://github.com/facebookresearch/fastText/archive/v0.9.2.zip#解压!unzipv0.9.2.zip#%cdfastText-0.9.2#Forcommandlineuse!make#Bindpython,install!pipinstall.%cd..test是否安装成功#commandlinetest!./fastText-0.9.2/fasttext#python环境测试importfasttexthelp(fasttext.FastText)如果可以正常输出相关命令信息,说明安装成功,万事俱备,可以开始使用FastText进行文本分类了#导入库importpandasaspdimportosfromcollectionsimportCounterimportmatplotlib.pyplotaspltfromsklearn.feature_extraction.textimportCountVectorizer,TfidfVectorizerfromsklearn.metricsimportf1_scorefromsklearn.model_selectionimporttrain_test_splitfromsklearn.linear_modelimportRidgeClassifier%matplotlibinlineimportfasttext#帮助(fasttext.FastText_dir)#读取数据root='/content/drive/MyDrive/competitions/NLPNews'df=pd.read_csv(root_dir+'/train.csv',sep='\t',nrows=30000)#训练前需要将label转换为fasttext要求的格式,label需要以`__label__`df['开头label']=df['label'].apply(lambdax:'__label__'+str(x))train_df=df.loc[:27000,['text','label']]train_df.to_csv('train.csv',header=False,index=False,sep='\t')#loss='hs'表示hierarchicalsoftmax,是softmax的近似,但是计算速度更快"""epoch:推荐范围[5,50]lr:推荐范围[0.0,1.0]wordNgrams:推荐范围[1,5]"""model=fasttext.train_supervised('train.csv',lr=0.1,wordNgrams=2,verbose=2,minCount=1,epoch=25,loss="hs")val_pred=[model.predict(x)[0][0].split('__')[-1]forxindf.iloc[-3000:]['text']]#val_df=train_df.iloc[-3000:]print('F1_score',f1_score(df.iloc[-3000:]['label'].apply(lambdax:x.split('__')[-1]),val_pred,average='macro'))F1_score:0.8008228595916222交叉验证调整参数这里,10-foldcross-使用了validation,按照trainingset:validationset=9:1划分数据,因为这里的数据量很大,所以这个比例不是问题。需要注意的是,训练集和验证集需要保证同分布。我们可以预先设定参数搜索范围,比如wordNgrams:[2,3,4],对于搜索范围的每一个值都进行交叉验证,最后取最高的f1-score对应的参数值在这里总结,主要学习了两种基于深度学习的文本表示方法,CBOW和Skip-gram,同样使用FastText库对文本进行分类。由于硬件限制,暂时没有对模型进行交叉验证,只是简单描述一下。参考[1]FastText安装教程[2]文本分类[3]WordEmbedding和Word2Vec简介[4]学习WordEmbedding[5]NLP101:Word2Vec—Skip-gram和CBOW[6]Datawhale零基础入门NLP事件-Task4基于深度学习的文本分类1-fastText
