NLP.TM | 再看word2vector

再看word2vector

NLP.TM似乎很久没有更新了哈哈哈,其实有些积累了,后面慢慢开始写。

word2vector是自然语言处理中非常非常经典的embedding,即词嵌入模型,主要完成的功能是将文字转化为可供计算的词向量,虽然目前已经被BERT等新型模型逐渐取代,但是在目前一些基线的使用上,仍有非常大的应用空间,这次我计划重看word2vector,主要有下面几个目标:

  • 部分细节已经不太熟悉,希望复习一下,避免有暗坑
  • 一些数据处理上的trick值得再深入挖掘
  • 某些关键API需要确认一下,并且可以避免以后重复查

当然了,熟悉我的朋友都知道,我在文章里,是希望能给大家一些在其他地方找不到或者不好找的东西,重复性的工作和文章我写出来意义不大,且可能写的不如一些前辈更好,所以重复性内容我会用参考文献或者跳转的方式去介绍给大家。

word2vector简述

对于w2v的原理,网上已经有非常多的解释,同时也非常精细,此处我筛选了一些我认为写的非常好的博客和论文,大家可以阅读看看。

开始之前提醒一下先修知识,理解基本神经网络的正反向传播以及SGD算法。

word2vector顾名思义,其实就是旨在把每个单词转化为词向量,其实很多方式都可以实现这个功能,最简单的当然就是one-hot了,但是面对无敌庞大的词库,直接使用one-hot来进行表示将会面临很大的内存占用和很高的计算时间,于是有了LDA、GloVe以及现在比较新的bert等,都是尝试通过使用连续的词向量模型来进行词向量转化,从而进行后续的自然语言处理任务。

那么word2vector是通过什么方式来产生词向量呢——答案就是上下文+网络的模式,而这种上下文如何体现,就是通过类似完形填空的方式进行,对于上下文若干个单词,来预测我挖空位置的单词,这就是CBOW的目前最为常见的方式,看好,是最为常见的方式,即multi-word context(多词语境)形式,这种形式是目前很多文章里面提到的形式,但他的形式并不唯一,这个在《word2vec Parameter Learning Explained》论文里面谈到了,只是一种目前出现最多的形式,其实它的原始形式是一种只有一个单词输入的形式。

CBOW

而反过来,我们同样可以通过该单词预测上下文,这就是Sikp-gram的形式。

skip-gram

两个图的含义非常类似,input layer和output layer都是one-hot类型的文本信息,CBOW和Skip-gram的区别在于是多输入单输出和单输入多输出,中间是一个隐含层,这种模式训练(SGD训练)之后,隐含层的输出结果提取出来其实就是对应词汇的词向量了。

word2vector的优化

模型其实并不复杂,然而在实际操作中其实会遇到大量问题,而针对这些问题,很多人提出了很好的方案,而这些方案,也成为了计算中的技巧,这些技巧其实同样可以在现实中得到实践。

Hierarchical Softmax

Hierarchical Softmax(下面简称HS)是一种为了解决词汇表过大导致计算维度过大问题的解决方案,借助树结构的层次性来缓解维度过大的问题,按照出现时间来看其实方法本身的提出甚至早于word2vector本身,它的实质是构建一棵二叉树,每个单词都挂在叶子节点上,对于大小为V的词库,非叶子节点则对应有V-1个,由于树本身无环的特性(在离散数学中,树的定义是连通但无回路的图),每个单词都能通过从根节点开始的唯一一条路径进行表示。

Hierarchical Softmax

很多文章都有讨论过这个结构,我这里有一个比较规范化的理解,看看对于各位的理解有无帮助。

首先是,这棵树怎么建立的。这棵树的实质是一棵Huffman树(给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为Huffman树),而这棵Huffman树的权重则来源于每个单词出现的频率,根据每个单词的出现频率即可构建出Huffman树。至于原因,可以比较简单的理解为,更为经常出现的单词,在训练的时候经常会出现,快点找到他更有利于进行后续的计算,因此深度可以浅一些,相反不经常出现的单词弱化存在感问题不大,所以建造这样的Huffman树有利于提升效率。

那么,建立这棵树之后,是怎么应用和计算呢。此时在word2vec中,使用的就转为分层二分类逻辑斯蒂回归,从根节点出发,分为负类则向左子树走,分为正类则向右子树走,分类的依据来源于每个非叶子节点上所带有的内部节点向量。

说完应用,就需要回头说怎么训练,训练的原理其实和一般地word2vector非常类似,就是使用基于梯度的方式,如SGD进行更新,值得注意的是,对于树内的每个分类模型,对应的权重也需要更新。

那么此处,我想要提炼的两个trick就是:

  • 多分类问题,可以转化为多个二分类进行计算。
  • 多个二分类问题,可以通过树结构,尤其是Huffman树进行,能进一步提升计算效率。

经过证明,使用Hierarchical Softmax的搜索复杂度是对数级的,而不使用则是线性级的,虽然复杂度都不是很高但是在与如此大的词库场景下,这个提升绝对有必要。

Negative Sampling

也成为负采样。负采样需要解决的是每次迭代的过程中都需要更新大量向量的问题,它的核心思想就是“既然要更新这么多,那就更新一部分呗”。在实际应用中,是需要正负样本输入的,正样本(输出的上下文单词)当然需要保留下来,而负样本(不对的样本)同样需要采集,但是肯定不能是词库里面的所有其他词,因此我们需要采样,这个采样被就是所谓的Negative Sampling,抽样要根据一定的概率,而不是简单地随机,而是可以根据形式的分布。

这个分布估计是这一小块方向下研究最多的,里面谈到很多,如果看单词在语料库中出现的频次,则停止词出现的会很多,当然还可能会有一些由于文本领域产生的特殊词汇,如果平均分配,则采样并没有特别意义,区分度不大,因此根据经验,如下形式似乎得到较多人认可:

Negative Sampling

其中f表示计算对应词汇的词频,这是一个抽样的概率,当然了,还有很多诸如考虑共现概率等构建的指标也有,但是目前似乎没有得到普遍认可,不再赘述。

那么此处能够提炼的关键就是:

  • 样本不平衡或者更新复杂的情况下可以考虑仅使用部分样本进行计算和更新

这个技巧其实在推荐系统中也非常常见,尤其是CTR预估一块,大部分场景下负样本并不少,此时需要一定的负采样。

word2vector的实现

说了这么多word2vector的理论和技巧,当然要谈到这个模型怎么用了,虽然说BERT、ELMo等目前逐渐火了起来,但是在“实现为王”的工业界,word2vector仍然是非常重要的实验基线,因此非常建议大家学起来用起来,甚至的,类似推荐系统等,都会用类似word2vector的方式进行embedding,所以使用起来真的是非常重要的。

此处个人推荐使用gensim中自带的word2vector模型,个人感觉比较合适,即gensim.models里面的word2vec。

数据载入与训练

要进行有关训练,首先需要进行数据的载入,数据载入的形式主要由进入模型的API需求决定,要找这个,就得看这里:

Word2Vec的API文档:https://radimrehurek.com/gensim/models/word2vec.html

这里补充一句严肃的话,一定一定要会自己查API文档,看看每个函数的输入是什么,需要什么格式,输出是什么,格式是什么样的,这是做这行的基本操作

API展示1

这是一个wordvector类的构造函数,运行构造函数可以得到一个word2vector模型类,而且是进行过训练后的,后续可以进行词向量提取等操作,这个文档可以让你知道,这个函数有哪些输入参数,那些是必要的,那些是不必要的,因为有些命名会比较简单,所以在个文字下面,还有更详细的说明。

API展示2

例如这里的size,就是指词向量的维度,具体含义在这里就不赘述啦,自己看自己查。

然后在这里下面给出了一个非常简单的例子,如下。

from gensim.models import Word2Vec
sentences = [["cat", "say", "meow"], ["dog", "say", "woof"]]
model = Word2Vec(sentences, min_count=1)

这里需要大家读出一个非常重要的信息,那就是这里给出了sentences这个变量所需要的格式,句子所需要的格式是一个二维数组,第一维下是一个一个句子的句子数组,内部句子是通过字符串数组组成,那么我们就知道怎么够造句子,从而放入自己的语料进行训练。

data = []
with open(INPUTPATH) as f:
    for line in f:
        ll = line.strip().split(" ")
        data.append(ll[1:])
print("finish formulating")

model = word2vec.Word2Vec(data, size=300)

在这里,我的语料放在了INPUTPATH中,每一行是一个中文句子(已经进行好分词,用空格隔开),因此读取的石油,我用空格将其分开成字符串数组,然后把字符串数组装到data中,构成和上述sentences相同的形式,此处我们就能完成预料的导入。size=300与我实际场景应用有关,词向量长度是300。

word2vector的应用

网上说到了很多类似求距离之类的操作,其实在现实应用中,求距离是一个进行检测的方法,但是更多的,我们只需要和查字典类似,找到我们需要的词汇对应的词向量即可,因此,我们也可以这么做。

网上和API提供了很多方案,此处我给出一个我已经走通的方案。

def loadw2c(inputpath):
    model = gensim.models.Word2Vec.load(inputpath)
    wordEmb = {}
    for k, v in model.wv.vocab.items():
        wordEmb[k] = model.wv[k]
    return wordEmb

首先载入模型,模型路径是inputpath,而model.wv.vocab是一个dictionary形式的数据,这里面存着所有词汇对应的词向量,此处我们将其转到wordEmb中,然后输出,这样通过wordEmb这个词典我们能更快的查找到所需词汇的词向量,当然了,大家也可以直接用model.wv.vocab甚至是model.wv来查找,一样可以。

总结

本文从基础上、优化技巧上以及实现上分别讨论了word2vector模型,虽然比较简略,忽略了大量的公式推导和推理,但是希望大家能从更为宏观的角度去理解并且能够保证实现,这里再次总结一下几个本文提到的关键trick,无论是理论上还是技术上的。

  • 多分类问题,可以转化为多个二分类进行计算。
  • 多个二分类问题,可以通过树结构,尤其是Huffman树进行,能进一步提升计算效率。
  • 样本不平衡或者更新复杂的情况下可以考虑仅使用部分样本进行计算和更新.
  • 经常查文档,阅读文章,能快速理解工具的使用方法。

另外,在文末还是给大家整理一些有关word2vector的资料,方便大家深入理解。

文章写到这里啦,希望能对大家有帮助。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 前面的文章主要从理论的角度介绍了自然语言人机对话系统所可能涉及到的多个领域的经典模型和基础知识。这篇文章,甚至之后...
    我偏笑_NSNirvana阅读 13,648评论 2 64
  • 一、如何表示一个词语的意思 在计算机中如何表示一个词的意思 过去几个世纪里一直用的是分类词典。计算语言学中常见的方...
    DataArk阅读 3,778评论 0 8
  • 本文关键词:NLP、词向量、word2vec、ELMo、语言模型该系列更新的第二篇已在个人微信公众号「AI极客 」...
    流川枫AI阅读 27,199评论 6 48
  • 最近新接触文本分类问题,对于我来数第一个问题就是Word Embedding这个词到底是什么意思,因此也就开始学习...
    小松qxs阅读 24,719评论 2 27
  • 山下时断时续有清风,天上忽多忽少飘云彩。 看骄阳似火把柏油路面烤焦, 可有大雨会来? 不愿把清静时光,换作闹市噪杂...
    泠风思语阅读 273评论 0 2