2019-11-09 09:01:03 weixin_42479155 阅读数 24
  • 60分钟带你掌握NLP BERT理论与实战

    本课程会介绍最近NLP领域取得突破性进展的BERT模型。首先会介绍一些背景知识,包括Word Embedding、RNN/LSTM/GRU、Seq2Seq模型和Attention机制等。然后介绍BERT的基础Transformer模型,这个模型最初用于机器翻译,但是它提出的Self-Attention被用于替换传统的RNN/LSTM/GRU模型。再然后是介绍BERT出现之前的Universal Sentence Embedding模型,包括ELMo和OpenAI GPT。接着介绍BERT模型是什么,它解决了之前模型的哪些问题从而可以达到这么好的效果。代码分析和案例介绍,通过解决实际问题加深理解

    4019 人正在学习 去看看 CSDN讲师

title: ‘NLP-3:机器学习和模型评价初步’
date: 2019-11-08 23:14:24
mathjax: true
categories:

  • nlp-自然语言处理
    tags:
  • nlp-自然语言处理

NLP-3:机器学习和模型评价初步

  • 由经验生成的数据。
    1. 优点:全面
    2. 缺点:抽象性弱,数据多且冗余,不易修改维护

KNN(K-nearest neighbors,K-近邻算法)

  • 如果一个样本在特征空间中的 k 个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别

决策树模型(decision tree)

  • 决策树模型 (Decision Tree)。将问题的抽象层次变高。减少了 The First Book 的数据。

    关键是找到合适的分割条件。将最显著的特征放在最前面,权重最大

  • 信息熵

    Entroy=imPr(xi)log(Pr(xi)) Entroy =- \sum_i^m Pr(x_i) log(Pr(x_i))
    熵指的是一个群体的混论程度就是熵

    def entropy(elements):
        '''群体混乱程度'''
        counter = Counter(elements)
    #     print(counter)类似于统计map一样,键是元素,值是次数
    
        probs = [counter[c]/len(elements) for c in set(elements)]#这里只是使用的set函数而已
        #print(probs)
        return -sum(p*np.log(p) for p in probs)
    entropy([1,1,1,1])
    entropy([1,2,3,4])
    #这里只是混乱程度不是大小
    entropy([1,2,2,3])
    

决策树如何决定哪一个值或者哪一个特征进行分割

  • 示例

    mock_data = {
        'gender':['F', 'F', 'F', 'F', 'M', 'M', 'M'],
        'income': ['+10', '-10', '+10', '+10', '+10', '+10', '-10'],
        'family_number': [1, 1, 2, 1, 1, 1, 2],
        'bought': [1, 1, 1, 0, 0, 0, 1],
    }
    import pandas as pd
    dataset = pd.DataFrame(mock_data)# 将set组装成下面模样
    dataset
    

  • 其实是为了寻找一个分割的线

    split_by gender:
    [1,1,1,0],[0,0,1]
    split_by_income:
    [1,1,0,0,0],[1,1]
    split_by_family_number:
    [1,1,0,0,0] [1,1]
    if split_by_some_feature:
    [1,1,1,1],[0,0,0]
    如果存在这样数据,那么对我们信息切分最好:也就是优先级最高
    entropy(第一部分)和entropy(第二部分)为0

  • print(entropy([1,1,1,0])+entropy([0,0,1]))
    print(entropy([1,1,0,0,0])+entropy([1,1]))
    print(entropy([1,1,1,1])+entropy([0,0,0]))
    
  • 决策树在选择决策的过程,决策顺序的其实是按照某种特征,进行分割之后按照熵最小原则进行的

def find_the_min_spilter(training_data:pd.DataFrame,target:str)->str:
    x_fields = set(training_data.columns.tolist())-{target}
    #print(x_fields)
    spliter = None
    min_entropy = float('inf')
    for f in x_fields:
        ic(f)
        values = set(training_data[f])#这里面的f就是每条记录的结果,类似于列的列头,然后把所有的结果进行统计,放到数组里面
        ic(values)
        for v in values:
            sub_spliter_1 = training_data[training_data[f] == v][target].tolist()#统计某一个值中买了的有多少,转化为list
            ic(sub_split_1)
            entroy_1 = entropy(sub_spliter_1)#信息熵
            ic(entroy_1)
            sub_spliter_2 = training_data[training_data[f] !=v ][target].tolist()
            ic(sub_split_2)
            entroy_2 = entropy(sub_spliter_2)
            ic(entroy_2)
            entroy_v = entroy_1 + entroy_2
            ic(entroy_v)
            if entroy_v <= min_entropy:
                min_entropy = entroy_v
                spliter = (f,v)
                #print(spliter)
#                 这个代码是冗余的,
    print('spliter is: {}'.format(spliter))
    print('the min entropy is: {}'.format(min_entropy))
    return spliter

Naive Bayesian Classification (朴素贝叶斯)

朴素贝叶斯朴素在哪里

K-Means算法

  • 选择K个点作为初始质心 repeat 将每个点指派到最近的质心,形成K个簇 重新计算每个簇的质心 until 簇不发生变化或达到最大迭代次数

  • 数据示例:

    from sklearn.cluster import KMeans
    X1= [random.randint(0, 100) for _ in range(100)]
    X2 = [random.randint(0, 100) for _ in range(100)]
    plt.scatter(X1, X2)
    

    image

  • 数据示例

    tranning_data = [[x1, x2] for x1, x2 in zip(X1, X2)]
    cluster = KMeans(n_clusters=3,max_iter=500)
    cluster.cluster_centers_
    from collections import defaultdict
    centers = defaultdict(list)
    for label, location in zip(cluster.labels_, tranning_data):
        centers[label].append(location)
    color = ['red', 'green', 'grey', 'black', 'yellow', 'orange']
    
    for i, c in enumerate(centers):
        for location in centers[c]:
            plt.scatter(*location, c=color[i])
            
    for center in cluster.cluster_centers_:
        plt.scatter(*center, s=100)
    

    image

  • 计算复杂度

    O(INKd)O(I*N*K*d)

    1. I:迭代次数
    2. N:点的数目
    3. K:聚类的数目
    4. d:距离
2018-05-07 21:00:03 songbinxu 阅读数 30804
  • 60分钟带你掌握NLP BERT理论与实战

    本课程会介绍最近NLP领域取得突破性进展的BERT模型。首先会介绍一些背景知识,包括Word Embedding、RNN/LSTM/GRU、Seq2Seq模型和Attention机制等。然后介绍BERT的基础Transformer模型,这个模型最初用于机器翻译,但是它提出的Self-Attention被用于替换传统的RNN/LSTM/GRU模型。再然后是介绍BERT出现之前的Universal Sentence Embedding模型,包括ELMo和OpenAI GPT。接着介绍BERT模型是什么,它解决了之前模型的哪些问题从而可以达到这么好的效果。代码分析和案例介绍,通过解决实际问题加深理解

    4019 人正在学习 去看看 CSDN讲师

自然语言处理NLP中的N-gram模型

Naive Bayes

  首先我们复习一下一个非常基本的模型,朴素贝叶斯(Naive Bayes)。朴素贝叶斯的关键组成是贝叶斯公式与条件独立性假设。为了方便说明,我们举一个垃圾短信分类的例子。

**"在家日赚百万,惊人秘密..."**

  上面这句话抄自我手机中的一条垃圾短信,自从去过澳门,手机就时不时收到这样的关于赌场的短信。朴素贝叶斯模型就是要衡量这句话属于垃圾短信敏感句子的概率,我们以前半句为例:
p("")p()p("")p(垃圾短信|"在家日赚百万")\propto p(垃圾邮件)p("在家日赚百万"|垃圾短信)
由条件独立性假设:
p(""J)=p("","","","","",""J)=p(""J)p(""J)p(""J)p(""J)p(""J)p(""J)p("在家日赚百万"|J)=p("在","家","日","赚","百","万"|J)\\ =p("在"|J)p("家"|J)p("日"|J)p("赚"|J)p("百"|J)p("万"|J)
  上面每一项条件概率都可以通过在训练数据的垃圾短信中统计每个字出现的次数得到,然而这里有一个问题,朴素贝叶斯将句子处理为一个**词袋模型(Bag-of-Words, BoW)**,以至于不考虑每个单词的顺序。这一点在中文里可能没有问题,因为有时候即使把顺序捣乱,我们还是能看懂这句话在说什么,但有时候不行,例如:

**我烤面筋 = 面筋烤我 ?**

  那么有没有模型是考虑句子中单词之间的顺序的呢?有,N-gram就是。


N-gram

N-gram简介

  在介绍N-gram之前,让我们回想一下**“联想”**的过程是怎样发生的。如果你是一个玩LOL的人,那么当我说“正方形打野”、“你是真的皮”,“你皮任你皮”这些词或词组时,你应该能想到的下一个词可能是“大司马”,而不是“五五开”。如果你不是LOL玩家,没关系,当我说“上火”、“金罐”这两个词,你能想到的下一个词应该更可能“加多宝”,而不是“可口可乐”。
  N-gram正是基于这样的想法,它的第一个特点是某个词的出现依赖于其他若干个词,第二个特点是我们获得的信息越多,预测越准确。我想说,我们每个人的大脑中都有一个N-gram模型,而且是在不断完善和训练的。我们的见识与经历,都在丰富着我们的阅历,增强着我们的联想能力。

  N-gram模型是一种语言模型(Language Model,LM),语言模型是一个基于概率的判别模型,它的输入是一句话(单词的顺序序列),输出是这句话的概率,即这些单词的联合概率(joint probability)。
这里写图片描述

  N-gram本身也指一个由NN个单词组成的集合,各单词具有先后顺序,且不要求单词之间互不相同。常用的有 Bi-gram (N=2N=2) 和 Tri-gram (N=3N=3),一般已经够用了。例如在上面这句话里,我可以分解的 Bi-gram 和 Tri-gram :

Bi-gram : {I, love}, {love, deep}, {love, deep}, {deep, learning}
Tri-gram : {I, love, deep}, {love, deep, learning}


N-gram中的概率计算

  假设我们有一个由nn个词组成的句子S=(w1,w2,,wn)S=(w_1,w_2,\cdots,w_n),如何衡量它的概率呢?让我们假设,每一个单词wiw_i都要依赖于从第一个单词w1w_1到它之前一个单词wi1w_{i-1}的影响:
p(S)=p(w1w2wn)=p(w1)p(w2w1)p(wnwn1w2w1)p(S)=p(w_1w_2\cdots w_n)=p(w_1)p(w_2|w_1)\cdots p(w_n|w_{n-1}\cdots w_2w_1)
是不是很简单?是的,不过这个衡量方法有两个缺陷:

  • 参数空间过大,概率 p(wnwn1w2w1)p(w_n|w_{n-1}\cdots w_2w_1) 的参数有 O(n)O(n) 个。
  • 数据稀疏严重,词同时出现的情况可能没有,组合阶数高时尤其明显。

  为了解决第一个问题,我们引入马尔科夫假设(Markov Assumption)一个词的出现仅与它之前的若干个词有关
p(w1wn)=p(wiwi1w1)p(wiwi1wiN+1)p(w_1\cdots w_n)=\prod p(w_i|w_{i-1}\cdots w_1)\approx \prod p(w_i|w_{i-1}\cdots w_{i-N+1})

  • 如果一个词的出现仅依赖于它前面出现的一个词,那么我们就称之为 Bi-gram
    p(S)=p(w1w2wn)=p(w1)p(w2w1)p(wnwn1)p(S)=p(w_1w_2\cdots w_n)=p(w_1)p(w_2|w_1)\cdots p(w_n|w_{n-1})
  • 如果一个词的出现仅依赖于它前面出现的两个词,那么我们就称之为 Tri-gram
    p(S)=p(w1w2wn)=p(w1)p(w2w1)p(wnwn1wn2)p(S)=p(w_1w_2\cdots w_n)=p(w_1)p(w_2|w_1)\cdots p(w_n|w_{n-1}w_{n-2})

N-gram的 NN 可以取很高,然而现实中一般 bi-gram 和 tri-gram 就够用了。

  那么,如何计算其中的每一项条件概率 p(wnwn1w2w1)p(w_n|w_{n-1}\cdots w_2w_1) 呢?答案是**极大似然估计(Maximum Likelihood Estimation,MLE)**,说人话就是数频数:
p(wnwn1)=C(wn1wn)C(wn1)p(w_n|w_{n-1})=\frac{C(w_{n-1}w_n)}{C(w_{n-1})}
p(wnwn1wn2)=C(wn2wn1wn)C(wn2wn1)p(w_n|w_{n-1}w_{n-2})=\frac{C(w_{n-2}w_{n-1}w_n)}{C(w_{n-2}w_{n-1})}
p(wnwn1w2w1)=C(w1w2wn)C(w1w2wn1)p(w_n|w_{n-1}\cdots w_2w_1)=\frac{C(w_1w_2\cdots w_n)}{C(w_1w_2\cdots w_{n-1})}

  具体地,以Bi-gram为例,我们有这样一个由三句话组成的语料库:

  容易统计,“I”出现了3次,“I am”出现了2次,因此能计算概率:
p(amI)=23p(am|I)=\frac{2}{3}
  同理,还能计算出如下概率:
p(I<s>)=0.67p(Samam)=0.5p(<s>Sam)=0.5p(doI)=0.33p(notdo)=1p(likenot)=1\begin{matrix}p(I|<s>)=0.67 & p(Sam | am)=0.5 & p(<s>|Sam)=0.5 \\ p(do|I)=0.33 & p(not|do)=1 & p(like|not)=1\end{matrix}

  另外再提供一个《Language Modeling with Ngrams》中的例子,Jurafsky et al., 1994 从加州一个餐厅的数据库中做了一些统计:
这里写图片描述
这里写图片描述
这里写图片描述

  据统计,p(I<s>)=0.25p(I|<s>)=0.25p(<s>food)=0.68p(<s>|food)=0.68,于是:
p(<s>I want chinese food<s>)=0.25×0.33×0.0065×0.52×0.68=1.896×104p(<s>I\ want\ chinese\ food<s>)\\=0.25\times 0.33\times 0.0065 \times 0.52 \times 0.68=1.896\times 10^{-4}
  我们算出了“I want chinese food”这句话的概率,但有时候这句话会很长,那么概率(都是小于1的常数)的相乘很可能造成数据下溢(downflow),即很多个小于1的常数相乘会约等于0,此时可以使用log概率解决。


N-gram的用途

用途一:词性标注

  N-gram可以实现词性标注。例如“爱”这个词,它既可以作为动词使用,也可以作为名词使用。不失一般性,假设我们需要匹配一句话中“爱”的词性。
这里写图片描述

  我们可以将词性标注看成一个多分类问题,按照Bi-gram计算每一个词性概率:

p(i"","")=i""""p(词性_i|"龙龙"的词性, "爱")=\frac{前面是“名词”的“爱”作为词性_i 的出现次数}{前面是"名词"的"爱"的出现次数}

  选取概率更大的词性(比如动词)作为这句话中“爱”字的词性。


用途二:垃圾短信分类

  文章开头提到的那个垃圾短信分类问题,我们可以用N-gram来解决。在朴素贝叶斯的基础上,稍微对条件概率做一点改动即可。
p("")p()p("")p(垃圾短信|"在家日赚百万")\propto p(垃圾邮件)p("在家日赚百万"|垃圾短信)
条件概率不再是各词语之间独立:
p(""J)=p("","","","","",""J)=p(""J)×p("""",J)×p("""",J)×p("""",J)×p("""",J)×p("""",J)p("在家日赚百万"|J)=p("在","家","日","赚","百","万"|J)\\ =p("在"|J)\times p("家"|"在",J)\times p("日"|"家",J)\times\\p("赚"|"日",J)\times p("百"|"赚",J)\times p("万"|"百",J)

  垃圾短信分类问题可以总结为以下三个步骤:

  • 步骤一:给短信的每个句子断句。
  • 步骤二:用N-gram判断每个句子是否垃圾短信中的敏感句子。
  • 步骤三:若敏感句子个数超过一定阈值,认为整个邮件是垃圾短信。

用途三:分词器

  在NLP中,分词的效果很大程度上影响着模型的性能,因此分词甚至可以说是最重要的工程。用N-gram可以实现一个简单的分词器(Tokenizer)。同样地,将分词理解为多分类问题:XX 表示有待分词的句子,YiY_i 表示该句子的一个分词方案。

X=""X="我爱深度学习"
Y1={"","",""}Y2={"","","",""}Y3={"","",""}Y_1=\{"我","爱深","度学习"\}\\ Y_2=\{"我爱","深","度学","习"\}\\ Y_3=\{"我","爱","深度学习"\}
p(Y1)=p()p()p()p(Y2)=p()p()p()p()p(Y3)=p()p()p()p(Y_1)=p(我)p(爱深|我)p(度学习|爱深)\\ p(Y_2)=p(我爱)p(深|我爱)p(度学|深)p(习|度学)\\ p(Y_3)=p(我)p(爱|我)p(深度学习|爱)

  三个概率中,“我爱”可能在语料库中比较常见,因此p()p(爱|我)会比较大,然而“我爱深”这样的组合比较少见,于是p()p(爱深|我)p()p(深|我爱)都比较小,导致p(Y3)p(Y_3)p(Y1)p(Y_1)p(Y2)p(Y_2)都大,因此第三种分词方案最佳。


用途四:机器翻译和语音识别

机器翻译

  同一句话,可能有多种翻译方式,它们的区别仅在于单词的组合顺序,这时候使用N-gram分别计算各种情况的概率,选最大的那个即可。

这里写图片描述

语音识别

  同一种发音,可能被解析成不同的句子,然而其中有一种更符合语法规则。
这里写图片描述


N-gram中N的确定

  为了确定NN的取值,《Language Modeling with Ngrams》使用了 Perplexity 这一指标,该指标越小表示一个语言模型的效果越好。文章使用了华尔街日报的数据库,该数据库的字典大小为19,979,训练集包含 38 million 个词,测试集包含 1.5 million 个词。针对不同的N-gram,计算各自的 Perplexity。

PP(W)=1P(w1w2wn)n=i=1n1p(wiwi1w1)nPP(W)=\sqrt[n]{\frac{1}{P(w_1w_2\cdots w_n)}}=\sqrt[n]{\prod_{i=1}^n \frac{1}{p(w_i|w_{i-1}\cdots w_1)}}
  结果显示,Tri-gram的Perplexity最小,因此它的效果是最好的。那么NN越大是否越好呢?


N-gram中的数据平滑方法

  上面提到,N-gram的NN越大,模型 Perplexity 越小,表示模型效果越好。这在直观意义上是说得通的,毕竟依赖的词越多,我们获得的信息量越多,对未来的预测就越准确。然而,语言是有极强的创造性的(Creative),当NN变大时,更容易出现这样的状况:某些n-gram从未出现过,这就是稀疏问题
  n-gram最大的问题就是稀疏问题(Sparsity)。例如,在bi-gram中,若词库中有20k个词,那么两两组合(C20k2C_{20k}^2)就有近2亿个组合。其中的很多组合在语料库中都没有出现,根据极大似然估计得到的组合概率将会是0,从而整个句子的概率就会为0。最后的结果是,我们的模型只能计算零星的几个句子的概率,而大部分的句子算得的概率是0,这显然是不合理的。
  因此,我们要进行数据平滑(data Smoothing),数据平滑的目的有两个:一个是使所有的N-gram概率之和为1,使所有的n-gram概率都不为0。它的本质,是重新分配整个概率空间,使已经出现过的n-gram的概率降低,补充给未曾出现过的n-gram。


拉普拉斯平滑

Add-one

  拉普拉斯平滑,即强制让所有的n-gram至少出现一次,只需要在分子和分母上分别做加法即可。这个方法的弊端是,大部分n-gram都是没有出现过的,很容易为他们分配过多的概率空间。
p(wnwn1)=C(wn1wn)+1C(wn1)+Vp(w_n|w_{n-1})=\frac{C(w_{n-1}w_n)+1}{C(w_{n-1})+|V|}

Add-K

  在Add-one的基础上做了一点小改动,原本是加一,现在加上一个小于1的常数KK。但是缺点是这个常数仍然需要人工确定,对于不同的语料库KK可能不同。

p(wnwn1)=C(wn1wn)+kC(wn1)+kVp(w_n|w_{n-1})=\frac{C(w_{n-1}w_n)+k}{C(w_{n-1})+k|V|}


内插与回溯

内插

  **内插法(Interpolation)**有点像滑动平均,它的核心思想是,既然高阶组合可能出现次数为0,那稍微低阶一点的组合总有不为0的。如下是一个三阶组合,假设p(wnwn1wn2)=0p(w_n|w_{n-1}w_{n-2})=0,而p(wnwn1)>0p(w_n|w_{n-1})>0p(wn)>0p(w_n)>0,则加权平均后的概率不为0,从而达到平滑的效果。

p^(wnwn1wn2)=λ3p(wnwn1wn2)+λ2p(wnwn1)+λ1p(wn)\hat{p}(w_n|w_{n-1}w_{n-2})=\lambda_3 p(w_n|w_{n-1}w_{n-2})+\lambda_2p(w_n|w_{n-1})+\lambda_1p(w_n)

回溯

  **回溯法(backoff)**与内插有点像,只是它会尽可能地用最高阶组合计算概率,当高阶组合不存在时,退而求其次找次低阶,直到找到非零组合为止。参考下式,这是一个递归运算。

p(wnwn1wnN+1)={p(wnwn1wnN+1)C(wn1wnN+1)>0α(wn1wnN+1)p(wnwn1wnN+2)otherwisep(w_n|w_{n-1}\cdots w_{n-N+1})=\left \{ \begin{matrix} p^*(w_n|w_{n-1}\cdots w_{n-N+1}) & C(w_{n-1}\cdots w_{n-N+1})>0\\ \alpha(w_{n-1}\cdots w_{n-N+1})p(w_n|w_{n-1}\cdots w_{n-N+2}) & otherwise\end{matrix} \right .


Absolute Discounting

  Church & Gale (1991) 取了个巧,他们在训练集里找到一些出现次数为C=4C=4的bi-gram,然后在留出集(held-out)中统计它们的出现次数,平均下来发现约等于3.23。接着他们继续统计其他的CC,发现除了0和1外,基本上留出集bi-gram的出现次数等于训练集出现次数减去0.75。
  因此,他们提出直接在分子上减去一个常数,然后在后面加上一项保证概率求和为1。此处d=0.75d=0.75
p(wnwn1)=C(wn1wn)dC(wn1)+λ(wn1)p(wn)p(w_n|w_{n-1})=\frac{C(w_{n-1}w_n)-d}{C(w_{n-1})}+\lambda(w_{n-1})p(w_n)


Kneser-Ney Smoothing

  考虑这样一个填空:

**I can't see without my ( )**

  一个完形填空题,正常来说,我们可能会填入**“glasses”这个词,意思是“我不戴眼镜就看不到东西”。那么,考虑上面提到的内插模型:
λ2p(wiwi1)+λ1p(wi)\lambda_2 p(w_i|w_{i-1})+\lambda_1 p(w_i)
  这个模型很可能会在这个空里填上
“Kong”这个词,是不是觉得很奇怪?因为语料库里,“Hong Kong”** 这个词组是高频词汇,以至于λ1p(wi)\lambda_1 p(w_i)这一项的概率会跟高,而**“glasses”是低频词,相应的概率较低,于是模型就填上了“Kong”**,在我们看来这显然是不合理的,但在模型看来却是合理的选择。
  为了解决这个问题,Kneser and Ney (1995) , Chen and Goodman(1998) 提出,修改这个 p(wi)p(w_i),具体来说,是要求它与“wiw_i为结尾的bi-gram的集合的势正相关的变量”,以表征wiw_i这个单词作为一个新的接续的可能性(即作为其他单词的下一个词的可能性)。
  以Bi-gram为例,实际上就是用下面这个PcontinuationP_{continuation}代替原来的p(w)p(w),所谓集合的势其实是要求集合中的元素互不相同后取集合的大小,其意义就是:语料库有多少种不同的以ww结尾的bi-gram。

Pcontinuation(w){v:C(vw)>0}P_{continuation}(w)\propto |\left \{v:C(vw)>0\right\}|
  作为概率,需要进行归一化:
Pcontinuation(w)={v:C(vw)>0}w{v:C(vw)>0}P_{continuation}(w)=\frac{|\left \{v:C(vw)>0\right\}|}{\sum_{w'}|\left\{v:C(vw')>0\right\}|}

  那么,为什么这样改过之后就能有效解决 p(Kong)p(Kong) 偏大的问题呢?根据 PcontinuationP_{continuation} 的定义,我们去统计语料库中以“Kong”结尾的bi-gram,然后发现只有“Hong Kong”一个,于是 PcontinuationP_{continuation} 就比较小了,而 “glasses”,可能有“sun glasses”,“reading glasses”等,相比“Hong Kong”这个专有名词肯定会更多。因此,问题得到解决。
  Kneser-Ney Smoothing的本质是改进Unigram概率p(w)p(w),像上文提到的其他用到这个概率的平滑方法,也可以代入这个概率,比如Absolute Discounting就变成:
pKN(wnwn1)=C(wn1wn)dC(wn1)+λ(wn1)Pcontinuation(wn)p_{KN}(w_n|w_{n-1})=\frac{C(w_{n-1}w_n)-d}{C(w_{n-1})}+\lambda(w_{n-1})P_{continuation}(w_n)


N-gram对训练数据集的要求

  关于N-gram的训练数据,如果你以为**“只要是英语就可以了”,那就大错特错了。文献《Language Modeling with Ngrams》**的作者做了个实验,分别用莎士比亚文学作品,以及华尔街日报作为训练集训练两个N-gram,他认为,两个数据集都是英语,那么用他们生成的文本应该也会有所重合。然而结果是,用两个语料库生成的文本没有任何重合性,即使在语法结构上也没有。
  这告诉我们,N-gram的训练是很挑数据集的,你要训练一个问答系统,那就要用问答的语料库来训练,要训练一个金融分析系统,就要用类似于华尔街日报这样的语料库来训练。
这里写图片描述
这里写图片描述


N-gram的进化版:NNLM

  NNLMNeural Network based Language Model,由Bengio在2003年提出,它是一个很简单的模型,由四层组成,输入层、嵌入层、隐层和输出层。模型接收的输入是长度为nn的词序列,输出是下一个词的类别。首先,输入是单词序列的index序列,例如单词 I 在字典(大小为V|V|)中的index是10,单词 am 的 index 是23, Bengio 的 index 是65,则句子“I am Bengio”的index序列就是 10, 23, 65。嵌入层(Embedding)是一个大小为V×K|V|\times K的矩阵,从中取出第10、23、65行向量拼成3×K3\times K的矩阵就是Embedding层的输出了。隐层接受拼接后的Embedding层输出作为输入,以tanh为激活函数,最后送入带softmax的输出层,输出概率。
  NNLM最大的缺点就是参数多,训练慢。另外,NNLM要求输入是定长nn,定长输入这一点本身就很不灵活,同时不能利用完整的历史信息。
这里写图片描述


NNLM的进化版:RNNLM

  针对NNLM存在的问题,Mikolov在2010年提出了RNNLM,其结构实际上是用RNN代替NNLM里的隐层,这样做的好处包括减少模型参数、提高训练速度、接受任意长度输入、利用完整的历史信息。同时,RNN的引入意味着可以使用RNN的其他变体,像LSTM、BLSTM、GRU等等,从而在时间序列建模上进行更多更丰富的优化。
  论文给的模型结构图不多,这里就不放出来了,有兴趣可以直接去读论文。另外,RNNLM有开源的工具包,自行编译后得到可执行文件,可在命令行中直接使用。


Word2Vec

  Word2Vec解决的问题已经和上面讲到的N-gram、NNLM等不一样了,它要做的事情是:学习一个从高维稀疏离散向量到低维稠密连续向量的映射。该映射的特点是,近义词向量的欧氏距离比较小,词向量之间的加减法有实际物理意义。Word2Vec由两部分组成:CBoW和Skip-Gram。其中CBoW的结构很简单,在NNLM的基础上去掉隐层,Embedding层直接连接到Softmax,CBoW的输入是某个Word的上下文(例如前两个词和后两个词),Softmax的输出是关于当前词的某个概率,即CBoW是从上下文到当前词的某种映射或者预测。Skip-Gram则是反过来,从当前词预测上下文,至于为什么叫Skip-Gram这个名字,原因是在处理过程中会对词做采样。
  Word2Vec这个内容比较丰富,这里只做一点概括性的描述,以后应该会再专门写一个博客。


参考资料

【博客】一周论文 | Word2Vec 作者Tomas Mikolov 的三篇代表作
【博客】word2vector:NPLM、CBOW、Skip-gram
【博客】大白话讲解word2vec到底在做些什么
【博客】Deep Learning in NLP (一)词向量和语言模型
【博客】word2vec前世今生
【博客】Hinton神经网络公开课编程题2–神经概率语言模型(NNLM)
【博客】神经网络语言模型(NNLM)
【博客】NLP系列(2)_用朴素贝叶斯进行文本分类(上)
【博客】NLP系列(5)_从朴素贝叶斯到N-gram语言模型
【博客】语言模型系列之N-Gram、NPLM及Word2vec
【博客】OpenNLP ngram n元语法模型(简介)
【博客】关于N-Gram模型(例子很好)
【博客】自然语言处理中的N-Gram模型详解
【博客】Deep Learning 读书笔记(十二):A Neural Probabilistic Language Model
【博客】Recurrent Neural Network Based Language Model(RNNLM)原理及BPTT数学推导
【博客】RNNLM的使用方法
【斯坦福课程】Speech and Language Processing
【NNLM论文】A Neural Probabilistic Language Models
【RNNLM论文】Statistical Language Models Based on Neural Networks
【开源】RNNLM Toolkit

2019-08-07 12:20:00 dingyplucky 阅读数 134
  • 60分钟带你掌握NLP BERT理论与实战

    本课程会介绍最近NLP领域取得突破性进展的BERT模型。首先会介绍一些背景知识,包括Word Embedding、RNN/LSTM/GRU、Seq2Seq模型和Attention机制等。然后介绍BERT的基础Transformer模型,这个模型最初用于机器翻译,但是它提出的Self-Attention被用于替换传统的RNN/LSTM/GRU模型。再然后是介绍BERT出现之前的Universal Sentence Embedding模型,包括ELMo和OpenAI GPT。接着介绍BERT模型是什么,它解决了之前模型的哪些问题从而可以达到这么好的效果。代码分析和案例介绍,通过解决实际问题加深理解

    4019 人正在学习 去看看 CSDN讲师

基于markov的语言模型,在遇到未登录词时,会将语法合理的句子概率计算为0.这是不合理的。

Add-one Smoothing (laplace smoothing)

P_{MLE}\left ( w_{i}|w_{i-1} \right )=\frac{c\left (w_{i-1}\cdot w_{i} \right )}{c\left (w_{i} \right )}

P_{Add-1}\left ( w_{i}|w_{i-1} \right )=\frac{c\left (w_{i-1}\cdot w_{i} \right ) +1 }{c\left (w_{i} \right ) + V}

分母上加一个V(词典大小)的一个理由,使概率之和为1.

Add-K Smoothing 

P_{Add-k}\left ( w_{i}|w_{i-1} \right )=\frac{c\left (w_{i-1}\cdot w_{i} \right ) +\boldsymbol{{\color{Red} k}} }{c\left (w_{i} \right ) + \boldsymbol{{\color{Red} kV}}}

以perplexity为优化目标,计算最优的\boldsymbol{k}

Interpolation平滑

核心思想:计算Trigram概率时同时考虑Unigram,Bigram,Trigram出现的频次。

P\left ( w_{n}|w_{n-1},w_{n-2} \right )=\lambda _{1}P\left ( w_{n}|w_{n-1},w_{n-2} \right ) +\lambda _{2}P\left ( w_{n}|w_{n-1} \right ) +\lambda _{3}P\left ( w_{n} \right )

\lambda _{1}+\lambda _{2}+\lambda _{3}=1

Good-Turing平滑

2018-05-04 11:05:15 sinat_33588424 阅读数 150
  • 60分钟带你掌握NLP BERT理论与实战

    本课程会介绍最近NLP领域取得突破性进展的BERT模型。首先会介绍一些背景知识,包括Word Embedding、RNN/LSTM/GRU、Seq2Seq模型和Attention机制等。然后介绍BERT的基础Transformer模型,这个模型最初用于机器翻译,但是它提出的Self-Attention被用于替换传统的RNN/LSTM/GRU模型。再然后是介绍BERT出现之前的Universal Sentence Embedding模型,包括ELMo和OpenAI GPT。接着介绍BERT模型是什么,它解决了之前模型的哪些问题从而可以达到这么好的效果。代码分析和案例介绍,通过解决实际问题加深理解

    4019 人正在学习 去看看 CSDN讲师
  • 主题模型理论
  • 什么是主体模型? 比如,文章属于哪一主题?分类问题
  • 直观的看:
特征--->简历--->好/坏
  • LDA
    是一种无监督的贝叶斯模型
是一种主题模型,它可以将文档集中每篇文档的主题按照概率分布的形式给出。同时她是一种无监督学习算法,
在训练时,不需要手工标注的训练集,需要的仅仅是文档集以及指定主题的数量K即可。此外LDA的另一个优点是,
对于每一个主题均可找到一些词语来描述它

是一种典型的词袋模型,即它认为⼀一篇⽂文档是由⼀一组词构成的⼀一个集合,词与词之间没有顺序以及先后的关系。
一篇⽂文档可以包含多个主题,⽂文档中每⼀一个词都由其中的⼀一个主题⽣生成。
2019-01-15 10:41:42 qq_40006058 阅读数 210
  • 60分钟带你掌握NLP BERT理论与实战

    本课程会介绍最近NLP领域取得突破性进展的BERT模型。首先会介绍一些背景知识,包括Word Embedding、RNN/LSTM/GRU、Seq2Seq模型和Attention机制等。然后介绍BERT的基础Transformer模型,这个模型最初用于机器翻译,但是它提出的Self-Attention被用于替换传统的RNN/LSTM/GRU模型。再然后是介绍BERT出现之前的Universal Sentence Embedding模型,包括ELMo和OpenAI GPT。接着介绍BERT模型是什么,它解决了之前模型的哪些问题从而可以达到这么好的效果。代码分析和案例介绍,通过解决实际问题加深理解

    4019 人正在学习 去看看 CSDN讲师

主要介绍Word2Vec中的Skip-Gram模型和CBOW模型。总结来说,skip-gram是用中心词预测周围词,预测的时候是一对word pair,等于对每一个中心词都有K个词作为output,对于一个词的预测有K次,所以能够更有效的从context中学习信息,但是总共预测K*V词。CBOW模型中input是context(周围词),而output是中心词。因此,skip gram的训练时间更长,但是对于一些出现频率不高的词,在CBOW中的学习效果就不日skip-gram。

1 Skip-gram

假如我们有一个句子“The dog barked at the mailman”。

  1. 首先,我们选句子中间的一个词作为我们的输入词,例如我们选取“dog”作为input word;
  2. 然后,有了input word以后,我们再定义一个叫做skip_window的参数,它代表着我们从当前input word的一侧(左边或右边)选取词的数量。如果skip_window=2,那么我们最终获得窗口中的词(包括input word在内)就是**[‘The’, ‘dog’,‘barked’, ‘at’]**。skip_window=2代表着选取左input word左侧2个词和右侧2个词进入我们的窗口,所以整个窗口大小span=2x2=4。另一个参数叫num_skips,它代表着我们从整个窗口中选取多少个不同的词作为我们的output word,当skip_window=2,num_skips=2时,我们将会得到两组(input word, output word)形式的训练数据,即(‘dog’, ‘barked’),(‘dog’, ‘the’)。
  3. 最后,神经网络基于这些训练数据将会输出一个概率分布,这个概率代表着我们的词典中的每个词是output word的可能性。这句话有点绕,我们来看个栗子。第二步中我们在设置skip_window和num_skips=2的情况下获得了两组训练数据。假如我们先拿一组数据 (‘dog’, ‘barked’)来训练神经网络,那么模型通过学习这个训练样本,会告诉我们词汇表中每个单词是“barked”的概率大小。

选定句子“The quick brown fox jumps over lazy dog”,设定我们的窗口大小为2(window_size=2),也就是说我们仅选输入词前后各两个词和输入词进行组合。下图中,蓝色代表input word,方框内代表位于窗口内的单词。

模型细节

我们如何来表示这些单词呢?
首先,我们都知道神经网络只能接受数值输入,我们不可能把一个单词字符串作为输入,因此我们得想个办法来表示这些单词。最常用的办法就是基于训练文档来构建我们自己的词汇表(vocabulary)再对单词进行one-hot编码。

假设从我们的训练文档中抽取出10000个唯一不重复的单词组成词汇表。我们对这10000个单词进行one-hot编码,得到的每个单词都是一个10000维的向量,向量每个维度的值只有0或者1,假如单词ants在词汇表中的出现位置为第3个,那么ants的向量就是一个第三维度取值为1,其他维都为0的10000维的向量(ants=[0,0, 1, 0, …, 0])。还是上面的例子,“The dog barked at the mailman”,那么我们基于这个句子,可以构建一个大小为5的词汇表(忽略大小写和标点符号):(“the”, “dog”, “barked”, “at”, “mailman”),我们对这个词汇表的单词进行编号0-4。那么”dog“就可以被表示为一个5维向量[0,1, 0, 0, 0]。

模型的输入如果为一个10000维的向量,那么输出也是一个10000维度(词汇表的大小)的向量,它包含了10000个概率,每一个概率代表着当前词是输入样本中output word的概率大小。

隐层

隐层没有使用任何激活函数,但是输出层使用了sotfmax。我们基于成对的单词来对神经网络进行训练,训练样本是 ( input word,output word ) 这样的单词对,input word和output word都是one-hot编码的向量。最终模型的输出是一个概率分布。

如果我们现在想用300个特征来表示一个单词(即每个词可以被表示为300维的向量)。那么隐层的权重矩阵应该为10000行,300列(隐层有300个结点)。Google在最新发布的基于Google news数据集训练的模型中使用的就是300个特征的词向量。词向量的维度是一个可以调节的超参数(在Python的gensim包中封装的Word2Vec接口默认的词向量大小为100, window_size为5)。

看下面的图片,左右两张图分别从不同角度代表了输入层-隐层的权重矩阵。左图中每一列代表一个10000维的词向量和隐层单个神经元连接的权重向量。从右边的图来看,每一行实际上代表了每个单词的词向量。

所以我们最终的目标就是学习这个隐层的权重矩阵。我们现在回来接着通过模型的定义来训练我们的这个模型。上面我们提到,input word和output word都会被我们进行one-hot编码。仔细想一下,我们的输入被one-hot编码以后大多数维度上都是0(实际上仅有一个位置为1),所以这个向量相当稀疏,那么会造成什么结果呢。如果我们将一个1 x 10000的向量和10000 x 300的矩阵相乘,它会消耗相当大的计算资源,为了高效计算,它仅仅会选择矩阵中对应的向量中维度值为1的索引行(这句话很绕),看图就明白。

我们来看一下上图中的矩阵运算,左边分别是1 x 5和5 x 3的矩阵,结果应该是1 x 3的矩阵,按照矩阵乘法的规则,结果的第一行第一列元素为0 x 17 + 0 x 23 + 0 x 4 + 1 x 10 + 0 x 11 = 10,同理可得其余两个元素为12,19。如果10000个维度的矩阵采用这样的计算方式是十分低效的。

为了有效地进行计算,这种稀疏状态下不会进行矩阵乘法计算,可以看到矩阵的计算的结果实际上是矩阵对应的向量中值为1的索引,上面的例子中,左边向量中取值为1的对应维度为3(下标从0开始),那么计算结果就是矩阵的第3行(下标从0开始)—— [10, 12, 19],这样模型中的隐层权重矩阵便成了一个”查找表“(lookup table),进行矩阵计算时,直接去查输入向量中取值为1的维度下对应的那些权重值。隐层的输出就是每个输入单词的“嵌入词向量”。

输出层
经过神经网络隐层的计算,ants这个词会从一个1 x 10000的向量变成1 x 300的向量,再被输入到输出层。输出层是一个softmax回归分类器,它的每个结点将会输出一个0-1之间的值(概率),这些所有输出层神经元结点的概率之和为1。下面是一个例子,训练样本为 (input word: “ants”, output word: “car”) 的计算示意图。

CBOW—连续词袋模型

CBOW的神经网络模型与skip-gram的神经网络模型也是互为镜像的。

现在的Corpus是这一个简单的只有四个单词的document:{I drink coffee everyday},我们选coffee作为中心词,window size设为2。也就是说,我们要根据单词"I","drink"和"everyday"来预测一个单词,并且我们希望这个单词是coffee。

输入层:上下文单词的onehot14维3个词

输出层:1*4维的向量(概率表示)

ram模型的输入输出是相反的。这里输入层是由one-hot编码的输入上下文{x1,,xC{x_1,…,x_C}}组成,其中窗口大小为CC,词汇表大小为VV。隐藏层是NN维的向量。最后输出层是也被one-hot编码的输出单词yy。被one-hot编码的输入向量通过一个V×NV×N维的权重矩阵WW连接到隐藏层;隐藏层通过一个N×VN×V的权重矩阵WW′连接到输出层。

接下来,我们假设我们知道输入与输出权重矩阵的大小。

  1. 第一步就是去计算隐藏层hh的输出。如下:
    (1)h=1CW(i=1Cxi)h = \frac{1}{C}W\cdot (\sum_{i=1}^C x_i)\tag{$1$}
    该输出就是输入向量的加权平均。这里的隐藏层与skip-gram的隐藏层明显不同。

  2. 第二部就是计算在输出层每个结点的输入。如下:
    (2)uj=vwjThu_{j}=v^{&#x27;T}_{wj}\cdot h\tag{$2$}
    其中vwjTv^{&#x27;T}_{wj}是输出矩阵WW^′的第jj列。

  3. 最后我们计算输出层的输出,输出yjy_j如下:
    (3)yc,j=p(wy,jw1,...,wc)=exp(uj)j=1Vexp(uj)y_{c,j} =p(w_{y,j}|w_1,...,w_c) = \frac{exp(u_{j})}{\sum^V_{j^{&#x27;}=1}exp(u^{&#x27;}j)}\tag{$3$}

通过BP(反向传播)算法及随机梯度下降来学习权重

在学习权重矩阵WWWW′过程中,我们可以给这些权重赋一个随机值来初始化。然后按序训练样本,逐个观察输出与真实值之间的误差,并计算这些误差的梯度。并在梯度方向纠正权重矩阵。这种方法被称为随机梯度下降。但这个衍生出来的方法叫做反向传播误差算法。

3 理论基础

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

后面将会介绍Word2Vec之基于Negative Sampling的 CBOW 和 skip-gram 模型

参考资料

  1. Skip-Gram模型理解
  2. An Intuitive Understanding of Word Embeddings: From Count Vectors
    to Word2Vec
    这一篇非常赞,介绍了embeddings的两种基本形式以及每种形式下的代表方法。
  3. 轻松理解CBOW
  4. word2vec中CBOW和Skip-Gram训练模型的原理
  5. CBOW与Skip-Gram模型基础
  6. 基于Hierarchical Softmax的 skip-gram 和 CBOW 模型数学理论,也很好。

nlp技术模块分类

阅读数 477

没有更多推荐了,返回首页