爲什麼共享圖層後,輸出向量的形狀還不一樣
# 這一層可以輸入一個矩陣,並返回一個 64 維的向量
shared_lstm = LSTM(64)
# 當我們重用相同的圖層實例多次,圖層的權重也會被重用 (它其實就是同一層)
encoded_a = shared_lstm(tweet_a)
encoded_b = shared_lstm(tweet_b)
這裏重用了shared_lstm 層,但是如果要我們獲取輸出形狀時,有文章指出圖層的權重是一樣的,但是輸出形狀不一樣,這裏不太理解
assert shared_lstm.get_output_at(0) == encoded_a
assert shared_lstm.get_output_at(1) == encoded_b
雖然我們可以通過shared_lstm 的方法來獲取圖層,但是我不太理解,我的理解是輸出已經定義好了,所有的輸入的輸出都是一樣的,寫個代碼可以瞭解一下。
a = Input(shape=(280, 128))
b = Input(shape=(250, 128))
lstm = LSTM(32)
encoded_a = lstm(a)
encoded_b = lstm(b)
print(lstm.get_input_shape_at(0))
print(lstm.get_input_shape_at(1))
print(lstm.get_output_shape_at(0))
print(lstm.get_output_shape_at(1))
輸出結果:
(None, 280, 128)
(None, 250, 128)
(None, 32)
(None, 32)
其中如果a、b的input中,shape的後一維向量不一樣就會報錯,根據矩陣運算來說,後一維矩陣關係到後一個向量的行維數,如果不同,則兩次輸入得到的向量維數都是不一樣的,這是我的理解,也不知道對不對,
疑問:
- 1、如果兩次調用通一個層,同一個輸入維數,用的是也是兩個層,那麼權重怎麼共享?
- 2、對這個共享還是不太理解,我覺得共享就是權重也是共享的,這個權重對於同一個維數的輸入來說應該是一樣的。
Embedding層和Input層有啥區別
這兩個層都是作爲網絡模型的第一層,當然模型也可以不用這個層,所以我就很奇怪,這兩個層作爲第一層的作用是什麼?他們之間有什麼區別?
Input層 很多資料就說實例化一個keras張量,如下:
x = Input(shape=(32,))
明顯很多layers的輸出都是返回一個向量,
Embedding層:嵌入層將正整數(下標)轉換爲具有固定大小的向量,如[[4],[20]]->[[0.25,0.1],[0.6,-0.2]]
是不是很奇怪,這個怎麼轉換的?其實這裏的embeding 是詞向量化,但我不清楚 是不是用的word2vec,但大概是用的skip-word算法來構建的,將輸入作爲語料集,一定長度的窗口來滑動,訓練模型從而得到指定長度的輸出詞的相似性,輸出的是相關性較高的詞的概率,一共有窗口大小的長度,
如果輸入數據不需要詞的語義特徵語義,簡單使用Embedding層就可以得到一個對應的詞向量矩陣,但如果需要語義特徵,我們大可把訓練好的詞向量權重直接扔到Embedding層中即可
大家可以看下這個定義:
keras.layers.Embedding(input_dim, output_dim, embeddings_initializer='uniform', embeddings_regularizer=None, activity_regularizer=None, embeddings_constraint=None, mask_zero=False, input_length=None)
- input_dim: int > 0。詞彙表大小, 即最大整數 index + 1,類似語料集分詞後詞彙大小。
- output_dim: int >= 0。詞向量的維度。
- input_length: 輸入序列的長度,當它是固定的時。 如果你需要連接 Flatten 和 Dense 層,則這個參數是必須的 (沒有它,dense 層的輸出尺寸就無法計算)
model = Sequential()
model.add(Embedding(4, 5, input_length=7))
model.compile('rmsprop','mse')
model.predict(np.array([[0,1,0,1,1,0,3]]))
輸出結果:
array([[[-0.03462106, 0.01587335, -0.04886673, 0.01961641,
0.01314208],
[ 0.02410911, -0.03580334, 0.02348015, 0.02070605,
0.01584761],
[-0.03462106, 0.01587335, -0.04886673, 0.01961641,
0.01314208],
[ 0.02410911, -0.03580334, 0.02348015, 0.02070605,
0.01584761],
[ 0.02410911, -0.03580334, 0.02348015, 0.02070605,
0.01584761],
[-0.03462106, 0.01587335, -0.04886673, 0.01961641,
0.01314208],
[ 0.00639332, -0.03460374, 0.01854259, 0.02507687,
0.03259133]]], dtype=float32)
參數分析:
- 4:3+1,一共有3個詞彙,0、1、3
- 5:詞向量的維度
- 7:輸入的長度
具體可以看下參考博客。
dot()
全稱是 tf.keras.backend.dot,表示兩個矩陣相乘得到一個新的矩陣。
# dot product between tensors
>>> x = K.placeholder(shape=(2, 3))
>>> y = K.placeholder(shape=(3, 4))
>>> xy = K.dot(x, y)
>>> xy
<tf.Tensor 'MatMul_9:0' shape=(2, 4) dtype=float32>
不過這些都是隻有形狀,也就是說並不知道這個矩陣的具體值是多少,可能跟我們線性代數裏的具體的矩陣不太一樣,畢竟這裏只是定義這麼一個相乘的操作。
Model類與Layer的區別
這裏的Layer包括我們自己定義的Layer Class。通常,我們使用Layer類來定義內部計算塊,並使用Model類來定義外部模型 - 即要訓練的對象。
Model類與Layer的區別:
它公開了內置的訓練,評估和預測循環(model.fit(),model.evaluate(),model.predict())。
它通過model.layers屬性公開其內層列表。
它公開了保存和序列化API。