【特征工程】Chap3 Text Data: Flatten, Filtering, Chunking

本章介绍文本的特种工程。从最简单的 bag-of-words开始。下一章会介绍tf-idf。

Bag of X: Turning Natural Text into Flat Vectors

简单而好理解的特征虽然不一定得到最精确的模型,但从简单开始,只有到必须的时候才增加复杂性确实是好主意。

bag-of-words,一个词数统计的列表,虽然找不到文本中特殊的词,但可以发现那些多次出现的词。这对解决文本分类问题,或者提取文本关键信息(从文本中提取和input text query有关的信息)是足够的。因为词的出现与否是文章主题的强反应。

Bag-of-words

将文本转换为词向量,flat vector. 原文本是词的序列而bow不是序列,bow只记住了每个词出现的次数。同时bow也不表达任何词的等级

bow中,每个词代表向量的一个维度,若向量是n维的,则该文本表示n维空间中的一个点。

Bag-of-N-Grams

bon,bow的进阶。 bon长度为n的tokens序列,保留了更多的原文本序列结构,因此包含更多信息。但是,k个不同的词就有k*k个bigrams(2grams),虽然实际不会有这么多但仍比unigram多很多,这意味着更加大更稀疏的特征空间。同时,计算存储和模型也更麻烦。

举个例子:

关键:

from sklearn.feature_extraction.text import CountVectorizer
CountVectorizer
>>> import pandas
>>> import json
>>> from sklearn.feature_extraction.text import CountVectorizer
# Load the first 10,000 reviews
>>> f = open('data/yelp/v6/yelp_dataset_challenge_academic_dataset/yelp_academic_dataset_review.json')
>>> js = []
>>> for i in range(10000):
... js.append(json.loads(f.readline()))
>>> f.close()
>>> review_df = pd.DataFrame(js)
# Create feature transformers for unigram, bigram, and trigram.
# The default ignores single-character words, which is useful in practice because it trims
# uninformative words. But we explicitly include them in this example for illustration purposes.
>>> bow_converter = CountVectorizer(token_pattern='(?u)\\b\\w+\\b')
>>> bigram_converter = CountVectorizer(ngram_range=(2,2), token_pattern='(?u)\\b\\w+\\b')
>>> trigram_converter = CountVectorizer(ngram_range=(3,3), token_pattern='(?u)\\b\\w+\\b')
# Fit the transformers and look at vocabulary size
>>> bow_converter.fit(review_df['text'])
>>> words = bow_converter.get_feature_names()
>>> bigram_converter.fit(review_df['text'])
>>> bigrams = bigram_converter.get_feature_names()
>>> trigram_converter.fit(review_df['text'])
>>> trigrams = trigram_converter.get_feature_names()
>>> print (len(words), len(bigrams), len(trigrams))
26047 346301 847545
# Sneak a peek at the ngrams themselves
>>> words[:10]
['0', '00', '000', '0002', '00am', '00ish', '00pm', '01', '01am', '02']
>>> bigrams[-10:]
['zucchinis at',
'zucchinis took',
'zucchinis we',
'zuma over',
'zuppa di',
'zuppa toscana',
'zuppe di',
'zurich and',
'zz top',
'à la']
>>> trigrams[:10]
['0 10 definitely',
'0 2 also',
'0 25 per',
'0 3 miles',
'0 30 a',
'0 30 everything',
'0 30 lb',
'0 35 tip',
'0 5 curry',
'0 5 pork']

可以看出随着n增加,ngrams数目也是暴增的


Filtering for Cleaner Features

通过过滤让bow或者bon更有用。


Stopwords

文本分类和提取不需要对文本太深入的理解。比如'Emma knocked on the door','on','the' 这两个词不包含什么信息。代词介词一般也不包含什么信息。也就是说,这些词是可以去掉的。

NLTK包含了语言学家定义的 stopword包。

Frequency-based filtering

stopword可以过滤那些普通平常的词,去掉没意义的特征。同时也有其他统计方法来定义“common words”。下面介绍频率统计。

Frequent words

词频统计是过滤特殊文本库中的common words和一般性文本库的好方法。

For instance, the phrase “New York Times” and each ofthe individual words appear frequently in the New York Times articles dataset. Theword “house” appears often in the phrase “House of Commons” in the Hansard corpus

of Canadian parliament debates

这些词在一般的语言中有意义,但在corpus中,这个语料库中就没意义了,所以手选的stopword不能抓到特殊语料库中的stopword。

在纽约时报语料库中词频最高的是times,有时候是个好主意把这个词去掉。在实践中词频统计和stopword结合会有帮助。但是选择怎样的频率来去掉高频词是有难度的,需要手工选择。

Rare words

根据具体的任务,有时候需要将极少出现的词去掉。对模型来说,整个语料库中,词只在一两篇文章出现过的,通常提供噪声多过有用信息。

The set of 1.6 million Yelp reviews contains 357,481 unique words (tokenizedby space and punctuation characters), 189,915 of which appear in only one review, and41,162 in two reviews. Over 60% of the vocabulary occurs rarely. This is a so-called heavy-tailed distribution, and it is very common in real-world data.

稀有词很容易辨认并取除,也可考虑将其都归为一类计数,作为附加的特征。


Stemming 词干

简单的parsing会带来一个问题: 一个词的不同变种会被算作不同的词. 如: flower, flowers; swim,swimming, swimming等等. 

stemming 就是将词划分成其基本的词干的形式. 有许多方法, 包括基于语言学规则的, 或者基于统计的. 有一种方法叫 lemmatization.(wiki介绍)

英语最广泛使用的stemming工具是 Porter stemmer

可以看出大部分能词性还原,也有部分不准确的.


Atoms of Meaning: From Words to  N-Grams to Phrases

语义的基本单位, 从词到n-grams到短语.

bow的概念很好理解,但计算机知道一个词是什么吗? 一个文本文档是以字符串的形式电子表达的, 根本上就是一字符的序列. 即使对于JSON或HTML这种半结构化的数据, 他们有标签和结构, 基本单位依旧是字符串.  他们是如何变成词的序列的?

所以接下来我们来讨论 parsing and tokenization.

parsing and tokenization

parsing是将纯文本之外的结构从原始数据中取除. 如网页中的各种url, headers, footers 等等.

tokenization(可以理解为分词) 是在得到纯文本后, 将字符序列转换成token序列. 每个token可以来表示一个词. tokenizer 需要知道哪里是token的开始和结尾. 在英语中, 空格可以很好的作为分隔符(中文句子中没有空格), 以及各种标点符号. 

特别注意: 这种分析是在句子层面完成的,而不是整个文档. 比如 n-grams, 甚至 更复杂的word2vec 也是在句子,段落层面工作的. 在这中情况下, 要先将文档划分成句子再 tokenize each sentence into words.

OMT: 注意字符串编码.


Collocation Extraction for Phrase Detection

Manning and Schütze (1999: 141): “A COLLOCATION is an expression consisting of two or more words that correspond to some conventional way of saying things.”

collcation 可以理解为 有用的短语. 即这个短语比 组成该短语的词的意思之和 包含了更多的意思. 如: strong tea 的意思是浓茶, 就与 强壮的  茶 意思不同. 而cute puppy 就不是个collocation, 因为 cute + puppy 就等于可爱的小狗的意思. 

同时, collocation 不一定是连续序列. 如: Emma knocked on the door. 中有collocation "knock door". 因此, 不是每个 collocation 都是 n-grams, 相反的, 不是每个n-grams 都被认为是个collocation.

正因为collocation 含有比其组成的部分更多的意思, 那么单个的word count 就不能充分表示其意思了. 所以 BOW在这里达不到表达的标准. BOW的另一个缺点/问题是,BOW关注了太多没有意义的序列, 而对有意义的序列的捕捉不够.

那么,怎么捕捉collocation这种有用的特征呢? 一种方式是预定义, 非常费时费力. 对于那些针对特殊领域的, 包含专业术语的语料库这可能是可行的操作. 但对于那些在不停扩大的语料库,不停进行更新的工作就需要太多人工了.

下面就介绍用统计学方式找短语的方法:

Frequency-based method

统计最频繁的n-grams:


Hypothesis testing for collocation extraction

基于出现次数的方式太粗糙了, 我们还是需要找到更聪明的统计方式来更简单的找到有意义的短语.

key idea就是 是否两个词一起出现的频率高于随机一起出现的频率.

所用方式是 hypothesis testing.

对数据集中每对词, Hypothesis1(H1) 表示word1 和 word2 无关,二者独立. H2表示word1 的出现改变了word2出现的可能性, H2表明这两个词可以组成短语. 现在问题就变成了: 在一个语料库中观察到的词出现次数是从一个什么样的模型生成的, 一组词是独立出现的, 还是出现的概率是相关的?



通过 likelihood比 来识别常见短语的算法是这么分析的:

  1. 对单独的一个词计算出现概率 P(w).
  2. 对所有bigrams(不重复), 计算这对词出现的条件概率 P(w2/w1).
  3. 对所有bigrams(不重复), 计算似然比 log λ
  4. 似然比排序
  5. 取有 最小似然比 的bigrams 作为特征. (intuition: log λ 最小意味着 L(Data; H2) >> L(Data;H1),  即这对词不相关的可能性远大于其相关的可能性, 相当于P(w2) << P(w2/w1))


最便捷的方式还是对n-grams计数,而且考虑计算复杂度,一般只对连续的bigrams最多trigrams. 而要考虑更长的短语的时候,就要用其他方式: 如chunking 或者 结合part-of-speech tagging(接下来介绍)


Chunking and Part-of-Speech Tagging

首先,chunking是NLP中很重要的一个概念:点击打开链接, 大致可以理解为词语含义的层次,从抽象到具体.


词类:利用part-of-speech标签


chunking就是通过这样的词类标记将一段语料进行抽象抽取, 通常都是名词, 这样出来的名词短语通常会包含更多的信息. python可以用nltk实现.


总结

  • Bag-of-words 简单易懂, 可用于做文本分类和搜索. 但有时候过于简单
  • Bag-of-ngrams 增加了存储计算等成本, 存在维度灾难的问题,所有通常n不会超过3.
  • collocation extraction 提取更有意义的短语, 实践中只考虑 连续短语. 用统计学方法进行过滤

下一章将学习 ti-idf.

猜你喜欢

转载自blog.csdn.net/nemoyy/article/details/79519911