Tensorflow 对于一个只有10000个单词的字典,真正需要什么嵌入层输出?
我正在训练一个RNN,它有一组非常精简的单词特征,大约10000个。在添加RNN之前,我计划先从嵌入层开始,但我不清楚真正需要的维度是什么。我知道我可以尝试不同的值(32、64等),但我宁愿先有一些直觉。例如,如果我使用一个32维的嵌入向量,那么每个维度只需要3个不同的值来完整描述空间(Tensorflow 对于一个只有10000个单词的字典,真正需要什么嵌入层输出?,tensorflow,keras,deep-learning,word-embedding,Tensorflow,Keras,Deep Learning,Word Embedding,我正在训练一个RNN,它有一组非常精简的单词特征,大约10000个。在添加RNN之前,我计划先从嵌入层开始,但我不清楚真正需要的维度是什么。我知道我可以尝试不同的值(32、64等),但我宁愿先有一些直觉。例如,如果我使用一个32维的嵌入向量,那么每个维度只需要3个不同的值来完整描述空间(32**3>>10000) 或者,对于一个单词数量如此之少的空间,是否真的需要使用嵌入层,或者从输入层直接转到RNN更合理?这是一个没有好答案的好问题。您当然应该使用嵌入层,而不是直接使用LSTM/GRU。然而,
32**3>>10000
)
或者,对于一个单词数量如此之少的空间,是否真的需要使用嵌入层,或者从输入层直接转到RNN更合理?这是一个没有好答案的好问题。您当然应该使用嵌入层,而不是直接使用
LSTM/GRU
。然而,嵌入层的潜在维度应该“尽可能大,同时保持峰值验证性能”。对于一本和你差不多大小的字典,128或256应该是一个合理的选择。我怀疑你会看到完全不同的表现
然而,在一个小数据集上真正影响结果的事情是不使用预先训练好的单词嵌入。这将导致您的嵌入严重超出您的培训数据。我建议使用单词嵌入。下载手套数据后,您可以使用它们初始化嵌入层的权重,然后emebdding层将根据您的用例微调权重。下面是一些我用于Keras手套嵌入的代码。它可以让您加载不同大小的矩阵,还可以缓存矩阵,以便快速运行第二次
class GloVeSize(Enum):
tiny = 50
small = 100
medium = 200
large = 300
__DEFAULT_SIZE = GloVeSize.small
def get_pretrained_embedding_matrix(word_to_index,
vocab_size=10000,
glove_dir="./bin/GloVe",
use_cache_if_present=True,
cache_if_computed=True,
cache_dir='./bin/cache',
size=__DEFAULT_SIZE,
verbose=1):
"""
get pre-trained word embeddings from GloVe: https://github.com/stanfordnlp/GloVe
:param word_to_index: a word to index map of the corpus
:param vocab_size: the vocab size
:param glove_dir: the dir of glove
:param use_cache_if_present: whether to use a cached weight file if present
:param cache_if_computed: whether to cache the result if re-computed
:param cache_dir: the directory of the project's cache
:param size: an enumerated choice of GloVeSize
:param verbose: the verbosity level of logging
:return: a matrix of the embeddings
"""
def vprint(*args, with_arrow=True):
if verbose > 0:
if with_arrow:
print(">>", *args)
else:
print(*args)
if not os.path.exists(cache_dir):
os.makedirs(cache_dir)
cache_path = os.path.join(cache_dir, 'glove_%d_embedding_matrix.npy' % size.value)
if use_cache_if_present and os.path.isfile(cache_path):
return np.load(cache_path)
else:
vprint('computing embeddings', with_arrow=True)
embeddings_index = {}
size_value = size.value
f = open(os.path.join(glove_dir, 'glove.6B.' + str(size_value) + 'd.txt'),
encoding="ascii", errors='ignore')
for line in f:
values = line.split()
word = values[0]
coefs = np.asarray(values[1:], dtype='float32')
embeddings_index[word] = coefs
f.close()
vprint('Found', len(embeddings_index), 'word vectors.')
embedding_matrix = np.random.normal(size=(vocab_size, size.value))
non = 0
for word, index in word_to_index.items():
embedding_vector = embeddings_index.get(word)
if embedding_vector is not None:
embedding_matrix[index] = embedding_vector
else:
non += 1
vprint(non, "words did not have mappings")
vprint(with_arrow=False)
if cache_if_computed:
np.save(cache_path, embedding_matrix)
return embedding_matrix
然后用权重矩阵实例化嵌入层:
embedding_size = GloVeSize.small
embedding_matrix = get_pretrained_embedding_matrix(data.word_to_index,
size=embedding_size)
embedding = Embedding(
output_dim=self.embedding_size,
input_dim=self.vocabulary_size + 1,
input_length=self.input_length,
mask_zero=True,
weights=[np.vstack((np.zeros((1, self.embedding_size)),
self.embedding_matrix))],
name='embedding'
)(input_layer)
这是一个非常好的答案,我非常感谢您提供的代码。对于这个特殊的问题,我正在探索使用字符二元图而不是实际的单词,所以我不确定我是否会有过拟合的问题。但是为了好玩,我还打算尝试一个预先训练好的单词向量,所以当我谈到这个问题时,你的回答会非常有用。:-)