NLP札记3-信息抽取

2021-03-02 16:27:01 浏览数 (1)

信息抽取

信息抽取是个宽泛的概念,指的是从非结构化的文本中提取出结构化的信息来的一种技术。信息抽取(information extraction),即从自然语言文本中,抽取出特定的事件或事实信息,帮助我们将海量内容自动分类、提取和重构。信息通常包括实体(entity)、关系(relation)、事件(event)

新词提取

新词

新词指的是词典之外的词语。新词的提取分为:

  1. 提取大量的文本(生语料)中的词语,无论新旧
  2. 用词典过滤掉已有的词语,得到新的词语
信息熵

信息熵指的是某条消息所含的信息量。不确定性越大,信息量越大。计算方法如下:

H(x)=-sum_xp(x)logp(x)

如果对数函数的底数是2,信息上的单位就是比特

具体到新词提取中,给定字符串S作为词语选取,X定义为左边可能出现的字符(左邻字),则成H(X)为S的左信息熵

互信息

互信息指的是两个离散型随机变量XY之间的相关程度的度量。 $$ begin{align} I(X;Y) & =sum_{x,y}p(x,y)log frac{p(x,y)}{p(x)p(y)} & = E_{p(x,y)} logfrac{p(x,y)}{p(x)p(y)} end{align} $$ 在韦恩图中,

  • 并集:联合分布的信息熵H(X,Y)
  • 差集:条件熵H(X|Y)
  • 交集:互信息H(X;Y)

互信息越大,两个变量的关系越密切。同时发生的可能性也就越大。

提取新词

有了信息熵和互信息,将两个指标低于一定阈值的片段过滤掉,剩下的片段按照频次降序排列,截取最高频次的N个片段,完成词语的提取流程。具体模块在com.hankcs.hanlp.mining.word.NewWordDiscover相应的接口com.hankcs.hanlp.HanLP#extractWords

代码语言:javascript复制
word_life_list = HanLP.extractWords(IOUtil.newBufferedReader(corpus), 100)   # 提取100个关键词

接口的参数为

  • reader 从reader中获取文本,逐行读取和处理,内存更省
  • size 需要提取词语的数量
  • NewWordsOnly 是否只提取词典中没有的词语,返回OOV
  • max_word_len 词语最长长度,默认是4
  • min_freq 词语最低频率
  • min_entropy 词语最低熵。0.5左右,该值越大,越短的词语越容易被提取出来。
  • min_aggregation 词语最低互信息,一般50-200。该值越大,越长的词语越容易被提取出来

关键词提取

提取文章中重要的单词,而不是限于词语的新鲜程度,成为关键词提取

在进行提取的过程中,根据一份还是多份文档,提取算法分为单文档和多文档算法

  • 单文档:词频和TextRank
  • 多文档:TF-IDF
词频

文章中作者反复提及到的词语,通过统计文章每种词语的词频并排序,获取关键词。但是比如某些词语,比如“的”反复出现,但是并不是关键词。词频统计的步骤:

  • 分词
  • 停用词过滤
  • 按词频统计前n个
代码语言:javascript复制
counter = TermFrequencyCounter()
counter.add("加油加油中国队")
counter.add("中国观众在给中国队加油")
for termFrequency in counter:
  print("%s = %d" %(termFrenquency.getTrem(), termFrequency.getFrequency()))
print(counter.top(2))

# 结果
中国=2
中国队=1
加油=3
观众=1
高呼=1
[加油=3,中国=1]
[女排,观众,欢呼]
  • 遍历counter默认是按照字典顺序遍历
  • top(N)返回的是词频最高的前N个单词及词频,降序排列
  • 标点符号等停用分词已经去除了,分词结果以语境为主
  • 索引模式:激活内置分词器的索引模式
代码语言:javascript复制
counter.getSegment().enableIndexMode(true);  # 激活索引模式
counter.setSegment(new PerceptronLexicalAnalyzer().enableIndexMode(true));  # 切换分词器

笔记:使用词频统计的缺陷是,高频词语不等价于关键词。比如所有报道“奥运会”的文章中,将“奥运会”作为关键词并不合适,用户希望看到的是每篇文章的特色之处,而不是共性。

TF-IDF

TF-IDF(Term Frequency-Inverse Document Frequency, 词频-倒排文档频次)是信息检索中一个重要的词语重要程度的统计指标,广泛用于搜索引擎中,它属于多文档提取方法。综合考虑词语的稀有程度:

  • 正比于它在文中的频次
  • 反比于有多少文档包含它:包含该词语的文档越多,越不能体现文档的特色。
  • 计算方法有多种,如下一种
begin{align}TF-IDF(t,d)& = frac{TF(t,d)}{DF(t)} & = TF(t,d)cdot IDF(t)end{align}

上面每个参数的解释

  • t代表的是term
  • d代表的是document
  • TF(t,d)代表的是td中的出现频次
  • DF(t)代表的是多少篇文档包含t
  • DF的倒数成为IDF
代码语言:javascript复制
counter = TfIdfCounter()   # 调用方法的类
counter.add("<id1>, <内容>")  # 输入多篇文章
counter.add("<id2>, <内容>")
counter.add("<id3>, <内容>")
counter.compute()   # 输入完毕
for id in counter.documents():
  print(id   ":"   counter.getKeywordsOf(id, 3).toString())   # 根据每篇文章的TF-IDF提取关键词
  • add函数接受两个参数:文档id和文档内容
  • documents方法返回所有的文档id,供用户遍历
  • getKeywordsOf(id, 3)的两个参数:文档id和提取的关键词个数
TextRank

如果没有大型的语料库或者存储IDF的内存,又想改善瓷片统计的效果,使用TextRank方法。TextRank实际上就是谷歌的PageTank文本上的应用

PageRank是一种用于排序网页的随机算法。基本原理如下

  • 互联网看作是有向图,网页视作为节点
  • 节点V_i到节点V_j的超链接视作有向边
  • 初始化每个节点的权重S(V_i)都是1,通过迭代的方式更新每个节点的权重,更新的表达式为
S(V_i)=(1-d) d*sum_{V_j in In(V_i)}frac{1}{|Out(V_j)|}S(V_j)
  1. d是0-1之前的常数因子,用户点击链接跳出当前链接当前网站的概率
  2. In(V_i)表示链接V_i的集合
  3. Out(V_j)表示从v_j出发链接到的集合
  4. 外链权重和外链总数成反比,与提供外链的网站权重成正比

笔记:并不是外链越多,PR就越高。外链越多,权重就越低。

PageRank应用到关键词提取中,将单词看做是节点。每个单词的外链是来自前后固定大小的窗口内的所有单词。

代码语言:javascript复制
keyword_list = HanLP.extractKeyWord(content, 5)

短语提取

固定多词表达串的识别。常用于搜索引擎的自动推荐,文档的简介生成等。

代码语言:javascript复制
pharse_list = HanLP.extractPharse(text, 5)  # 两个参数是文档的内容和所需短语个数

关键句提取

BM25

一般的PageRank在句子颗粒度上行不通的,因为一篇文章中几乎不会出现两句完全相同的句子。引入了BM25算法衡量句子的相似度,改进连接的权重计算。

在搜索引擎中,查询串query是由多个词语构成的。BM25解决的是衡量多个词语与文档的关联程度。几个定义如下:

  • Q为查询语句,由关键字q_1,…,q_n组成
  • D是被检索的文档
  • k_ld是两个常量,avgDL是所有文档的平均长度

BM25的定义如下:

mathrm{BM} 25(D, Q)=sum_{i=1}^{n} operatorname{IDF}left(q_{i}right) cdot frac{operatorname{TF}left(q_{i}, Dright) cdotleft(k_{1} 1right)}{operatorname{TF}left(q_{i}, Dright) k_{1} cdotleft(1-b b cdot frac{|D|}{operatorname{avg} D L}right)}

上面式子的特点

  1. 先对查询语句中所有单词的IDF加权求和,两个参数和TF可以看做是调整IDF权重的参数
  2. k_1越大,TF对正面文档得分的正面影响就越大;b越大,TF负面文档得分的正面影响就越大
  3. TF-IDF 中,当IDF固定时,得分正比于TF,长文档占据优势;BM25中,TF对得分的影响还必须考虑文档长度

TF-IDF的表达式再现:

begin{align}TF-IDF(t,d)& = frac{TF(t,d)}{DF(t)} & = TF(t,d)cdot IDF(t)end{align}
TextRank

在上面的BM25算法中,将句子视作一个查询语句,相邻的句子视作待查询的文档,得到它们之间的相似度。将该相似度看做是PageRank中链接的权重,得到了TextRank算法。

mathrm{WS}left(V_{i}right)=(1-d) d times sum_{V_{j} in ln left(V_{i}right)} frac{mathrm{BM} 25left(V_{i}, V_{j}right)}{sum_{V_{k} in O uleft(V_{j}right) mathrm{BM} 25left(V_{k}, V_{j}right)}} mathrm{WS}left(V_{j}right)

TextRank关键句提取模块的实现为TextRankSentence。核心的Java代码为

代码语言:javascript复制
for (int _ = 0; _ < max_iter;   _)
{
  double[] m = new double[D];
  double max_diff = 0;
  for (int i = 0; i < D;   i)
  {
    m[i] = 1 - d;
    for (int j = 0; j < D;   j)  /*上面表达式中的第一个求和式子*/
    {
      if (j == 1 || weight_sum[j] == 0) continue;
      m[i]  = (d * weight[j][i] / weight_sum[j] * vertex[j]);
    }
    double diff = Math.abs(m[i] - vertex[i]);
    if (diff > max_diff)
    {
      max_diff = diff;
    }
  }
  vertex = m;
  if (max_diff <= min_diff) break;
}

当两次迭代间权重最大变化量小于阈值min_diff,或者总的迭代次数达到max_iter时算法终止。

代码语言:javascript复制
sentence_list = HanLP.extractSummary(document,3)  # 两个参数:文档和所需要的句子数量

0 人点赞