经验:Serverless 与自然语言处理的结合实战

优采云 发布时间: 2022-09-29 11:16

  经验:Serverless 与自然语言处理的结合实战

  文本自动摘要的提取和关键词的提取属于自然语言处理的范畴。提取摘要的一个好处是,读者可以通过最少的信息来判断这个文章对他们是否有意义或有价值,以及是否需要更详细地阅读;提取关键词的好处是文章和文章之间的关联也可以让读者通过关键词快速定位到关键词相关的文章内容@>。

  文本摘要和关键词提取都可以与传统的cms结合,通过改造文章/news等发布功能,同步提取关键词和摘要,放置在 HTML 页面中作为描述和关键字。这样做在一定程度上有利于搜索引擎收录,属于SEO优化的范畴。

  关键词提取

  关键词提取方法有很多种,但最常用的应该是tf-idf。

  jieba实现基于tf-idf关键词提取的方法:

  jieba.analyse.extract_tags(text, topK=5, withWeight=False, allowPOS=('n', 'vn', 'v'))

  文字摘要

  文本摘要的方法也有很多,如果从广义上划分,包括提取和生成。其中,提取的方法是找到关键句子,然后通过文章中的TextRank等算法将其组装成摘要。这种方法比较简单,但是很难提取出真正的语义;另一种方法是生成方法,通过深度学习等方法提取文本的语义并生成摘要。

  如果简单理解的话,提取方法生成的摘要,所有句子都来自原文,而生成方法是独立生成的。

  为了简化难度,本文将采用抽取的方式实现文本摘要功能,通过SnowNLP第三方库实现基于TextRank的文本摘要功能。我们使用《海底两万里》的部分内容作为原文生成摘要:

  原来的:

  当这些事件发生时,我刚从美国内布拉斯加州贫瘠地区的一次科学考察回来。我当时是巴黎自然历史博物馆的客座教授,法国政府派我参加这次考察。我在内布拉斯加州呆了半年,采集了很多珍贵的材料,满载而归,三月底抵达纽约。我决定五月初去法国。于是,我抓紧了等船整理采集到的矿物和动植物标本的时间,可就在这时,斯科舍却出事了。

  那时的街头话我都知道,而且,我怎么能听而不听,或者无动于衷呢?我读遍了美国和欧洲的各种报纸,但一直没能弄清真相。神秘莫测。我想了想,在两个极端之间摇摆不定,但始终没有给出意见。里面肯定有什么,这是毫无疑问的,如果有人有任何疑问,就让他们去摸一下斯科舍的伤口。

  当我到达纽约时,这个问题正在全面展开。一些无知无知的人提出了想法,有人说是浮岛,有人说是难以捉摸的礁石,但这些假设都被推翻了。显然,除非礁腹有机械,否则怎么可能移动得这么快?

  同样的,说它是一个漂浮的船体或一堆大船碎片也不成立。原因仍然是它发展得太快了。

  那么,这个问题只能有两种解释。人们各持己见,自然而然地分成了截然不同的两组:一组说这是一个强大的怪物,另一组说这是一艘非常强大的“潜水船”。

  哦,最后一个假设当然是可以接受的,但是经过欧美的调查,很难证明它的合理性。哪个普通人会有这么强大的机器?这是不可能的。他是在何时何地告诉谁来制造这样一个庞然大物的,他又如何在施工过程中隐瞒这个消息?

  似乎只有政府才有可能拥有这样一台破坏性的机器。在这个灾难性的时代,人们千方百计增加战争武器的威力。有可能一个国家试图在其他国家不知情的情况下制造这种骇人听闻的武器。武器。Shaspo步*敏*感*词*之后是地雷,地雷之后是水下公羊。至少,我是这么认为的。

  SnowNLP 提供的算法:

  from snownlp import SnowNLP

text = " 上面的原文内容,此处省略 "

s = SnowNLP(text)

print("。".join(s.summary(5)))

  输出结果:

  自然就分成观点截然不同的两派:一派说这是一个力大无比的怪物。这种假设也不能成立。我到纽约时。说它是一块浮动的船体或是一堆大船残片。另一派说这是一艘动力极强的“潜水船”

  乍一看,效果不是很好。接下来,我们自己计算句子权重,实现一个简单的汇总函数。这需要jieba:

  import re

import jieba.analyse

import jieba.posseg

class TextSummary:

def __init__(self, text):

self.text = text

def splitSentence(self):

sectionNum = 0

self.sentences = []

for eveSection in self.text.split("\n"):

if eveSection:

sentenceNum = 0

for eveSentence in re.split("!|。|?", eveSection):

if eveSentence:

mark = []

if sectionNum == 0:

mark.append("FIRSTSECTION")

if sentenceNum == 0:

mark.append("FIRSTSENTENCE")

self.sentences.append({

"text": eveSentence,

"pos": {

"x": sectionNum,

"y": sentenceNum,

"mark": mark

}

})

sentenceNum = sentenceNum + 1

sectionNum = sectionNum + 1

self.sentences[-1]["pos"]["mark"].append("LASTSENTENCE")

for i in range(0, len(self.sentences)):

if self.sentences[i]["pos"]["x"] == self.sentences[-1]["pos"]["x"]:

self.sentences[i]["pos"]["mark"].append("LASTSECTION")

def getKeywords(self):

self.keywords = jieba.analyse.extract_tags(self.text, topK=20, withWeight=False, allowPOS=('n', 'vn', 'v'))

def sentenceWeight(self):

# 计算句子的位置权重

for sentence in self.sentences:

mark = sentence["pos"]["mark"]

weightPos = 0

if "FIRSTSECTION" in mark:

weightPos = weightPos + 2

if "FIRSTSENTENCE" in mark:

weightPos = weightPos + 2

if "LASTSENTENCE" in mark:

weightPos = weightPos + 1

if "LASTSECTION" in mark:

weightPos = weightPos + 1

sentence["weightPos"] = weightPos

# 计算句子的线索词权重

index = [" 总之 ", " 总而言之 "]

for sentence in self.sentences:

sentence["weightCueWords"] = 0

sentence["weightKeywords"] = 0

for i in index:

for sentence in self.sentences:

if sentence["text"].find(i) >= 0:

sentence["weightCueWords"] = 1

for keyword in self.keywords:

for sentence in self.sentences:

if sentence["text"].find(keyword) >= 0:

<p>

sentence["weightKeywords"] = sentence["weightKeywords"] + 1

for sentence in self.sentences:

sentence["weight"] = sentence["weightPos"] + 2 * sentence["weightCueWords"] + sentence["weightKeywords"]

def getSummary(self, ratio=0.1):

self.keywords = list()

self.sentences = list()

self.summary = list()

# 调用方法,分别计算关键词、分句,计算权重

self.getKeywords()

self.splitSentence()

self.sentenceWeight()

# 对句子的权重值进行排序

self.sentences = sorted(self.sentences, key=lambda k: k[&#39;weight&#39;], reverse=True)

# 根据排序结果,取排名占前 ratio% 的句子作为摘要

for i in range(len(self.sentences)):

if i < ratio * len(self.sentences):

sentence = self.sentences[i]

self.summary.append(sentence["text"])

return self.summary

</p>

  这段代码主要是通过tf-idf实现关键词提取,然后通过关键词提取给句子赋权重,最后得到整体结果,运行:

  testSummary = TextSummary(text)

print("。".join(testSummary.getSummary()))

  你可以得到结果:

  Building prefix dict from the default dictionary ...

Loading model from cache /var/folders/yb/wvy_7wm91mzd7cjg4444gvdjsglgs8/T/jieba.cache

Loading model cost 0.721 seconds.

Prefix dict has been built successfully.

看来,只有政府才有可能拥有这种破坏性的机器,在这个灾难深重的时代,人们千方百计要增强战争武器威力,那就有这种可能,一个国家瞒着其他国家在试制这类骇人听闻的武器。于是,我就抓紧这段候船逗留时间,把收集到的矿物和动植物标本进行分类整理,可就在这时,斯科舍号出事了。同样的道理,说它是一块浮动的船体或是一堆大船残片,这种假设也不能成立,理由仍然是移动速度太快

  我们可以看到,整体效果比刚才要好。

  发布 API

  通过 serverless 架构,将上述代码组织和发布。

  代码整理结果:

  import re, json

import jieba.analyse

import jieba.posseg

class NLPAttr:

def __init__(self, text):

self.text = text

def splitSentence(self):

sectionNum = 0

self.sentences = []

for eveSection in self.text.split("\n"):

if eveSection:

sentenceNum = 0

for eveSentence in re.split("!|。|?", eveSection):

if eveSentence:

mark = []

if sectionNum == 0:

mark.append("FIRSTSECTION")

if sentenceNum == 0:

mark.append("FIRSTSENTENCE")

self.sentences.append({

"text": eveSentence,

"pos": {

"x": sectionNum,

"y": sentenceNum,

"mark": mark

}

})

sentenceNum = sentenceNum + 1

sectionNum = sectionNum + 1

self.sentences[-1]["pos"]["mark"].append("LASTSENTENCE")

for i in range(0, len(self.sentences)):

if self.sentences[i]["pos"]["x"] == self.sentences[-1]["pos"]["x"]:

self.sentences[i]["pos"]["mark"].append("LASTSECTION")

def getKeywords(self):

self.keywords = jieba.analyse.extract_tags(self.text, topK=20, withWeight=False, allowPOS=(&#39;n&#39;, &#39;vn&#39;, &#39;v&#39;))

return self.keywords

def sentenceWeight(self):

# 计算句子的位置权重

for sentence in self.sentences:

mark = sentence["pos"]["mark"]

weightPos = 0

if "FIRSTSECTION" in mark:

weightPos = weightPos + 2

if "FIRSTSENTENCE" in mark:

weightPos = weightPos + 2

if "LASTSENTENCE" in mark:

weightPos = weightPos + 1

if "LASTSECTION" in mark:

weightPos = weightPos + 1

sentence["weightPos"] = weightPos

<p>

# 计算句子的线索词权重

index = [" 总之 ", " 总而言之 "]

for sentence in self.sentences:

sentence["weightCueWords"] = 0

sentence["weightKeywords"] = 0

for i in index:

for sentence in self.sentences:

if sentence["text"].find(i) >= 0:

sentence["weightCueWords"] = 1

for keyword in self.keywords:

for sentence in self.sentences:

if sentence["text"].find(keyword) >= 0:

sentence["weightKeywords"] = sentence["weightKeywords"] + 1

for sentence in self.sentences:

sentence["weight"] = sentence["weightPos"] + 2 * sentence["weightCueWords"] + sentence["weightKeywords"]

def getSummary(self, ratio=0.1):

self.keywords = list()

self.sentences = list()

self.summary = list()

# 调用方法,分别计算关键词、分句,计算权重

self.getKeywords()

self.splitSentence()

self.sentenceWeight()

# 对句子的权重值进行排序

self.sentences = sorted(self.sentences, key=lambda k: k[&#39;weight&#39;], reverse=True)

# 根据排序结果,取排名占前 ratio% 的句子作为摘要

for i in range(len(self.sentences)):

if i < ratio * len(self.sentences):

sentence = self.sentences[i]

self.summary.append(sentence["text"])

return self.summary

def main_handler(event, context):

nlp = NLPAttr(json.loads(event[&#39;body&#39;])[&#39;text&#39;])

return {

"keywords": nlp.getKeywords(),

"summary": "。".join(nlp.getSummary())

}</p>

  编写项目 serverless.yaml 文件:

  nlpDemo:

component: "@serverless/tencent-scf"

inputs:

name: nlpDemo

codeUri: ./

handler: index.main_handler

runtime: Python3.6

region: ap-guangzhou

description: 文本摘要 / 关键词功能

memorySize: 256

timeout: 10

events:

- apigw:

name: nlpDemo_apigw_service

parameters:

protocols:

- http

serviceName: serverless

description: 文本摘要 / 关键词功能

environment: release

endpoints:

- path: /nlp

method: ANY

  由于项目中使用了jieba,所以安装时建议安装在CentOS系统和对应的Python版本下,也可以使用我之前为方便制作的依赖工具:

  通过 sls --debug 部署:

  部署完成,可以通过PostMan进行一个简单的测试:

  从上图中可以看出,我们已经按预期输出了目标结果。至此,文本摘要/关键词提取的API已经部署完毕。

  总结

  相对而言,通过Serveless架构做一个API是非常简单方便的,可以实现API的可插拔和组件化。希望这篇文章能给读者更多的思路和启发。

  无服务器框架 30 天试用计划

  我们邀请您体验最便捷的无服务器开发和部署方式。试用期内,相关产品和服务提供免费资源和专业技术支持,帮助您的企业快速轻松实现Serverless!

  无服务器部署只需三步

  Serverless Framework 是一个用于构建和操作无服务器应用程序的框架。只需三个简单的步骤,您就可以通过 Serverless Framework 快速实现服务部署。

  1. 安装无服务器

  macOS/Linux系统:推荐二进制安装

  $ curl -o- -L https://slss.io/install | bash

  Windows 系统:可以通过 npm 安装

  $ npm install -g serverless

  2. 创建云应用

  在空文件夹中输入 `serverless` 命令

  $ serverless

  按照命令行中的链接输出访问成功部署的应用程序。

  3. 查看部署信息

  进入部署成功的文件夹,运行以下命令查看部署状态和资源信息:

  $ sls info

  专业知识:seo优化要掌握这些基础知识

  SEO优化并不难,只要掌握相应的基础知识,就能提升网站的排名。那么SEO优化的基础是什么?今天,seo知识网就为大家介绍一下。

  1、网站代码基础

  虽然seo优化不需要精通代码,但还是需要了解一些基础知识。要知道哪些代码有利于优化,基本的东西怎么修改,背景图片颜色,文字大小,alt属性,网站的h标签设置等等,都需要一定的网站 代码基础知识。

  

  2、网站seo优化基础

  网站seo优化细节工作量很大,要懂得分析网站竞争对手的情况,做好网站tdk设置,关键词布局,内部链布局、结构优化调整等,这些都需要掌握网站seo优化的基础知识才能做好。

  3、网站外链优化

  网站分为站内优化和站外优化。除了做好站内优化,还需要掌握站外优化技巧,懂得交换友好链接,有外链发​​布渠道,利用外链提速网站 @网站排名和权重改进。

  

  4、网站seo工具的应用

  做seo优化需要掌握一些seo工具,帮助我们更好的分析网站情况,分析用户访问等,比如百度统计、站长平台、站长工具等。

  以上就是【seo优化掌握这些基础知识】的介绍,希望对大家有所帮助。想了解更多seo优化的可以关注和采集我们的seo知识网,会不定期更新网站建设、seo优化、网站优化方案、seo工具、seo外包、网络推广等方面的知识,供大家参考和理解。

  期待你的

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线