与传统机器学习不同,深度学习既提供特征提取功能,也可以完成分类的功能。这一TASK主要演示了如何利用深度学习来完成文本表示。
本章主要使用FastText来完成深度学习词向量的表示。FastText通过Embedding层将单词映射到稠密空间,然后将句子中的所有单词在Embedding层空间进行平均,进而完成分类工作。所以FastText层是一个三层的神经网络:输入层、隐含层和输出层。
下图是使用Keras实现的FastText网络结构
以下是通过FastText完成词文本分类的代码和释义,通过代码复现来完成FastText的学习
导入第三方模块
import pandas as pd
from sklearn.metrics import f1_score
from sklearn.model_selection import StratifiedKFold # 这可以保证每一折分布一致
import fasttext
这里使用‘pip install fasttext’报错
解决方案是先下载了fasttext的第三方安装包,然后指定本地路径安装的
网址导航:https://www.lfd.uci.edu/~gohlke/pythonlibs/#fasttext
安装命令:pip install fasttext-0.9.2-cp38-cp38-win_amd64.whl(需要把安装文件放到当前环境的路径下)
分类模型
为了减小机器的压力,还是导入15000条训练样本数据
train_df = pd.read_csv(r'D:\Users\Felixteng\Documents\Pycharm Files\Nlp\data\train_set.csv',
sep='\t', nrows=15000)
转换为FastText需要的格式,默认情况下,我们假设标签是以字符串__label__为前缀的词
train_df['label_ft'] = '__label__' + train_df['label'].astype(str)
取前10000个训练样本的text和新label,创建一个适合FastText格式的新训练集
train_df[['text', 'label_ft']].iloc[:-5000].to_csv('train.csv', index=None, header=None, sep='\t')
训练数据,学习率设为1,n-gram个数为2,为每个epoch输出一行记录,词频阈值为1,次数为25,损失函数选择分层softmax
model = fasttext.train_supervised('train.csv', lr=1.0, wordNgrams=2, verbose=2,
minCount=1, epoch=25, loss='hs')
'''
fasttext.train_supervised() - 训练一个监督模型,返回一个模型对象
参数详解:
input - 训练数据文件路径
lr - 学习率
dim - 向量维度
ws - cbow模型时使用
epoch - 次数
minCount - 词频阈值,小于该值在初始化时会被过滤
minCountLabel - 类别阈值,类别小于改值初始化时会被过滤
minn - 构造subword时最小char个数
maxn - 构造subword时最大char个数
neg - 负采样
wordNgrams - n-gram个数,组成词语的长度
loss - 损失函数类型,softmax, ns:负采样, hs:分层softmax
bucket - 词扩充大小,[A, B]:A语料中包含的词向量,B不在语料中的词向量
thread - 线程个数,每个线程处理输入数据的一段,0号线程负责loss输出
lrUpdateRate - 学习率更新
t - 负采样阈值
label - 类别前缀
pretrainedVectors - 预训练的词向量文件路径,如果word出现在文件夹中初始化不再随机
verbose - 日志显示
verbose = 0 为不在标准输出流输出日志信息
verbose = 1 为输出进度条记录
verbose = 2 为每个epoch输出一行记录
'''
预测验证集数据并计算精度
val_pred_fasttext = [model.predict(x)[0][0].split('__')[-1] for x in train_df.iloc[-5000:]['text']]
'''
由于FastText单个预测值返回的是一个元组,元组包括标签列表和概率列表,如:
(('__label__4',), array([0.99362451]))
所以我们在提取预测类别值的时候提前加上切片操作,将词标签的值取出;
然后按照'__'对词标签进行分割,从而获取实际预测到的类别值
模型单例预测函数代码:
def model.predict(self, text, k=1, threshold=0.0):
"""
模型预测,给定文本预测分类
@param text: 字符串, 需要utf-8
@param k: 返回标签的个数
@param threshold 概率阈值, 大于该值才返回
@return 标签列表, 概率列表
"""
pass
'''
print(f1_score(train_df['label'].values[-5000:].astype(str), val_pred_fasttext, average='macro'))
f1_score为0.82左右。
尝试增加训练样本的数量以提升其精度
train_df_big = pd.read_csv(r'D:\Users\Felixteng\Documents\Pycharm Files\Nlp\data\train_set.csv',
sep='\t', nrows=75000)
train_df_big['label_ft'] = '__label__' + train_df_big['label'].astype(str)
train_df_big[['text', 'label_ft']].iloc[:5000