问题描述
Embedding层在机器学习中用的非常多,不问是NLP系统还是推荐系统,都会用到这个层,而且是放在最模型的最前面使用的,那么它到底有什么意义,今天我们就探讨一下。
直观感受
Embedding在keras是这样描述的的
Turns positive integers (indexes) into dense vectors of fixed size. eg. [[4], [20]] -> [[0.25, 0.1], [0.6, -0.2]]
把单个整数变成固定大小的数组。这件事情的意义何在?
在实际的例子中,比如用户的id,本来是单个整数表示,但是这些整数之间不存在任何关系,比如你不能说100021的用户比100020的用户更大,也不能说用户100021-用户100020=用户000001。但是实际项目中,我们需要找到用户100021和100020之间的某种关系,所以我们需要另外一种描述方式。
所用的描述方式就是通过遍历所有用户的数据,找到这些用户的隐藏属性(隐藏特征值),每个人用这种隐藏特征值来描述,这个时候,他们之间就可以有很强的关系了。比如相同特征值的用户,我们认为更加相似。
小小的例子
Keras里的Embedding层就是做这个事情的
model = Sequential()
model.add(Embedding(1000, 64, input_length=10))
# the model will take as input an integer matrix of size (batch, input_length).
# the largest integer (i.e. word index) in the input should be no larger than 999 (vocabulary size).
# now model.output_shape == (None, 10, 64), where None is the batch dimension.
input_array = np.random.randint(1000, size=(32, 10))
model.compile('rmsprop', 'mse')
output_array = model.predict(input_array)
assert output_array.shape == (32, 10, 64)
在这个例子中,相当于输入的是32行密码,每行密码有10个数字,经过Embedding层之后,每个数字变成64维的数组。目的是什么?是让密码的这十个数字之间具有某种关系。
再举个例子,输入相当于是32句话,每句话里有10个单词,经过Embedding层,之后每个单词用64维的数组表示了。目的是什么?是让一句话里的10个单词之间有某种关系。他们之间的关系就是通过64维的数组表示的。
到底是怎么变换的呢?
秘密就在那个1000的数字上。我们看这里的1000表示输入整数的最大数。也就是最大能解释的数,超过1000我就无法给你映射了。所以Embedding的本质是定义了一个巨大的数组,在此案中就是(1000, 64),你如输入任意一个整数,我就能根据输入的整数到这个数组里给你找出对应的64个数。
又了这样一个大的矩阵转换数组,那么接下来在机器学习中,
比如输入的是32行句子,每行句子有10个字符,
现在变成
32行句子,每行句子有10个[64维的数组]。虽然数据量变大了,但是这里的每个句子内的单词都有某种特殊的关系了,这个关系是通过64个隐藏特征带来的。
Embedding 是如何学习的
那么在Embedding中,这1000x64的大矩阵是如何学习得到的呢?
按照机器学习的传统。
第1步,先定义这样一个1000x64的矩阵,并且用随机数来初始化它。
第2步,针对一批输入数据(32, 10),映射出(32, 10, 64)
第3步,把上一步输出,作为输入进入到模型里,获得输出结果
第4步,把上一步的结果和真实值进行比较。从而微调各个参数,然后从第2步重复开始。
一个特容易误解的地方
在我刚开始学习NLP的时候,都有把字符文本,转化成数字文本的需求,当时看到有的程序里,把字符文本转换成数字文本,然后再把数字文本,转化成这个矩阵文本,也使用了Embedding层,当时以为Embedding层是别人创建好的映射层,现在看来并不是这样的。最起码在Keras里,这个Embedding层的数据是需要学习得到,初始化的都是一些随机数据。