Deeplearning4j 实战 (16):FastText在监督学习和无监督学习中的应用

Eclipse Deeplearning4j GitChat课程https://gitbook.cn/gitchat/column/5bfb6741ae0e5f436e35cd9f
Eclipse Deeplearning4j 系列博客https://blog.csdn.net/wangongxi
Eclipse Deeplearning4j Githubhttps://github.com/eclipse/deeplearning4j

Deeplearning4j 1.0.0-beta5的版本中NLP模块开始支持FastText模型。在这之前的版本中,已经支持的embedding算法有Word2Vec、Glove、Doc2Vec以及Graph Embedding。这些模块的使用在我的GitChat CSDN达人课中有详细讲解,有需要的开发人员可以参考。
FastText是Word2Vec的作者Tomas Mikolov在Facebook的研究成果,这里先贴下论文的地址:Link。FastText的模型结构非常简单,本质是一个三层的神经网络结构。输入层是文本的N-gram语言模型特征,这些词被embedding后转化成词向量并且加权平均形成隐藏层,在输出层可以使用负采样(Negative Sampling)、层次SoftMax(Hierarchical Softmax)以及直接Softmax作为损失函数。以下是论文中模型结构的截图:
fasttext-model
FastText相对于Word2Vec的创新点其实是在于输入层引入N-gram语言模型的这一trick。其余的模型结构包括损失函数都和Word2Vec类似。因此FastText也是可以直接进行无监督的建模,用于提取语义向量。但更多场景下,开发人员将FastText用于诸如文本分类的工作中,作为对比其他复杂神经网络模型的baseline。由于其网络结构相对简单,因此baseline的工作可以放在CPU上进行,非常快速和方便。
FastText的实现已经开源,开发人员可以去Github托管地址查看相关代码。另外,官方同样针对全世界近300种语言提供了预训练的模型,其中包括欧美语言以及中日韩等常用语言。对于预训练模型的使用在下面的内容中将会详细描述,这里先附上下载说明的地址:预训练模型

1. 预训练中文维基百科模型

Deeplearning4j 1.0.0-beta5版本中的FastText模型支持加载Python原生预训练的模型。在上文的介绍中我们已经给出了预训练模型的地址,开发人员可以自行下载。需要指出的是,下载页面上对于每一种语言会放上bin+text和text两个链接。bin+tex的链接包含两个部分,一个是预训练好的词向量(以.vec为扩展名的文件)另一个是模型文件本身(以.bin为扩展名的文件)。我们直接用文本编辑器打开.vec文件,可以看下类似下面截图的信息:
在这里插入图片描述
可以看到,文件内容的第一行包含了词表大小和词向量大小两个重要信息。从第二行开始是每一个次以及其对应的词向量。图中就是包含了5W左右中文词并且词向量维度是100的一份数据。
下面我们介绍如何基于Deeplearning4j中的FastText模型加载Facebook官方预训练的中文词向量来做预测。Facebook官方提供的词向量都是基于各大语言的维基百科来进行训练的。
在这里插入图片描述
我们直接点击bin+text的链接下载模型和词向量文件。下载下来的是个zip文件,解压后可以得到之前说的两个文件,其中.vec文件800M左右,.bin文件3G左右。我们可以通过以下逻辑来加载这两个预训练好的模型文件。

public void loadPretrained(){
    FastText fastText = new FastText(new File("fasttext/model/wiki.zh.bin"));
    fastText.loadPretrainedVectors(new File("fasttext/model/wiki.zh.vec"));
	//加载预训练模型结束
	//预测相似词        
	System.out.println(fastText.wordsNearest("网络", 3));
	//预测词向量
    System.out.println(Arrays.toString(fastText.getWordVector("网络")));
}

在上面这段逻辑中,我们分别加载了模型和词向量文件,之后我们预测了“网络”这个词的Top3相似词以及该词本身的词向量,可以得到以下结果。
在这里插入图片描述
需要注意,由于Facebook官方预训练的模型较大,因此在程序启动的时候,开发人员可以适当调整下JVM参数。我这边设置的参数是:-Xms4G -Xmx8G。

2. 监督学习

这部分我们介绍下如何基于FastText进行文本分类的工作。在之前的博客中,我们介绍过基于Embedding+LSTM的结构做文本分类问题,这里我们使用那篇博客相同的语料。为了兼容FastText官方的语料格式,我们将原始语料处理成类似下面截图的这种样式。
在这里插入图片描述
语料中第一列是标注。真正和业务相关的标注是“正面”和“负面”,而且带有label的前缀是默认的用于定义标注信息的前缀。当然这个在声明模型实例的时候,可以自定义。语料中以空格隔开标注和语料。同之前的博客一样,我们用jieba分词预先将句子进行分词。下面我们给出FastText的分类建模逻辑。

    public void supervised(File inputFile, File output){
    FastText fastText = FastText.builder()
                                .supervised(true)
                                .learningRate(0.01)
                                .wordNgrams(2)
                                .numThreads(4)
                                .epochs(20)
                                .inputFile(inputFile.getAbsolutePath())
                                .outputFile(output.getAbsolutePath()).build();
    fastText.fit();
    
    //
    FastText _fastText = new FastText(new File("fasttext/supervised/supervised.mod.bin"));
    //
    Pair<String,Float> result = _fastText.predictProbability("鄙视 蒙牛 鄙视 中粮 鄙视 宁高宁");
    System.out.println(result.getFirst() + "\t" + Math.exp(result.getRight()));
}

在上述逻辑中,我们首先声明了一个FastText模型的实例并配置一些参数。这里涉及的主要是学习率、语言模型等。由于实际可设置的参数众多,这里不一一列举。具体我们可以参考Facebook官方给出的参数列表,以下是截图。
在这里插入图片描述
每一行的参数给出了一些物理含义的解释,最后方括号中的是默认取值。例如,-loss参数的默认取值是softmax,同时也支持ns(negative sampling,负采样),hs(hierarchical softmax,分层softmax)的损失函数。在上面代码中,我们没有对损失函数做特别设置,因此就是默认的softmax。
我们直接调用fit接口来进行模型的训练。在训练结束后,我们重新加载这一模型到内存,并且尝试预测单条语料的分类结果。我们调用predictProbability接口可以得到一个二元组的返回值。其中key是预测标注,value是对数概率。为了更加直观的展示原始分类概率,我们将对数概率结果取自然指数值就可以还原成原始概率值。训练过程中的日志和预测结果可以参考下图。
在这里插入图片描述
从日志中我们可以看到,训练语料中一共包含50920个词,2个标注。我们最后预测了单条语料的标注,获得了预测结果以及概率大小。

3. 无监督学习

FastText的无监督学习主要用于生成词向量,使用的方法和训练Word2Vec以及Glove等模型类似。首先我们看下语料的构建。
在这里插入图片描述
无监督训练语料的构建只需要在之前带标注语料的基础上将标注信息删去即可。换言之,语料中的每一行其实是分词后的单条语料。我们同样使用jieba分词,并且词间用空格进行分隔。我们来看下建模的逻辑。

    public void unsupervised(File inputFile,  File output){
    FastText fastText = FastText.builder()
                                .supervised(false)	//无监督建模
                                .skipgram(true)
                                .minCount(1)
                                .bucket(10)
                                .numThreads(4)
                                .lossName("ns")
                                .epochs(10)
                                .inputFile(inputFile.getAbsolutePath())
                                .outputFile(output.getAbsolutePath()).build();
    fastText.fit();
    //
    FastText _fastText = new FastText(new File("fasttext/unsupervised/unsupervised.mod.bin"));
    //
	//        VocabCache vocab = _fastText.vocab();
	//        System.out.println(vocab.vocabWords());
    _fastText.loadPretrainedVectors(new File("fasttext/unsupervised/unsupervised.mod.vec"));
    System.out.println(_fastText.wordsNearest("内存", 3));
    System.out.println(Arrays.toString(_fastText.getWordVector("内存")));
}

同第二部分监督学习的建模逻辑类似,我们声明一个FastText实例,但是需要在supervised方法设置为false,即设置无监督学习。我们通过skipgram或者cbow设置需要用的算法,包括在lossName方法中设置损失函数为ns,即负采样。我们调用fit方法进行模型训练并且将模型文件保存到指定磁盘位置。之后,类似在第一部分加载预训练模型的那种操作,我们分别加载模型和词向量文件到内存,并且使用“内存”这个词进行相似词的推理测试以及打印该词的词向量。结果如下图。
在这里插入图片描述
从截图中我们看到红色字体的是训练部分的日志。主要记录了建模期间主要参数的变化。最后两行信息是我们在代码中通过控制台输出的,可以看到和“内存”这个词相似的Top3的词是“1G”,“2G”,“标配”这几个词以及最后一行词向量本身。词向量本身会保存在.vec的文件中,格式在上面的部分已经介绍过,这里不展开讲了。词向量本身可以直接通过计算某种相似度来作为一些应用场景的召回,当然也可以作为下一阶段神经网络的输入。

4. 小结

这次我们主要介绍了Deeplearning4j 1.0.0-beta5版本中新增的FastText模型的使用。我们分别介绍了在监督学习、无监督学习以及加载官方预训练模型三个主要场景下的使用方法。Deeplearning4j中的FastText底层实际是依赖JFastText这个项目。JFastText是通过JavaCPP的JNI方式调用Facebook原生接口来实现的,因此可以完全兼容原始项目的接口和文件格式。
FastText模型本身使用了N-gram语言模型来优化输入的特征。对于一些经典的NLP问题,如:文本分类,语言模型的引入会较大程度地提升模型指标。FastText正是借鉴了这样的思想,将其与之前Word2Vec中使用过的网络结构相结合从而产生了一种快速高效可以用于监督学习的模型。在上文中我们提到,FastText的分类结果往往会作为baseline的指标,这样源于其模型较为简单,建模快速的特点。上述的这些工作,作者都是在本地CPU机器上完成,有兴趣的朋友也可以自己尝试下。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wangongxi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值