手把手教你用Python构建自己的「王二狗」
题图 | 智能二狗聊天机器人
导读
在人手N部智能手机的时代,我们对聊天机器人早已不陌生。这两年很火的游戏群聊天机器人「王二狗」更是用它的机智幽默征服了很多人。
今天,我们将手把手教你用Python从头开始创建一个聊天机器人,这种机器人能够理解用户的话,并给出适当的回应。闲话不多说,让我们开始从头开始做出自己的「王二狗」吧!
作者:Shivashish Thkaur
编译:刘文元
预 备
需要使用开源人工神经网络库Keras、自然语言处理工具NLTK和其他一些有用的库。运行以下命令以确保已安装所有的库:
pip install tensorflow keras pickle nltk
聊天机器人是如何工作的?
聊天机器人都属于NLP(自然语言处理)范畴。NPL包括两方面:
NLU(自然语言理解):机器理解人类语言的能力。
NLG(自然语言生成):机器生成类似于人类书面句子的文本的能力。
当我们向聊天机器人提问:“嘿,今天有什么新闻?”
聊天机器人会将我们的句子分解为两部分:意图和限定。这句话的意图可能是“获取新闻”,因为它意在说明用户想要执行的操作。而限定则指明了“意图”的具体细节,也就是“今天”。
项目文件结构
项目完成后,将会留下以下所有文件。让我们快速浏览一下,它们会让你了解这个项目是怎么实施的。
Train_chatbot.py——在这个文件里,我们将构建和训练深度学习模型,该模型可以分类和识别用户对聊天机器人的要求。
Gui_Chatbot.py——这个文件是用来构建图形用户界面、与聊天机器人聊天的。
Intents.json——这个意图文件有我们即将用于训练模型的所有数据,它包含一批标签及其相应的模式和响应。
Chatbot_model.h5——这是一个分层数据格式文件,其中存储了训练模型的权重和架构。
Classes.pkl——pickle文件可用于存储所有的标签名,以便对我们预测消息进行分类。
Words.pkl——这个文件包含模型的词汇表中所有的特有词语(unique words)。
可以在这里下载源代码和数据集↓
https://drive.google.com/drive/folders/1r6MrrdE8V0bWBxndGfJxJ4Om62dJ2OMP
开始构建自己的聊天机器人吧
我们通过5个步骤简化这个构建过程。
步骤1. 导入库并加载数据
创建一个新的Python文件并将其命名为train_chatbot,然后导入所有必需的模块。之后,我们将在Python程序中读取JSON数据文件。
Python
1import numpy as np2from keras.models import Sequential3from keras.layers import Dense, Activation, Dropout4from keras.optimizers import SGD5import random67import nltk8from nltk.stem import WordNetLemmatizer9lemmatizer = WordNetLemmatizer()
10import json
11import pickle
12
13intents_file = open('intents.json').read()
14intents = json.loads(intents_file)
步骤2. 预处理数据
该模型不能读取原始数据,它必须经过大量的预处理才能让机器轻松地理解。文本数据有许多可用的预处理技术。一种技术叫令牌化(tokenizing),我们用它把句子分解成单词。
通过观察意图文件(intents file),可以看到每个标签都包含一个模式和响应的列表。把每个模式做令牌化处理,并将单词添加到列表中。此外,我们还创建了一个类别和文档列表,以添加跟模式相关的所有意图。
Python
1words=[]2classes = []3documents = []4ignore_letters = ['!', '?', ',', '.']56for intent in intents['intents']:7 for pattern in intent['patterns']:8 #tokenize each word9 word = nltk.word_tokenize(pattern)
10 words.extend(word)
11 #add documents in the corpus
12 documents.append((word, intent['tag']))
13 # add to our classes list
14 if intent['tag'] not in classes:
15 classes.append(intent['tag'])
16
17print(documents)
还有一种技术是词形还原(lemmatization)。可以将单词转换成词根(lemma)形式,这样就可以减少所有的标准词,例如单词play、playing、plays、played等都能用play替换。如此一来,就能减少词汇表中的总单词数了。所以,我们现在对每个单词进行词形还原并删除重复的单词。
Python
1# lemmaztize and lower each word and remove duplicates2words = [lemmatizer.lemmatize(w.lower()) for w in words if w not in ignore_letters]3words = sorted(list(set(words)))4# sort classes5classes = sorted(list(set(classes)))6# documents = combination between patterns and intents7print (len(documents), "documents")8# classes = intents9print (len(classes), "classes", classes)
10# words = all words, vocabulary
11print (len(words), "unique lemmatized words", words)
12
13pickle.dump(words,open('words.pkl','wb'))
14pickle.dump(classes,open('classes.pkl','wb'))
最后,单词包含了项目词汇表、类别包含了要分类的全部限定。为将Python对象保存在一个文件里,我们用pickle.dump()方法。
步骤3. 创建训练和测试数据
为了训练模型,我们将没种输入模式转换成数字。首先,对模式的每个单词进行词形还原,并创建一个0列表,其长度与单词总数相同的。将只对那些在模式中包含该词的索引设置为1。同样地,通过为模式所属类输入设置1来创建输出。
Python
1# create the training data2training = []3# create empty array for the output4output_empty = [0] * len(classes)5# training set, bag of words for every sentence6for doc in documents:7 # initializing bag of words8 bag = []9 # list of tokenized words for the pattern
10 word_patterns = doc[0]
11 # lemmatize each word - create base word, in attempt to represent related words
12 word_patterns = [lemmatizer.lemmatize(word.lower()) for word in word_patterns]
13 # create the bag of words array with 1, if word is found in current pattern
14 for word in words:
15 bag.append(1) if word in word_patterns else bag.append(0)
16
17 # output is a '0' for each tag and '1' for current tag (for each pattern)
18 output_row = list(output_empty)
19 output_row[classes.index(doc[1])] = 1
20 training.append([bag, output_row])
21# shuffle the features and make numpy array
22random.shuffle(training)
23training = np.array(training)
24# create training and testing lists. X - patterns, Y - intents
25train_x = list(training[:,0])
26train_y = list(training[:,1])
27print("Training data is created")
步骤4. 训练模型
该模型的架构将是一个由3个致密层组成的神经网络。第一层有128个神经元,第二层有64个神经元,最后一层的神经元数量与“类”的数量相同。引入丢弃层(drop out layers)是为了减少模型的过度拟合。我们使用SGD优化器并拟合数据来开始模型的训练。在完成了200个epoch的训练后,使用Keras model.save(“chatbot_model.h5”)保存训练好的模型。
Python
1# deep neural networds model2model = Sequential()3model.add(Dense(128, input_shape=(len(train_x[0]),), activation='relu'))4model.add(Dropout(0.5))5model.add(Dense(64, activation='relu'))6model.add(Dropout(0.5))7model.add(Dense(len(train_y[0]), activation='softmax'))89# Compiling model. SGD with Nesterov accelerated gradient gives good results for this model
10sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
11model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
12
13#Training and saving the model
14hist = model.fit(np.array(train_x), np.array(train_y), epochs=200, batch_size=5, verbose=1)
15model.save('chatbot_model.h5', hist)
16
17print("model is created")
步骤5. 与聊天机器人交互
至此,我们的模型已经可以聊天了,所以现在让我们在一个新文件中为聊天机器人创建一个漂亮的图形用户界面。可以讲该文件命名为gui_chatbot.py
在GUI文件中,我们使用Tkinter模块来构建桌面应用程序的结构,然后我们将捕获用户的消息,并再次做一些预处理,然后将信息输入我们训练好的模型。
然后,该模型将能预测用户消息的标签,我们从intents文件的响应列表中随机选择响应。
下面是GUI文件的完整源代码:
Python
1import nltk2from nltk.stem import WordNetLemmatizer3lemmatizer = WordNetLemmatizer()4import pickle5import numpy as np67from keras.models import load_model8model = load_model('chatbot_model.h5')9import json10import random11intents = json.loads(open('intents.json').read())12words = pickle.load(open('words.pkl','rb'))13classes = pickle.load(open('classes.pkl','rb'))1415def clean_up_sentence(sentence):16 # tokenize the pattern - splitting words into array17 sentence_words = nltk.word_tokenize(sentence)18 # stemming every word - reducing to base form19 sentence_words = [lemmatizer.lemmatize(word.lower()) for word in sentence_words]20 return sentence_words21# return bag of words array: 0 or 1 for words that exist in sentence2223def bag_of_words(sentence, words, show_details=True):24 # tokenizing patterns25 sentence_words = clean_up_sentence(sentence)26 # bag of words - vocabulary matrix27 bag = [0]*len(words) 28 for s in sentence_words:29 for i,word in enumerate(words):30 if word == s: 31 # assign 1 if current word is in the vocabulary position32 bag[i] = 133 if show_details:34 print ("found in bag: %s" % word)35 return(np.array(bag))3637def predict_class(sentence):38 # filter below threshold predictions39 p = bag_of_words(sentence, words,show_details=False)40 res = model.predict(np.array([p]))[0]41 ERROR_THRESHOLD = 0.2542 results = [[i,r] for i,r in enumerate(res) if r>ERROR_THRESHOLD]43 # sorting strength probability44 results.sort(key=lambda x: x[1], reverse=True)45 return_list = []46 for r in results:47 return_list.append({"intent": classes[r[0]], "probability": str(r[1])})48 return return_list4950def getResponse(ints, intents_json):51 tag = ints[0]['intent']52 list_of_intents = intents_json['intents']53 for i in list_of_intents:54 if(i['tag']== tag):55 result = random.choice(i['responses'])56 break57 return result5859#Creating tkinter GUI60import tkinter61from tkinter import *6263def send():64 msg = EntryBox.get("1.0",'end-1c').strip()65 EntryBox.delete("0.0",END)6667 if msg != '':68 ChatBox.config(state=NORMAL)69 ChatBox.insert(END, "You: " + msg + '\n\n')70 ChatBox.config(foreground="#446665", font=("Verdana", 12 )) 7172 ints = predict_class(msg)73 res = getResponse(ints, intents)7475 ChatBox.insert(END, "Bot: " + res + '\n\n') 7677 ChatBox.config(state=DISABLED)78 ChatBox.yview(END)7980root = Tk()81root.title("Chatbot")82root.geometry("400x500")83root.resizable(width=FALSE, height=FALSE)8485#Create Chat window86ChatBox = Text(root, bd=0, bg="white", height="8", width="50", font="Arial",)8788ChatBox.config(state=DISABLED)8990#Bind scrollbar to Chat window91scrollbar = Scrollbar(root, command=ChatBox.yview, cursor="heart")92ChatBox['yscrollcommand'] = scrollbar.set9394#Create Button to send message95SendButton = Button(root, font=("Verdana",12,'bold'), text="Send", width="12", height=5,96 bd=0, bg="#f9a602", activebackground="#3c9d9b",fg='#000000',97 command= send )9899#Create the box to enter message
100EntryBox = Text(root, bd=0, bg="white",width="29", height="5", font="Arial")
101#EntryBox.bind("<Return>", send)
102
103#Place all components on the screen
104scrollbar.place(x=376,y=6, height=386)
105ChatBox.place(x=6,y=6, height=386, width=370)
106EntryBox.place(x=128, y=401, height=90, width=265)
107SendButton.place(x=6, y=401, height=90)
108
109root.mainloop()
最后:运行聊天机器人
现在我们有两个单独的文件,其中一个是train_chatbot.py,我们先用它来训练模型。
python train_chatbot.py
本文编译自:
https://dzone.com/articles/python-chatbot-project-build-your-first-python-pro
扩展阅读——《Python深度学习》
简介:本书由Keras之父、现任Google人工智能研究员的弗朗索瓦•肖莱(François Chollet)执笔,详尽介绍了用Python和Keras进行深度学习的探索实践,包括计算机视觉、自然语言处理、产生式模型等应用。书中包含30多个代码示例,步骤讲解详细透彻。由于本书立足于人工智能的可达性和大众化,读者无须具备机器学习相关背景知识即可展开阅读。在学习完本书后,读者将具备搭建自己的深度学习环境、建立图像识别模型、生成图像和文字等能力。
手把手教你用Python构建自己的「王二狗」相关推荐
- 利用python编写祝福_手把手|教你用Python换个姿势,送狗年祝福语
春节既是一个阖家团圆的节日,也是一个集中问候亲朋好友.了解近况的机会.但是也有很多人过年也不能聚在一起,所以就会会选择发短信这一方式来表达自己的祝福.其中大多人都是复制转发,让人一眼就看穿,显得自己在 ...
- 独家 | 手把手教你用Python构建你的第一个多标签图像分类模型(附案例)
翻译:吴金笛 校对:郑滋 本文约4600字,建议阅读12分钟. 本文明确了多标签图像分类的概念,并讲解了如何构建多标签图像分类模型. 介绍 你正在处理图像数据吗?我们可以使用计算机视觉算法来做很多事情 ...
- python如何训练模型生产_手把手教你用Python构建你的第一个多标签图像分类模型(附案例)...
你正在处理图像数据吗?我们可以使用计算机视觉算法来做很多事情: 对象检测 图像分割 图像翻译 对象跟踪(实时),还有更多-- 这让我思考--如果一个图像中有多个对象类别,我们该怎么办?制作一个图像分类 ...
- 手把手教你用Python构建你的第一个多标签图像分类模型(附案例)
原文链接: https://www.analyticsvidhya.com/blog/2019/04/build-first-multi-label-image-classification-mode ...
- python图片分类技术介绍_手把手教你用Python构建你的第一个多标签图像分类模型(附案例)!...
介绍 你正在处理图像数据吗?我们可以使用计算机视觉算法来做很多事情:对象检测 图像分割 图像翻译 对象跟踪(实时),还有更多-- 这让我思考--如果一个图像中有多个对象类别,我们该怎么办?制作一个图像 ...
- python图像分类_手把手教你用Python构建你的第一个多标签图像分类模型(附案例)...
介绍 你正在处理图像数据吗?我们可以使用计算机视觉算法来做很多事情:对象检测 图像分割 图像翻译 对象跟踪(实时),还有更多-- 这让我思考--如果一个图像中有多个对象类别,我们该怎么办?制作一个图像 ...
- 使用key 发smtp.sendgrid.net_手把手教你使用 iOS 13 效率神器 「快捷指令」
我写的小应用,几乎每天都会用到它们 比如这个,点击一下就可以知道我和女朋友在一起多少天了! 第二个小应用大大的节省了我的时间--是因为我每两天都要给女朋友发一封邮件,里面包含了一章<道德经> ...
- python编程例子 输入 输出-推荐 :手把手教你用Python创建简单的神经网络(附代码)...
原标题:推荐 :手把手教你用Python创建简单的神经网络(附代码) 作者:Michael J.Garbade:翻译:陈之炎:校对:丁楠雅 本文共2000字,9分钟. 本文将为你演示如何创建一个神经网 ...
- python代码示例图形-纯干货:手把手教你用Python做数据可视化(附代码)
原标题:纯干货:手把手教你用Python做数据可视化(附代码) 导读:制作提供信息的可视化(有时称为绘图)是数据分析中的最重要任务之一.可视化可能是探索过程的一部分,例如,帮助识别异常值或所需的数据转 ...
最新文章
- php get memory,PHP memory_get_usage 和 memory_get_peak_usage获取内存的区别
- php.ini 中开启短标签
- Python 5种不为人知的高级特征
- 1.Java(初级)编程教程(油管 thenewboston)学习笔记get user input
- 三维点云网络——PointNet论文解读
- pageinfo对合并list进行分页_PageInfo实现分页
- 如何把一个数据库的数据copy到另外一个数据库
- 设备管理系统未来发展的四大趋势
- 计算机组成原理总概括(转)
- activemq 下载以及安装、应用
- 介绍:一款Mathematica的替代开源软件Mathetics
- Win连接android打印机,教你用Android/Iphone/MacWindows和群晖实现无线打印
- 互联网早报20220720
- 一文带你彻底了解电子灌封(灌胶)工艺技术
- 《神经网络与深度学习》基础篇
- 洛谷P4315 月下“毛景树”(树剖+线段树)
- Android蓝牙音乐获取歌曲信息
- postman传String类型参数时不能加双引号
- OLAP引擎 :CH Doris impala+kudu优缺点分析
- PCIe扫盲系列博文连载目录
热门文章
- python读中文文本_python读取中文txt文本
- java log4j和logback,跨过slf4j和logback,直接晋级log4j 2
- 【c语言】蓝桥杯算法提高 三角形面积
- jsp是在html中添加什么作用域,JSP九个内置对象 四大作用域 动作指令
- android xml opacity,Android Drawable详解
- python cs开发框架_我的第一个python web开发框架(24)——系统重构与ORM
- [译] RxJS: 避免 takeUntil 造成的泄露风险
- VBA编程常用语句(转载)
- XtraBackup
- 前端每周清单第 50 期: AngularJS and Long Term Support, Web 安全二三论