使用 doc2vec 和 gensim 的文本分类模型
text classification model using doc2vec and gensim
我正在使用 gensim 和 doc2vec 进行文本分类。我正在使用两个数据集对此进行测试,一个是堆栈交换数据集和一个 Reddit 数据集。我正在尝试对来自一个 subreddit/stackexchange 站点的某个特定主题的帖子进行分类,然后使用来自其他不相关 subreddit/stackexchange 站点的帖子作为负面示例。
我正在使用包含 10k 个帖子的数据集来训练模型,并使用 5k 个测试集分为 50% 的正例和 50% 的负例。然后,我使用 infer_vector 和 most_similar 函数将条目分类为正面或负面。在训练模型之前,我预处理数据以删除任何单词、符号、链接等,只留下最重要的单词来训练模型。下面是用于训练模型的代码。
df = pd.read_csv("fulltrainingset.csv")
df.columns.values[0] = "A"
tagged_data = [TaggedDocument(words=word_tokenize(_d.lower()), tags=[str(i)]) for i, _d in enumerate(df["A"])]
epoch_list = [1,5,10,15,25,50,100,200,300,400]
size_list = [1,5,10,15,25,50,100,200,300]
for x in epoch_list:
for y in size_list:
vec_size = y
max_epochs = x
minimum_count = 1
mode = 0
window_ = 15
negative_sampling = 5
subsampling = 1e-5
alpha = 0.025
minalpha = 0.00025
model = Doc2Vec(alpha=alpha, min_alpha=minalpha, vector_size=vec_size, dm=mode, min_count=minimum_count, window =window_, sample=subsampling ,hs =negative_sampling)
model.build_vocab(tagged_data)
for epoch in range(max_epochs):
print('iteration {0}'.format(epoch))
model.train(tagged_data,
total_examples=model.corpus_count,
epochs=model.epochs)#self.epochs
model.alpha -= 0.0002
model.min_alpha = model.alpha
model.save(str(y)+"s_"+str(x)+"e.model")
这个方法有效,我可以从中得到结果,但我想知道是否有不同的训练方式可以达到更好的效果。目前我只是训练许多具有不同时期和 vector_sizes 的模型,然后使用 infer_vector 和 most_similar 函数查看从 most_similar 条目返回的向量分数是否大于有一定数量,但是有没有办法在模型训练方面对此进行改进?
此外,为了获得更好的结果,我以相同的方式使用更大的数据集(超过 100k 个条目)训练了另一个模型。当我在同一个数据集上使用这个模型时,它产生了与在较小数据集上训练的模型相似但更差的结果。我认为更多的训练数据会改善结果而不是使它们变得更糟,有人知道这是什么原因吗?
此外,为了进一步测试,我创建了一个新的但更大的测试集(15k 个条目),它比原始测试集表现更差。此测试集中的数据虽然唯一,但与原始测试集中使用的数据类型相同,但产生的结果更差,这可能是什么原因?
df = pd.read_csv("all_sec_tweets.csv")
df.columns.values[0] = "A"
tagged_data = [TaggedDocument(words=word_tokenize(_d.lower()), tags=[str(i)]) for i, _d in enumerate(df["A"])]
epoch_list = [1,5,10,15,25,50,100]
size_list = [1,5,10,15,25,50,100]
for x in epoch_list:
for y in size_list:
vec_size = y
max_epochs = x
mode = 0
window_ = 5
subsampling = 1e-5
model = Doc2Vec(vector_size=vec_size, dm=mode, window =window_, sample=subsampling,epochs=max_epochs)
model.build_vocab(tagged_data)
model.train(tagged_data,total_examples=model.corpus_count,epochs=model.epochs)
model.save(str(y)+"s_"+str(x)+"e.model")
听起来好像您正在为每个论坛的 "in"/"out" 决定训练一个单独的 Doc2Vec
模型,然后使用一组即兴的 infer_vector()
/most_similar()
操作做出决定。
这是一种非常粗略的临时方法,您应该研究更正式的文本分类方法的介绍,其中有明确的特征发现步骤(可能包括创建 Doc2Vec
向量对于您的文本或其他技术),然后是分类器训练的明确步骤,然后是评估。
(那时您可能还会训练更大的模型,其中包括来自所有论坛的带标签的训练示例,以及从众多可能中选择一个的分类器 类。)
另外,您的 Doc2Vec
训练中有几处错误或不理想,包括:
在您自己的循环中多次调用 train()
或更改默认的 alpha
/min_alpha
值几乎总是被误导。您当前的代码实际上是 model.epochs
(5) 传递每次调用的数据,并且经常将 alpha
递减 0.0002
数百次(变为无意义的负值)。只需调用一次 train()
,使用所需数量的 epochs
,默认值为 alpha
/min_alpha
,它就会做正确的事情。 (并且:不要相信在线 tutorial/example 建议的上述循环调用。)
你的 hs=5
将打开严格的 on/off hierarchical-softmax 模式,但保留默认的 negative=5
参数 - 所以你的模型将使用负采样和分层 softmax 训练的(非标准且可能无用且缓慢)组合。最好使用一些 negative
值和 hs=0
(对于纯负采样)或 negative=0, hs=1
(对于纯分层 softmax)。或者只是坚持使用默认设置 (negative=5, hs=0
) unless/until 一切都已经正常工作,并且您想进行更深入的优化。
min_count=1
很少是最佳选择:这些模型通常受益于丢弃稀有词。
纠正这些问题后,您可能会发现更多的数据往往会带来通常预期的改进结果。 (如果当时没有,请仔细检查所有文本 preprocessing/tokenization 在训练、推理和评估时是否正确完成——如果你仍然有问题,也许 post 一个新的那么问题,更多 specifics/numbers 关于预期改进的地方反而得分更差。)
我正在使用 gensim 和 doc2vec 进行文本分类。我正在使用两个数据集对此进行测试,一个是堆栈交换数据集和一个 Reddit 数据集。我正在尝试对来自一个 subreddit/stackexchange 站点的某个特定主题的帖子进行分类,然后使用来自其他不相关 subreddit/stackexchange 站点的帖子作为负面示例。
我正在使用包含 10k 个帖子的数据集来训练模型,并使用 5k 个测试集分为 50% 的正例和 50% 的负例。然后,我使用 infer_vector 和 most_similar 函数将条目分类为正面或负面。在训练模型之前,我预处理数据以删除任何单词、符号、链接等,只留下最重要的单词来训练模型。下面是用于训练模型的代码。
df = pd.read_csv("fulltrainingset.csv")
df.columns.values[0] = "A"
tagged_data = [TaggedDocument(words=word_tokenize(_d.lower()), tags=[str(i)]) for i, _d in enumerate(df["A"])]
epoch_list = [1,5,10,15,25,50,100,200,300,400]
size_list = [1,5,10,15,25,50,100,200,300]
for x in epoch_list:
for y in size_list:
vec_size = y
max_epochs = x
minimum_count = 1
mode = 0
window_ = 15
negative_sampling = 5
subsampling = 1e-5
alpha = 0.025
minalpha = 0.00025
model = Doc2Vec(alpha=alpha, min_alpha=minalpha, vector_size=vec_size, dm=mode, min_count=minimum_count, window =window_, sample=subsampling ,hs =negative_sampling)
model.build_vocab(tagged_data)
for epoch in range(max_epochs):
print('iteration {0}'.format(epoch))
model.train(tagged_data,
total_examples=model.corpus_count,
epochs=model.epochs)#self.epochs
model.alpha -= 0.0002
model.min_alpha = model.alpha
model.save(str(y)+"s_"+str(x)+"e.model")
这个方法有效,我可以从中得到结果,但我想知道是否有不同的训练方式可以达到更好的效果。目前我只是训练许多具有不同时期和 vector_sizes 的模型,然后使用 infer_vector 和 most_similar 函数查看从 most_similar 条目返回的向量分数是否大于有一定数量,但是有没有办法在模型训练方面对此进行改进?
此外,为了获得更好的结果,我以相同的方式使用更大的数据集(超过 100k 个条目)训练了另一个模型。当我在同一个数据集上使用这个模型时,它产生了与在较小数据集上训练的模型相似但更差的结果。我认为更多的训练数据会改善结果而不是使它们变得更糟,有人知道这是什么原因吗?
此外,为了进一步测试,我创建了一个新的但更大的测试集(15k 个条目),它比原始测试集表现更差。此测试集中的数据虽然唯一,但与原始测试集中使用的数据类型相同,但产生的结果更差,这可能是什么原因?
df = pd.read_csv("all_sec_tweets.csv")
df.columns.values[0] = "A"
tagged_data = [TaggedDocument(words=word_tokenize(_d.lower()), tags=[str(i)]) for i, _d in enumerate(df["A"])]
epoch_list = [1,5,10,15,25,50,100]
size_list = [1,5,10,15,25,50,100]
for x in epoch_list:
for y in size_list:
vec_size = y
max_epochs = x
mode = 0
window_ = 5
subsampling = 1e-5
model = Doc2Vec(vector_size=vec_size, dm=mode, window =window_, sample=subsampling,epochs=max_epochs)
model.build_vocab(tagged_data)
model.train(tagged_data,total_examples=model.corpus_count,epochs=model.epochs)
model.save(str(y)+"s_"+str(x)+"e.model")
听起来好像您正在为每个论坛的 "in"/"out" 决定训练一个单独的 Doc2Vec
模型,然后使用一组即兴的 infer_vector()
/most_similar()
操作做出决定。
这是一种非常粗略的临时方法,您应该研究更正式的文本分类方法的介绍,其中有明确的特征发现步骤(可能包括创建 Doc2Vec
向量对于您的文本或其他技术),然后是分类器训练的明确步骤,然后是评估。
(那时您可能还会训练更大的模型,其中包括来自所有论坛的带标签的训练示例,以及从众多可能中选择一个的分类器 类。)
另外,您的 Doc2Vec
训练中有几处错误或不理想,包括:
在您自己的循环中多次调用
train()
或更改默认的alpha
/min_alpha
值几乎总是被误导。您当前的代码实际上是model.epochs
(5) 传递每次调用的数据,并且经常将alpha
递减0.0002
数百次(变为无意义的负值)。只需调用一次train()
,使用所需数量的epochs
,默认值为alpha
/min_alpha
,它就会做正确的事情。 (并且:不要相信在线 tutorial/example 建议的上述循环调用。)你的
hs=5
将打开严格的 on/off hierarchical-softmax 模式,但保留默认的negative=5
参数 - 所以你的模型将使用负采样和分层 softmax 训练的(非标准且可能无用且缓慢)组合。最好使用一些negative
值和hs=0
(对于纯负采样)或negative=0, hs=1
(对于纯分层 softmax)。或者只是坚持使用默认设置 (negative=5, hs=0
) unless/until 一切都已经正常工作,并且您想进行更深入的优化。min_count=1
很少是最佳选择:这些模型通常受益于丢弃稀有词。
纠正这些问题后,您可能会发现更多的数据往往会带来通常预期的改进结果。 (如果当时没有,请仔细检查所有文本 preprocessing/tokenization 在训练、推理和评估时是否正确完成——如果你仍然有问题,也许 post 一个新的那么问题,更多 specifics/numbers 关于预期改进的地方反而得分更差。)