今天将学习如何使用意图匹配和自然语言处理算法从零开始构建一个AI聊天机器人。以下是将要执行的步骤:
首先,需要准备包含问题(关键词)和相应意图的数据集。然后,需要准备一个包含每个意图回复的JSON文件。接着,将数据转换为Tf-Idf向量。之后,使用深度神经网络将用户的问题分类为模型训练过的意图之一。最后,保存模型以便将来部署,并加载保存的模型以生成对用户查询的回复。
准备数据集时,需要一些问题或关键词以及相应的意图来使用意图匹配算法创建聊天机器人。在这里,将创建一个包含关键词及其相应意图的CSV文件,格式如下(可以使用自己的格式,只需要一些带有问题或关键词(模式)和相应意图(标签)作为目标变量的数据)。每个意图下的独特关键词或问题越多,回复的准确性就越高。将数据保存为“training_data.csv”。
准备包含回复的JSON文件时,现在已经创建了数据,让为每个意图创建回复。如果不知道JSON文件是什么,可以将其视为Python字典。JSON文件的工作原理完全相同。只需要在每个意图下有一些回复,这些回复将显示给用户。以下是一个包含每个意图下回复的JSON格式示例。将回复保存为“responses.json”。
{
"greeting": ["好!能帮什么吗?", "嗨!问任何问题。", "嗨!准备好回答所有问题。"]
}
Tf-Idf是什么?它是一种类似于词袋(向量中包含文档中每个词的出现次数)的方法,但它为每个词分配一个权重,对于像‘is’、‘are’、‘was’、‘the’等频繁出现的词,权重变得非常低,而不是出现次数。公式如下:
tf(t,d) = t在d中的数量 / d中的词数
idf(t) = log(N/(df + 1))
tf-idf(t, d) = tf(t, d) * log(N/(df + 1))
其中,t代表词,d代表文档,N代表词出现的文档数量。现在,既有训练数据又有回复,也知道了Tf-Idf向量是什么。让开始构建聊天机器人。
创建和训练模型时,需要导入必要的模块。以下是导入模块的代码示例:
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.preprocessing import LabelEncoder
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import save_model
让加载数据。以下是加载训练数据的代码示例:
training_data = pd.read_csv("training_data.csv")
让处理数据(将把所有数据转换为小写,然后将其转换为Tf-Idf向量)。Scikit-learn中的TfidfVectorizer将使这变得容易。以下是预处理训练数据的代码示例:
training_data["patterns"] = training_data["patterns"].str.lower()
vectorizer = TfidfVectorizer(ngram_range=(1, 2), stop_words="english")
training_data_tfidf = vectorizer.fit_transform(training_data["patterns"]).toarray()
在这里,ngram_range指定了如何转换数据,ngram_range为(1, 2)将包含Tf-Idf向量中的单字和双字。stop_words指定了要移除的停用词的语言。
让对目标变量(意图)进行独热编码。LabelEncoder将为完成这项工作。以下是预处理目标变量(标签)的代码示例:
le = LabelEncoder()
training_data_tags_le = pd.DataFrame({"tags": le.fit_transform(training_data["tags"])})
training_data_tags_dummy_encoded = pd.get_dummies(training_data_tags_le["tags"]).to_numpy()
让定义模型架构。以下是创建DNN的代码示例:
chatbot = Sequential()
chatbot.add(Dense(10, input_shape=(len(training_data_tfidf[0]),)))
chatbot.add(Dense(8))
chatbot.add(Dense(8))
chatbot.add(Dense(6))
chatbot.add(Dense(len(training_data_tags_dummy_encoded[0]), activation="softmax"))
chatbot.compile(optimizer="rmsprop", loss="categorical_crossentropy", metrics=["accuracy"])
这些参数对数据效果很好。可以使用适合数据的不同参数。正在进行多类分类。因此,必须使用“categorical_crossentropy”损失。此外,希望在输出层获得不同意图的概率。因此,必须在输出层使用“softmax”激活函数。
让用训练数据的Tf-Idf向量和相应的独热编码意图(目标变量)来训练模型。以下是拟合DNN的代码示例:
chatbot.fit(training_data_tfidf, training_data_tags_dummy_encoded, epochs=50, batch_size=32)
已经训练了模型50个周期,批量大小为32。可以根据数据集更改这些值。
让保存模型以便于将来部署。以下是保存模型文件的代码示例:
save_model(chatbot, "chatbot")
恭喜!已经成功地从头开始创建了一个AI聊天机器人并保存了它。现在,可能想知道如何为问题生成回复,也将学到这一点。
现在,考虑一个新的Python脚本“chatbot_main.py”,将在其中让聊天机器人回答用户的问题。以下是导入必要模块的代码示例:
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.preprocessing import LabelEncoder
import numpy as np
from tensorflow.keras.models import load_model
import json
import random
让加载数据、模型和回复。以下是导入训练数据的代码示例:
training_data = pd.read_csv("training_data.csv")
chatbot = load_model("chatbot")
responses = json.load(open("responses.json", "r"))
让将Tf-Idf向量化器拟合到旧的训练数据上,以便转换来自用户的新数据。以下是拟合TfIdfVectorizer与训练数据以预处理输入的代码示例:
training_data["patterns"] = training_data["patterns"].str.lower()
vectorizer = TfidfVectorizer(ngram_range=(1, 2), stop_words="english")
vectorizer.fit(training_data["patterns"])
让将LabelEncoder拟合到旧的目标变量上,以便反向转换模型新预测的目标。以下是拟合LabelEncoder与目标变量(标签)以反向转换预测的代码示例:
le = LabelEncoder()
le.fit(training_data["tags"])
def predict_tag(inp_str):
inp_data_tfidf = vectorizer.transform([inp_str.lower()]).toarray()
predicted_proba = chatbot.predict(inp_data_tfidf)
encoded_label = [np.argmax(predicted_proba)]
predicted_tag = le.inverse_transform(encoded_label)[0]
return predicted_tag
def start_chat():
print("--------------- AI Chat bot ---------------")
print("Ask any queries...")
print("I will try to understand you and reply...")
print("Type EXIT to quit...")
while True:
inp = input("Ask anything... : ")
if inp == "EXIT":
break
else:
if inp:
tag = predict_tag(inp)
response = random.choice(responses[tag])
print("Response... : ", response)
else:
pass
start_chat()