如何用Python构建情感和实体检测API的完整教程

89 阅读10分钟

我们正生活在自然语言处理(NLP)研究的一个惊人的创新时期。获取最先进的算法和技术供自己使用从未如此简单,HuggingFaceExplosion(Spacy)等公司的工作令人惊叹。在这两部分中,我们将研究如何使用Python和FastAPI来构建自然语言处理(NLP)的API。

我们将学习什么是API,我们将建立一个基于Python的API,它可以识别积极和消极的情绪,并从任何文本中找到 "实体",如人、地方和公司。

目录

  1. 什么是API?
  2. 我们正在构建的--一个NLP API
  3. 库的选择 - FastAPI、Spacy、Flair
  4. 包裹情绪和实体检测功能
  5. 将NLP代码添加到FastAPI应用程序中

什么是API?

如果你刚开始接触数据科学,或一般的编程,API的概念可能很难掌握。你可以把API(技术上是 "应用编程接口")看作是一个计算机程序,它是为了通过互联网与其他计算机程序进行通信而建立的。

What are APIs and how do APIs work? | MuleSoft Blog

API或 "应用编程接口 "是指在联网的计算机上运行的软件程序,可以处理来自其他计算机的 "请求"。

把互联网想象成一群计算机,通常被称为 "服务器",(只是大型计算机),它们都通过网络连接(电缆/WIFI/光纤都构成了这个网络)。服务器上经常有一些软件被设计用来接收来自其他服务器的 "请求"--这些软件程序被称为API。一个 "请求 "可以是检索数据,存储数据,或更新数据。很多时候,请求是通过 "HTTP "协议提出的(与你的网络浏览器获取数据的方法相同,也是你在屏幕上得到这个页面的方法)。

对于注重编程的人来说,现代API经常以JSON格式发送和接收数据,这在几乎所有编程语言中都很容易阅读和使用。

你可能知道的API实例

为了使之成为现实,这里有一些例子。

  • 地理编码。 谷歌为地理编码(将地址字符串转换为GPS坐标)提供了一个很好的API。这些API被那些正在建立网站或应用程序的人使用,他们需要将位置字符串转换成GPS 坐标。在这些网站中,你可以想象填写你的地址,在后台,网站会向谷歌发出 "API请求",并发送你的地址字符串。谷歌在 "API响应 "中发回了GPS坐标,而应用程序则向你展示了你房子周围的漂亮地图。谷歌对每个API的请求收取少量费用。
  • 天气报告。了解现在的天气,并知道某地的天气预报,在很多应用中都很有用,从航海到高尔夫。任何具有这种能力的应用程序都很可能在你打开它时使用API请求和响应,从天气API中 "获取 "天气数据,然后以视觉提示的方式呈现给你。你可以在WeatherAPI上看到一个很好的例子,我以前也做过关于天气数据和使用WundergroundAPI的通勤的工作。
  • 交通。你最喜欢的交通规划应用程序?它在内部几乎不知道你所搜索的每辆公交车的实时位置。在这种情况下,你可以想象打开应用程序,一个后台任务 "请求 "你感兴趣的公交车的实时位置,然后,通过响应,在地图上向你显示该点。举例来说,这里有印度的火车时间爱尔兰的交通SkyScanner航班预订API

我们要建立的是什么--一个NLP API

在本教程中,我们将建立一个能够进行四个步骤的API。

  1. 通过API请求接收文本(我们可以使用 "GET "或 "POST "请求,这只是不同类型的HTTP请求。你一直在使用GET请求--每次你在地址栏中输入一个新的URL或点击一个链接时,你的浏览器都会对一个网页进行GET请求)。
  2. 对文本进行情感分析。情感分析是对文本字符串中的积极性或消极性的识别。例如,"这个API很糟糕 "会得到一个低的情感分数,而 "这个教程是我见过的最好的 "会得到高的积极情感分数。
  3. 对文本进行命名实体识别(NER)。命名实体是指文本中提到 "命名项目 "的元素,如人、组织、地点、时间、数量等。例如,"我在Shane Lynn的网站上读了这个帖子 "应该可以成功地提取出 "人。Shane Lynn"。
  4. 以JSON格式的响应返回所有这些分析的结果,可以在其他程序中使用。

Python库生态系统为上述每个步骤提供了工具包,大量减少了操作的复杂性。十年前,一个具有这种能力的玩具应用程序需要一个研究小组和几年的时间来建立--而你现在只需要不到100行的代码就可以做到。

库的选择 - FastAPI, Spacy, Flair

FastAPI NLP API示意图。本教程是建立一个API,使用FastAPI来处理包含文本段落的HTTP请求。该API向用户(或其他机器)回应所提交段落中检测到的情感和实体。Flair和Spacy被用来进行NLP处理。

网络应用程序框架。FastAPI

在本教程中,我们使用FastAPI框架来处理API的 "网络应用 "部分。这部分程序管理HTTP上的通信,我们在这里设置 "路由 "或 "路径",其他程序可以用它来向API发送文本。

FastAPI是一个相对较新的(2018年)Python的网络应用框架。它承诺提供一种快速启动但性能良好的方法来构建网络API,使大量的文档创建工作自动化。我特别喜欢FastAPI对参数验证的类型化使用,以及对异步操作符的方便使用(这样你就可以同时处理多个请求)。

这里还有其他的Web应用框架可以使用,都有优点和缺点,最明显的是Python中的Flask、Django、Cherrypi、Tornado等等--所有这些都可以在这个演示应用中使用。

情感分析。Flair

Flair是一个用于NLP的python框架。由柏林洪堡大学建造,Flair基本上整齐地包装了强大的NLP技术和单词嵌入模型 ,使用户可以通过几个简单的命令获得最先进的技术。对于那些对训练模型不感兴趣的人来说,Flair下载并安装了所有必要的东西,并在多种语言下工作。

我们几乎不打算用Flair来做表面文章,而是用一个模型进行情感分析。使用Flair,在Python中实现这一目的的代码非常简单。

"""
A simple demonstration of sentiment analysis using the Python Flair
library.

Shane Lynn 2021
"""

from flair.models import TextClassifier
from flair.data import Sentence

# For Flair, you load models in advance.
# Note that this is memory intensive and can take some time
sentiment_model = TextClassifier.load("en-sentiment")

# We're going to analyse these two texts for sentiment
sample_text = [
    "I love using Python to make really fast APIs.",
    "I hate silly bugs that happen and annoy me."
]

# Simply iterate through the samples, and run the prediction
for text in sample_text:
    # For Flair, you convert your raw data into "sentences" prior to analysis
    sentence = Sentence(text)
    # This is the analysis step, note that it edits the sentence to include the
    # prediction
    sentiment_model.predict(sentence)
    print(f"The sentence '{text}' is detected as {sentence.labels[0]}.")



这段代码应该输出。

The sentence 'I love using Python to make really fast APIs.' is detected as POSITIVE (0.9981).
The sentence 'I hate silly bugs that happen and annoy me.' is detected as NEGATIVE (0.9856).

Flair输出情感标签(正面/负面)以及预测的极性(声明的极化程度,在0和1之间)。

请记住,情感分析并不完美,因为它是基于一个可能与你的文本不太匹配的训练集;你会发现一些句子提供的结果与你期望的不一致。然而,我发现Flair "一般来说 "是相当好的。

命名实体识别。Spacy

我们拼图的最后一块将是命名实体识别。为此,我们使用了Spacy库,这是另一个用于NLP应用的python框架,它再次包装了预训练的模型,并使它们对开发者来说非常方便。Spacy是一个性能卓越且易于使用的库,它支持超过60种语言的NLP任务,如命名实体识别、部分语音标记、依赖性分析、句子分割、文本分类、词法等等。这是一个非常令人印象深刻的工具包,由一家名为Explosion的伟大公司建造。

Spacy的工作方式与Flair类似;你在将文本传递给它之前加载一个预先训练好的模型,然后再提取结果。

"""
A simple example showing Named-Entity Recognition (NER) with the Spacy
library in Python.

Shane Lynn 2021
"""

import spacy
nlp = spacy.load("en_core_web_sm")

# Here is a sample sentence with some entities:
sample_text = "I was walking down 5th Avenue yesterday in New York City and I saw Bill Gates!"

# For Spacy, first turn your raw text data into a "document":
doc = nlp(sample_text)
# The document then "magically" has everything calculated:
for entity in doc.ents:
    print(f"Entity Detected: {entity.text}, of type: {entity.label_}")

这个代码段应该输出。

Entity Detected: 5th Avenue, of type: FAC
Entity Detected: yesterday, of type: DATE
Entity Detected: New York City, of type: GPE
Entity Detected: Bill Gates, of type: PERSON

Spacy,开箱即用,支持以下实体类型。

  • PERSON
  • NORP (国籍/宗教/政治团体)
  • FAC(建筑物/街道/高速公路)
  • ORG (公司/机构)
  • GPE (地点/国家/城市)

请注意,我们可以在我们的API中使用Flair的NER功能 ,而不是Spacy,以达到简单和内存效率的目的(这个简单的应用程序将是非常密集的内存,因为我们正在加载两个语言模型 - 大约800MB - 1GB)。然而,为了演示,我想同时展示Spacy和Flair的操作。

包裹情绪和实体检测功能

为了保持简单,并使我们能够看到我们的API代码和我们的NLP代码之间的清晰划分,我们可以创建一个单一的函数,为我们的新应用程序完成NLP的重任。

以上面的实体提取和情感检测为例,我们可以创建一个组合,一次性完成所有工作。下面的代码段将接收文本到该函数,并通过Spacy和Flair模型运行它。

from typing import Tuple, List

from typing import Tuple, List
from flair.models import TextClassifier
from flair.data import Sentence
import spacy

nlp = spacy.load("en_core_web_sm")
sentiment_model = TextClassifier.load('en-sentiment')

def get_entities_and_sentiment(text: str) -> Tuple[dict, List[dict]]:
    """Parse a string, and determine sentiment polarity and entities contained within"""
    doc = nlp(text)
    entity_list = [
        {"name": x.text, "type": x.label_} for x in doc.ents
    ]
    sentence = Sentence(text)
    sentiment_model.predict(sentence)
    label = sentence.labels[0]
    sentiment = {'sentiment': label.value, 'polarity':label.score}
    return sentiment, entity_list


# Run a small test
if __name__ == '__main__':
    # We're testing if our sentiment and entity function is working correctly:
    result = get_entities_and_sentiment("I travelled to New York and I hated it.")
    print(result)
    

我们可以把这个新函数放在一个叫做get_entities_and_sentiment.py 的新文件中,我们可以在我们的API代码中导入,我们将在本教程的第二部分看到。

作为一个测试,单独运行这个文件,将输出。

>> python get_entities_and_sentiment.py

({'sentiment': 'NEGATIVE', 'polarity': 0.9999203681945801}, [{'name': 'New York', 'type': 'GPE'}])

将NLP代码添加到FastAPI应用程序中

下一步是将我们上面的文本处理功能集成到一个API中,也就是说,通过一个网络框架将功能暴露在互联网上。