Оригинальная статья Tencent DeepOcean:сделай pro.IO/NLP_porn 2 порно…
Умных роботов в жизни можно увидеть везде: говорящая сири в айфоне, альфаГо, умеющий играть в шахматы, озорной и милый Microsoft Сяобин... Все они обладают определенным интеллектом и могут взаимодействовать с людьми. Эти умные роботы очень волшебные и кажутся очень далекими от нас, но на самом деле, пока мы двигаем руками, мы можем построить своего собственного разумного робота.
Эта статья научит вас создавать с нуля умственно отсталого, а не «умного чатбота».
Чтобы создать чат-бота, вам сначала нужно понять некоторые связанные концепции — обработку естественного языка (NLP), которая представляет собой науку, объединяющую лингвистику, информатику и математику, и изучает, как заставить компьютеры «понимать» человеческий язык. Конечно, он также содержит множество разделов: чтение текста, распознавание речи, синтаксический анализ, генерация естественного языка, диалог человека с компьютером, поиск информации, извлечение информации, корректура текста, классификация текста, автоматическое суммирование, машинный перевод, вывод текста и так далее. .
Когда вы видите здесь друзей, не пугайтесь их. Поскольку эта статья называется «Создание чат-бота для умственно отсталых» с нуля, не беда, если вы этого не понимаете! Следуйте по моим стопам шаг за шагом.
0x1 Основная концепция
Основные принципы, задействованные здесь, могут быть пропущены теми, кому это не интересно, и не повлияют на последующую реализацию кода.
01|Нейронная сеть
Нижний уровень искусственного интеллекта — это «нейронная сеть», на которой основаны многие сложные приложения (такие как распознавание образов, автоматическое управление) и продвинутые модели (такие как глубокое обучение). Изучение искусственного интеллекта должно начинаться с него.
Итак, вопрос в том, что такое нейронная сеть? Проще говоря, нейронная сеть имитирует человеческий мозг.нейронная сеть, чтобы компьютер понял "мышление". Здесь не будут повторяться конкретные понятия, а в Интернете есть много простых и понятных объяснений.
В этой статье используетсяРекуррентная нейронная сеть (RNN), давайте рассмотрим один из самых простыхБазовая рекуррентная нейронная сеть:
Хотя изображение выглядит абстрактно, на самом деле его очень легко понять. х, о, свектор, х представляетвходной слойЗначение , o представляетвыходной слойЗначение сскрытый слой(узлов здесь на самом деле много); U, Vвесовая матрица, U означаетвходной слойприбытьскрытый слойизвесовая матрица, а V означаетскрытый слойприбытьвыходной слойизвесовая матрица. Так что же такое W? фактическиРекуррентная нейронная сетьизскрытый слойВеличина s определяется не только x, U, но и последнимскрытый слойЗначение s и W - это время последнего скрытого слоя до этого времени.весовая матрица, разверните его следующим образом:
Это делает логику намного понятнее, и это простая рекуррентная нейронная сеть. А наша умственная отсталость, это не "умный чатбот", это использованиеРекуррентная нейронная сеть, основанный на лексическом анализе и синтаксическом анализе естественного языка, непрерывном обучающем корпусе иСемантический анализВ него внесены дополнения и улучшения.
02|Структура глубокого обучения
Подходит дляRNNСуществует множество фреймворков глубокого обучения, чат-бот в этой статье основан на открытом исходном коде Google.Tensorflow, из ГайхабаGithubКоличество пусков можно увидеть,TensorflowЭто чрезвычайно популярная среда глубокого обучения, которая может легко выполнять распределенные вычисления на процессоре/графическом процессоре.Ниже перечислены характеристики некоторых современных основных сред глубокого обучения.Вы можете выбрать структуру для исследований в зависимости от ваших интересов:
03|модель seq2seq
Как следует из названия, модель seq2seq подобна модели перевода, входные данные представляют собой последовательность (например, английское предложение), а выходные данные также представляют собой последовательность (например, французский перевод, соответствующий английскому предложению). Наиболее важным аспектом этой структуры является то, что длины входных и выходных последовательностей являются переменными.
Например:
В машине разговора: ввод (привет) -> вывод (привет).
На входе 1 английское слово, на выходе 2 китайских символа. Мы задаем (вводим) вопрос, а машина автоматически генерирует (выводит) ответ. Вход и выход здесь, очевидно, представляют собой последовательности неопределенной длины.
Возьмем более длинный пример:
Я научил маленького желтого цыпленка говорить: «О чем ты мечтаешь днем?» Ответ был: «О, хахаха, не беспокойся об этом».
Step1:Применить двухсторонний алгоритм максимального соответствия для сегментации слов: результат двухсторонней сегментации слов, вперед «Светлый день, ах, что делать, сладкий сон, а»; обратно «Светлый день, ах, что делать, сладкий сон, ах». Прямое и обратное одно и то же, поэтому нет необходимости иметь дело с двусмысленностью. Предпочтение отдается длинным словам, «широкий день» и «что делать».
Sшаг 2:Возьмем в качестве примера «большой день», предположим, что хеш-функцией является f(), и зададим f (большой день), чтобы он указывал на первую запись хэш-слова [big, 11, P]. Следовательно, запись указывает на «индекс из 3 слов», а затем указывает на соответствующий «словарь».
Step3:Вставьте структуру в конец очереди. В теле есть поле Ans, а указатель в поле указывает на «О, хахаха, не беспокойтесь об этом».
Это основной принцип seq2seq, у нас есть принцип и технология, следующий шаг — реализовать его!
0x2 Подготовка корпуса
Разобравшись с некоторыми предпосылками, не будем много говорить, а перейдем непосредственно к созданиюУмный чат-ботсцена. Во-первых, нам нужно подготовить соответствующий учебный корпус.
01|Организация
Корпус для этого тренинга загружен с Github (китайский и английский корпуса Github для диалоговой системы: https://github.com/candlewill/Dialog_Corpus). Мы загружаем xiaohuangji50w_fenciA.conv (Xiaohuangji corpus) для нашего обучения.
Когда мы открываем его после загрузки, корпус выглядит так:
Хотя мы можем понять текст и диалог здесь, что, черт возьми, эти Е, М, /? На самом деле, по картинке легко понять,Mозначает это предложение, иEОн представляет собой начало и конец разговора.
После того, как мы получим этот корпус, мы используем код, чтобы разделить его на две категории «Question.txt» и «Answer.txt» в соответствии с вопросом/ответом:
1import горячий
2importсистема
3def prepare(num_dialogs=50000):
4 withоткрыть("xhj.conv")asфопен:
5 # Заменить E, M и т. д.
6reg = перекомпилировать ("EnM (.*?)nM (.*?)n")
7match_dialogs = re.findall(reg, fopen.read())
8 # Используйте диалоги 5W в качестве учебного корпуса
9 ifnum_dialogs >= len(match_dialogs):
10диалоги = match_dialogs
11 else:
12диалоги = match_dialogs[:num_dialogs]
13вопросы = []
14ответы = []
15 forque, ansinдиалоги:
16вопросы .append(que)
17ответы.добавлять(ответы)
18 # Сохраняем в каталог data/folder
19сохранить(вопросы,"data/Question.txt")
20сохранить(ответы,"data/Answer.txt")
21def save(диалоги, файл):
22 withоткрыть файл,"w")asфопен:
23fopen.write("n".join(dialogs))
Наконец, мы получаем 5W вопросов и данные ответов:
02|Векторное картографирование
В этот момент вы можете спросить, соответствует ли этот «умный» чат-бот вопросам, которые мы вводим?Question.txtвнутри проблемы, а затем изAnswer.txtНайти соответствующий ответ на вывод?
Конечно, это не так просто, по сути, чат-бот генерирует новый ответ, исходя из контекста вопроса, вместо того, чтобы вынимать данные о соответствующем правильном ответе из базы данных.
Так откуда же машина знает, что отвечать?Вот схематическая диаграмма seq2seq от Google:
Проще говоря: каждое введенное нами предложение будет разделено на слова и оценено машиной; эти слова служатвходной слойвектор, свесовая матрицапосле расчетаскрытый слой,скрытый слойЗатем выходной вектор объединяется свесовая матрицаВыполните вычисления, чтобы получить окончательный вектор. Когда мы сопоставляем этот вектор с библиотекой векторов слов, мы получаем желаемый результат.
Это относительно просто реализовать в коде, потому что сложная базовая логика управляетсяTensorflowЭто сделано за нас, давайте приведем глоссарий к окончательному виду:
1def gen_vocabulary_file(input_file, output_file):
2 vocabulary = {}
3 with open(input_file) as f:
4 counter = 0
5 for line in f:
6 counter += 1
7 tokens = [word for word in line.strip()]
8 for word in tokens:
9 # 过滤非中文 文字
10 if u'u4e00' <= word <= u'u9fff':
11 if word in vocabulary:
12 vocabulary[word] += 1
13 else:
14 vocabulary[word] = 1
15 vocabulary_list = START_VOCABULART + sorted(vocabulary, key=vocabulary.get, reverse=True)
16 # 取前3500个常用汉字,vocabulary_size = 3500
17 if len(vocabulary_list) > vocabulary_size:
18 vocabulary_list = vocabulary_list[:vocabulary_size]
19 print(input_file + " 词汇表大小:", len(vocabulary_list))
20 with open(output_file, "w") as ff:
21 for word in vocabulary_list:
22 ff.write(word + "n")
23 ff.close
0x3 начать обучение
01|Обучение
После того, как наш корпус готов, мы можем начать мое обучение.На самом деле, само обучение очень просто.Ядро состоит в том, чтобы вызвать Seq2SeqModel Tensorflow для непрерывного выполнения циклического обучения. Ниже приведен основной код и настройки параметров обучения:
1# 源输入词表的大小
2vocabulary_encode_size = 3500
3# 目标输出词表的大小
4vocabulary_decode_size = 3500
5#一种有效处理不同长度的句子的方法
6buckets = [(5, 10), (10, 15), (20, 25), (40, 50)]
7# 每层单元数目
8layer_size = 256
9# 网络的层数。
10num_layers = 3
11# 训练时的批处理大小
12batch_size = 64
13# max_gradient_norm:表示梯度将被最大限度地削减到这个规范
14# learning_rate: 初始的学习率
15# learning_rate_decay_factor: 学习率衰减因子
16# forward_only: false意味着在解码器端,使用decoder_inputs作为输入。例如decoder_inputs 是‘GO, W, X, Y, Z ’,正确的输出应该是’W, X, Y, Z, EOS’。假设第一个时刻的输出不是’W’,在第二个时刻也要使用’W’作为输入。当设为true时,只使用decoder_inputs的第一个时刻的输入,即’GO’,以及解码器的在每一时刻的真实输出作为下一时刻的输入。
17model = seq2seq_model.Seq2SeqModel(source_vocab_size=vocabulary_encode_size, target_vocab_size=vocabulary_decode_size,buckets=buckets, size=layer_size, num_layers=num_layers, max_gradient_norm= 5.0,batch_size=batch_size, learning_rate=0.5, learning_rate_decay_factor=0.97, forward_only=False)
18
19config = tf.ConfigProto()
20config.gpu_options.allocator_type = 'BFC' # 防止 out of memory
21
22with tf.Session(config=config) as sess:
23 # 恢复前一次训练
24 ckpt = tf.train.get_checkpoint_state('.')
25 if ckpt != None:
26 print(ckpt.model_checkpoint_path)
27 model.saver.restore(sess, ckpt.model_checkpoint_path)
28 else:
29 sess.run(tf.global_variables_initializer())
30
31 train_set = read_data(train_encode_vec, train_decode_vec)
32 test_set = read_data(test_encode_vec, test_decode_vec)
33
34 train_bucket_sizes = [len(train_set[b]) for b in range(len(buckets))]
35 train_total_size = float(sum(train_bucket_sizes))
36 train_buckets_scale = [sum(train_bucket_sizes[:i + 1]) / train_total_size for i in range(len(train_bucket_sizes))]
37
38 loss = 0.0
39 total_step = 0
40 previous_losses = []
41 # 一直训练,每过一段时间保存一次模型
42 while True:
43 random_number_01 = np.random.random_sample()
44 bucket_id = min([i for i in range(len(train_buckets_scale)) if train_buckets_scale[i] > random_number_01])
45
46 encoder_inputs, decoder_inputs, target_weights = model.get_batch(train_set, bucket_id)
47 _, step_loss, _ = model.step(sess, encoder_inputs, decoder_inputs, target_weights, bucket_id, False)
48
49 loss += step_loss / 500
50 total_step += 1
51
52 print(total_step)
53 if total_step % 500 == 0:
54 print(model.global_step.eval(), model.learning_rate.eval(), loss)
55
56 # 如果模型没有得到提升,减小learning rate
57 if len(previous_losses) > 2 and loss > max(previous_losses[-3:]):
58 sess.run(model.learning_rate_decay_op)
59 previous_losses.append(loss)
60 # 保存模型
61 checkpoint_path = "chatbot_seq2seq.ckpt"
62 model.saver.save(sess, checkpoint_path, global_step=model.global_step)
63 loss = 0.0
64 # 使用测试数据评估模型
65 for bucket_id in range(len(buckets)):
66 if len(test_set[bucket_id]) == 0:
67 continue
68 encoder_inputs, decoder_inputs, target_weights = model.get_batch(test_set, bucket_id)
69 _, eval_loss, _ = model.step(sess, encoder_inputs, decoder_inputs, target_weights, bucket_id, True)
70 eval_ppx = math.exp(eval_loss) if eval_loss < 300 else float('inf')
71 print(bucket_id, eval_ppx)
02|Актуальный эффект вопросов и ответов
Если наша модель тренировалась, как машина узнает, когда прекратить тренировку? Каков порог прекращения тренировки? Здесь мы вводим метрику оценки языковой модели — недоумение.
① Что такое недоумение:
PPL — это индикатор, используемый в области обработки естественного языка (NLP) для измерения качества языковых моделей. Он в основном оценивает вероятность появления предложения по каждому слову и использует длину предложения в качестве нормализации, формула такова:
S дляsentence, N — длина предложения, а p(wi) — вероятность i-го слова. Первое слово — это p(w1|w0), а w0 — это START, что означает начало предложения и является заполнителем.
Эту формулу можно понимать таким образом: чем меньше PPL, тем больше p(wi) и тем выше вероятность появления ожидаемого нами предложения.
Другие говорят, что о недоумении можно думать как о среднем факторе ветвления, то есть о том, сколько вариантов доступно при предсказании следующего слова. Когда другие сообщили, что PPL модели упал до 90, можно интуитивно понять, что когда модель генерирует предложение, есть 90 разумных вариантов для следующего слова.Чем меньше необязательных слов, тем точнее модель. Это также объясняет, почему чем меньше PPL, тем лучше модель.
Для нашей тренировки Недоумение последних нескольких раз выглядит следующим образом:
На момент публикации эта модель обучалась 27 часов, и ееС недоумением еще трудно сойтись,Так что обучение модели действительно требует некоторого терпения. Эта скорость будет значительно улучшена, если возможны условия для использования графических процессоров для обучения.
Мы использовали текущую модель для обсуждения и обнаружили, что она начала обретать форму:
На этом наш «умный чат-бот» готов! Но нетрудно заметить, что этот робот все еще тупой, и многие задачи неверны, поэтому мы также называем его «умственно отсталым роботом».
0x4 Эпилог
Пока что мы обучили робота, отвечающего на вопросы, с нуля, хотя он все еще немного «умственно отсталый» и не понимает больше словарного запаса, в целом процесс пройден и имеет определенный эффект. Последующая работа заключается в постоянном его совершенствовании.алгоритм,параметриКорпус. Корпус является особенно важной частью, которая, вероятно, займет50%-70%Поскольку в этой статье используется корпус, обработанный в Интернете, это экономит много времени. На самом деле большая часть времени разработчика уходит на препроцессинг корпуса:Очистка данных,Причастие,маркировка частями речи,удалить стоп-словаи Т. Д.
В будущем у меня будет возможность поделиться с вами предварительной обработкой корпуса. Вот милый QR-код, не забудьте обратить внимание~
Связанная литература и ссылки:
Начните с машинного обучения(HTTP://woowoo.cn blog.com/subсознательный/afraid/4107357.HTML)
Реализация нейронных сетей с помощью Python(HTTP://woowoo.wild ml.com/2015/09/implementing-ah-neural-network-from-scratch/)
Рекуррентная нейронная сеть(https://onlytribe.com/Hanbingsu/note/541458)
Метрики оценки языковой модели(HTTPS://blog.CSDN.net/index20001/article/details/78884646)
Tensorflow(https://github.com/google/seq2seq)
Источник: общедоступный аккаунт WeChat: Tencent DeepOcean