词嵌入提供了词语及其相对含义的密集表示。
它们是对简单词袋模型表示中使用的稀疏表示的改进。
词嵌入可以从文本数据中学习,并在项目之间重用。它们也可以作为拟合文本数据神经网络的一部分来学习。
在本教程中,您将学习如何在 Python 中使用 Keras 进行深度学习时使用词嵌入。
完成本教程后,您将了解:
- 关于词嵌入以及 Keras 通过嵌入层支持词嵌入。
- 如何在拟合神经网络时学习词嵌入。
- 如何在神经网络中使用预训练的词嵌入。
通过我的新书《自然语言处理深度学习》启动您的项目,包括分步教程和所有示例的 Python 源代码文件。
让我们开始吧。
- 2018年2月更新:修复了由于底层 API 更改导致的错误。
- 2019 年 10 月更新:更新至 Keras 2.3 和 TensorFlow 2.0。

如何使用 Keras 的词嵌入层进行深度学习
图片由此人提供,保留部分权利。
教程概述
本教程分为3个部分;它们是
- 词嵌入
- Keras 嵌入层
- 学习嵌入的示例
- 使用预训练 GloVe 嵌入的示例
需要深度学习处理文本数据的帮助吗?
立即参加我的免费7天电子邮件速成课程(附代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
1. 词嵌入
词嵌入是一类使用密集向量表示来表示词语和文档的方法。
它比传统的词袋模型编码方案有所改进,传统的方案使用大型稀疏向量来表示每个词,或者在向量中对每个词进行评分以表示整个词汇表。这些表示是稀疏的,因为词汇量庞大,给定的词或文档将由一个大部分由零值组成的大型向量表示。
相反,在嵌入中,词语由密集向量表示,其中向量表示词语在连续向量空间中的投影。
词语在向量空间中的位置是从文本中学习的,并基于词语使用时周围的词语。
词语在学习到的向量空间中的位置被称为其嵌入。
从文本中学习词嵌入的两个流行方法包括:
- Word2Vec。
- GloVe。
除了这些精心设计的方法之外,词嵌入还可以作为深度学习模型的一部分进行学习。这可能是一种较慢的方法,但它使模型适应特定的训练数据集。
2. Keras 嵌入层
Keras 提供了一个嵌入层,可用于文本数据的神经网络。
它要求输入数据是整数编码的,以便每个词都由一个唯一的整数表示。这个数据准备步骤可以使用 Keras 提供的Tokenizer API 来执行。
嵌入层用随机权重初始化,并将学习训练数据集中所有词语的嵌入。
它是一个灵活的层,可以通过多种方式使用,例如:
- 它可以单独使用来学习词嵌入,然后可以保存并在另一个模型中使用。
- 它可以作为深度学习模型的一部分使用,其中嵌入与模型本身一起学习。
- 它可以用于加载预训练的词嵌入模型,这是一种迁移学习。
嵌入层被定义为网络的第一个隐藏层。它必须指定 3 个参数:
它必须指定 3 个参数:
- input_dim:这是文本数据中词汇表的大小。例如,如果您的数据被整数编码为 0-10 之间的值,那么词汇表的大小将是 11 个词。
- output_dim:这是词语将被嵌入的向量空间的大小。它定义了该层为每个词输出向量的大小。例如,它可以是 32 或 100,甚至更大。为您的具体问题尝试不同的值。
- input_length:这是输入序列的长度,就像您为 Keras 模型的任何输入层定义的那样。例如,如果您的所有输入文档都包含 1000 个词,那么这将是 1000。
例如,下面我们定义了一个嵌入层,其中词汇表大小为 200(例如,整数编码的词语从 0 到 199,包括在内),词语将被嵌入的向量空间为 32 维,输入文档各有 50 个词。
1 |
e = Embedding(200, 32, input_length=50) |
嵌入层具有学习到的权重。如果您将模型保存到文件,这将包括嵌入层的权重。
嵌入层的输出是一个 2D 向量,其中输入词序列(输入文档)中的每个词都有一个嵌入。
如果您希望将一个 Dense 层直接连接到嵌入层,您必须首先使用 Flatten 层将 2D 输出矩阵展平为 1D 向量。
现在,让我们看看如何在实践中使用嵌入层。
3. 学习嵌入的示例
在本节中,我们将探讨如何在文本分类问题上拟合神经网络时学习词嵌入。
我们将定义一个小型问题,其中有 10 个文本文档,每个文档都包含对学生提交作品的评论。每个文本文档被分类为积极“1”或消极“0”。这是一个简单的情感分析问题。
首先,我们将定义文档及其类别标签。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# 定义文档 文档 = ['做得好!', '好工作', '巨大的努力', '不错的工作', '太棒了!', '弱', '努力不够!', '不好', '工作糟糕', '可以做得更好。'] # 定义类别标签 labels = array([1,1,1,1,1,0,0,0,0,0]) |
接下来,我们可以对每个文档进行整数编码。这意味着作为输入,嵌入层将有整数序列。我们可以尝试其他更复杂的词袋模型编码,如计数或 TF-IDF。
Keras 提供了 one_hot() 函数,它将每个词创建为高效的整数编码哈希。我们将词汇表大小估计为 50,这远大于所需,以减少哈希函数冲突的可能性。
1 2 3 4 |
# 整数编码文档 vocab_size = 50 encoded_docs = [one_hot(d, vocab_size) for d in docs] 打印(encoded_docs) |
序列的长度不同,Keras 倾向于将输入向量化,并且所有输入具有相同的长度。我们将把所有输入序列填充到长度为 4。同样,我们可以使用 Keras 内置函数,在这种情况下是 pad_sequences() 函数。
1 2 3 4 |
# 将文档填充到最大长度为 4 个单词 max_length = 4 padded_docs = pad_sequences(encoded_docs, maxlen=max_length, padding='post') print(padded_docs) |
我们现在准备将我们的 Embedding 层定义为神经网络模型的一部分。
嵌入的词汇表大小为 50,输入长度为 4。我们将选择一个 8 维的小型嵌入空间。
该模型是一个简单的二分类模型。重要的是,Embedding 层的输出将是 4 个 8 维向量,每个词一个。我们将其展平为一个 32 元素向量,以传递给 Dense 输出层。
1 2 3 4 5 6 7 8 9 |
# 定义模型 model = Sequential() model.add(Embedding(vocab_size, 8, input_length=max_length)) model.add(Flatten()) model.add(Dense(1, activation='sigmoid')) # 编译模型 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) # 总结模型 print(model.summary()) |
最后,我们可以拟合和评估分类模型。
1 2 3 4 5 |
# 拟合模型 model.fit(padded_docs,labels, epochs=50, verbose=0) # 评估模型 loss, accuracy = model.evaluate(padded_docs, labels, verbose=0) print('Accuracy: %f' % (accuracy*100)) |
完整的代码列表如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
from numpy import array from keras.preprocessing.text import one_hot from keras.preprocessing.sequence import pad_sequences from keras.models import Sequential from keras.layers import Dense from keras.layers import Flatten from keras.layers.embeddings import Embedding # 定义文档 文档 = ['做得好!', '好工作', '巨大的努力', '不错的工作', '太棒了!', '弱', '努力不够!', '不好', '工作糟糕', '可以做得更好。'] # 定义类别标签 labels = array([1,1,1,1,1,0,0,0,0,0]) # 整数编码文档 vocab_size = 50 encoded_docs = [one_hot(d, vocab_size) for d in docs] 打印(encoded_docs) # 将文档填充到最大长度为 4 个单词 max_length = 4 padded_docs = pad_sequences(encoded_docs, maxlen=max_length, padding='post') print(padded_docs) # 定义模型 model = Sequential() model.add(Embedding(vocab_size, 8, input_length=max_length)) model.add(Flatten()) model.add(Dense(1, activation='sigmoid')) # 编译模型 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) # 总结模型 print(model.summary()) # 拟合模型 model.fit(padded_docs,labels, epochs=50, verbose=0) # 评估模型 loss, accuracy = model.evaluate(padded_docs, labels, verbose=0) print('Accuracy: %f' % (accuracy*100)) |
运行示例首先打印整数编码的文档。
1 |
[[6, 16], [42, 24], [2, 17], [42, 24], [18], [17], [22, 17], [27, 42], [22, 24], [49, 46, 16, 34]] |
然后打印每个文档的填充版本,使它们都具有统一的长度。
1 2 3 4 5 6 7 8 9 10 |
[[ 6 16 0 0] [42 24 0 0] [ 2 17 0 0] [42 24 0 0] [18 0 0 0] [17 0 0 0] [22 17 0 0] [27 42 0 0] [22 24 0 0] [49 46 16 34]] |
定义网络后,会打印层摘要。我们可以看到,正如预期的那样,嵌入层的输出是一个 4x8 矩阵,并通过 Flatten 层将其压缩为 32 元素向量。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
_________________________________________________________________ 层(类型) 输出形状 参数数量 ================================================================= embedding_1 (Embedding) (None, 4, 8) 400 _________________________________________________________________ flatten_1 (Flatten) (None, 32) 0 _________________________________________________________________ dense_1 (Dense) (None, 1) 33 ================================================================= 总参数:433 可训练参数:433 不可训练参数: 0 _________________________________________________________________ |
注意:由于算法或评估过程的随机性,或者数值精度的差异,您的结果可能会有所不同。考虑多次运行示例并比较平均结果。
最后,打印出训练模型的准确率,显示它完美地学习了训练数据集(这并不奇怪)。
1 |
准确率:100.000000 |
您可以将嵌入层学习到的权重保存到文件中,以便将来在其他模型中使用。
您也可以普遍使用此模型来分类测试数据集中具有相同词汇表的其他文档。
接下来,让我们看看如何在 Keras 中加载预训练的词嵌入。
4. 使用预训练 GloVe 嵌入的示例
Keras 嵌入层也可以使用在其他地方学习到的词嵌入。
在自然语言处理领域,学习、保存和免费提供词嵌入是很常见的。
例如,GloVe 方法的研究人员在其网站上提供了一套根据公共领域许可发布的预训练词嵌入。请参阅
最小的嵌入包是 822MB,名为“glove.6B.zip”。它在一个包含十亿个标记(词语)的数据集上进行训练,词汇表大小为 40 万个词。有几种不同的嵌入向量大小,包括 50、100、200 和 300 维。
您可以下载此嵌入集合,我们可以用预训练嵌入中的权重来初始化 Keras 的 Embedding 层,以用于训练数据集中的词语。
此示例的灵感来自 Keras 项目中的一个示例:pretrained_word_embeddings.py。
下载并解压后,您会看到几个文件,其中之一是“glove.6B.100d.txt”,其中包含 100 维的嵌入版本。
如果您查看该文件,您会看到每行都有一个标记(单词)和权重(100 个数字)。例如,下面是嵌入 ASCII 文本文件的第一行,显示了“the”的嵌入。
1 |
the -0.038194 -0.24487 0.72812 -0.39961 0.083172 0.043953 -0.39141 0.3344 -0.57545 0.087459 0.28787 -0.06731 0.30906 -0.26384 -0.13231 -0.20757 0.33395 -0.33848 -0.31743 -0.48336 0.1464 -0.37304 0.34577 0.052041 0.44946 -0.46971 0.02628 -0.54155 -0.15518 -0.14107 -0.039722 0.28277 0.14393 0.23464 -0.31021 0.086173 0.20397 0.52624 0.17164 -0.082378 -0.71787 -0.41531 0.20335 -0.12763 0.41367 0.55187 0.57908 -0.33477 -0.36559 -0.54857 -0.062892 0.26584 0.30205 0.99775 -0.80481 -3.0243 0.01254 -0.36942 2.2167 0.72201 -0.24978 0.92136 0.034514 0.46745 1.1079 -0.19358 -0.074575 0.23353 -0.052062 -0.22044 0.057162 -0.15806 -0.30798 -0.41625 0.37972 0.15006 -0.53212 -0.2055 -1.2526 0.071624 0.70565 0.49744 -0.42063 0.26148 -1.538 -0.30223 -0.073438 -0.28312 0.37104 -0.25217 0.016215 -0.017099 -0.38984 0.87424 -0.72569 -0.51058 -0.52028 -0.1459 0.8278 0.27062 |
与上一节一样,第一步是定义示例,将其编码为整数,然后填充序列以使其长度相同。
在这种情况下,我们需要能够将词映射到整数,并将整数映射到词。
Keras 提供了一个 Tokenizer 类,该类可以在训练数据上进行拟合,可以通过调用 Tokenizer 类的 texts_to_sequences() 方法将文本一致地转换为序列,并提供对词到整数映射字典的访问,该字典存储在 word_index 属性中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# 定义文档 文档 = ['做得好!', '好工作', '巨大的努力', '不错的工作', '太棒了!', '弱', '努力不够!', '不好', '工作糟糕', '可以做得更好。'] # 定义类别标签 labels = array([1,1,1,1,1,0,0,0,0,0]) # 准备分词器 t = 分词器() t.fit_on_texts(文档) vocab_size = len(t.word_index) + 1 # 整数编码文档 encoded_docs = t.texts_to_sequences(docs) 打印(encoded_docs) # 将文档填充到最大长度为 4 个单词 max_length = 4 padded_docs = pad_sequences(encoded_docs, maxlen=max_length, padding='post') print(padded_docs) |
接下来,我们需要将整个 GloVe 词嵌入文件加载到内存中,作为词到嵌入数组的字典。
1 2 3 4 5 6 7 8 9 10 |
# 将整个嵌入加载到内存中 embeddings_index = dict() f = open('glove.6B.100d.txt') for line in f: values = line.split() word = values[0] coefs = asarray(values[1:], dtype='float32') embeddings_index[word] = coefs f.close() print('Loaded %s word vectors.' % len(embeddings_index)) |
这相当慢。最好是过滤掉训练数据中不唯一的词的嵌入。
接下来,我们需要为训练数据集中的每个词创建一个嵌入矩阵。我们可以通过枚举 Tokenizer.word_index 中的所有唯一词,并从加载的 GloVe 嵌入中找到嵌入权重向量来完成此操作。
结果是一个仅包含训练期间我们将看到的词的权重矩阵。
1 2 3 4 5 6 |
# 为训练文档中的词创建权重矩阵 embedding_matrix = zeros((vocab_size, 100)) for word, i in t.word_index.items(): embedding_vector = embeddings_index.get(word) if embedding_vector is not None: embedding_matrix[i] = embedding_vector |
现在我们可以像以前一样定义模型、拟合和评估它。
关键区别在于嵌入层可以用 GloVe 词嵌入权重初始化。我们选择了 100 维版本,因此嵌入层的 output_dim 必须设置为 100。最后,我们不想更新此模型中学习到的词权重,因此我们将模型的 trainable 属性设置为 False。
1 |
e = Embedding(vocab_size, 100, weights=[embedding_matrix], input_length=4, trainable=False) |
完整的示例代码如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
from numpy import array from numpy import asarray from numpy import zeros from keras.preprocessing.text import Tokenizer from keras.preprocessing.sequence import pad_sequences from keras.models import Sequential from keras.layers import Dense from keras.layers import Flatten from keras.layers import Embedding # 定义文档 文档 = ['做得好!', '好工作', '巨大的努力', '不错的工作', '太棒了!', '弱', '努力不够!', '不好', '工作糟糕', '可以做得更好。'] # 定义类别标签 labels = array([1,1,1,1,1,0,0,0,0,0]) # 准备分词器 t = 分词器() t.fit_on_texts(文档) vocab_size = len(t.word_index) + 1 # 整数编码文档 encoded_docs = t.texts_to_sequences(docs) 打印(encoded_docs) # 将文档填充到最大长度为 4 个单词 max_length = 4 padded_docs = pad_sequences(encoded_docs, maxlen=max_length, padding='post') print(padded_docs) # 将整个嵌入加载到内存中 embeddings_index = dict() f = open('../glove_data/glove.6B/glove.6B.100d.txt') for line in f: values = line.split() word = values[0] coefs = asarray(values[1:], dtype='float32') embeddings_index[word] = coefs f.close() print('Loaded %s word vectors.' % len(embeddings_index)) # 为训练文档中的词创建权重矩阵 embedding_matrix = zeros((vocab_size, 100)) for word, i in t.word_index.items(): embedding_vector = embeddings_index.get(word) if embedding_vector is not None: embedding_matrix[i] = embedding_vector # 定义模型 model = Sequential() e = Embedding(vocab_size, 100, weights=[embedding_matrix], input_length=4, trainable=False) model.add(e) model.add(Flatten()) model.add(Dense(1, activation='sigmoid')) # 编译模型 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) # 总结模型 print(model.summary()) # 拟合模型 model.fit(padded_docs,labels, epochs=50, verbose=0) # 评估模型 loss, accuracy = model.evaluate(padded_docs, labels, verbose=0) print('Accuracy: %f' % (accuracy*100)) |
注意:由于算法或评估过程的随机性,或者数值精度的差异,您的结果可能会有所不同。考虑多次运行示例并比较平均结果。
运行示例可能需要更长的时间,但随后演示了它同样能够解决这个简单的问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
[[6, 2], [3, 1], [7, 4], [8, 1], [9], [10], [5, 4], [11, 3], [5, 1], [12, 13, 2, 14]] [[ 6 2 0 0] [ 3 1 0 0] [ 7 4 0 0] [ 8 1 0 0] [ 9 0 0 0] [10 0 0 0] [ 5 4 0 0] [11 3 0 0] [ 5 1 0 0] [12 13 2 14]] 已加载 400000 个词向量。 _________________________________________________________________ 层(类型) 输出形状 参数数量 ================================================================= embedding_1 (Embedding) (None, 4, 100) 1500 _________________________________________________________________ flatten_1 (Flatten) (None, 400) 0 _________________________________________________________________ dense_1 (Dense) (None, 1) 401 ================================================================= 总参数:1,901 可训练参数:401 不可训练参数:1,500 _________________________________________________________________ 准确率:100.000000 |
在实践中,我鼓励您尝试使用固定的预训练嵌入来学习词嵌入,并尝试在预训练嵌入之上进行学习。
看看哪种方法最适合您特定的问题。
进一步阅读
如果您想深入了解此主题,本节提供了更多资源。
- 维基百科上的词嵌入
- Keras 嵌入层 API
- 在 Keras 模型中使用预训练词嵌入, 2016
- 在 Keras 中使用预训练 GloVe 嵌入的示例
- GloVe 嵌入
- 词嵌入及其与分布式语义模型的连接概述, 2016
- 深度学习、自然语言处理和表示, 2014
总结
在本教程中,您了解了如何在 Python 中使用 Keras 进行深度学习时使用词嵌入。
具体来说,你学到了:
- 关于词嵌入以及 Keras 通过嵌入层支持词嵌入。
- 如何在拟合神经网络时学习词嵌入。
- 如何在神经网络中使用预训练的词嵌入。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
谢谢你,Jason。
我很期待阅读更多自然语言处理文章。
谢谢。
谢谢,这真的很有帮助。
不客气。
嵌入之后,必须有一个“Flatten()”层吗?在我的项目中,我直接在嵌入之后使用了一个 Dense 层。这样可以吗?
试试看吧。
我非常感谢您能将这些教程保持更新。我开始阅读时,第一件总是看的就是更新日期。非常感谢您。
不客气。
我要求所有代码都能工作并持续工作!
嗨,Jason
使用独热编码时,为什么需要填充?独热编码难道不是已经创建了等长输入吗?
独热编码是针对一个时间步的一个变量,例如特征。
需要填充以使所有序列具有相同数量的时间步。
看这里
https://machinelearning.org.cn/faq/single-faq/what-is-the-difference-between-samples-timesteps-and-features-for-lstm-input
我将数据分成 80-20 的测试-训练集,但我仍然得到 100% 的准确率。有什么想法吗?在第 1 个 epoch 时约为 99%,其余的都是 100%。
考虑使用此帖子中的过程来评估您的模型
https://machinelearning.org.cn/evaluate-skill-deep-learning-models/
使用 20% 的 dropout,您的模型过拟合了!!
谢谢你,杰森。我总觉得读你的文章更容易理解。
我有一个关于训练后每个单词向量的问题。例如,句子“Well done!”中的单词“done”与句子“Could have done better!”中的该单词会用不同的向量表示吗?我的意思是,每个单词的表示会根据每个句子的上下文而定吗?
不,字典中的每个词的表示都不同,但在不同上下文中的同一个词将具有相同的表示。
词语的表示是根据它在不同上下文中的使用来定义的。
这有帮助吗?
是的,谢谢你。但我还有一个问题。我们将分别训练每个上下文,然后训练第一个上下文,在这种情况下是“Well done!”,我们将得到“done”这个词的向量表示。训练第二个上下文“Could have done better”之后,我们将得到“done”这个词的另一个向量表示。那么,我们将选择哪个向量作为“done”这个词的表示呢?
我可能误解了训练过程。谢谢你为我澄清。
不。所有使用一个词的示例都用于该词的表示训练。在训练期间和之后,每个词只有一个表示。
我明白了。谢谢你,杰森。
嗨,Jason,
关于如何“过滤训练数据中独一无二的词的嵌入”,教程中有提及,有什么想法吗?
词到向量的映射字典已内置于 Gensim 中,您可以直接访问它以检索您想要的词的表示:model.wv.vocab
嗨 Jason,
我非常感谢您抽出时间撰写本教程并回复。
我的问题是关于您写的“model.wv.vocab”。它是一个地址站点吗?
实际上它不起作用。
不,它是模型上的一个属性。
嗨,Jason
你好。
我只是需要您的建议和示例。我有两个不同的数据集,一个是结构化的,另一个是非结构化的。目标是使用结构化数据为非结构化数据构建表示,因此对两个输入数据都应用词嵌入,但我如何才能找到这两个嵌入的平均值并将其展平为一个,然后再将该层输入到 CNN 和 LSTM 中。
期待您的回复。
此致
Abbey
抱歉,您的问题是什么?
如果你的问题是这是否是一个好方法,我的建议是尝试一下,看看结果。
嗨,Jason
如何找到两个输入的词嵌入的平均值?
此致
Abbey
也许你可以检索每个单词的向量并取它们的平均值?
也许你可以使用 Gensim API 来实现这个结果?
嗨,Jason,
我有一组文档(1200 篇电影剧本文本),我想使用预训练的嵌入。但我想更新词汇表并重新训练,添加我的语料库中的词。这可能吗?
当然可以。
加载预训练向量。为词汇表中的新词添加新的随机向量,然后将它们一起训练。
嗨 Jason…您能也为我们提供使用预训练 GloVe 嵌入的 R 代码吗?
抱歉,我没有词嵌入的 R 代码。
嗨 Jason,非常感谢你回复了所有评论!我计划在文本分类上尝试 CNN 和 RNN(可能是 LSTM 和 GRU)。我的大部分文档都不到 100 字,但大约有 5% 的文档长度超过 500 字。您建议在使用 RNN 时如何设置最大长度?如果我将其设置为 1000,会降低学习结果吗?我应该只使用 100 吗?在 CNN 的情况下会有所不同吗?
谢谢!
我建议尝试不同的配置,看看对模型技能的影响。
亲爱的Hao,
您尝试过在文本分类中使用RNN(LSTM或GRU)吗?如果尝试过,请问您能提供代码吗?
这里有一个例子
https://machinelearning.org.cn/sequence-classification-lstm-recurrent-neural-networks-python-keras/
我想感谢您这篇文章。我挣扎了一个星期才理解 Keras 的这种精确使用方法,而这是我找到的唯一一篇真正解释了过程中每个步骤在做什么的文章——并且提供了自我记录了数据在模型构建和训练过程中如何变化的代码。这使得它更容易适应我的特定需求。
谢谢,很高兴对您有帮助。
在上面的 Keras 示例中,我们如何根据给定单词预测上下文单词列表?比方说我有一个单词叫“sudoku”,想预测周围的单词。我们如何使用 keras 的 word2vec 来实现这一点?
听起来您正在描述一个语言模型。我们可以使用 LSTM 来学习这些关系。
这里有一个例子
https://machinelearning.org.cn/text-generation-lstm-recurrent-neural-networks-python-keras/
不,我的意思是 word2vec skip-gram 模型会根据中心词预测上下文词。所以如果我训练了一个 word2vec skip-gram 模型,如果我的中心词是“sudoku”,我如何预测上下文词列表?
此致,
Azim
我不知道,阿齐姆。
您可以获取单词之间的余弦距离,距离最小的那个将围绕它.. 这是链接
https://github.com/Hvass-Labs/TensorFlow-Tutorials
转到自然语言处理,您可以在那里找到一个余弦函数,用它来找到您的。
嗨,Jason,
感谢您的有用博客,我学到了很多。
我想知道,如果我已经有了预训练的词嵌入,是否可以将 keras 嵌入层设置为可训练?如果可行,当我只使用少量数据预训练词嵌入模型时,我会得到更好的结果吗?非常感谢!
你可以。很难知道它是否会带来更好的结果。试试看。
嗨,Jason,
是否可以对标签执行概率计算?我正在考虑一个案例,它不仅仅是 +/-,而是给定的数据条目可能既是也可能不是,但更有可能是一个而不是另一个。
是的,带有 sigmoid 或 softmax 输出的神经网络可以预测每个类别的概率得分。
我正在做类似的事情,只不过是用我自己的特征向量——但就标签而言——我使用 categorical_crossentropy 和 softmax 输出进行三元分类。我得到的是每个标签的概率答案。
太棒了!
嘿,杰森!
感谢您对该帖子的精彩而详细的解释。它对我帮助很大。
然而,我仍然不明白模型如何预测一个句子是积极的还是消极的。
我明白文档中的每个词都被转换为词嵌入,那么我们的模型如何评估整个句子是积极的还是消极的呢?它会取所有词向量的和吗?或者它们的平均值?我一直无法弄清楚这部分。
很好的问题!
模型解释序列中的所有词,并学习将特定的模式(编码词的)与积极或消极情绪关联起来
嗨,Jason,
非常感谢您精彩的帖子。我与 Ravil 有相同的问题。您能更详细地解释一下“学习关联特定模式”吗?
好问题,Ken,也许这篇文章能更清楚地说明机器学习算法是如何工作的(一种函数映射)。
https://machinelearning.org.cn/how-machine-learning-algorithms-work/
这有帮助吗?
谢谢你的回复。但我试图问的是,keras 是如何通过每个词的向量来生成文档级表示的?我似乎在代码中找不到这是如何实现的。
谢谢。
像 LSTM 或 CNN 这样的模型会将其整合在一起。
对于 LSTM,你可以在这里了解更多
https://machinelearning.org.cn/start-here/#lstm
这有帮助吗?
嗨,Jason,
首先,感谢您所有非常有用的帖子。
如果我理解您的帖子以及对 Ken 和 Ravil 的回复,您构建的神经网络实际上将对应于文档中所有单词的嵌入向量序列,通过 Flatten 层将其降维为一维向量,并且您只是训练这种扁平化以及嵌入,以在您的训练集上获得最佳分类,对吗?
提前感谢您的回答。
差不多吧。
单词 => 整数 => 嵌入
嵌入层为每个词提供一个向量,网络将使用该向量作为词的表示。
我们有一个词向量序列,所以我们把这个序列展平为一个长向量,供稠密模型读取。或者,我们可以将稠密层封装在一个 timedistributed 层中。
啊!所以扁平化时没有做什么花哨的事情,或多或少只是连接了固定数量的嵌入向量,这些向量是嵌入层的输出,这就是为什么每个文档的单词数量必须固定为该层的一个设置。如果这是正确的,我想我终于明白了这一切是如何工作的。
很抱歉再次打扰您,但是如果一个文档比最长的文档短得多(其词数被设置为嵌入层每个文档的词数),那么网络如何工作?它只是将那些未出现的词的嵌入向量填充为 0 吗?我一直在寻找将文本的所有词嵌入转换为某种文档嵌入的方法,这看起来太简单了,似乎不太可能起作用,或者它可能起作用,但只适用于短文档(以及其他选项,例如对词向量求平均或取逐元素的最大值或最小值)。
我正在尝试对西班牙语新闻进行情感分析,我的新闻中有大约 1000 甚至更多个词,并且想使用每个 300 维的预训练词嵌入。这对于网络来说,每个文档的大小会不会太大了,无法正常训练,或者训练速度不够快?我想你没有精确的答案,但我想知道你是否用长文档尝试过上述方法,或者知道有人尝试过。
再次感谢您,很抱歉问了这么长的问题。
是的。
我们可以对小文档使用填充,并使用 Masking 输入层来忽略填充值。更多信息在此。
https://machinelearning.org.cn/handle-missing-timesteps-sequence-prediction-problems-python/
尝试不同大小的嵌入,并根据结果指导配置。
好的,非常感谢!我会试一试的。
中文词语如何进行向量序列化
抱歉?
我机器人尝试与评论互动,生于 lstm
嗨,Jason,
我已成功使用词嵌入和 Keras 训练了一个模型。准确率达到 100%。
我保存了训练好的模型和词语标记以进行预测。
MODEL.save(‘model.h5’, True)
TOKENIZER = Tokenizer(num_words=MAX_NB_WORDS)
TOKENIZER.fit_on_texts(TEXT_SAMPLES)
pickle.dump(TOKENIZER, open(‘tokens’, ‘wb’))
进行预测时
– 加载已保存的模型。
– 通过加载已保存的词语标记设置分词器。
– 然后预测新数据的类别。
我不确定预测逻辑是否正确,因为我没有看到预期的预测类别。
源代码在 Github 上:https://github.com/hilmij/keras-test/blob/master/predict.py
如果您能查看并告诉我我遗漏了什么,将不胜感激。
此致,
希尔米。
你的流程听起来是正确的。抱歉,我无法审阅你的代码。
问题到底是什么?
谢谢你,杰森!你的例子非常有帮助。我希望能得到你的关注,我的问题是。在训练时,你通过以下方式准备分词器:
t = text.Tokenizer();
t.fit_on_texts(docs)
这会创建一个词语到数字的字典。如果在预测时有一个包含许多新词的新文档,我们该怎么办?所有这些词都会变成未知标记吗?如果是这样,有什么解决方案吗,比如我们能将分词器拟合到英语词汇表中的所有词语上吗?
在训练时,您必须知道您想要支持的词汇,即使您必须猜测。
为了支持新词汇,您将需要一个新模型。
你好,Jason!
在使用预训练GloVe嵌入的示例中,您是否使用词嵌入向量作为嵌入层的权重?
是的。
关于NLP和Keras的博客系列非常棒——感谢您的撰写。
给其他人快速说明一下
当我尝试使用以下行加载glove文件时
f = open(‘../glove_data/glove.6B/glove.6B.100d.txt’)
我收到错误
UnicodeDecodeError: ‘charmap’ 编码器无法解码位置2776处的字节0x9d:字符映射到
为了修复,我添加了
f = open(‘../glove_data/glove.6B/glove.6B.100d.txt’,encoding=”utf8″)
此问题可能是由于使用了Windows造成的。
谢谢Alex的提示。
嗨,Jason,
精彩的教程!
我有一个问题。为什么我们必须对标签进行独热向量化?另外,如果我有一个填充序列,例如 [2,4,0],那么独热编码会是什么?我正在努力更好地理解独热向量化。
感谢您的回复!
我们不对标签进行独热编码,我们对词汇进行独热编码。
也许这篇帖子能帮助您更好地理解独热编码
https://machinelearning.org.cn/how-to-one-hot-encode-sequence-data-in-python/
嗨,Jason,
感谢您的精彩教程。您知道是否有办法构建一个网络,同时使用文本嵌入数据和分类数据进行分类?
谢谢你
当然,您可以构建一个具有两个输入的网络
https://machinelearning.org.cn/keras-functional-api-deep-learning/
谢谢你,Jason。
如何在keras中使用CNN进行句子分类?请帮忙
请看这个教程
https://machinelearning.org.cn/develop-word-embedding-model-predicting-movie-review-sentiment/
解释得很棒,非常感谢。我惊讶于自上次查看以来,这变得如此容易。
很高兴这篇帖子帮助了Stuart!
嗨,Jason……您的文档中的14个词汇是“well done good work great effort nice excellent weak poor not could have better”。对于14个词汇量,它独热编码为[13 8 7 6 10 13 3 6 10 4 9 2 10 12]。为什么“great”、“weak”和“have”都出现了3次10?
抱歉,Stuart,我不明白。您能重新提问吗?
嗨,Jason,我上面示例中提供的编码来自kerasR,词汇量为14。所以,让我用您上面第3部分的独热示例,词汇量为50,来问相同的问题,即编码的唯一性。
这里,针对不同的新内核(使用Spyder3/Python 3.4)产生了不同的编码
[[31, 33], [27, 33], [48, 41], [34, 33], [32], [5], [14, 41], [43, 27], [14, 33], [22, 26, 33, 26]]
[[6, 21], [48, 44], [7, 26], [46, 44], [45], [45], [10, 26], [45, 48], [10, 44], [47, 3, 21, 27]]
[[7, 8], [16, 42], [24, 13], [45, 42], [23], [17], [34, 13], [13, 16], [34, 42], [17, 31, 8, 19]]
请注意,在第一行,“33”编码了“done”、“work”、“work”、“work”和“done”这些词。在第二行,“45”编码了“excellent”、“weak”和“not”这些词。在第三行,“13”编码了“effort”、“effort”和“not”。
所以我想知道为什么编码不是唯一的?其次,词汇量是否必须比实际词汇量大得多?
谢谢
one_hot() 函数不会将单词映射到唯一整数,它使用可能存在冲突的哈希函数,在此处了解更多信息
https://keras.org.cn/preprocessing/text/#one_hot
谢谢Jason,在您的第4部分示例中,Tokenizer 方法总是给出相同的编码,并且这些编码似乎是唯一的。
是的,我建议使用 Tokenizer,请参阅这篇帖子了解更多信息
https://machinelearning.org.cn/prepare-text-data-deep-learning-keras/
Jason,很棒的文章。
如何从嵌入反向转换为独热编码?例如,如果您有一个seq2seq模型,并将输入作为词嵌入,在您的解码器中,您需要将嵌入反向转换为表示字典的独热编码。如果您通过矩阵乘法来实现,那可能是一个相当大的矩阵(例如,嵌入大小300,词汇量40万)。
输出层可以直接预测整数,您可以将其映射到词汇表中的单词。输出层将不会有嵌入层。
你好,
非常有用的文章。
我使用gensim和预训练的Google新闻向量创建了一个句子的word2vec矩阵。我可以直接将此矩阵展平为向量并将其用作神经网络的输入吗?
例如:
每个句子长度为140,我使用的是一个100维的预训练模型,因此:- 我有一个140*100的矩阵表示句子,我可以直接将其展平为一个14000长度的向量并将其馈送到我的输入层吗?
这取决于您想要建模的内容。
很棒的文章,您能解释一下两个神经网络中参数#400和#1500是如何得来的吗?谢谢
哦!它仅仅是词汇量 * 嵌入空间的维度数吗?
1. 50 * 8 = 400
2. 15* 100 = 1500
你具体指的是什么?
很棒的帖子!我正在使用自己的语料库。我如何将嵌入层的权重向量保存到像glove数据集一样的文本文件中?
我的想法是,这样我就可以更容易地将向量表示应用于新的数据集和/或机器学习平台(mxnet等),并使输出具有可读性(因为单词与向量相关联)。
您可以使用Keras API中的 get_weights() 函数检索向量并直接保存为CSV文件。
get_weights() 具体是做什么的?它需要一个循环吗?
get_weights 是一个函数,它将返回模型或层的权重,具体取决于您调用它的对象
https://keras.org.cn/layers/about-keras-layers/
清晰简洁,阅读愉快,一如既往地感谢您的工作!
谢谢。
你好 Jason,
我有一个数据集,通过5折交叉验证使用SVM获得了0.87的fscore。最大上下文窗口为20,并进行了独热编码。
现在,我已经完成了所有提到的操作,并且在RNN模型中获得了13-15%的准确率,每个模型都有一个LSTM单元,带有3、20、150、300个隐藏单元。我预训练的嵌入维度是300。
损失正在减少,甚至达到了负值,但准确率没有变化。
我用您为文本分类提到的CNN、基本ANN模型也尝试了同样的方法。
您能否提供一些解决方案。提前致谢。
我这里有一些想法
https://machinelearning.org.cn/improve-deep-learning-performance/
当我复制第一个框中的代码时,出现错误
AttributeError: ‘int’ object has no attribute ‘ndim’
在这一行
model.fit(padded_docs, labels, epochs=50, verbose=0)
问题出在哪里?
复制“完整示例”中的代码。
嗨,Jason,
我得到了同样的错误,在运行“竞争示例”时也是如此。
原因可能是什么?
尝试将标签转换为numpy数组。
我得到了同样的!
我已经修复并更新了示例。
Carsten,您需要labels是numpy.array而不是list。
嗨,Jason,
如果在训练集中有未知单词,在使用预训练向量模型(如glove或w2v)时,如何将相同的随机初始化向量分配给所有未知单词。谢谢!!!
你为什么要那样做?
如果我的数据在特定领域,并且我仍然想利用通用词嵌入模型(例如,从维基训练的glove.6b.100d),那么它在领域数据中肯定会有一些OOV,所以,无论是在训练时间还是推理时间,都可能出现一些未知词。
也许会。
您可以忽略这些词。
您可以创建一个新的嵌入,从现有嵌入中设置向量并学习新词。
太棒了,Jason博士!
感谢您精彩的演练。
请就以下问题提供建议。
在将每个单词编码为整数的步骤中,您说:“我们可以尝试其他更复杂的词袋模型编码,如计数或TF-IDF”。您能否详细说明如何实现它,因为tfidf将标记编码为浮点数。以及如何将其与Keras关联,并将其传递给嵌入层?我渴望尝试一下,希望它能产生更好的结果。
另一个问题是关于输入文档。假设我已经通过nltk对文本进行了预处理,直到词形还原,因此,每个样本都是一个标记列表。在这种情况下,将其传递给Keras嵌入层的最佳方法是什么?
我有很多关于词袋模型的帖子,请在此处了解更多信息
https://machinelearning.org.cn/?s=bag+of+words&submit=Search
您可以手动将您的令牌编码为整数,或使用Keras Tokenizer。
嗯,Keras Tokenizer 只能接受文本或序列。看来唯一的办法是使用 ' '.join(token_list) 将标记连接起来,然后传递给 Tokenizer。
至于BOW文章,我已经通读了,它们非常有价值。谢谢!
使用BOW与使用嵌入有很大的不同。BOW会为每个样本引入巨大的稀疏特征数组,而嵌入旨在将这些特征(标记)密集地表示为数百个项目。
所以,另一篇文章中的BOW仅通过非常简单的NN架构(1层50或100个神经元)就获得了令人难以置信的好结果。而我却难以使用嵌入和卷积层获得好结果……
根据您的经验,您能就此提供建议吗?嵌入是否真的可行,只是找到正确架构的问题?
太棒了!而且您能完成这些教程,干得好。我喜欢看到这样的成果,很少有人真正“完成工作”。
一般来说,嵌入在较大/困难的问题上更有意义——例如,大型词汇量,前端的复杂语言模型等。
明白了,谢谢。
感谢Jason的另一个精彩教程。
我有一些问题
独热编码的定义不是二进制的,即0和1的向量吗?
所以[[1,2]]会被编码为[[0,1,0],[0,0,1]]
在keras word2vec/globe或简单的密集层(或其他东西)上,嵌入算法是如何完成的
谢谢
joseph
抱歉,我不明白您的问题。您能重新表述一下吗?
太棒了,Jason博士!
感谢您精彩的演练。
例如上面例子中的8,每个词向量的维度是随机设置的吗?
谢谢你
维度是固定且指定的。
在第一个示例中是8,在第二个示例中是100。
感谢Jason博士的快速反馈!
好的,我明白了预训练的词嵌入被设置为100维,因为原始文件“glove.6B.100d.txt”包含了每行ASCII固定的100个权重。
然而,正如您在此处提到的第一个例子,“嵌入的词汇量为50,输入长度为4。我们将选择一个小的8维嵌入空间。”
您为第一个例子选择了8维。这是否意味着它可以设置为8以外的任何数字?我尝试将维度更改为12。它没有出现任何错误,但准确率从100%下降到89%。
_________________________________________________________________
层(类型) 输出形状 参数 #
=================================================================
embedding_1 (Embedding) (None, 4, 12) 600
_________________________________________________________________
flatten_1 (Flatten) (None, 48) 0
_________________________________________________________________
dense_1 (Dense) (None, 1) 49
=================================================================
总参数:649
可训练参数:649
不可训练参数: 0
准确率:89.999998
那么,维度是如何设置的?维度会影响准确率性能吗?
抱歉,我正在努力理解NLP基础概念。非常感谢Jason博士的帮助。
谢谢你
没问题,请提出更多问题。
是的,您可以选择任何您喜欢的维度。越大表示表达能力越强,对于更大的词汇量来说是必需的。
这有帮助吗,Anna?
确实如此,博士。现在我明白了维度是根据词汇量设置的。
再次感谢Jason博士的启发!🙂
你问了很好的问题。
嗨,Jason,
感谢精彩的教程。
我有一个问题。我正在尝试使用Keras中的上下文窗口进行语义角色标注。如何使用嵌入层实现上下文窗口?
谢谢你
我不知道,抱歉。
你好,很棒的网站!我从所有的教程中学到了很多。感谢您提供所有这些易于理解的信息。
我该如何将其他数据用于CNN模型呢?目前,我只使用文本数据和词嵌入来构建我的模型。据我所知,模型的第一层必须是嵌入层,那么我如何将整数等其他输入数据与嵌入层一起使用呢?
谢谢!
很好的问题!
您可以使用多输入模型,请在此处查看示例
https://machinelearning.org.cn/keras-functional-api-deep-learning/
感谢您的快速回复!
你好Jason,这个教程简单易懂。谢谢。
然而,我有一个问题。在使用预训练的嵌入权重(如Glove或word2vec)时,如果我的数据集中存在一些单词,而这些单词在word2vec或Glove训练的数据集中不存在,模型如何表示这些单词?
我的理解是,在您的第二节(使用预训练的Glove嵌入)中,您将加载的权重中的单词映射到您数据集中存在的单词,因此有上述问题。
如果我的理解不对,请纠正我。
您可以忽略它们,或者将它们设置为零向量,或者训练一个包含它们的新模型。
你好Jason。感谢这篇以及其他非常清晰和信息丰富的文章。
想给Aditya的帖子补充一个问题
“将加载的权重中的单词映射到数据集中存在的单词”
它是如何映射的?它是否使用矩阵索引 == (padded_docs 或) 中的单词编号?
我之所以问,是因为——如果我传递带有原始顺序的embedding_matrix,但在model.fit之前打乱padded_docs会怎样?
单词必须分配唯一的整数,并且在所有数据和嵌入中保持一致。
嗨,Jason,
我正在尝试使用Keras LSTM模型训练一些文本情感数据。我还使用sklearn中的GridSearchCV来寻找最佳参数。我不太确定哪里出了问题,但是sklearn的分类报告显示
UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples.
以下是分类报告的样子
精确率 召回率 f1分数 支持数
负面 0.00 0.00 0.00 98
正面 0.70 1.00 0.83 232
平均/总计 0.49 0.70 0.58 330
您知道问题出在哪里吗?
也许您正在尝试将 keras 度量与 sklearn 结合使用?请注意您在指定 keras 模型与 sklearn 评估 (CV) 时使用的关键词。
嗨,Jason,
你的博客真的很有趣。我有一个问题:使用word2vec和Keras中Tokenizer的texts_to_sequences有什么区别?我的意思是文本表示方式的区别。
这两种选择中哪一个更好?
非常感谢。
此致。
word2vec 将单词(整数)编码为向量。texts_to_sequences 将单词编码为整数。它是 word2vec 之前的一个步骤,或者是词袋模型之前的一个步骤。
嗨,Jason,
我有一个包含文本和相应标签的数据框。我使用了 gensim 模块并使用 word2vec 从文本中生成了一个模型。现在我想将该模型用作 Conv1D 层的输入。您能告诉我如何在 Keras Embedding 层中加载 word2vec 模型吗?我是否需要在加载之前以某种方式预处理模型?提前感谢。
是的,将权重加载到嵌入层,然后定义网络的其余部分。
上面的教程会很有帮助。
这真的很有帮助。你让我们在工作中变得更棒。谢谢!!
很高兴听到这个消息。
感谢这篇极有帮助的博客文章。我有一个关于解释模型的问题。有没有办法在模型训练后知道/可视化单词的重要性?我正在寻找一种方法来做到这一点。例如,有没有办法找出前10个会触发模型将文本分类为负面的单词,反之亦然?提前非常感谢您的帮助
可能有方法,但我并不了解。一般来说,神经网络是不透明的,即使第一层/最后一层的权重激活如果用作重要性分数也可能产生误导。
也许可以看看 Lime
https://github.com/marcotcr/lime
谢谢。
嗨,Jason,
您能告诉我这背后的逻辑吗?
vocab_size = len(t.word_index) + 1
我们为什么要在这里加1??
这样词汇索引从1开始,而0保留用于填充/无数据。
嗨,Jason,
如果我想用这个模型预测下一个词,我可以直接将输出层改为Dense(100, activation = ‘linear’)并将损失函数改为MSE吗?
非常感谢,
雷
也许可以看看一些关于训练语言模型进行单词生成的帖子
https://machinelearning.org.cn/?s=language+model&submit=Search
感谢这个教程!非常清晰有用!
不客气。
嗨,Jason,
您在keras教程和回复问题方面都是最棒的。我真的非常感谢。
尽管我理解了您上面所写的内容和代码,但我无法理解您这句话的意思:[最好根据训练数据中唯一的词汇来筛选嵌入。]
“筛选嵌入”是什么意思?
感谢您的回复。
这意味着,只在嵌入中包含您知道存在于您的数据集中的单词。
嗨,Jason,
感谢您的回复,但由于我不是母语为英语的人,我不确定我是否理解了。您的意思是移除所有在glove中存在但不在我的数据集中存在的单词吗?为了提高实现速度?
我很抱歉再次提问,因为我没有清楚地理解。
提前感谢Jason
没错。
你好,
这篇帖子很棒。我是机器学习新手,所以我有一个可能很基础的问题,我不确定。据我所知,模型一次性接收嵌入矩阵、文本和标签。我尝试做的是将POS标签嵌入与每个预训练的词嵌入连接起来,但POS标签可能因上下文而异。这本质上意味着我不能修改嵌入矩阵并将其添加到网络嵌入层。我想逐句处理,找到其嵌入,并与POS标签嵌入连接,然后输入神经网络。有没有办法逐句进行训练?谢谢
您可以使用嵌入并预先计算每个句子的向量表示。
抱歉,我不太明白。您能详细说明一下吗?
抱歉,我的意思是您可以单独准备一个word2vec模型。然后将每个句子通过它来构建向量列表。将向量连接起来,您就拥有了一个分布式的句子表示。
非常感谢!还有一件事,除了权重之外,是否可以向嵌入层传递其他信息?例如,我当时想,如果我完全不改变嵌入矩阵,而是为整个训练数据创建一个单独的POS标签矩阵,也将其传递给嵌入层,该层将按顺序连接这两个矩阵,会怎样?
您可以开发一个具有多个输入的模型,例如,请参阅此帖子中的示例
https://machinelearning.org.cn/keras-functional-api-deep-learning/
谢谢。我看到了这篇帖子。您的模型有独立的输入,但在展平后合并。在我的例子中,我希望将嵌入传递给第一个卷积层,只有在它们连接后才传递。到目前为止我所做的是,我根据POS标签(embedding_pos)创建了另一个整数序列,作为另一个输入,以及另一个包含所有POS标签嵌入的嵌入矩阵。
e=(Embedding(vocab_size, 50, input_length=23, weights=[embedding_matrix], trainable=False))
e1=(Embedding(38, 38, input_length=23, weights=[embedding_matrix_pos], trainable=False))
merged_input = concatenate([e,e1], axis=0)
model_embed = Sequential()
model_embed.add(merged_input)
model_embed.fit(data,embedding_pos, final_labels, epochs=50, verbose=0)
我知道这是错误的,但我不知道如何连接这两个序列,如果您能给我正确的方向,那将非常棒。错误是
‘Layer concatenate_6 was called with an input that isn’t a symbolic tensor. Received type: . Full input: [, ]. All inputs to the layer should be tensors.’
也许您可以尝试并比较不同合并层模型在组合输入时的性能。
嗨Jason,一如既往地写得真棒!
不过你最后一句有点难懂。你写道
“实际上,我鼓励你尝试使用预训练的固定嵌入来学习词嵌入,并尝试在预训练嵌入的基础上进行学习。”
如果没有原始语料库,我会说,那是不可能的。
在谷歌的案例中,大约1000亿词的原始语料库没有公开。解决方案?我相信您建议的是“NLP的迁移学习”。在这种情况下,我看到的唯一解决方案是手动添加词汇。
例如,您需要“dolares”,它不在谷歌的Word2Vec中。您希望拥有与“money”相似的向量。在这种情况下,您添加“dolares” + 300个来自money的向量。我知道这很痛苦。但这是我看到的进行“NLP迁移学习”的唯一方法。
如果您有更好的解决方案,我乐意听取您的意见。
再见,一位忠实粉丝
并非不可能,您可以使用在其他语料库上训练的嵌入,并忽略差异或在拟合模型时微调嵌入。
您还可以将缺失的单词添加到嵌入中并学习这些单词。
请记住,我们希望每个单词都有一个最能捕捉其用法的向量,一些不一致不会导致模型无用,这不是二进制有用/无用的情况。
非常感谢您的详细解答!
Tokenizer API 的链接是此同一个网页。请您更新它吗?
已修正,谢谢。
嗨 Jason,很棒的帖子!
我已经成功地使用词嵌入和Keras训练了我的模型。我保存了训练好的模型和词令牌。现在为了进行一些预测,我必须使用与训练时相同的分词器吗?
正确。
非常感谢!
嗨Jason,当我寻找如何使用预训练词嵌入时,
我发现了您的文章以及这篇
https://jovianlin.io/embeddings-in-keras/
它们有很多相似之处。
很高兴听到这个消息。
嘿 Jason,
我正在尝试这样做,但有时Keras会给不同的单词相同的整数。使用scikit编码器将单词转换为整数会更好吗?
如果您使用的是哈希编码器(Keras就是如此,但将其称为独热编码器),则可能会发生这种情况。
也许可以尝试不同的单词到整数编码方案
嗨,Jason,
我已经实现了上述教程,代码在GloVe下运行良好。我非常感谢Jason的教程。
但当我下载预训练的word2vec嵌入模型GoogleNews-vectors-negative300.bin时,它给我报了这个错误
文件“/home/mary/anaconda3/envs/virenv/lib/python3.5/site-packages/gensim/models/keyedvectors.py”,第171行,在__getitem__中
返回vstack([self.get_vector(entity) for entity in entities])
TypeError: 'int' object is not iterable.
我写的代码与您加载glove的代码相同,只是稍有改动。
‘model = gensim.models.KeyedVectors.load_word2vec_format(‘./GoogleNews-vectors-negative300.bin’, binary=True)
for line in model
values = line.split()
word = values[0]
coefs = asarray(values[1:], dtype=’float32′)
embeddings_index[word] = coefs
model.close()
print(‘Loaded %s word vectors.’ % len(embeddings_index))
embedding_matrix = zeros((vocab_dic_size, 300))
for word in vocab_dic.keys()
embedding_vector = embeddings_index.get(word)
if embedding_vector is not None
embedding_matrix[vocab_dic[word]] = embedding_vector
我看到您在这篇文章“https://machinelearning.org.cn/develop-word-embedding-model-predicting-movie-review-sentiment/”中写了一个关于自己创建word2vec的教程,
但我还没有看到关于应用预训练word2vec(如GloVe)的教程。
请指导我解决此错误以及如何应用GoogleNews-vectors-negative300.bin预训练的word2vec?
我很抱歉写了很多,因为我想详细解释清楚。
任何指导都将不胜感激。
祝好
Meysam
也许可以尝试像上面教程中的文本版本?
嗨 Jason
非常感谢您的回复,但由于我英语不好,这句话的意思不清楚。“尝试文本版本”是什么意思??
实际上,GloVe 包含 txt 文件,我正确地实现了它,但当我想要运行一个使用 GoogleNews-vectors-negative300.bin(这是一个预训练的 word2vec 嵌入)的程序时,它给我报错了,而且这个文件是二进制的,没有以 txt 为前缀的预训练 word2vec 嵌入文件。
即使您很忙,您能帮我吗?
祝好
Meysam
您正在使用glove文件的二进制版本(.bin)。请尝试下载并使用文本版本。
您可以在这里获取.txt版本
https://nlp.stanford.edu/projects/glove/
我们如何在移动设备上使用预训练的词嵌入?
除了磁盘/内存大小问题,我看不出有什么不行。
很棒的帖子!如果标签不是二进制的,而是有4个类,例如
labels = array([2,1,1,1,2,0,-1,0,-1,0])
?
例如,代替“binary_crossentropy”,也许是“categorical_crossentropy”?
以及Dense层应该如何改变?
如果我使用:model.add(Dense(4, activation=’sigmoid’)),我将得到一个错误
ValueError: Error when checking target: expected dense_1 to have shape (None, 4) but got array with shape (10, 1)
感谢您的工作!
我相信这会有帮助
https://machinelearning.org.cn/faq/single-faq/how-can-i-change-a-neural-network-from-regression-to-classification
谢谢!还需要使用Keras的to_categorical来离散化标签。
还有一个问题:有没有一种简单的方法来创建Tokenizer()实例,拟合它,保存它,然后在新文档上扩展它?具体来说,就是让t.fit_on_texts()可以在新数据上更新。
我不确定你是否能做到。
管理编码/映射可能更容易,这样您就可以随意扩展它。
不错。
嗨,Jason,
首先,感谢这篇帖子。它非常适合快速启动。如果您不介意,我还有几个问题
1) 我认为独热编码字符串向量并不理想。即使使用建议的词汇量(50),我仍然会遇到冲突,这即使在玩具示例中也违背了目的。甚至文档也说明不保证唯一性。Keras的Tokenizer(),您在预训练示例中使用的那个,是一个更可靠的选择,因为没有两个单词会共享相同的整数映射。为什么您建议独热编码,而Tokenizer()能更好地完成相同的工作?
2) 获取 Tokenizer() 的 word_index 属性,返回完整的字典。我期望 vocab_size 等于 len(t.word_index),但您将该值递增了 1。这实际上是必需的,否则模型拟合会失败。但我无法理解其中的道理。为什么输入维度大小等于 vocab_size + 1?
3) 我创建了一个模型,期望每个“文档”的BoW向量表示。自然地,向量更大更稀疏[ (10,14) ],这意味着要学习更多的参数,不是吗。然而,在您的文档中,您将这种编码或tf-idf称为“更复杂”。您为什么这样认为?使用这种编码,您不是会丢失对学习词嵌入很重要的词序吗?顺便说一句,这种编码也运行良好,但这可能归因于这个小实验的性质。
先谢谢您了。
Keras 的独热编码方法实际上只是一个哈希。在需要时,最好使用真正的独热编码。
我实际上更喜欢使用 Tokenizer 类。
这些单词是1偏移的,为0留出了“未知”单词的空间。
tf-idf 在词袋模型中提供了一些关于单词频率而非简单存在/缺失的信息。
希望这有帮助。
我在哪里可以找到文件“../glove_data/glove.6B/glove.6B.100d.txt”?因为我遇到了以下错误。
文件“”,第36行
f = open(‘../glove_data/glove.6B/glove.6B.100d.txt’)
^
SyntaxError: 标识符中包含无效字符
您必须下载它并将其放置在您的当前工作目录中。
也许可以重新阅读第4节。
我已将代码和数据集放在同一目录中。代码有什么问题?
f = open(‘glove.6B/glove.6B.100d.txt’)
我遇到了以下错误。
文件“”,第36行
f = open(‘glove.6B/glove.6B.100d.txt’)
^
SyntaxError: 标识符中包含无效字符
也许这会在您从教程中复制代码时有所帮助
https://machinelearning.org.cn/faq/single-faq/how-do-i-copy-code-from-a-tutorial
干得漂亮!这对新手很有帮助。
我想知道这是否对英语以外的其他语言有用?因为我是中国人,我想知道我是否可以将其应用于汉语和词汇。
再次感谢您的付出!
我看不出为什么不。
你好,
您能解释一下词嵌入如何作为隐藏状态输入到LSTM吗?
先谢谢了
词嵌入没有隐藏状态。它们没有任何状态。
例如,我有一个单词及其50维的嵌入。如何将这些嵌入作为隐藏状态输入到LSTM层?
你为什么想把它们作为隐藏状态而不是作为LSTM的输入呢?
嗨,多么实用的一篇文章!
我有一个问题,我正在用word2vec作为嵌入模型在keras中进行情感分析项目。我的问题是,当我想要预测一个新句子作为输入时,我遇到了这个错误
ValueError: Error when checking input: expected conv1d_1_input to have shape (15, 512) but got array with shape (3, 512)
请注意,我想输入一个简单的句子,例如:“I’m really sad”,长度为3,而我的输入形状长度为15。我不知道如何重塑它或如何解决这个错误。
这是我的代码的相关部分
model = Sequential()
model.add(Conv1D(32, kernel_size=3, activation=’elu’, padding=’same’, input_shape=(15, 512)))
model.add(Conv1D(32, kernel_size=3, activation=’elu’, padding=’same’))
model.add(Conv1D(32, kernel_size=3, activation=’elu’, padding=’same’))
model.add(Conv1D(32, kernel_size=3, activation=’elu’, padding=’same’))
model.add(Dropout(0.25))
model.add(Conv1D(32, kernel_size=2, activation=’elu’, padding=’same’))
model.add(Conv1D(32, kernel_size=2, activation=’elu’, padding=’same’))
model.add(Conv1D(32, kernel_size=2, activation=’elu’, padding=’same’))
model.add(Conv1D(32, kernel_size=2, activation=’elu’, padding=’same’))
model.add(Dropout(0.25))
model.add(Dense(256, activation=’relu’))
model.add(Dense(256, activation=’relu’))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(2, activation=’softmax’))
您能帮我解决这个问题吗?
您必须以与训练数据完全相同的方式准备新句子,包括长度和整数编码。
至少您能否分享一些合适的资源来帮助我解决这个问题?
希望您能像往常一样回答我的问题。谢谢
我很乐意提供帮助并回答具体问题,但我没有能力为您编写代码,抱歉。
嗨,Jason,
我有两个问题。首先,对于新实例,如果长度大于此模型输入,我们是否应该截断句子?
此外,由于嵌入输入仅用于已见过的训练集单词,那么预测到单词的过程会发生什么?我假设它只返回一些与训练单词相似的单词,而不考虑所有词典单词。当然,我正在谈论的是带有Glove的语言模型。
是的,截断。
未见词被映射为无或0。
训练数据集必须代表您正在解决的问题。
根据我对这个评论的理解,它是关于测试数据上的预测。假设词汇表中有50个词,这意味着句子将有唯一的整数,直到50。现在,由于测试数据必须使用相同的分词器实例进行分词,如果它有一些新词,它将有51、52等整数。在这种情况下,模型会自动使用0作为词嵌入,还是会抛出越界异常?谢谢
您会将未见词编码为0。
所有50个词汇词都应该从索引1到50开始,而0留给词汇表中未见过的词。我说的对吗?
正确。
这可以描述为迁移学习吗?
也许可以。
我们需要为作业提供帮助,请帮助我们!!
请参阅 https://machinelearning.org.cn/faq/single-faq/can-you-help-me-with-my-homework-or-assignment/
你好,
我训练并测试了自己的网络。在我的工作中,当我将句子整数化并创建相应的词嵌入矩阵时,它也包含了训练、验证和测试数据的嵌入。
现在,如果我想重新加载我的模型来测试一些其他类似数据,我很困惑这些新数据中的词如何与嵌入矩阵相关联?
你也应该有测试数据的嵌入,对吗?或者当你创建嵌入矩阵时,你会排除测试数据吗?谢谢
嵌入是从训练数据集中创建的。
它应该足够丰富/具有代表性,以涵盖你未来期望的所有数据。
新数据在进行预测时,在映射到嵌入之前,必须与训练数据具有相同的整数编码。
这有帮助吗?
是的,我明白我应该使用相同的分词器对象来编码训练和测试数据,但我不确定嵌入层对于不属于嵌入矩阵的词或索引会如何表现。显然,测试数据会有类似的词,但肯定会有一些新词。你会说这种方法在为模型创建嵌入矩阵时也包含测试数据是正确的吗?如果你想使用一些预训练模型进行预测,我该如何处理这个问题?一个小例子会非常有帮助。非常感谢你的所有帮助和时间!
不会。编码会将未知词设置为0。
这真的取决于你想要评估的目标。
我想训练我的模型来预测给定5个词序列的目标词。我如何表示我的目标词?
可能是使用独热编码。
你好 Jason,
这是关于第一个嵌入层的输出形状:(None,4,8)。
我理解为4代表输入大小,即4个词,8是它使用这些词生成的特征数量,对吗?
我相信是的。
嗨,Jason,
感谢分享您的知识。
我的任务是将一组文档分类到不同的类别。(我有一个包含100个文档和10个类别的训练集)。
想法是从每个文档的前几行中提取前M个词(例如20个),将词转换为词嵌入,并将其用作神经网络的特征向量。
问题:由于我从文档中提取前M个词,它们的顺序可能不总是“正确”的,这意味着输入层在给定位置可能有不同的词(不像词袋模型)。这种方法不会影响神经网络的收敛吗?
此致,
Srini
关键是在将数据输入嵌入层之前,为每个词分配相同的整数值。
您必须对所有文档使用相同的文本分词器。
嗨,Jason,
感谢您精彩的解释。我在我的seqtoseq项目中使用了预训练的Google嵌入矩阵,通过编码器-解码器。但在我的测试中,我遇到了一个问题。我不知道如何反转我的嵌入矩阵。您有示例项目吗?我的解决方案是:当我的解码器预测一个向量时,我应该在我的预训练嵌入矩阵中搜索它,然后找到它的索引,然后理解它相关的词。我说的对吗?
你为什么要反转它?
嗨 Jason
感谢这篇出色的教程。使用您的方法,我已将文本转换为词索引并应用了词嵌入。
和Fatemeh一样,我想知道是否有可能反转这个过程,将嵌入向量转换回文本?这对于文本摘要等应用可能很有用。
谢谢你。
是的,每个向量都有一个由嵌入层已知的整数值,每个整数通过分词器映射到一个词。
空间中的随机向量没有,您必须使用欧几里得距离找到嵌入层中最接近的向量。
尊敬的Jason博士,
准确率:我的笔记本电脑上是89.999998,结果和别的电脑不同?
干得好!
每次运行的结果都不同,在这里了解更多
https://machinelearning.org.cn/randomness-in-machine-learning/
你好,
非常感谢这篇教程!
我一直在尝试训练一个包含嵌入层、LSTM和softmax作为输出层的网络。然而,损失和准确率似乎在某个点卡住了。
您有什么建议吗?
提前感谢。
是的,我这里有很多建议
https://machinelearning.org.cn/improve-deep-learning-performance/
非常感谢您,
它在学习如何在神经网络中使用预训练嵌入方面对我帮助很大
很高兴听到这个消息。
嗨,Jason,感谢您提供的精彩资料。
我有一个疑问,想对1200个文档列表进行嵌入,然后将其作为分类模型的输入,根据电影剧本文本预测电影票房……
我的问题是……如果我想用真实数据集的词汇训练嵌入,那么我如何才能对未训练的其余数据集进行分类呢?我可以使用训练中学到的嵌入作为分类模型的输入吗?
好问题。
您必须确保训练数据集能代表更广泛的问题。除非您更新模型,否则在训练期间未见过的任何单词都将由分词器标记为零(未知)。
谢谢你,Jason。我一拿到结果就会在这里分享。
我也想感谢您的出色平台,它对我非常有帮助。
不客气。
又一篇好文章!似乎每个批次中的所有嵌入都已更新,我认为这不应该发生。您知道如何只更新每次通过的嵌入吗?这是出于计算原因或其他与问题定义相关的原因。
我不太明白你的意思,能详细说明一下吗?
你好Jason,我想感谢你这篇文章,它真的很有趣且易懂。
我重复使用了脚本,但没有使用“docs”和“labels”列表,而是使用了IMDB电影评论数据集。问题是准确率无法超过50%,并且所有epochs中的损失都稳定在0.6932。
你对此有什么看法?
我在这里有一些建议
https://machinelearning.org.cn/improve-deep-learning-performance/
好的,我会去看看,谢谢Jason
谢谢你的文章。你能不能也提供一个只用一个嵌入层训练模型的例子?我正尝试用 Keras 做同样的事情,但问题是 fit 方法需要标签,而我没有。我的意思是,我只有一堆文本文件,我正在尝试为它们找到映射。
模型通常只有一个嵌入层。你具体是什么意思?
你好,
感谢您出色的解释!
我对未知词有一些疑问。
一些预训练的词嵌入,比如GoogleNews嵌入,也包含一个名为“UNKNOWN”的标记的嵌入向量。
1. 我可以使用这个向量来表示训练集中不存在的词,而不是全零向量吗?如果可以,我应该如何将这个向量加载到Keras嵌入层中?它应该加载到嵌入矩阵的第0个索引位置吗?
2. 另外,我可以使用Tokenizer API来帮助我将所有未知词(不在训练集中的词)转换为“UNKNOWN”吗?
谢谢你。
是的,找到未知词的整数值,并用它来赋值给词汇表中没有的所有词。
你好,
如果词嵌入不包含我们输入到模型中的词,如何解决这个问题?
1) 是否可以在嵌入矩阵中加载额外的词(除了词汇表中的词)?
或者您有什么其他优雅的方法可以建议吗?
它被标记为“未知”。
嗨。非常感谢你的帖子。我是Python和深度学习的新手!
我有240,000条推文训练集(50%男性和50%女性类别)。以及120,000条推文测试集(50%男性和50%女性)。我想在Python中使用LSTM,但在“fit”方法中出现以下错误:
ValueError: 检查输入时出错:期望lstm_16_input具有3个维度,但得到形状为(120000, 400)的数组
你能帮我吗?
这看起来是您的数据与模型不匹配,您可以更改数据或更改模型。
嗨 Jason,感谢您的这篇文章。
我收到了这个错误
TypeError: ‘OneHotEncoder’ 对象不可调用
如何解决?
谢谢
我在这里有一些建议
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
嗨,我有2个带有嵌入层的模型,我如何合并这些模型?
谢谢
你具体是什么意思?一个集成模型?
嗨Jason,很棒的教程,我对这一切都很陌生。我有一个疑问,您在嵌入层使用glove,但在拟合时直接使用padded_docs。padded_docs中的向量与glove没有关联。我确信我遗漏了一些东西,请指教。
填充只是添加“0”以确保序列长度相同。它不影响编码。
你好,Jason。考虑到“3. 学习嵌入的例子”,我在嵌入层之后添加了“model.add(LSTM(32, return_sequences=True))”,我想了解会发生什么。这个LSTM层返回的参数数量是“5248”,我不知道如何计算它。谢谢。
LSTM中的每个单元都将整个嵌入作为输入,因此必须为嵌入中的每个维度分配一个权重。
嗨,Jason,
您有任何示例展示如何将双向LSTM应用于文本(即使用词嵌入)吗?
它和使用LSTM一样,只是LSTM被封装在双向层包装器中。
这是一个如何使用双向包装器的示例
https://machinelearning.org.cn/develop-bidirectional-lstm-sequence-classification-python-keras/
我很有兴趣使用预测函数来预测新文档。例如,“出局!”我的理解是,如果想要预测的文档中有一个或多个词没有参与训练,那么模型就无法预测。解决方案是不是简单地在足够的文档上进行训练,以确保词汇量足够广泛,从而以这种方式进行新预测?
是的,或者在预测时将新词标记为“未知”。
你好Jason,嵌入层的输出是一个4x8矩阵,有什么原因吗?
不,这只是一个演示概念的例子。
嗨,Jason。非常感谢这篇优秀的教程。我对Keras嵌入层有一个小问题。
vocab_size = len(t.word_index) + 1
t.word_index 从1开始,到15结束。因此,词汇表中总共有15个词。那么我们为什么需要在这里加1呢?
非常感谢您的帮助!
这些词是1-偏移的,索引0保留给“未知”词。
您介意详细说明这个答案吗?我仍然不太清楚
当然,哪一部分不清楚?
在这种情况下,1-偏移究竟是什么意思?
如果“索引0保留给未知词”,那是否意味着你可以忽略它们?
如果我改用这个
vocab_size = len(t.word_counts.keys()) + 1
我还需要加1吗?
词汇表中没有的词被赋值为0,该值映射到第一个向量的索引,代表未知词。
词汇表中的第一个词映射到索引1处的向量。第二个词映射到索引2处的向量,依此类推,直到处理完所有向量。
这有帮助吗?
谢谢您的回复,但我还是不太明白。我的理解是,当我使用t.word_counts而不是t.word_index(不确定这是否有所不同)时,我会得到类似这样的东西:
OrderedDict([('word1', 35), ('word2'), 232))
那么,如果我使用len(t.word_counts),在这种情况下它会给我2。我为什么要加1呢?
也就是说,如果我使用t.word_counts,当我打印它时,我没有看到任何未知词。
我们没有在计数上加1。我们没有触碰词的有序字典。
我们只是在词汇表中添加了一个名为“未知”的词,它映射到嵌入中的第一个向量。
Tensorflow文档也说要加1,但我真的不确定为什么
https://tensorflowcn.cn/api_docs/python/tf/keras/layers/Embedding
为了给“未知”词——词汇表中没有的词——留出空间。
加1意味着在词汇表中增加一个词,第一个词映射到索引0——第零个词。
您知道有没有解释为什么我们必须加1的资源吗?我明白这是因为未知词,所以我们将给定词汇量增加1。但我就是不明白为什么。
我们不必这样做,我们可以简单地忽略词汇表中没有的词。
嗨,Jason,
如果我有三列(字符串类型)多元数据,其中一列是分类数据,另外两列不是。我用LabelEncoding()对其进行整数编码,然后使用MinMax、StandardScaler等特征缩放方法对编码后的数据进行缩放,再将其输入异常检测模型,这可以吗?尽管ROC显示出令人印象深刻的结果。但是这样预处理文本数据是否有效?
谢谢你。
也许可以尝试一下并比较性能。
我试过了,它显示了接近100%的ROC。我的意思是,这样预处理文本数据是否准确?因为当我查看您关于预处理文本数据的帖子时,在将其编码为整数后,文本数据没有进行特征缩放(MinMax、StandardScaler等)。我担心我的数据预处理方式不准确。
通常文本被编码为整数,然后进行独热编码或映射到词嵌入。不需要其他数据准备(例如缩放)。
你好
我尝试使用Keras在R和Python中对文本数据进行多类别分类。
在Python中,我能够使用inverse_transform()方法从编码后的类别值获取预测标签。但是当我在R中使用CatEncoders库进行同样的操作时,会得到一些NA标签。有什么原因吗?
无需转换预测,模型可以直接进行类别或概率预测。
嗨,Jason,
感谢您的分享!我有一个关于词嵌入的问题。如果我错了,请纠正我:这里创建的词嵌入只包含训练/测试集中的词。我认为包含GloVE文件中所有词汇的词嵌入会更好?例如,如果在生产中,我们遇到一个训练/测试集中没有的新词,但它属于GloVE词汇表,在这种情况下,我们可以捕获生产词的含义,尽管我们在训练/测试集中没有看到它。我认为这会使情感分类问题在训练集较小的情况下受益?
谢谢!
此致
小红
通常,您会仔细选择词汇表。如果您希望保留一个比项目所需的词汇表更大的词汇表,“以防万一”,那就去做吧。
Jason,
嵌入是否有非文本应用?例如,我有一大组分类变量,每个变量都有大量级别,这些变量输入到分类模型中。在这种情况下我可以使用嵌入吗?
Rahul
是的,嵌入对于分类数据非常棒!
你好 Jason……
非常感谢您这篇精彩的帖子。它极大地丰富了我的知识。
我对keras提供的text_to_sequence和one_hot方法有一个疑问。它们都使用您的示例给出了相同的编码文档。如果它们给出相同的输出,那么我们何时应该使用text_to_sequence,何时应该使用one_hot?
再次感谢您这篇精彩的帖子。
使用您喜欢的方法。
嗨,Jason,
您的帖子真的很棒。感谢您写出如此精彩的帖子。
我有一个疑问,既然我们已经从word2vec或glove获得了词的向量表示,为什么人们还要使用嵌入层呢?使用这两个预训练模型,我们已经获得了每个词相同大小的向量表示,如果找不到词,我们可以分配相同大小的随机值。在获得向量表示之后,为什么我们还要传递给嵌入层?
谢谢
通常,神经网络中学习到的嵌入表现更好,因为它特定于模型和预测任务。
嗨,Jason,
谢谢你的回复。
如果我设置 trainable = False。那么,当我已经使用 word2vec 或 glove 在序列中为每个单词提供了向量表示时,还需要使用 Embedding 层吗?
谢谢
是的,如果你愿意,可以在训练期间保持嵌入固定。根据我的经验,结果通常不如预期。
你好Jason,非常感谢这篇非常好的教程。我有一个问题:我在IMBD情感分析数据集上训练了您的模型。模型的准确率达到了80%。但是我的嵌入效果非常差。
首先一个简短的细节,我使用了 `one_hot`,它使用了哈希技巧,但我使用了 `md5`,因为默认的 `hash` 函数在不同运行中不一致,Keras 的文档中提到了这一点(所以要保存模型并预测新文档,这不好,对吗?)。
但重要的是我的词嵌入非常差,我创建了一个将小写词和嵌入(大小为8)映射的字典。遵循这个:https://stackoverflow.com/questions/51235118/how-to-get-word-vectors-from-keras-embedding-layer 我暂时没有使用Glove向量。
我测试了搜索最相似的词,结果“good”得到了随机的词(holt, christmas, stodgy, artistic, szabo, mandatory…)。我将词汇大小设置为100000。当然,由于哈希技巧,两个词可以有相同的索引,所以我没有考虑1.0的相似度。我认为糟糕的词向量嵌入是由于我们在整个文档而不是像word2vec那样在上下文中训练嵌入,您认为呢?
一般来说,根据我的经验,模型学习到的嵌入比预训练的嵌入表现更好。
你好,这是一篇很棒的教程。您的所有教程都非常有帮助!谢谢。
我想找到三个不同希腊语句子的嵌入(用于分类)。然后我想对它们进行配对合并并拟合我的模型。
我读过您的教程“如何使用Keras函数式API进行深度学习”,这对于合并非常有帮助。
我的问题是:有没有办法在将其用作模型输入之前进行计算?我必须有三个不同的模型来计算嵌入吗?
提前感谢您。
是的,如果你愿意,可以手动准备输入:每个词映射到一个整数,整数将是嵌入中的一个索引。从那里你可以检索每个词的向量,并将其用作模型的输入。
谢谢!!!
嗨,Jason,
非常感谢您精彩的解释。在阅读了许多其他资源后,我直到阅读了这篇文章才理解嵌入层。我有一些问题,如果您能抽出时间回答,我将不胜感激。
1) 在您的代码中,您在嵌入层之后和密集层之前使用了一个展平层。在其他一些地方,我注意到使用GlobalAveragePooling1D()层代替了展平。您能解释一下全局平均池化是什么,以及为什么它用于文本分类吗?
2) 您在其中一个评论中解释说,每个单词在训练前后都只有一个向量表示。所以只是为了确认,当单词x输入到嵌入层时,输出总是更新代表x的同一个向量吗?例如,对于词汇量大小为500,嵌入维度为10([500, 10]输出形状),如果单词x是输出中的第一个向量([0,10]),那么每次输入单词x时,第一个向量([0, 10])都会更新,而不是如果单词不存在?
3) 选择嵌入维度的直觉是什么?
再次感谢您,Jason。我将等待您的回复。
Mohit
这两种方法都可以使用,它们做的事情相同。也许可以尝试两种方法,看看哪种最适合您的特定数据集。
给定词的向量是学习出来的。模型训练完成后,每个词的向量是固定的。如果在训练期间某个词不存在,模型将无法支持它。
嵌入必须足够大,才能捕获词之间的关系。通常100到300对于大型词汇量来说已经足够了。
对初学者非常有用的帖子。但我对嵌入向量的大小有一个疑问。正如您在帖子中提到的——
“嵌入层有一个50的词汇表和4的输入长度。我们将选择一个8维的小嵌入空间。
该模型是一个简单的二元分类模型。重要的是,嵌入层的输出将是4个8维向量,每个词一个。”
我不明白为什么嵌入层的输出应该是4个向量。如果它与输入长度有关,请解释一下如何?另外,“每个词一个”这个短语,我也不明白。
一个好的经验法则是从长度50开始,然后尝试增加到100或200,看看是否会影响模型性能。
嗨Jason,我在CNN中使用词袋作为特征时遇到了麻烦。你有没有关于实现基于BoW的CNN的想法?
我不太清楚你为什么/如何将BoW编码的文档传递给CNN——因为所有的空间信息都会丢失。听起来是个坏主意。
嗨!感谢您提供的好教程。我有一个关于嵌入的问题。使用嵌入层训练嵌入与使用预训练嵌入相比,性能如何?使用预训练嵌入时,训练是否更快,模型所需时间是否更少?
感谢您的回答。
根据我的经验,作为模型一部分训练的嵌入似乎表现更好。
你好,很棒的帖子!
我想了解更多关于Keras嵌入层中词汇量大小的信息。我正在使用希腊语和意大利语。您有什么科学论文可以推荐吗?
非常感谢!
也许可以尝试几种不同的词汇量大小,看看它对您的数据集的模型性能有何影响?
好的,非常感谢!
嗨 Jason
在使用预训练嵌入矩阵的无监督模型时,需要改变什么?
如果你想使用弱监督怎么办?
您可以按照此处的示例进行操作
https://machinelearning.org.cn/use-word-embedding-layers-deep-learning-keras/
好
谢谢。
嗨,Jason,
对于独热编码器,如果我们给出了新的测试集,我们如何使用one_hot函数来获得与训练集相同的矩阵空间?因为我们不能为测试集设置一个单独的one_hot编码器。
非常感谢。
您可以保留用于准备数据的编码器对象,并将其用于新数据。
你好,
我经常看到像您这样的实现,其中嵌入层是根据包含所有词的word_index构建的,例如使用Keras预处理Tokenizer API构建。但是,如果我用Tokenizer和词汇量限制(使用num_words)拟合我的语料库,为什么我需要一个与总唯一词数量相同大小的嵌入层?这不会浪费空间吗?构建一个大小适合我所需词汇量限制的嵌入层有问题吗?
没关系,空间很小。
这可以很好地激励您确保您的词汇表只包含做出准确预测所需的词。
嗨,Jason先生,
确实是优秀的教程!
我有一个关于嵌入层维度的问题,您能帮帮我吗?
e = Embedding(200, 32, input_length=50)
我们如何决定选择out_dim的大小,这里是32?这个值有什么特定的原因吗?
提前感谢
莉娜
您可以尝试不同的输出维度大小,并评估它们对您的特定数据集的模型性能有何影响。
如果您不确定,50或100是一个很好的起点。
你好,
我使用带有 glove 的词嵌入训练了我的模型,但请告诉我如何准备测试数据以使用训练好的权重预测结果。我仍然没有找到任何遵循整个过程的帖子。特别是带有 glove 的词嵌入
词嵌入不能预测任何东西。我不明白,也许你能详细说明一下?
您好,Jason,
感谢您的帖子。我有一个关于您实际拟合的嵌入数据的问题。我在模型编译后打印了 padded_docs。在我看来,打印出的矩阵不是嵌入矩阵。它是一个整数矩阵。所以我认为您在CNN中拟合的不是嵌入,而是您定义的整数矩阵。您能帮我解释一下吗?非常感谢。
是的,padded_docs 是整数,它们被馈送到嵌入层,该层将每个整数映射到一个8元素的向量。
这些向量的值然后通过训练网络来定义。
嗨,Jason,
我正在进行字符嵌入。我的数据集包含原始的HTTP流量,包括正常和恶意的。我使用了Tokenizer API对我的数据进行整数编码,每个字符都有一个分配给它的索引。
请让我知道我是否理解正确
我的数据被整数编码为1-55之间的值,因此我的input_dim是55。
我将从输出维度32开始,并根据需要修改此值。
现在对于input_length,我有点困惑如何设置这个值。
我的数据集中数字字符串的长度不同,最长的是666。我是否将input-length设置为666?如果这样做,长度较短的序列会发生什么?
感谢您的帮助!
另外,我应该将输入维度设置为大于55的值吗?
你是说词嵌入而不是字符嵌入吗?
我没有任何嵌入字符的例子——我不确定它是否有效。
我指的是字符嵌入。我使用了分词器并将字符级别设置为True。
我不知道如何对http流量的查询字符串使用词嵌入,因为它们不是由实际单词组成的,而只是一串字符。
我正在设计一个字符级神经网络,用于检测http请求中的参数注入。
结果将以二进制格式表示,如果请求正常则为0,如果恶意则为1。
所以您不认为字符嵌入在这里有用?
抱歉,我没有字符嵌入的例子。
不过,您应该能够向模型中的嵌入层提供整数编码字符的字符串。它会很像词嵌入,只是基数较低(可能小于100个字符)。另外,我不期望得到好的结果。
你到底遇到了什么问题?
我发现 `vocab_size = len(t.word_index) + 1` 是错误的。这个索引不仅忽略了 `Tokenizer(num_words=X` 参数,而且存储的单词比实际编码的单词更多。
我没有词数限制地拟合了我的文本,然后使用分词器对相同的文本进行编码,结果 `word_index` 的长度大于 `max(max(encoded_texts))`。
这真是令人惊讶!
你确定你的代码没有bug吗?
嗨 Mario,
是的。我今天刚注意到 Keras Tokenizer 的 num_words 问题。我想 GitHub 上已经记录了多个相关问题
https://github.com/keras-team/keras/issues/8092
你好Jason,你好吗?
我正在用词嵌入做我的文本摘要硕士论文,现在我有很多问题,我该如何使用这些特征,以及哪种神经网络算法最好。请问您能给些指导吗……
我相信这会有帮助
https://machinelearning.org.cn/encoder-decoder-models-text-summarization-keras/
谢谢你 Jason…这真的很有帮助…
很高兴听到这个消息。
嗨,Jason,
这整篇文章都非常有用。它帮助我编写了我的初步实现。
我有一个关于Keras中的Input()和Embedding()的问题。
如果我有一个预训练的词嵌入。在这种情况下,我应该使用Embedding还是Input?
是的,嵌入向量被加载到Embedding层中,并且该层可能被标记为不可训练。
如果在测试中我们遇到了一些训练文本中没有的新词怎么办?
它就无法通过嵌入层,对吗?
它们将被映射到0或“未知词”。
嗨,Jason
我想问一下如何保存我学到的词嵌入?
您可以使用层的get_weights()方法,并直接将向量保存为numpy数组。
或者保存整个Keras模型
https://machinelearning.org.cn/save-load-keras-deep-learning-models/
我能构建一个只用于学习嵌入矩阵的网络吗?
是的,它被称为word2vec模型,这里是操作方法
https://machinelearning.org.cn/develop-word-embeddings-python-gensim/
你好,
我有一个文本相似性应用程序,我将皮尔逊相关系数作为 Keras 指标来衡量。
在许多 epoch 中,我注意到相关系数值为 nan。
这是正常的还是模型有问题?
您可能需要调试模型以找出 NAN 的原因。
也许是梯度爆炸或梯度消失?
你是说我必须调整激活函数吗?
我使用elu激活函数和Adam优化函数,
你是说我必须改变其中任何一个并查看结果吗?
也许可以。
尝试relu。
尝试批量归一化。
尝试更小的学习率。
…
我能知道您所说的调试模型是什么意思吗?
是的,这里有一些想法
– 考虑积极地将代码削减到最低限度。这将帮助您隔离问题并专注于它。
– 考虑将问题削减到只有一个或几个简单示例。
– 考虑寻找其他类似的代码示例,这些示例有效,并缓慢修改它们以满足您的需求。这可能会暴露您的错误。
– 考虑将您的问题和代码发布到 StackOverflow。
vocab_size = len(t.word_index) + 1
为什么我们需要将词汇量增加1???
这是为了我们可以将0保留给未知词,并将已知词从1开始。
非常感谢这项出色的工作……我们现在是2019年7月,仍在从中受益。
谢谢。我 стараюсь写出经久不衰的教程,使其保持有用。
亲爱的 Jason,
非常感谢您的详细解释和代码示例。
然而,我仍然想知道的是,如何将嵌入与其他变量结合起来,即有一些数值或分类变量,然后有一个或两个文本变量。因为我看到您在 model.fit 中输入了填充文档(仅文本)。但是我如何添加其他变量呢?输入总是只有一个文本变量似乎不切实际。
好问题。您可以为每个嵌入设置一个单独的模型输入,为其他数字静态变量设置一个。
这称为多输入模型。
这会有帮助
https://machinelearning.org.cn/keras-functional-api-deep-learning/
感谢 Jason 的精彩工作和示例。这真的很有帮助。
我的最后一条评论与此相关:https://machinelearning.org.cn/develop-word-embeddings-python-gensim/!
不客气,我很高兴它有所帮助。
谢谢你,Jason Brownlee,这非常有趣和清晰。
如果我有两个输入呢?
例如,我正在进行 Text-to-SQL 任务,这需要两个输入:用户问题和表模式(列名)。
我该如何处理?如何进行嵌入?使用两个嵌入层吗?
感谢您的帮助。
您可以设计一个多输入模型,我在这里给出示例
https://machinelearning.org.cn/keras-functional-api-deep-learning/
啊,好的,这也很有趣,谢谢!
您能确认一下上述架构,以便在同一个模型中编码用户问题和表模式吗?
(1) userQuestion ==> One-hote-endoding ==> Embedding(GloVe) ==> LSTM
(2) tableShema ==> One-hote-endoding ==> Embedding(GloVe) ==> LSTM
(1) 连接 (合并) (2) ==> 模型的其余层……。
谢谢 Jason。
无需进行独热编码,文本可以编码为整数,整数通过嵌入映射到向量。
好的,清楚了,谢谢。
注意力机制只能通过合并来完成吗?
不,如果您愿意,可以在每个输入上使用注意力。
我应该对两个输入(用户问题和表模式)分别进行注意力处理,还是可以在合并两个输入之后进行?
测试多种不同的模型类型,看看哪种类型最适合您的特定数据集。
好的,谢谢你 Jason!!
不客气。
我想知道预训练的 word2vec,目前还没有这么好的教程。我正在寻找实现预训练的 word2vec,但我不知道是应该遵循 Glove 的相同步骤,还是寻找其他资源?
谢谢 Jason 先生,您在机器学习方面对我启发很大
我在这里展示了如何拟合一个独立的 word2vec
https://machinelearning.org.cn/develop-word-embeddings-python-gensim/
为什么你的嵌入层不使用 mask_zero=True?这似乎是必要的,因为你正在用0填充句子。
很好的建议,不确定这个参数在我写这些教程的时候是否存在。我当时用的是掩蔽输入层。
嗨,能帮我一个问题吗?
我正在处理一个数据集,其中有一个城市列作为特征,并且有很多不同的城市。因此,我为这个特征创建了一个嵌入层。首先,我使用了这个命令
data['city']= data['city'].astype('category')
data['city']= data['city'].cat.codes
之后,每个不同的城市都被分配了一个从0开始的值
所以,我很困惑,当测试数据有一个未训练的输入时,这个嵌入层是如何工作的。我看到您说当这种情况发生时,我们必须将0作为输入,但是0
它与某个城市有关。我应该从1开始给城市分配这些值吗?
好问题。
通常,未见类别被分配为 0,表示“未知”。
0 应该保留,实际编号应该从 1 开始。
谢谢你,你总是帮我很多!
非常欢迎你,Nathalia!
嗨,Jason。
感谢您如此精彩的教程。我困惑的是,当我们谈论学习到的词嵌入时,我们是考虑嵌入层的权重还是嵌入层的输出。
换句话说,当我们使用预训练的嵌入,比如说“glove.6B.50d.txt”时,这些词嵌入是权重还是层的输出?
它们是同一回事。整数被映射到向量,这些向量是嵌入的输出。
嗨,Jason,
我是机器学习新手,尝试不同的东西,您的帖子是我遇到的最有帮助的,它对我理解帮助很大,谢谢!
在这里我想我理解了过程,但我还有一个更深层的问题,关于嵌入。如果我理解正确的话,这种嵌入将一组词作为点映射到另一个维度空间。您的示例中令人惊讶的事实是,我们从一个维度为4的空间传递到一个维度为8的空间,所以乍一看可能不会被视为一种改进。
但我仍然认为嵌入使得新空间中的点更均匀地分布,我说的对吗?那么我不明白几件事
-一个词出现的上下文是如何发挥作用的?经常靠近的其他词也会在新空间中由更接近的点表示吗?
-为什么它必须是整数?为什么它更适用于词编码?我的意思是我们可以想象同样的过程也可能对图像有帮助。或者它只是一个为词文档量身定制的降维技术?
无论如何,感谢您的见解
不是均匀分布,而是以一种保留或最佳捕捉它们关系的方式分布。
上下文定义了嵌入中捕捉到的关系,例如哪些词与其他词一起出现。它们的亲近度。
每个词都有一个向量。最简单的方法是将词映射到整数,并将整数映射到矩阵中向量的索引。没有其他原因。
很好的问题!
Jason,非常感谢您的时间和精力!
我的问题与此行有关——
“e = Embedding(vocab_size, 100, weights=[embedding_matrix], input_length=4, trainable=False)”
这里您使用了 weights=[embedding_matrix],但是没有关系表明哪个词对应哪个向量。然后,它为每个文档生成一个 4*100 矩阵(例如 [ 6 2 0 0])。它将如何准确地提取与 6,2,0,0 相关的向量?
向量是有序的,您可以使用数组索引检索每个词的向量,例如词 0、词 1、词 2、词 3 等。
你好 Jason,
我正在寻找关于 Python(numpy pandas…以及 ML DL 和 NLP 工具)和 Keras 的有趣培训!
有什么建议吗?
如果您正在研究 NLP,这可能是一个很好的起点。
https://machinelearning.org.cn/start-here/#nlp
再次感谢 Jason!!
不客气。
感谢您的文章,我将为意大利语文档运行它。有没有涵盖意大利语词汇的 GoogleNews 预训练 word2vec?
好问题,我不太清楚,抱歉。
哈喽 Jason,我可以在这个模型中加入 Dropout 吗?
我看不出为什么不。
e = Embedding(vocab_size, 100, weights=[embedding_matrix], input_length=4, trainable=False)
参数 – weights=[embedding_matrix] – 代表什么?是嵌入层的权重还是输入?
权重就是向量,例如词汇表中每个词的向量。
_________________________________________________________________
层(类型) 输出形状 参数 #
=================================================================
embedding_1 (Embedding) (None, 4, 8) 400
_________________________________________________________________
flatten_1 (Flatten) (None, 32) 0
_________________________________________________________________
dense_1 (Dense) (None, 1) 33
=================================================================
总参数:433
可训练参数:433
不可训练参数: 0
_
您能解释一下嵌入层学习到的权重数量吗?现在我们有10个文档,嵌入层从4到8。这里实际上会学习多少个权重参数。我的理解是应该只有 (4+1)*8 = 40 个权重需要学习,包括偏置项。为什么它会单独为所有文档学习权重 (10*(4+1)*8 = 400)?
嵌入中的权重数量是向量长度乘以向量(词)数量。
嗨,Jason
在这个例子中,这是哪种神经网络架构?它不是 LSTM,也不是 CNN。它是多层感知器模型吗?
我们只是在处理嵌入。我想有了一个输出层,你可以称它为 MLP。
你好,感谢这篇优秀的文章。我尝试在一个基于 Keras 的分类器中使用预训练的词嵌入,而不是随机数。然而,在构建嵌入矩阵并按照以下方式将其添加到嵌入层后,在训练 epoch 期间,所有准确性值都相同,没有发生学习。但是,在删除“weights=[embedding_matrix]”后,它工作得很好,达到了 90% 的准确性。
layers.Embedding(input_dim=vocab_size, weights=[embedding_matrix],
output_dim=embedding_dim,
input_length=max_len,trainable=True)
这种奇怪行为的原因可能是什么?
谢谢
专门针对您自己的数据进行的嵌入通常比通用嵌入更好。
快速提问。在使用预训练嵌入(MUSE)的嵌入层中,将 trainable=True 设置为可以吗?
注意:当我设置 trainable=True 时,模型不会过拟合。如果我设置 trainable=False,模型预测得不好。
是的,尽管您可能希望使用较小的学习率,以确保不会冲掉权重。
非常感谢您的回复。目前我正在使用 0.0001 的学习率。
“Adam(learning_rate=0.0001)”
也许使用 SGD 代替 Adam,因为 Adam 会为每个模型参数改变学习率,并且可能会变得非常大。
或者至少比较 Adam 和 SGD 的结果。
嗨,Jason,
谢谢您的帖子。我有一个问题。我使用的数据包括分类和数值特征。比如说,有些特征是成本和时间,而另一些是邮政编码。我应该如何编写代码?构建单独的模型并将它们连接起来吗?谢谢
很好的问题!
这些特征必须单独准备,然后聚合。
我喜欢这样做的两种方法是:
1. 手动。单独准备每种特征类型,然后连接成输入向量。
2. 多输入模型。单独准备特征,并将不同的特征输入到模型的不同输入中,让模型连接特征。
这有帮助吗?
分类变量是否应该使用独热编码转换为数值变量?
可以,也可以使用嵌入。
如果您有多变量时间序列,并且您知道它们有意义地连接(例如 x 和 y 的轨迹),那么在将它们馈入嵌入之前放置一个 Conv 层是否有意义?
您所说的“准备”特征是什么意思?
通常情况下,嵌入是第一步,例如对输入的解释。
“准备”意味着以您想要的任何方式进行转换,例如编码或缩放。
谢谢您的回答!如果我能再问一个问题:多变量数值数据的嵌入是否不常见?我见过很少使用它的工作。
嵌入用于分类数据,而不是数值数据。
嗨,Jason,
我使用了一个例子,其中词汇量大小设置为200,训练样本包含大约20个不同的词。
当我使用 ** layers[0].get_weights()[0]** 检查嵌入(向量)时,我得到一个包含200行的数组。
1/ 我如何知道每个词(从我得到的20个词中)对应的向量?
2/ 既然我只使用了20个词,那180个(200-20)向量是从哪里来的?
提前感谢。
词汇量大小和词数是同一个东西。
我想你可能混淆了嵌入的大小和词汇量?
每个词都被分配一个数字(0, 1, 2 等),向量的索引映射到词,向量 0 是词 0,以此类推。
感谢您的回答,Jason,
我将澄清我的问题
词汇量大小是 200,这意味着词的数量是 200。
但实际上我只处理了 20 个词(我的训练样本中的词):比如说 word[0] 到 word[19]。
那么,在嵌入之后,vector[0] 对应于 word[0],依此类推。但是 vector[20].. vector [30] … 它们对应什么呢?
我没有 word[20] 或 word[30]。
如果您定义了200个词的词汇表,但在训练集中只有20个词,那么不在训练集中的词将具有随机向量。
好的。谢谢你。
我想以 GloVe 保存其模型为文本文件(词后跟其向量)的相同方式保存我自己的预训练模型。我该怎么做?
谢谢你
您可以从嵌入层通过 layer.get_weights() 提取权重,然后枚举向量并以您喜欢的格式保存到文件中。
我是Python新手,我不明白你说的枚举是什么意思……我应该从哪个层获取权重?
您可以从嵌入层获取向量。
您可以保留对构建模型时嵌入层的引用,或者通过索引(例如 model.get_layers()[0])或名称(如果您命名它)检索该层。
枚举意味着循环。
你好,杰森!
谢谢你的文章!
我一直在思考可学习嵌入层的 input_dim。
您将其设置为 vocab_size,在您的示例中是 50(哈希技巧的上限),这比实际词汇量 15 大得多。
Keras 中 Embedding 的文档写道:
“词汇表的大小,即最大整数索引 + 1。”
这很模糊。
我用了一些数字来实验 vocab_size,但没有发现任何系统性的差异。
对于更实际的例子,这真的有关系吗?
您能简单说几句吗?
再次感谢
较小的词汇量意味着您将拥有较少的单词/词向量,从而模型更简单,学习速度更快/更容易。代价是它的性能可能会更差。
这是一个权衡:大/慢但好,小/快但稍差。
谢谢你,Jason!
我可能没有解释清楚
词汇表中的*实际*单词数量是相同的 (14)。
区别在于 Embedding() 的 input_dim 值。
在示例中,您选择了 50,这个值足够高以防止编码冲突,但同时也
在其中一个案例中将其用作 input_dim。
Michael
我明白了。
我以为问题是“词汇表的大小,即最大整数索引 + 1”。既然这个例子中有 14 个词,为什么词汇表大小不是 15,而是 50?
词汇量的大小,也是嵌入空间的大小。它们是不同的——以防引起混淆。
嵌入中必须有 size(vocab) + 1 个向量,以便为“未知”留出空间,例如索引 0 处的向量。
Jason:在这个例子中,使用了“one_hot”函数而不是“to_categorical”函数。第二个是真正的独热表示,第一个只是为每个词创建一个整数。为什么这里没有使用 to_categorical?它们是不同的,对吧?
这个函数命名不当,但它确实对单词进行了整数编码。
https://keras.org.cn/preprocessing/text/
非常感谢 Jason!在第 3 节“学习嵌入示例”中,您能详细说明嵌入层中正在训练的 400 个参数是什么吗?谢谢
是的,每个向量都映射到一个 8 元素向量,词汇表有 50 个词。因此是 50*8 = 400。
Jason,为什么嵌入层的输出形状是:(4,8)?
它应该是 (50,8),因为词汇量大小是 50,我们正在为词汇表中的所有词创建嵌入。
词汇量大小是层中向量的总数——支持的词的数量,而不是输出。
输出是输入词的数量 (8),其中每个词具有相同的向量长度 (4)。
这是笔误吗?输出是输入词的数量(4),其中每个词的向量长度相同(8)。
嗨 Sean……我们不认为这是笔误。当您执行代码时会发生什么?
嗨,我运行文件时需要一些帮助。
(wordembedding) C:\Users\Criz Lee\Desktop\Python Projects\wordembedding>wordembedding.py
回溯(最近一次调用)
文件 “C:\Users\Criz Lee\Desktop\Python Projects\wordembedding\wordembedding.py”, 第 1 行,在
from numpy import array
文件 “C:\Users\Criz Lee\Anaconda3\lib\site-packages\numpy\__init__.py”, 第 140 行,在
from . import _distributor_init
文件 “C:\Users\Criz Lee\Anaconda3\lib\site-packages\numpy\_distributor_init.py”, 第 34 行,在
from . import _mklinit
ImportError: DLL 加载失败:找不到指定的模块。
请指导..谢谢
看起来您的开发环境有问题。
这个教程可能会有所帮助
https://machinelearning.org.cn/setup-python-environment-machine-learning-deep-learning-anaconda/
嗨 Jason,我尝试了您提供的网址,但仍然无法解决问题。
我基本上输入了
1. conda create -n wordembedding
2. activate wordembedding
3. pip install numpy (安装版本 1.16)
4. 运行 wordembedding.py
错误显示
文件 “C:\Users\Criz Lee\Desktop\Python Projects\wordembedding\wordembedding.py”, 第 2 行,在
from numpy import array
ModuleNotFoundError: 没有名为 'numpy' 的模块
请指导..谢谢
听到这个消息我很难过。我不是调试工作站的专家,也许可以尝试在 stackoverflow 上发帖。
嗨,Jason:如何使用在训练数据上拟合的 Tokenizer 对象编码新文档?似乎没有函数可以从 tokenizer 对象返回编码器。
您可以保存分词器,并以与分词器拟合后处理训练数据相同的方式使用它来准备新数据。
“保存分词器”是什么意思?分词器是一个对象,而不是模型。
它和模型一样重要,从这个意义上说,它是模型的一部分。
您可以使用 pickle 将 Python 对象保存到文件。
简短的帖子……我对阅读用于序列标注任务的预训练词嵌入很感兴趣。
太棒了,上面的教程有帮助吗?
你好先生,
我无法理解向量空间的意义?
您为第一个问题给出了 8,glove 向量为每个词有 100 维度。
这些向量空间背后的思想是什么,每个维度的值告诉我们什么?
谢谢你 :)
向量空间的大小并不太重要。
更重要的是,模型学习到了一种表示,其中相似的词在向量空间中将具有相似的表示(坐标)。我们无需指定这些关系,它们是自动学习的。
谢谢先生的回答。我清楚地理解了向量空间。
我还有一个问题——如果我将词汇量大小声明为 50,而我的训练数据中有超过 50 个词,那些额外的词会发生什么?
出于同样的原因,我无法理解 glove 向量的这一行——
“最小的嵌入包是 822MB,名为“glove.6B.zip”。它在一个包含十亿个 token(单词)的数据集上训练,词汇量为 40 万个单词。”
那 60 万个词呢?
不在词汇表中的词被标记为 0 或未知。
你好,
我有一个词列表作为我的数据集/训练数据。因此,我按照以下方式运行您的 glove 代码
—-错误是——
ValueError 回溯 (最近一次调用)
in ()
8 values = line.split()
9 words = values[0]
—> 10 coefs = asarray(values[1:], dtype='float32')
11 embeddings_index[words] = coefs
12 f.close()
/usr/local/lib/python3.6/dist-packages/numpy/core/_asarray.py in asarray(a, dtype, order)
83
84 “””
—> 85 return array(a, dtype, copy=False, order=order)
86
87
ValueError: could not convert string to float: '0.1076.097748'
————————————————————————————-
能帮帮我吗
这是我在这里回答的一个常见问题
https://machinelearning.org.cn/faq/single-faq/can-you-read-review-or-debug-my-code
我查阅了常见问题,没有找到任何与“ValueError: could not convert string to float:”相关的问题
我建议遵循我链接到的特定常见问题解答中的说明。
您好,Jason Brownlee
希望您一切安好,感谢您撰写如此精彩的文章。我想向您请教一个我遇到的问题。
我使用 glove 词嵌入在 imdb 电影数据集上创建了 keras 深度学习模型。我使用了 50 维,但在验证过程中,训练和验证数据的准确性之间存在很大差距。我非常仔细地使用自定义方法进行了预处理,但仍然出现过拟合。
在预测阶段,我没有使用测试数据集,而是获取了实时文本并进行预测,但是如果我一遍又一遍地对相同的输入数据进行预测,结果会有所不同。我正在尽力找出为什么我的结果会不同。
我有 8 个类别,它们描述了每个评论的分数,数据是分类的。Softmax 层每次向训练好的模型输入相同数据时都会预测出不同的结果。
一个模型会为相同的输入产生相同的输出。
但是,如果您在相同数据上多次拟合相同的模型,您将得到不同的预测。这是意料之中的。
https://machinelearning.org.cn/faq/single-faq/why-do-i-get-different-results-each-time-i-run-the-code
您可以通过创建最终模型的集成并结合它们的预测来减少方差。
我有一个数据集,其中训练数据是不同文件中的测试数据。我如何将测试数据传递给模型进行评估?
将它们分别加载到内存中,然后一个用于训练,一个用于测试/验证。
也许我没理解问题所在?
如何将文本输入到一个输入层形状为 (200, ) 的预训练 LSTM 模型中。
我想知道如何转换文本输入并将其作为模型的输入。
新文本必须以与用于训练模型的数据相同的方式进行准备。
先生,您能给我一个例子或代码链接吗?
是的,请参见此处的示例
https://machinelearning.org.cn/start-here/#nlp
非常感谢这篇详细的教程。我想我漏掉了一些东西……当使用预训练的 GloVe 嵌入时,如果您想进行训练测试拆分,什么时候是执行它的正确时机?
我是否需要在创建权重矩阵之后进行?
抱歉,我不太明白你的问题——嵌入和训练/测试拆分有什么关系?你能详细说明一下吗?
当然。我想使用嵌入来创建一个模型,该模型将预测 30 个不同类别中的一个类别。我使用的数据框包含一个文本列,我希望用它来预测类别。为了做到这一点,我考虑使用预训练的嵌入(与您所做的一样,但类别更多)。现在,为了测试模型,我想进行拆分,所以我的问题是您建议何时进行?我尝试为所有数据创建权重矩阵,然后将其拆分为训练集和测试集,但它在测试集上给出了非常差的结果。
有什么想法是我做错了吗?
如果您自己训练嵌入,它是在训练数据集上准备的。
如果您使用预训练的嵌入,则没有拆分是合理的,因为它已经在不同的数据上训练过。
谢谢,我想我明白了(抱歉,我有点新手)。假设我想使用训练好的模型来预测未见数据上的标签,输入应该是什么?它应该是一个相同形状的填充文档吗?
新输入必须以与训练数据相同的方式准备。
你好,又一篇很棒的帖子!
我想问一下,关于使用预训练嵌入的示例,是否可以减少词汇量大小?我有一个 300 维的预训练嵌入。我的词汇量大小是 7000。
当我将词汇量大小设置为 300 时,我得到了这个错误
embedding_matrix[i] = embedding_vector
IndexError: index 300 is out of bounds for axis 0 with size 300
提前感谢
是的,但您必须在 Tokenizer 中设置词汇量大小。
感谢您的快速回复。我做到了。
干得好!
感谢教程!我正在为我的图像到字幕模型使用 300d 嵌入,但过滤掉词汇表中的稀有词。假设我有 10k 个词,我应该只用
tokenizer.word_index.get(word, vocab_size + 1) <= vocab_size
来过滤掉我不想要的词吗?
另外,您认为在训练后期重新训练嵌入权重以进行微调值得吗?我正在从冻结预训练编码器,然后随着解码器达到一定有效性逐渐解冻层的角度思考这个问题。
您可以通过在构建分词器时设置“num_words”参数来控制词汇量大小
https://keras.org.cn/preprocessing/text/
也许可以尝试微调和不微调,然后比较结果。
嗨,Jason,
我有一个关于代码的问题。您将 vocab_size 设置为比唯一词的数量大 1。我无法理解您为什么这样做,您能告诉我吗?
我完全是新手,也不是编程背景出身,所以如果这是个愚蠢的问题,我很抱歉。
谢谢你
是的,我们对词使用 1 的偏移量,并将索引 0 保留给“未知”词。
哦……谢谢 Jason
不客气。
嗨,Jason,
我正在处理一个包含类别特征和数值特征的多元时间序列。我使用了3年的数据:20支股票作为训练窗口期30天,20支股票作为目标X_train,持续7天。X_train.shape = (N_samples, 20*30, N_features),y_train.shape = (N_samples, 20*7, N_features)。我的问题是,如何为这3个3D数组中的3个类别变量应用嵌入层?
我尝试使用这部分代码,但它不起作用
cat1_input = Input(shape=(1,), name='cat1')
cat2_input = Input(shape=(1,), name='cat2')
cat3_input = Input(shape=(1,), name='cat3')
cat1_emb = Flatten()(Embedding(33, 1)(cat1_input))
cat2_emb = Flatten()(Embedding(18, 1)(cat2_input))
cat3_emb = Flatten()(Embedding( 2, 1)(cat3_input))
请看这个教程
https://machinelearning.org.cn/how-to-prepare-categorical-data-for-deep-learning-in-python/
感谢您的及时回复,Jason。本教程是关于2D数组的嵌入,但在我的情况下,我需要构建一个模型,以3D数组(N_samples, time_steps, N_features)作为输入,并以(time_steps,N_stocks)作为输出。
也许您可以根据您的需求调整示例。
再次问好,
我这次想知道,比较两种不同语言的两个嵌入矩阵是否值得。我想找出两种不同语言的两个矩阵之间的相似性。
非常感谢
也许可以使用向量距离度量?
https://machinelearning.org.cn/distance-measures-for-machine-learning/
谢谢,我会尝试的。
不客气。
你好,Jason,这篇文章真的帮到我了,我觉得参数已经变了,
Keras 文档中,weights 参数现在是“Embedding_initializer”。
谢谢,很高兴听到这个。
同意,谢谢
https://keras.org.cn/layers/embeddings/#embedding
嗨,Jason,我遇到了内存问题,因为我的词汇量约为400,000。我有大约195847个训练样本,每个句子的输出最大长度为5个词。
所以当我尝试为解码器输出创建一个one_hot时,因为它试图创建一个195847、400000、5的矩阵,所以它显然会耗尽内存。
我该如何解决这个问题?
好问题。
尝试减少词汇量。
尝试缩小数据集的大小。
尝试缩小模型的大小。
尝试使用其他表示,例如哈希。
尝试在具有更多内存的 EC2 实例上运行。
另外一点是可以使用 keras 的 fit_generator 进行批量运行。
我还有一个问题,我知道这可能听起来很傻,但是
为什么测试需要推断模型或解码模型?那么训练模型有什么帮助呢?我唯一能看到的是它有助于决定编码器输入。我是否遗漏了什么?在我看来,训练的全部目的都失去了。
我不明白。你训练一个模型,然后用它来推断。没有训练,它是无用的。没有推断,你训练也就没有意义。
也许你可以详细说明一下?
你好,
我想问一下,如果我的标签不仅有积极和消极,还有中性,我该如何将其添加到y_training中?
那将是一个三分类问题。
你好,
感谢这篇解释得非常清楚的文章。
我不明白嵌入层中嵌入是如何学习的。这是常见的反向传播吗?
不客气。
是的,它使用反向传播。
亲爱的Jason
感谢您精彩有用的指导。当我运行本页第4部分(使用预训练GloVe嵌入的示例)中您建议的代码时,我收到以下错误,而我已经从您上面提供的URL下载了glove.6B.100d文件。您能帮我找到错误原因吗?
回溯(最近一次调用)
文件“C:/Users/Dehkhargani/PycharmProjects/test2/test2.py”,第40行,在
coefs = asarray(values[1:], dtype=’float32′)
文件“C:\Users\Dehkhargani\Anaconda\lib\site-packages\numpy\core\_asarray.py”,第85行,在asarray
返回数组(a, dtype, copy=False, order=order)
ValueError: 无法将字符串转换为浮点数:'ng'
听到这个消息很抱歉,这可能会有帮助
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
嗨,Jason,感谢您的有用帖子。
GloVe 或 Google news 等预训练词嵌入在非英语文本上仍然有效吗?
谢谢
不,它们是用于英文文本的。
谁能告诉我,我们为什么要将词汇量加1。
vocab_size = len(t.word_index) + 1
请告诉我。谢谢!!
为“0”留出空间,它代表“未知”词汇。
“该模型是一个简单的二元分类模型。重要的是,嵌入层的输出将是4个8维向量,每个向量对应一个单词。”
你是怎么知道输出将是4个向量的?
我们可以通过调用 model.summary() 来检查模型的形状。
嗨 Jason
很棒的教程!这是我第一次接触NLP,特别是“文本分类/情感分析”。因此,我对技术定义、程序、它们的含义等有点困惑。
让我用我自己的想法,为大家总结一下,以便分享并期待您的更正/评论。
1º) 从一个由文本文档列表组成的数据集中,我们将针对文本分类问题(例如)进行训练,我们读取它们并获取每个文档的单词列表(例如,使用keras API “text_to_word_sequence()”)。
2º) 然后我们可以应用某种词语清理/整理过程,使用字符串对象方法只获取字母词,或抑制词语标点符号,或消除最小词长或词语重复等。
使用 keras “Tokenizer” 对象(例如),我们可以定义一个词汇表(或构成整个数据集文档的不同单词的最小公共数量),此外,通过分词器方法“fit_on_texts”(应用于所有文档单词)来定义一个单词计数器。
3º) 现在我们有了所有文档的所有词(已清理),我们必须执行机器学习中最重要的问题。那就是,将词(标记)转换为数字,以便通过机器学习模型进行训练。如何转换?通过编码它们!
这些数字必须排列成张量(或数组),由样本(张量的行)、列(每个文档的不同特征或数字词或词汇词的数量),甚至张量的第三维度(例如,深度轴?),通过将它们嵌入到词向量空间(任意维度)中。
为了执行这种编码工作(数字转换),我们可以使用keras分词器方法,例如“texts_to_matrix()”、“texts_to_sequences()”或其他keras方法,例如“one_hot()”,始终借助keras的“pad_sequences()”方法来使所有文档的所有词(特征)具有相同的长度,例如使用每个文档的最大词长,或者仅仅因为我们想将完整的词汇表大小表示作为每个文档的特征长度。
所有这些过程的结果是,我们必须有一个干净的输入数据集,一个2D维度(文档,特征)或3D维度(文档,特征,一个额外的嵌入维度)的数字X张量,如果我们使用深度学习技术(例如嵌入)。
4) 我们还可以利用“迁移学习”的优势,当我们应用嵌入式深度学习层时,如果我们加载其他地方训练过的嵌入式层的预训练权重(例如 GloVe 词典,包含 400,000 个不同的词及其各自的 100 个坐标权重),我们必须将其适应于我们自己文档中使用的词汇表(例如,我们自己任意选择的 100 个不同的词,以及 100 个坐标作为每个词的向量词空间)。
5º) 所以现在我们已经将文档列表(词语列表)转换为一个单一的数字张量X,除了关联的Y标签之外,我们必须定义模型,其中包含一个输入层,以及embedding()、Conv1D()和MaxPool1D()层(例如),如果我们正在使用深度学习技术,再加上一个最终的flatten()层,以便将特征词提取呈现给头部全连接层(主要包括Dense()层),这些层最终将学习与每个文档标签关联的数字模式提取(代表每个文档的词语集合)。
这是我对NLP文本分类问题的总结理解。谢谢。
不错的总结,从我粗略一看,基本准确。
抱歉评论太长了,Jason!
——我还要分享我的代码结果,基于您精彩的教程。因为我喜欢您教导我们的方式……不是理论学习,而是通过最终和可操作的代码进行实践和实验……再次感谢!
——我首要关注的是,即使我们有字符串方法、“分词器”对象(类)等……我们仍然需要编写许多行代码……我可以想到,可能已经存在更高级别的API文本处理和编码,以便为它们提供适当的参数,例如(要读取的文档、清理文档单词的方式过滤器、要应用于单词的编码类型,包括是否要使用预训练权重)……以便获得主要的输出数据集准备,即“X”输入张量……而不是经历这些繁琐的代码行!
——无论如何,我完成了它,得到了以下结果
——我使用一个基本的ML模型(非深度学习)在评估中获得了100%的准确率,该模型通过keras的“texts_to_matrix()”进行词编码,但使用2D的X数据集输入(10个不同的文档样本行和2个不同的vocab_size选项50(您的)甚至更少(15),与其中使用的词语更少相关)。我使用了一个全连接模型,包含2个Dense层(输出层和前一个10个节点的层)。
——我还获得了100%的准确率,但现在使用的是带有“one_hot()”编码(您建议的)的DL嵌入层,而不是GloVe预训练权重,并且除了嵌入层之外,我还添加了Conv1D层、MaxPool1D和Flatten层(CNN部分!)。我使用了一个2D的X张量,其中有两个选项作为特征列,最大长度为4,甚至后来应用了50个词汇列特征(使用“pad-sequences()”方法)。我随后使用可训练的GloVe预训练权重(设置为False和True)训练嵌入层。以及相同的全连接头模型(带有2个Dense层)。
——作为第三个主要选项,我也获得了100%的准确率,但使用的是带有keras的“texts_to_sequences()”编码方法的DL嵌入层,并且针对两个选项(最大长度和应用50个词汇量(在应用pad_sequences()之后))。我还使用GloVe训练嵌入(可训练为false和可训练为true),以及不使用GloVe权重。并且头部模型使用相同的全连接模型。
我的结论是,最稳定和最快达到最大水平的方法是应用带有预训练GloVe(trainable = true)的嵌入层,并使用编码“texts_to_sequences()”。我通过减少50个epochs或者在我的第二个Dense层中使用更少的单元来获得相同的100%准确率来衡量最佳性能。
致敬
我希望这能帮到Jason!
精彩的总结!
是的,在过去的3-4年里,文本数据准备可能已经取得了长足的进步,自从我写下这些东西以来。
是的……我认为“spaCY”……是新的强大机器学习/深度学习NLP库之一
https://spacy.io/
确实如此。
嗨 Jason
好文章!我想对这个有更清楚的了解
我们为什么要设置 trainable = False?
如果我们想使用嵌入矩阵中存在的 GloVe 100-D 权重,我们不应该将其设置为“True”吗?
我不太明白将其设置为“True”和“False”之间的区别
谢谢
维韦克
这意味着如果设置为“False”,集合中的权重在训练期间无法更改。也就是说,无法进行训练。
我认为这里有一个错别字:“例如,下面我们定义一个词汇量为200的嵌入层(例如,从0到199(包含0和199)的整数编码单词),……”因为,既然0(零)用于填充,单词是从1(不是零!)到199(包含1和199)编码的。此致,
错别字是什么,您能详细说明一下吗?
对于多标签分类器,其中每个文本可以链接到一个或多个主题,上述示例需要进行哪些更改?
例如,假设我有一个主题列表,如 [“politics”, “sports”, entertainment”, “finance”, “health”]。
一篇提到医疗保健和立法的文档将被标记为 [1,0,0,0,1]。
将“y”标签编码为上述二进制数组格式是否足够?
通常在多分类中,我们会对标签进行整数编码,然后进行one-hot编码,并在输出层使用softmax激活函数。
在“学习嵌入的例子”部分,为什么是8维?
没原因,它是任意的。
你好,
在预训练GloVe嵌入部分,您使用了 vocab_size = len(t.word_index) + 1。
为什么加1?我不明白原因。
为索引0留出空间,0表示未知词,所以词汇从索引1开始。
嗨,Joson Brownlee,
您认为哪种更好?
抱歉,您是什么意思?
是否有适用于日志文件(syslogs、应用程序日志等)的良好词或标记嵌入模型?
您能否推荐一些关于日志文件机器学习应用的链接?例如:
– 日志文件是否包含敏感数据?例如个人数据、IP地址等拓扑数据?
– 日志文件中包含哪些类型的敏感数据?
我建议为您的特定数据集训练一个模型。
我可以在哪里获取全部代码?
您可以从教程中复制,方法如下
https://machinelearning.org.cn/faq/single-faq/how-do-i-copy-code-from-a-tutorial
你好 jason,
您能给我一些关于这篇论文的见解吗 https://www.researchgate.net/publication/327173446?
我的意思是,当他们将模型的输出用于NCRF++时,我有一些困惑,他们说:“为了将实例转换为嵌入,使用了两个特征,即MNN的sigmoid输出(fe1),以及大小为30的字符嵌入(fe2)”。他们是什么意思以及如何实现?
也许如果您有一些关于使用NCRF++进行序列标记的教程,那将非常有帮助。谢谢您。
这是我在这里回答的一个常见问题
https://machinelearning.org.cn/faq/single-faq/can-you-explain-this-research-paper-to-me
啊,抱歉,让我解释一下。
长话短说,作者使用了一个深度学习模型,其输出是 sigmoid 概率。
然后作者将其输入到NCRF++中,作者说“为了将实例转换为嵌入,使用了两个特征,即MNN的sigmoid输出(fe1),以及大小为30的字符嵌入(fe2)”。
基本上我想问的是,你有没有关于NCRF++如何工作的文章?谢谢
抱歉,我没有。
各位,请考虑为网站添加深色模式(主题)
感谢您的建议。
你好,我正在尝试在 Keras 中连接两个嵌入层,一个将是固定的,另一个将进行训练,
model = Sequential()
fixed_weights = np.array([word2glove[w] for w in words_in_glove])
e1 = Embedding(input_dim = fixed_weights.shape[0], output_dim = EMBEDDING_DIM, weights = [fixed_weights], input_length = MAX_NEWS_LENGTH, trainable = False)
e2 = Embedding(input_dim = len(word2index) – fixed_weights.shape[0],output_dim = EMBEDDING_DIM, input_length = MAX_NEWS_LENGTH)
# model.add()
model.add(concatenate([e1, e2]))
但这似乎不成功,我收到错误,('NoneType' object is not subscriptable).. 您能指导我哪里错了吗?
也许可以为模型设置2个输入,每个输入一个嵌入层和LSTM,然后连接LSTM的输出。
嗨,我想编写一个通用的python函数来构建一个模型,该模型既适用于自定义嵌入层,也适用于GloVe的预训练嵌入。
听起来很棒,祝你好运!
嗨,Jason,
感谢这些精彩的教程。总是很有帮助。
我有一个问题。我正在尝试从一些带注释的症状(来自对话)中提取特征。所以我的序列是“头痛程度重,头痛频率有时”,每个序列长度不同,并分配了一个时间点。
我想提取特征,以便稍后用于时间序列分类(所以在扁平化之后,我将添加一个大小为100的密集层)。问题是我不想在这里使用相同的标签进行嵌入(在model.fit中)。我担心当我使用这些特征训练主分类器时,会与包含这些样本的时间点分配相同的标签,这会导致偏差。
有没有办法在不为每个样本分配标签的情况下进行嵌入?
谢谢你,
也许你可以使用独立的doc2vec技术,例如独立的word2vec方法的等效物。
嗨,Jason,
关于准确率和预测方法的一个简短问题。当我使用
model.predict(pad_sequences([one_hot(‘poor work’, vocab_size)], maxlen=max_length, padding=’post’))
我得到的输出是 0.5076578 {array([[0.5076578]], dtype=float32)},根据我的理解,这意味着它既不好也不坏。如果我运行 model.evaluate,我得到的准确率是 100%,但这不可能是真的,因为“poor work”在我的测试集中,我得到的分数是 0.50…而不是 0。
这怎么可能?
非常感谢
模型在某些情况下可能不确定。
尽管如此,如果四舍五入到清晰的标签,准确率显示出很好的结果。
如果您更喜欢根据模型的置信度来评估模型,可以使用对数损失或布里尔技能分数。
https://machinelearning.org.cn/probability-metrics-for-imbalanced-classification/
谢谢 Jason,
运行2-3次后,我能够像你说的达到100%的准确率。
不错。
嗨,Jason,
我正在尝试使用此代码训练后预测输出。当我查看输出时,它总是预测 [[0.72645265]]。为什么会这样?
我使用以下模型调用进行预测:
output = model.predict(padded_docs)
以下是获取 padded_docs 的代码:
t = Tokenizer()
t.fit_on_texts([“good job”])
vocab_size = len(t.word_index) + 1
encoded_docs = t.texts_to_sequences(docs)
max_length = 4
padded_docs = pad_sequences(encoded_docs, maxlen=max_length, padding=’post’)
还是我哪里出错了?我不确定应该在 predict() 中传递什么。
看起来不错,它正在预测文档属于类别1的概率。
例如,P(class=1) = 70%
更多关于使用 Keras 模型进行预测的信息,请参见此处
https://machinelearning.org.cn/how-to-make-classification-and-regression-predictions-for-deep-learning-models-in-keras/
是的,进展顺利。但并非所有情况都如此。当我在输入“poor job”上进行测试时,它预测的输出与“[[0.72645265]]”相同(所有测试用例都相同)。我想我提供了错误的输入,每次都只是填充数据([[1,2,0,0]]),而不是确切的单词。我应该如何为model.predict()函数构建输入?
新的输入数据必须以与训练数据集相同的方式准备——相同的编码、词汇等。
我也有同样的错误,您能向我们展示正确预测的代码吗?
抱歉,我不明白。您具体遇到了什么错误?
我回答我自己和Tammay
try=[“太棒了!”]
encoded_try = t.texts_to_sequences(try)
padded_try = pad_sequences(encoded_try, maxlen=4, padding=’post’)
model.predict(padded_try)
只有经过训练的词才有效***
贾森的博客很棒,下次也请像评估模型一样,我们是新手????
psdt:(问题是我们不知道如何评估文本“model.predict”,因为我们总是认为结果相同)
你好,
嵌入层的输出是3D(参考:https://tensorflowcn.cn/api_docs/python/tf/keras/layers/Embedding),但您的博客中写道输出是2D
我回答我自己和Tammay
try=[“太棒了!”]
encoded_try = t.texts_to_sequences(try)
padded_try = pad_sequences(encoded_try, maxlen=4, padding=’post’)
model.predict(padded_try)
只有经过训练的词才有效***
杰森的博客很棒,下次也请像评估模型一样,我们是新手 😉
谢谢。
您可以在博客上看到数百个模型评估的示例,也许可以从这里开始
https://machinelearning.org.cn/start-here/#deeplearning
模型中的嵌入层是什么意思?
抱歉,我不明白您的问题,您能详细说明一下吗?
我的意思是为什么我们在模型中使用嵌入层????
嵌入层可用于学习单词之间的关系。
嗨,Jason,感谢您精彩的教程。
您如何向嵌入添加偏差?
提前感谢
不客气!
您说的“向嵌入添加偏差”是什么意思?
我的意思是,在您训练嵌入时,为每个学习到的嵌入设置一个单一的偏差项是否有利?
感谢您的关注!
不行。
感谢Jason澄清了这一点。
不客气。
嗨,Jason,
有没有办法将2D输入转换为嵌入。基本上,我有一个表示图的邻接矩阵(2D数组),并且训练将发生在批量图作为数据点上。有没有办法可以将图的每个节点(基本上由邻接矩阵中的每一行表示)转换为更有意义的嵌入?
是的,自编码器可以用于将数据转换为“嵌入”。
也许从这里开始
https://machinelearning.org.cn/autoencoder-for-classification/
还有这里
https://machinelearning.org.cn/lstm-autoencoders/
谢谢,Jason先生,请帮助我。
1- 如果我每句话只有一个词,并且它们之间没有关系,那么我如何表示类别标签,我真的不知道这里类别标签有什么好处?
2- 嵌入过程背后的数学模型是什么?
也许可以尝试这里的这三种方法
https://machinelearning.org.cn/how-to-prepare-categorical-data-for-deep-learning-in-python/
也许可以查阅教科书或论文以了解嵌入层背后的数学原理。
预训练意味着测试数据
不。预训练是指使用不同的算法进行训练,并生成一个独立的模型,该模型可以用作后续模型(如神经网络)的一部分。
你好……我想将隐藏状态与词嵌入连接起来……我们怎么做呢?
也许可以尝试在keras中使用合并或连接层,看看是否能达到您想要的效果?
谢谢……我试了以下方法,结果出现维度错误
latent_dim=128
encoder_inputs = Input(shape=(None,))
enc_emb = Embedding(eng_vocab_size, latent_dim, mask_zero = True)(encoder_inputs)
encoder_lstm = LSTM(latent_dim*4, return_sequences=True, return_state=True)
encoder_outputs, state_h, state_c = encoder_lstm(enc_emb)
state_h=Concatenate()([state_h,enc_emb])
encoder_states = [state_h, state_c]
错误是
ValueError: 一个`Concatenate`层需要输入具有匹配的形状,除了连接轴。得到的输入形状为:[(None, 512), (None, None, 128)]
抱歉,我没有能力调试您的代码。
嗨,Jason,我正在尝试理解如何提取嵌入特征?例如,对于每个训练样本,我如何获取文本特征(例如300维x 50序列长度)。这样我就可以在序列模型中不需要使用嵌入层,并且可以直接使用LSTM和其他层。任何指导都会非常有帮助。
每个单词都被映射到一个向量。直接检索您单词的向量。
你好,如果我有一个包含30万个句子的文档,并且文档中最长的句子有451个单词,那么嵌入层中的vocab_size和input_length会是多少?我还是不太明白。
您可以选择词汇量和单词数量。
它可以任意选择,也可以根据从您的数据中计算出的摘要统计数据选择。
不知道嵌入的底层算法,让人费解输出维度可以是任意大小。
请告诉我 input_length 实际上应该是最长句子的长度。如果 input_length 可以填充到超过最长句子,我不会感到惊讶,但那有什么意义呢?
没有算法——它只是词汇表中每个词的权重向量,这些权重在训练期间像网络中的任何其他权重一样更新。
输入长度是您希望在样本中传入的单词数量。它可以随心所欲地短或长,并用零填充以使其具有相同的长度。
也许可以进行实验,找出最适合您的数据集和模型的方案。
Keras中嵌入层和Elom嵌入有什么区别???
“Keras中的Elom嵌入”是什么?
那,准确率是为了什么?
我将它们用于分类问题
同意,准确率在示例中可能不相关。
你好 jason,
您将词汇量解释为:“这是文本数据中词汇量的大小。例如,如果您的数据被整数编码为0-10之间的值,那么词汇量的大小将是11个单词。”
请向我解释一下词汇和词汇量。
您在词汇量的解释中提到了“整数编码”。但是当我们使用整数编码时,它会基于我们数据中的单词数量,对吗?那么为什么我们将其设置为200呢?请向我解释一下。我是机器学习新手,如果我的问题很傻,请原谅。
谢谢你
词汇表是模型已知词的数量,每个词都有一个您分配的唯一编号。
哪一部分让您感到困惑?
感谢您的善意回复。
我的疑问是,在上面的例子中,“doc”有12个独特的词。那么我们为什么将“vocab_size”设置为50呢?词汇量是基于数据中存在的词的数量吗?
50这个值是怎么来的?
请给我举例解释一下词汇量是什么。
谢谢你
在该示例的那部分中,词汇量是人为设计的。
非常感谢。
不客气。
你好,
一个疑问:在给出的例子中,嵌入层有“vocab_size”x 8 = 400个参数。
就好像我们有50个输入和8个处理单元(向量)。
当向嵌入层提供一串不同的词(长度=4,如例子所示)作为输入时,我们是否只会“激活”嵌入层的32个权重?
32 = 4(输入字符串中的单词数)x 8(向量的维度)
如果您提供一个包含4个单词的序列,并且嵌入的维度是8,那么嵌入将为每个单词输出一个8元素的向量,例如一个4x8矩阵。
如果在分词器中添加 oov_token='UNK',我仍然需要添加 ,vocab_size = len(t.word_index) + 1 吗?
t=tf.keras.preprocessing.text.Tokenizer(
filters='!"#$%&()*+,-./:;?@[\\]^`{|}~\t\n',
lower=True, split=' ', char_level=False,oov_token='UNK'
)
是的,0总是保留给未知/缺失的,无论您是否使用它。
你好 Jason,
非常感谢您的精彩文章。
我几乎查看了这篇文章中的所有问题和答案,我注意到有好几个人问了和我一样的问题,但您的答案与他们所问的问题无关。
你提到了
“该模型是一个简单的二元分类模型。重要的是,嵌入层的输出将是4个8维向量,每个向量对应一个单词。”
我明白8个维度是一个任意的数字。但我不明白的是4个向量是什么意思?如果文档有10个,每个文档都被翻译或转换为一个4维向量,为什么嵌入层的输出会是4个向量呢?
谢谢你。
文档不会被翻译成向量,单词会被翻译成向量。每个单词都将是一个长度为8的向量,文档将是由这些向量组成的矩阵。10个文档将是10个这样的向量矩阵。
这有帮助吗?
运行代码,亲眼看看!
嗨
在GloVe嵌入的情况下,我们可以使用Tf-idf向量化器或ohe来将字符转换为向量,而不是test_to_sequence()吗?
当然,试试看,然后比较结果。
谢谢
非常感谢Jason,您的博客文章写得非常精彩。
不客气!
例如,我有一个数据框,假设有3列:评论、有趣与否、积极或消极。我将评论列转换为填充序列列,使用该列从Word2Vec获取结果嵌入矩阵,并将“有趣与否”列二值化。好的,现在除了填充序列之外,我如何将另一列作为特征发送到我的模型?
抱歉,我没听懂你的问题。
也许你可以总结或重新表述一下?
谢谢你,Jason!!
那么,一般来说(不只针对文本),当我们使用Keras中的嵌入层将类别特征转换为数值向量时,是只需在我们的主机器学习模型中添加一个嵌入层(且嵌入层只转换类别特征)吗?还是我们分别训练两个不同的模型,第一个模型带嵌入层用于生成数值特征(转换类别特征),第二个模型用于预测(我们的主要问题),我们将嵌入作为特征输入?
谢谢!
不客气。
是的,嵌入只是将序数编码值转换为实值向量,适用于任何你喜欢的模型。神经网络允许你将嵌入作为模型的一部分进行训练。
您好,感谢您创建了出色的博客。我有一个关于嵌入来源的问题。考虑到像BERT这样的模型学习上下文嵌入,我们有没有可能在翻译模型中使用它们的tokenizer和嵌入?我已经针对我的特定领域数据预训练了波斯语BERT模型,现在我想知道是否可以在翻译模型中使用这些嵌入。
我相信是的。
先生,
当我尝试运行这段代码时,我得到了这个错误。这段代码有什么问题?提前感谢。
embeddings_index = dict()
f = open(‘glove.6B.100d.txt’, ‘r’, errors = ‘ignore’, encoding=’utf8′)
for line in f
values = line.split()
word = values[0]
coefs = asarray(values[1:], dtype=’float32′)
embeddings_index[word] = coefs
f.close()
print(‘Loaded %s word vectors.’ % len(embeddings_index))
TypeError Traceback (most recent call last)
in ()
4 values = line.split()
5 word = values[0]
—-> 6 coefs = array(values[1:], dtype=’float32′)
7 embeddings_index[word] = coefs
8 f.close()
TypeError: array.array() takes no keyword arguments
听到这个消息很抱歉,这些技巧可能会有所帮助
https://machinelearning.org.cn/faq/single-faq/why-does-the-code-in-the-tutorial-not-work-for-me
嗨,感谢您精彩的博客。有没有办法验证我的嵌入效果如何?
也许可以在模型中使用它,并比较使用和不使用它,或者使用不同编码/嵌入的模型性能。
我正在研究结合数值和文本特征进行预测的方法。有没有办法通过神经网络利用词嵌入来实现这一点?
是的,你可以使用多输入模型,一个输入用于文本数据,一个输入用于数值数据。
这将帮助您入门
https://machinelearning.org.cn/keras-functional-api-deep-learning/
你好 Jason,
感谢您写得如此精彩的文章。关于第三种情况,我有一个问题:
“如何在神经网络中使用预训练词嵌入”
在本教程中,我们使用GloVe词嵌入作为嵌入层的“权重”。我们能否改为用相应的GloVe词嵌入来表示/编码输入(训练数据)中的每个词,然后训练神经网络?在这种情况下,我们根本不需要嵌入层了,对吗?
不客气。
是的,这是同一个意思。嵌入要么直接在模型中使用,要么作为输入数据的预处理。都是一样的。
谢谢你的回复!我会试试看的!
嗨,Jason,
我正在使用BERT进行词嵌入,我正在对新闻标题进行情感分析,并将数据分为积极和消极两类。只使用CLS token的嵌入然后进行分类可以吗?我正在使用带有BERT嵌入的SVM分类器。我得到了84%的准确率,这不是我想要的,我想要更高的准确率。有没有其他的解决方案会很感激。谢谢。
也许可以尝试替代的嵌入方式、替代的数据准备方式、替代的预测模型和配置等。
Keras 提供了 one_hot() 函数,它将每个单词哈希为一个高效的整数编码。我们将估计词汇量大小为 50,这比所需的大得多,以减少哈希函数冲突的可能性。
对于上面的句子,我不明白为什么在词汇量大约为15的时候,我们却取了50的词汇量大小?您能用通俗易懂的方式解释一下吗?我们总是需要取比实际词汇量大的值吗?
词汇量应该足够大,以捕捉数据集的复杂性。
你好,Jason,感谢你的教程,它们对我帮助很大。我有一个关于你在本教程中解决的问题的疑问。
我正在做一个文本摘要的项目,我有一个数据框,包含两列:第一列是文本,第二列是摘要。我想在将文本输入到我的seq2seq模型进行摘要之前学习词嵌入(我想为嵌入创建一个单独的模型,否则一个模型要学习的参数太多了)。
在预处理阶段,我对文本和摘要都进行了独热编码,然后进行了填充。现在每个文本序列的长度为462,而每个摘要序列的长度为140。
我的问题是:既然我想学习数据集中所有词汇的嵌入,我是否需要拉伸摘要序列的长度,使其达到462,以便所有序列都具有相同的长度并可以输入到嵌入模型中?
通常你需要进行你所描述的对齐,但有很多方法可以做到。填充(Padding)是其中之一。如果你有Word2Vec嵌入,你也可以对每个单词的向量求和,这样无论你的句子有多长,你都会得到一个长度为N的词向量,而不是长度为462或140。我相信你可以想到许多不同的方法。这里由你来决定选择的方法并给出理由。
亲爱的朋友您好,
感谢您的本教程
我尝试了代码,但最终陷入了我想要解决的问题,我有疑问
问题是:比较两个句子,看它们是否具有相同的含义
所以训练数据包括 [句子1, 句子2],以及标签 [0 或 1]
1- 我从训练数据和测试数据中提取词嵌入,这是正确的吗?
2- 如何将输入传递给模型,我找到的所有方法都只传递一个文档/句子
但我需要传递两个句子
你能帮忙吗?
也许这能作为第一步的帮助
https://machinelearning.org.cn/develop-word-embeddings-python-gensim/
非常感谢您的回复
是的,我已经做了词嵌入,我的数据集已经准备好了,但我卡在了模型的拟合上!!
如何输入两个嵌入的句子?
我的数据看起来像这样
x_trine_data = [ [ [0.2 , 0.3, 0.9], [0.7, …,],[…],..] [ [0.4,0.3..],[0.32,..] ] ]
其中
x_trine_data[0] 代表 sen1
x_trine_data [1] 代表 sen2
sen1 sen 2 标签
[0] hello word there [0]welcome to class 0
[1] A went to school [1] A in the school 1
....
你可以使用一个多输入模型,每个嵌入有一个输入。请看这个
https://machinelearning.org.cn/keras-functional-api-deep-learning/
太棒了,非常感谢
不客气。
Francois Chollet 图61 从文本到标记到向量,其中有零点,不理解零点
非常感谢本教程!解释得简单明了!
很高兴你喜欢。谢谢。
嗨,我不太理解嵌入层如何将权重矩阵映射到其各自的键(单词)。另外,您传递给padded_docs模型中,但GloVe向量单词中不存在的单词怎么办?
对于预训练向量中未知的单词,你可以预定义一个替换嵌入(或者你可以在查找嵌入之前进行一些预处理来替换这些未定义的单词)。
嗨,Jason!
感谢您的本教程。
我的问题是:Keras 嵌入层只能用于文本数据吗?
谢谢!
并非仅限于文本数据,但英语单词最容易,因为有很多可供下载的嵌入数据。但从技术上讲,这并不意味着它是唯一的应用。只要你能够证明其合理性,你可以将嵌入层用于任何事物。
亲爱的布朗利博士,
我想感谢您的宝贵文章,我确实学到了很多。
我的问题是:我们可以像使用GloVe一样使用FastText预训练嵌入吗?
应该可以。只是维度会不同。
谢谢Jason,这篇好文章。我有以下疑问
# 整数编码文档
vocab_size = 50
# 将文档填充到最大长度为 4 个单词
max_length = 4
该方法难道不能自动找出输入中词语的总数并决定vocab_size吗?我们可能不知道实际的vocab_size,因此可能会提供错误的值。例如,我们可能传入5而不是50。这样许多词语就可能具有相同的数字。
同样,填充最大长度,该方法难道不能根据每个句子中的词语数量来找出吗?就像上面提到的,我们传入这个值时也可能会犯错误。
请对此阐明一下。谢谢。
嗨,Raja……请您缩小问题范围或提供更具体的疑问,以便我们更好地协助您。
谢谢Brownlee博士的这篇很棒的博客。我使用glove作为字幕模型中的嵌入层,通过获取嵌入矩阵,但如果我需要使用BERT,我该如何开始,请指教。
嗨,Sam……感谢您的反馈和友善之词!以下内容可能对您有帮助
https://towardsml.com/2019/09/17/bert-explained-a-complete-guide-with-theory-and-tutorial/
非常感谢这个链接。请问,我需要BERT的哪种类型的嵌入来进行图像字幕生成?
你好 Sam……以下文章可能对你感兴趣
https://mccormickml.com/2019/05/14/BERT-word-embeddings-tutorial/
嗨 Jason
我很困惑为什么第三节中嵌入层的输出是4乘8?
如果句子是1乘4的向量,而嵌入矩阵是8乘50的矩阵,
如果我们将它们相乘,您不会得到一个4乘8的矩阵,您会得到一个错误,因为它混淆了矩阵乘法的定律。
那么输出维度为什么会是这样呢?我肯定我遗漏了一些东西!非常感谢。
正是我在找的!爱你,老兄!
太棒了 Dev!
在这个例子中,
这有点像迁移学习,对吗?
嗨,zi……我同意。以下内容可能对您有帮助
https://machinelearning.org.cn/transfer-learning-for-deep-learning/
嗨,Jason,
请指导——我如何将预训练词嵌入模型用于那些在预训练模型中不可用的本地语言?或者我是否必须使用一个嵌入层来生成嵌入矩阵?
我如何从预训练模型中受益于本地语言?
嗨,Majida……请您澄清“本地语言”的含义,以便我们更好地协助您。
你好,感谢你的善意回复。
英文句子:“He is a good boy”
罗马乌尔都语:“ye acha larka ha”
“ye”表示“he”。
“ha”表示“is”。
“acha”表示“good”
“larka”表示“boy”。
实际上,这不是巴基斯坦、印度和世界各地所说的正宗乌尔都语。但这种写法在社交媒体用户中很流行。
此致
嗨 Jason
tf.keras.preprocessing.text.one_hot 已被弃用,建议使用 tf.keras.layers.Hashing 并设置 output_mode=’one_hot’。
但我使用时,它显示:“('Keyword argument not understood:', 'output_mode')”
你有什么想法吗?
谢谢
嗨,Silvio……请您澄清您所指的建议来源和错误,以便我们更好地协助您。
你好!我正在构建一个模型,使用嵌入层后接 GlobalAveragePooling1D() 层和其他层,如下所示:
tf.keras.layers.Embedding(vocab_size=10000, embedding_dim=300, input_length=16),
tf.keras.layers.GlobalAveragePooling1D(),
tf.keras.layers.Dense(32, activation=’tanh’),
tf.keras.layers.Dense(16, activation=’tanh’),
tf.keras.layers.Dense(1, activation=’sigmoid’)
我的理解是,在嵌入层之后,后续层获取相应单词的数据或特征向量。然后,该特征向量用于其他层中的进一步处理。因此,嵌入层本身足以生成特征向量。
但从这篇文章(尽管信息量很大)中,我的理解是,为了生成特征向量,它需要通过所有其他层传播。如果数据通过整个层来生成特征向量,那么该特征向量是如何使用的呢?
我的另一个问题是,如果我使用RNN层,我是否必须使用嵌入层?
嗨 Subodh……您可能会觉得以下资源很有趣
https://medium.com/analytics-vidhya/understanding-embedding-layer-in-keras-bbe3ff1327ce
很棒的文章,谢谢。
例如,下面我们定义了一个嵌入层,其中词汇表大小为 200(例如,整数编码的词语从 0 到 199,包括在内),词语将被嵌入的向量空间为 32 维,输入文档各有 50 个词。
关于嵌入层的以下设置
e = Embedding(200, 32, input_length=50)
如果我们想同时处理三个独立的输入而不是上面一个输入,嵌入层或层的设置会是怎样?
例如,我有三个输入,每个输入都有100个词汇量大小?
为了澄清我的问题:
我有三个子地址,每个都是唯一的整数0-99,这三个的组合将构成一个唯一的地址。我没有使用一个带有100*100*100=1000000个输入的密集层,而是使用了三个嵌入层,每个嵌入层都在输入层之后,并且是相同的。接下来将嵌入层的输出连接起来,最后处理密集层的输出。
我的问题是,我是否可以使用单个密集层?如果可以,密集层的设置会是怎样的?
谢谢
已知:每个案例最多3个单词,嵌入大小=8。展平后,每个案例最终将有3 x 8 = 24个“特征”用于模型中的任何下游架构。
考虑句子“cat sat mat”、“mat cat sat”、“sat mat cat”等。每个句子都有相同的24个特征,只是顺序/块不同。
这似乎意味着“特征X”或“列X”在概念上并不是逐案相同的。例如,有时特征9是CAT的第一个潜在嵌入值,有时是SAT的第一个潜在嵌入元素,有时是MAT的。这与标记无关,而与该案例中“恰好存在”(词袋)的标记有关。
这些24个新特征的下游学习如何获得一致的结果?我觉得我遗漏了一些概念上的东西。
谢谢
Tao
嗨,陶……以下资源可能会为您提供清晰的解释
https://www.geeksforgeeks.org/word-embeddings-in-nlp/
如果我使用 tokenizer = Tokenizer(oov_token = oov_token),那么我就不必将 vocab_size 加 1 了……对吗?
嗨,Sandeep……请您继续您的想法,并告诉我们您的发现。
您好 Jason 和团队,
我正在尝试在训练数据集(Ubuntu对话语料库)上实现动态嵌入,而不是使用预训练的GloVe/Word-2-vec嵌入。我的目标是创建能够不仅仅一次(即,最初在嵌入层)学习的嵌入,而且通过整个NLP模型反向传播的权重可以用于更新嵌入层本身的初始嵌入。
您的文章中标题为“学习嵌入的示例”的第3节是否是正确的起点?
嗨 KSaeed……是的,实现可以通过反向传播更新的动态嵌入是现代NLP模型中的一种基本方法。如果文章中“学习嵌入的示例”的第3节涵盖了动态创建和更新嵌入的过程,那么它确实是一个很好的起点。以下是更详细的解释和步骤,以帮助您实现此功能:
### 实施动态嵌入的步骤
1. **准备数据集:**
– 预处理 Ubuntu 对话语料库:对文本进行分词,处理词汇表外单词,并创建词汇索引。
2. **初始化嵌入层:**
– 不使用预训练嵌入,而是用随机权重初始化嵌入层。
– 这可以使用 TensorFlow 或 PyTorch 等库完成。例如,在 PyTorch 中:
python
import torch.nn as nn
embedding = nn.Embedding(num_embeddings=vocab_size, embedding_dim=embedding_dim)
3. **构建 NLP 模型:**
– 创建您的 NLP 模型,该模型将包含嵌入层作为第一层。嵌入将在训练期间更新。
– 例如,一个简单的模型可能看起来像这样:
python
class NLPModel(nn.Module):
def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim):
super(NLPModel, self).__init__()
self.embedding = nn.Embedding(vocab_size, embedding_dim)
self.rnn = nn.LSTM(embedding_dim, hidden_dim)
self.fc = nn.Linear(hidden_dim, output_dim)
def forward(self, x):
embedded = self.embedding(x)
output, (hidden, cell) = self.rnn(embedded)
return self.fc(hidden[-1])
4. **训练模型:**
– 定义损失函数和优化器。交叉熵损失通常用于分类任务。
python
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
– 通过前向传播输入、计算损失、反向传播和更新权重来训练模型。
python
for epoch in range(num_epochs):
for inputs, labels in dataloader:
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
5. **更新嵌入:**
– 在反向传播过程中,梯度将流经嵌入层,根据模型的误差动态更新嵌入权重。
– 嵌入将变得更有意义,因为它们在训练期间会根据您的特定任务进行调整。
### PyTorch 示例
这是一个完整的示例,以进行说明:
python
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, Dataset
class UbuntuDataset(Dataset)
# 用于加载 Ubuntu 对话语料库的自定义数据集
def __init__(self, data, vocab)
self.data = data
self.vocab = vocab
def __len__(self)
return len(self.data)
def __getitem__(self, idx)
return self.data[idx]
class NLPModel(nn.Module)
def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim)
super(NLPModel, self).__init__()
self.embedding = nn.Embedding(vocab_size, embedding_dim)
self.rnn = nn.LSTM(embedding_dim, hidden_dim, batch_first=True)
self.fc = nn.Linear(hidden_dim, output_dim)
def forward(self, x)
embedded = self.embedding(x)
output, (hidden, cell) = self.rnn(embedded)
return self.fc(hidden[-1])
# 示例数据和词汇表(替换为实际数据和预处理)
data = [('hello how are you', 0), ('i am fine thank you', 1)]
vocab = {'hello': 0, 'how': 1, 'are': 2, 'you': 3, 'i': 4, 'am': 5, 'fine': 6, 'thank': 7}
vocab_size = len(vocab)
embedding_dim = 50
hidden_dim = 100
output_dim = 2
num_epochs = 5
# 将数据转换为索引
data = [([vocab[word] for word in text.split()], label) for text, label in data]
dataset = UbuntuDataset(data, vocab)
dataloader = DataLoader(dataset, batch_size=2, shuffle=True)
model = NLPModel(vocab_size, embedding_dim, hidden_dim, output_dim)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
for epoch in range(num_epochs)
for inputs, labels in dataloader
inputs = torch.tensor(inputs, dtype=torch.long)
labels = torch.tensor(labels, dtype=torch.long)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
print(f'Epoch {epoch+1}, Loss: {loss.item()}')
通过遵循这些步骤,您将能够创建并动态更新特定于您的数据集和任务的嵌入,从而提高您的 NLP 模型的性能。
谢谢 James!这非常有帮助,我一定会尝试一下并告诉您性能!