Question

J'ai un tas de données provenant de (appels vers un centre d'appel automatisé) si oui ou non une personne achète un produit particulier, 1 pour acheter, 0 pour ne pas acheter.

Je veux utiliser ces données pour créer une probabilité estimée qu'une personne va acheter un produit particulier, mais le problème est que je peux avoir besoin de le faire avec des données historiques relativement peu sur la façon dont beaucoup de gens ont acheté / ne pas acheter que produit.

Un ami recommandé avec une probabilité bayésienne, vous pouvez « aider » votre estimation de probabilité en proposant une « distribution de probabilité a priori », essentiellement ce sont des informations sur ce que vous attendez de voir, avant de prendre en compte les données réelles.

Alors, ce que je voudrais faire est de créer une méthode qui a quelque chose comme cette signature (Java):

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

priorProbabilities est un tableau de probabilités que j'ai vu des produits précédents, qui cette méthode utiliser pour créer une distribution préalable pour cette probabilité. buyCount et noBuyCount sont les données réelles spécifiques à ce produit, dont je veux estimer la probabilité de l'achat de l'utilisateur, compte tenu des données et l'avant. Il est renvoyé par la méthode en double.

Je ne suis pas besoin d'une solution mathématiquement parfaite, juste quelque chose qui va faire mieux qu'un uniforme ou avant plat (ie. = probabilité buyCount / (+ buyCount noBuyCount) ). Depuis que je suis beaucoup plus familier avec le code source que la notation mathématique, je serais reconnaissant si les gens pouvaient utiliser le code dans leur explication.

Était-ce utile?

La solution

Voici le calcul bayésienne et un exemple / test:

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()

sortie est la suivante:

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

qui est d'accord avec mon calcul en main pour ce cas simple. Notez que la probabilité d'achat, par définition, sera toujours entre le plus bas et le plus élevé parmi l'ensemble des probabilités a priori; si ce n'est pas ce que vous voulez, vous pouvez introduire un peu fudge en introduisant deux « pseudo-produits », l'un que personne ne jamais acheter (p = 0,0), un que tout le monde aura toujours acheter (p = 1,0) - ce qui donne plus de poids aux observations réelles, rares car ils peuvent être, et moins les statistiques sur les produits passés. Si nous le faisons ici, nous obtenons:

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

Les niveaux intermédiaires de truquage (pour tenir compte de la chance improbable mais pas impossible que ce nouveau produit peut être pire que tout jamais auparavant vendu, ou mieux que l'un d'eux) peuvent facilement être envisagées (donner un poids inférieur à la 0,0 artificielle et 1.0 probabilités, en ajoutant un vecteur priorWeights aux arguments de estimateProbability).

Ce genre de chose est une partie importante de ce que je fais tous les jours, maintenant que je travaille à développer des applications en Business Intelligence, mais je ne peux pas en avoir assez ... -)

Autres conseils

Une façon très simple de faire cela sans mathématiques difficile est d'augmenter artificiellement buyCount et noBuyCount en ajoutant des clients virtuels qui soit acheté ou ne pas acheter le produit. Vous pouvez régler combien vous croyez dans chaque probabilité a priori notamment en termes de nombre de clients virtuels que vous pensez qu'il vaut la peine.

En pseudocode:

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]

Sons comme ce que vous essayez de faire est Association Règle d'apprentissage . Je n'ai pas le temps maintenant de vous fournir un code, mais je vais vous diriger dans la direction de WEKA qui est une boîte à outils d'exploration de données open source fantastique pour Java. Vous devriez trouver beaucoup de choses intéressantes là-bas qui vous aidera à résoudre votre problème.

Comme je le vois, le mieux que vous pouvez faire est d'utiliser la distribution uniforme, sauf si vous avez quelques indices au sujet de la distribution. Vous parlez de faire un lien entre ces produits et les produits déjà achetés par la même personne dans le mode Amazon « Les gens qui achètent ce produit acheter aussi ... » ??

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top