python - 如果输入值大于 input_dim,keras 嵌入层如何工作?
问题描述
如果输入值大于 input_dim,嵌入层如何工作?
为什么keras不会引发异常?
from keras.models import Sequential
from keras.layers import Embedding
model = Sequential()
model.add(Embedding(1, 2, trainable=True, mask_zero=False))
input_array = [5]
model.compile("rmsprop", "mse")
output_array = model.predict(input_array)
outpur_array
#array([[[0., 0.]]], dtype=float32)
输入值 = 5 input_dim = 1
文档说输入值(5)必须小于 input_dim(1)。在我的示例中它是错误的,但代码仍然没有引发异常
谢谢!
解决方案
嵌入层使用形状为 (input_dim, output_dim) 的查找矩阵。其中输入要学习的暗号嵌入向量。当我传递索引时,图层通过嵌入矩阵中的索引获取向量。
感谢您指出我对 input_length 和 input_dim 感到困惑。
首先,如果使用 tensorflow.keras 会报错。
张量流
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Embedding, Input
import numpy as np
ip = Input(shape = (3,))
emb = Embedding(1, 2, trainable=True, mask_zero=True)(ip)
model = Model(ip, emb)
input_array = np.array([[5, 3, 1], [1, 2, 3]])
model.compile("rmsprop", "mse")
output_array = model.predict(input_array)
print(output_array)
print(output_array.shape)
model.summary()
但是如果我使用 keras 2.3.1,我不会收到任何错误。
喀拉拉邦 2.3.1
from keras.models import Model
from keras.layers import Embedding, Input
import numpy as np
ip = Input(shape = (3,))
emb = Embedding(1, 2, trainable=True, mask_zero=True)(ip)
model = Model(ip, emb)
input_array = np.array([[5, 3, 1], [1, 2, 3]])
model.compile("rmsprop", "mse")
output_array = model.predict(input_array)
print(output_array)
print(output_array.shape)
model.summary()
那么,keras 坏了吗?首先要注意的是 keras 和 tensorflow.keras 对嵌入层有不同的实现。为了验证这一点,让我们去 keras 嵌入层。
https://github.com/keras-team/keras/blob/master/keras/layers/embeddings.py#L16
现在让我们看看调用函数。
def call(self, inputs):
if K.dtype(inputs) != 'int32':
inputs = K.cast(inputs, 'int32')
out = K.gather(self.embeddings, inputs)
return out
注意:如果您想要 keras 2.3.1 的确切源代码,请访问此处并下载源代码:https ://github.com/keras-team/keras/releases
但是如果我们去实现 tensorflow,那就不一样了。
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/ops/embedding_ops.py
只是为了验证一下,调用函数的写法不同。
def call(self, inputs):
dtype = K.dtype(inputs)
if dtype != 'int32' and dtype != 'int64':
inputs = math_ops.cast(inputs, 'int32')
out = embedding_ops.embedding_lookup(self.embeddings, inputs)
return out
现在,我们可以更深入地挖掘不同的行为并查明 keras 不会引发错误而 tensorflow.keras 会引发错误的来源,但让我们简单说明一下。keras嵌入层做错了吗?
让我们像以前一样设计一个简单的网络并观察权重矩阵。
from keras.models import Model
from keras.layers import Embedding, Input
import numpy as np
ip = Input(shape = (3,))
emb = Embedding(1, 2, trainable=True, mask_zero=True)(ip)
model = Model(ip, emb)
input_array = np.array([[5, 3, 1], [1, 2, 3]])
model.compile("rmsprop", "mse")
output_array = model.predict(input_array)
print(output_array)
print(output_array.shape)
model.summary()
该模型给出以下输出。
[[[0. 0.]
[0. 0.]
[0. 0.]]
[[0. 0.]
[0. 0.]
[0. 0.]]]
(2, 3, 2)
Model: "model_18"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_21 (InputLayer) (None, 3) 0
_________________________________________________________________
embedding_33 (Embedding) (None, 3, 2) 2
=================================================================
Total params: 2
Trainable params: 2
Non-trainable params: 0
好的,我们得到了一堆零,但默认的 weight_initializer 不是零!
所以,现在让我们观察一下权重矩阵。
import keras.backend as K
w = model.layers[1].get_weights()
print(w)
[array([[ 0.03680499, -0.04904002]], dtype=float32)]
事实上,它并非全为零。
那么,为什么我们会得到零呢?
让我们更改对模型的输入。
由于 input_dim = 1 的词汇表中唯一的词索引为 0。让我们将 0 作为输入之一传递。
from keras.models import Model
from keras.layers import Embedding, Input
import numpy as np
ip = Input(shape = (3,))
emb = Embedding(1, 2, trainable=True, mask_zero=True)(ip)
model = Model(ip, emb)
input_array = np.array([[5, 0, 1], [1, 2, 0]])
model.compile("rmsprop", "mse")
output_array = model.predict(input_array)
print(output_array)
print(output_array.shape)
model.summary()
现在,我们得到了我们通过 0 的位置的非零向量。
[[[ 0. 0. ]
[-0.04339869 -0.04900574]
[ 0. 0. ]]
[[ 0. 0. ]
[ 0. 0. ]
[-0.04339869 -0.04900574]]]
(2, 3, 2)
Model: "model_19"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_22 (InputLayer) (None, 3) 0
_________________________________________________________________
embedding_34 (Embedding) (None, 3, 2) 2
=================================================================
Total params: 2
Trainable params: 2
Non-trainable params: 0
简而言之,Keras 使用零向量映射任何词汇表外的词索引,这是合理的,因为对于那些位置,前向传递将确保所有贡献都是 NIL(尽管偏差可能会起作用)。这有点违反直觉,因为将词汇标记传递给模型似乎是一种开销(而不仅仅是在预处理步骤中删除它们)和不好的做法。
教训将是完全避免 Keras 并转向 tensorflow.keras,因为他们清楚地提到在 2.2 版本之后将有更少的支持和小错误修复。
keras github repo 的相关问题:https ://github.com/keras-team/keras/issues/13989
推荐阅读
- python - 美汤中的进一步提炼清单
- c++ - 在 Visual Studio 2017 中使用函数从 main 创建和初始化数组
- deep-learning - 可变错误 O'Reilly 编程 PyTorch
- ag-grid-angular - 无法读取未定义的属性“setRowData”/HTML 模板问题?
- java - 如何通过android java发送google pay“请求”,如amazon bhim pay在线支付
- selenium - 如何确保在量角器测试中打开了一个新窗口
- snowflake-cloud-data-platform - 关于在 Snowflake 中的函数内嵌套多个函数的问题
- python - 为文本创建装饰牌匾
- javascript - 使用 onkeypress 事件验证两个输入字段
- vue.js - vue js,IE9点击路由器链接刷新?