Keras深度學習——從零開始構建單詞向量
theme: hydrogen
持續創作,加速成長!這是我參與「掘金日新計劃 · 6 月更文挑戰」的第28天,點選檢視活動詳情
構建單詞向量
構建單詞向量的核心思想是,在向量空間中,每個單詞周圍都存在著與之相似的單詞。例如:“queen
” 和 “princess
” 單詞的周圍會出現類似的詞,如 “kingdom
”。從某種意義上說,這些詞的上下文同樣是相似的。
使用句子 “I love watching movie
” 和 “I like watching movie
”,當我們一個句子中的某個單詞作為輸出,而句子中的其餘單詞作為輸入時,可以構造以下資料集:
輸入 | 輸出 | ||
---|---|---|---|
love | watching | movie | I |
I | watching | movie | love |
I | love | movie | watching |
I | love | watching | movie |
like | watching | movie | I |
I | watching | movie | like |
I | like | movie | watching |
I | like | watching | movie |
當我們將某一個單詞用作輸出,其餘單詞用作輸入,將輸入和輸出進行獨熱編碼後得到以下形式的向量:
輸入向量 | 輸出向量 | ||||||||
---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 |
1 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 |
1 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 |
1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 |
1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |
可以看到,輸入向量的第一行為 {0, 1, 1, 1, 0}
,因為輸入單詞的索引為 {1, 2, 3}
,輸出為 {1, 0, 0, 0, 0}
,因為輸出單詞的索引為 {0}
。
如果我們使用的神經網路中隱藏層包含三個神經元,則神經網路架構如下所示:
網路中每層的資訊如下:
|網路層| 尺寸| 描述
|--|--|--|
|輸入層| 5
|每個輸入向量尺寸為 5
|輸入層權重 |5x3
| 隱藏層中的 3
個神經元各有 5
個連線到輸入層的權重
|隱藏層 |3
|隱藏層包含 3
個神經元
|輸出層權重 |3x5
| 由於有 5
個不同單詞,因此 3
個隱藏單元輸出對映到輸出層的 5
個輸出
|輸出層 |5
| 輸出向量的尺寸為 5
,每一單詞對應一個預測單詞概率
在構建單詞向量時,在隱藏層中並不使用啟用函式。使用 softmax
函式處理輸出層輸出值,以便得到單詞概率,使用交叉熵損失作為損失函式,使用 Adam
優化器優化網路權重值。當向網路中輸入單詞(而非輸入語句)的獨熱編碼時,給定單詞的編碼向量可以使用隱藏層的輸出值表示。
從零開始構建單詞向量
根據我們在上一節中介紹的單詞向量的生成方式,我們使用 Keras
實現單詞編碼向量神經網路。
首先,定義輸入句子:
python
docs = ["I love watching movie", "I like watching movie"]
在以上語句中,我們期望 love
和 like
的詞向量是相似的,因為 love
和 like
的上下文是完全相同的。
然後,我們為每個句子建立一個獨熱編碼:
python
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer(min_df=0, token_pattern=r"\b\w+\b")
vectorizer.fit(docs)
vectorizer
定義了將文件轉換為向量格式的引數。此外,通過傳遞引數 min_df
確保在 CountVectorizer
中不會過濾掉諸如 I
之類的詞,使用定義的輸入句子擬合 vectorizer
得到合適的單詞向量化模型。
將文件 docs
轉換為向量格式:
python
vector = vectorizer.transform(docs)
驗證執行轉換後的語句向量:
python
print(vectorizer.vocabulary_)
print(vector.shape)
print(vector.toarray())
vocabulary_
返回各種單詞的索引,而 vector.toarray
將返回句子的獨熱編碼,輸出結果如下:
shell
{'i': 0, 'love': 2, 'watching': 4, 'movie': 3, 'like': 1}
(2, 5)
[[1 0 1 1 1]
[1 1 0 1 1]]
建立輸入和輸出資料集:
```python
x = []
y = []
for i in range(len(docs)):
for j in range(len(docs[i].split())):
t_x = []
t_y = []
for k in range(4):
if(j==k):
t_y.append(docs[i].split()[k])
continue
else:
t_x.append(docs[i].split()[k])
x.append(t_x)
y.append(t_y)
x2 = []
y2 = []
for i in range(len(x)):
x2.append(' '.join(x[i]))
y2.append(' '.join(y[i]))
從前面的程式碼中,我們建立了輸入和輸出資料集,我們可以列印資料集,檢視其內容:
python
print(x2)
print(y2)
列印粗的輸入和輸出資料如下:
python
['love watching movie', 'I watching movie', 'I love movie', 'I love watching', 'like watching movie', 'I watching movie', 'I like movie', 'I like watching']
['I', 'love', 'watching', 'movie', 'I', 'like', 'watching', 'movie']
將前面的輸入和輸出單詞轉換為向量:
python
vector_x = vectorizer.transform(x2)
vector_y = vectorizer.transform(y2)
vector_x = vector_x.toarray() vector_y = vector_y.toarray()
列印輸入與輸出陣列
print('Input: ', vector_x)
print('Output: ' vector_y)
打印出的輸入和輸出陣列如下:
python
Input: [[0 0 1 1 1]
[1 0 0 1 1]
[1 0 1 1 0]
[1 0 1 0 1]
[0 1 0 1 1]
[1 0 0 1 1]
[1 1 0 1 0]
[1 1 0 0 1]]
Output: [[1 0 0 0 0]
[0 0 1 0 0]
[0 0 0 0 1]
[0 0 0 1 0]
[1 0 0 0 0]
[0 1 0 0 0]
[0 0 0 0 1]
[0 0 0 1 0]]
根據定義的神經網路,構建模型:
python
from keras.layers import Dense
from keras.models import Sequential
model = Sequential()
model.add(Dense(3, input_shape=(5,)))
model.add(Dense(5,activation='sigmoid'))
model.summary()
模型簡要架構資訊輸入如下:
shell
Model: "sequential"
Layer (type) Output Shape Param #
dense (Dense) (None, 3) 18
dense_1 (Dense) (None, 5) 20
Total params: 38 Trainable params: 38 Non-trainable params: 0
編譯並擬合模型:
python
model.compile(loss='categorical_crossentropy',optimizer='adam')
model.fit(vector_x, vector_y, epochs=1000, batch_size=2,verbose=1)
通過獲取中間層值來提取詞向量,其中輸入是每個單個詞的編碼向量:
python
from keras.models import Model
layer_name = 'dense'
intermediate_layer_model = Model(inputs=model.input,outputs=model.get_layer(layer_name).output)
在以上程式碼中,我們從目標層中提取輸出——通過模型中的名為 `dense` 的層獲取單詞編碼向量。
接下來,向網路中傳遞單詞的獨熱編碼向量作為輸入,提取中間層的輸出:
python
for i in range(len(vectorizer.vocabulary_)):
word = list(vectorizer.vocabulary_.keys())[i]
word_vec = vectorizer.transform([list(vectorizer.vocabulary_.keys())[i]]).toarray()
print(word, intermediate_layer_model.predict(word_vec))
各個單詞的編碼向量如下:
shell
i [[-1.41066 0.02432728 -1.0654368 ]]
love [[-1.1692711 1.7719828 0.54331756]]
watching [[ 1.163808 1.908086 -1.5191256]]
movie [[0.01165223 2.0688105 1.532387 ]]
like [[-1.197992 1.662775 0.5817174]]
``
可以看出,在以上單詞編碼向量中,“
love” 和 “
like`” 這兩個單詞之間的相關性更高,因此可以更好地表示單詞向量。
- Python 常用字串操作
- 使用 dlib 進行人臉識別
- OpenCV 人臉檢測詳解(僅需2行程式碼學會人臉檢測)
- Keras深度學習——使用fastText構建單詞向量
- Keras深度學習——使用skip-gram和CBOW模型構建單詞向量
- Keras深度學習——從零開始構建單詞向量
- Keras深度學習——生成對抗網路
- Keras深度學習——建立自定義目標檢測資料集
- PyTorch強化學習——基於值迭代的強化學習演算法
- PyTorch強化學習——模擬FrozenLake環境
- PyTorch強化學習——策略評估
- PyTorch強化學習——馬爾科夫決策過程
- Keras深度學習——DeepDream演算法生成影象
- Keras深度學習——使用對抗攻擊生成可欺騙神經網路的影象
- PyTorch強化學習——策略梯度演算法
- Keras深度學習——交通標誌識別
- Keras深度學習——面部特徵點檢測
- Keras深度學習——基於Inception v3實現性別分類
- Keras深度學習——視覺化神經網路中間層輸出
- Keras深度學習——使用預訓練VGG16模型實現性別分類