人工智能|深度学习——使用多层级注意力机制和keras实现问题分类

代码下载

使用多层级注意力机制和keras实现问题分类资源-CSDN文库

1 准备工作

1.1 什么是词向量?

”词向量”(词嵌入)是将一类将词的语义映射到向量空间中去的自然语言处理技术。即将一个词用特定的向量来表示,向量之间的距离(例如,任意两个向量之间的L2范式距离或更常用的余弦距离)一定程度上表征了的词之间的语义关系。由这些向量形成的几何空间被称为一个嵌入空间。

传统的独热表示( one-hot representation)仅仅将词符号化,不包含任何语义信息。必须考虑将语义融入到词表示中。

解决办法将原来稀疏的巨大维度压缩嵌入到一个更小维度的空间进行分布式表示。这也是词向量又名词嵌入的缘由了。

例如,“椰子”和“北极熊”是语义上完全不同的词,所以它们的词向量在一个合理的嵌入空间的距离将会非常遥远。但“厨房”和“晚餐”是相关的话,所以它们的词向量之间的距离会相对小。

理想的情况下,在一个良好的嵌入空间里,从“厨房”向量到“晚餐”向量的“路径”向量会精确地捕捉这两个概念之间的语义关系。在这种情况下,“路径”向量表示的是“发生的地点”,所以你会期望“厨房”向量 - “晚餐"向量(两个词向量的差异)捕捉到“发生的地点”这样的语义关系。基本上,我们应该有向量等式:晚餐 + 发生的地点 = 厨房(至少接近)。如果真的是这样的话,那么我们可以使用这样的关系向量来回答某些问题。例如,应用这种语义关系到一个新的向量,比如“工作”,我们应该得到一个有意义的等式,工作+ 发生的地点 = 办公室,来回答“工作发生在哪里?”。

词向量通过降维技术表征文本数据集中的词的共现信息。方法包括神经网络(“Word2vec”技术),或矩阵分解。

1.2 获取词向量

词向量 对与中文自然语言处理任务 是基石,一般情况下 有两种获取方式:

  • 别人训练好的百科数据。优势:包含词语多,符合日常用语的语义;劣势:专有名词不足,占用空间大;
  • 自己训练。优势:专有名词,针对具体任务语义更准确; 劣势:泛化性差。

步骤:

graph LR
文本-->分词
分词-->训练词向量
训练词向量-->保存词向量

具体代码:

import gensim## 训练自己的词向量,并保存。
def trainWord2Vec(filePath):sentences =  gensim.models.word2vec.LineSentence(filePath) # 读取分词后的 文本model = gensim.models.Word2Vec(sentences, size=100, window=5, min_count=1, workers=4) # 训练模型model.save('./CarComment_vord2vec_100')def testMyWord2Vec():# 读取自己的词向量,并简单测试一下 效果。inp = './CarComment_vord2vec_100'  # 读取词向量model = gensim.models.Word2Vec.load(inp)print('空间的词向量(100维):',model['空间'])print('打印与空间最相近的5个词语:',model.most_similar('空间', topn=5))if __name__ == '__main__':#trainWord2Vec('./CarCommentAll_cut.csv')testMyWord2Vec()pass

这样我们就 拥有了 预训练的 词向量文件CarComment_vord2vec_100 。

下一单元 继续讲解如何在keras中使用它。

2 转化词向量为keras所需格式

上一步拿到了所有词语的词向量,但还需转化词向量为keras所需格式。众所周知,keras中使用预训练的词向量的层是Embedding层,而Embedding层中所需要的格式为 一个巨大的“矩阵”:第i列表示词索引为i的词的词向量

所以,本单元的总体思路就是给 Embedding 层提供一个 [ word : word_vector] 的词典来初始化Embedding层中所需要的大矩阵 ,并且标记为不可训练。

2.1 获取所有词语word和词向量

首先要导入 预训练的词向量。

## 1 导入 预训练的词向量
myPath = './CarComment_vord2vec_100' # 本地词向量的地址
Word2VecModel = gensim.models.Word2Vec.load(myPath) # 读取词向量vector = Word2VecModel.wv['空间']  # 词语的向量,是numpy格式
gensim的word2vec模型 把所有的单词和 词向量 都存储在了Word2VecModel.wv里面,讲道理直接使用这个.wv即可。 但是我们打印这个东西的 类型print(type(Word2VecModel.wv)) # 结果为:Word2VecKeyedVectorsfor i,j in Word2VecModel.wv.vocab.items():print(i) # 此时 i 代表每个单词print(j) # j 代表封装了 词频 等信息的 gensim“Vocab”对象,例子:Vocab(count:1481, index:38, sample_int:3701260191)break

发现它是 gensim自己封装的一种数据类型:Word2VecKeyedVectors

<class 'gensim.models.keyedvectors.Word2VecKeyedVectors'>

不能使用for循环迭代取单词。

2.2 构造“词语-词向量”字典

第二步 构造数据:

  • 构造 一个list存储所有单词:vocab_list 存储所有词语。
  • 构造一个字典word_index :{word : index} ,key是每个词语,value是单词在字典中的序号。 在后期 tokenize(序号化) 训练集的时候就是用该词典。 构造包含
  • 构造一个 大向量矩阵embeddings_matrix (按照embedding层的要求):行数 为 所有单词数,比如 10000;列数为 词向量维度,比如100。

代码:

## 2 构造包含所有词语的 list,以及初始化 “词语-序号”字典 和 “词向量”矩阵
vocab_list = [word for word, Vocab in Word2VecModel.wv.vocab.items()]# 存储 所有的 词语word_index = {" ": 0}# 初始化 `[word : token]` ,后期 tokenize 语料库就是用该词典。
word_vector = {} # 初始化`[word : vector]`字典# 初始化存储所有向量的大矩阵,留意其中多一位(首行),词向量全为 0,用于 padding补零。
# 行数 为 所有单词数+1 比如 10000+1 ; 列数为 词向量“维度”比如100。
embeddings_matrix = np.zeros((len(vocab_list) + 1, Word2VecModel.vector_size))

2.3 填充字典和矩阵

第三步:填充 上述步骤中 的字典 和 大矩阵

## 3 填充 上述 的字典 和 大矩阵
for i in range(len(vocab_list)):# print(i)word = vocab_list[i]  # 每个词语word_index[word] = i + 1 # 词语:序号word_vector[word] = Word2VecModel.wv[word] # 词语:词向量embeddings_matrix[i + 1] = Word2VecModel.wv[word]  # 词向量矩阵

2.4 在 keras的Embedding层中使用 预训练词向量

from keras.layers import EmbeddingEMBEDDING_DIM = 100 #词向量维度embedding_layer = Embedding(input_dim = len(embeddings_matrix), # 字典长度EMBEDDING_DIM, # 词向量 长度(100)weights=[embeddings_matrix], # 重点:预训练的词向量系数input_length=MAX_SEQUENCE_LENGTH, # 每句话的 最大长度(必须padding) trainable=False # 是否在 训练的过程中 更新词向量)
  • Embedding层的输入shape

此时 输入Embedding层的数据的维度是 形如(samples,sequence_length)的2D张量,注意,此时句子中的词语word已经被转化为 index(依靠word_index,所以在 embedding层之前 往往结合 input层, 用于将 文本 分词 转化为数字形式)

  • Embedding层的输出shape

Embedding层把 所有输入的序列中的整数,替换为对应的词向量矩阵中对应的向量(也就是它的词向量),比如一句话[1,2,8]将被序列[词向量第[1]行,词向量第[2]行,词向量第[8]行]代替。

这样,输入一个2D张量后,我们可以得到一个3D张量:(samples, sequence_length, embeddings_matrix)

*2.5 不使用“预训练”而直接生成词向量

我们也可以直接使用Keras自带的Embedding层训练词向量,而不用预训练的word2vec词向量。代码如下所示:

embedding_layer = Embedding(len(word_index) + 1, # 由于 没有预训练,设置+1 EMBEDDING_DIM, # 设置词向量的维度input_length=MAX_SEQUENCE_LENGTH) #设置句子的最大长度

可以看出在使用 Keras的中Embedding层时候,不指定参数weights=[embeddings_matrix] 即可自动生成词向量。

先是随机初始化,然后,在训练数据的过程中训练。

在参考文献1中 做的对比实验,对于新闻文本分类任务:直接使用Keras自带的Embedding层训练词向量而不用预训练的word2vec词向量,得到0.9的准确率。

使用预训练的word2vec词向量,同样的模型最后可以达到0.95的分类准确率。

所以使用预训练的词向量作为特征是非常有效的。一般来说,在自然语言处理任务中,当样本数量非常少时,使用预训练的词向量是可行的(实际上,预训练的词向量引入了外部语义信息,往往对模型很有帮助)。

3 整体代码:在Keras模型中使用预训练的词向量

文本数据预处理,将每个文本样本转换为一个数字矩阵,矩阵的每一行表示一个词向量。下图梳理了处理文本数据的一般步骤。 

3.1 读取数据

def load_file():dataFrame_2016 = pd.read_csv('data\\nlpcc2016_kbqa_traindata_zong_right.csv',encoding='utf-8')print(dataFrame_2016.columns) # 打印列的名称texts = []   # 存储读取的 xlabels = []  # 存储读取的y# 遍历 获取数据for i in range(len(dataFrame_2016)):texts.append(dataFrame_2016.iloc[i].q_text) # 每个元素为一句话“《机械设计基础》这本书的作者是谁?”labels.append(dataFrame_2016.iloc[i].q_type) # 每个元素为一个int 代表类别 # [2, 6, ... 3] 的形式## 把类别从int 3 转换为(0,0,0,1,0,0)的形式labels = to_categorical(np.asarray(labels)) # keras的处理方法,一定要学会# 此时为[[0. 0. 1. 0. 0. 0. 0.]....] 的形式return texts, labels # 总文本,总标签

3.2 句子分词

## 2. cut_sentence2word 句子分词
def cut_sentence2word(texts):texts = [jieba.lcut(Sentence.replace('\n', '')) for Sentence in texts] # 句子分词return texts

3.3 *构造词向量字典

## 3.获取word2vec模型, 并构造,词语index字典,词向量字典
def get_word2vec_dictionaries(texts):def get_word2vec_model(texts=None): # 获取 预训练的词向量 模型,如果没有就重新训练一个。if os.path.exists('data_word2vec/Word2vec_model_embedding_25'): # 如果训练好了 就加载一下不用反复训练model = Word2Vec.load('data_word2vec/Word2vec_model_embedding_25')# print(model['作者'])return modelelse:model = Word2Vec(texts, size = EMBEDDING_LEN, window=7, min_count=10, workers=4)model.save('data_word2vec/Word2vec_model_embedding_25') # 保存模型return modelWord2VecModel = get_word2vec_model(texts) #  获取 预训练的词向量 模型,如果没有就重新训练一个。vocab_list = [word for word, Vocab in Word2VecModel.wv.vocab.items()]  # 存储 所有的 词语word_index = {" ": 0}# 初始化 `[word : token]` ,后期 tokenize 语料库就是用该词典。word_vector = {} # 初始化`[word : vector]`字典# 初始化存储所有向量的大矩阵,留意其中多一位(首行),词向量全为 0,用于 padding补零。# 行数 为 所有单词数+1 比如 10000+1 ; 列数为 词向量“维度”比如100。embeddings_matrix = np.zeros((len(vocab_list) + 1, Word2VecModel.vector_size))## 填充 上述 的字典 和 大矩阵for i in range(len(vocab_list)):word = vocab_list[i]  # 每个词语word_index[word] = i + 1  # 词语:序号word_vector[word] = Word2VecModel.wv[word] # 词语:词向量embeddings_matrix[i + 1] = Word2VecModel.wv[word]  # 词向量矩阵return word_index, word_vector, embeddings_matrix

3.4 文本序号化Tokenizer

在上文中已经得到了每条文本的文字了,但是text-CNN等深度学习模型的输入应该是数字矩阵。可以使用Keras的Tokenizer模块实现转换。

简单讲解Tokenizer如何实现转换。当我们创建了一个Tokenizer对象后,使用该对象的fit_on_texts()函数,可以将输入的文本中的每个词编号,编号是根据词频的,词频越大,编号越小。可能这时会有疑问:Tokenizer是如何判断文本的一个词呢?其实它是以空格去识别每个词。因为英文的词与词之间是以空格分隔,所以我们可以直接将文本作为函数的参数,但是当我们处理中文文本时,我们需要使用分词工具将词与词分开,并且词间使用空格分开。具体实现如下:

当然 ,也可以使用之前构建的word_index字典,手动 构建文本tokenizer句子:(推荐这种方法,这样序号下标与预训练词向量一致。)

# 序号化 文本,tokenizer句子,并返回每个句子所对应的词语索引
def tokenizer(texts, word_index):data = []for sentence in texts:new_txt = []for word in sentence:try:new_txt.append(word_index[word])  # 把句子中的 词语转化为indexexcept:new_txt.append(0)data.append(new_txt)texts = sequence.pad_sequences(data, maxlen = MAX_SEQUENCE_LENGTH)  # 使用kears的内置函数padding对齐句子,好处是输出numpy数组,不用自己转化了return texts

3.5 切分数据

## 5.切分数据
def split_data(texts, labels):x_train, x_test, y_train, y_test = train_test_split(texts, labels, test_size=0.2)return x_train, x_test, y_train, y_test

3.6 使用Embedding层将每个词编码转换为词向量

通过以上操作,已经将每个句子变成一个向量,但上文已经提及text-CNN的输入是一个数字矩阵,即每个影评样本应该是以一个矩阵,每一行代表一个词,因此,需要将词编码转换成词向量。使用Keras的Embedding层可以实现转换。

需要声明一点的是Embedding层是作为模型的第一层,在训练模型的同时,得到该语料库的词向量。当然,也可以使用已经预训练好的词向量表示现有语料库中的词。

embedding_layer = Embedding(input_dim=len(embeddings_matrix),  # 字典长度output_dim = EMBEDDING_LEN,  # 词向量 长度(25)weights=[embeddings_matrix],  # 重点:预训练的词向量系数input_length=MAX_SEQUENCE_LENGTH,  # 每句话的 最大长度(必须padding) 10trainable=False,  # 是否在 训练的过程中 更新词向量name= 'embedding_layer')

然后利用 keras的建模能力,把Embedding层嵌入到 模型中去即可。后面可以接CNN或者LSTM

参考文献

参考《Keras的中Embedding层 官方文档》: 嵌入层 Embedding - Keras中文文档

参考1 官方文档《在Keras模型中使用预训练的词向量》:在Keras模型中使用预训练的词向量 - Keras中文文档

参考2 :《Keras 模型中使用预训练的 gensim 词向量(word2vec) 和可视化》 Keras 模型中使用预训练的 gensim 词向量和可视化 | Eliyar's Blog

参考3《Embedding原理和Tensorflow-tf.nn.embedding_lookup()》:Embedding原理和Tensorflow-tf.nn.embedding_lookup()_embedding必须通过nn.lookup-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【 buuctf--刷新过的图片】

前言&#xff1a;这题主要运用到了新的工具F5-steganography由于 java 环境不合适的原因&#xff0c;我不得不重新配java11.0.18。 具体思路&#xff1a;非常帅气的一张图片。。。用 binwalk&#xff0c;stegsolve&#xff0c;zsteg&#xff0c;exiftool 等工具无果后&#xf…

【Java程序设计】【C00253】基于Springboot的在线考试管理系统(有论文)

基于Springboot的在线考试管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的在线考试系统 本系统分为系统功能模块、管理员功能模块以及用户功能模块。 系统功能模块&#xff1a;系统登录&#xff0c;管理…

【Django】Django文件上传

文件上传 1 定义&场景 定义&#xff1a;用户可以通过浏览器将图片等文件上传至网站。 场景&#xff1a; 用户上传头像。 上传流程性的文档[pdf&#xff0c;txt等] 2 上传规范-前端[html] 文件上传必须为POST提交方式 表单 <form> 中文件上传时必须带有 enctype…

图(高阶数据结构)

目录 一、图的基本概念 二、图的存储结构 2.1 邻接矩阵 2.2 邻接表 三、图的遍历 3.1 广度优先遍历 3.2 深度优先遍历 四、最小生成树 4.1 Kruskal算法 4.2 Prim算法 五、最短路径 5.1 单源最短路径-Dijkstra算法 5.2 单源最短路径-Bellman-Ford算法 5.3 多源最…

JCIM | MD揭示PTP1B磷酸酶激活RtcB连接酶的机制

Background 内质网应激反应&#xff08;UPR&#xff09; 中的一个重要过程。UPR是由内质网中的三种跨膜传感器&#xff08;IRE1、PERK和ATF6&#xff09;控制的细胞应激反应&#xff0c;当内质网中的蛋白质折叠能力受到压力时&#xff0c;UPR通过减少蛋白质合成和增加未折叠或错…

springcloud分布式架构网上商城源码和论文

首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数据库设计。本项…

集合进阶(双列集合、HashMap、LinkedHashMap、TreeMap、Collections)

目录 一、双列集合 1、双列集合的特点 2、双列集合的常见API 3、Map的遍历方式 3.1第一种遍历方式&#xff1a;键找值&#xff08;keySet&#xff09; 3.2第二种遍历方式&#xff1a;键值对&#xff08;entrySet&#xff09;Entry&#xff1a;键值对对象 3.3第三种遍历方…

vue 引入 百度地图API 和 路书

公司项目中&#xff0c;偶尔都会涉及到地图的使用&#xff0c;这里以百度地图为例&#xff0c;我们梳理一下引用流程及注意点 账号和获取密钥 百度地图示例 百度地图 类参考 1、账号和获取密钥 // api.map.baidu.com/api?typewebgl&v3.0&ak您的密钥<script type…

EasyExcel下载带下拉框和批注模板

EasyExcel下载带下拉框和批注模板 一、 代码实现 controller下载入口 /***下载excel模板* author youlu* date 2023/8/14 17:31* param response* param request* return void*/PostMapping("/downloadTemplate")public void downloadExcel(HttpServletResponse r…

Linux笔记之xhost +和docker的关系以及GDK_SCALE和GDK_DPI_SCALE详解

Linux笔记之xhost 和docker的关系以及GDK_SCALE和GDK_DPI_SCALE详解 ——2024-02-11 code review! 文章目录 Linux笔记之xhost 和docker的关系以及GDK_SCALE和GDK_DPI_SCALE详解xhost 的作用xhost 与 Docker 的关系 -e GDK_SCALE 和 -e GDK_DPI_SCALE详解GDK_SCALEGDK_DPI_SC…

Java设计模式大全:23种常见的设计模式详解(一)

本系列文章简介&#xff1a; 设计模式是在软件开发过程中&#xff0c;经过实践和总结得到的一套解决特定问题的可复用的模板。它是一种在特定情境中经过验证的经验和技巧的集合&#xff0c;可以帮助开发人员设计出高效、可维护、可扩展和可复用的软件系统。设计模式提供了一种在…

华为 huawei 交换机 接口 MAC 地址学习限制接入用户数量 配置示例

目录 组网需求: 配置思路&#xff1a; 操作步骤&#xff1a; 配置文件&#xff1a; 组网需求: 如 图 2-14 所示&#xff0c;用户网络 1 和用户网络 2 通过 LSW 与 Switch 相连&#xff0c; Switch 连接 LSW 的接口为GE0/0/1 。用户网络 1 和用户网络 2 分别属于 VLAN10 和 V…

幻兽帕鲁PalWorld服务器2024年配置选择

幻兽帕鲁PalWorld是一款备受期待的虚拟游戏&#xff0c;其独特的幻兽系统和丰富的世界观吸引了大量玩家。然而&#xff0c;随着游戏日益受到关注&#xff0c;服务器的配置选择成为了关键问题。2024年&#xff0c;随着技术不断发展&#xff0c;玩家对于游戏体验的需求也在不断提…

Quartus工程的qsf配置约束文件介绍

一、qsf文件概述 qsf&#xff1a;Quartus Setting File&#xff0c;是Quartus工程的配置文件&#xff1b; 包含一个Quartus工程的所有约束&#xff0c;包括工程的软件版本信息、FPGA器件信息、引脚约分配、引脚电平分配&#xff0c;编译约束和用于Classic TimingAnalyzer的时…

通过QT制作一个模仿微信主界面的界面(不要求实现具体通信功能)

main.cpp #include "widget.h" #include "second.h"#include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();//实例化第二个界面Second s;QObject::connect(&w, &Widget::my_jump, &…

微信,支付宝在线换钱平台系统源码

探索全新、全开源的在线换钱系统源码&#xff0c;它将以前所未有的方式改变您的支付体验。我们为您精心打造了一个集简单易用与安全高效于一身的优质产品&#xff0c;它采用最新的技术开发&#xff0c;为您带来前所未有的便捷与安心。 这款在线换钱系统源码设计直观&#xff0…

netty-websocket扩展协议及token鉴权补充

文章源码&#xff1a;gitee 源码部分可以看上一篇文章中的源码分析netty-websocket 鉴权token及统一请求和响应头&#xff08;鉴权控制器&#xff09; 最近刚好没事&#xff0c;看到有朋友说自定义协议好搞&#xff0c;我就想了想&#xff0c;发现上面那种方式实现确实麻烦&…

分享springboot框架的一个开源的本地开发部署教程(若依开源项目开发部署过程分享持续更新二开宝藏项目MySQL数据库版)

1首先介绍下若依项目&#xff1a; 若依是一个基于Spring Boot和Spring Cloud技术栈开发的多租户权限管理系统。该开源项目提供了一套完整的权限管理解决方案&#xff0c;包括用户管理、角色管理、菜单管理、部门管理、岗位管理等功能。 若依项目采用前后端分离的架构&#xf…

Python中使用opencv-python进行人脸检测

Python中使用opencv-python进行人脸检测 之前写过一篇VC中使用OpenCV进行人脸检测的博客。以数字图像处理中经常使用的lena图像为例&#xff0c;如下图所示&#xff1a; 使用OpenCV进行人脸检测十分简单&#xff0c;OpenCV官网给了一个Python人脸检测的示例程序&#xff0c;…