自然语言处理②

举报
十八岁讨厌编程 发表于 2022/08/05 23:42:07 2022/08/05
【摘要】 文章目录 自然语言处理实战项目分析计算评论情感得分计算商品情感得分控制整体流程 自然语言处理实战 我们可以想象一种场景,在网络购物的时候,我们总要在多家电商平台上反复横跳,为的就是找到...

自然语言处理实战

我们可以想象一种场景,在网络购物的时候,我们总要在多家电商平台上反复横跳,为的就是找到价格更低、质量更好的产品。显然这个过程是繁杂耗时的,那么我们能不能通过人工智能来帮我们完成这个目标呢?

有需求便有市场。

如今,有越来越多的商家意识到了推荐的重要性,纷纷推出 智能推荐 服务。实现智能推荐的方式有很多,商业上运用相对成熟的有以下两种:

  • 第一种,寻找 类似商品。即根据你的历史记录,比如曾经浏览过的商品、曾经看过的视频,从软件提供的物品本身出发,给你推荐属性相似的物品。
  • 第二种,寻找 类似用户。即根据你的个人信息及使用习惯,为你绘制 用户画像,并从万千用户中,寻找画像与你类似的用户,把他们浏览过的商品、听过的歌曲推荐给你。

对于我们这类个人用户而言,显然无法获取其他用户的使用数据。不过我们可以另辟蹊径,分析 商品评论,寻找出最受消费者认可的商品,也就是评论整体的情感色彩更偏向积极的商品,达到智能推荐的效果。

接下来我们可以自己设计一个智能商品推荐系统

项目分析

商品推荐,自然离不开商品的评论数据。我已经事先帮你爬取了某平台上多种笔记本电脑的评论数据,并从中筛选出了一部分,转换成 Python 中的数据格式,放在 data.py 文件中:

# data.py
laptop_data = {
  '笔记本A': [
    '很薄,很重,外观漂亮。可惜就像大家说的,屏幕的分辨率不是很给力,另外电脑正面的材质还是比较容易收集指纹的。散热还不错。有一点很奇怪,第二次开机时由于不小心碰掉了电源,再开时,系统居然自己进行了重装还原。'
    # 其余评论省略
  ],
  '笔记本B': [
    '最失败的1次,笔记本买来后根本没法用,明明是本子问题,卖家非得说可能是快递和我们人为的,折腾好几天搭上不少时间和费用才能好,以后再也不在这店买了。'
    # 其余评论省略
  ],
  '笔记本C': [
    '绝对是便携的轻便本,配24G的SSD硬盘。不过启动速度感觉不出来快。1T的硬盘,8G的内存,配置还不错。颜色也还不错,键盘的手感确实非常不错,还带背光键盘,值得称赞下。感觉非常不爽的是整体没有硬盘/cap等状态指示灯,除去屏幕外只有一个电源的开机指示灯等。对习惯了靠硬盘闪烁判断是否死机的,肯定要适应一段时间。',
    # 其余评论省略
  ]
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

这个获得产品评论的过程,在实际应用中我们一般通过爬虫去获得

首先我们的第一想法:既然百度的情感倾向分析接口,一次可以容纳长度在 2048 字节以内(UTF-8 编码下约为 682 个汉字,GBK 编码下为 1024 个汉字)的文本,这些评论应该都没有超过此限度。并且百度情感倾向分析接口得到的情感极性标签都是数字,那我们直接把每条评论的情感极性标签加起来,作为该商品总得分。再找出得分最高的商品,不就行了?🤔️

慢着,让我们来设想一下极端情况:

  • A 商品有 10 条评论,每条评论的情感分类都是 1(中立),用上述方法计算,总得分为 10 分;
  • B 商品有 4 条评论,每条评论的情感得分都是 2(积极),用上述方法计算,总得分为 8 分;
  • 由于 A 商品总得分更好,因此计算机将认为,A 商品更受欢迎。

这显然与我们的直观感受相悖。虽然 A 得分高,但它的好评率是 0%;相反,B 得分稍低,但好评率为 100%。所以应当是 B 更受欢迎。

为了消除评论数量对最终结果的影响,我们可以选取 平均值 这一指标,用评论情感极性标签平均值作为最终的 商品情感得分。

在这里插入图片描述

此时 A 商品情感得分为 10 / 10 = 1 分,B 商品情感得分为 8 / 4 = 2 分,计算机将认为 B 商品更受欢迎。这就比较符合我们的认知了。

如此分析过程,也引发我们思考:用评论情感极性标签总和代表商品情感得分情况,是不科学的。那么简单地用情感极性标签来表示一条评论的情感得分,又是否科学呢?

我们可以找个例子一试便知:

# A 店铺评论
天啊,这家店也太太太好吃了吧!咖喱鱼蛋Q弹有嚼劲,咖喱香十足,虾皇饺外皮薄而韧,虾仁贼大,我一口差点没包下哈哈哈。还送了一小杯鸳鸯奶茶,爱了爱了!
# B 店铺评论
蒜蓉扇贝口感一般。不过整体还不错,下次再来。

  
 
  • 1
  • 2
  • 3
  • 4

比如对于机器来说,上面两条评论的情感倾向都是积极的,情感极性标签都是 2(积极),并没有区别:

# A 店铺评论情感分析结果
{
  'positive_prob': 0.999921,
  'confidence': 0.999825,
  'negative_prob': 7.86681e-05, # 此处为科学计数法,值为 0.0000786681
  'sentiment': 2
}
# B 店铺评论情感分析结果
{
  'positive_prob': 0.963015,
  'confidence': 0.917812,
  'negative_prob': 0.0369847,
  'sentiment': 2
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

但我们一眼就能看出,A 店铺的评论情感色彩较 B 店铺更浓。如果在某点评网站看到这样两条评价,相信有不少人会选择 A 店铺而不是 B 店铺。因此我们不能囫囵地把它当作整体来处理,否则很可能会稀释情感浓度。

解决这一问题的方法有很多。

由于百度 SDK 在正确分析文本情感倾向后,会返回积极概率、消极概率、情感极性标签和本次分类置信度。其中 积极概率 取值范围为 0~1,越靠近 1,说明该文本情感偏向积极的可能性越大。因此我们可以用积极概率与情感极性标签的乘积,表示整段评论的情感得分

在这里插入图片描述
此时 A 店铺评论情感得分为 0.999921 * 2 = 1.999842 分,B 店铺情感得分为 0.963015 * 2 = 1.92603 分,计算机便能辨别出来,A 店铺很可能是更受欢迎的。

如此一来,我们能得出智能推荐系统的整体流程:
在这里插入图片描述
可以看出,我们的智能推荐系统可以分为三大部分:

  • 计算评论情感得分
  • 计算商品情感得分
  • 控制整体流程

计算评论情感得分

我们将这一部分功能封装成函数 calc_comment_senti(),用来计算评论情感得分。它接受 1 个参数,表示需要处理的评论文本内容。

如果调用百度接口成功,会返回情感得分;如果调用失败,则会返回错误码和错误原因。

from aip import AipNlp

# 你的 App ID, API Key 及 Secret Key
APP_ID = ''
API_KEY = ''
SECRET_KEY = ''

client = AipNlp(APP_ID, API_KEY, SECRET_KEY)

def calc_comment_senti(comment):
  # 调用情感倾向分析接口
  r = client.sentimentClassify(comment)
  # 判断请求是否成功
  if r.get('error_code'):
    # 请求失败时,返回错误码和错误原因
    return r['error_code'], r['error_msg']
  else:
    # 请求成功时,返回评论情感得分
    # 评论情感得分 = 积极概率 * 情感极性标签
    item = r['items'][0]
    return item['positive_prob'] * item['sentiment']

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

计算商品情感得分

在项目分析环节我们知道,商品情感得分是评论情感得分的平均值。因此我们实际上需要完成的任务是遍历每条评论,调用 calc_comment_senti() 函数计算、累计评论情感得分,最终计算出评论情感得分平均值并返回。

在这里插入图片描述

我们把这部分功能抽象为 calc_product_senti() 函数:

def calc_product_senti(comments):
  sum_score = 0 # 用来累计得分
  for comment in comments:
    # 调用函数,计算单条评论情感得分
    comment_senti = calc_comment_senti(comment)
    # 若返回值为浮点数,表示分析成功;否则表示分析失败
    if type(comment_senti) == float:
      sum_score += comment_senti
    else:
      print('评论“{}...”分析失败,错误码:{},错误原因:{}'.format(
        comment[:5], comment_senti[0], comment_senti[1]
      ))
  # 返回商品情感得分
  return sum_score / len(comments)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

不过在这一个部分,我们要注意一个问题百度AI智能云平台提供给我们的接口有QPS限制。如果我们不间断的反复请求会得不到返回结果。所以这里我们要引入time模块,使用其中的sleep()方法来实现间断请求的要求。

sleep() 函数
它接受一个参数,单位为秒,表示需要暂停的时间。当我们调用函数 sleep(1) 时,计算机会暂停 1 秒,再继续执行后面的代码。

百度接口对每个接口的 QPS 限制是固定的,因此我们可以用 常量 QPS_LIMIT 来表示接口 QPS 限制,每当访问一次接口,便暂停 1 / QPS_LIMIT 秒,从而控制访问速度。一般情况下,我们为 QPS_LIMIT 赋值为 2 即可满足需要,不过保险起见,我们也可以延长暂停时间,赋值为 1.8、1.5 等等,使程序运行更加稳定。写成代码就是这样:

from aip import AipNlp
from time import sleep
from data import laptop_data

# 你的 App ID, API Key 及 Secret Key
APP_ID = ''
API_KEY = ''
SECRET_KEY = ''
# 该接口每秒最多可处理几条信息(query per second)
QPS_LIMIT = 2 # 可减小数值,提升程序稳定性

# 实例化 AipNlp 类,用以调用百度自然语言处理相关服务
client = AipNlp(APP_ID, API_KEY, SECRET_KEY)

# calc_comment_senti() 函数省略

def calc_product_senti(comments):
  sum_score = 0 # 用来累计得分
  for comment in comments:
    # 调用函数,计算单条评论情感得分
    comment_senti = calc_comment_senti(comment)
    sleep(1 / QPS_LIMIT) # 防止请求过快
    # 若返回值为浮点数,表示分析成功;否则表示分析失败
    if type(comment_senti) == float:
      sum_score += comment_senti
    else:
      print('评论“{}...”分析失败,错误码:{},错误原因:{}'.format(
        comment[:5], comment_senti[0], comment_senti[1]
      ))
  # 返回商品情感得分
  return sum_score / len(comments)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

控制整体流程

def recommend(data):
  # 定义变量 max_senti,用于保存当前最高商品情感得分
  max_senti = 0
  # 定义变量 recommend_pro,用于保存情感得分最高商品名
  recommend_pro = ''
  # 遍历 data 中每件商品
  for i in laptop_data:
    # 计算商品得分
    score = calc_product_senti(laptop_data[i])
    # 若该商品得分大于目前最高分
    if score > max_senti:
    	# 更新当前最高分
      max_senti = score
      # 记录商品名
      recommend_pro = i
  # 遍历结束,返回最终结果
  return max_senti,recommend_pro

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

最后我们整合以上的步骤,整体代码实现如下:

from aip import AipNlp
from time import sleep
from data import laptop_data

# 你的 App ID, API Key 及 Secret Key
APP_ID = 'xxxxx'
API_KEY = 'xxxxxxxxxxxxxxxxxxx'
SECRET_KEY = 'xxxxxxxxxxxxxxxxx'
# 该接口每秒最多可处理几条信息(query per second)
QPS_LIMIT = 2

# 实例化 AipNlp 类,用以调用百度自然语言处理相关服务
client = AipNlp(APP_ID, API_KEY, SECRET_KEY)

def calc_comment_senti(comment):
  # 调用情感倾向分析接口
  r = client.sentimentClassify(comment)
  # 判断请求是否成功
  if r.get('error_code'):
    # 请求失败时,返回错误码和错误原因
    return r['error_code'], r['error_msg']
  else:
    # 请求成功时,返回评论情感得分
    # 评论情感得分 = 积极概率 * 情感极性标签
    item = r['items'][0]
    return item['positive_prob'] * item['sentiment']

def calc_product_senti(comments):
  sum_score = 0 # 用来累计得分
  for comment in comments:
    # 调用函数,计算单条评论情感得分
    comment_senti = calc_comment_senti(comment)
    sleep(1 / QPS_LIMIT) # 防止请求过快
    # 若返回值为浮点数,表示分析成功;否则表示分析失败
    if type(comment_senti) == float:
      sum_score += comment_senti
    else:
      print('评论“{}...”分析失败,错误码:{},错误原因:{}'.format(
        comment[:5], comment_senti[0], comment_senti[1]
      ))
  # 返回商品情感得分
  return sum_score / len(comments)

# 请根据提示,完成函数 recommend()编写
def recommend(data):
  # 定义变量 max_senti,用于保存当前最高商品情感得分
  max_senti = 0
  # 定义变量 recommend_pro,用于保存情感得分最高商品名
  recommend_pro = ''
  # 遍历 data 中每件商品
  for i in laptop_data:
    # 计算商品得分
    score = calc_product_senti(laptop_data[i])
    # 若该商品得分大于目前最高分
    if score > max_senti:
    	# 更新当前最高分
      max_senti = score
      # 记录商品名
      recommend_pro = i
  # 遍历结束,返回最终结果
  return max_senti,recommend_pro

senti, product = recommend(laptop_data)
print('评价更好的商品是:{},得分为:{}'.format(product, senti))

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

文章来源: blog.csdn.net,作者:十八岁讨厌编程,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/zyb18507175502/article/details/124631567

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。