Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Вычисление вероятностей попадания объекта X на место Y, в зависимости от одного параметра. / 7 сообщений из 7, страница 1 из 1
15.04.2008, 14:30
    #35256278
tIT-GP
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вычисление вероятностей попадания объекта X на место Y, в зависимости от одного параметра.
Задача следующая. Есть M клиентов, готовых платить бабло за каждый показ на рекламной площадке. Рекламная площадка представляет из себя список мест от 1 до k>=5. Чем больше клиент платит за показ, тем выше его вероятность оказаться на первом месте.
Требуется расписать клиенту таблицу вероятностей для первых 5 мест. В первой строчке информация о самом клиенте с его ставкой, далее идут 4 строки с конкурентами по убыванию вероятностей для первого места и далее строка со "всеми остальными". Поскольку мест для расчета немного, решил для каждого места реализовать свой алгоритм.

Для первого места все просто: P1(x) = x / sum(Xi), где i = 1..M

Для второго места сложнее: P2(x) = Sum( P1(Xi) * (x / sum(Xj)) ), где i = 1..M, кроме позиции x; j = 1..M при j != i.
Иначе говоря, суммируем произведения вероятностей показа каждого объекта на первом месте, кроме x и вероятностей показа на втором месте без учета уже показанного на первом (звучит ужасно!).

Для третьего места еще сложнее: P3(x) = Sum ( P1(Xi)*P2(Xj)* (x / sum(Xk)) ), где i=1..M, кроме позиции x; j = 1..M, кроме позиции x и j != i; k = 1..M, при k != i и k != j.

Далее я расписал на бумаге подробные формулы для 4, 5 и 6 объектов, упростил их и реализовал соответствующие алгоритмы. Считаю алгоритмы работающими, если, как минимум, возвращаемые ими вероятности для данного места в сумме дают 1.
Для первого и второго случая все работает корректно, а в третьем стабильно не хватает до единицы от 0.2 до 0.3.

Вот готовая программа на PHP:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
#!/usr/bin/php
<?php

error_reporting(E_ALL);

$in_out[ 0 ] = array(
     5 ,  10 ,  15 ,  20 
);

TV1(&$in_out);
TV2(&$in_out);
TV3(&$in_out);

//print_r($in_out);

function TV1 (&$in_out)
{
    $sum = array_sum($in_out[ 0 ]);
    foreach ($in_out[ 0 ] as $k => $v)
        $in_out[ 1 ][$k] = $v / $sum;
}

function TV2(&$in_out)
{
    // Init divisors once
    $divs = array();
    $cnt = count($in_out[ 0 ]);
    for ($i =  0 ; $i < $cnt; $i++)
    {
        $buf = $in_out[ 0 ];
        array_splice(&$buf, $i,  1 );
        $divs[$i] = array_sum($buf);
    }

    // Calculates chances
    for ($i =  0 ; $i < $cnt; $i++)
    {
        $in_out[ 2 ][$i] =  0 ;
        foreach ($in_out[ 0 ] as $k => $v) {
            if ($k == $i)
                continue;
            $in_out[ 2 ][$i] += $in_out[ 1 ][$k] * $in_out[ 0 ][$i] / $divs[$k];
        }
    }
}

function TV3(&$in_out)
{
    // Init factors once
    $factors = array();
    $cnt = count($in_out[ 0 ]);
    for ($i =  0 ; $i < $cnt -  1 ; $i++)
    {
        for ($j = $i +  1 ; $j < $cnt; $j++)
        {
            $buf = $in_out[ 0 ];
            // Keep this order - first $j, next $i!
            array_splice(&$buf, $j,  1 );
            array_splice(&$buf, $i,  1 );
            $factors[$i.$j] = ($in_out[ 1 ][$i]*$in_out[ 2 ][$j] + $in_out[ 1 ][$j]*$in_out[ 2 ][$i]) / array_sum($buf);
            echo "$i$j\n";
        }
    }
    $keys = array_keys($factors);
    for ($i =  0 ; $i < $cnt; $i++)
    {
        $sum =  0 ;
        foreach ($keys as $v) {
            $v = (string) $v;
            if ($v{ 0 } == $i || $v{ 1 } == $i)
                continue;
            $sum += $factors[$v];
            echo 'a';
        }
        $in_out[ 3 ][$i] = $in_out[ 0 ][$i] * $sum;
        echo "\n";
    }
}

?>

Алгоритм много раз трассировал на соответствие математическим выкладкам - все работает корректно.
...
Рейтинг: 0 / 0
15.04.2008, 19:01
    #35257222
mikhail_n
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вычисление вероятностей попадания объекта X на место Y, в зависимости от одного параметра.
Если сами формулы верные (для второго места выглядит правильно, по-крайней мере словестное описание, а дальше не вникал) то теряете точность при суммировании длинных рядов. Вообщем-то проблема стара как компьютерный мир. Как это отслеживать на PHP не знаю, на C существуют специальные либы в соответсвии с IEEE стандартом. Погуглите на тему "алгоритм сумирования Кахана/Kahan summation algorithm", может поможет. А на PHP я даже не понимаю в переменных какого типа/длины Вы храните суммируемые обьекты и накапливаемую сумму.
...
Рейтинг: 0 / 0
16.04.2008, 14:43
    #35259060
tIT-GP
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вычисление вероятностей попадания объекта X на место Y, в зависимости от одного параметра.
Вообще представление от платформы зависит - вплоть до IEEE. Попробую bcmath использовать.
...
Рейтинг: 0 / 0
16.04.2008, 16:09
    #35259485
tIT-GP
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вычисление вероятностей попадания объекта X на место Y, в зависимости от одного параметра.
Да нет, проблема где-то в формулах третьего уровня.
Вот результат с использованием библиотеки точных чисел:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
Array
(
    [ 0 ] => Array
        (
            [ 0 ] =>  5 
            [ 1 ] =>  10 
            [ 2 ] =>  15 
            [ 3 ] =>  20 
        )

    [ 1 ] => Array
        (
            [ 0 ] =>  0 . 10000000000000000000 
            [ 1 ] =>  0 . 20000000000000000000 
            [ 2 ] =>  0 . 30000000000000000000 
            [ 3 ] =>  0 . 40000000000000000000 
        )

    [ 2 ] => Array
        (
            [ 0 ] =>  0 . 13452380952380952380 
            [ 1 ] =>  0 . 24126984126984126983 
            [ 2 ] =>  0 . 30833333333333333333 
            [ 3 ] =>  0 . 31587301587301587301 
        )

    [ 3 ] => Array
        (
            [ 0 ] =>  0 . 13942857142857142850 
            [ 1 ] =>  0 . 20328571428571428560 
            [ 2 ] =>  0 . 19287074829931972770 
            [ 3 ] =>  0 . 18385941043083900200 
        )

)

В первом элементе массива тестовые цены за показ - 5, 10, 15, 20.
...
Рейтинг: 0 / 0
17.04.2008, 20:48
    #35263088
mikhail_n
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вычисление вероятностей попадания объекта X на место Y, в зависимости от одного параметра.
Вот результат с использованием библиотеки точных чисел:

А это што ещё за зверь? Я видел библиотеку где длина слова не фиксирована и в зависимости от заказанной точности выходного результата может рости до 1МБ, так даже её авторы не называли библиотекой "точных" чисел. Всё-таки я грешу на точность. Если применять алгоритм Кахана влом, ну... попробуйте с формулами поиграться. Скажем для третьего уровня можно переписать в "более реккурентном" виде так:

P3(x) = P1(x) * Sum (Sum ( P1(Xi)*P2(Xj)* (1 / 1 - P1(Xi) - P1(Xj)))

Не думаю что поможет, но шанс есть...
...
Рейтинг: 0 / 0
17.04.2008, 20:51
    #35263099
mikhail_n
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вычисление вероятностей попадания объекта X на место Y, в зависимости от одного параметра.
Уупс, пропустил одну пару скобок, но Вы поймёте что я имел ввиду...
...
Рейтинг: 0 / 0
18.04.2008, 13:25
    #35264459
tIT-GP
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вычисление вероятностей попадания объекта X на место Y, в зависимости от одного параметра.
Вот ее я, видимо и использовал - bcmath зовется. Точность относительная, разумеется )
Я сделал иначе: при вычислении вероятностей для первого месте меняем цену:

Код: plaintext
price = ( 1  - P1(x)) * price;

Затем при вычислении вероятностей второго места аналогично вычисляем:

Код: plaintext
1.
2.
3.
P2(x) = price / sum(price);
price = (  1  - ( P2(x) + P1(x) ) ) * price;
P3(x) = price / sum(price);

и т.д.

Погонял эти два алгоритма на разных тестовых данных - величины для вторых мест (которые у меня в первом случае работают верно) совпадают с погрешностью в пределах 2%. Этот алгоритм намного проще и эффективнее, и таблица получается хорошая - у кого на первом месте вероятность большая, на остальных местах падает и в сумме дает сотку, у кого маленькая - растет. Фиг знает, насколько это правомерно, но работает ;)
...
Рейтинг: 0 / 0
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Вычисление вероятностей попадания объекта X на место Y, в зависимости от одного параметра. / 7 сообщений из 7, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]