我有一个项目对的列表,其中每个项目都由一个数字id索引。
例如
| 项目1|项目2|
| --|--|
| 1 | 1 |
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 3 | 2 |
| 4 | 5 |
| ......你好。|......你好。|
数字对不一定从0开始排列,并且可能不包括其间的所有值(例如,项目7可能存在,即使项目6不在数据集中)。
我从这个列表中随机抽样,并希望创建多个负样本(即,不存在的样本)。
目前,我的代码看起来像这样,但花的时间太长了:
import pandas as pd
import numpy as np
num_neg_samples = 4
# sample data
rng = np.random.default_rng()
all_pairs = pd.DataFrame({
'TARGET_ID': rng.choice(1_000_000, size=500_000, replace=True),
'CONTEXT_ID': rng.choice(1_000_000, size=500_000, replace=True)
})
pair_sample = all_pairs.sample(10240)
print(pair_sample.head())
import time
start = time.time()
targets = np.repeat(pair_sample['TARGET_ID'].values,(num_neg_samples+1),axis=0)
contexts = pair_sample['CONTEXT_ID']
negids = []
print(f'{len(pair_sample["TARGET_ID"])} target_ids to create neg samples for')
for index, target_id in enumerate(pair_sample['TARGET_ID']):
neg_samples = rng.choice(
all_pairs.loc[all_pairs['TARGET_ID'] != target_id, 'TARGET_ID'].values,
size=num_neg_samples
)
negids.append(neg_samples)
print(time.time() - start, 'seconds')
batch = (negatives, contexts, targets)
测试结果:
TARGET_ID CONTEXT_ID
252373 5238 953345
290732 589947 869541
124135 365468 373147
129140 566125 542728
450409 688717 936377
10240 target_ids to create neg samples for
26.611750602722168 seconds
每轮训练我抽取10240对。因此,我希望最终得到40960个负对,在我的数据集中每个“目标项”有4个。
有没有人有好的方法来加速这段代码?任何帮助都非常感谢。
编辑:随着问题的出现:成对项是一起出现在搜索结果中的项。我想训练一个类似于word 2 vec或自动编码器的模型,它生成一个嵌入,这个嵌入对于在搜索结果中一起出现的项目是相似的。为了改进嵌入,我也想用负样本进行训练,即。不同时出现在搜索结果中的成对项目。
编辑2:请注意,我可用的对可能包括重复,即。相同的一对每个项目ID将在item_1
和item_2
列中出现多次。
3条答案
按热度按时间af7jpaap1#
对DataFrame进行切片的成本很高。使用python和sets对我来说快了5倍:
输出量:
使用python的
random.sample
快10倍:xkftehaa2#
您可以通过使用
concurrent.futures.ThreadPoolExecutor
在并行线程中收集过滤后的负样本来加快处理速度。我在我的机器上获得了4-5倍的速度提升(初始方法:~93秒,螺纹:约20秒):w8biq8rn3#
根据@mozway的回答和这个,我在一个相关的帖子中发现:https://stackoverflow.com/a/44349133/5240684,我想出了以下,这是足够的我的情况:
测试结果:
即使从1 mio不同的目标id中采样,我的机器上的处理时间也增加到只有大约0.31秒。
基本思想是将目标id的索引设置为从0到len(unique_targets)的范围,这样我们就可以从一个范围而不是从一个集合中采样一个随机整数,因为这样更快。
这样,我最终得到
batch = (contexts, targets, negative_contexts, negative_targets)
作为我的批处理。谢谢你给我指明了正确的方向。