函數(shù)調(diào)用形式

torch.nn.Embedding(num_embeddings, embedding_dim, padding_idx=None,
max_norm=None, norm_type=2.0, scale_grad_by_freq=False,
sparse=False, _weight=None)
其為一個(gè)簡(jiǎn)單的存儲(chǔ)固定大小的詞典的嵌入向量的查找表,意思就是說(shuō),給一個(gè)編號(hào),嵌入層就能返回這個(gè)編號(hào)對(duì)應(yīng)的嵌入向量,嵌入向量反映了各個(gè)編號(hào)代表的符號(hào)之間的語(yǔ)義關(guān)系。
輸入為一個(gè)編號(hào)列表,輸出為對(duì)應(yīng)的符號(hào)嵌入向量列表。
參數(shù)解釋
- num_embeddings (python:int) – 詞典的大小尺寸,比如總共出現(xiàn)5000個(gè)詞,那就輸入5000。此時(shí)index為(0-4999)
embedding_dim (python:int) – 嵌入向量的維度,即用多少維來(lái)表示一個(gè)符號(hào)。- padding_idx (python:int, optional) – 填充id,比如,輸入長(zhǎng)度為100,但是每次的句子長(zhǎng)度并不一樣,后面就需要用統(tǒng)一的數(shù)字填充,而這里就是指定這個(gè)數(shù)字,這樣,網(wǎng)絡(luò)在遇到填充id時(shí),就不會(huì)計(jì)算其與其它符號(hào)的相關(guān)性。(初始化為0)
- max_norm (python:float, optional) – 最大范數(shù),如果嵌入向量的范數(shù)超過(guò)了這個(gè)界限,就要進(jìn)行再歸一化。
- norm_type (python:float, optional) – 指定利用什么范數(shù)計(jì)算,并用于對(duì)比max_norm,默認(rèn)為2范數(shù)。
- scale_grad_by_freq (boolean, optional) – 根據(jù)單詞在mini-batch中出現(xiàn)的頻率,對(duì)梯度進(jìn)行放縮。默認(rèn)為False.
- sparse (bool, optional) – 若為T(mén)rue,則與權(quán)重矩陣相關(guān)的梯度轉(zhuǎn)變?yōu)橄∈鑿埩俊?/li>
下面是關(guān)于Embedding的使用
torch.nn包下的Embedding,作為訓(xùn)練的一層,隨模型訓(xùn)練得到適合的詞向量。
#建立詞向量層
embed = torch.nn.Embedding(n_vocabulary,embedding_size)
找到對(duì)應(yīng)的詞向量放進(jìn)網(wǎng)絡(luò):詞向量的輸入應(yīng)該是什么樣子
實(shí)際上,上面通過(guò)隨機(jī)初始化建立了詞向量層后,建立了一個(gè)“二維表”,存儲(chǔ)了詞典中每個(gè)詞的詞向量。每個(gè)mini-batch的訓(xùn)練,都要從詞向量表找到mini-batch對(duì)應(yīng)的單詞的詞向量作為RNN的輸入放進(jìn)網(wǎng)絡(luò)。那么怎么把mini-batch中的每個(gè)句子的所有單詞的詞向量找出來(lái)放進(jìn)網(wǎng)絡(luò)呢,輸入是什么樣子,輸出是什么樣子?
首先我們知道肯定先要建立一個(gè)詞典,建立詞典的時(shí)候都會(huì)建立一個(gè)dict:word2id:存儲(chǔ)單詞到詞典序號(hào)的映射。假設(shè)一個(gè)mini-batch如下所示:
['I am a boy.','How are you?','I am very lucky.']
顯然,這個(gè)mini-batch有3個(gè)句子,即batch_size=3
第一步首先要做的是:將句子標(biāo)準(zhǔn)化,所謂標(biāo)準(zhǔn)化,指的是:大寫(xiě)轉(zhuǎn)小寫(xiě),標(biāo)點(diǎn)分離,這部分很簡(jiǎn)單就略過(guò)。經(jīng)處理后,mini-batch變?yōu)椋?/p>
[['i','am','a','boy','.'],['how','are','you','?'],['i','am','very','lucky','.']]
可見(jiàn),這個(gè)list的元素成了一個(gè)個(gè)list。還要做一步:將上面的三個(gè)list按單詞數(shù)從多到少排列。標(biāo)點(diǎn)也算單詞。至于為什么,后面會(huì)說(shuō)到。
那就變成了:
batch = [['i','am','a','boy','.'],['i','am','very','lucky','.'],['how','are','you','?']]
可見(jiàn),每個(gè)句子的長(zhǎng)度,即每個(gè)內(nèi)層list的元素?cái)?shù)為:5,5,4。這個(gè)長(zhǎng)度也要記錄。
lens = [5,5,4]
之后,為了能夠處理,將batch的單詞表示轉(zhuǎn)為在詞典中的index序號(hào),這就是word2id的作用。轉(zhuǎn)換過(guò)程很簡(jiǎn)單,假設(shè)轉(zhuǎn)換之后的結(jié)果如下所示,當(dāng)然這些序號(hào)是我編的。
batch = [[3,6,5,6,7],[6,4,7,9,5],[4,5,8,7]]
同時(shí),每個(gè)句子結(jié)尾要加EOS,假設(shè)EOS在詞典中的index是1。
batch = [[3,6,5,6,7,1],[6,4,7,9,5,1],[4,5,8,7,1]]
那么長(zhǎng)度要更新:
lens = [6,6,5]
很顯然,這個(gè)mini-batch中的句子長(zhǎng)度不一致!所以為了規(guī)整的處理,對(duì)長(zhǎng)度不足的句子,進(jìn)行填充。填充PAD假設(shè)序號(hào)是2,填充之后為:
batch = [[3,6,5,6,7,1],[6,4,7,9,5,1],[4,5,8,7,1,2]]
這樣就可以直接取詞向量訓(xùn)練了嗎?
不能!上面batch有3個(gè)樣例,RNN的每一步要輸入每個(gè)樣例的一個(gè)單詞,一次輸入batch_size個(gè)樣例,所以batch要按list外層是時(shí)間步數(shù)(即序列長(zhǎng)度),list內(nèi)層是batch_size排列。即batch的維度應(yīng)該是:
[seq_len,batch_size]
[seq_len,batch_size]
[seq_len,batch_size]
重要的問(wèn)題說(shuō)3遍!
怎么變換呢?變換方法可以是:使用itertools模塊的zip_longest函數(shù)。而且,使用這個(gè)函數(shù),連填充這一步都可以省略,因?yàn)檫@個(gè)函數(shù)可以實(shí)現(xiàn)填充!
batch = list(itertools.zip_longest(batch,fillvalue=PAD))
# fillvalue就是要填充的值,強(qiáng)制轉(zhuǎn)成list
經(jīng)變換,結(jié)果應(yīng)該是:
batch = [[3,6,4],[6,4,5],[5,7,8],[6,9,7],[7,5,1],[1,1,2]]
記得我們還記錄了一個(gè)lens:
lens = [6,6,5]
batch還要轉(zhuǎn)成LongTensor:
batch=torch.LongTensor(batch)
這里的batch就是詞向量層的輸入。
詞向量層的輸出是什么樣的?
好了,現(xiàn)在使用建立了的embedding直接通過(guò)batch取詞向量了,如:
embed_batch = embed (batch)
假設(shè)詞向量維度是6,結(jié)果是:
tensor([[[-0.2699, 0.7401, -0.8000, 0.0472, 0.9032, -0.0902],
[-0.2675, 1.8021, 1.4966, 0.6988, 1.4770, 1.1235],
[ 0.1146, -0.8077, -1.4957, -1.5407, 0.3755, -0.6805]],
[[-0.2675, 1.8021, 1.4966, 0.6988, 1.4770, 1.1235],
[ 0.1146, -0.8077, -1.4957, -1.5407, 0.3755, -0.6805],
[-0.0387, 0.8401, 1.6871, 0.3057, -0.8248, -0.1326]],
[[-0.0387, 0.8401, 1.6871, 0.3057, -0.8248, -0.1326],
[-0.3745, -1.9178, -0.2928, 0.6510, 0.9621, -1.3871],
[-0.6739, 0.3931, 0.1464, 1.4965, -0.9210, -0.0995]],
[[-0.2675, 1.8021, 1.4966, 0.6988, 1.4770, 1.1235],
[-0.7411, 0.7948, -1.5864, 0.1176, 0.0789, -0.3376],
[-0.3745, -1.9178, -0.2928, 0.6510, 0.9621, -1.3871]],
[[-0.3745, -1.9178, -0.2928, 0.6510, 0.9621, -1.3871],
[-0.0387, 0.8401, 1.6871, 0.3057, -0.8248, -0.1326],
[ 0.2837, 0.5629, 1.0398, 2.0679, -1.0122, -0.2714]],
[[ 0.2837, 0.5629, 1.0398, 2.0679, -1.0122, -0.2714],
[ 0.2837, 0.5629, 1.0398, 2.0679, -1.0122, -0.2714],
[ 0.2242, -1.2474, 0.3882, 0.2814, -0.4796, 0.3732]]],
grad_fn=<EmbeddingBackward>)
維度的前兩維和前面講的是一致的??梢?jiàn)多了一個(gè)第三維,這就是詞向量維度。所以,Embedding層的輸出是:
[seq_len,batch_size,embedding_size]
一些注意的點(diǎn)
- nn.embedding的輸入只能是編號(hào),不能是隱藏變量,比如one-hot,或者其它,這種情況,可以自己建一個(gè)自定義維度的線性網(wǎng)絡(luò)層,參數(shù)訓(xùn)練可以單獨(dú)訓(xùn)練或者跟隨整個(gè)網(wǎng)絡(luò)一起訓(xùn)練(看實(shí)驗(yàn)需要)
- 如果你指定了padding_idx,注意這個(gè)padding_idx也是在num_embeddings尺寸內(nèi)的,比如符號(hào)總共有500個(gè),指定了padding_idx,那么num_embeddings應(yīng)該為501
- embedding_dim的選擇要注意,根據(jù)自己的符號(hào)數(shù)量,舉個(gè)例子,如果你的詞典尺寸是1024,那么極限壓縮(用二進(jìn)制表示)也需要10維,再考慮詞性之間的相關(guān)性,怎么也要在15-20維左右,雖然embedding是用來(lái)降維的,但是>- 也要注意這種極限維度,結(jié)合實(shí)際情況,合理定義
- 其他的好像也沒(méi)啥要注意的啦~,歡迎評(píng)論區(qū)補(bǔ)充(●′ω`●)