Press "Enter" to skip to content

零基础入门NLP – 基于深度学习的文本分类1

学习目标

学习FastText的使用和基础调参
使用交叉验证提高精度

文本表示方法Part2

 

传统文本表示方法的缺陷

 

在上一节种, 介绍了几种文本表示方法

One-hot
Bag of words(BoW)
N-gram
TF-IDF

以上的方法在一定程度上可以很好的表示文本, 但它们只能挖掘出文本种很有限的信息, 它们更关注文档种单词的统计特征, 而忽视了单词间相互的关系, 并且或多或少存在维度过高的问题.

 

另外, 通过以上的方式训练的模型, 几乎无法迁移到其他任务, 因为不同的任务具有不同的字典, 而我们几乎无法修改训练好的模型中的字典.

 

这节中, 我会介绍基于深度学习中的其中一种方式 FastText , 它更高效, 表达能力也更强.

 

FastText介绍

 

FastText是一个用于高效的词表示和句子分类的库, fasttext提供了2种模型来计算词表示, 分别是 cbow 和 skip-gram . 下面对这两种模型进行简要介绍

 

在介绍之前, 还需要了解一个概念, Word Embedding . 因为cbow和skip-gram都是word embedding的具体实现方式.

 

word embedding其实更上一节当中的词表示方法很像, 它其实就是词的向量化表现形式, 就好比我们用RGB3个值来表示一个像素一样.

 

那幺为什幺需要embedding呢, 比如在人类语言中, 词 catdog 都是动物, 两者比较接近, 那幺如何表示两个词比较相似呢. 再比如 intelligentclever 都可以表示聪明的, 具有相同的含义; 还有很多这种单词之间的语义关系.

 

而word embedding可以将这种语义关系进行量化, 从而解决这个问题, 在word embedding中, 我们期待同一个类别的词向量在嵌入空间中应该靠的比较近, 即相互之间的距离比较小; 没有关系的词应该相距很远等等.

 

那幺如何在考虑单词之间的语义信息下对单词进行量化呢, 这就是接下来介绍的内容了

 

CBOW(continuous bag of words)

 

CBOW也叫连续词袋模型, 它是由一个3层的全连接神经网络构成, 如下图所示

 

 

它将每个单词的上下文作为输入, 来预测与上下文相对应的单词. 比如下面的这个例子: Have a great day

 

我们将 great 作为网络输入, 尝试使用单个上下文输入 great 来预测目标单词 day . 具体来说, 使用输入单词的one-hot向量输入, 然后评估目标单词(day)的one-hot向量与网络输出的损失. 在预测目标单词的one-hot向量的过程中, 网络学习目标单词的向量表示(隐层的输出).

 

回到上图, 上下文输入是大小为$V$的one-hot向量, 隐层包含$N$个神经元, 网络的输出是大小为$V$的softmax激活函数输出.

 

整个网络只有最后一个激活函数(softmax), 输入层和隐层之间没有激活函数.

 

上边的网络只用了一个上下文单词来训练网络, 下面的网络使用了$C$个上下文单词, $W_{V\times N}$ 用来计算隐层的输入

 

 

依次将句子中的每个单词作为target, 其余单词作为上下文输入, 训练网络, 最终可以得到所有词向量.

 

Skip-gram

 

假设现在在一个句子上有一个固定尺寸的滑动窗口, 处于窗口最中间的单词作为 target , 窗口内其余单词(target左边和target右边的单词)作为上下文单词.

 

skip-gram模型训练用来预测在给定的 target 下的上下文单词的概率分布(softmax的输出). skip-gram模型的结构如下图所示:

 

 

比如下面这句话, 我们使用skip-gram模型来得到每个词的向量表示

 

“The man who passes the sentence should swing the sword.” – Ned Stark

 

设定窗口大小为5, 则窗口每次移动对应的 targetcontext 为如下表所示

Sliding window (size = 5)Target wordContext
[The man who]theman, who
[The man who passes]manthe, who, passes
[The man who passes the]whothe, man, passes, the
[man who passes the sentence]passesman, who, the, sentence
[sentence should swing the sword]swingsentence, should, the, sword
[should swing the sword]theshould, swing, sword
[swing the sword]swordswing, the

 

可以看到, skip-gram模型结构就像是cbow模型水平翻转过来一样, 跟cbow模型的结构刚好相反.

 

FastText安装以及使用

 

FastText推荐在linux或者MacOs系统上安装, 需要具备C++11的支持, 如下的安装步骤在linux系统下进行.

 

# 下载FastText安装包
!wget  https://github.com/facebookresearch/fastText/archive/v0.9.2.zip
# 解压
!unzip v0.9.2.zip
# 
%cd fastText-0.9.2
# 对于命令行使用
!make
# 绑定python, 安装
!pip install .
%cd ..

 

测试是否安装成功

 

# 命令行测试
!./fastText-0.9.2/fasttext
# python环境测试
import fasttext  
help(fasttext.FastText)

 

如果可以输出正常的相关命令信息, 则说明已经安装成功

 

一切准备就绪, 就可以开始使用FastText来对文本分类了

 

# 导入库
import pandas as pd
import os
from collections import Counter
import matplotlib.pyplot as plt
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.metrics import  f1_score
from sklearn.model_selection import train_test_split
from sklearn.linear_model import RidgeClassifier
%matplotlib inline
import fasttext
# help(fasttext.FastText)
# 读取数据
root_dir = '/content/drive/My Drive/competitions/NLPNews'
df = pd.read_csv(root_dir+'/train.csv', sep='\t', nrows=30000)

# 在训练之前需要把标签转换为fasttext所需要的格式, label需要以`__label__`开头
df['label'] = df['label'].apply(lambda x: '__label__' + str(x))
train_df = df.loc[:27000, ['text', 'label']]
train_df.to_csv('train.csv', header=False, index=False, sep='\t')

# loss = 'hs'表示的是hierarchical softmax, 它是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] for x in df.iloc[-3000:]['text']]
# val_df = train_df.iloc[-3000:]
print('F1_score', f1_score(df.iloc[-3000:]['label'].apply(lambda x: x.split('__')[-1]), val_pred, average='macro'))

 

F1_score: 0.8008228595916222

 

交叉验证调参

 

这里使用10折交叉验证, 将数据按照训练集:验证集 = 9:1来划分, 因为这里数据量较大, 所以这个比例是没有问题的. 需要注意的是训练集和验证集需要保证是同分布的.

 

我们可以预先设定参数搜索范围, 比如wordNgrams: [2, 3, 4], 对搜索范围内的每个值都进行交叉验证, 最后取最高的f1-score对应的参数取值

 

总结

 

这里, 主要学习了两种基于深度学习的文本表示方法CBOW和Skip-gram, 同时使用了FastText库对文本进行了分类. 由于硬件限制, 暂时没有进行模型的交叉验证, 只是简要说明.

 

Reference

 

[1] FastText install tutorial

 

[2] Text classification

 

[3] Introduction to Word Embedding and Word2Vec

 

[4] Learning Word Embedding

 

[5] NLP 101: Word2Vec — Skip-gram and CBOW

 

[6] Datawhale零基础入门NLP赛事 – Task4 基于深度学习的文本分类1-fastText

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注