嵌入(embedding)層的理解

首先,我們有一個one-hot編碼的概念。

 

假設,我們中文,一共只有10個字。。。只是假設啊,那麼我們用0-9就可以表示完

比如,這十個字就是“我從哪裏來,要到何處去”

其分別對應“0-9”,如下:

我  從  哪  裏  來  要  到  何  處  去

0    1    2    3   4    5   6    7    8   9

那麼,其實我們只用一個列表就能表示所有的對話

如:我  從  哪  裏  來  要  到  何  處  去  ——>>>[0 1 2 3 4 5 6 7 8 9]

或:我  從  何  處  來  要  到  哪  裏  去  ——>>>[0 1 7 8 4 5 6 2 3 9]

 

但是,我們看看one-hot編碼方式(詳見:https://blog.csdn.net/tengyuan93/article/details/78930285)

他把上面的編碼方式弄成這樣

# 我從哪裏來,要到何處去
[
[1 0 0 0 0 0 0 0 0 0]
[0 1 0 0 0 0 0 0 0 0]
[0 0 1 0 0 0 0 0 0 0]
[0 0 0 1 0 0 0 0 0 0]
[0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0]
[0 0 0 0 0 0 1 0 0 0]
[0 0 0 0 0 0 0 1 0 0]
[0 0 0 0 0 0 0 0 1 0]
[0 0 0 0 0 0 0 0 0 1]
]

# 我從何處來,要到哪裏去
[
[1 0 0 0 0 0 0 0 0 0]
[0 1 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 1 0]
[0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 1 0 0 0 0]
[0 0 0 0 0 0 1 0 0 0]
[0 0 1 0 0 0 0 0 0 0]
[0 0 0 1 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 1]
]
即:把每一個字都對應成一個十個(樣本總數/字總數)元素的數組/列表,其中每一個字都用唯一對應的數組/列表對應,數組/列表的唯一性用1表示。如上,“我”表示成[1。。。。],“去”表示成[。。。。1],這樣就把每一系列的文本整合成一個稀疏矩陣。

 

那問題來了,稀疏矩陣(二維)和列表(一維)相比,有什麼優勢。

很明顯,計算簡單嘛,稀疏矩陣做矩陣計算的時候,只需要把1對應位置的數相乘求和就行,也許你心算都能算出來;而一維列表,你能很快算出來?何況這個列表還是一行,如果是100行、1000行和或1000列呢?

所以,one-hot編碼的優勢就體現出來了,計算方便快捷、表達能力強。

然而,缺點也隨着來了。

比如:中文大大小小簡體繁體常用不常用有十幾萬,然後一篇文章100W字,你要表示成100W X 10W的矩陣???

這是它最明顯的缺點。過於稀疏時,過度佔用資源。

比如:其實我們這篇文章,雖然100W字,但是其實我們整合起來,有99W字是重複的,只有1W字是完全不重複的。那我們用100W X 10W的豈不是白白浪費了99W X 10W的矩陣存儲空間。

那怎麼辦???

這時,Embedding層橫空出世。

接下來給大家看一張圖

 

假設:我們有一個2 x 6的矩陣,然後乘上一個6 x 3的矩陣後,變成了一個2 x 3的矩陣。

先不管它什麼意思,這個過程,我們把一個12個元素的矩陣變成6個元素的矩陣,直觀上,大小是不是縮小了一半?

也許你已經想到了!!!對!!!不管你想的對不對,但是embedding層,在某種程度上,就是用來降維的,降維的原理就是矩陣乘法。在卷積網絡中,可以理解爲特殊全連接層操作,跟1x1卷積核異曲同工!!!484很神奇!!!

也就是說,假如我們有一個100W X10W的矩陣,用它乘上一個10W X 20的矩陣,我們可以把它降到100W X 20,瞬間量級降了。。。10W/20=5000倍!!!

這就是嵌入層的一個作用——降維。

然後中間那個10W X 20的矩陣,可以理解爲查詢表,也可以理解爲映射表,也可以理解爲過度表,whatever。

接着,既然可以降維,當然也可以升維。爲什麼要升維?
 

 

這張圖,我要你在10米開外找出五處不同!。。。What?煩請出題者走近兩步,我先把我的刀拿出來,您再說一遍題目我沒聽清。

當然,目測這是不可能完成的。但是我讓你在一米外,也許你一瞬間就發現衣服上有個心是不同的,然後再走近半米,你又發現左上角和右上角也是不同的。再走近20釐米,又發現耳朵也不同,最後,在距離屏幕10釐米的地方,終於發現第五個不同的地方在耳朵下面一點的雲。

但是,其實無限靠近並不代表認知度就高了,比如,你只能距離屏幕1釐米遠的地方找,找出五處不同。。。出題人你是不是腦袋被門擠了。。。

由此可見,距離的遠近會影響我們的觀察效果。同理也是一樣的,低維的數據可能包含的特徵是非常籠統的,我們需要不停地拉近拉遠來改變我們的感受野,讓我們對這幅圖有不同的觀察點,找出我們要的茬。

embedding的又一個作用體現了。對低維的數據進行升維時,可能把一些其他特徵給放大了,或者把籠統的特徵給分開了。同時,這個embedding是一直在學習在優化的,就使得整個拉近拉遠的過程慢慢形成一個良好的觀察點。比如:我來回靠近和遠離屏幕,發現45釐米是最佳觀測點,這個距離能10秒就把5個不同點找出來了。

 

回想一下爲什麼CNN層數越深準確率越高,卷積層捲了又卷,池化層池了又升,升了又降,全連接層連了又連。因爲我們也不知道它什麼時候突然就學到了某個有用特徵。但是不管怎樣,學習都是好事,所以讓機器多捲一捲,多連一連,反正錯了多少我會用交叉熵告訴你,怎麼做纔是對的我會用梯度下降算法告訴你,只要給你時間,你遲早會學懂。因此,理論上,只要層數深,只要參數足夠,NN能擬合任何特徵。總之,它類似於虛擬出一個關係對當前數據進行映射。這個東西也許一言難盡吧,但是目前各位只需要知道它有這些功能的就行了。

 

接下來,繼續假設我們有一句話,叫“公主很漂亮”,如果我們使用one-hot編碼,可能得到的編碼如下:

公 [0 0 0 0 1]
主 [0 0 0 1 0]
很 [0 0 1 0 0]
漂 [0 1 0 0 0]
亮 [1 0 0 0 0]
乍一眼看過似乎沒毛病,其實本來人家也沒毛病,或者假設咱們的詞袋更大一些

公 [0 0 0 0 1 0 0 0 0 0]
主 [0 0 0 1 0 0 0 0 0 0]
很 [0 0 1 0 0 0 0 0 0 0]
漂 [0 1 0 0 0 0 0 0 0 0]
亮 [1 0 0 0 0 0 0 0 0 0]
假設吧,就假設咱們的詞袋一共就10個字,則這一句話的編碼如上所示。

這樣的編碼,最大的好處就是,不管你是什麼字,我們都能在一個一維的數組裏用01給你表示出來。並且不同的字絕對不一樣,以致於一點重複都沒有,表達本徵的能力極強。

但是,因爲其完全獨立,其劣勢就出來了。表達關聯特徵的能力幾乎爲0!!!

我給你舉個例子,我們又有一句話“王妃很漂亮”

那麼在這基礎上,我們可以把這句話表示爲

王 [0 0 0 0 0 0 0 0 0 1]
妃 [0 0 0 0 0 0 0 0 1 0]
很 [0 0 1 0 0 0 0 0 0 0]
漂 [0 1 0 0 0 0 0 0 0 0]
亮 [1 0 0 0 0 0 0 0 0 0]
從中文表示來看,我們一下就跟感覺到,王妃跟公主其實是有很大關係的,比如:公主是皇帝的女兒,王妃是皇帝的妃子,可以從“皇帝”這個詞進行關聯上;公主住在宮裏,王妃住在宮裏,可以從“宮裏”這個詞關聯上;公主是女的,王妃也是女的,可以從“女”這個字關聯上。

但是呢,我們用了one-hot編碼,公主和王妃就變成了這樣:

公 [0 0 0 0 1 0 0 0 0 0]
主 [0 0 0 1 0 0 0 0 0 0]
王 [0 0 0 0 0 0 0 0 0 1]
妃 [0 0 0 0 0 0 0 0 1 0]
你說,你要是不看前面的中文註解,你知道這四行向量有什麼內部關係嗎?看不出來,那怎麼辦?

既然,通過剛纔的假設關聯,我們關聯出了“皇帝”、“宮裏”和“女”三個詞,那我們嘗試這麼去定義公主和王妃

公主一定是皇帝的女兒,我們假設她跟皇帝的關係相似度爲1.0;公主從一出生就住在宮裏,直到20歲才嫁到府上,活了80歲,我們假設她跟宮裏的關係相似度爲0.25;公主一定是女的,跟女的關係相似度爲1.0;

王妃是皇帝的妃子,沒有親緣關係,但是有存在着某種關係,我們就假設她跟皇帝的關係相似度爲0.6吧;妃子從20歲就住在宮裏,活了80歲,我們假設她跟宮裏的關係相似度爲0.75;王妃一定是女的,跟女的關係相似度爲1.0;

於是公主王妃四個字我們可以這麼表示:

皇 宮
帝 裏 女
公主 [ 1.0 0.25 1.0]
王妃 [ 0.6 0.75 1.0]
這樣我們就把公主和王妃兩個詞,跟皇帝、宮裏、女這幾個字(特徵)關聯起來了,我們可以認爲:

公主=1.0 *皇帝 +0.25*宮裏 +1.0*女

王妃=0.6 *皇帝 +0.75*宮裏 +1.0*女

或者這樣,我們假設沒歌詞的每個字都是對等(注意:只是假設,爲了方便解釋):

皇 宮
帝 裏 女
公 [ 0.5 0.125 0.5]
主 [ 0.5 0.125 0.5]
王 [ 0.3 0.375 0.5]
妃 [ 0.3 0.375 0.5]
這樣,我們就把一些詞甚至一個字,用三個特徵給表徵出來了。然後,我們把皇帝叫做特徵(1),宮裏叫做特徵(2),女叫做特徵(3),於是乎,我們就得出了公主和王妃的隱含特徵關係:

王妃=公主的特徵(1) * 0.6 +公主的特徵(2) * 3 +公主的特徵(3) * 1

於是乎,我們把文字的one-hot編碼,從稀疏態變成了密集態,並且讓相互獨立向量變成了有內在聯繫的關係向量。

 

所以,embedding層做了個什麼呢?它把我們的稀疏矩陣,通過一些線性變換(在CNN中用全連接層進行轉換,也稱爲查表操作),變成了一個密集矩陣,這個密集矩陣用了N(例子中N=3)個特徵來表徵所有的文字,在這個密集矩陣中,表象上代表着密集矩陣跟單個字的一一對應關係,實際上還蘊含了大量的字與字之間,詞與詞之間甚至句子與句子之間的內在關係(如:我們得出的王妃跟公主的關係)。他們之間的關係,用的是嵌入層學習來的參數進行表徵。從稀疏矩陣到密集矩陣的過程,叫做embedding,很多人也把它叫做查表,因爲他們之間也是一個一一映射的關係。

更重要的是,這種關係在反向傳播的過程中,是一直在更新的,因此能在多次epoch後,使得這個關係變成相對成熟,即:正確的表達整個語義以及各個語句之間的關係。這個成熟的關係,就是embedding層的所有權重參數。

Embedding是NPL領域最重要的發明之一,他把獨立的向量一下子就關聯起來了。這就相當於什麼呢,相當於你是你爸的兒子,你爸是A的同事,B是A的兒子,似乎跟你是八竿子纔打得着的關係。結果你一看B,是你的同桌。Embedding層就是用來發現這個祕密的武器。

 

 

原文:https://blog.csdn.net/weixin_42078618/article/details/84553940

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章