我相信你一定听说过Duolingo:一款流行的语言学习应用。它以其创新的外语教学风格而广受欢迎,其概念很简单:一天五到十分钟的互动训练就足以学习一门语言。
然而,尽管Duolingo使人们能够学习一种新的语言,但使用者在学习过程中缺少与人交流的机会,因此,他们的团队通过在其应用程序中构建一个本地聊天机器人来解决这个问题,以帮助用户学习会话技能和实践他们所学到的东西。
由于机器人是设计成对话式的,所以学习者可以在一天中的任何时间练习会话。这解决了使用者的痛点,并使通过应用程序学习的方式更加有趣。
什么是聊天机器人?
聊天机器人它是一款人工智能软件(Siri、Alexa、Google助手等)、应用程序、网站或其他网络,这些软件试图挖掘消费者的需求,然后帮助他们完成一项特定任务,如商业交易、酒店预订、表单提交等。如今,几乎每一家公司都部署了一个聊天机器人来与用户打交道。公司使用聊天机器人的一些方式有:
· 提供飞行信息
· 把客户和他们的财务联系起来
· 作为客户支持
聊天机器人的可能性几乎是无限的。
聊天机器人是怎么工作的?
大致上有两种类型的聊天机器人: 基于规则的和自学习的。
1. 基于规则的:根据训练的规则哎回答问题。定义的规则可以非常简单,也可以非常复杂。机器人可以处理简单的查询,但不能处理复杂的查询。
2. 自学习机器人:使用一些基于机器学习的方法,它比基于规则的机器人更有效率。这些机器人还可以有两种类型:基于检索或生成性
(一)基于检索的模型:聊天机器人使用一些启发式方法从预定义响应库中选择响应。Chatbot使用会话的消息和上下文从预定义的bot消息列表中选择最佳响应。上下文可以包括对话框树中的当前位置、会话中的所有先前消息、先前保存的变量(例如用户名)。选择响应的启发式方法可以通过多种不同的方式进行,从基于规则的if-否则条件逻辑到机器学习分类器。
(二)生成性机器人可以生成答案,而不是总是从一组答案中生成一个答案。这使得他们更聪明,因为他们从查询中逐字逐句地获取并生成答案。
在本文中,我们将在python中基于NLTK库构建一个简单的基于检索的Chatbot。
建造机器人
先决条件
专注于人类语言和计算机之间相互作用的研究领域被称为自然语言处理,简称NLP。它位于计算机科学、人工智能和计算语言学[维基百科]的交汇处。NLP是计算机以有用的方式从人类语言中分析、理解和获得意义的一种方式。通过使用NLP,开发人员可以组织和构造知识,完成自动摘要、翻译、命名实体识别、关系提取、情感分析、语音识别和主题分割等任务。
NLTK简介
NLTK(NaturalLanguageToolkit)是构建Python程序以处理人类语言数据的领先平台。它提供了易于使用的接口50多个语料库和词汇资源例如WordNet,以及一套用于分类、标记化、词干、标记、解析和语义推理的文本处理库,以及用于工业强度nlp库的包装器。《用Python进行自然语言处理》提供语言处理编程的实用介绍,我强烈推荐这本书给从Python的NLP开始的人。
下载和安装NLTK
1. 安装NLTK:运行pip install nltk
2. 测试安装:运行python然后键入import nltk
安装NLTK软件包
导入NLTK并运行nltk.download().这将打开NLTK下载器,你可以从其中选择要下载的语料库和模型,你也可以一次下载所有软件包。
用NLTK对文本进行预处理
文本数据的主要问题是它都是文本格式(字符串)。然而,机器学习算法需要一定的数值特征向量来完成任务。因此,在我们开始任何NLP项目之前,我们需要对其进行预处理,使其成为理想的工作方式。基本文本预处理包括:
· 将整个文本转换为大写或小写,这样,算法就不会在不同的情况下将相同的单词视为不同的词。
· 标记化:标记化只是用来描述将普通文本字符串转换为标记列表的过程,即我们实际需要的单词。句子标记器可用于查找句子列表,而Word标记器可用于查找字符串中的单词列表。
NLTK数据包括一个经过预先训练的Punkt英语标记器。
在初始预处理阶段之后,我们需要将文本转换为有意义的数字向量。单词袋描述文档中单词的出现的文本表示,它涉及两件事:
*已知单词的词汇表。
*衡量已知词语的存在程度。
为什么叫它“袋“?这是因为有关文档中单词的顺序或结构的任何信息都会被丢弃,并且模型只涉及已知单词是否发生在文档中,而不是在文档中发生的位置。
TF-IDF方法
单词袋法的一个问题是,频繁出现的单词开始在文档中占据主导地位,但可能不包含那么多的“信息内容”。此外,它将给予长文件比短文件更大的权重。
一种方法是根据单词在所有文档中出现的频率来重新确定单词的频率,以便对所有文档中也经常出现的“the”这样的频繁单词的得分进行惩罚。这种得分方法称为术语频率-反向文档频率,其中:
术语频率*是对当前文件中单词频率的评分。
TF = (Number of times term t appears in a document)/(Number of terms in the document)
逆文档频率这个词在文档中十分罕见。
IDF = 1 log(N/n), where, N is the number of documents and n is the number of documents a term t has appeared in.
TF-IDF权重是信息检索和文本挖掘中常用的权重。此权重是一种统计度量,用于评估单词对集合或语料库中的文档的重要程度。
例子:
假设一份包含100个单词的文档,其中“电话”这个词出现了5次。
The term frequency (i.e., tf) for phone is then (5 / 100) = 0.05. Now, assume we have 10 million documents and the word phone appears in one thousand of these. Then, the inverse document frequency (i.e., IDF) is calculated as log(10,000,000 / 1,000) = 4. Thus, the Tf-IDF weight is the product of these quantities: 0.05 * 4 = 0.20.
TF-IDF可在科学知识学习中实施,具体如下:
从sklearn.FeatureExpresaction.text导入TfidfVectorizer
余弦相似
TF-ID是一种应用于文本的变换,用于得到向量空间中的两个实值向量。然后,我们可以获得余弦通过取它们的点积并除以它们的范数的乘积来表示任意一对向量的相似性。产生矢量之间夹角的余弦。余弦相似是相似性度量在两个非零向量之间。利用这个公式,我们可以找出任意两个文档D1和D2之间的相似性。
Cosine Similarity (d1, d2) = Dot product(d1, d2) / ||d1|| * ||d2||
其中D1,D2是两个非零向量。
关于TF-IDF和余弦相似的详细解释和实例,请参阅以下文件。
现在我们对NLP进程有了一个基本的认识。现在是我们完成真正任务的时候了,那就是创建聊天机器人。我们将这里的聊天机器人命名为“Robo”’
导入必要的库
import nltk import numpy as np import random import string # to process standard python strings
语料库
对于我们的例子,我们将使用Wikipedia页面聊天机器人作为我们的主体。复制页面中的内容,并将其放入名为“chatbot.txt”的文本文件中。然而,你也可以使用你选择的任何语料库。
读取数据
我们将在corpu.txt文件中阅读,并将整个语料库转换为句子列表和单词列表,以便进行进一步的预处理。
f=open('chatbot.txt','r',errors = 'ignore')
raw=f.read()
raw=raw.lower()# converts to lowercase
nltk.download('punkt') # first-time use only nltk.download('wordnet') # first-time use only
sent_tokens = nltk.sent_tokenize(raw)# converts to list of sentences word_tokens = nltk.word_tokenize(raw)# converts to list of words
让我们看看已发送的令牌和Word_Tokens的示例。
sent_tokens[:2] ['a chatbot (also known as a talkbot, chatterbot, bot, im bot, interactive agent, or artificial conversational entity) is a computer program or an artificial intelligence which conducts a conversation via auditory or textual methods.', 'such programs are often designed to convincingly simulate how a human would behave as a conversational partner, thereby passing the turing test.']
word_tokens[:2] ['a', 'chatbot', '(', 'also', 'known']
预处理原始文本
现在我们将定义一个名为LemTokens的函数,它将接受这些令牌并返回规范化令牌。
lemmer = nltk.stem.WordNetLemmatizer() #WordNet is a semantically-oriented dictionary of English included in NLTK.
def LemTokens(tokens): return [lemmer.lemmatize(token) for token in tokens] remove_punct_dict = dict((ord(punct), None) for punct in string.punctuation) def LemNormalize(text): return LemTokens(nltk.word_tokenize(text.lower().translate(remove_punct_dict)))
关键词匹配
接下来,我们将定义一个用于BOT问候的函数,即如果用户的输入是问候语,bot将返回问候语响应。ELIZA使用简单的关键字匹配来表示问候。我们将在这里使用同样的概念。
GREETING_INPUTS = ("hello", "hi", "greetings", "sup", "what's up","hey",)
GREETING_RESPONSES = ["hi", "hey", "*nods*", "hi there", "hello", "I am glad! You are talking to me"]
def greeting(sentence): for word in sentence.split(): if word.lower() in GREETING_INPUTS: return random.choice(GREETING_RESPONSES)
生成响应
为了产生我们的机器人对输入问题的响应,将使用文档相似的概念。因此,我们首先导入必要的模块。
· 从Scikit学习库导入TFidf向量器将原始文档集合转换为TF-IDF矩阵。
从sklearn.FeatureExpresaction.text导入TfidfVectorizer
· 另外,import余弦相似SICKIT学习库中的模块
from sklearn.metrics.pairwise import cosine_similarity
这将用于查找用户输入的单词与语料库中的单词之间的相似性。这是聊天机器人最简单的实现。
我们定义了一个函数反应它搜索用户的话语,寻找一个或多个已知的关键字,并返回几个可能的响应中的一个。如果它找不到与任何关键字匹配的输入,它将返回一个响应:“I am sorry! I don’t understand you“
def response(user_response): robo_response=''
TfidfVec = TfidfVectorizer(tokenizer=LemNormalize, stop_words='english') tfidf = TfidfVec.fit_transform(sent_tokens) vals = cosine_similarity(tfidf[-1], tfidf) idx=vals.argsort()[0][-2] flat = vals.flatten() flat.sort() req_tfidf = flat[-2]
if(req_tfidf==0): robo_response=robo_response "I am sorry! I don't understand you" return robo_response else: robo_response = robo_response sent_tokens[idx] return robo_response
最后,根据用户的输入,在开始和结束对话时,我们将输入我们希望机器人说的话。
flag=True print("ROBO: My name is Robo. I will answer your queries about Chatbots. If you want to exit, type Bye!")
while(flag==True): user_response = input() user_response=user_response.lower() if(user_response!='bye'): if(user_response=='thanks' or user_response=='thank you' ): flag=False print("ROBO: You are welcome..") else: if(greeting(user_response)!=None): print("ROBO: " greeting(user_response)) else: sent_tokens.append(user_response) word_tokens=word_tokens nltk.word_tokenize(user_response) final_words=list(set(word_tokens)) print("ROBO: ",end="") print(response(user_response)) sent_tokens.remove(user_response) else: flag=False print("ROBO: Bye! take care..")
差不多就是这样了。我们在NLTK有我们的第一个聊天机器人。你可以通过语料库找到整个代码。现在,让我们看看它是如何与人类互动的:
尽管聊天机器人不能对一些问题给出令人满意的答案,但它在其他问题上表现得很好。
结语
虽然它是一个非常简单的机器人,几乎没有任何认知技能,但它是进入NLP和了解聊天机器人的好方法。对于一个生产系统,你会想要考虑一个现有的机器人平台或框架,这个例子应该可以帮助你思考创建一个聊天机器人的设计和挑战。互联网充斥着资源,在阅读了本文之后,你可以创建一个你自己的聊天机器人。
原文标题《Building a Simple Chatbot from Scratch in Python (using NLTK)》
作者:Parul Pandey
译者:lemon
不代表云加社区观点,更多详情请查看原文链接