zoukankan      html  css  js  c++  java
  • 词向量与相关应用

    一、基础知识

    计算机没有人类的先验知识,如何理解文字,如何让实现文本分类,必须找到一套方法或方式对这些我们人类造成的词去表达和表式。一是从大量的预料中,拿到一些可以对它的含义表达的一些表达方式,二是文本是标记性的语言没办法去做机器学习,转成计算机可以理解的数值型的向量

    词编码---> N-gram, TFIDF--->word2vec

    Nlp常见问题:自动摘要、指代消解、机器翻译、词性标注、分词(中文、日文等)、主题识别、文本分类。 

    传统:基于规则

    现代:基于统计机器学习 HMM, CRF, SVM, LDA, CNN….”规则“隐含在模型参数里

    词编码

    词编码需要保证词的相似性,如果每个词都给一个码就不能保证识别子类、近义词等,比如青蛙和蟾蜍等等

    我们希望编码方式可以表达同样含义的词在向量空间里面分布相似,例如下面假设的二维空间。

     

    向量空间子结构

    每个词一定是空间中的某个点,期望词向量能捕捉到词和词之间的相对关系

    VKing – Vqueen +Vwomen = Vman

    VParis – VFrance +VGerman = VBerlin

    最终目标,词向量表示作为机器学习、特别是深度学习的输入和表示空间

    英语里面自然语言处理的库NLTK,他会建立很大一个字典,根据专家构建出来的权威的东西,比如猫,是一个动物,有胎生,弹跳性等上位词。但是会有很多问题,不能分辨细节的差别、需要大量人为劳动、主管、无法发现新词、难以精确计算词之间的相似度

     

    二、离散表示

    离散表示:one-hot表示

    很早之前的词编码的方式,建索引,one-hot,每个单词都有唯一索引,在词典中的顺序和在句子中的顺序没有关联。先建索引,再one-hot表示。

    这种方式非常吃空间,维度非常非常高,如果每个词给一个编码,会做一个高频统计,只表示3000或4000个高频词,其他的词都用一个维度表示。

     

    离散表示:bag of words

    刚刚方式可以表达词,但最终目标是表达文本。文档的向量表示可以直接将各词的词向量表示加和。对应维度下面填充数字,表示这个数字出现了多少次。

     

    from sklearn.feature_extraction.text import CountVectorizer
    vectorizer = CountVectorizer()
    #四段语料
    corpus = ["i come to China to travel",
                    “This is  a car popular in china”,
                    "i love tea and apple",
                    "the work is  to write some papers in science"]
    print vectorizer.fit_transform(corpus)
    print vectorizer.fit_transform(corpus).toarray()
    print vectorizer.get_feature_names()

    离散表示:TF-IDF

    在搜索引擎中,常用到词权重,从而引申出TF-IDF。

     

     1 # 读入文本
     2 with open('./nlp_text1.txt') as f3:
     3        res1 = f3.read()
     4 
     5 with open('./nlp_text3.txt') as f4:
     6        res2 = f4.read()
     7 
     8 #停用词
     9 #从文件导入停用词表                                                  
    10 stpwrdpath = "stop_words.txt"
    11 stpwrd_dic = open(stpwrdpath, 'rb')
    12 stpwrd_content = stpwrd_dic.read()
    13 #将停用词表转换为list  
    14 stpwrdlst = stpwrd_content.splitlines()
    15 stpwrd_dic.close()
    16 
    17 # 向量化,TF-IDF和标准化 当然,还可以处理停用词
    18 from sklearn.feature_extraction.text import TfidfVectorizer
    19 corpus = [res1,res2]
    20 vector = TfidfVectorizer(stop_words=stpwrdlst)
    21 tfidf = vector.fit_transform(corpus)
    22 print tfidf
    23 
    24 wordlist = vector.get_feature_names()#获取词袋模型中的所有词  
    25 # tf-idf矩阵 元素a[i][j]表示j词在i类文本中的tf-idf权重
    26 weightlist = tfidf.toarray()  
    27 #打印每类文本的tf-idf词语权重,第一个for遍历所有文本,第二个for便利某一类文本下的词语权重
    28 for i in range(len(weightlist)):  
    29     print "-------第",i,"段文本的词语tf-idf权重------"  
    30     for j in range(len(wordlist)):  
    31         print wordlist[j],weightlist[i][j]

    离散表示:语言模型 Bi-gram和N-gram

    上面两个表示方式都没有考虑词的顺序。Bi-gram和N-gram考虑了词的顺序,但是缺点是词表膨胀。

     

    离散表示的问题:

    无法衡量词向量之间的关系(没有捕获文本的含义);词表维度随着语料库增长膨胀;n-gram词序列随语料库膨胀更快;数据稀疏问题。

    对于词袋模型的稀疏问题可以用常用的文本降维方法是Hash Trick。在Hash Trick中,首先定义一个Hash后对应的哈希表,这个哈希表的维度会远远小于词汇表的特征维度,因此可以看成是降维。具体的方法是,对任意一个特征,使用用Hash函数找到对应哈希表的位置,然后将该特征对应的词频统计值累加到该哈希表位置。在scikit-learn的HashingVectorizer类中,实现了基于signed hash trick的算法。

    from sklearn.feature_extraction.text import HashingVectorizer
    vectorizer2 = HashingVectorizer(n_features=6,norm=None)
    print vectorizer2 .fit_transform(corpus)

    三、分布式连续表示

    分布式表示(Distributed representation)

     

    1957年firth提出,用一个词附近的其他词来表示该词,这被认为是现代统计自然语言处理中最有创见的想法之一。计算机可以看很多语料,比如发现banking经常和经济这类词放到一起,基于这种思路,就有很多人提出了不同的解决思路。

    共现矩阵(Cocurrence matrix)

    即两个词同时出现。Word-Document的共现矩阵主要用于发现主题,用于主题模型,如LSA(latent semantic analysis)

    这时候就有一个局域窗的概念,就是在一个范围内看共现的单词。局域窗中的word-word共现矩阵可以挖掘语法和语义信息。

    Window length设为1(一般设为5-10)

    使用对窗函数(左右window length都为1)

    将共现矩阵行作为词向量。

    下图为这三句话的共现矩阵,假设左右窗口为1,i旁边左右窗口中like出现2次,enjoy出现1次。这时候的向量表示用的是共现矩阵的方式。

     

    优势:能表示出来词的相关度。把周边朋友拿过来了,上下文捕捉到了

    缺点:向量维数随着词典大小线性增长;存储整个词典的空间消耗非常大;一些模型如文本分类模型会面临稀疏性问题;模型会欠稳定(加了新的句子,统计的频率就不一样)。

    解决上面维度的缺陷,最直接的想法是降维,用SVD对共现矩阵向量做降维,取    U矩阵里面的值。该想法依然有问题,计算量随语料库和词典增长膨胀太快,对X(m*n)维的矩阵,计算量o(n^3);难以为词典中新加入的词分配词向量。与其他深度学习模型框架差异大(已经再原始数据上处理了,可能不是deeplearnning想要的输入方式)。

    Import numpy as np

    la = np.linalg

    x = np.array([

    [0,2,1,0,0,0,0,0],

    [2,0,0,1,0,0,0,0],

    [1,0,0,1,,0,0,1,0]

    ])

    U, S, Vh = la.svd(X, full_matrices=False)

    四、WORD2VEC

    NNLM(neural network language model)2003年提出word2vec前身

    直接从语言模型出发,将模型最优化过程转化为求词向量表示的过程。前向窗函数,由N-1个词推断下一个词的概率,会遍历整个语料库。

    使用了非对称的前向窗函数,窗长度为n-1,滑动窗口遍历整个语料库求和,

    与标准答案的相近度,希望越大越好。

    要求概率P满足归一化条件,这样不同位置t处的概率才能相加,即:

    对所有的词做一个稀疏的向量表示,前n-1个词去预测下一个词。 NNLM只有1个隐层。最后W假设是1*8000(对1个词的描述),假设最后的向量是个500维的,那C就是80000*500。先通过投影矩阵(先随机初始化)做投影,只是从W里面选出一行或者一列,然后到一个隐层,然后再到softmax,最后完成拼接。最后的维度,取决于你的n,如果你要用前10个词预测,那应该是10*500=5000维。输出层softmax,我们希望拿到的概率值尽量的高,可以加上一个负号然后用BP+SDG可以完成优化,一旦优化完了,投影矩阵也就是最好的稠密向量表示。

     

    因为是神经网络,所以需要大量的数据,每个训练样本的复杂度为N*D+N*D*H+H*V,因此在这个基础上去做了简化。

     Word2Vec实际上是两种不同的方法:Continuous Bag of Words (CBOW) 和 Skip-gram。

    这两种方法都利用人工神经网络作为它们的分类算法。起初,每个单词都是一个随机 N 维向量。经过训练之后,该算法利用 CBOW 或者 Skip-gram 的方法获得了每个单词的最优向量。

     Word2vec:CBOW(连续词袋)

    Continue bag of words由周边的n个词,去推中间的1个词。

    如何简化?

    试试无隐层。

    使用双向上下文窗口。

    上下文词序无关。

    输入层直接使用低维稠密表示。

    投影层简化为求和(平均)

     

    最后是一个softmax,类似于多分类的softmax,也需要去完成一个全连接的计算,拼接,如果词表是40W,500*40W你就需要有这样一个连接,消耗太大,所以要处理,有两种方式:

    一种是层次softmax。40W词是平铺开来的,意思是和40w词都要有连接,对于平铺开来的结构如果要压缩空间是层叠起来的结构,使用huffman树对原本文本语料进行编码,根据出现频次的高低。边上的权重可以共享。根据语料在这个huffman树上找到路径(每个节点就是个二分类),求出这条路径上的概率相加,使其最大,就把刚刚平铺的变成了层叠的结构。

      

    另一种是负例采样(工业上用的多一些)。由前后的词预测第t个词,可以将第t个词当成是正确的正样本,其他的作为负样本(40w-1),负样本的量太大了,所以我们可以去对这些负样本去采样。这个采样是要有技巧的,保证采样完的东西和原本的相近度很高。Google在做这个事情的时候想了个办法,拉出一个长度为1的小段,切成了10^8次方等分,然后按照词出现的词频的3/4划分占多少线段,在从空中抛色子,色子有10^8面,那个面朝上,查一查这个数落在哪一段,就把这一段的词取出来。之后就可以train一个softmax。

     

    Word2vec:Skip-Gram(连续词袋)

    上面是由周边的词推断中间的词,而Skip-Gram是中间的词推断周边的词,其他的和CBOW基本一致。语料非常大的话Skip-Gram的结果稍微比CBOW好一点

     

    Word2vec存在的问题

    对每个local context window单独训练,没有利用包含在global co-currence矩阵中的统计信息。改进方法:Glove

    对多义词无法很好的表示和处理(比如苹果手机和苹果),因为使用了唯一的词向量。

    Glove可以利用全局的信息,如果你需要一个对词表示的很好的词向量,可以试试Glove有开源的专门的库。但是深度学习里面还是用word2vec比较多,因为词嵌入这种方式你是可以可以作为嵌入层,直接做一个端到端的模型,嵌入的词表和目标直接关联的。

    词嵌入效果评估:词类比任务。

    词嵌入效果评估:词相似度任务。

    词嵌入效果评估:作为特征用于CRF。

     

     四、工具

    1.Google word2vec

    Git clone https://github.com/dav/word2vec

    cd word2vec/src

    Make

    2.Python库

    Genism

    easy_install -U genism或pip install –upgrade

    示例代码 https://www.zybuluo.com/hanxiaoyang/note/472184

    word2vec作为此的初始输入,后面可以接各种各样的模型

    word2vec + CNN尤其是建立成端到端的模型

    电商情感分析 snownlp

    参考博客 

    http://mp.weixin.qq.com/s?__biz=MzIxODM4MjA5MA==&mid=2247485748&idx=1&sn=daca1a059a51e3a2265a49c34faa3fe9&chksm=97ea2351a09daa4720c84c139751b1515c5447dac4d92741b9a7a3583a51aadbd758db013b26&scene=21#wechat_redirect 

  • 相关阅读:
    PHP读取excel中地址实现多文件下载
    PHP中域名绑定
    js生成word中图片处理
    Mysql查询不为null值
    Specified key was too long max key length is 1000 bytes
    无法向Windows服务器复制粘贴文件
    Sql Server Configuration Manager 网络配置为空,没有实例
    The first one
    前端基本知识 防抖、节流,compose 函数,apply,bind,call
    写一个闭包 ,每次调用都加1
  • 原文地址:https://www.cnblogs.com/fionacai/p/8268202.html
Copyright © 2011-2022 走看看