【问题标题】:Estimating a probability given other probabilities from a prior在给定先验的其他概率的情况下估计概率
【发布时间】:2010-11-01 08:22:04
【问题描述】:

我有一堆关于某人是否购买特定产品的数据(呼叫自动呼叫中心),1 表示购买,0 表示不购买。

我想使用这些数据来估计一个人会购买特定产品的概率,但问题是我可能需要使用相对较少的历史数据来计算有多少人购买/没有购买该产品产品。

一位朋友建议使用贝叶斯概率,您可以通过提出“先验概率分布”来“帮助”您的概率估计,本质上这是在考虑实际数据之前有关您期望看到的信息。

所以我想做的是创建一个具有类似签名(Java)的方法:

double estimateProbability(double[] priorProbabilities, int buyCount, int noBuyCount);

priorProbabilities 是我在以前的产品中看到的一组概率,此方法将使用它来创建此概率的先验分布。 buyCount 和 noBuyCount 是该产品特定的实际数据,我想从中估计用户购买的概率,给定数据和先验。这是从方法作为双精度返回的。

我不需要数学上完美的解决方案,只需要比统一或平坦先验更好的解决方案(即,probability = buyCount / (buyCount+noBuyCount))。由于我对源代码比对数学符号更熟悉,如果人们可以在解释中使用代码,我将不胜感激。

【问题讨论】:

  • 真的很酷的问题,我想我知道确切的贝叶斯解决方案,但编写代码仍然需要一段时间(您介意可执行伪代码,AKA Python 源代码吗?我对 Java 有点生疏...;-)。
  • Alex,是的 - Python 或伪 Python 绝对没问题!
  • 我不认为这是一个编程问题。这是一个包含在 java 方法存根中的理论数学问题。
  • @Steven,对这里隐约涉及数学的任何事物的仇恨是什么?数学和编程密切相关。许多编程问题都有数学成分。如果在 SO 上不允许有任何与数学相关的内容,那么我很遗憾地说 SO 将是一个没那么有用且没那么有趣的网站。
  • 我同意@Steven A. Lowe;不直接编程相关

标签: java statistics probability


【解决方案1】:

听起来你想要做的是Association Rule Learning。我现在没有时间为您提供任何代码,但我会为您指明 WEKA 的方向,这是一个出色的 Java 开源数据挖掘工具包。你应该在那里找到很多有趣的东西来帮助你解决问题。

【讨论】:

  • 这很有趣,但我看不出它如何解决我描述的具体问题:-/
  • +1 对抗无知/懒惰;这是一个很好的建议
  • Steven,我已完整阅读了有关 ARL 的链接文章。或许您可以解释一下这个建议如何解决我概述的具体问题?
  • @sanity:如果你有其他相关的东西,ARL 会有所帮助。
  • @Steven,我不想与任何其他元数据相关联。我认为您(和 n3rd)正在尝试解决与问题中提出的问题不同的问题。
【解决方案2】:

在我看来,你能做的最好的就是使用均匀分布,除非你对分布有一些线索。或者您是在谈论在亚马逊时尚“购买此产品的人也购买......”的同一个人之前购买的产品之间建立关系??

【讨论】:

  • 关于分布的线索在方法的priorProbabilities参数中提供。这是我们为其他产品找到的购买概率列表 - 它可以(希望)用于得出该产品购买概率的先验分布。
  • 恕我直言,您需要将购买或不购买与其他一些参数相关联(例如,年龄、性别、国家、一年中的时间、一天中的时间、购买的其他产品等)。否则,您拥有的最佳信息是使用累积购买率的均匀分布。
  • 这就是我目前正在寻找的全部内容。通常我会寻求与年龄和性别等元数据相关联,但问题是根本没有足够的数据。我的挑战是根据最少量的数据(可能只有几百个电话,典型的购买率约为 5-10%)得出最准确的购买概率。根本不可能根据年龄或性别对数据进行分区,因为没有足够的数据。
  • @sanity:那么你必须使用均匀分布,其他任何东西都属于魔法领域。如果 100 人中有 20 人购买过,那么新人购买的概率是 1/5,仅此而已。
  • @tekBlues:我不这么认为。其他产品的实际发现概率形成了我们预期该概率所在位置的先验分布。例如,如果所有其他概率都在 5% 到 15% 之间,那么均匀分布显然是不合适的。
【解决方案3】:

这是贝叶斯计算和一个示例/测试:

def estimateProbability(priorProbs, buyCount, noBuyCount):
  # first, estimate the prob that the actual buy/nobuy counts would be observed
  # given each of the priors (times a constant that's the same in each case and
  # not worth the effort of computing;-)`
  condProbs = [p**buyCount * (1.0-p)**noBuyCount for p in priorProbs]
  # the normalization factor for the above-mentioned neglected constant
  # can most easily be computed just once
  normalize = 1.0 / sum(condProbs)
  # so here's the probability for each of the prior (starting from a uniform
  # metaprior)
  priorMeta = [normalize * cp for cp in condProbs]
  # so the result is the sum of prior probs weighed by prior metaprobs
  return sum(pm * pp for pm, pp in zip(priorMeta, priorProbs))

def example(numProspects=4):
  # the a priori prob of buying was either 0.3 or 0.7, how does it change
  # depending on how 4 prospects bought or didn't?
  for bought in range(0, numProspects+1):
    result = estimateProbability([0.3, 0.7], bought, numProspects-bought)
    print 'b=%d, p=%.2f' % (bought, result)

example()

输出是:

b=0, p=0.31
b=1, p=0.36
b=2, p=0.50
b=3, p=0.64
b=4, p=0.69

这与我对这个简单案例的手动计算一致。请注意,根据定义,购买概率始终介于先验概率集合中的最低和最高之间;如果这不是您想要的,您可能想通过引入两种“伪产品”来引入一点软糖,一种没有人会购买(p=0.0),一种任何人都会购买(p=1.0)——这给出了对实际观察的重视程度更高,尽管它们可能很稀缺,而对过去产品的统计数据的重视程度较低。如果我们在这里这样做,我们会得到:

b=0, p=0.06
b=1, p=0.36
b=2, p=0.50
b=3, p=0.64
b=4, p=0.94

可以很容易地设想到中等水平的捏造(考虑到这种新产品可能比以前销售的任何产品都差,或比其中任何产品更好的可能性不大,但并非不可能)(将较低的权重赋予人工 0.0和 1.0 的概率,通过将向量 priorWeights 添加到 estimateProbability 的参数)。

这类事情是我整天工作的重要组成部分,现在我在商业智能中开发应用程序,但我就是无法获得足够的...!-)

【讨论】:

  • 谢谢亚历克斯,我很高兴有人赞赏这个问题 :-) 这看起来绝对正确,但直到明天我才能详细检查你的答案。话虽如此,我现在很高兴接受你的回答:-)
  • 无论如何,请检查一下(根据需要转码为 Java,但请考虑使用 Jython 进行快速和肮脏的测试)并就这个问题或新问题回复我,我是至少和你一样热衷于让它正常工作!-) 贝叶斯万岁...!-)
【解决方案4】:

一种非常简单且无需任何复杂数学运算的方法是通过添加购买或未购买产品的虚拟客户来人为地增加 buyCount 和 noBuyCount。您可以根据您认为值得多少虚拟客户来调整您对每个特定先验概率的信任程度。

在伪代码中:

def estimateProbability(priorProbs, buyCount, noBuyCount, faithInPrior=None):
    if faithInPrior is None: faithInPrior = [10 for x in buyCount]
    adjustedBuyCount = [b + p*f for b,p,f in 
                                zip(buyCount, priorProbs, faithInPrior]
    adjustedNoBuyCount = [n + (1-p)*f for n,p,f in 
                                zip(noBuyCount, priorProbs, faithInPrior]
    return [b/(b+n) for b,n in zip(adjustedBuyCount, adjustedNoBuyCount]

【讨论】:

    猜你喜欢
    • 2014-08-11
    • 2020-10-23
    • 2021-03-14
    • 1970-01-01
    • 2015-07-29
    • 2014-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多