使用Python从头开始构建简单的Siri机器人?

89 阅读7分钟

使用NLTK进行文本预处理

=============

文本数据的主要问题是它们全部为文本格式(字符串)。但是,机器学习算法需要某种数字特征向量才能执行任务。因此,在开始任何NLP项目之前,我们需要对其进行预处理以使其适合工作。基本的文本预处理包括:

  • 将整个文本转换为大写或小写,这样算法就不会将相同单词在不同情况下视为不同

  • 标记化:标记化只是用于描述将普通文本字符串转换为标记列表(即我们实际需要的单词)的过程的术语。句子标记器可用于查找句子列表,单词标记器可用于查找字符串中的单词列表。

NLTK数据包包括一个经过预训练的Punkt令牌生成器。

  • 消除噪音,即所有不是标准数字或字母的东西。

  • 删除停止词。有时,一些极为常见的词汇在帮助用户选择符合用户需求的文档时似乎没有什么价值,但却被完全排除在词汇表之外。这些词被称为停止词

  • 词干分析:词干分析是将词形变化(有时是派生的)的单词还原为词干、词根或词根的过程,通常是书面形式。

  • 词法化:词干法的一个小变种是词法化。它们之间的主要区别在于,词干通常可以创建不存在的词,而引理是实际的词。因此,你的词根意思不是你只能在字典中查找的内容,而是你可以查找引理的意思。合法化的例子是“运行”是“运行”或“奔跑”等词的基本形式,或者“更好”和“好”一词处于同一引理中,因此它们被认为是相同的。

言语包

===

在初始预处理阶段之后,我们需要将文本转换为有意义的数字矢量(或数组)。词袋是文本的表示形式,描述了文档中单词的出现。它涉及到两件事:

  • 已知单词的词汇表。

  • 衡量已知词汇的存在。

TF-IDF方法

========

“词袋”方法的一个问题是,频繁出现的单词开始在文档中占主导地位(例如,较大的分数),但可能没有那么多的“信息内容”。同样,与较短的文件相比,较长的文件将具有更大的权重。

一种方法是通过单词在所有文档中出现的频率来重新调整单词的频率,以便对在所有文档中也很常见的诸如“ the”之类的单词的分数进行惩罚。这种计分方法称为术语频率反文档频率,简称TF-IDF,其中:

术语频率:是当前文档中单词频率的得分。

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个单词的文档,其中单词“ phone”出现5次。

那么电话的术语频率(即tf)为(5/100)= 0.05。现在,假设我们有1000万个文档,其中有1000万个单词出现在电话中。然后,反向文档频率(即IDF)计算为log(10,000,000 / 1,000)=4。因此,Tf-IDF权重是这些数量的乘积:0.05 * 4 = 0.20。

TF-IDF可以在scikit学习中实现为:

sklearn.feature_extraction.text导入TfidfVectorizer

余弦相似度

=====

TF-IDF是一种应用于文本的变换,用于在向量空间中获得两个实值向量。然后,我们可以通过取向量的点积并将其除以其范数的乘积来获得任何一对向量的余弦相似度。得出向量之间角度的余弦值。余弦相似度是两个非零向量之间相似度的量度。使用此公式,我们可以找出任意两个文档d1和d2之间的相似性。

Cosine Similarity (d1, d2) = Dot product(d1, d2) / ||d1|| * ||d2||

其中d1,d2是两个非零向量。

现在,我们对NLP流程有了一个清晰的想法。现在是时候完成真正的任务,即创建聊天机器人了。我们在这里将聊天机器人命名为“ ROBO ”。

导入必要的库

======

import nltk

import numpy as np

import random

import string # to process standard python strings

语料库

===

对于我们的示例,我们将使用聊天机器人的Wikipedia页面作为语料库。复制页面中的内容,并将其放置在名为“ chatbot.txt”的文本文件中。但是,您可以使用您选择的任何语料库。

读取数据

====

我们将读取corpus.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

让我们看一个send_tokens和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)))

关键字匹配

=====

接下来,我们将定义机器人的问候语功能,即如果用户输入的是问候语,则机器人应返回问候语响应.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功能的矩阵。

from sklearn.feature_extraction.text import TfidfVectorizer

  • 另外,从scikit学习库导入余弦相似度模块

from sklearn.metrics.pairwise import cosine_similarity

_这将用于查找用户输入的单词与语料库中的单词之间的相似性。_这是聊天机器人的最简单的实现。

我们定义了一个函数响应,该函数在用户的发声中搜索一个或多个已知关键字,并返回几种可能的响应之一。如果找不到与任何关键字匹配的输入,它将返回一个响应:“对不起!我不明白你的意思。”

def response(user_response):

robo_response=''

sent_tokens.append(user_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' ):

最后

🍅 硬核资料:关注即可领取PPT模板、简历模板、行业经典书籍PDF。
🍅 技术互助:技术群大佬指点迷津,你的问题可能不是问题,求资源在群里喊一声。
🍅 面试题库:由技术群里的小伙伴们共同投稿,热乎的大厂面试真题,持续更新中。
🍅 知识体系:含编程语言、算法、大数据生态圈组件(Mysql、Hive、Spark、Flink)、数据仓库、Python、前端等等。

了解详情:docs.qq.com/doc/DSnl3ZG…