NLP复习之【使用飞桨构造生成词向量】(下)

简介: NLP复习之【使用飞桨构造生成词向量】

3. 网络定义


定义skip-gram的网络结构,用于模型训练。在飞桨动态图中,对于任意网络,都需要定义一个继承自paddle.nn.layer的类来搭建网络结构、参数等数据的声明。同时需要在forward函数中定义网络的计算逻辑。值得注意的是,我们仅需要定义网络的前向计算逻辑,飞桨会自动完成神经网络的后向计算。

在skip-gram的网络结构中,使用的最关键的API是paddle.nn.Embedding函数,可以用其实现Embedding的网络层。通过查询飞桨的API文档,可以得到如下更详细的说明:

paddle.nn.Embedding(numembeddings, embeddingdim, paddingidx=None, sparse=False, weightattr=None, name=None)

该接口用于构建 Embedding 的一个可调用对象,其根据input中的id信息从embedding矩阵中查询对应embedding信息,并会根据输入的size (num_embeddings, embedding_dim)自动构造一个二维embedding矩阵。 输出Tensor的shape是在输入Tensor shape的最后一维后面添加了emb_size的维度。注:input中的id必须满足 0 =< id < size[0],否则程序会抛异常退出。


#定义skip-gram训练网络结构
#使用paddlepaddle的2.0.0版本
#一般来说,在使用paddle训练的时候,我们需要通过一个类来定义网络结构,这个类继承了paddle.nn.layer
class SkipGram(nn.Layer):
    def __init__(self, vocab_size, embedding_size, init_scale=0.1):
        # vocab_size定义了这个skipgram这个模型的词表大小
        # embedding_size定义了词向量的维度是多少
        # init_scale定义了词向量初始化的范围,一般来说,比较小的初始化范围有助于模型训练
        super(SkipGram, self).__init__()
        self.vocab_size = vocab_size
        self.embedding_size = embedding_size
        # 使用Embedding函数构造一个词向量参数
        # 这个参数的大小为:[self.vocab_size, self.embedding_size]
        # 数据类型为:float32
        # 这个参数的初始化方式为在[-init_scale, init_scale]区间进行均匀采样
        self.embedding = Embedding(
            num_embeddings = self.vocab_size,
            embedding_dim = self.embedding_size,
            weight_attr=paddle.ParamAttr(
                initializer=paddle.nn.initializer.Uniform(
                    low=-init_scale, high=init_scale)))
        # 使用Embedding函数构造另外一个词向量参数
        # 这个参数的大小为:[self.vocab_size, self.embedding_size]
        # 这个参数的初始化方式为在[-init_scale, init_scale]区间进行均匀采样
        self.embedding_out = Embedding(
            num_embeddings = self.vocab_size,
            embedding_dim = self.embedding_size,
            weight_attr=paddle.ParamAttr(
                initializer=paddle.nn.initializer.Uniform(
                    low=-init_scale, high=init_scale)))
    # 定义网络的前向计算逻辑
    # center_words是一个tensor(mini-batch),表示中心词
    # target_words是一个tensor(mini-batch),表示目标词
    # label是一个tensor(mini-batch),表示这个词是正样本还是负样本(用0或1表示)
    # 用于在训练中计算这个tensor中对应词的同义词,用于观察模型的训练效果
    def forward(self, center_words, target_words, label):
        # 首先,通过self.embedding参数,将mini-batch中的词转换为词向量
        # 这里center_words和eval_words_emb查询的是一个相同的参数
        # 而target_words_emb查询的是另一个参数
        center_words_emb = self.embedding(center_words)
        target_words_emb = self.embedding_out(target_words)
        # 我们通过点乘的方式计算中心词到目标词的输出概率,并通过sigmoid函数估计这个词是正样本还是负样本的概率。
        word_sim = paddle.multiply(center_words_emb, target_words_emb)
        word_sim = paddle.sum(word_sim, axis=-1)
        word_sim = paddle.reshape(word_sim, shape=[-1])
        pred = F.sigmoid(word_sim)
        # 通过估计的输出概率定义损失函数,注意我们使用的是binary_cross_entropy_with_logits函数
        # 将sigmoid计算和cross entropy合并成一步计算可以更好的优化,所以输入的是word_sim,而不是pred
        loss = F.binary_cross_entropy_with_logits(word_sim, label)
        loss = paddle.mean(loss)
        # 返回前向计算的结果,飞桨会通过backward函数自动计算出反向结果。
        return pred, loss

4. 网络训练


完成网络定义后,就可以启动模型训练。我们定义每隔100步打印一次Loss,以确保当前的网络是正常收敛的。同时,我们每隔10000步观察一下skip-gram计算出来的同义词(使用 embedding的乘积),可视化网络训练效果,代码如下:


# 开始训练,定义一些训练过程中需要使用的超参数
batch_size = 512
epoch_num = 3
embedding_size = 200
step = 0
learning_rate = 0.001
#定义一个使用word-embedding查询同义词的函数
#这个函数query_token是要查询的词,k表示要返回多少个最相似的词,embed是我们学习到的word-embedding参数
#我们通过计算不同词之间的cosine距离,来衡量词和词的相似度
#具体实现如下,x代表要查询词的Embedding,Embedding参数矩阵W代表所有词的Embedding
#两者计算Cos得出所有词对查询词的相似度得分向量,排序取top_k放入indices列表
def get_similar_tokens(query_token, k, embed):
    W = embed.numpy()
    x = W[word2id_dict[query_token]]
    cos = np.dot(W, x) / np.sqrt(np.sum(W * W, axis=1) * np.sum(x * x) + 1e-9)
    flat = cos.flatten()
    indices = np.argpartition(flat, -k)[-k:]
    indices = indices[np.argsort(-flat[indices])]
    for i in indices:
        print('for word %s, the similar word is %s' % (query_token, str(id2word_dict[i])))
# 通过我们定义的SkipGram类,来构造一个Skip-gram模型网络
skip_gram_model = SkipGram(vocab_size, embedding_size)
# 构造训练这个网络的优化器
adam = paddle.optimizer.Adam(learning_rate=learning_rate, parameters = skip_gram_model.parameters())
# 使用build_batch函数,以mini-batch为单位,遍历训练数据,并训练网络
for center_words, target_words, label in build_batch(
    dataset, batch_size, epoch_num):
    # 使用paddle.to_tensor,将一个numpy的tensor,转换为飞桨可计算的tensor
    center_words_var = paddle.to_tensor(center_words)
    target_words_var = paddle.to_tensor(target_words)
    label_var = paddle.to_tensor(label)
    # 将转换后的tensor送入飞桨中,进行一次前向计算,并得到计算结果
    pred, loss = skip_gram_model(
        center_words_var, target_words_var, label_var)
    # 程序自动完成反向计算
    loss.backward()
    # 程序根据loss,完成一步对参数的优化更新
    adam.step()
    # 清空模型中的梯度,以便于下一个mini-batch进行更新
    adam.clear_grad()
    # 每经过100个mini-batch,打印一次当前的loss,看看loss是否在稳定下降
    step += 1
    if step % 1000 == 0:
        print("step %d, loss %.3f" % (step, loss.numpy()[0]))
    # 每隔10000步,打印一次模型对以下查询词的相似词,这里我们使用词和词之间的向量点积作为衡量相似度的方法,只打印了5个最相似的词
    if step % 10000 ==0:
        get_similar_tokens('movie', 5, skip_gram_model.embedding.weight)
        get_similar_tokens('one', 5, skip_gram_model.embedding.weight)
        get_similar_tokens('chip', 5, skip_gram_model.embedding.weight)
step 1000, loss 0.691
step 2000, loss 0.684
step 3000, loss 0.619
step 4000, loss 0.505
step 5000, loss 0.452
step 6000, loss 0.269

image.png


下一步计划使用PaddleNLP加载词向量


欢迎大家一起讨论交流



目录
相关文章
|
12月前
|
机器学习/深度学习 自然语言处理 数据可视化
NLP复习之【使用飞桨PaddleNLP计算词向量、句向量】
NLP复习之【使用飞桨PaddleNLP计算词向量、句向量】
287 0
|
12月前
|
数据采集 存储 自然语言处理
NLP复习之【使用飞桨构造生成词向量】(上)
NLP复习之【使用飞桨构造生成词向量】
80 0
|
机器学习/深度学习 自然语言处理
②机器学习之自然语言处理——基于TfidfVectorizer和CountVectorizer及word2vec构建词向量矩阵(代码+原理)
机器学习之自然语言处理——基于TfidfVectorizer和CountVectorizer及word2vec构建词向量矩阵(代码+原理)
298 0
②机器学习之自然语言处理——基于TfidfVectorizer和CountVectorizer及word2vec构建词向量矩阵(代码+原理)
|
机器学习/深度学习 自然语言处理 Python
①机器学习之自然语言处理——基于TfidfVectorizer和CountVectorizer及word2vec构建词向量矩阵(代码+原理)
机器学习之自然语言处理——基于TfidfVectorizer和CountVectorizer及word2vec构建词向量矩阵(代码+原理)
366 0
①机器学习之自然语言处理——基于TfidfVectorizer和CountVectorizer及word2vec构建词向量矩阵(代码+原理)
|
机器学习/深度学习 存储 人工智能
斯坦福NLP课程 | 第2讲 - 词向量进阶
NLP课程第2讲内容覆盖ord2vec与词向量、算法优化基础、计数与共现矩阵、GloVe模型、词向量评估、word senses等。
1056 1
斯坦福NLP课程 | 第2讲 - 词向量进阶
|
机器学习/深度学习 人工智能 自然语言处理
NLP教程(2) - GloVe及词向量的训练与评估
本文介绍GloVe词向量、词向量内部与外部评估方法、类比任务中的词向量训练超参数影响、相关度评估任务中词向量与人工表现差异、基于上下文处理一词多义问题和窗分类。
1453 1
NLP教程(2) - GloVe及词向量的训练与评估
|
机器学习/深度学习 人工智能 自然语言处理
斯坦福NLP课程 | 第1讲 - NLP介绍与词向量初步
NLP课程第1讲直接切入语言和词向量,讲解自然语言处理的基本概念、文本表征的方法和演进、包括word2vec等核心方法,词向量的应用等。
528 1
斯坦福NLP课程 | 第1讲 - NLP介绍与词向量初步
|
机器学习/深度学习 存储 人工智能
NLP教程(1) - 词向量、SVD分解与Word2Vec
本文介绍自然语言处理(NLP)的概念及其面临的问题,进而介绍词向量和其构建方法(包括基于共现矩阵降维和Word2Vec)。
1293 1
NLP教程(1)  -  词向量、SVD分解与Word2Vec
|
自然语言处理 Java API
阿里云自然语言处理--词向量(高级版-搜索领域)Quick Start
自然语言处理(Natural Language Processing,简称NLP),是为各类企业及开发者提供的用于文本分析及挖掘的核心工具,旨在帮助用户高效的处理文本,已经广泛应用在电商、文娱、司法、公安、金融、医疗、电力等行业客户的多项业务中,取得了良好的效果。词向量是一种简单有效的将最小语义单元 —— 词转化为数值表示的方法。通过词向量得到的数值表示的形式是高维稠密向量。这种数值表示的特点是语义相近的词(如“红色”和“蓝色”)在向量空间中的位置接近。这种数值表示可以支撑语义相似度计算等具体应用。本文将使用Java CommonSDK演示词向量(高级版-搜索领域)服务的快速调用以供参考。
392 0
阿里云自然语言处理--词向量(高级版-搜索领域)Quick Start
|
2月前
|
机器学习/深度学习 自然语言处理 监控
利用深度学习技术实现自然语言处理中的情感分析
本文将深入探讨如何利用深度学习技术在自然语言处理领域中实现情感分析。通过介绍情感分析的背景和原理,结合深度学习模型如LSTM、BERT等的应用,帮助读者了解情感分析的重要性以及如何利用最新技术实现更准确的情感识别。