FastText学习笔记

目标

  • 了解fasttext
  • 使用fasttext进行分类

分类问题

首先介绍分类问题,以二分类问题为例。目前具有人工标注的数据集,数据集分为2类标签,正例和反例。数据示例如下:

  • 正例: 印度药企对中国市场充满期待
  • 反例: 中国驻维也纳代表团举办改革开放40周年活动

预测新样例的类别

我国东部第一口干热岩钻井获得成功 => [正例?/反例?]

FastText简介

fasttext结构

FastText学习笔记_第1张图片

  • xi x i : 一个句子的特征,初始值为随机生成(也可以采用预训练的词向量)
  • hidden: xi x i 的平均值
  • output: 样本标签

目标函数

  • N N : 样本个数
  • yn y n : 第n个样本对应的类别
  • f f : 损失函数 softmax/ns(negative sampling)/hs(hierarchical softmax)
  • xn x n : 第n个样本的归一化特征
  • A A : 权重矩阵(构建词,embedding层)
  • B B : 权重矩阵(隐层到输出层)

词向量初始化

一个句子的embedding为 [iw1,iw2,...,iwn,ow1,ow2,...,ows] [ i w 1 , i w 2 , . . . , i w n , o w 1 , o w 2 , . . . , o w s ]

  • iwi i w i : 语料中出现的词,排在数组的前面
  • owi o w i : n-gram或n-char特征
  • 初始化为随机数, 如果提供预训练的词向量,对应的词采用预训练的词向量

hierarchical Softmax

FastText学习笔记_第2张图片

图片来源 https://blog.csdn.net/itplus/article/details/37969519

  • 当语料类别较多时,使用hierarchical Softmax(hs)减轻计算量
  • hs利用Huffman 树实现,词(生成词向量)或label(分类问题)作为叶子节点
  • 根据词或label的count构建Huffman 树,则叶子到root一定存在一条路径
  • 利用逻辑回归二分类计算loss

n-gram和n-char

fasttext方法不同与word2vec方法,引入了两类特征并进行embedding。其中n-gram颗粒度是词与词之间,n-char是单个词之间。两类特征的存储均通过计算hash值的方法实现。

n-gram

示例: who am I? n-gram设置为2

n-gram特征有,who, who am, am, am I, I

n-char

  • 示例: where, n=3, 设置起止符<, >
  • n-char特征有,

模型压缩

为了减小模型大小和内存占用量,fasttext针对分类问题的模型提供了模型压缩的方法,采用的模型压缩方法,模型压缩之后可能会造成准确率和召回率的下降。

训练词向量模型

fasttext作为训练词向量任务,有2种类型的模型,一是根据周围词语预测自身的cbow(continuous bag-of-words)模型,另一个是根据自身预测周围词的skip-gram(continuous skip-gram)模型。2种类型的示例图如下:

  • cbow

    FastText学习笔记_第3张图片

    图片来源 https://blog.csdn.net/itplus/article/details/37969519

  • skipgram
    FastText学习笔记_第4张图片
    图片来源 https://blog.csdn.net/itplus/article/details/37969519

FastText分类(python)

语料准备

语料示例

\__label__1 印度 药企 中国市场 充满 期待
  • __label__: 类别前缀,涉及fasttext参数-label,两者需保持一致,构造词典时根据前缀判断是词还是label
  • 1: 类别id,用来区分不同类,可自定义
  • “印度 药企 中国市场 充满 期待”: 分词结果

API介绍

为使用fasttext的python版,前提安装fasttext,从github下载最新代码并安装,并

from fastText import train_supervised, load_model
  • 分类问题模型训练

    def train_supervised(input, lr=0.1, dim=100, 
                       ws=5, epoch=5, minCount=1, 
                       minCountLabel=0, minn=0, 
                       maxn=0, neg=5, wordNgrams=1, 
                       loss="softmax", bucket=2000000, 
                       thread=12, lrUpdateRate=100,
                       t=1e-4, label="__label__", 
                       verbose=2, pretrainedVectors=""):
      """
      训练一个监督模型, 返回一个模型对象
    
      @param input: 训练数据文件路径
      @param lr:              学习率
      @param dim:             向量维度
      @param ws:              cbow模型时使用
      @param epoch:           次数
      @param minCount:        词频阈值, 小于该值在初始化时会过滤掉
      @param minCountLabel:   类别阈值,类别小于该值初始化时会过滤掉
      @param minn:            构造subword时最小char个数
      @param maxn:            构造subword时最大char个数
      @param neg:             负采样
      @param wordNgrams:      n-gram个数
      @param loss:            损失函数类型, softmax, ns: 负采样, hs: 分层softmax
      @param bucket:          词扩充大小, [A, B]: A语料中包含的词向量, B不在语料中的词向量
      @param thread:          线程个数, 每个线程处理输入数据的一段, 0号线程负责loss输出
      @param lrUpdateRate:    学习率更新
      @param t:               负采样阈值
      @param label:           类别前缀
      @param verbose:         ??
      @param pretrainedVectors: 预训练的词向量文件路径, 如果word出现在文件夹中初始化不再随机
      @return model object
    
      """
      pass
  • 词向量训练

    fasttext不仅可以进行文本分类,也可以训练词向量,准备语料时,只需要去掉原始数据中的label标签即可。

    def train_unsupervised(input, model="skipgram", lr=0.05, dim=100, 
                       ws=5, epoch=5, minCount=5, 
                       minCountLabel=0, minn=3, 
                       maxn=6, neg=5, wordNgrams=1, 
                       loss="ns", bucket=2000000, 
                       thread=12, lrUpdateRate=100,
                       t=1e-4, label="__label__", 
                       verbose=2, pretrainedVectors=""):
      """
      训练词向量,返回模型对象
      输入数据不要包含任何标签和使用标签前缀
    
      @param model: 模型类型, cbow/skipgram两种
      其他参数参考train_supervised()方法
      @return model
      """
      pass

  • 模型压缩

    def model.quantize(self, input=None, qout=False, cutoff=0,
                     retrain=False, epoch=None, lr=None, thread=None,
                     verbose=None, dsub=2, qnorm=False):
      """
      减小模型大小和内存占用
    
      @param input:   训练数据文件路径
      @param qout:    是否修剪输出层
      @param cutoff:  重新训练的词和n-gram的个数
      @param retrain: 是否重新训练
      @param epoch:   次数
      @param lr:      学习率
      @param thread:  线程个数
      @param verbose: ?
      @param dsub:    压缩方法将向量分成几块, 每块大小
      @param qnorm:   是否归一化(l2范数)
    
      """
      pass
  • 模型存储

    def model.save_model(self, path):
      """
      把模型存储到给定的路径
    
      @param path: 模型路径
      """
      pass
  • 模型单例预测

    def model.predict(self, text, k=1, threshold=0.0):
      """
      模型预测,给定文本预测分类
    
      @param text:       字符串, 需要utf-8
      @param k:          返回标签的个数
      @param threshold   概率阈值, 大于该值才返回
      @return 标签列表, 概率列表
      """
      pass
  • 模型批量预测

    def model.test(self, path, k=1):
      """
      根据给定的测试数据进行模型评价
    
      @param path: 测试数据路径
      @param k:    返回标签的个数
      @return [样本个数, 准确率, 召回率]
      """
      pass
  • 模型加载

    def load_model(path):
      """
      从给定的路径加载模型, 返回一个模型对象
    
      @param path: 模型路径
      @return model object
      """
      pass

分类评测

根据precision, recall, f1值进行评测算法性能

参考文献

  1. word2vec详解 https://blog.csdn.net/itplus/article/details/37969519
  2. fastText源码 https://github.com/facebookresearch/fastText
  3. 分层softmax和n-gram https://arxiv.org/abs/1607.01759
  4. N-gram https://arxiv.org/abs/1607.04606
  5. 模型压缩 https://arxiv.org/abs/1612.03651

你可能感兴趣的:(机器学习系列)