赞
踩
作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客
本文网址:
上述模型的方法在文本中单词数量较小时很好用,也很直接,但在有些场景下很难使用,比如分词后的词汇字典表非常大,达到100万+词(不是单字上百万个),此时如果直接使用词频向量或Tf-idf权重向量的方法,那么文本的特征向量的分量太多,占用的内存太大。有可能将内存撑爆。
在这种情况下我们该怎么办呢?
我们可以应用哈希向量技巧进行降维, 哈希向量是一种特征降维的技术手段。
无论是词频向量,还是权重向量,对于文本而言,每个单词代表一个维度的特征,单词的词频或权重值,就是该特征的特征值。
推广:
然后,有时候,特征值太多,并非所有的特征值都能够其关键作用,按照辩证唯物主义的观点,万事万物都有联系和普遍矛盾的,导致一个结果的原因有多种,有主要因素和次要因素,而矛盾有主要矛盾和矛盾的主要方面(特征),决结果产生影响的往往是主要矛盾和矛盾的主要方面。因此,不加区分的选择所有的特征参与模型计算,导致大量的计算工作放在次要矛盾的次要因素(特征)上。
有没有方法忽略这些次要矛盾或次要因素呢?
特征的降维就是这样的一种技术手段,hash向量就是特征降维的一种方法。
样本所包含的特征过多,过于庞大,导致计算量暴增。
而部分特征的特征性和区分性很小,这些特征对最终的结果其实影响很小。
去除掉矛盾中的次要方面和次要因素(特征),保留主要方面和主要特征。
提升计算和决策的速度和效率。
所谓特征降维,就是较少、降低特征的维度。
简单的说,对所有的特征,该合并的合并,该去掉的去掉,
部分特征信息的丢失
关于特征降维技术,后续会进一步的深入阐述。
(1)什么是hash
Hash是一种多对1的数据结构,在计算机中,是一个非常基础性的数据结构。
(2)什么是Hash表
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
(3)Hash函数
给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。
既然是多对一,就会出现多个输入关键值key,映射到相同的位置,这就是函数冲突。
解决hash冲突的方法与hash的应用相关。
(1)Hash表 + 链表
上述方法,并非是为了降维,而是为了进行快速、高效的数据存储和访问。
因此,需要通过链表存储所有的信息。
(2)合并降维:Hash的本质是“合并”
有些应用场合,需要把映射到相同位置的输入,合并在一起,不需要链表区分具备相同映射索引的输入,映射后具备相同索引的所有输入,合并为同一类型,起到降维的目的。
文本hash编码就采用的这种策略。
在文本分类中,特征的基本单元是“单词”,每个单词是一个特征,该单词出现的词频是特征值。
Hash函数可以将任意个数的单词,一个个映射到一个固定长度的散列数字中去。
这个映射的过程,就完成了不同单词的合并!!!即不同特征的合并,并给出了合并后的特征的编号[0 - (N-1)]。
比如有100万个单词的文本,如果没有hash,这就有100万种特征,假设Hahs表的长度N=1万,经过Hash之后,这些100万个特征就被合并成了1万特征,合并的方法就是Hahs函数。
Hash函数是一种典型的多对一映射,这种映射具备如下的特征:
(1)正向快速:
给定明文和 hash 算法,在有限时间和有限资源内能计算出 hash 值。
(2)逆向困难:
给定(若干) hash 值,在有限时间内很难(基本不可能)逆推出明文。
(3)输入敏感:
原始输入信息修改一点信息,产生的 hash 值看起来应该都有很大不同。
(4)碰撞避免:
很难找到两段内容不同的明文,使得它们的 hash 值一致(发生碰撞)。即对于任意两个不同的数据块,其hash值相同的可能性极小;对于一个给定的数据块,找到和它hash值相同的数据块极为困难。
(5)输出长度任意指定:
可以指定任意指定输出长度,比如指定N=10或N=1000.
目前流行的Hash函数, 包括MD4,MD5,SHA等。
hash映射的本质是特征提取,就原始的单词数据中,提取能够用于机器学习模型的特征。
(1)特征提取的方法:hash函数
(2)特征提取的输入:文本经过分词后的单词+词频
(3)特征提取后的输出:hash索引+词频
(4)hash之后的进一步处理:hash索引+词频=》转换成=》Hash词向量
每个索引代表一种特征,并采用OneHot编码,作为特征所在的位置!!!
该位置上的数值,就是特征该特征的特征值,就得到了特征向量!!!
如下图所示:
(1)生成hash函数对象,创建hash表
vectorizer = HashingVectorizer(n_features=6,stop_words = 'english')
(2)使用输入数据,进行hash映射
outputs = vectorizer.transform(输入数据)
(3)获得合并、映射后表格
- from sklearn.feature_extraction.text import HashingVectorizer
-
- corpus = ['smart boy', 'ate', 'bacon', 'a cat']
-
- # Hashingvectorizer是无状态的,你不需要fit它
- # Hash向量化时,这里指定向量长度为6
- vectorizer = HashingVectorizer(n_features=6,stop_words = 'english')
-
- # 进行hash转换
- counts = vectorizer.transform(corpus).todense()
-
- # 显示转换后的结果
- print(counts)
[[-0.70710678 -0.70710678 0. 0. 0. 0. ] [ 0. 0. 0. 1. 0. 0. ] [ 0. 0. 0. 0. -1. 0. ] [ 0. 1. 0. 0. 0. 0. ]]
备注:
长度任意指定:
不管输入文本的长度如何,不管输入文本中包含多少个“词”,输出词向量都会被hash成长度为6的词向量。
归一化:每个向量的分量值都会被限制在[0,1]之间。
- from sklearn.feature_extraction.text import HashingVectorizer
-
- corpus = [
- 'UNC played Duke in basketball',
- 'Duke lost the basketball game,game over',
- 'I ate a sandwich'
- ]
-
- # 生成转换对象
- vectorizer = HashingVectorizer(n_features = 3)
-
- # 进行转换
- counts = vectorizer.transform(corpus).todense()
-
- # 显示转换后的结果
- print(counts)
-
- counts.shape
[[ 0. 0. -1. ] [-0.33333333 -0.66666667 -0.66666667] [ 0.70710678 0. 0.70710678]]
Out[28]:
(3, 3)
备注:
Hash表达长度N越小,Hash冲突的可能性越大。
作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客
本文网址:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。