chatbot icon indicating copy to clipboard operation
chatbot copied to clipboard

Как обучить модель понимать новые факты?

Open GraphGrailAi opened this issue 5 years ago • 5 comments

Крутой бот, точнее это вопросно-ответная система. В процессе тестов нашел нсколько багов системных, например: 1) Вопрос: у тебя есть конфета? понимается моделью как "У меня нет коньков" - ошибка. В данном случае модель должна была ответить "нет информации", как делает в других случаях. Как это исправить?

Вопрос: дай покататься лыжи понимается как "вызвать скорую" - почему так, как исправить?

Поиск по базе фактов показал, что фраза "вызвать скорую находится только в /data/ orders.txt, а различные варианты фраз со словом "лыжи" во многих файлах, не ясно, как исходя из анализа релевантности https://github.com/Koziev/chatbot/blob/master/README.relevance.md получился ответ. Как переобучить модель, отвязать ее от неверного ответа? Как я понимаю, нужно дописать факты в файлы и переобучить сетку? Могли бы указать полный путь, где и что изменять?

(P.S. на самом деле накачивать фактами файлы это ведь тоже самое что на правилах бота делать. Мне кажется правильнее было бы делать несколько классов вопросов, например "из чего сделано -слот-" из на месте -слот- делать анализ семантики на основе скажем НКРЯ http://ruscorpora.ru/corpora-sem.html - тем самым отсекая скажем всю технику от еды. После этого ответ на вопрос про технику можно делать сначала универсальным: "танк сделан из -металла, пушек, гусениц-" а дополнять уже фактами из Википедии распарсенными.)


H:> у тебя есть конфета?
2019-05-03 11:42:18,430 Question to process=у меня есть конфета ?
2019-05-03 11:42:18,868 Best premise is "У меня нет коньков" with relevancy=0.985838135691
2019-05-03 11:42:19,505 model_selector=0

B:> нет
H:> а что у тебя есть?
2019-05-03 11:42:34,456 Question to process=а что у меня есть ?
2019-05-03 11:42:34,887 Best premise is "У меня есть лыжи" with relevancy=0.958263324015
2019-05-03 11:42:34,895 model_selector=1

B:> лыжи
H:> дай покататься лыжи
2019-05-03 11:42:49,643 Closest order is "вызвать скорую" with similarity=0.799867285573
2019-05-03 11:42:49,644 Phrase "дай покататься лыжи" is interpreted as "вызвать скорую"
2019-05-03 11:42:49,644 Process order "вызвать скорую"

B:> Выполняю команду "вызвать скорую"

GraphGrailAi avatar May 03 '19 13:05 GraphGrailAi

Привет, спасибо за сообщение об ошибках. С переобучением чатбота сейчас не особо практично все. Есть ряд предобученных моделей, которые в репозитории лежат в папке tmp. Я их обучаю на больших датасетах, которые в полном виде в репозиторий пока не выкладываю. Поэтому если, например, модель определения синонимичности или релевантности косячит (это как раз случай с лыжами и скорой помощью), то как бы ничего исправить нельзя без полного переобучения.

Все, что сейчас можно сделать для кастомизации - редактировать базу фактов, это те самые файлы premises*.txt, faq2.txt и orders.txt в папке data, типа как тут описано https://kelijah.livejournal.com/254532.html.

Мне кажется правильнее было бы делать несколько классов вопросов, например "из чего сделано -слот-" из на месте -слот- делать анализ семантики на основе скажем НКРЯ

Очень не хотелось бы врукопашную реализовывать семантику в любом виде... Все варианты "семантического анализа", которые я видел, крайне сложны под капотом, хрупкие и требуют очень квалифицированного разработчика, чтобы аккуратно и правильно вносить изменения. Ну те самые "онтоинженеры". А хотелось бы, чтобы бот обучался на простых, интуитивно понятных датасетах, которые любой русскоязычный нейтив с iq>=80 сможет дополнять под свои нужды :) Лучше конечно вообще в unsupervised режиме. Но пока нормальной language acquisition модели у меня нет, то хотя бы и с ручной разметкой там, где нужно. Отсюда и эти примитивные "правила" в https://github.com/Koziev/chatbot/blob/master/data/faq2.txt и т.д.

Koziev avatar May 04 '19 15:05 Koziev

Я поиграл с параметрами: self.min_faq_relevancy = 0.83 и пока как костыль это заставляет бота сказать "нет необходимой информации". Я бы еще подумал в сторону гуглового BERT, мне вот реально непонятно почему файл word2vec такой маленький, в то время как на русвекторс они огромные.

Есть еще пара вопросов: 1)

B:> нет
H:> кто твои мама и папа?
2019-05-08 20:04:32,465 Question to process=кто твои мама и папа ?
2019-05-08 20:04:32,891 Best premise is "У меня нет папы, потому что я - компьютерная программа" with relevancy=0.0051393265165935
2019-05-08 20:04:32,892 Question to process=как тебя зовут
2019-05-08 20:04:33,315 Best premise is "а ты на машине" with relevancy=0.7999146021050917
2019-05-08 20:04:33,385 model_selector=1

B:> не хватает знаний для ответа на вопрос

Вот тут проблема с релевантностью, ответ-то найдет в фактах верно, как-то можно ее поправить?

Файл simple_answering_machine.py https://github.com/Koziev/chatbot/blob/master/PyModels/bot/simple_answering_machine.py 415-431 строки Хотелось бы дописывать к ответу побуждающие реплики, я так понял это в этом месте, но не ясно как этот участок кода работает (после if False видимо код недописан?). Также хочется проверять юзера на повторные вопросы и опять же дописывать ему вопрос типа "зачем повторяешься" - насколько понял это проверка переменной session.conversation_history[-2], а вот в какой класс лучше добавить?

        else:
            # обрабатываем вопрос
            answers = self.build_answers(bot, interlocutor, interpreted_phrase)
            for answer in answers:
                self.say(session, answer)

            # Возможно, кроме ответа на вопрос, надо выдать еще какую-то реплику.
            # Например, для смены темы разговора.
            if len(answers) > 0:
                if False:  #bot.has_scripting():
                    additional_speech = bot.scripting.generate_after_answer(bot,
                                                                            self,
                                                                            interlocutor,
                                                                            interpreted_phrase,
                                                                            answers[-1])
                    if additional_speech is not None:
                        self.say(session, additional_speech)

GraphGrailAi avatar May 08 '19 17:05 GraphGrailAi

Привет, спасибо за замечания по поводу релевантности и вообще идей.

Я бы еще подумал в сторону гуглового BERT BERT к сожалению очень прожорлив при обучении. Даже сильно упрощенная модель (~5 миллионов параметров против штатных 100 млн. или сколько там их) у меня на 1080Ti обучается по 3 суток.

мне вот реально непонятно почему файл word2vec такой маленький, в то время как на русвекторс они огромные.

На самом деле w2v файл большой, больше 2 Гб. Вот чтобы такого монстра не пихать в контейнер, да и вообще не портить себе жизнь ожиданиями загрузки при тестах, я делаю следующее. Беру все слова, которые есть в обучающих датасетах. Затем из полного w2v файлы оставляю только векторы для этих слов. Получается 90 Мб файлик, приятный для тестирования и деплоймента. Вся эта подготовка делается тут https://github.com/Koziev/chatbot/blob/master/PyModels/preparation/prepare_word_embeddings.py.

Вот тут проблема с релевантностью, ответ-то найдет в фактах верно, как-то можно ее поправить?

Да, действительно косячит, надо подумать, как с такими вопросами быть.

Также хочется проверять юзера на повторные вопросы и опять же дописывать ему вопрос типа "зачем повторяешься" - насколько понял это проверка переменной session.conversation_history[-2], а вот в какой класс лучше добавить?

Наверное, проще всего вклиниться перед этой строкой:

            # обрабатываем вопрос
            answers = self.build_answers(bot, interlocutor, interpreted_phrase)

Если встать отладчиком на строку answers = ... после заданного вопроса "Как тебя зовут?", то в структуре interpreted_phrase будет заданный вопрос со сменой лица "Как меня зовут?", а в списке session.conversation_history будет все реплики участников, включая последний заданный вопрос "Как тебя зовут". Каждый элемент этого списка имеет флаг is_bot_phrase - с его помощью можно отфильтровать реплики человека, ну и далее сгенерировать какую-то свою реплику. Метод self.build_answers занимается генерацией ответа и может возвращать несколько ответов (например, для вопроса "Кто летает?"), остается подмешать свою реплику к этим сгенерированным, или вообще не вызывать генерацию - смотря что хочется получить.

Koziev avatar May 10 '19 12:05 Koziev

На самом деле w2v файл большой, больше 2 Гб.

А, ну понятно, что для тестов. А можно же этот большой файл на мэйл или я.диск залить? Я пробовал приделывать стандартный файл с русвекторс, он не подходит почему-то. Дело в том, что вот я когда сам факты добавляю, то в уменьшенной до 90мб модели наверняка окажется, что многих слов из фактов нет и она не может оценивать их близость. А вообще как на опертативную память это влияет, сколько занято? Остальные моменты попробую.

Еще гляньте в сторону https://habr.com/ru/post/440564/ https://openai.com/blog/better-language-models/ и файнтюнинга https://svilentodorov.xyz/blog/gpt-finetune уже есть код, чтобы тюнить под специфику. Применение: все общие вопросы типа: Земля это какая по счету планета? он дополняет до 3

GraphGrailAi avatar May 10 '19 13:05 GraphGrailAi

А можно же этот большой файл на мэйл или я.диск залить? Я пробовал приделывать стандартный файл с русвекторс, он не подходит почему-то.

https://drive.google.com/open?id=1w05QAVU_hoiFXzDg_jG3i9-Dr9DrkQt4

Другие w2v модели, даже если подобрать такую-же размерность вектора (64), точно не подойдут, потому что на этих векторах обучились нейросетки, и они ожидают вполне определенные значения компонентов векторов для слов. Даже если я сейчас переобучу w2v на этом же корпусе, то из-за рандомной инициализации начальных векторов получатся совершенно новые векторы, и нейросетки будут на них лажать.

Еще гляньте в сторону https://habr.com/ru/post/440564/ https://openai.com/blog/better-language-models/ и файнтюнинга https://svilentodorov.xyz/blog/gpt-finetune

Ага, большое спасибо за ссылки, почитаю.

Koziev avatar May 10 '19 14:05 Koziev