Python 全栈体系【四阶】(六十一)

第五章 深度学习

十三、自然语言处理(NLP)

5. NLP应用

5.2 文本情感分析

目标:利用训练数据集,对模型训练,从而实现对中文评论语句情感分析。情绪分为正面、负面两种

数据集:中文关于酒店的评论,5265笔用户评论数据,其中2822笔正面评价、其余为负面评价

步骤:同上一案例

模型选择:

在这里插入图片描述

代码:

【数据预处理】

# 中文情绪分析:数据预处理部分
import paddle
import paddle.dataset.imdb as imdb
import paddle.fluid as fluid
import numpy as np
import os
import random
from multiprocessing import cpu_count

# 数据预处理,将中文文字解析出来,并进行编码转换为数字,每一行文字存入数组
mydict = {}  # 存放出现的字及编码,格式: 好,1
code = 1
data_file = "data/hotel_discuss2.csv"  # 原始样本路径
dict_file = "data/hotel_dict.txt" # 字典文件路径
encoding_file = "data/hotel_encoding.txt" # 编码后的样本文件路径
puncts = " \n"  # 要剔除的标点符号列表

with open(data_file, "r", encoding="utf-8-sig") as f:
    for line in f.readlines():
        # print(line)
        trim_line = line.strip()
        for ch in trim_line:
            if ch in puncts:  # 符号不参与编码
                continue

            if ch in mydict:  # 已经在编码字典中
                continue
            elif len(ch) <= 0:
                continue
            else:  # 当前文字没在字典中
                mydict[ch] = code
                code += 1
    code += 1
    mydict["<unk>"] = code  # 未知字符

# 循环结束后,将字典存入字典文件
with open(dict_file, "w", encoding="utf-8-sig") as f:
    f.write(str(mydict))
    print("数据字典保存完成!")


# 将字典文件中的数据加载到mydict字典中
def load_dict():
    with open(dict_file, "r", encoding="utf-8-sig") as f:
        lines = f.readlines()
        new_dict = eval(lines[0])
    return new_dict

# 对评论数据进行编码
new_dict = load_dict()  # 调用函数加载
with open(data_file, "r", encoding="utf-8-sig") as f:
    with open(encoding_file, "w", encoding="utf-8-sig") as fw:
        for line in f.readlines():
            label = line[0]  # 标签
            remark = line[1:-1]  # 评论

            for ch in remark:
                if ch in puncts:  # 符号不参与编码
                    continue
                else:
                    fw.write(str(mydict[ch]))
                    fw.write(",")
            fw.write("\t" + str(label) + "\n")  # 写入tab分隔符、标签、换行符

print("数据预处理完成")

【模型定义与训练】

# 获取字典的长度
def get_dict_len(dict_path):
    with open(dict_path, 'r', encoding='utf-8-sig') as f:
        lines = f.readlines()
        new_dict = eval(lines[0])

    return len(new_dict.keys())

# 创建数据读取器train_reader和test_reader
# 返回评论列表和标签
def data_mapper(sample):
    dt, lbl = sample
    val = [int(word) for word in dt.split(",") if word.isdigit()]
    return val, int(lbl)

# 随机从训练数据集文件中取出一行数据
def train_reader(train_list_path):
    def reader():
        with open(train_list_path, "r", encoding='utf-8-sig') as f:
            lines = f.readlines()
            np.random.shuffle(lines)  # 打乱数据

            for line in lines:
                data, label = line.split("\t")
                yield data, label

    # 返回xmap_readers, 能够使用多线程方式读取数据
    return paddle.reader.xmap_readers(data_mapper,  # 映射函数
                                      reader,  # 读取数据内容
                                      cpu_count(),  # 线程数量
                                      1024)  # 读取数据队列大小

# 定义LSTM网络
def lstm_net(ipt, input_dim):
    ipt = fluid.layers.reshape(ipt, [-1, 1],
                               inplace=True) # 是否替换,True则表示输入和返回是同一个对象
    # 词嵌入层
    emb = fluid.layers.embedding(input=ipt, size=[input_dim, 128], is_sparse=True)

    # 第一个全连接层
    fc1 = fluid.layers.fc(input=emb, size=128)

    # 第一分支:LSTM分支
    lstm1, _ = fluid.layers.dynamic_lstm(input=fc1, size=128)
    lstm2 = fluid.layers.sequence_pool(input=lstm1, pool_type="max")

    # 第二分支
    conv = fluid.layers.sequence_pool(input=fc1, pool_type="max")

    # 输出层:全连接
    out = fluid.layers.fc([conv, lstm2], size=2, act="softmax")

    return out

# 定义输入数据,lod_level不为0指定输入数据为序列数据
dict_len = get_dict_len(dict_file)  # 获取数据字典长度
rmk = fluid.layers.data(name="rmk", shape=[1], dtype="int64", lod_level=1)
label = fluid.layers.data(name="label", shape=[1], dtype="int64")

# 定义长短期记忆网络
model = lstm_net(rmk, dict_len)

# 定义损失函数,情绪判断实际是一个分类任务,使用交叉熵作为损失函数
cost = fluid.layers.cross_entropy(input=model, label=label)
avg_cost = fluid.layers.mean(cost)  # 求损失值平均数
# layers.accuracy接口,用来评估预测准确率
acc = fluid.layers.accuracy(input=model, label=label)

# 定义优化方法
# Adagrad(自适应学习率,前期放大梯度调节,后期缩小梯度调节)
optimizer = fluid.optimizer.AdagradOptimizer(learning_rate=0.001)
opt = optimizer.minimize(avg_cost)

# 定义网络
# place = fluid.CPUPlace()
place = fluid.CUDAPlace(0)
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())  # 参数初始化

# 定义reader
reader = train_reader(encoding_file)
batch_train_reader = paddle.batch(reader, batch_size=128)

# 定义输入数据的维度,数据的顺序是一条句子数据对应一个标签
feeder = fluid.DataFeeder(place=place, feed_list=[rmk, label])

for pass_id in range(40):
    for batch_id, data in enumerate(batch_train_reader()):
        train_cost, train_acc = exe.run(program=fluid.default_main_program(),
                                        feed=feeder.feed(data),
                                        fetch_list=[avg_cost, acc])

        if batch_id % 20 == 0:
            print("pass_id: %d, batch_id: %d, cost: %0.5f, acc:%.5f" %
                  (pass_id, batch_id, train_cost[0], train_acc))

print("模型训练完成......")

# 保存模型
model_save_dir = "model/chn_emotion_analyses.model"
if not os.path.exists(model_save_dir):
    print("create model path")
    os.makedirs(model_save_dir)

fluid.io.save_inference_model(model_save_dir,  # 保存路径
                              feeded_var_names=[rmk.name],
                              target_vars=[model],
                              executor=exe)  # Executor

print("模型保存完成, 保存路径: ", model_save_dir)

【推理预测】

import paddle
import paddle.fluid as fluid
import numpy as np
import os
import random
from multiprocessing import cpu_count

data_file = "data/hotel_discuss2.csv"
dict_file = "data/hotel_dict.txt"
encoding_file = "data/hotel_encoding.txt"
model_save_dir = "model/chn_emotion_analyses.model"

def load_dict():
    with open(dict_file, "r", encoding="utf-8-sig") as f:
        lines = f.readlines()
        new_dict = eval(lines[0])
        return new_dict

# 根据字典对字符串进行编码
def encode_by_dict(remark, dict_encoded):
    remark = remark.strip()
    if len(remark) <= 0:
        return []

    ret = []
    for ch in remark:
        if ch in dict_encoded:
            ret.append(dict_encoded[ch])
        else:
            ret.append(dict_encoded["<unk>"])

    return ret


# 编码,预测
lods = []
new_dict = load_dict()
lods.append(encode_by_dict("总体来说房间非常干净,卫浴设施也相当不错,交通也比较便利", new_dict))
lods.append(encode_by_dict("酒店交通方便,环境也不错,正好是我们办事地点的旁边,感觉性价比还可以", new_dict))
lods.append(encode_by_dict("设施还可以,服务人员态度也好,交通还算便利", new_dict))
lods.append(encode_by_dict("酒店服务态度极差,设施很差", new_dict))
lods.append(encode_by_dict("我住过的最不好的酒店,以后决不住了", new_dict))
lods.append(encode_by_dict("说实在的我很失望,我想这家酒店以后无论如何我都不会再去了", new_dict))

# 获取每句话的单词数量
base_shape = [[len(c) for c in lods]]

# 生成预测数据
place = fluid.CPUPlace()
infer_exe = fluid.Executor(place)
infer_exe.run(fluid.default_startup_program())

tensor_words = fluid.create_lod_tensor(lods, base_shape, place)

infer_program, feed_target_names, fetch_targets = fluid.io.load_inference_model(dirname=model_save_dir, executor=infer_exe)
# tvar = np.array(fetch_targets, dtype="int64")
results = infer_exe.run(program=infer_program,
                  feed={feed_target_names[0]: tensor_words},
                  fetch_list=fetch_targets)

# 打印每句话的正负面预测概率
for i, r in enumerate(results[0]):
    print("负面: %0.5f, 正面: %0.5f" % (r[0], r[1]))

6. 附录

6.1 附录一:相关数学知识

向量余弦相似度

余弦相似度使用来度量向量相似度的指标,当两个向量夹角越大相似度越低;当两个向量夹角越小,相似度越高。

在这里插入图片描述

在三角形中,余弦值计算方式为 c o s θ = a 2 + b 2 − c 2 2 a b cos \theta = \frac{a^2 + b^2 - c^2}{2ab} cosθ=2aba2+b2c2,向量夹角余弦计算公式为:

c o s θ = a b ∣ ∣ a ∣ ∣ × ∣ ∣ b ∣ ∣ cos \theta = \frac{ab}{||a|| \times ||b||} cosθ=∣∣a∣∣×∣∣b∣∣ab

分子为两个向量的内积,分母是两个向量模长的乘积。

在这里插入图片描述

其推导过程如下:

c o s θ = a 2 + b 2 − c 2 2 a b = x 1 2 + y 1 2 + x 2 2 + y 2 2 + ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 2 x 1 2 + y 1 2 x 2 2 + y 2 2 = 2 x 1 x 2 + 2 y 1 y 2 2 x 1 2 + y 1 2 x 2 2 + y 2 2 = a b ∣ ∣ a ∣ ∣ × ∣ ∣ b ∣ ∣ cos \theta = \frac{a^2 + b^2 - c^2}{2ab} \\ = \frac{\sqrt{x_1^2 + y_1^2} + \sqrt{x_2^2 + y_2^2 }+ \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2}}{2 \sqrt{x_1^2 + y_1^2} \sqrt{x_2^2 + y_2^2}} \\ = \frac{2 x_1 x_2 + 2 y_1 y_2}{2 \sqrt{x_1^2 + y_1^2} \sqrt{x_2^2 + y_2^2}} = \frac{ab}{||a|| \times ||b||} cosθ=2aba2+b2c2=2x12+y12 x22+y22 x12+y12 +x22+y22 +(x1x2)2+(y1y2)2 =2x12+y12 x22+y22 2x1x2+2y1y2=∣∣a∣∣×∣∣b∣∣ab

以上是二维向量的计算过程,推广到N维向量,分子部分依然是向量的内积,分母部分依然是两个向量模长的乘积。由此可计算文本的余弦相似度。

6.2 附录二:参考文献

1)《Python自然语言处理实践——核心技术与算法》 ,涂铭、刘祥、刘树春 著 ,机械工业出版社

2)《Tensorflow自然语言处理》,【澳】图珊·加内格达拉,机械工业出版社

3)《深度学习之美》,张玉宏,中国工信出版集团 / 电子工业出版社

4)网络部分资源

6.3 附录三:专业词汇列表
英文简写英文全写中文
NLPNature Language Processing自然语言处理
NERNamed Entities Recognition命名实体识别
PoSpart-of-speech tagging词性标记
MTMachine Translation机器翻译
TF-IDFTerm Frequency-Inverse Document Frequency词频-逆文档频率
Text Rank文本排名算法
One-hot独热编码
BOWBag-of-Words Model词袋模型
N-GramN元模型
word embedding词嵌入
NNLMNeural Network Language Model神经网络语言模型
HMMHidden Markov Model隐马尔可夫模型
RNNRecurrent Neural Networks循环神经网络
Skip-gram跳字模型
CBOWContinous Bag of Words连续词袋模型
LSTMLong Short Term Memory长短期记忆模型
GRUGated Recurrent Unit门控环单元
BRNNBi-recurrent neural network双向循环神经网络
FMMForward Maximum Matching正向最大匹配
RMMReverse Maximum Matching逆向最大匹配
Bi-MMBi-directional Maximum Matching双向最大匹配法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/744114.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Orangepi Zero2 全志H616 的初识

目录 一、全志H616简介 1.1 为什么学&#xff1a; 1.2 学什么&#xff1a; 1.3 全志H616平台介绍&#xff1a; 二、刷机 系统启动和初始化配置 2.1 需要的工具&#xff1a; 2.2 工具安装&#xff1a; 2.3 刷机&#xff1a; 2.4 登录系统&#xff1a; 2.5 修改登录密码…

2024年世界移动大会(MWC Shanghai)——飞睿智能诚邀您,超宽带技术定位测距传输全家桶

超宽带UWB芯片SIP系列&#xff1a; FS100 FS200 超宽带UWB标签系列&#xff1a; FU3620-2 FUP410-1 超宽带UWB应用系列&#xff1a; FMFB200A&#xff08;门锁方案&#xff09; FU2625-2&#xff08;TAG方案&#xff09; FPDB200A&#xff08;音频&#xff09; FSTB200…

emqx4.4.3关于如何取消匿名登录,添加认证用户这件事

emqx4.4.3如何取消匿名登录&#xff0c;添加认证用户 emqx版本&#xff1a;4.4.3 背景&#xff1a;使用docker搭建完emqx后&#xff0c;使用 MQTTX 连接总是超时&#xff1a; 检查Java项目 是否有接口&#xff1a;https://XXXX:80/mqtt/auth? 若有&#xff0c;则具体逻辑查询…

MAB规范(3):Chapter6 Glossary 术语表

第6章 - 术语表 此章不做过多的批注&#xff0c;都是些简单的术语解释。

电机故障检测系统的通用性限制分析

电机故障检测系统因应用环境、功能需求、经济性等多方面差异而难以实现通用。工厂与实验室在环境条件、使用频率、功能需求、成本、维护及数据处理方面有显著不同&#xff0c;此外&#xff0c;LabVIEW软件在两者中的应用和数据处理也存在差异&#xff0c;这进一步限制了系统的通…

Android app Java层异常捕获方案

背景: 在Android app运行中,有时一些无关紧要的异常出现时希望App 不崩溃,能继续让用户操作,可以有效提升用户体验和增加业务价值。 新流程: 哪些场景需要Catch Crash Config配置信息: 支持从网络上获取Crash配置表,动态防护,避免crash。 使用: 在Application o…

汽车零部件制造企业如何选择合适的ESOP电子作业指导书系统

随着汽车产业的不断发展&#xff0c;汽车零部件制造企业在提高生产效率和产品质量方面面临着越来越大的挑战。为了解决这些问题&#xff0c;越来越多的汽车零部件制造企业开始采用ESOP电子作业指导书系统&#xff0c;以帮助他们管理和优化生产流程。但是&#xff0c;在选择合适…

Retrofit类型安全的HTTP客户端库(json)

简介 Retrofit是Square公司开发的一个类型安全的HTTP客户端库&#xff0c;用于Android和Java平台&#xff0c;它使得与Web服务的交互变得更加简单快捷。Retrofit将HTTP API转换成Java接口&#xff0c;让你可以用更简洁的代码形式调用RESTful API&#xff0c;Android网络编程重点…

机器学习之数学基础(七)~过拟合(over-fitting)和欠拟合(under-fitting)

目录 1. 过拟合与欠拟合 1.1 Preliminary concept 1.2 过拟合 over-fitting 1.3 欠拟合 under-fitting 1.4 案例解析&#xff1a;黑天鹅 1. 过拟合与欠拟合 1.1 Preliminary concept 误差 经验误差&#xff1a;模型对训练集数据的误差。泛化误差&#xff1a;模型对测试…

你还不知道Modbus RTU???

1. 什么是Modbus RTU Modbus RTU&#xff08;Remote Terminal Unit&#xff09;是Modbus通信协议的一种变种&#xff0c;用于串行通信。它是一种常见的工业控制系统通信协议&#xff0c;通常用于采集传感器数据、控制执行器和监控设备状态。Modbus RTU采用二进制编码&#xff0…

ChatBI开源实现: 基于SuperSonic的AI+BI的产品设计

产品起源 为什么要做这样的产品&#xff1f;文章《ChatBI开源实现: AIBI的产品设计》中有介绍 为什么要自己做这样的产品&#xff1f;1、低成本试错&#xff1b;2、未来数据生态入口&#xff1b; 为什么要基于Supersonic做&#xff1f; 开源协议友好&#xff1a;可魔改商用 社区…

# Kafka_深入探秘者(6):kafka 物理存储

Kafka_深入探秘者&#xff08;6&#xff09;&#xff1a;kafka 物理存储 一、kafka 存储结构 1、kafka 存储结构概述图 2、kafka 存储结构概述 每一个 partion (文件夹)相当于一个巨型文件被平均分配,到多个大小相等 segment(段) 数据文件里。但每一个段 segment file 消息数…

上海计算机学会2020年3月月赛C++丙组T4连乘问题

题目描述 给定 a1​,a2​,⋯,an​&#xff0c;请计算一组乘积&#xff0c;记为P1​,P2​,⋯,Pn​&#xff0c;其中 Pi​ 的定义如下&#xff1a; 也就是说&#xff0c;Pi​ 是 a1​ 到 an​ 的连乘再除去 ai​。由于答案可能比较大&#xff0c;输出每个 Pi​ 模 10000 的余数。…

第六十七:iview的select组件在页面上,下拉数据被遮挡

iview的select组件在页面上&#xff0c;下拉数据被遮挡 加上**:transfer"true"** 代码截图&#xff1a; 官方解说截图&#xff1a;因为默认值是false 所以要改成:transfer“true”

PPT的精细化优化与提升策略

&#x1f44f;&#x1f44f;&#x1f44f;欢迎来到我的博客 ! 亲爱的朋友们&#xff0c;欢迎您们莅临我的博客&#xff01;这是一个分享知识、交流想法、记录生活的温馨角落。在这里&#xff0c;您可以找到我对世界独特视角的诠释&#xff0c;也可以与我一起探讨各种话题&#…

STL——常用算法(二)

一、常用拷贝和替换算法 1.copy #include <iostream> #include <vector> #include <algorithm> using namespace std; void printVector(int val) {cout << val << " "; } void test01() {vector<int>v1;for (int i 0; i <…

【耐水好】强耐水UV胶水是怎样的?

【耐水好】强耐水UV胶水是怎样的&#xff1f; 强耐水UV胶水是一种特殊的胶水&#xff0c;其设计重点在于其出色的耐水性能。以下是关于强耐水UV胶水的特点&#xff1a; 优异的耐水性能&#xff1a;这种胶水能在水环境下保持稳定的粘接强度&#xff0c;不易被水分解或削弱。因…

利用scalene进行性能分析和优化

​ 上一篇文章&#xff0c;我们详细讲解了Py-Spy这个性能分析和优化工具的使用流程&#xff1b;今天&#xff0c;我们将深入探讨另一个性能分析和优化工具——scalene。 什么是scalene&#xff1f; scalene是一个高精度的Python性能分析工具&#xff0c;可以对CPU和内存使用情…

照片放大工具Topaz Gigapixel AI for Mac v7.1.2

Topaz Gigapixel AI软件是一款相当高效的PC端图像大小调整工具&#xff0c;更是一款能够为摄影师、设计师以及图像处理爱好者带来革命性体验的强大软件。它凭借先进的深度学习技术&#xff0c;打破了传统图像大小调整的限制&#xff0c;实现了真正意义上的无损放大和图像恢复。…

OpenAI 前首席科学家 Ilya Sutskever 成立新人工智能公司

OpenAI 联合创始人之一 Ilya Sutskever 在正式离开 OpenAI 一个月后&#xff0c;成立了一家新公司 Safe Superintelligence Inc. (SSI)。Sutskever 是 OpenAI 的长期首席科学家&#xff0c;他与前 Y Combinator 合伙人 Daniel Gross 以及前 OpenAI 工程师 Daniel Levy 共同创立…