快來!建立你的第一個Python聊天機器人項目
利用Python,我們可以實現(xiàn)很多目標,比如說建立一個你專屬的聊天機器人程序。
聊天機器人程序不光滿足個人需求,它對商業(yè)組織和客戶都非常有幫助。大多數(shù)人喜歡直接通過聊天室交談,而不是打電話給服務中心。
Facebook發(fā)布的數(shù)據(jù)證明了機器人的價值。每月有超過20億條信息在人和公司之間發(fā)送。HubSpot的研究顯示,71%的人希望從信息應用程序獲得客戶支持。這是解決問題的快速方法,因此聊天機器人在組織中有著光明的未來。
今天要做的是在Chatbot上建立一個令人興奮的項目。從零開始完成一個聊天機器人,它將能夠理解用戶正在談論的內容并給出適當?shù)幕貞?/p>
先決條件
為了實現(xiàn)聊天機器人,將使用一個深度學習庫Keras,一個自然語言處理工具包NLTK,以及一些有用的庫。運行以下命令以確保安裝了所有庫:
- pip installtensorflow keras pickle nltk
聊天機器人是如何工作的?
聊天機器人只是一個智能軟件,可以像人類一樣與人互動和交流。很有趣,不是嗎?現(xiàn)在來看看它們是如何工作的。
所有聊天機器人都基于自然語言處理(NLP)概念。NLP由兩部分組成:
- NLU(自然語言理解):機器理解人類語言(如英語)的能力。
- NLG(自然語言生成):機器生成類似于人類書面句子的文本的能力。
想象一個用戶問聊天機器人一個問題:“嘿,今天有什么新聞?”
該聊天機器人就會將用戶語句分解為兩個部分:意圖和實體。這句話的目的可能是獲取新聞,因為它指的是用戶希望執(zhí)行的操作。實體告訴了關于意圖的具體細節(jié),所以“今天”將是實體。因此,這里使用機器學習模型來識別聊天的意圖和實體。
項目文件結構
項目完成后,將留下所有這些文件??焖贋g覽每一個。它將給開發(fā)員一個如何實施該項目的想法。
- Train_chatbot.py-在本文件中,構建和訓練深度學習模型,該模型可以分類和識別用戶向機器人提出的要求。
- Gui_Chatbot.py-這個文件是構建圖形用戶界面用來與訓練后的聊天機器人聊天的地方。
- Intents.json-Intents文件包含將用于訓練模型的所有數(shù)據(jù)。它包含一組標記及其相應的模式和響應。
- Chatbot_model.h5-這是一個分層數(shù)據(jù)格式文件,其中存儲了訓練模型的權重和體系結構。
- Classes.pkl-pickle文件可用于存儲預測消息時要分類的所有標記名。
- Words.pkl-Words.pklpickle文件包含模型詞匯表中的所有唯一單詞。
下載源代碼和數(shù)據(jù)集:
mailto:https://drive.google.com/drive/folders/1r6MrrdE8V0bWBxndGfJxJ4Om62dJ2OMP?usp=sharing
如何建立自己的聊天機器人?
筆者將這個聊天機器人的構建簡化為5個步驟:
第一步:導入庫并加載數(shù)據(jù)
創(chuàng)建一個新的python文件并將其命名為train_chatbot,然后導入所有必需的模塊。之后,從Python程序中讀取JSON數(shù)據(jù)文件。
- importnumpy as np
- fromkeras.models importSequential
- fromkeras.layers importDense, Activation,Dropout
- fromkeras.optimizers importSGD
- importrandom
- importnltk
- fromnltk.stem importWordNetLemmatizer
- lemmatizer = WordNetLemmatizer()
- importjson
- importpickle
- intents_file = open('intents.json').read()
- intents= json.loads(intents_file)
第二步:數(shù)據(jù)預處理
模型無法獲取原始數(shù)據(jù)。為了使機器容易理解,必須經過許多預處理。對于文本數(shù)據(jù),有許多預處理技術可用。第一種技術是標記化,把句子分解成單詞。
通過觀察intents文件,可以看到每個標記包含模式和響應的列表。標記每個模式并將單詞添加到列表中。另外,創(chuàng)建一個類和文檔列表來添加與模式相關的所有意圖。
- words=[]
- classes= []
- documents= []
- ignore_letters = ['!', '?', ',', '.']
- forintent in intents['intents']:
- forpattern in intent['patterns']:
- #tokenize each word
- word= nltk.word_tokenize(pattern)
- words.extend(word)
- #add documents in the corpus
- documents.append((word, intent['tag']))
- # add to our classes list
- ifintent['tag'] notin classes:
- classes.append(intent['tag'])
- print(documents)
另一種技術是詞形還原。我們可以將單詞轉換成引理形式,這樣就可以減少所有的規(guī)范單詞。例如,單詞play、playing、playing、played等都將替換為play。這樣,可以減少詞匯表中的單詞總數(shù)。所以將每個單詞進行引理,去掉重復的單詞。
- # lemmaztize and lower each word andremove duplicates
- words= [lemmatizer.lemmatize(w.lower()) forw in words if w notinignore_letters]
- words= sorted(list(set(words)))
- # sort classes
- classes= sorted(list(set(classes)))
- # documents = combination betweenpatterns 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()方法。這些文件將有助于訓練完成后進行預測聊天。
第三步:創(chuàng)建訓練集和測試集
為了訓練模型,把每個輸入模式轉換成數(shù)字。首先,對模式中的每個單詞進行引理,并創(chuàng)建一個長度與單詞總數(shù)相同的零列表。只將值1設置為那些在模式中包含單詞的索引。同樣,將1設置為模式所屬的類輸入,來創(chuàng)建輸出。
- # create the training data
- training= []
- # create empty array for the output
- output_empty = [0] * len(classes)
- # training set, bag of words for everysentence
- fordoc in documents:
- # initializing bag of words
- bag= []
- # list of tokenized words for thepattern
- word_patterns = doc[0]
- # lemmatize each word - create baseword, in attempt to represent related words
- word_patterns = [lemmatizer.lemmatize(word.lower()) for word in word_patterns]
- # create the bag of words array with1, if word is found in current pattern
- forword in words:
- bag.append(1) if word inword_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])] = 1
- training.append([bag, output_row])
- # shuffle the features and make numpyarray
- 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")
第四步:訓練模型
該模型將是一個由3個密集層組成的神經網絡。第一層有128個神經元,第二層有64個,最后一層的神經元數(shù)量與類數(shù)相同。為了減少模型的過度擬合,引入了dropout層。使用SGD優(yōu)化器并對數(shù)據(jù)進行擬合,開始模型的訓練。在200個階段的訓練完成后,使用Kerasmodel.save(“chatbot_model.h5”)函數(shù)保存訓練的模型。
- # 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 Nesterovaccelerated 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")
第五步:與聊天機器人互動
模型已經準備好聊天了,現(xiàn)在在一個新文件中為聊天機器人創(chuàng)建一個很好的圖形用戶界面??梢詫⑽募麨間ui_chatbot.py
在GUI文件中,使用Tkinter模塊構建桌面應用程序的結構,然后捕獲用戶消息,并在將消息輸入到訓練模型之前,再次執(zhí)行一些預處理。
然后,模型將預測用戶消息的標簽,從intents文件的響應列表中隨機選擇響應。
這是GUI文件的完整源代碼。
- importnltk
- fromnltk.stem importWordNetLemmatizer
- lemmatizer = WordNetLemmatizer()
- importpickle
- importnumpy as np
- fromkeras.models importload_model
- model= load_model('chatbot_model.h5')
- importjson
- importrandom
- intents= json.loads(open('intents.json').read())
- words= pickle.load(open('words.pkl','rb'))
- classes= pickle.load(open('classes.pkl','rb'))
- defclean_up_sentence(sentence):
- # tokenize the pattern - splittingwords into array
- sentence_words = nltk.word_tokenize(sentence)
- # stemming every word - reducing tobase form
- sentence_words = [lemmatizer.lemmatize(word.lower()) for word in sentence_words]
- returnsentence_words
- # return bag of words array: 0 or 1for words that exist in sentence
- defbag_of_words(sentence, words,show_details=True):
- # tokenizing patterns
- sentence_words = clean_up_sentence(sentence)
- # bag of words - vocabulary matrix
- bag= [0]*len(words)
- fors in sentence_words:
- fori,word inenumerate(words):
- ifword == s:
- # assign 1 if current word is in thevocabulary position
- bag[i] = 1
- ifshow_details:
- print("found in bag:%s" % word)
- return(np.array(bag))
- defpredict_class(sentence):
- # filter below thresholdpredictions
- p= bag_of_words(sentence,words,show_details=False)
- res= model.predict(np.array([p]))[0]
- ERROR_THRESHOLD = 0.25
- results= [[i,r] fori,r inenumerate(res) ifr>ERROR_THRESHOLD]
- # sorting strength probability
- results.sort(key=lambdax: x[1],reverse=True)
- return_list = []
- forr in results:
- return_list.append({"intent": classes[r[0]],"probability": str(r[1])})
- returnreturn_list
- defgetResponse(ints, intents_json):
- tag= ints[0]['intent']
- list_of_intents = intents_json['intents']
- fori in list_of_intents:
- if(i['tag']== tag):
- result= random.choice(i['responses'])
- break
- returnresult
- #Creating tkinter GUI
- importtkinter
- fromtkinter import *
- defsend():
- msg= EntryBox.get("1.0",'end-1c').strip()
- EntryBox.delete("0.0",END)
- ifmsg != '':
- 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("<Return>",send)
- #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()
運行聊天機器人
現(xiàn)在有兩個獨立的文件,一個是train_chatbot.py,首先使用它來訓練模型。
- pythontrain_chatbot.py
快來試試吧~