用于预测集合成员的机器学习方法

数据挖掘 机器学习 深度学习 预测建模
2022-02-26 05:48:40

假设我有一个包含 40 个项目的大型训练数据集,并且集合中的每个项目都是唯一的(因此每个训练输入都是一个集合),并且有 40 多种独特的物品可以成为套装的一部分。S={i1,i2,...,i40}

给定一些不完整的集合,我希望能够预测哪些项目可能是集合的成员。所以让我们看下面的例子:

训练数据: , , 假设我有一个输入,我希望该方法能够返回 1、2、4 和 5 比 7、8 更可能的集合成员。理想情况下,具有一些概率值。S1={1,2,3}S2={3,4,5}S3={6,7,8}
S4={3}

我考虑过以下几点:
使用先验算法学习一些关联规则。我不确定如何将支持或提升解释为集合成员的概率。

在输入(可能是 one-hot 编码)上训练多层感知器以学习与各种输入项对应的权重。但是,如果我只是简单地将 40 项集合作为输入和输出,那么网络只会学习复制输入,而不会提供有关可能的其他集合成员的信息。我曾考虑将 40 个项目集的所有变体作为输入,将 40 个项目集作为输出,但这会导致可能性,这将是巨大的。240

在这种情况下,是否有一些机器学习方法或数据结构可以提供帮助?

4个回答

你可以训练一个嵌入模型每个元素将根据其与其他元素的共现被投影到向量空间的位置。然后可以通过最近邻搜索来找到相似的元素。

也许这有点矫枉过正并且偏向于我自己的领域(神经机器翻译),但是您可以在掩码语言模型(即BERT)配置中使用具有自注意力的神经网络架构

网络的输入将是一个固定大小 (40) 的离散符号序列,这意味着该位置的元素是否存在于集合中 (P), 没有它 (A) 或其存在未知 (U)。输入标记的“词汇”将是P,A,U. 这样,输入将是 40 个符号的序列,例如A,A,P,U,U,...,P.

输入将被送入嵌入层,然后是N层层暴露的自我关注。

最后,最后的注意力层输出将被投影到大小为 40 的表示空间中,然后将应用 sigmoid 函数来获得集合中 40 个元素中的每一个元素成为原始输入一部分的概率。

损失函数只会在输入被标记为未知的元素上计算(U) 并在其他地方忽略。这些位置的预期输出将是1如果元素实际存在,否则0. 您可以使用二元交叉熵作为损失函数进行优化。

您应该准备训练数据,以便标记为未知(U) 原始集合中的元素,具有您在测试数据中期望的未知元素比率。

在推理时,您只需将您知道的信息设置为P或者A并将未知元素设置为U,并在这些位置获得网络的输出。

请注意,从任何完整的集合中,您可以为您的任务形成一个问答对:您可以构建一个不完整的集合(“问题”),您知道所需的完整集合(“答案”)。特别是,给定一个完整的集合S, 你可以随机选择一个子集TS特定大小,并调用T不完整的集合。这样,从您的完整集数据集中,您可以形成一个非常大的输入-输出对训练集(T,S).

接下来,给定这个训练集,我建议训练任何 ML 模型来预测ST. 如何实例化模型有很多可能性。

例如,假设宇宙(可能出现在集合中的所有可能元素)不是太大,比如说m项目。然后,您可以使用 one-hot 编码对集合进行编码。现在,您可以构建一个神经网络,其输入是T并且其输出是m维向量(p1,,pm)这样p1++pm=1(这个向量可以由最终的 softmax 层生成)。您现在可以解释pi作为该项目的概率i应该包含在最后的集合中。换句话说,您可以通过包含 itemi有概率pi并有可能省略它1pi(为每个人做一个独立的选择i)。现在,在以这种方式诱导的集合的分布中,我们希望限制为大小为 40 的集合,即以结果集合大小为 40 的事件为条件。给定一个目标集合S,可以明确计算获得该特定集合的概率:它是x40在多项式中(p1x+1p1)(p2x+1p2)(pmx+1pm),可以相对有效地计算。也是一个可微函数p1,,pm. 因此,您可以将损失函数定义为该概率的负对数,并且您可以使用随机梯度下降来训练您的网络并找到最小化该损失的参数。作为优化,您可能会强制输出集自动包含输入T, 并且只在不在的元素上使用 softmaxT.

您可以采用纯粹基于计数的方法,通常称为最大似然估计 (MLE)。

遍历集合并计算同时出现的频率。然后找到最常见的项目。

这是 Python 中的一个直接(但不是非常优化)的解决方案:

from collections import defaultdict
from itertools   import permutations 

sets = [{1, 2, 3}, {3, 4, 5}, {6, 7, 8}, {3, 4, 5}]

counts = defaultdict(lambda: defaultdict(int))

# Create the frequency count of co-occurance of pairs
for s in sets:
    perms = permutations(s, 2)
    for p in perms:
        counts[p[0]][p[1]] += 1

# For a given element, order by co-occurance frequency 
key = 3
counts_ordered = dict(sorted(counts[key].items(), 
                      key=lambda x: x[1],
                      reverse=True))

# Find probability
denominator = sum(counts_ordered.values())
print(f"For element {key}:") 
for k,v in counts_ordered.items():
    print(f"The probability of {k} co-occuring is {v/denominator:.3}.")
print("All other probabilities are zero.")

对于元素 3:
4 同时出现的概率是 0.333。
5 同时出现的概率是 0.333。
1 同时出现的概率是 0.167。
2 同时出现的概率是 0.167。
所有其他概率为零。