【NLP】任务



2019年06月08日    Author:Guofei

文章归类: 0x24_NLP    文章编号: 300

版权声明:本文作者是郭飞。转载随意,但需要标明原文链接,并通知本人
原文链接:https://www.guofei.site/2019/06/08/nlp_tasks.html


文本分类/文本聚类

文本分类

文本聚类

情感分析

step1:搜集一个褒义词/贬义词词典
step2:计算一句话中褒义词的数量 $cnt_p$,贬义词的数量 $cnt_n$,然后情感评分为 $\dfrac{cnt_p}{cnt_p+cnt_n}$
step3:另外,由于褒义词和贬义词的词典大小不一样,所以可以做个修正 $\dfrac{cnt_p/len_p}{cnt_p/len_p+cnt_n/len_n}$

机器翻译

信息检索

Information Retrieval(IR)

布尔检索:主要从数据结构/数据库的角度,探索如何提高关键词检索的性能。

向量空间模型

  1. 把用户输入的查询也作为文档
  2. 统一用 tf-idf 转化为向量
  3. 按照余弦相似度,检索出结果

信息提取

NER

问答系统

分为2部分

  1. 对用户的问题做分类模型
  2. 一个高效的检索系统,给出最接近的文档。

主题建模

根据输入的语料,给出主题

主要模型是

  • LDA(Latent Dirichlet Allocation)
  • LSI(Latent Semantics Indexing)

信息摘要

目的:给定一个文档,返回摘要。

思路:有较多实体和名词的句子,往往重要性较高。因此只需要构建一个重要性评分标准,然后找出前n句。如此简单的算法即可获得不错的效果。

方案1 : 返回每个段落的第一句话。这是最简单但往往有效的方法。

方案2
step1:给定一个文档,其有 n 句话。
step2:对每个句子i,求出它与其它 n-1 个句子的相似度
step3:对每个句子i,求出 i 与其它 n-1 个句子的平均相似度
step4:返回相似度最大的 k 个句子。

注:如何定义相似度呢?求两个句子对应的单词之间的 杰卡德相似系数,如果 Jaccard。。。。

代码如下:

分句+分词,没什么好说的。

import numpy as np

sentences_raw = '卷积神经网络是优雅且有用的图像算法。卷积本身是一种传统的图像处理方法。相比之下,它的优雅之处在于它能够自动计算卷积。它被用于图像识别、人脸识别等图像算法中'
# 分句
sentences_raw = [i for i in sentences_raw.split('。') if len(i) > 1]

# 分词
import jieba
import re

sentences = [jieba.lcut(sentence, cut_all=False) for sentence in sentences_raw]  # 拆词
regex = re.compile(u'[\u4e00-\u9fa5]')
sentences = [[word for word in sentence if regex.match(word) is not None] for sentence in
             sentences]  # jieba 拆开的词,一串数字也作为一个词返回,这里过滤一下
# sentences=[[word for word in sentence if word not in stops] for sentence in sentences] # 停词
sentences = [' '.join(sentence) for sentence in sentences]

摘要提取算法


def get_score(sent1, sent2):
    if len(sent1) == 0 or len(sent2) == 0:
        return 0

    return len(sent1 & sent2) / len(sent1 | sent2)


def get_avg_score(sent1, sentences):
    return np.average([get_score(sent1, sent2) for sent2 in sentences])


def get_summary_idx(sentences):
    sentences_ = [set(sentence.split(' ')) for sentence in sentences]
    return np.argmax([get_avg_score(sent1, sentences_) for sent1 in sentences_])


summary_idx = get_summary_idx(sentences)
summary = sentences_raw[summary_idx]
print(summary)

卷积神经网络是优雅且有用的图像算法

看起来效果还行

以上算法还可以用来 减少冗余

改进:

  1. 动态调整分数。
    • 根据所在位置调整分数,首句和尾句的权重加大
    • 根据标点符号调整分数,陈述句、疑问句、感叹句的权重各有不同
    • 根据关键词调整分数,出现“总而言之”,“总之”,“本文”,“综上所述”的,增加分数;出现“比如”,“例如”的,减少分数 用单词的 TF-IDF 评分。

语言检测

给出某个文本使用的是哪种语言

OCR

Sentiment Classification

难点

相对于单词数量来说,训练集太少,例如,你的训练集有10k,但涉及到的单词量也是10k
难点解决:利用其它模型训练好的 word embedding 进行转化。

简单版模型

假设共有5个分数(label有5种)。对于某条评论,每个单词用 embedding matrix 转化为向量后(假设转化后的向量是$300\times 1$的),把向量求平均,输入 softmax 模型进行回归(weights 形状是$5\times 300$)。

RNN for sentiment classification

上面的方法有个缺陷,例如句子是 “Completely lacking in good taste, good service, and good ambience.”,这个句子会被判别为非常正向。

这是一种 Many-to-one 的RNN
这种模型可用性很好的原因是,你用近义词替换后,模型的输出结果会差不多。

消除偏见

由于训练用的文本有偏见,embedding matrix 也会有偏见,例如性别偏见:
Man: computer programmers as woman :Homemaker
偏见会导致 embedding matrix 在使用时的问题。

做法(以sexual bias为例):
step1. Identify bias direction $avg (e_{he}-e_{she},e_{male}-e_{female},…)$,这就找到表示性别的轴
step2. Neutralize: For every word that is not definitional, project to get rid of bias.就是把那些性别无关的单词(如computer programmers),投影到轴上
step3. Equalize pairs. 使得与性别有关的单词(如gril和boy)词组到computer programmers的距离相等。

生成模型

(这个图里面,左边和右边是不同的RNN)

  1. 翻译,Many-to-Many RNN model.
  2. 读图讲故事。模型的输入是一张图,输出是一句话,描述图中的内容。
    做法:一个训练好点的CNN,去除最后的 softmax 层,将这个输出作为RNN的输入。

2020年更新:
这个模型叫做Seq2Seq,有这几种类型

  • 图中的输出和输入不是同时,这个叫做 Delayed Many2Many,左半部分的神经元都一样,叫做 Encoder,右半部分的神经元都一样,叫做 Decoder。另外如果输入输出同时的话,叫做 Many-to-Many,也是最原始的那个RNN
  • 每一块可以是 LSTM,GRU等。GRU更常见
  • 针对右半部分,每个节点输入的y可以是上一个节点的输出(叫做AR,例如DeepAR),也可以是真实值(叫做MQRNN)

DeepAR

DeepAR:(论文 https://arxiv.org/abs/1704.04110)

  • 神经网络节点是GRU,
  • 输出不是y,而是正态分布的$u,\sigma$,损失函数会相应调整。

MQRNN

(论文 https://arxiv.org/abs/1711.11053)

  • encoder用的是GRU,decoder用的是DNN
  • 输出的是分位数。并且有对应的损失函数。

WaveNet(https://arxiv.org/abs/1609.03499)

Attention(https://arxiv.org/abs/1706.03762)

Picking the most likely sentence

缺点一样,在生成过程中,单词是依概率选取的。
解决:Picking the most likely sentence
我们想要找到$\arg\max P(y^{<1>},…,y^{}\mid x)$

  • 不能用遍历,情况太多了。假设有$10k$个单词,要生成长度为10的句子,那么搜索空间是$10k^{10}$,非常巨大
  • 不能用 greedy search (因为未必是全局最大)
  • 用 beam search (未必能达到最优,但往往是最优)
    1. 有一个 hyperparameter ,B,下面以$B=3$为例
    2. 每一步生成 top 3 (top B)个单词,放到下一步
    3. 如果要生成长度为10的句子,那么搜索空间变成$3^10$
      (如果B=1,等价于 greedy search)

beam search的改进
新问题,$\arg\max\limits_y P(y^{<1>},…,y^{}\mid x) = \arg\max\limits_y \prod\limits_{t=1}^{T_y}P(y^{}\mid x,y^{<1>},...,y^{})$这个数字实际上非常小,很可能低于计算机所能表示的下界,尤其是要生成的句子很长的时候。

  • 我们考虑用这个$\arg\max\limits_y \sum\limits_{t=1}^{T_y} \log P(y^{}\mid x,y^{<1>},...,y^{})$
  • 进一步,为了将句子的长度也纳入最优化的考虑因素中,用这个,$\arg\max\limits_y \dfrac{1}{T_y^{\alpha}}\sum\limits_{t=1}^{T_y} \log P(y^{}\mid x,y^{<1>},...,y^{})$,这里,$\alpha$是一个 hyperparameter
    • $\alpha=0$,就是整个句子概率最大
    • $\alpha=1$,就是平均到每个单词,概率最大

假设你有一个好的翻译(可能来自人的翻译),记为 $ y^* $
算法用 beam search 计算出的句子,记为$\hat y$

可以用算法计算 $P(y^* \mid x),P(\hat y \mid x)$

  • case1:$P(y^* \mid x)>P(\hat y \mid x)$,需要调整 beam search 算法
  • case2:$P(y^* \mid x)\leq P(\hat y \mid x)$,需要调整 RNN

Bleu Score (bilingual evaluation understudy)是一种给文本生成效果打分的方法。
假如我们有人工翻译的标准答案,和机器翻译的结果:

Reference 1: The cat is on the mat.
Reference 2: There is a cat on the mat.
MT output: The cat the cat on the mat.

step1:对于 MT output,用n-gram拆分,并计数
这里假设用 2-gram,计数结果是{‘the cat’:2, ‘cat the’:1, ‘cat on’:1, ‘on the’: 1, ‘the mat’: 1}
step2:对step1中拆分出的gram,找到标准答案的计数中最大的那个,结果是{‘the cat’:1, ‘cat the’:0, ‘cat on’:1, ‘on the’: 1, ‘the mat’: 1}
step3: sum(step2)/sum(step1) 就是 Bleu Score

  • 可以是 n-gram
  • 如果 MT output 与某个标准答案完全一样,得分为1
  • 假设 $p_n=$ Bleu score on n-grams,用$BP * \exp (1/4 \sum\limits_{n=1}^4 p_n)$作为总分,其中,$BP=\exp(1-\max(MTOutputLength/ReferenceOutputLength))$
    (BP 是 brevity penalty 的缩写)

Attention Model Intuition

https://www.coursera.org/learn/nlp-sequence-models/lecture/lSwVa/attention-model

语音识别

Speech recognition 解决的问题是,输入的音频,$T_x»T_y$

https://www.coursera.org/learn/nlp-sequence-models/lecture/sjiUm/speech-recognition

Trigger Word Detection

https://www.coursera.org/learn/nlp-sequence-models/lecture/Li4ts/trigger-word-detection

常见 NLP 任务

1、token-level task:token级别的任务. 如完形填空(Cloze), 预测句子中某个位置的单词; 或者实体识别; 或是词性标注; SQuAD等.

  • 1.1 Cloze task :BERT模型预训练的两个任务之一, 完形填空任务。给出句子中其他的上下文token, 推测出当前位置应当是什么token. BERT在预训练时使用 masked language model, 即在与训练时, 将句子中的部分token用【masked】这个特殊的token进行替换,然后目标就是预测[masked]对应位置的单词.
  • 1.2. SQuAD(Standford Question Answering Dataset) task:这是一个生成式的任务. 样本为语句对. 给出一个问题, 和一段来自于Wikipedia的文本, 其中这段文本之中, 包含这个问题的答案, 返回一短语句作为答案. 因为给出答案, 这是一个生成式的问题, 这个问题的特殊性在于最终的答案包含在语句对的文本内容之中, 是有范围的, 而且是连续分布在内容之中的.因此, 我们找出答案在文本语句的开始和结尾处, 就能找到最后的答案. 通过对文本语句序列中每个token对应的所有hidden vector做softmax判断是开始的概率和是结束的概率, 最大化这个概率就能进行训练, 并得到输出的结果.
  • 1.3 Named Entity Recognition(NER)对每个token打标签, 判断每个token的类别.
    • SpaCy:基于Python的NER系统
    • Stanford NER:基于JAVA的NER系统

2、sequence-level (Segment-level) task:序列级别的任务(也叫做句子级别的任务). 如情感分类等各种句子分类问题; 推断两个句子的是否是同义等.

  • 2.1 NLI(Natural Language Inference) task:自然语言推断任务, 即给出一对(a pair of)句子, 判断两个句子是entailment(相近), contradiction(矛盾)还是neutral(中立)的. 由于也是分类问题, 也被称为sentence pair classification tasks.
    • 在智能问答, 智能客服, 多轮对话中有应用.
    • 常用的数据集有:
    • MNLI(Multi-Genre Natural Language Inference): 是GLUE Datasets(General Language Understanding Evaluation)中的一个数据集. 是一个大规模的来源众多的数据集, 目的就是推断两个句子是意思相近, 矛盾, 还是无关的.
    • WNLI(Winograd NLI)
  • 2.2. Sentence Pair Classification tasks. 两个句子相关性的分类问题, NLI task是其中的特殊情况. 经典的此类问题和对应的数据集有:
    • QQP(Quora Question Pairs): 这是一个二分类数据集. 目的是判断两个来自于Quora的问题句子在语义上是否是等价的.
    • QNLI(Question Natural Language Inference): 也是一个二分类问题, 两个句子是一个(question, answer)对. 正样本为answer是对应question的答案, 负样本则相反.
    • STS-B(Semantic Textual Similarity Benchmark): 这是一个类似回归的问题. 给出一对句子, 使用1~5的评分评价两者在语义上的相似程度.
    • MRPC(Microsoft Research Paraphrase Corpus): 句子对来源于对同一条新闻的评论. 判断这一对句子在语义上是否相同.
    • RTE(Recognizing Textual Entailment): 是一个二分类问题, 类似于MNLI, 但是数据量少很多.
  • 2.3. Single Sentence Classification tasks
    • SST-2(Stanford Sentiment Treebank): 单句的二分类问题, 句子的来源于人们对一部电影的评价, 判断这个句子的情感.
    • CoLA(Corpus of Linguistic Acceptability): 单句的二分类问题, 判断一个英文句子在语法上是不是可接受的.
  • 2.4. SWAG(Situations With Adversarial Generations) 给出一个陈述句子和4个备选句子, 判断前者与后者中的哪一个最有逻辑的连续性, 相当于阅读理解问题.

常用 NLP 工具

spaCy

https://github.com/explosion/spaCy

import spacy

nlp = spacy.load("en_core_web_sm")
doc = nlp("This is a sentence.")
print([(w.text, w.pos_) for w in doc])


nlp = spacy.load("zh_core_web_sm")
doc = nlp("我叫郭飞,是一名算法工程师。")
print([(w.text, w.pos_) for w in doc])
# [('我', 'PRON'), ('叫', 'VERB'), ('郭飞', 'PROPN'), (',', 'PUNCT'), ('是', 'VERB'), ('一', 'NUM'), ('名', 'NUM'), ('算法', 'NOUN'), ('工程师', 'NOUN'), ('。', 'PUNCT')]

中文分词工具 jieba

中文转拼音工具 Pypinyin

# pip install pypinyin

from pypinyin import lazy_pinyin, Style

lazy_pinyin('我叫郭飞,是一名算法工程师', style=Style.TONE3)
# ['wo3', 'jiao4', 'guo1', 'fei1', ',', 'shi4', 'yi1', 'ming2', 'suan4', 'fa3', 'gong1', 'cheng2', 'shi1']

您的支持将鼓励我继续创作!