1.6.1.如何表示字符串
1.6.1.1.word embedding
1.6.1.1.1.文本表示(Representation)
1.6.1.1.2.独热编码 | one-hot representation
1.6.1.1.3.整数编码
1.6.1.1.4.什么是词嵌入 | word embedding ?
1.6.1.1.5. 2中主流的word embedding算法
1.6.1.1.6.百度百科和维基百科
1.6.1.1.7.维基百科版本
1.6.1.2.One - hot
1.6.1.2.1.文本数据向量化
1.6.1.2.2.ont-hot编码
1.6.1.2.3.one-hot散列技巧
1.6.1.3.Embedding
1.6.1.3.1.Word2vec
1.6.1.3.1.1.什么是Word2vec
1.6.1.3.1.2.Word2vec的2中训练模式
1.6.1.3.1.3.Word2vec的优缺点
1.6.1.3.1.4.百度百科
1.6.1.3.2.BERT
1.6.1.3.3.Glove
1.6.1.3.3.1.什么是GloVe?
1.6.1.3.3.2.GloVe是如何实现的?
1.6.1.3.3.4.Glove与LSA、word2vec的比较
1.6.1.3.3.5.公式推导
主要参考博文:
https://www.bilibili.com/read/cv4053575/
https://easyai.tech/ai-definition/word-embedding/
https://easyai.tech/ai-definition/word2vec/
https://easyai.tech/ai-definition/bert/
在深度学习中字符串不好表示,要通过以下的方式来表示。
本文转自:https://easyai.tech/ai-definition/word-embedding/
文本是一种非结构化的数据信息,是不可以直接被计算的。
文本表示的作用就是将这些非结构化的信息转化为结构化的信息,这样就可以针对文本信息做计算,来完成我们日常所见到的文本分类,情感分析等任务。
文本表示的方法有很多种,下面只介绍3类方式:
1.独热编码 | one-hot representation
2.整数编码
3.词嵌入 | word embedding
假设我们要计算的文本中一共出现了4个词:猫、狗、牛、羊。向量里每一个位置都代表一个词。所以用one-hot来表示就是:
猫: [ 1, 0 ,0 ,0 ]
狗: [ 0, 1, 0, 0 ]
牛: [ 0, 0, 1, 0 ]
羊: [ 0, 0, 0, 1 ]
但是在实际情况中,文本中很可能出现成千上万个不同的词,这时候向量就会非常长。其中99%以上都是0。
one-hot的缺点如下:
1.无法表达词语之间的关系。
2.这种过于稀疏的向量,导致计算和存储的效率都不高。
这种方法也非常好理解,用一种数字来代表一个词,上面的例子则是:
猫: 1
狗: 2
牛: 3
羊: 4
将句子里的每个词拼起来就是可以表示一句话的向量。
整数编码的缺点如下:
1.无法表达词语之间的关系
2.对于模型解释而言,整数编码可能具有挑战性。
word embedding 是文本表示的一类方法。跟one-hot编码和整数编码的目的一样,不过他有更多的优点。
词嵌入并不特指某个具体的算法,跟上面2种方式相比,这种方法有几个明显的优势:
1.他可以将文本通过一个低维向量来表示,不像one-hot那么长。
2.语意相似的词在向量空间上也会比较相近。
3.通用性很强,可以用在不同的任务中。
Word2vec
这是一种基于统计方法来获得词向量的方法,他是 2013 年由谷歌的 Mikolov 提出了一套新的词嵌入方法。
这种算法有2种训练模式:
1.通过上下文来预测当前词。
2.通过当前词来预测上下文。
GloVe
Glove是对Word2vec方法的扩展,它将全局统计和Word2vec的基于上下文的学习结合了起来。
想要了解GloVe的三步实现方法、训练方法、和w2c的比较。
词向量(Word embedding),又叫Word嵌入式自然语言处理(NLP)中的一组语言建模和特征学习技术的统称,其中来自词汇表的单词或短语被映射到实数的向量。从概念上讲,它涉及从每个单词一维的空间到具有更低维度的连续向量空间的数学嵌入。
生成这种映射的方法包括神经网络,单词共生矩阵的降维,概率模型,可解释的知识方法,和术语的显示表示 单词出现的背景。
当用做底层输入表示时,单词和短语嵌入已经被证明可以提高NLP任务的性能,例如语法分析和情感分析。
Word embedding 是自然语言处理中的重要环节,它是一些语言处理模型的统称,并不具体指某种算法或模型。Word embedding 的任务是把词转换成可以计算的向量 。从概念上讲,它涉及从每个单词一维的空间到具有更低维度的连续向量空间的数学嵌入。
生成这种映射的方法包括神经网络,单词共生矩阵的降维,概率模型,可解释的知识库方法,和术语的显式表示单词出现的上下文。
当用作底层输入表示时,单词和短语嵌入已经被证明可以提高NLP任务的性能,例如句法分析和情感分析。
参考博文:https://www.bilibili.com/read/cv4053575/
文本数据的格式是一个序列数据,常见的有单词和字符序列。如果需要应用到深度学习网络模型中,就需要将将这些序列进行有效编码。
这里所谓的编码其实就将这些单词或者字符进行向量化。
向量化:就是将文本信息转化为数据张量信息。主要的方法如下:
将文本分割为单词,并将每个单词转换为一个向量。
将文本分割为字符,并将每个字符转换为一个向量。
提取单词或字符的 n-gram,并将每个 n-gram 转换为一个向量。n-gram 是多个连续单词或字符的集合(n-gram 之间可重叠)。
上面的整个过程就是将文本信息进行单元分割。这里有几个概念:
标记(token): 将文本分解而成的单元(单词、字符或 n-gram)
分词(tokenization): 将文本分解成标记的过程
向量编码: 将向量与标记相关联的方法
one-hot编码(one-hot encoding)
标记嵌入[token embedding] 词嵌入(word embedding)
总结文本数据向量化的三个过程:
原始文本(原始数据)
将文本分解成标记(标记)
将标记进行编码(向量编码)
如下图所示:
n-gram是从一个句子中提取的N个(或更少)连续单词(或字符)的集合。
例如:“The cat sat on the mat.”
二元语法(2-gram)集合:
{"The", "The cat", "cat", "cat sat", "sat", "sat on", "on", "on the", "the", "the mat", "mat"}
三元语法(3-gram)集合:
{"The", "The cat", "cat", "cat sat", "The cat sat", "sat", "sat on", "on", "cat sat on", "on the", "the", "sat on the", "the mat", "mat", "on the mat"}
以上的集合又称为词袋,处理的是标记组成的集合.一般它往往被用于浅层的语言处理模型,而不是深度学习模型.
在使用轻量级的浅层文本处理模型时(比如 logistic 回归和随机森林),n-gram 是一种功能强大、不可或缺的特征工程工具。
one-hot编码是将标记转换为向量的最常用、最基本的方法。
它将每个单词与一个唯一的整数索引相关联,然后将这个整数索引 i 转换为长度为 N 的二进制向量(N 是词表大小),这个向量只有第 i 个元素是 1,其余元素都为 0。
单词向量化
# -*- coding: UTF-8 -*-
import numpy as np
# 初始化数据,每个"样本"一个条目
samples = ['The cat sat on the mat.', 'The dog ate my homework.']
# 首先,构建数据中所有token的索引
token_index = {}
for sample in samples:
# 通过'split'方法对样本进行标记。实际使用时还会从样本中删除标点符号和特殊字符
for word in sample.split():
# 可以参考如下去掉非字符的
'''
word = word.lower()
# 去掉非字母字符
if not word.isalpha():
new_word = filter(str.isalpha(), word)
word = ''.join(list(new_word))
'''
# 添加索引
if word not in token_index:
token_index[word] = len(token_index) + 1
# 接下来,对样本进行矢量化
# 对样本进行分词。只考虑每个样本前max_length个单词
max_length = 5
# 用于存储结果
results = np.zeros((len(samples), max_length, max(token_index.values()) + 1))
for i , samples in enumerate(samples):
for j , word in list(enumerate(sample.split()))[:max_length]:
index = token_index.get(word)
results[i, j , index] = 1
print(token_index)
print(results)
输出结果:
{'The': 1, 'cat': 2, 'sat': 3, 'on': 4, 'the': 5, 'mat.': 6, 'dog': 7, 'ate': 8, 'my': 9, 'homework.': 10}
[[[0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]]
[[0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]]]
字符向量化
# -*- coding: UTF-8 -*-
import numpy as np
import string
samples = ['The cat sat on the mat.', 'The dog ate my homeword.']
characters = string.printable
token_index = dict(zip(characters, range(1, len(characters) + 1)))
max_length = 50
results = np.zeros((len(samples), max_length, max(token_index.values()) + 1))
for i ,samples in enumerate(samples):
for j, characters in enumerate(samples[: max_length]):
index = token_index.get(characters)
results[i, j ,index] = 1
print(token_index)
print(results)
输出结果:
{'0': 1, '1': 2, '2': 3, '3': 4, '4': 5, '5': 6, '6': 7, '7': 8, '8': 9, '9': 10, 'a': 11, 'b': 12, 'c': 13, 'd': 14, 'e': 15, 'f': 16, 'g': 17, 'h': 18, 'i': 19, 'j': 20, 'k': 21, 'l': 22, 'm': 23, 'n': 24, 'o': 25, 'p': 26, 'q': 27, 'r': 28, 's': 29, 't': 30, 'u': 31, 'v': 32, 'w': 33, 'x': 34, 'y': 35, 'z': 36, 'A': 37, 'B': 38, 'C': 39, 'D': 40, 'E': 41, 'F': 42, 'G': 43, 'H': 44, 'I': 45, 'J': 46, 'K': 47, 'L': 48, 'M': 49, 'N': 50, 'O': 51, 'P': 52, 'Q': 53, 'R': 54, 'S': 55, 'T': 56, 'U': 57, 'V': 58, 'W': 59, 'X': 60, 'Y': 61, 'Z': 62, '!': 63, '"': 64, '#': 65, '$': 66, '%': 67, '&': 68, "'": 69, '(': 70, ')': 71, '*': 72, '+': 73, ',': 74, '-': 75, '.': 76, '/': 77, ':': 78, ';': 79, '<': 80, '=': 81, '>': 82, '?': 83, '@': 84, '[': 85, '\\': 86, ']': 87, '^': 88, '_': 89, '`': 90, '{': 91, '|': 92, '}': 93, '~': 94, ' ': 95, '\t': 96, '\n': 97, '\r': 98, '\x0b': 99, '\x0c': 100}
[[[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
...
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]]
[[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
...
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]]]
keras实现的one-hot 编码
from keras.preprocessing.text import Tokenizer
samples = ['The cat sat on the mat.', 'The dog ate my homeword.']
# 创建一个tokenizer,配置为只考虑前1000个最常用的单词
tokenizer = Tokenizer(num_words=20)
# 构建单词索引
tokenizer.fit_on_texts(samples)
# 将字符串转换为整数索引组成的列表
one_hot_results = tokenizer.texts_to_matrix(samples,mode='binary')
# 找回单词索引
word_index = tokenizer.word_index
print('Found %s unique tokens.' % len(word_index))
print(one_hot_results)
输出结果:
Found 9 unique tokens.
[[0. 1. 1. 1. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 1. 0. 0. 0. 0. 1. 1. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]
如果词表中唯一标记的数量太大而无法直接处理,就可以使用这种技巧。
这种方法没有为每个单词显式分配一个索引并将这些索引保存在一个字典中,而是将单词散列编码为固定长度的向量,通常用一个非常简单的散列函数来实现。
优点 它避免了维护一个显式的单词索引,从而节省内存并允许数据的在线编码
缺点 就是可能会出现散列冲突(hash collision),即两个不同的单词可能具有相同的散列值。
以下转自:https://easyai.tech/ai-definition/word2vec/
Word2vec是Word Embedding方式之一,属于NLP领域。他是将此转化为”可计算”、”结构化”的向量的过程。
这种方式在2018年之前比较主流,但是随着BERT、GPT2.0的出现,这种方式已经不算效果最好的方法了。
什么是Word Embedding?
在说明 Word2vec 之前,需要先解释一下 Word Embedding。 它就是将”不可计算” , ”非结构化” 的词转化为”可计算”, ”结构化”的向量。
**这一步解决的是”将现实问题转化为数学问题”,**是人工智能非常关键的一步。
将现实问题转化为数学问题只是第一步,后面还需要求解这个数学问题。所以Word Embedding的模型本身并不重要,重要的是生成出来的结果----词向量。因为在后续的任务中会直接用到这个词向量。
什么是Word2vec ?
Word2vec 是 Word Embedding 的方法之一。他是 2013 年由谷歌的 Mikolov 提出了一套新的词嵌入方法。
在Word2vec 出现之前,已经有一些 Word Embedding 的方法,但是之前的方法并不成熟,也没有大规模的得到应用。
CBOW(Continuous Bag-of-Words Model)和Skip-gram (Continuous Skip-gram Model),是Word2vec 的两种训练模式。下面简单做一下解释:
CBOW
通过上下文来预测当前值。相当于一句话中扣掉一个词,让你猜这个词是什么。
Skip-gram
用当前词来预测上下文。相当于给你一个词,让你猜前面和后面可能出现什么词。
优化方法
为了提高速度,Word2Vec经常采用2中加速方式:
1.Negative Sample(负采样)
2.Hierarchical Softmax
需要说明的是:Word2vec 是上一代的产物(18 年之前),18 年之后想要得到最好的效果,已经不使用 Word Embedding 的方法了,所以也不会用到 Word2vec。
优点:
1.由于 Word2vec 会考虑上下文,跟之前的 Embedding 方法相比,效果要更好(但不如 18 年之后的方法)
2.比之前的 Embedding方 法维度更少,所以速度更快
3.通用性很强,可以用在各种 NLP 任务中
缺点:
1.由于词和向量是一对一的关系,所以多义词的问题无法解决。
2.Word2vec是一种静态的方法,虽然通用性强,但是无法针对特定任务做动态优化。
Word2vec,是一群用来产生词向量的相关模型。这些模型为浅而双层的神经网络,用来训练以重新建构语言学之词文本。网络以词表现,并且需猜测相邻位置的输入词,在word2vec中词袋模型假设下,词的顺序是不重要的。训练完成之后,word2vec模型可用来映射每个词到一个向量,可用来表示词对词之间的关系,该向量为神经网络之隐藏层。
此部分来自:https://easyai.tech/ai-definition/bert/
BERT的全称是Bidirectional Encoder Representation from Transformers,即双向Transformer的Encoder,因为decoder是不能获要预测的信息的。模型的主要创新点都在pre-train方法上,即用了Masked LM和Next Sentence Prediction两种方法分别捕捉词语和句子级别的representation。
从现在的大趋势来看,使用某种模型预训练一个语言模型看起来是一种比较靠谱的方法。从之前AI2的 ELMo,到 OpenAI的fine-tune transformer,再到Google的这个BERT,全都是对预训练的语言模型的应用。BERT这个模型与其它两个不同的是
1.它在训练双向语言模型时以减小的概率把少量的词替成了Mask或者另一个随机的词。我个人感觉这个目的在于使模型被迫增加对上下文的记忆。至于这个概率,我猜是Jacob拍脑袋随便设的。
2.增加了一个预测下一句的loss。这个看起来就比较新奇了。
BERT模型具有以下两个特点:
1.是这个模型非常的深,12层,并不宽(wide),中间层只有1024,而之前的Transformer模型中间层有2048。这似乎又印证了计算机图像处理的一个观点——深而窄 比 浅而宽 的模型更好。
2.MLM(Masked Language Model),同时利用左侧和右侧的词语,这个在ELMo上已经出现了,绝对不是原创。其次,对于Mask(遮挡)在语言模型上的应用,已经被Ziang Xie提出了(我很有幸的也参与到了这篇论文中):[1703.02573] Data Noising as Smoothing in Neural Network Language Models。这也是篇巨星云集的论文:Sida Wang,Jiwei Li(香侬科技的创始人兼CEO兼史上发文最多的NLP学者),Andrew Ng,Dan Jurafsky都是Coauthor。但很可惜的是他们没有关注到这篇论文。用这篇论文的方法去做Masking,相信BRET的能力说不定还会有提升。
扩展阅读
入门类文章
深入浅出解析BERT原理及其表征的内容(2019-8)
NLP新秀 : BERT的优雅解读(2019-2-18)
[NLP] Google BERT详解]
[NLP自然语言处理]谷歌BERT模型深度解析
扩展视野类文章
BERT王者归来!Facebook推出RoBERTa新模型,碾压XLNet 制霸三大排行榜(2019-7)
Bert 改进: 如何融入知识(2019-7)
详解BERT阅读理解(2019-7)
XLNet:运行机制及和Bert的异同比较(2019-6)
站在BERT肩膀上的NLP新秀们(PART III)(2019-6)
站在BERT肩膀上的NLP新秀们(PART II)(2019-6)
站在BERT肩膀上的NLP新秀们(PART I)(2019-6)
BERT模型在NLP中目前取得如此好的效果,那下一步NLP该何去何从?(2019-6)
Bert时代的创新:Bert应用模式比较及其它(2019-5)
进一步改进GPT和BERT:使用Transformer的语言模型(2019-5)
76分钟训练BERT!谷歌大脑新型优化器LAMB加速大批量训练(2019-4-3)
知乎-如何评价 BERT 模型?
从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史
BERT 论文
深度长文:NLP的巨人肩膀(上)
NLP 的巨人肩膀(下):从 CoVe 到 BERT
实践类文章
美团BERT的探索和实践(2019-11)
加速 BERT 模型有多少种方法?从架构优化、模型压缩到模型蒸馏最新进展详解!(2019-10)
BERT, RoBERTa, DistilBERT, XLNet的用法对比(2019-9)
一大批中文(BERT等)预训练模型等你认领!(2019-6)
[GitHub] BERT模型从训练到部署全流程(2019-6)
Bert时代的创新:Bert在NLP各领域的应用进展(2019-6)
BERT fintune 的艺术(2019-5)
中文语料的 Bert finetune(2019-5)
BERT源码分析PART III(2019-5)
BERT源码分析PART II(2019-5)
BERT源码分析PART I(2019-5)
【干货】BERT模型的标准调优和花式调优
BERT fine-tune 终极实践教程
详解谷歌最强NLP模型BERT(理论+实战)
用BRET进行多标签文本分类(附代码)
转自:http://www.fanyeong.com/2018/02/19/glove-in-detail/
正如论文的标题而言,GloVe的全称叫Global Vectors for Word Representation,它是一个基于全局词频统计(count-based & overall statistics)的词表征(word representation)工具,它可以把一个单词表达成一个由实数组成的向量,这些向量捕捉到了单词之间一些语义特性,比如相似性(similarity)、类比性(analogy)等。我们通过对向量的运算,比如欧几里得距离或者cosine相似度,可以计算出两个单词之间的语义相似性。
这个图一共采用了三个指标:语义准确度,语法准确度以及总体准确度。那么我们不难发现Vector Dimension在300时能达到最佳,而context Windows size大致在6到10之间。
LSA(Latent Semantic Analysis)是一种比较早的count-based的词向量表征工具,它也是基于co-occurance matrix的,只不过采用了基于奇异值分解(SVD)的矩阵分解技术对大矩阵进行降维,而我们知道SVD的复杂度是很高的,所以它的计算代价比较大。还有一点是它对所有单词的统计权重都是一致的。而这些缺点在GloVe中被一一克服了。而word2vec最大的缺点则是没有充分利用所有的语料,所以GloVe其实是把两者的优点结合了起来。从这篇论文给出的实验结果来看,GloVe的性能是远超LSA和word2vec的,但网上也有人说GloVe和word2vec实际表现其实差不多。