Я хочу иметь возможность вводить новые «строки тегов» в базу данных, которые показываются пользователям «случайным образом». (Эти строки тегов показаны как введение в виде анимированного текста.)
Судя по количеству продаж, связанных с этими лозунгами, я бы хотел, чтобы лучшие из них попадали в топ, а остальные показывались реже.
Я мог бы довольно легко придумать базовый алгоритм, но мне нужно что-то более «статистически точное».
Я действительно не знаю, с чего начать. Давненько я не делал ничего, кроме базовой статистики. Моя модель должна быть чувствительна к допускам, но, очевидно, она не должна быть достойной докторской степени.
Редактировать: В настоящее время я отслеживаю «коэффициент конверсии», то есть количество обращений за заказ. Это значение, вероятно, лучше всего рассчитать как совокупную скорость преобразования «за все время», которую необходимо ввести в алгоритм.





Я бы предложил случайный выбор с весовым коэффициентом на основе предыдущих продаж. Итак, допустим, у вас было это:
Простая формула взвешивания: 1 + количество продаж, то есть вероятность выбора каждого тега:
Вы можете легко изменить формулу взвешивания, чтобы получить желаемое распределение.
Вы должны придумать формулу взвешивания, основанную на продажах.
Я не думаю, что здесь есть такая вещь, как «статистически точная» формула - все зависит от ваших предпочтений.
Никто не может сказать, что «это правильный вес, а другой вес - неверный», потому что нет окончательного результата, который вы пытаетесь смоделировать - это не то же самое, что пытаться взвесить ответы на опрос о предстоящих выборах (где вы пытаются смоделировать результаты, чтобы представить то, что произойдет в будущем).
Глядя на вашу проблему, я бы немного изменил требования -
1) Чаще следует показывать самый популярный. 2) Слоганы должны «стареть», поэтому те, за которые было много голосов (покупка) в прошлом, но ни одно из них в последнее время, не должны показываться реже. 3) Новые слоганы следует показывать чаще в первые дни.
Если вы согласны с этим, то алгоритм может быть примерно таким:
START:
x = random(1, 3);
if x = 3 goto NEW else goto NORMAL
NEW:
TagVec = Taglines.filterYounger(5 days); // I'm taking a LOT of liberties with the pseudo code,,,
x = random(1, TagVec.Length);
return tagVec[x-1]; // 0 indexed vectors even in made up language,
NORMAL:
// Similar to EBGREEN above
sum = 0;
ForEach(TagLine in TagLines) {
sum += TagLine.noOfPurhcases;
}
x = random(1, sum);
ForEach(TagLine in TagLines) {
x -= TagLine.noOfPurchase;
if ( x > 0) return TagLine; // Find the TagLine that represent our random number
}
Теперь, в качестве установки, я бы дал каждому новому слогану 10 покупок, чтобы не получить действительно большой уклон для одной покупки.
Процесс старения Я бы посчитал покупку старше недели как 0,8 покупки за неделю возраста. Таким образом, 1 неделя дает 0,8 балла, 2 недели дают 0,8 * 0,8 = 0,64 и так далее ...
Вам придется поиграть с параметром Initial purhcases (10 в моем примере), скоростью старения (здесь 1 неделя) и коэффициентом старения (здесь 0,8), чтобы найти что-то, что вам подходит.
Вот пример на javascript. Не то чтобы я не предлагал запускать эту клиентскую часть ... Также можно сделать много оптимизации.
Примечание: createMemberInNormalDistribution () реализована здесь Преобразование равномерного распределения в нормальное распределение
/*
* an example set of taglines
* hits are sales
* views are times its been shown
*/
var taglines = [
{"tag":"tagline 1","hits":1,"views":234},
{"tag":"tagline 2","hits":5,"views":566},
{"tag":"tagline 3","hits":3,"views":421},
{"tag":"tagline 4","hits":1,"views":120},
{"tag":"tagline 5","hits":7,"views":200}
];
/*set up our stat model for the tags*/
var TagModel = function(set){
var hits, views, sumOfDiff, sumOfSqDiff;
hits = views = sumOfDiff = sumOfSqDiff = 0;
/*find average*/
for (n in set){
hits += set[n].hits;
views += set[n].views;
}
this.avg = hits/views;
/*find standard deviation and variance*/
for (n in set){
var diff =((set[n].hits/set[n].views)-this.avg);
sumOfDiff += diff;
sumOfSqDiff += diff*diff;
}
this.variance = sumOfDiff;
this.std_dev = Math.sqrt(sumOfSqDiff/set.length);
/*return tag to use fChooser determines likelyhood of tag*/
this.getTag = function(fChooser){
var m = this;
set.sort(function(a,b){
return fChooser((a.hits/a.views),(b.hits/b.views), m);
});
return set[0];
};
};
var config = {
"uniformDistribution":function(a,b,model){
return Math.random()*b-Math.random()*a;
},
"normalDistribution":function(a,b,model){
var a1 = createMemberInNormalDistribution(model.avg,model.std_dev)* a;
var b1 = createMemberInNormalDistribution(model.avg,model.std_dev)* b;
return b1-a1;
},
//say weight = 10^n... higher n is the more even the distribution will be.
"weight": .5,
"weightedDistribution":function(a,b,model){
var a1 = createMemberInNormalDistribution(model.avg,model.std_dev*config.weight)* a;
var b1 = createMemberInNormalDistribution(model.avg,model.std_dev*config.weight)* b;
return b1-a1;
}
}
var model = new TagModel(taglines);
//to use
model.getTag(config.uniformDistribution).tag;
//running 10000 times: ({'tagline 4':836, 'tagline 5':7608, 'tagline 1':100, 'tagline 2':924, 'tagline 3':532})
model.getTag(config.normalDistribution).tag;
//running 10000 times: ({'tagline 4':1775, 'tagline 5':3471, 'tagline 1':1273, 'tagline 2':1857, 'tagline 3':1624})
model.getTag(config.weightedDistribution).tag;
//running 10000 times: ({'tagline 4':1514, 'tagline 5':5045, 'tagline 1':577, 'tagline 2':1627, 'tagline 3':1237})
config.weight = 2;
model.getTag(config.weightedDistribution).tag;
//running 10000 times: {'tagline 4':1941, 'tagline 5':2715, 'tagline 1':1559, 'tagline 2':1957, 'tagline 3':1828})