如何使用 Python+tensorflow+keras进行深度学习创建聊天机器人

如何使用 Python+tensorflow+keras进行深度学习创建聊天机器人

如何使用 <a href='/tag/python.html'>Python</a>+tensorflow+keras进行深度学习创建聊天机器人

聊天机器人是一种软件,它通过聊天中的文本消息与用户进行类似人类的对话。它的主要任务是通过回答用户提出的问题来帮助用户。我们将通过使用深度学习使软件变得智能。这样聊天机器人就可以预测对用户的更准确的反应,也可以理解用户他/她想问什么,并根据它的理解给出反馈。

根据它们的构建方式,有两种类型的聊天机器人模型:

基于检索的模型:此聊天机器人使用预定义的输入模式和响应。

基于机器学习生成的模型:此聊天机器人不基于某些预定义的响应。

本文我们说说如何使用深度学习创建聊天机器人:

市场上有很多强大的机器人开发框架、工具和平台,我们可以从中开发智能聊天机器人。但我们将使用深度学习从头开始创建一个简单而智能的聊天机器人。

因此,在这个项目中,我们将从头开始使用 Tensorflow 和 keras 的深度学习开发一个智能聊天机器人。我们将创建一个模型,该模型将在包含intent(类别)、问和答的数据集上进行训练。我们的模型将分类用户发送的消息属于哪个类别,并从响应列表中提供随机响应。

一、安装依赖库

您的系统中应该有以下库,创建聊天机器人时需要这些库:

Tensorflow (pip install tensorflow)
Keras (pip install keras)
Numpy (pip install numpy)
Natural Language processing (Nltk) (pip install nltk)
Pickle (pip install pickle)

如果您没有这些库,请使用 pip 安装它们,打开命令提示符,键入 pip install keras、pip install numpy 等,如括号内所示。

二、数据集准备

我们的 intents.json 文件如下所示,包含标签、多款相似问词和回答词。

如何使用 <a href='/tag/python.html'>Python</a>+tensorflow+keras进行深度学习创建聊天机器人

三、代码编写

1、代码中导入必要的库

import tensorflow
import nltk
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout , Activation, Flatten , Conv2D, MaxPooling2D
from tensorflow.keras.optimizers import SGD
import random
import json
import pickle

这些都是我们创建项目所需的库。nltk 需要对单词和句子进行标记,也需要对单词进行词形还原。

基本上 nltk 将需要预处理我们的数据(我们必须对我们的数据执行某些操作,因为我们将处理一个包含单词和句子的 json 文件)。

我们将使用 Tensorflow 创建我们的模型,使用 numpy 将我们的数据转换为数组形式。Random 根据用户消息生成随机响应。Json 读取 json 文件。pickle来保存我们的标签和文字。

2. 声明常量:

在这一步中,我们声明了一些分隔句子时需要的常量。

words=[]
labels = []
docs = []
ignore_list = ['?', '!']


3.加载我们的数据集即intents.json文件:

使用 json.loads() 方法加载 json 数据集。

dataset = open('intents.json').read()
intents = json.loads(dataset)

4、处理数据

for intent in intents['intents']:
    for pattern in intent['patterns']:
        #tokenize each word
        word_token = nltk.word_tokenize(pattern)
        words.extend(word_token)
        #add documents in the corpus
        docs.append((word_token, intent['tag']))
        # add to our labels list
        if intent['tag'] not in labels:
            labels.append(intent['tag'])

当我们处理文本数据时,我们需要在创建模型并训练该数据之前对数据执行预处理。

在上面的代码中,我们首先遍历我们的tag和patterns,并对模式中存在的每个句子进行标记(标记意味着将文本分解成像单词一样的小部分),然后将每个标记化单词附加到单词列表中。在此,我们还为我们的标签创建了一个标签列表。

5. 词形还原每个单词:

# lemmatize each word, and sort words by removing duplicates:
words = [lemmatizer.lemmatize(word.lower()) for word in words if word not in ignore_list]
words = sorted(list(set(words)))
# sort labels:
labels = sorted(list(set(labels)))


在这段代码中,我们对每个单词进行词法化(词法化意味着将一个词转换为它的词法形式),并从列表中删除重复的单词并对单词和标签列表进行排序。

6.保存单词和标签列表(使用pickle):

现在我们将保存我们使用 pickle 库创建的单词和标签列表。

pickle.dump(words,open('words.pkl','wb'))
pickle.dump(labels,open('labels.pkl','wb'))


7. 创建我们的训练数据:

# creating our training data:
training_data = []
# creating an empty array for our output (with size same as length of labels):
output = [0]*len(labels)
for doc in docs:
    bag_of_words = []
    pattern_words = doc[0]
    #lemmatize pattern words:
    pattern_words = [lemmatizer.lemmatize(word.lower()) for word in pattern_words]
    
    for w in words:
        if w in pattern_words:
            bag_of_words.append(1)
        else:
            bag_of_words.append(0)
            
    output_row = list(output)
    output_row[labels.index(doc[1])] = 1
    
    training_data.append([bag_of_words,output_row])


在这段代码中,我们创建了我们的训练数据,我们将 bag_of_words 作为输入,而 ouput_row 将作为输出告诉我们我们的问句属于哪个标签。由于计算机不理解文本,这就是我们将其转换为数字的原因。

8. 洗牌并将我们的训练数据转换为数组:

我们使用 random.shuffle() 方法打乱我们的训练数据,并使用 numpy 库将我们的数据转换为 numpy 数组。

# convert training_data to numpy array and shuffle the data:
random.shuffle(training_data)
training_data = np.array(training_data)


9. 将数据拆分为 x_train 和 y_train:

将我们的训练数据拆分为 x_train 和 y_train。X_train 由单词组成,y_train 由其对应的标签组成。

# Now we have to create training list:
x_train = list(training_data[:,0])
y_train = list(training_data[:,1])

10. 模型创建:

# Creating Model:
model = Sequential()
model.add(Dense(128, input_shape=(len(x_train[0]),), activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(64, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(len(y_train[0]), activation='softmax'))

11.模型总结:

model.summary()

12. 编译并拟合我们的模型以找到准确度

sgd_optimizer = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd_optimizer, metrics=['accuracy'])
在此,我们将使用带有 Nesterov 加速梯度的随机梯度下降 (sgd) 优化器。

# fit the model 
history = model.fit(np.array(x_train), np.array(y_train), epochs=200, batch_size=5, verbose=1)

13. 保存模型:

现在创建模型后,我们将使用 save() 方法保存模型。

model.save('chatbot_Application_model.h5', history)
14. 预测句子并获得响应的最后一步:

现在,我们必须再创建一个 python 文件来加载我们的模型,我们加载我们上面保存的单词列表和标签列表。我们知道我们的模型只会预测它所属的标签,所以我们必须创建某些函数来识别标签并从响应列表中提供随机响应。

import nltk
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
import pickle
import numpy as np
import json
import random
from keras.models import load_model
model = load_model('chatbot_Application_model.h5')
intents = json.loads(open('intents.json').read())
words = pickle.load(open('words.pkl','rb'))
labels = pickle.load(open('labels.pkl','rb'))


要运行我们的模型,我们必须以与创建模型时相同的方式提供输入。因此,为此我们创建了一个函数,它将执行文本操作,然后预测标签。

def bank_of_words(s,words, show_details=True):
    bag_of_words = [0 for _ in range(len(words))]
    sent_words = nltk.word_tokenize(s)
    sent_words = [lemmatizer.lemmatize(word.lower()) for word in sent_words]
    for sent in sent_words:
        for i,w in enumerate(words):
            if w == sent:
                bag_of_words[i] = 1
    return np.array(bag_of_words)
def predict_label(s, model):
    # filtering out predictions
    pred = bank_of_words(s, words,show_details=False)
    response = model.predict(np.array([pred]))[0]
    ERROR_THRESHOLD = 0.25
    final_results = [[i,r] for i,r in enumerate(response) if r>ERROR_THRESHOLD]
    final_results.sort(key=lambda x: x[1], reverse=True)
    return_list = []
    for r in final_results:
        return_list.append({"intent": labels[r[0]], "probability": str(r[1])})
    return return_list


在预测之后,现在我们将创建一个函数,该函数将从intents列表中给出响应。

def Response(ints, intents_json):
    tags = ints[0]['intent']
    list_of_intents = intents_json['intents']
    for i in list_of_intents:
        if(i['tag']== tags):
            response = random.choice(i['responses'])
            break
    return response
def chatbot_response(msg):
    ints = predict_label(msg, model)
    response = Response(ints, intents)
    return response


现在,在此响应之后,我们创建了一个函数,该函数将使用户和 机器人交互:

def chat():
    print("Start chat with ChatBot of ProjectGurukul")
    while True:
        inp = input("You: ")
        if inp.lower() == 'quit':
            break
        response = chatbot_response(inp)
        print("\n BOT: " + response + '\n\n')
chat()


15. 完整可在线运行代码

训练模型

#!/usr/local/python3/bin/python3
# -*- coding: utf-8 -*
import nltk

from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
import json
import pickle
import tensorflow

import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout , Activation, Flatten , Conv2D, MaxPooling2D
from tensorflow.keras.optimizers import SGD
import random

words=[]
labels = []
docs = []
ignore_list = ['?', '!']

dataset = open('/data/wwwroot/default/dataset/intents.json').read()
intents = json.loads(dataset)


for intent in intents['intents']:
    for pattern in intent['patterns']:

        #tokenize each word
        word_token = nltk.word_tokenize(pattern)
        print(word_token)
        words.extend(word_token)
        #add documents in the corpus
        docs.append((word_token, intent['tag']))
        print(docs)

        # add to our labels list
        if intent['tag'] not in labels:
            labels.append(intent['tag'])

print(labels)
# lemmatize each word, and sort words by removing duplicates:
words = [lemmatizer.lemmatize(word.lower()) for word in words if word not in ignore_list]
print(words)
words = sorted(list(set(words)))
print(words)
# sort labels:
labels = sorted(list(set(labels)))
print(labels)

pickle.dump(words,open('words.pkl','wb'))
pickle.dump(labels,open('labels.pkl','wb'))

# creating our training data:
training_data = []
# creating an empty array for our output (with size same as length of labels):
output = [0]*len(labels)

for doc in docs:
    bag_of_words = []
    pattern_words = doc[0]
    #lemmatize pattern words:
    pattern_words = [lemmatizer.lemmatize(word.lower()) for word in pattern_words]
    
    for w in words:
        if w in pattern_words:
            bag_of_words.append(1)
        else:
            bag_of_words.append(0)
            
    output_row = list(output)
    output_row[labels.index(doc[1])] = 1
    
    training_data.append([bag_of_words,output_row])

# convert training_data to numpy array and shuffle the data:
random.shuffle(training_data)
training_data = np.array(training_data)


# Now we have to create training list:
x_train = list(training_data[:,0])
print(x_train)

y_train = list(training_data[:,1])
print(y_train)
# Creating Model:

model = Sequential()
model.add(Dense(128, input_shape=(len(x_train[0]),), activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(64, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(len(y_train[0]), activation='softmax'))

model.summary()

sgd_optimizer = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd_optimizer, metrics=['accuracy'])

# fit the model 
history = model.fit(np.array(x_train), np.array(y_train), epochs=200, batch_size=5, verbose=1)

model.save('chatbot_Application_model.h5', history)

模型预测

#!/usr/local/python3/bin/python3
# -*- coding: utf-8 -*
import nltk
from nltk.stem import WordNetLemmatizer
lemmatizer = WordNetLemmatizer()
import pickle
import numpy as np
import json
import random
from tensorflow.keras.models import load_model

model = load_model('chatbot_Application_model.h5')

intents = json.loads(open('/data/wwwroot/default/dataset/intents.json').read())
words = pickle.load(open('words.pkl','rb'))
labels = pickle.load(open('labels.pkl','rb'))


def bank_of_words(s,words, show_details=True):
    bag_of_words = [0 for _ in range(len(words))]
    sent_words = nltk.word_tokenize(s)
    sent_words = [lemmatizer.lemmatize(word.lower()) for word in sent_words]
    for sent in sent_words:
        for i,w in enumerate(words):
            if w == sent:
                bag_of_words[i] = 1
    return np.array(bag_of_words)

def predict_label(s, model):
    # filtering out predictions
    pred = bank_of_words(s, words,show_details=False)
   
    response = model.predict(np.array([pred]))[0]
    ERROR_THRESHOLD = 0.25
    final_results = [[i,r] for i,r in enumerate(response) if r>ERROR_THRESHOLD]
    final_results.sort(key=lambda x: x[1], reverse=True)
    return_list = []
    for r in final_results:
        return_list.append({"intent": labels[r[0]], "probability": str(r[1])})
    return return_list

def Response(ints, intents_json):
    tags = ints[0]['intent']
    list_of_intents = intents_json['intents']
    for i in list_of_intents:
        if(i['tag']== tags):
            response = random.choice(i['responses'])
            break
    return response

def chatbot_response(msg):
    ints = predict_label(msg, model)
    response = Response(ints, intents)
    return response
            
def chat():
    print("Start chat with ChatBot of Project Gurukul")
    while True:
        inp = input("You: ")
        if inp.lower() == 'quit':
            break
        response = chatbot_response(inp)
        print("\n BOT: " + response + '\n\n')

chat()
        

		

16、效果
如何使用 <a href='/tag/python.html'>Python</a>+tensorflow+keras进行深度学习创建聊天机器人

17、项目源码下载

chatbot-project-souce-code.zip

总结

在这个深度学习项目中,我们成功开发了一个基于智能检索的聊天机器人,它可以根据您的消息理解和响应。在这里,我们创建了一个模型,该模型可以准确预测用户消息所属的标签,然后它从意图列表中给出随机响应,这使得我们的 聊天机器人变得智能。

{{collectdata}}

网友评论0