По вопросам сотрудничества вы можете связаться с serge dot rogatch на gmail dot com.
.NET: https://github.com/srogatch/ProbQA/tree/master/ProbQA/ProbQANetCore.
Python: https://github.com/srogatch/ProbQA/tree/master/Interop/Python/ProbQAInterop
Вы также можете просмотреть примеры использования Python в исходном коде сайта: https://github.com/srogatch/probqa-web
Приложение вероятностной системы вопросов теперь доступно на веб-сайте (исходный код: https://github.com/srogatch/probqa-web): http://probqa.com/ или http://best-games. .info — интерактивная система рекомендаций для игр. Здесь пользователи могут найти следующую игру, в которую можно поиграть, не зная ее названия или ключевых слов. Пользователям нужно только отвечать на вопросы, и программа выдает лучшие рекомендации для каждого пользователя. Предполагается, что движок, на котором работает веб-сайт, работает аналогично популярной игре Akinator, где пользователь думает о персонаже, а программа задает вопросы, чтобы угадать секретного персонажа пользователя.
В ProbQA нет никакого секрета: пользователь просто не знает точно, чего он хочет. Поэтому программа задает вопросы, чтобы придумать что-то подходящее для пользователя.
Попробовав систему интерактивных рекомендаций, вы можете пройти опрос https://www.surveymonkey.com/r/SMJ2ZRZ.
С точки зрения целей прикладного ИИ, это экспертная система. Точнее, это вероятностная вопросно-ответная система: программа спрашивает, пользователи отвечают. Минимальная цель программы — определить, что нужно пользователю (цель), даже если пользователь не знает о существовании такой вещи/продукта/услуги. Это просто бэкэнд на C++. Остальные должны реализовать интерфейсы для своих нужд. Бэкенд можно применить к чему-то вроде этого http://en.akinator.com/ или для продажи товаров и услуг в некоторых интернет-магазинах (в качестве чат-бота, помогающего пользователям определить, что им нужно, даже если они не могут сформулировать ключевые слова или даже конкретно их желания).
Ниже приведены кривые обучения программы для размера матрицы 5 000 000: это 1000 вопросов, умноженные на 5 вариантов ответа на каждый вопрос, умноженные на 1000 целей. В этом эксперименте мы обучаем программу двоичному поиску: диапазон целей Tj составляет от 0 до 999, и каждый вопрос Qi звучит так: «Как ваше предположение соотносится с Qi?». Варианты ответа: 0 – «Предположение намного ниже, чем Ци», 1 – «Предположение немного ниже, чем Ци», 2 – «Предположение точно равно Ци», 3 – «Предположение немного выше, чем Ци». » и 4 — «Предположение намного выше, чем Ци».
Ось X содержит количество заданных и отвеченных вопросов (до 5 миллионов). На оси Y для каждых 256 тестов подряд указан процент случаев, когда программа правильно включила угаданную цель в число 10 наиболее вероятных целей. Обратите внимание, что тестирование всегда проводится на новых данных: сначала мы выбираем случайное число, затем позволяем программе угадать его, задавая вопросы и получая от нас ответы, а затем либо после того, как программа угадала правильно, либо задала более 100 вопросов (что означает неудачу). , мы обучаем программу, раскрывая ей выбранное нами случайное число.
Судя по данным и диаграмме, программа обучается быстрее и достигает более высокой точности для приоритетных функций, которые отдают больше предпочтения вариантам с более низкой энтропией. Так что, возможно, какая-то экспоненциальная функция приоритета может дать превосходные результаты. Но пока я не знаю, как это реализовать без переполнения. Функция приоритета находится в файле ProbQAProbQAPqaCoreCEEvalQsSubtaskConsider.cpp, который сейчас находится ближе к концу.
В настоящее время в ключевой теории также есть недостаток, который делает программу упрямой (я думаю, что это близко к «переоснащению» термина машинного обучения). После того, как программа по ошибке выбирает какую-то цель как наиболее вероятную, она начинает задавать такие вопросы, которые позволяют ей зафиксировать свою ошибку, а не вопросы, которые позволили бы программе увидеть, что другие цели более вероятны. Хотя это то, что происходит в жизни, технически это ошибка в ключевом алгоритме/теории, лежащей в основе программы.
В предыдущем разделе я описал проблему упрямства программы: убедив себя в том, что какая-то неправильная цель является наиболее вероятной, программа начала задавать вопросы, которые позволяли ей зацикливаться на своей ошибке, вместо того, чтобы узнавать правду. Я думаю, что решил эту проблему, изменив функцию приоритета с основанной только на энтропии на основанную на расстоянии и энтропии. Вместо того, чтобы просто минимизировать энтропию апостериорных вероятностей, теперь он также учитывает евклидово расстояние между априорными и апостериорными векторами вероятностей. Это позволило программе учиться в 20 раз быстрее. Теперь он начинает включаться в топ-10 предполагаемой цели почти в 100% случаев после примерно 125 000 заданных и отвеченных вопросов (для матрицы 1000 вопросов, умноженных на 5 ответов, умноженных на 1000 целей). См. график точности.
После вышеупомянутого первоначального обучения положительный результат достигается в среднем по 4,3 вопросам, заданным (программой) и ответившим (пользователем). См. график ниже.
Так что это вполне конкурентоспособно по сравнению с алгоритмом бинарного поиска, запрограммированным человеком. Чтобы сузить диапазон поиска с 1000 до 10 целей, алгоритм бинарного поиска, запрограммированный человеком, потребует в среднем 3,32 шага (это логарифм по основанию 4 от 100, потому что у нас есть 5 вариантов ответа, один из которых представляет собой просто строгое равенство).
Однако алгоритм двоичного поиска, запрограммированный человеком, не терпит ошибок и не оценивает цели по вероятности того, что они искомые. И, конечно, он не учится по ходу дела. А вероятностная вопросно-ответная система это делает.
Более того, я думаю, что есть возможности для улучшения функции приоритета. В настоящее время я использую полиномиальный приоритет: pow(distance, 12) / pow(nExpectedTargets, 6), который эмпирически показал лучшие результаты в моих экспериментах с ограниченным количеством функций приоритета. Тем не менее я думаю, что еще лучших результатов можно добиться с помощью экспоненциальной функции приоритета. Теперь давайте посмотрим, лучше ли придумать и опробовать некоторые экспоненциальные функции сейчас или приступить к (менее интересным) инженерным задачам, таким как сохранение и загрузка базы знаний в файл и из файла и т. д.
Недавно завершилась реализация загрузки и сохранения базы знаний. Обучение и прогнозирование были завершены больше месяца назад, а после этого были протестированы/исправлены и настроены.
Что еще не закончено, так это изменение размера КБ. После создания базы знаний изменить количество вариантов ответа будет невозможно. Однако мне еще предстоит осуществить изменение количества вопросов и целей.
Вы можете попробовать интегрировать движок в свои системы.
Для компиляции вам понадобится MSVS2017 v15.4.2 или выше. Внешняя зависимость — gtest: https://github.com/google/googletest (только если вы хотите запускать тесты или слишком сильно не любите ошибки компиляции в несвязанных проектах).
Ранее я публиковал результаты экспериментов для топ-10 целей (где цель считается угаданной правильно, если она входит в число 10 наиболее вероятных целей). Вот результат для более сложной задачи - угадывания целей среди топ-1, т.е. ее необходимо выбрать как единственную наиболее вероятную цель. После многих экспериментов и настроек в настоящее время кривая обучения точности для изучения алгоритма двоичного поиска выглядит следующим образом:
Таким образом, для КБ размером 1000 вопросов по 5 вариантов ответа по 1000 целей точность достигает 100% после примерно 4,5 миллионов ответов на вопросы, а затем также остается на уровне 100%.
Я анализирую утечки памяти с помощью Deleaker: https://www.deleaker.com/