問(wèn)題描述
Embedding層在機(jī)器學(xué)習(xí)中用的非常多,不問(wèn)是NLP系統(tǒng)還是推薦系統(tǒng)剧董,都會(huì)用到這個(gè)層兔仰,而且是放在最模型的最前面使用的茫负,那么它到底有什么意義,今天我們就探討一下乎赴。
直觀感受
Embedding在keras是這樣描述的的
Turns positive integers (indexes) into dense vectors of fixed size. eg. [[4], [20]] -> [[0.25, 0.1], [0.6, -0.2]]
把單個(gè)整數(shù)變成固定大小的數(shù)組忍法。這件事情的意義何在潮尝?
在實(shí)際的例子中,比如用戶(hù)的id饿序,本來(lái)是單個(gè)整數(shù)表示勉失,但是這些整數(shù)之間不存在任何關(guān)系,比如你不能說(shuō)100021的用戶(hù)比100020的用戶(hù)更大嗤堰,也不能說(shuō)用戶(hù)100021-用戶(hù)100020=用戶(hù)000001戴质。但是實(shí)際項(xiàng)目中,我們需要找到用戶(hù)100021和100020之間的某種關(guān)系踢匣,所以我們需要另外一種描述方式告匠。
所用的描述方式就是通過(guò)遍歷所有用戶(hù)的數(shù)據(jù),找到這些用戶(hù)的隱藏屬性(隱藏特征值)离唬,每個(gè)人用這種隱藏特征值來(lái)描述后专,這個(gè)時(shí)候,他們之間就可以有很強(qiáng)的關(guān)系了输莺。比如相同特征值的用戶(hù)戚哎,我們認(rèn)為更加相似。
小小的例子
Keras里的Embedding層就是做這個(gè)事情的
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)
在這個(gè)例子中嫂用,相當(dāng)于輸入的是32行密碼型凳,每行密碼有10個(gè)數(shù)字,經(jīng)過(guò)Embedding層之后嘱函,每個(gè)數(shù)字變成64維的數(shù)組甘畅。目的是什么?是讓密碼的這十個(gè)數(shù)字之間具有某種關(guān)系往弓。
再舉個(gè)例子疏唾,輸入相當(dāng)于是32句話(huà),每句話(huà)里有10個(gè)單詞函似,經(jīng)過(guò)Embedding層槐脏,之后每個(gè)單詞用64維的數(shù)組表示了。目的是什么撇寞?是讓一句話(huà)里的10個(gè)單詞之間有某種關(guān)系顿天。他們之間的關(guān)系就是通過(guò)64維的數(shù)組表示的。
到底是怎么變換的呢蔑担?
秘密就在那個(gè)1000的數(shù)字上露氮。我們看這里的1000表示輸入整數(shù)的最大數(shù)。也就是最大能解釋的數(shù)钟沛,超過(guò)1000我就無(wú)法給你映射了。所以Embedding的本質(zhì)是定義了一個(gè)巨大的數(shù)組局扶,在此案中就是(1000, 64)恨统,你如輸入任意一個(gè)整數(shù)叁扫,我就能根據(jù)輸入的整數(shù)到這個(gè)數(shù)組里給你找出對(duì)應(yīng)的64個(gè)數(shù)。
又了這樣一個(gè)大的矩陣轉(zhuǎn)換數(shù)組畜埋,那么接下來(lái)在機(jī)器學(xué)習(xí)中莫绣,
比如輸入的是32行句子,每行句子有10個(gè)字符悠鞍,
現(xiàn)在變成
32行句子对室,每行句子有10個(gè)[64維的數(shù)組]。雖然數(shù)據(jù)量變大了咖祭,但是這里的每個(gè)句子內(nèi)的單詞都有某種特殊的關(guān)系了掩宜,這個(gè)關(guān)系是通過(guò)64個(gè)隱藏特征帶來(lái)的。
Embedding 是如何學(xué)習(xí)的
那么在Embedding中么翰,這1000x64的大矩陣是如何學(xué)習(xí)得到的呢牺汤?
按照機(jī)器學(xué)習(xí)的傳統(tǒng)。
第1步浩嫌,先定義這樣一個(gè)1000x64的矩陣檐迟,并且用隨機(jī)數(shù)來(lái)初始化它。
第2步码耐,針對(duì)一批輸入數(shù)據(jù)(32, 10)追迟,映射出(32, 10, 64)
第3步,把上一步輸出骚腥,作為輸入進(jìn)入到模型里敦间,獲得輸出結(jié)果
第4步,把上一步的結(jié)果和真實(shí)值進(jìn)行比較桦沉。從而微調(diào)各個(gè)參數(shù)每瞒,然后從第2步重復(fù)開(kāi)始。
一個(gè)特容易誤解的地方
在我剛開(kāi)始學(xué)習(xí)NLP的時(shí)候纯露,都有把字符文本剿骨,轉(zhuǎn)化成數(shù)字文本的需求,當(dāng)時(shí)看到有的程序里埠褪,把字符文本轉(zhuǎn)換成數(shù)字文本浓利,然后再把數(shù)字文本,轉(zhuǎn)化成這個(gè)矩陣文本钞速,也使用了Embedding層贷掖,當(dāng)時(shí)以為Embedding層是別人創(chuàng)建好的映射層,現(xiàn)在看來(lái)并不是這樣的渴语。最起碼在Keras里苹威,這個(gè)Embedding層的數(shù)據(jù)是需要學(xué)習(xí)得到,初始化的都是一些隨機(jī)數(shù)據(jù)驾凶。