Вычисление релевантности пользователя на основе конкретных данных

В настоящее время я пытаюсь создать алгоритм, который будет вычислять relevance a user в другой user на основе определенных бит данных.

К сожалению, мои навыки математики ухудшились после окончания школы почти десять лет назад, и поэтому я очень сильно борюсь с этим. Я нашел алгоритм онлайн, который подталкивает "горячие" сообщения к началу ленты новостей и рисует, что это хорошее место для начала. Это алгоритм/расчет, который я нашел онлайн (в MySQL):

LOG10(ABS(activity) + 1) * SIGN(activity) + (UNIX_TIMESTAMP(created_at) / 300000)

То, что я надеюсь сделать, - это адаптировать приведенную выше концепцию к работе с данными и моделями, которые у меня есть в моем собственном приложении. Рассмотрим этот объект пользователя (обрезанный):

{
    "id": 1
    "first_name": "Joe",
    "last_name": "Bloggs",
    "counts": {
        "connections": 21,
        "mutual_connections": 16
    },
    "mutual_objects": [
        {
            "created_at": "2017-03-26 13:30:47"
        },
        {
            "created_at": "2017-03-26 14:25:32"
        }
    ],
    "last_seen": "2017-03-26 14:25:32",
}

В алгоритме необходимо учитывать три бита соответствующей информации:

  • mutual_connections
  • mutual_objects, но принимая во внимание, что старые объекты не должны повышать значимость как более новых объектов, следовательно, поле created_at.
  • last_seen

Может ли кто-нибудь предложить довольно простой (если это возможно) способ сделать это?

Это была моя идея, но, честно говоря, я понятия не имею, что она делает, поэтому я не могу быть уверен, что это хорошее решение, и я также пропустил last_seen, поскольку не смог найти способ добавить это:

$mutual_date_sum = 0;

foreach ($user->mutual_objects as $mutual_object) {
    $mutual_date_sum =+ strtotime($mutual_object->created_at);
}

$mutual_date_thing = $mutual_date_sum / (300000 * count($user->mutual_objects));

$relevance = log10($user->counts->mutual_connections + 1) + $mutual_date_thing;

Просто, чтобы быть ясным, я не хочу реализовывать какой-то государственный уровень AI, 50 000 строк алгоритма из математического гения. Я просто ищу относительно простое решение, которое сделает трюк на данный момент.

UPDATE

У меня была небольшая игра, и мне удалось построить следующий тест. Похоже, что mutual_objects очень сильно переносит вес в этом конкретном алгоритме, так как я ожидаю увидеть пользователей 4 и 5 выше списка результатов, учитывая их большое количество mutual_connections.

Я не знаю, облегчает ли это изменение/играть, но это, наверное, лучшее, что я могу сделать. Пожалуйста, помогите, если у вас есть предложения: -)

$users = [
    [
        'id' => 1,
        'mutual_connections' => 15,
        'mutual_objects' => [
            [
                'created_at' => '2017-03-26 14:25:32'
            ],
            [
                'created_at' => '2017-03-26 14:25:32'
            ],
            [
                'created_at' => '2017-02-26 14:25:32'
            ],
            [
                'created_at' => '2017-03-15 14:25:32'
            ],
            [
                'created_at' => '2017-01-26 14:25:32'
            ],
            [
                'created_at' => '2017-03-26 14:25:32'
            ],
            [
                'created_at' => '2016-03-26 14:25:32'
            ],
            [
                'created_at' => '2017-03-26 14:25:32'
            ]
        ],
        'last_seen' => '2017-03-01 14:25:32'
    ],
    [
        'id' => 2,
        'mutual_connections' => 2,
        'mutual_objects' => [
            [
                'created_at' => '2016-03-26 14:25:32'
            ],
            [
                'created_at' => '2015-03-26 14:25:32'
            ],
            [
                'created_at' => '2017-02-26 14:25:32'
            ],
            [
                'created_at' => '2017-03-15 14:25:32'
            ],
            [
                'created_at' => '2017-01-26 14:25:32'
            ],
            [
                'created_at' => '2017-03-26 14:25:32'
            ],
            [
                'created_at' => '2016-03-26 14:25:32'
            ],
            [
                'created_at' => '2016-03-26 14:25:32'
            ],
            [
                'created_at' => '2016-03-26 14:25:32'
            ],
            [
                'created_at' => '2017-03-15 14:25:32'
            ],
            [
                'created_at' => '2017-02-26 14:25:32'
            ],
            [
                'created_at' => '2017-03-15 14:25:32'
            ],
            [
                'created_at' => '2017-01-26 14:25:32'
            ],
            [
                'created_at' => '2017-03-12 14:25:32'
            ],
            [
                'created_at' => '2016-03-13 14:25:32'
            ],
            [
                'created_at' => '2017-03-17 14:25:32'
            ]
        ],
        'last_seen' => '2015-03-25 14:25:32'
    ],
    [
        'id' => 3,
        'mutual_connections' => 30,
        'mutual_objects' => [
            [
                'created_at' => '2017-02-26 14:25:32'
            ],
            [
                'created_at' => '2017-03-26 14:25:32'
            ]
        ],
        'last_seen' => '2017-03-25 14:25:32'
    ],
    [
        'id' => 4,
        'mutual_connections' => 107,
        'mutual_objects' => [],
        'last_seen' => '2017-03-26 14:25:32'
    ],
    [
        'id' => 5,
        'mutual_connections' => 500,
        'mutual_objects' => [],
        'last_seen' => '2017-03-26 20:25:32'
    ],
    [
        'id' => 6,
        'mutual_connections' => 5,
        'mutual_objects' => [
            [
                'created_at' => '2017-03-26 20:55:32'
            ],
            [
                'created_at' => '2017-03-25 14:25:32'
            ]
        ],
        'last_seen' => '2017-03-25 14:25:32'
    ]
];

$relevance = [];

foreach ($users as $user) {

    $mutual_date_sum = 0;

    foreach ($user['mutual_objects'] as $bubble) {
        $mutual_date_sum =+ strtotime($bubble['created_at']);
    }

    $mutual_date_thing = empty($mutual_date_sum) ? 1 : $mutual_date_sum / (300000 * count($user['mutual_objects']));

    $relevance[] = [
        'id' => $user['id'],
        'relevance' => log10($user['mutual_connections'] + 1) + $mutual_date_thing
    ];
}

$relevance = collect($relevance)->sortByDesc('relevance');

print_r($relevance->values()->all());

Это выдает:

Array
(
    [0] => Array
        (
            [id] => 3
            [relevance] => 2485.7219150272
        )

    [1] => Array
        (
            [id] => 6
            [relevance] => 2484.8647045837
        )

    [2] => Array
        (
            [id] => 1
            [relevance] => 622.26175831599
        )

    [3] => Array
        (
            [id] => 2
            [relevance] => 310.84394042139
        )

    [4] => Array
        (
            [id] => 5
            [relevance] => 3.6998377258672
        )

    [5] => Array
        (
            [id] => 4
            [relevance] => 3.0334237554869
        )

)

Ответ 1

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

Если вы предпочитаете делать это "вручную"; вы создадите свою собственную модель с конкретными весами для разных факторов. Имейте в виду, что наши мозги обманывают нас очень часто, и то, что вы считаете идеальной моделью, может быть далеко не оптимальным.

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

Сказав это, вот мое предложение:

В конце концов, вам нужен такой список (с 3 пользователями):

A->B: relevance
----------------
User1->User2: 0.59
User1->User3: 0.17
User2->User1: 0.78
User2->User3: 0.63
User3->User1: 0.76
User3->User2: 0.45

1) Для каждого пользователя

1.1) Вычислить и кешировать возраст каждого пользователя "last_seen", в днях, целое округление (пол).

1.2) Хранить максимум (возраст (last_seen)) - просто назовите его просто макс. Это одно значение, а не одно для каждого пользователя. Но вы можете вычислить его только после того, как вы предварительно вычислили возраст каждого пользователя.

1.3) Для каждого пользователя измените сохраненное возрастное значение с результатом (max-age)/max, чтобы получить значение от 0 до 1.

1.4) Вычислить и кэшировать также каждый объект "created_at", в днях.

2) Для каждого пользователя, сравнивая с каждым другим пользователем

2.1) Что касается взаимных связей, подумайте об этом: если A имеет 100 соединений, 10 из них разделены с B, а C имеет 500 соединений, 10 из которых разделены с D, вы действительно принимаете 10 в качестве значения для вычисления в обоих случаях? Я бы взял процент. Для A- > B это будет 10, а для C- > D - 2. И тогда значение /100 должно иметь значение от 0 до 1.

2.2) Выберите максимальный возраст для взаимных объектов, чтобы быть релевантным. Возьмем 365 дней.

2.3) В пользователе A удалите объекты старше 365 дней. Не удаляйте их, просто отфильтровывайте их для этих вычислений.

2.4) Из остальных объектов вычислите процент взаимных объектов с каждым из других пользователей.

2.5) Для каждого из этих других пользователей вычислите средний возраст общих объектов с предыдущего шага. Возьмите максимальный возраст (365), вычтите вычисленное среднее значение и /365, чтобы иметь значение от 0 до 1.

2.6) Получить возрастное значение другого пользователя.

Итак, для каждой комбинации A- > B у вас есть четыре значения от 0 до 1:

  • MC: взаимные соединения A-B
  • MO: взаимные объекты A-B
  • OA: средний возраст объекта A-B
  • BA: возраст B

Теперь вам нужно назначить веса каждому из них, чтобы найти оптимальное решение. Назначьте проценты, которые составляют 100, чтобы облегчить вашу жизнь:

Релевантность = 40 * MC + 30 * MO + 10 * OA + 20 * BA

В этом случае, поскольку OA так связано с MO, вы можете их смешать:

Релевантность = 40 * MC + 20 * MO + 20 * MO * OA + 20 * BA

Я предлагаю запустить эту ночь, каждый день. Существует много способов улучшить и оптимизировать процесс... получайте удовольствие!