Tensorflow 嵌入层词汇量大小
Tensorflow Embedding Layer Vocabulary Size
我正在学习Tensorflow,遇到了tensorflow中的Embedding层,用来学习自己的word embeddings。该层采用以下参数:
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' 应该与词汇表大小相同,即独特的单词。如果我想将词汇量限制在前 25000 个最常用的单词——我应该怎么做?
我可以简单地将 'input_dim' 更改为 25000,还是我必须检查我的语料库并将前 25000 个单词之外的任何单词替换为标记?
实际上,如果你使用tensorflow.keras
,你必须确保在你的语料库中,标记不超过嵌入层的vocabulary_size或input_dim
,否则你'会出错。
如果您使用 keras
,那么您只需更改嵌入层中的 input_dim
,而无需更改语料库或标记中的任何内容。 keras
将用 zero
向量替换词汇表中的标记。
首先,如果使用tensorflow.keras会出错。
tensorflow
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]]) # out of vocabulary
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 嵌入层。
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
N.B:如果您想要 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
让我们像以前一样设计一个简单的网络并观察权重矩阵。
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(尽管偏差可能起作用)。这有点违反直觉,因为将词汇标记传递给模型似乎是一种开销(而不是仅仅在预处理步骤中删除它们)和不好的做法,但它是测试不同 input_dim
的一个很好的解决方法无需重新计算令牌。
我正在学习Tensorflow,遇到了tensorflow中的Embedding层,用来学习自己的word embeddings。该层采用以下参数:
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' 应该与词汇表大小相同,即独特的单词。如果我想将词汇量限制在前 25000 个最常用的单词——我应该怎么做?
我可以简单地将 'input_dim' 更改为 25000,还是我必须检查我的语料库并将前 25000 个单词之外的任何单词替换为标记?
实际上,如果你使用tensorflow.keras
,你必须确保在你的语料库中,标记不超过嵌入层的vocabulary_size或input_dim
,否则你'会出错。
如果您使用 keras
,那么您只需更改嵌入层中的 input_dim
,而无需更改语料库或标记中的任何内容。 keras
将用 zero
向量替换词汇表中的标记。
首先,如果使用tensorflow.keras会出错。
tensorflow
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]]) # out of vocabulary
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 嵌入层。
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
N.B:如果您想要 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
让我们像以前一样设计一个简单的网络并观察权重矩阵。
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(尽管偏差可能起作用)。这有点违反直觉,因为将词汇标记传递给模型似乎是一种开销(而不是仅仅在预处理步骤中删除它们)和不好的做法,但它是测试不同 input_dim
的一个很好的解决方法无需重新计算令牌。