2015-12-23 2 views
5

В настоящее время я строю систему, которая требует ранжирования на основе внутреннего действий/оценки. Сам счет может варьироваться от любого места в пределах от 0 до 20000.Logarithmic Scale - Рейтинг в PHP

Мне нужна функция, которую я создаю, чтобы ранжировать пользователей, чтобы вернуть значение между 1-100. Если это невозможно, было бы неплохо вернуть любые результирующие множества более 100 как 100. В настоящее время у меня возникают трудности с созданием логарифмического алгоритма определения баллов.

Я попытался следующие функции:

echo 1 + sqrt(500 + 2000 * $score)/50; 

Однако результаты этого возвращения не изменяются достаточно для более низких значений и экспоненциально возрастают для более высоких.

Пример входных баллов при низкой/средней части шкалы являются:

  • 0,15

Пример входных данных на высоком конце шкалы

  • 236,4
  • 17899,70

Любая помощь будет принята с благодарностью. Застрял на этом несколько дней. Вышеприведенная функция - лучшая попытка, которую я имею до сих пор, однако, как известно, недостаточно низкого уровня между средними и средними результатами и слишком большим количеством высших.

Спасибо,

Daniel

ответ

1

спасибо за помощь. Вот что я получил (благодаря помощи Jake L Price)

Оценка менялась немного после первоначального вопроса (при этом 120 000 были верхним краем шкалы), однако логика алгоритма должна была оставаться одна и та же. Как вы можете видеть ниже, мы использовали log * 10, чтобы получить приемлемое низкое число. Затем умножить это снова на число, которое обеспечивает 120000 имеет верхний уровень 100.

echo $this->rank($score); 

    public function rank($score) 
     { 
      //-- log reg time 
      // 7.143963378055477 being the numberic multiplier to ensure 120,000 has the score of 100. 
      $res = 7.143963378055477 * log($score * 10); 
      return $res; 
     } 

Это теперь возвращается

$scores = [0.15,1,7,12,236.4,1211,17899.70, 120000]; 

    foreach ($scores as $score){ 
     echo "Score: " . $score . ", Rank: " . $this->rank($score) . "</br>"; 
    } 

Выход:

Score: 0.15, Rank: 2.896627883404 
Score: 1, Rank: 16.449583579206 
Score: 7, Rank: 30.351094421044 
Score: 12, Rank: 34.201665683178 
Score: 236.4, Rank: 55.495096060882 
Score: 1211, Rank: 67.166020848577 
Score: 17899.7, Rank: 86.407125230156 
Score: 120000, Rank: 100 
4

Это открытый вопрос и нет четкого ответа с различными компромиссами .. Я не программист PHP, но что-то вроде следующего должно работать.

# THESE PARAMETERS CONTROL THE RANKING ALGORITHM. 
$rescale = 0; 
$spread = 1; 

function rescore ($n) { 
    return log($n) + $rescale; 
} 

function rank ($scores) { 
    return 100/(1 + exp(- $spread * array_sum(array_map("rescore", $scores)))); 
} 

Вы должны выбрать $rescale так, что средний балл rescores на что-то близкое к 0. И играть с $spread, пока вы не будете довольны, насколько ваши результаты распространятся.

Идея состоит в том, что log превращает широкий диапазон баллов в числа в сопоставимом диапазоне, который может быть положительным или отрицательным. Добавьте кучу скомбинированных баллов вместе, и вы получите произвольное действительное число. Затем переместите это в логистическую функцию (см. https://en.wikipedia.org/wiki/Logistic_function), чтобы превратить это в число в желаемом диапазоне.

+0

Привет @btilly - спасибо за ответ. Это решение, я думаю, потребовало бы, чтобы я получил все пользовательские баллы и запускал их через эту функцию каждый раз, когда добавляю нового пользователя? Потому что каждый ранг определяется на основе других из набора. Это означает, что мне также придется обновлять каждый рейтинг пользователей в базе данных каждый раз, когда будет добавлен новый пользователь. Я надеялся, что при статическом пределе 0 для минимума и 20 000 для максимума я мог бы избежать этого. –

+0

@ DanielBenzie Мое понимание вашего вопроса в том, что вы хотели совместить баллы для разных действий над предметами (например, с пользователем) и выплюнуть число в диапазоне 0-100. Но, похоже, вы хотите вместо этого сохранить процентильные ряды для пользователей, каждый из которых имеет баллы? Вы должны искать дерево статистики заказа. Бриф, созданный в BerkeleyDB с набором 'DB_RECNUM', может сделать это, но не в PHP. См. Https://docs.oracle.com/cd/E17275_01/html/api_reference/C/dbcget.html для интерфейса C. (Вы должны получить пару ключ/значение, а затем получить флаг 'DB_GET_RECNO', чтобы получить ранг.) – btilly

1

Попытка внимательно следить за определением в Wikepedia, где «каждая отметка в [логарифмической] шкале - это предыдущая отметка, умноженная на значение», мы устанавливаем value^100 = 20000 и получаем value = 1.104104805. Может ли эта логарифмическая шкала быть реализована с помощью функции, близкой к следующему?

function rank($score){ 
    return log($score,1.104104805); 
} 

Выход:

$scores = [0.15,1,7,12,236.4,1211,17899.70]; 

foreach ($scores as $score){ 
    echo "Score: " . $score . ", Rank: " . rank($score) . "\n"; 
} 

/* 
Score: 0.15, Rank: -19.156079885479 
Score: 1, Rank: 0 
Score: 7, Rank: 19.648736275112 
Score: 12, Rank: 25.091228109202 
Score: 236.4, Rank: 55.187884698844 
Score: 1211, Rank: 71.683855953272 
Score: 17899.7, Rank: 98.879704658993 
*/ 
+0

Привет :) спасибо за ответ. Это на самом деле очень близко к тому, что я закончил! –

Смежные вопросы