词向量与句向量模型

1. 模型进展

1.1 one hot编码

受限于词典大小
不能表示语义相似性
在这里插入图片描述

1.2 共现矩阵

n*n的对称矩阵X,矩阵维数随着词典数量n的增大而增大,可以使用奇异值分解SVD将矩阵维度降低。但是仍存在问题:

矩阵X的维度经常改变 由于大部分词并不共现而导致的稀疏性 矩阵维度过高带来的高计算复杂度

1.3 词袋模型(Bag Of Words, BOW)

将所有词语装进一个袋子里,不考虑其词法和语序的问题,即每个词语都是独立的。
例如上面2个例句,就可以构成一个词袋,袋子里包括Jane、wants、to、go、Shenzhen、Bob、Shanghai。假设建立一个数组(或词典)用于映射匹配
[Jane, wants, to, go, Shenzhen, Bob, Shanghai]
那么上面两个例句就可以用以下两个向量表示,对应的下标与映射数组的下标相匹配,其值为该词语出现的次数 1 [1,1,2,1,1,0,0] 2
[0,1,2,1,0,1,1] 这两个词频向量就是词袋模型,可以很明显的看到语序关系已经完全丢失。

1.2 word2vector

wordvec详细介绍
来源

2013年的论文《Efficient Estimation of Word Representation in Vector Space》,它的核心思想是通过词的上下文得到词的向量化表示,
有两种训练方式:
CBOW(通过附近词预测中心词)、
Skip-gram(通过中心词预测附近的词)
两种训练方式

前世今生:

NGRAM:将词当成一个离散的单元(因此存在一定的局限性,没有考虑到词与词之间的关系)
neural network language model:只能处理定长序列,训练慢。使用RNN之后有所改善
NNLM

两种优化方式

针对CBOW和SKIP-gram,样本大以及不均衡问题
考虑到sofmax归一化需要遍历整个词汇表,
层次softmax 实质上生成一颗带权路径最小的哈夫曼树,让高频词搜索路径变小;
负采样更为直接,实质上对每一个样本中每一个词都进行负例采样;

层次softmax:
从根节点到叶子节点的唯一路径编码了这个叶子节点所属的类别
代价:增强了词与词之间的耦合性层次softmax
Word2Vec中从输入到隐层的过程就是Embedding的过程。

CBOW

变量:词表大小V, 维度N,窗口大小C;N一般取50~300
步骤:input layer:窗口内的C个词的onehot表示
input layer -> hidden layer:(V维表示降到N维表示)
通过权重矩阵𝑊𝑉×𝑁 ,将 𝑉×𝐶映射为 𝑁×𝐶
hidden layer + 激活函数:C个词表示为1个词
word2vec中激活函数,用了简单取平均;
hidden layer -> output layer:1个N维词还原到高维V维中;
通过权重矩阵𝑊′𝑁×𝑉 ,将 𝑁×1映射为 𝑉×1
output layer + softmax 激活函数,将值归一化到0~1之间 y
用BP+梯度下降优化cost function y和真实y之间的距离,迭代优化参数 𝑊、𝑊′
收敛result:y是V维向量,每个元素取值0~1, 将最大元素值,还原为onehot编码,就是最终结果了。

word2vec结合了CBOW, skip-gram的方法 训练得到参数𝑊, 但在计算中做了很多优化;
可以看到,NNLM计算中,两个问题导致计算量大
词表维度大;
softmax计算量大
下面介绍两种优化方法;

skip-gram

思路同CBOW, 只是输入是1个词,输出是C个词;
一般用BP训练得到参数,预测用一次前向传播;

输入:embedding + 输出层。预测词的上下文。比如前后各取一个。
例如:你 真 漂亮。根据 真,预测其上下文的情况
输出:(0.3, 0.5, 0.7,), (0.1,0.9,0.1)
你出现在真之前的概率是0.3,之后是0.1;
真出现在真之前的概率是0.5,之后是0.9
漂亮出现在真之前的概率是0.7,之后是0.1
用蒙特卡洛模拟的方法根据哪些概率值去采样,就能得到一个具体的上下文。
然后就是优化了,使得输入的词之间“真漂亮”之间的概率足够大。
写出目标函数:
T是语料库单词的总个数,p(wt+j|wt)是已知当前词wt,预测周围词的总概率对数值在这里插入图片描述
在这里插入图片描述
层次softmax
1)用huffman编码做词表示
2)把N分类变成了log(N)个2分类。 如要预测的term(足球)的编码长度为4,则可以把预测为’足球’,转换为4次二分类问题,在每个二分类上用二元逻辑回归的方法(sigmoid);
3)逻辑回归的二分类中,sigmoid函数导数有很好的性质,𝜎′(𝑥)=𝜎(𝑥)(1−𝜎(𝑥))
4)采用随机梯度上升求解二分类,每计算一个样本更新一次误差函数
gensim的word2vec 默认已经不采用分层softmax了, 因为𝑙𝑜𝑔21000=10也挺大的;如果huffman的根是生僻字,则分类次数更多;
所以这时候负采样就派上了用场

1.3 glove

word2vec只考虑到了词的局部信息,没有考虑到词与局部窗口外词的联系
glove利用共现矩阵,同时考虑了局部信息和整体的信息
Count-based模型,如GloVe,本质上是对共现矩阵进行降维。
首先,构建一个词汇的共现矩阵,每一行是一个word,每一列是context。共现矩阵就是计算每个word在每个context出现的频率。由于context是多种词汇的组合,其维度非常大,我们希望像network embedding一样,在context的维度上降维,学习word的低维表示。

来自论文《Glove: Global vectors for word representation》。

设共现矩阵为X,其元素为Xi,j 每一个值的意义为:在整个语料库中,单词i和单词j共同出现在一个窗口中的次数。
Pij=P(j∣i)=Xij/Xi表示词汇jjj出现在词汇iii上下文的概率。
P在一定程度上可以反映词汇之间的相关性,当相关性比较低时,其值应该在1附件,当相关性比较高时,比值应该偏离1比较远。
因此主要是训练得到词向量满足以下规律。最终可通过训练迭代得到符合规律的词向量。
在这里插入图片描述

https://github.com/stanfordnlp/GloVe
详细使用步骤: https://blog.csdn.net/sscssz/article/details/53333225

1.4 ELMO

之前介绍词向量均是静态的词向量,无法解决一词多义等问题。下面介绍三种elmo、GPT、bert词向量,它们都是基于语言模型的动态词向量。

ELMO是“Embedding from Language Models"简称。其本质就是根据当前上下文对Word Embedding进行动态调整的过程。

但是elmo是一个伪双向模型
使用向量拼接方式融合上下文特征融合能力较弱,伪双向。

先将句子正向输入一遍得到正向的hide state值。再将句子逆向输入一遍,得到逆向的hide state值,拼接后得到整体。优化。
与训练后,得到每个单词的两个方向的hide state拼接。输入到下游模型中

1.5 GPT

GPT是Generative Pre-Traxining的简称。
与elmo不同的是,GPT使用transformer进行提取特征,并且是单向的transformer,只是根据上文来预测某个词,Transformer模型主要是利用自注意力(self-attention)机制的模型。

fine-tuning: 与ELMo当成特征的做法不同,OpenAI GPT不需要再重新对任务构建新的模型结构,而是直接在transformer这个语言模型上的最后一层接上softmax作为任务输出层,然后再对这整个模型进行微调。

1.6 BERT

BERT是“Bidirectional Encoder Representations from Transformers"的简称。

同GPT采用两阶段模式:利用双向transformer语言模型进行预训练,通过fine-tuning模式解决下游任务。

BERT创新: Masked语言模型和Next Sentence Prediction。

BERT(Bidirectional Encoder Representations from Transformers)详解(参考链接:https://plmsmile.github.io/2018/12/15/52-bert/

http://fancyerii.github.io/2019/03/09/bert-theory/#elmo):

缺点:对文本字数512限制,不利于文本生成。

2. 常见问题

2.1 词袋模型到word2vec改进了什么?

词袋模型(Bag-of-words
model)是将一段文本(比如一个句子或是一个文档)用一个“装着这些词的袋子”来表示,这种表示方式不考虑文法以及词的顺序。而在用词袋模型时,文档的向量表示直接将各词的词频向量表示加和。通过上述描述,可以得出词袋模型的两个缺点:

词向量化后,词与词之间是有权重大小关系的,不一定词出现的越多,权重越大。 词与词之间是没有顺序关系的。
而word2vec是考虑词语位置关系的一种模型。通过大量语料的训练,将每一个词语映射成一个低维稠密向量,通过求余弦的方式,可以判断两个词语之间的关系,word2vec其底层主要采用基于CBOW和Skip-Gram算法的神经网络模型。

因此,综上所述,词袋模型到word2vec的改进主要集中于以下两点:

考虑了词与词之间的顺序,引入了上下文的信息
得到了词更加准确的表示,其表达的信息更为丰富

1 Word2vector

import jieba
import os
import re
import pandas as pd
from gensim.models.word2vec import Word2Vec
import gensim

class TrainWord2Vec(object):
    """
    训练得到一个Word2Vec模型
    """
    def __init__(self, data, stopword, new_path, num_features=100, min_word_count=1, context=4, incremental=False):
        """
        定义变量
        :param data: 用于训练胡语料
        :param stopword: 停用词表
        :param num_features:  返回的向量长度
        :param min_word_count:  最低词频
        :param context: 滑动窗口大小
        :param incremental: 是否进行增量训练
        :param old_path: 若进行增量训练,原始模型路径
        """
        self.data = data
        self.stopword = stopword
        self.num_features = num_features
        self.min_word_count = min_word_count
        self.context = context
        self.incremental = incremental
        #self.old_path = old_path
        self.new_path = new_path

    def clean_text(self):
        """
        采用结巴分词函数分词
        :param corpus: 待分词的Series序列
        :return: 分词结果,list
        """
        # 去除无用字符
        pattern = re.compile(r'[\sA-Za-z~()()【】%*#+-\.\\\/:=:__,,。、;;“”""''’‘??!!<《》>^&{}|=……]')
        corpus_ = self.data.apply(lambda s: re.sub(pattern, '', str(s)))
        # 分词
        text = corpus_.apply(jieba.lcut)
        # 过滤通用词
        text = text.apply(lambda cut_words: [word for word in cut_words if word not in self.stopword])
        return text

    def get_model(self, text):
        """
        从头训练word2vec模型
        :param text: 经过清洗之后的语料数据
        :return: word2vec模型
        """
        model = Word2Vec(text, vector_size=self.num_features, min_count=self.min_word_count, window=self.context)
        return model

    def update_model(self, text):
        """
        增量训练word2vec模型
        :param text: 经过清洗之后的新的语料数据
        :return: word2vec模型
        """
        model = Word2Vec.load(self.old_path)  # 加载旧模型
        model.build_vocab(text, update=True)  # 更新词汇表
        model.train(text, total_examples=model.corpus_count, epochs=20)  # epoch=iter语料库的迭代次数;(默认为5)  total_examples:句子数。
        return model

    def train(self):
        """
        主函数,保存模型
        """
        # 加入自定义分析词库
        #jieba.load_userdict("add_word.txt")
        text = self.clean_text()
        if self.incremental:
            model = self.update_model(text)
        else:
            model = self.get_model(text)
            model.train(text, total_examples=model.corpus_count, epochs=20)

        # 保存模型
        model.wv.save_word2vec_format(self.new_path, binary=True)


if __name__ == '__main__':
    corpus = []
    infile = "/dataset/sentence_sim/V1_6/data/qiwei/single"
    stop_file = "qiwei_vocab_no_in.txt"
    w2v_file = 'w2v_qiwei.bin'
    for file_i in ["train.csv", "test.csv"]:
        corpus.append(pd.read_csv(os.path.join(infile, file_i))["text"])
    
    corpus = corpus[0].append(corpus[1])
    print(len(corpus))
    stopword = []
    with open(stop_file, "r") as f:
        for info in f.readlines():
            stopword.append(info.strip())
    new_model_path = w2v_file
    model = TrainWord2Vec(corpus, stopword, new_model_path)
    model.train()
   
  1. elmo
    elmoformanylangs git 地址

3.bert系列

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值