聊天机器人对企业组织和客户都非常有帮助。 大多数人都喜欢直接从聊天室进行交谈,而不是致电服务中心。 Facebook发布的数据证明了机器人的价值。 每月在人与公司之间发送的消息超过20亿条。 HubSpot研究表明,有71%的人希望通过消息传递应用程序获得客户支持。 这是解决问题的快速方法,因此聊天机器人在组织中拥有光明的前景。
今天,我们将在Chatbot上构建一个令人兴奋的项目。 我们将从头开始实现一个聊天机器人,该聊天机器人将能够理解用户在说什么并给出适当的响应。
先决条件
为了实现聊天机器人,我们将使用深度学习库Keras,自然语言处理工具包NLTK和一些有用的库。 运行以下命令以确保所有库均已安装
pip install tensorflow keras pickle nltk
Python备忘单- 免费学习Python的主要指南 。
聊天机器人不过是一种智能软件,可以像人类一样与人互动和交流。 有趣吗? 现在让我们了解它们的实际工作原理。 所有聊天机器人都属于NLP(自然语言处理)概念。 NLP由两部分组成:
向用户向聊天机器人提问的图像:“嘿,今天的新闻是什么? 聊天机器人会将用户句子分为两部分:意图和实体。 该句子的意图可能是get_news,因为它表示用户想要执行的操作。 实体会告知有关意图的详细信息,因此“今天”将是实体。 因此,使用这种机器学习模型来识别聊天的意图和实体。
项目完成后,将剩下所有这些文件。 让我们快速浏览它们中的每一个,它将使您对项目的实施方式有一个了解。
下载源代码和数据集
我通过5个步骤简化了此聊天机器人的构建:
步骤1.导入库并加载数据 -创建一个新的python文件并将其命名为train_chatbot,然后我们将导入所有必需的模块。 之后,我们将在python程序中读取JSON数据文件。
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout
from keras.optimizers import SGD
import random
import nltk
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
import json
import pickle
intents_file = open( 'intents.json' ).read()
intents = json.loads(intents_file)
这是我们的意图文件的外观。
步骤2.预处理数据
该模型无法获取原始数据。 它必须经过很多预处理才能使机器容易理解。 对于文本数据,有许多可用的预处理技术。 第一种技术是令牌化,其中我们将句子分解为单词。
通过观察意图文件,我们可以看到每个标签都包含一个模式和响应列表。 我们标记每个模式并将单词添加到列表中。 另外,我们创建一个类和文档的列表,以添加与模式关联的所有意图。
words=[]
classes = []
documents = []
ignore_letters = [ '!' , '?' , ',' , '.' ]
for intent in intents[ 'intents' ]:for pattern in intent[ 'patterns' ]:#tokenize each wordword = nltk.word_tokenize(pattern)words.extend(word)#add documents in the corpusdocuments.append((word, intent[ 'tag' ]))# add to our classes listif intent[ 'tag' ] not in classes:classes.append(intent[ 'tag' ])
print(documents)
另一种技术是放缩。 我们可以将单词转换为引理形式,以便我们可以减少所有规范的单词。 例如,单词play,play,play,play等都将全部替换为play。 这样,我们可以减少词汇量中的总单词数。 因此,现在我们对每个词进行词素化并删除重复的词。
# lemmaztize and lower each word and remove duplicates
words = [lemmatizer.lemmatize(w.lower()) for w in words if w not in ignore_letters]
words = sorted(list(set(words)))
# sort classes
classes = sorted(list(set(classes)))
# documents = combination between patterns and intents
print (len(documents), "documents" )
# classes = intents
print (len(classes), "classes" , classes)
# words = all words, vocabulary
print (len(words), "unique lemmatized words" , words)
pickle.dump(words,open( 'words.pkl' , 'wb' ))
pickle.dump(classes,open( 'classes.pkl' , 'wb' ))
最后,单词包含我们项目的词汇,而类包含要分类的全部实体。 为了将python对象保存在文件中,我们使用了pickle.dump()方法。 这些文件在培训结束后将很有帮助,我们可以预测聊天记录。
步骤3.创建培训和测试数据
为了训练模型,我们将每个输入模式转换为数字。 首先,我们将对模式中的每个单词进行词法限定,并创建一个与单词总数相同长度的零列表。 我们将仅对那些包含模式中单词的索引设置值1。 我们将通过将类输入模式所属的设置为1来创建输出。
# create the training data
training = []
# create empty array for the output
output_empty = [ 0 ] * len(classes)
# training set, bag of words for every sentence
for doc in documents:# initializing bag of wordsbag = []# list of tokenized words for the patternword_patterns = doc[ 0 ]# lemmatize each word - create base word, in attempt to represent related wordsword_patterns = [lemmatizer.lemmatize(word.lower()) for word in word_patterns]# create the bag of words array with 1, if word is found in current patternfor word in words:bag.append( 1 ) if word in word_patterns else bag.append( 0 )# output is a '0' for each tag and '1' for current tag (for each pattern)output_row = list(output_empty)output_row[classes.index(doc[ 1 ])] = 1training.append([bag, output_row])
# shuffle the features and make numpy array
random.shuffle(training)
training = np.array(training)
# create training and testing lists. X - patterns, Y - intents
train_x = list(training[:, 0 ])
train_y = list(training[:, 1 ])
print( "Training data is created" )
步骤4.训练模型
我们模型的架构将是由3个密集层组成的神经网络。 第一层具有128个神经元,第二层具有64个神经元,最后一层将具有与类数相同的神经元。 引入了辍学层以减少模型的过拟合。 我们使用了SGD优化器并拟合了数据以开始训练模型。 完成200个纪元的训练后,我们然后使用Keras model.save(“ chatbot_model.h5”)函数保存训练后的模型。
# deep neural networds model
model = Sequential()
model.add(Dense( 128 , input_shape=(len(train_x[ 0 ]),), activation= 'relu' ))
model.add(Dropout( 0.5 ))
model.add(Dense( 64 , activation= 'relu' ))
model.add(Dropout( 0.5 ))
model.add(Dense(len(train_y[ 0 ]), activation= 'softmax' ))
# Compiling model. SGD with Nesterov accelerated gradient gives good results for this model
sgd = SGD(lr= 0.01 , decay= 1e-6 , momentum= 0.9 , nesterov= True )
model.compile(loss= 'categorical_crossentropy' , optimizer=sgd, metrics=[ 'accuracy' ])
#Training and saving the model
hist = model.fit(np.array(train_x), np.array(train_y), epochs= 200 , batch_size= 5 , verbose= 1 )
model.save( 'chatbot_model.h5' , hist)
print( "model is created" )
步骤5.与聊天机器人进行交互
我们的模型已经准备好聊天,因此现在让我们在新文件中为聊天机器人创建一个漂亮的图形用户界面。 您可以将文件命名为gui_chatbot.py
在我们的GUI文件中,我们将使用Tkinter模块构建桌面应用程序的结构,然后我们将捕获用户消息并再次执行一些预处理,然后再将消息输入到经过训练的模型中。
然后,该模型将预测用户消息的标签,我们将从intent文件中的响应列表中随机选择响应。
这是GUI文件的完整源代码。
import nltk
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
import pickle
import numpy as np
from keras.models import load_model
model = load_model( 'chatbot_model.h5' )
import json
import random
intents = json.loads(open( 'intents.json' ).read())
words = pickle.load(open( 'words.pkl' , 'rb' ))
classes = pickle.load(open( 'classes.pkl' , 'rb' ))
def clean_up_sentence (sentence) :# tokenize the pattern - splitting words into arraysentence_words = nltk.word_tokenize(sentence)# stemming every word - reducing to base formsentence_words = [lemmatizer.lemmatize(word.lower()) for word in sentence_words]return sentence_words
# return bag of words array: 0 or 1 for words that exist in sentence
def bag_of_words (sentence, words, show_details=True) :# tokenizing patternssentence_words = clean_up_sentence(sentence)# bag of words - vocabulary matrixbag = [ 0 ]*len(words) for s in sentence_words:for i,word in enumerate(words):if word == s: # assign 1 if current word is in the vocabulary positionbag[i] = 1if show_details:print ( "found in bag: %s" % word)return (np.array(bag))
def predict_class (sentence) :# filter below threshold predictionsp = bag_of_words(sentence, words,show_details= False )res = model.predict(np.array([p]))[ 0 ]ERROR_THRESHOLD = 0.25results = [[i,r] for i,r in enumerate(res) if r>ERROR_THRESHOLD]# sorting strength probabilityresults.sort(key= lambda x: x[ 1 ], reverse= True )return_list = []for r in results:return_list.append({ "intent" : classes[r[ 0 ]], "probability" : str(r[ 1 ])})return return_list
def getResponse (ints, intents_json) :tag = ints[ 0 ][ 'intent' ]list_of_intents = intents_json[ 'intents' ]for i in list_of_intents:if (i[ 'tag' ]== tag):result = random.choice(i[ 'responses' ])breakreturn result
#Creating tkinter GUI
import tkinter
from tkinter import *
def send () :msg = EntryBox.get( "1.0" , 'end-1c' ).strip()EntryBox.delete( "0.0" ,END)if msg != '' :ChatBox.config(state=NORMAL)ChatBox.insert(END, "You: " + msg + '\n\n' )ChatBox.config(foreground= "#446665" , font=( "Verdana" , 12 ))ints = predict_class(msg)res = getResponse(ints, intents)ChatBox.insert(END, "Bot: " + res + '\n\n' )ChatBox.config(state=DISABLED)ChatBox.yview(END)
root = Tk()
root.title( "Chatbot" )
root.geometry( "400x500" )
root.resizable(width=FALSE, height=FALSE)
#Create Chat window
ChatBox = Text(root, bd= 0 , bg= "white" , height= "8" , width= "50" , font= "Arial" ,)
ChatBox.config(state=DISABLED)
#Bind scrollbar to Chat window
scrollbar = Scrollbar(root, command=ChatBox.yview, cursor= "heart" )
ChatBox[ 'yscrollcommand' ] = scrollbar.set
#Create Button to send message
SendButton = Button(root, font=( "Verdana" , 12 , 'bold' ), text= "Send" , width= "12" , height= 5 ,bd= 0 , bg= "#f9a602" , activebackground= "#3c9d9b" ,fg= '#000000' ,command= send )
#Create the box to enter message
EntryBox = Text(root, bd= 0 , bg= "white" ,width= "29" , height= "5" , font= "Arial" )
#EntryBox.bind("
#Place all components on the screen
scrollbar.place(x= 376 ,y= 6 , height= 386 )
ChatBox.place(x= 6 ,y= 6 , height= 386 , width= 370 )
EntryBox.place(x= 128 , y= 401 , height= 90 , width= 265 )
SendButton.place(x= 6 , y= 401 , height= 90 )
root.mainloop()
现在我们有两个单独的文件,一个是train_chatbot.py,我们将首先使用它来训练模型。
python train_chatbot. py
通过源代码探索更多@Python项目 。
From: https://hackernoon.com/python-chatbot-project-build-your-first-python-project-5mt30mi