使用 gensim.downloader 与手动加载训练 gensim 模型时结果不一致
Inconsistent results when training gensim model with gensim.downloader vs manual loading
我试图了解以下示例中出了什么问题。
要按照文档中的描述在 'text8' 数据集上进行训练,只需执行以下操作:
import gensim.downloader as api
from gensim.models import Word2Vec
dataset = api.load('text8')
model = Word2Vec(dataset)
这样做可以提供非常好的嵌入向量,正如通过对单词相似性任务的评估所验证的那样。
但是,当手动加载上面使用的相同文本文件时,如
text_path = '~/gensim-data/text8/text'
text = []
with open(text_path) as file:
for line in file:
text.extend(line.split())
text = [text]
model = Word2Vec(test)
该模型仍然表示它正在训练与上述 (5) 相同数量的 epoch,但训练速度要快得多,并且生成的向量在相似性任务上的表现非常非常糟糕。
这里发生了什么?我想这可能与'sentences'的数量有关,但是text8文件似乎只有一行,那么gensim.downloader是否将text8文件拆分成句子?如果是,长度是多少?
在您的第二个示例中,您创建了一个训练数据集,其中只有一个文本包含文件的全部内容。在一个列表中大约有 110 万个单词标记。
Word2Vec
(及其他相关算法)在 gensim 中有一个内部实现限制,在其优化路径中,每个文本项有 10,000 个标记。所有额外的标记都将被忽略。
因此,在您的第二种情况下,99% 的数据都被丢弃了。培训似乎是即时的,但实际培训很少发生。 (仅出现在前 10,000 个标记后的单词的单词向量根本不会被训练,只有它们的初始随机设置值。)如果您在 INFO 级别启用日志记录,您将看到有关每个标记的更多详细信息过程的步骤,这样的差异可能更容易识别。
是的,api.load()
变体采取额外的步骤将单行文件分成 10,000 个令牌块。我相信它正在为此目的使用 LineSentence
实用程序 class,可以在此处查看其来源:
但是,我建议完全避免使用 api.load()
功能。它不只是下载数据;它还下载了一个额外的版本控制之外的垫片 Python 代码,用于为额外操作准备该数据。与为 PyPI/etc 打包的官方 gensim 发布代码相比,此类代码更难浏览且审查较少,这也存在安全风险。每个加载目标(名称如 'text8')可能会做一些不同的事情,使您拥有不同的对象类型作为 return 值。
直接将您需要的数据文件精确下载到已知的本地路径,然后自己从这些路径执行 IO/prep 会更好,这样您就知道应用了哪些步骤,以及只有你 运行 的代码是正式版本和发布的代码。
我试图了解以下示例中出了什么问题。
要按照文档中的描述在 'text8' 数据集上进行训练,只需执行以下操作:
import gensim.downloader as api
from gensim.models import Word2Vec
dataset = api.load('text8')
model = Word2Vec(dataset)
这样做可以提供非常好的嵌入向量,正如通过对单词相似性任务的评估所验证的那样。
但是,当手动加载上面使用的相同文本文件时,如
text_path = '~/gensim-data/text8/text'
text = []
with open(text_path) as file:
for line in file:
text.extend(line.split())
text = [text]
model = Word2Vec(test)
该模型仍然表示它正在训练与上述 (5) 相同数量的 epoch,但训练速度要快得多,并且生成的向量在相似性任务上的表现非常非常糟糕。
这里发生了什么?我想这可能与'sentences'的数量有关,但是text8文件似乎只有一行,那么gensim.downloader是否将text8文件拆分成句子?如果是,长度是多少?
在您的第二个示例中,您创建了一个训练数据集,其中只有一个文本包含文件的全部内容。在一个列表中大约有 110 万个单词标记。
Word2Vec
(及其他相关算法)在 gensim 中有一个内部实现限制,在其优化路径中,每个文本项有 10,000 个标记。所有额外的标记都将被忽略。
因此,在您的第二种情况下,99% 的数据都被丢弃了。培训似乎是即时的,但实际培训很少发生。 (仅出现在前 10,000 个标记后的单词的单词向量根本不会被训练,只有它们的初始随机设置值。)如果您在 INFO 级别启用日志记录,您将看到有关每个标记的更多详细信息过程的步骤,这样的差异可能更容易识别。
是的,api.load()
变体采取额外的步骤将单行文件分成 10,000 个令牌块。我相信它正在为此目的使用 LineSentence
实用程序 class,可以在此处查看其来源:
但是,我建议完全避免使用 api.load()
功能。它不只是下载数据;它还下载了一个额外的版本控制之外的垫片 Python 代码,用于为额外操作准备该数据。与为 PyPI/etc 打包的官方 gensim 发布代码相比,此类代码更难浏览且审查较少,这也存在安全风险。每个加载目标(名称如 'text8')可能会做一些不同的事情,使您拥有不同的对象类型作为 return 值。
直接将您需要的数据文件精确下载到已知的本地路径,然后自己从这些路径执行 IO/prep 会更好,这样您就知道应用了哪些步骤,以及只有你 运行 的代码是正式版本和发布的代码。