Closed transposition closed 2 years ago
@transposition 抱歉,我们目前的context-aware模型在进行全排序的时候,只能使用.user
和.item
文件中的上下文信息,对于你说的这种交互时的上下文信息,我们目前不支持。主要原因是在构造负例时,设置负例的context信息比较麻烦,我们也会在之后考虑支持这个功能。
@transposition 抱歉,我们目前的context-aware模型在进行全排序的时候,只能使用
.user
和.item
文件中的上下文信息,对于你说的这种交互时的上下文信息,我们目前不支持。主要原因是在构造负例时,设置负例的context信息比较麻烦,我们也会在之后考虑支持这个功能。
不好意思哈,我还是小白,对很多概念可能有理解偏差。。。
先再描述下我的场景哈,差别是contex 信息,既不属于user,也不属于item
我现在的做法: 我现在是把contex信息放到.inter, 这样 train okay,但valid阶段报错 ,原因是valid 阶段用的是ContextFullDataLoader,他在生成batch样本的时候,是用 .user 为主表,而不是 .inter 导致 只取到了 user,iterm的信息
我理解需的流程: train阶段,有(user, contex,item_pos),要做负采样,将(user, contex,item_pos)中的item_pos 替换成负采样的item_neg,再增加label valid阶段,有(user, contex,),要将所有tiem信息补全,(user, contex,item_all),再增加label。如果是全排序,似乎是不需要负采样
我在想是不是改一下 ContextFullDataLoader部分data的生成就可以了?
def _next_batch_data(self):
# user_df = self.user_df[self.pr:self.pr + self.step] -- 不从user 取
-- step 1
user_df = self.inter[self.pr:self.pr + self.step] -- 改成 从inter取数,得到(user,contex)
# cur_data = self._neg_sampling(user_df) --这里一直没看明白,eval 阶段不是全排序么,为什么也要负采样,看完代码也还是懵逼。。。
-- step 2
(user, contex,)复制 item_num次
加入所有item (user, contex,) -> (user, contex,item)
-- step 3
(user, contex,item)-> (user, contex,item,label)
self.pr += self.step
return cur_data
求指正
@transposition 抱歉,我们目前的context-aware模型在进行全排序的时候,只能使用
.user
和.item
文件中的上下文信息,对于你说的这种交互时的上下文信息,我们目前不支持。主要原因是在构造负例时,设置负例的context信息比较麻烦,我们也会在之后考虑支持这个功能。
不好意思哈,我还是小白,对很多概念可能有理解偏差。。。
先再描述下我的场景哈,差别是contex 信息,既不属于user,也不属于item
我现在的做法: 我现在是把contex信息放到.inter, 这样 train okay,但valid阶段报错 ,原因是valid 阶段用的是ContextFullDataLoader,他在生成batch样本的时候,是用 .user 为主表,而不是 .inter 导致 只取到了 user,iterm的信息
我理解需的流程: train阶段,有(user, contex,item_pos),要做负采样,将(user, contex,item_pos)中的item_pos 替换成负采样的item_neg,再增加label valid阶段,有(user, contex,),要将所有tiem信息补全,(user, contex,item_all),再增加label。如果是全排序,似乎是不需要负采样
我在想是不是改一下 ContextFullDataLoader部分data的生成就可以了?
def _next_batch_data(self):
# user_df = self.user_df[self.pr:self.pr + self.step] -- 不从user 取
-- step 1
user_df = self.inter[self.pr:self.pr + self.step] -- 改成 从inter取数,得到(user,contex)
# cur_data = self._neg_sampling(user_df) --这里一直没看明白,eval 阶段不是全排序么,为什么也要负采样,看完代码也还是懵逼。。。
-- step 2
(user, contex,)复制 item_num次
加入所有item (user, contex,) -> (user, contex,item)
-- step 3
(user, contex,item)-> (user, contex,item,label)
self.pr += self.step
return cur_data
求指正
@transposition 你好,可能这里对于全排序来说,“负采样”这一说法并不准确,这里其实想强调的是负例的构造。在你所描述的这个场景下,负例的context信息构造存在一个问题,就是我如何生成负例的交互时的context信息。
以你所说的位置信息为例,它是个token类型,那么如果用户在测试集有两个正例交互,第一个在“北京”,第二个在“上海”;那么在评测时,对于其他未交互的商品(负例),我们如何设置它的这个位置信息呢?这里就会有很多做法,比如随机设置(从“北京,上海”中随机选),比如永远和第一个正例保持一致(都设置成“北京”),又或者可以设置成特殊的token等等。就目前对于这个问题,我们团队有过很多次讨论,但没有得出一个较为统一的结论,因此我们暂时搁置了这个功能的支持。
你的写法我看了,依然没有解决这个问题(或者说你的策略是context信息永远和第一个交互保持一致)。当然,如果你可以选择好自己的负例构造策略(比如都设置成“北京”),那么你可以按照你的思路自行修改这块的代码,来实现你的想法。但对于一个通用性较强的工具包来说,我们是不能写死这里的逻辑的;
希望我的回答能够解释你的问题,谢谢
@transposition 你好,可能这里对于全排序来说,“负采样”这一说法并不准确,这里其实想强调的是负例的构造。在你所描述的这个场景下,负例的context信息构造存在一个问题,就是我如何生成负例的交互时的context信息。
以你所说的位置信息为例,它是个token类型,那么如果用户在测试集有两个正例交互,第一个在“北京”,第二个在“上海”;那么在评测时,对于其他未交互的商品(负例),我们如何设置它的这个位置信息呢?这里就会有很多做法,比如随机设置(从“北京,上海”中随机选),比如永远和第一个正例保持一致(都设置成“北京”),又或者可以设置成特殊的token等等。就目前对于这个问题,我们团队有过很多次讨论,但没有得出一个较为统一的结论,因此我们暂时搁置了这个功能的支持。
你的写法我看了,依然没有解决这个问题(或者说你的策略是context信息永远和第一个交互保持一致)。当然,如果你可以选择好自己的负例构造策略(比如都设置成“北京”),那么你可以按照你的思路自行修改这块的代码,来实现你的想法。但对于一个通用性较强的工具包来说,我们是不能写死这里的逻辑的;
希望我的回答能够解释你的问题,谢谢
非常感谢你耐心、详尽又及时的回复,不好意思,最后能再追问一下,没有形成较为统一的结论争论的点具体是什么?
首先,我的策略,确实是context信息永远和第一个交互保持一致。比如,(user、晚上、上海) -> 买了 KFC,那(user、晚上、上海,其它商家)就都是负样本。 我理解实际场景中,context是可以获取的,所以test数据集,contex也是已知的。所以,目标就是要预测用户,用户在当前context的条件下购买各个item 的 P( buy |user,context)。
那么
对于没有交互的,可能是没有浏览,也可能是浏览了没有购买,我理解可以都当做负样本,都是用户在当前context条件下,没有购买。 问题:负样本可能不为负,但影响不大 对于没有浏的item,会有样本有偏的问题。假设用户当前购买item a ,但如果用户浏览的时候看到更便宜的b后,可能会放弃当前购买的item a,转而购买b,但这种样本在item库中占比可能特别少,所以即使label 都赋为0,label错误比例也很小。所以把没有交互的都当做负样本我觉得问题不大。
我理解这种做法好像不太能理解,我们只知道用户在当前context条件下,买了啥,但不知道用户在context条件变化后,会不会买其他的item,根本无法推断label。甚至contex维度多了之后,会随机采样出用户事实上都不会发生的context(比如一个奉行995的员工,时间:周末,地点:公司),那这个样本好像都没啥意义。当然也可以理解成一种样本增强。
在实际线上预测的时候,context都是已知的,所以设置成特殊的token,也会导致这个样本,在线上实际不存在,那对于训练来说,也是没有帮助的。
总结下,我觉得第1种方案,虽有label会有问题,但至少有实际意义,后2种的方案,不仅无法推断label,而且生成的负样本好像都没有实际意义。所以我觉得方案1是合理的策略,毕竟评估的时候也是看在当前context条件下的召回。
周末愉快!
@transposition 你好,我们没有确定好策略的主要原因是:目前没有找到有相关的文献(已发表的会议论文)来描述这一环节的策略(当然,也可能是我们没有调研完全),我刚刚提出的这几种策略,其实都是“拍脑袋”想到的方法。作为一款用于科研的工具包,我们希望我们设计的所有策略都是有依据可循的(有相关的论文支撑或者实际的工业应用支撑)。如果你的方案有相关的文献或者工业界真实应用的支撑,可以在本issue下进行回复你的reference,我们会仔细阅读并考虑。
关于方案一和方案二,其实方案一也有随机性的问题,这个随机性体现在第一个出现的交互是什么?还用刚刚的例子,如果第一个出现的是“北京”,那么你的负例可能都是“北京”,但如果第一个出现的是“上海”,那么负例就全部都是“上海”了。这和方案二不是有同样的问题吗?所以我个人认为,这个策略的设置有很多不确定的因素,无论哪种方法,可能都会有bias。
@transposition 你好,我们没有确定好策略的主要原因是:目前没有找到有相关的文献(已发表的会议论文)来描述这一环节的策略(当然,也可能是我们没有调研完全),我刚刚提出的这几种策略,其实都是“拍脑袋”想到的方法。作为一款用于科研的工具包,我们希望我们设计的所有策略都是有依据可循的(有相关的论文支撑或者实际的工业应用支撑)。如果你的方案有相关的文献或者工业界真实应用的支撑,可以在本issue下进行回复你的reference,我们会仔细阅读并考虑。
关于方案一和方案二,其实方案一也有随机性的问题,这个随机性体现在第一个出现的交互是什么?还用刚刚的例子,如果第一个出现的是“北京”,那么你的负例可能都是“北京”,但如果第一个出现的是“上海”,那么负例就全部都是“上海”了。这和方案二不是有同样的问题吗?所以我个人认为,这个策略的设置有很多不确定的因素,无论哪种方法,可能都会有bias。
原来如此,那等我找到了reference再回复哈。我先用方案一实现下,因为我这个场景,每个用户的contex其实不太随机,有点像用户的习惯吧。
再次感谢!
@transposition 我也遇到类似的问题,也是需要把 context加入至 inter之中,比如说 day-of-week, hour-of-day,之类,还有像 user_past_3_days_purchase
这种算是user feature,可是是会随着时间而改变的feature.
发现recbole处理不了这种情况,结果就需要自己改编。
文献的话,这里附上腾讯的 https://arxiv.org/pdf/1706.06978.pdf deep interest network, 里面可以看到他们也引用了context feature
希望recbole团队可以考虑列入这个需求。
我试着改了下,也挺容易的,放到.inter里面,改了下 GeneralFullDataLoader,你可以先应急,同期待官方
def _next_batch_data(self):
# user_df = self.user_df[self.pr:self.pr + self.step]
# cur_data = self._neg_sampling(user_df)
# self.pr += self.step
# return cur_data
inter_df = self.dataset.inter_feat[self.pr:self.pr + self.step]
# input_inter = self.dataset.join(inter_df) # join user feature
inter_df.update(self.dataset.user_feat[inter_df[self.dataset.uid_field]]) # join user feature
cur_data = self._neg_sampling(inter_df)
self.pr += self.step
return cur_data
@jianshen92 你好,我们会仔细阅读你提供的文献并尽快考虑添加这个功能,谢谢!
@jianshen92 你好,这篇DIN的论文我读过了,文中似乎并没有明确说明实验测试时,对于负样本的context信息的构造方法,而文中实验的测评方式也似乎不是全排序评测,因此目前我无法通过这篇文献来解决本issue的问题。如果我有阅读遗漏的地方,欢迎指出!
@transposition 你好,我们没有确定好策略的主要原因是:目前没有找到有相关的文献(已发表的会议论文)来描述这一环节的策略(当然,也可能是我们没有调研完全),我刚刚提出的这几种策略,其实都是“拍脑袋”想到的方法。作为一款用于科研的工具包,我们希望我们设计的所有策略都是有依据可循的(有相关的论文支撑或者实际的工业应用支撑)。如果你的方案有相关的文献或者工业界真实应用的支撑,可以在本issue下进行回复你的reference,我们会仔细阅读并考虑。
关于方案一和方案二,其实方案一也有随机性的问题,这个随机性体现在第一个出现的交互是什么?还用刚刚的例子,如果第一个出现的是“北京”,那么你的负例可能都是“北京”,但如果第一个出现的是“上海”,那么负例就全部都是“上海”了。这和方案二不是有同样的问题吗?所以我个人认为,这个策略的设置有很多不确定的因素,无论哪种方法,可能都会有bias。
为什么不去找最接近的Context呢?一般在Industry就是这么做
我试着改了下,也挺容易的,放到.inter里面,改了下 GeneralFullDataLoader,你可以先应急,同期待官方
def _next_batch_data(self): # user_df = self.user_df[self.pr:self.pr + self.step] # cur_data = self._neg_sampling(user_df) # self.pr += self.step # return cur_data inter_df = self.dataset.inter_feat[self.pr:self.pr + self.step] # input_inter = self.dataset.join(inter_df) # join user feature inter_df.update(self.dataset.user_feat[inter_df[self.dataset.uid_field]]) # join user feature cur_data = self._neg_sampling(inter_df) self.pr += self.step return cur_data
请问.iter文件除user_id与item_id外的特征如何引入模型训练呢?感谢。
请问,上下文信息怎么加入,比如预测用户每一次购买的商品TopK ,用户下单的时点信息(比如星期几),位置信息(城市) 之前没搞过这个。。。请见谅
我用Wide&Deep 模型的时候,尝试过放在.inter 里面,但是在eval 的时候,这些字段没有带进来。eval的时候,interaction 只有.user的字段,缺少了上下文信息,就会导致找不到field 报错。看了下源码,取出来的interaction只有user的字段