文本挖掘预处理之向量化与Hash Trick

https://www.cnblogs.com/pinard/p/6688348.html

文本挖掘的分词原理中,我们讲到了文本挖掘的预处理的关键一步:“分词”,而在做了分词后,如果我们是做文本分类聚类,则后面关键的特征预处理步骤有向量化或向量化的特例Hash Trick,本文我们就对向量化和特例Hash Trick预处理方法做一个总结。

1. 词袋模型

    在讲向量化与Hash Trick之前,我们先说说词袋模型(Bag of Words,简称BoW)。词袋模型假设我们不考虑文本中词与词之间的上下文关系,仅仅只考虑所有词的权重。而权重与词在文本中出现的频率有关。

    词袋模型首先会进行分词,在分词之后,通过统计每个词在文本中出现的次数,我们就可以得到该文本基于词的特征,如果将各个文本样本的这些词与对应的词频放在一起,就是我们常说的向量化。向量化完毕后一般也会使用TF-IDF进行特征的权重修正,再将特征进行标准化。 再进行一些其他的特征工程后,就可以将数据带入机器学习算法进行分类聚类了。

    总结下词袋模型的三部曲:分词(tokenizing),统计修订词特征值(counting)与标准化(normalizing)。

    与词袋模型非常类似的一个模型是词集模型(Set of Words,简称SoW),和词袋模型唯一的不同是它仅仅考虑词是否在文本中出现,而不考虑词频。也就是一个词在文本在文本中出现1次和多次特征处理是一样的。在大多数时候,我们使用词袋模型,后面的讨论也是以词袋模型为主。

    当然,词袋模型有很大的局限性,因为它仅仅考虑了词频,没有考虑上下文的关系,因此会丢失一部分文本的语义。但是大多数时候,如果我们的目的是分类聚类,则词袋模型表现的很好。

2. 词袋模型之向量化

    在词袋模型的统计词频这一步,我们会得到该文本中所有词的词频,有了词频,我们就可以用词向量表示这个文本。这里我们举一个例子,例子直接用scikit-learn的CountVectorizer类来完成,这个类可以帮我们完成文本的词频统计与向量化,代码如下:

    完整代码参见我的github:https://github.com/ljpzzz/machinelearning/blob/master/natural-language-processing/hash_trick.ipynb


from sklearn.feature_extraction.text import CountVectorizer

vectorizer=CountVectorizer()

corpus=["I come to China to travel",

    "This is a car polupar in China",         

    "I love tea and Apple ", 

    "The work is to write some papers in science"]

print vectorizer.fit_transform(corpus)


我们看看对于上面4个文本的处理输出如下:

  (0, 16) 1

  (0, 3) 1

  (0, 15) 2

  (0, 4) 1

  (1, 5) 1

  (1, 9) 1

  (1, 2) 1

  (1, 6) 1

  (1, 14) 1

  (1, 3) 1

  (2, 1) 1

  (2, 0) 1

  (2, 12) 1

  (2, 7) 1

  (3, 10) 1

  (3, 8) 1

  (3, 11) 1

  (3, 18) 1

  (3, 17) 1

  (3, 13) 1

  (3, 5) 1

  (3, 6) 1

  (3, 15) 1

    可以看出4个文本的词频已经统计出,在输出中,左边的括号中的第一个数字是文本的序号,第2个数字是词的序号,注意词的序号是基于所有的文档的。第三个数字就是我们的词频。

    我们可以进一步看看每个文本的词向量特征和各个特征代表的词,代码如下:


print vectorizer.fit_transform(corpus).toarray()

print vectorizer.get_feature_names()

 输出如下:

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

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

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

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

[u'and', u'apple', u'car', u'china', u'come', u'in', u'is', u'love', u'papers', u'polupar', u'science', u'some', u'tea', u'the', u'this', u'to', u'travel', u'work', u'write']

    可以看到我们一共有19个词,所以4个文本都是19维的特征向量。而每一维的向量依次对应了下面的19个词。另外由于词"I"在英文中是停用词,不参加词频的统计。

    由于大部分的文本都只会使用词汇表中的很少一部分的词,因此我们的词向量中会有大量的0。也就是说词向量是稀疏的。在实际应用中一般使用稀疏矩阵来存储。

    将文本做了词频统计后,我们一般会通过TF-IDF进行词特征值修订,这部分我们后面再讲。

    向量化的方法很好用,也很直接,但是在有些场景下很难使用,比如分词后的词汇表非常大,达到100万+,此时如果我们直接使用向量化的方法,将对应的样本对应特征矩阵载入内存,有可能将内存撑爆,在这种情况下我们怎么办呢?第一反应是我们要进行特征的降维,说的没错!而Hash Trick就是非常常用的文本特征降维方法。

3.  Hash Trick

    在大规模的文本处理中,由于特征的维度对应分词词汇表的大小,所以维度可能非常恐怖,此时需要进行降维,不能直接用我们上一节的向量化方法。而最常用的文本降维方法是Hash Trick。说到Hash,一点也不神秘,学过数据结构的同学都知道。这里的Hash意义也类似。

在Hash Trick里,我们会定义一个特征Hash后对应的哈希表的大小,这个哈希表的维度会远远小于我们的词汇表的特征维度,因此可以看成是降维。具体的方法是,对应任意一个特征名,我们会用Hash函数找到对应哈希表的位置,然后将该特征名对应的词频统计值累加到该哈希表位置。如果用数学语言表示,假如哈希函数hh使第ii个特征哈希到位置jj,即h(i)=jh(i)=j,则第ii个原始特征的词频数值ϕ(i)ϕ(i)将累加到哈希后的第jj个特征的词频数值ϕ¯ϕ¯上,即:


其中JJ是原始特征的维度。

但是上面的方法有一个问题,有可能两个原始特征的哈希后位置在一起导致词频累加特征值突然变大,为了解决这个问题,出现了hash Trick的变种signed hash trick,此时除了哈希函数hh,我们多了一个一个哈希函数:

这样做的好处是,哈希后的特征仍然是一个无偏的估计,不会导致某些哈希位置的值过大。

当然,大家会有疑惑,这种方法来处理特征,哈希后的特征是否能够很好的代表哈希前的特征呢?从实际应用中说,由于文本特征的高稀疏性,这么做是可行的。如果大家对理论上为何这种方法有效,建议参考论文:Feature hashing for large scale multitask learning.这里就不多说了。

    在scikit-learn的HashingVectorizer类中,实现了基于signed hash trick的算法,这里我们就用HashingVectorizer来实践一下Hash Trick,为了简单,我们使用上面的19维词汇表,并哈希降维到6维。当然在实际应用中,19维的数据根本不需要Hash Trick,这里只是做一个演示,代码如下:


fromsklearn.feature_extraction.textimport HashingVectorizer

vectorizer2=HashingVectorizer(n_features = 6,norm = None)printvectorizer2.fit_transform(corpus)

输出如下:

  (0, 1) 2.0

  (0, 2) -1.0

  (0, 4) 1.0

  (0, 5) -1.0

  (1, 0) 1.0

  (1, 1) 1.0

  (1, 2) -1.0

  (1, 5) -1.0

  (2, 0) 2.0

  (2, 5) -2.0

  (3, 0) 0.0

  (3, 1) 4.0

  (3, 2) -1.0

  (3, 3) 1.0

  (3, 5) -1.0

大家可以看到结果里面有负数,这是因为我们的哈希函数ξξ可以哈希到1或者-1导致的。

    和PCA类似,Hash Trick降维后的特征我们已经不知道它代表的特征名字和意义。此时我们不能像上一节向量化时候可以知道每一列的意义,所以Hash Trick的解释性不强。

4. 向量化与Hash Trick小结

    这里我们对向量化与它的特例Hash Trick做一个总结。在特征预处理的时候,我们什么时候用一般意义的向量化,什么时候用Hash Trick呢?标准也很简单。

    一般来说,只要词汇表的特征不至于太大,大到内存不够用,肯定是使用一般意义的向量化比较好。因为向量化的方法解释性很强,我们知道每一维特征对应哪一个词,进而我们还可以使用TF-IDF对各个词特征的权重修改,进一步完善特征的表示。

    而Hash Trick用大规模机器学习上,此时我们的词汇量极大,使用向量化方法内存不够用,而使用Hash Trick降维速度很快,降维后的特征仍然可以帮我们完成后续的分类和聚类工作。当然由于分布式计算框架的存在,其实一般我们不会出现内存不够的情况。因此,实际工作中我使用的都是特征向量化。

    向量化与Hash Trick就介绍到这里,下一篇我们讨论TF-IDF。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249