自然语言处理②
自然语言处理实战
我们可以想象一种场景,在网络购物的时候,我们总要在多家电商平台上反复横跳,为的就是找到价格更低、质量更好的产品。显然这个过程是繁杂耗时的,那么我们能不能通过人工智能来帮我们完成这个目标呢?
有需求便有市场。
如今,有越来越多的商家意识到了推荐的重要性,纷纷推出 智能推荐
服务。实现智能推荐的方式有很多,商业上运用相对成熟的有以下两种:
- 第一种,寻找
类似商品
。即根据你的历史记录,比如曾经浏览过的商品、曾经看过的视频,从软件提供的物品本身出发,给你推荐属性相似的物品。 - 第二种,寻找
类似用户
。即根据你的个人信息及使用习惯,为你绘制用户画像
,并从万千用户中,寻找画像与你类似的用户,把他们浏览过的商品、听过的歌曲推荐给你。
对于我们这类个人用户而言,显然无法获取其他用户的使用数据。不过我们可以另辟蹊径,分析 商品评论
,寻找出最受消费者认可的商品,也就是评论整体的情感色彩更偏向积极的商品,达到智能推荐的效果。
接下来我们可以自己设计一个智能商品推荐系统
项目分析
商品推荐,自然离不开商品的评论数据。我已经事先帮你爬取了某平台上多种笔记本电脑的评论数据,并从中筛选出了一部分,转换成 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
- 点赞
- 收藏
- 关注作者
评论(0)