5. 参考
文本挖掘预处理之TF-IDF:文本挖掘预处理之TF-IDF - 刘建平Pinard - 博客园
使用不同的方法计算TF-IDF值:使用不同的方法计算TF-IDF值 - 简书
sklearn-点互信息和互信息:sklearn:点互信息和互信息 - 专注计算机体系结构 - CSDN博客
如何进行特征选择(理论篇)机器学习你会遇到的“坑”:如何进行特征选择(理论篇)机器学习你会遇到的“坑”
1. 每一个文档的关键词(或主题词)包括哪些?
2. 给定一个(或一组)关键词,与这个(或组)词最相关的文档是哪一个?
3. 给定一个文档,哪个(或哪些)文档与它具有最大的相似度呢?
回答上述三个问题的关键是:对于一个给定的词和一个给定的文档,定义一个可以用来衡量该词对该文档相关性(或重要性)的指标。那么,如何定义这样的一个指标呢?
词频-逆文档频度(Term Frequency - Inverse Document Frequency,TF-IDF)技术,它是一种用于资讯检索与文本挖掘的常用加权技术,可以用来评估一个词对于一个文档集或语料库中某个文档的重要程度。
TF-IDF(termfrequency–inversedocumentfrequency,词频-逆文件频率))是一种用于资讯检索与资讯探勘的常用加权技术。TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。TF-IDF加权的各种形式常被搜寻引擎应用,作为文件与用户查询之间相关程度的度量或评级。除了TF-IDF以外,因特网上的搜寻引擎还会使用基于连结分析的评级方法,以确定文件在搜寻结果中出现的顺序。 在一份给定的文件里,词频 (term frequency, TF) 指的是某一个给定的词语在该文件中出现的次数。这个数字通常会被归一化(分子一般小于分母区别于IDF),以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词频,而不管该词语重要与否。)
逆向文件频率 (inverse document frequency, IDF) 是一个词语普遍重要性的度量。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。
某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。
TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。TF-IDF实际上是:TF * IDF,TF词频(TermFrequency),IDF反文档频率(InverseDocumentFrequency)。TF表示词条在文档d中出现的频率(另一说:TF词频(Term Frequency)指的是某一个给定的词语在该文件中出现的次数)。IDF的主要思想是:如果包含词条t的文档越少,也就是n越小,IDF越大,则说明词条t具有很好的类别区分能力。如果某一类文档C中包含词条t的文档数为m,而其它类包含t的文档总数为k,显然所有包含t的文档数n=m+k,当m大的时候,n也大,按照IDF公式得到的IDF的值会小,就说明该词条t类别区分能力不强。(另一说:IDF反文档频率(Inverse Document Frequency)是指果包含词条的文档越少,IDF越大,则说明词条具有很好的类别区分能力。)但是实际上,如果一个词条在一个类的文档中频繁出现,则说明该词条能够很好代表这个类的文本的特征,这样的词条应该给它们赋予较高的权重,并选来作为该类文本的特征词以区别与其它类文档。这就是IDF的不足之处.
1.计算词频(TF)
以上式子中,分母是该词在文件中的出现次数,而分母则是在文件中所有字词的出现次数之和。
2.计算逆文档频率(IDF)
分母表示语料库中的文件总数,分子表示包含词语的文件数目,如果该词语不在语料库中,就会导致被除数为零,因此一般情况下使用时会+1.
3.计算词频-逆文档频率(TF-IDF)
某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。
一:有很多不同的数学公式可以用来计算TF-IDF。这边的例子以上述的数学公式来计算。词频 (TF) 是一词语出现的次数除以该文件的总词语数。假如一篇文件的总词语数是100个,而词语“母牛”出现了3次,那么“母牛”一词在该文件中的词频就是3/100=0.03。一个计算文件频率 (DF)的方法是测定有多少份文件出现过“母牛”一词,然后除以文件集里包含的文件总数。所以,如果“母牛”一词在1,000份文件出现过,而文件总数是10,000,000份的话,其逆向文件频率就是 log(10,000,000/ 1,000)=4。最后的TF-IDF的分数为0.03 * 4=0.12。
二:根据关键字k1,k2,k3进行搜索结果的相关性就变成TF1*IDF1+ TF2*IDF2+ TF3*IDF3。比如document1的term总量为1000,k1,k2,k3在document1出现的次数是100,200,50。包含了k1,k2,k3的docuement总量分别是 1000, 10000,5000。document set的总量为10000。 TF1 = 100/1000 = 0.1 TF2 = 200/1000= 0.2 TF3= 50/1000 = 0.05 IDF1 = log(10000/1000)= log(10)= 2.3 IDF2= log(10000/100000)= log(1)= 0; IDF3= log(10000/5000)= log(2)= 0.69 这样关键字k1,k2,k3与docuement1的相关性=0.1*2.3 + 0.2*0 + 0.05*0.69 = 0.2645 其中k1比k3的比重在document1要大,k2的比重是0.
三:在某个一共有一千词的网页中“原子能”、“的”和“应用”分别出现了 2 次、35 次 和 5 次,那么它们的词频就分别是 0.002、0.035 和 0.005。我们将这三个数相加,其和 0.042 就是相应网页和查询“原子能的应用” 相关性的一个简单的度量。概括地讲,如果一个查询包含关键词w1,w2,...,wN, 它们在一篇特定网页中的词频分别是: TF1, TF2, ..., TFN。 (TF: termfrequency)。 那么,这个查询和该网页的相关性就是:TF1 + TF2 + ... + TFN。
在上面的例子中,词“的”站了总词频的 80% 以上,而它对确定网页的主题几乎没有用。我们称这种词叫“应删除词”(Stopwords),也就是说在度量相关性是不应考虑它们的频率。在汉语中,应删除词还有“是”、“和”、“中”、“地”、“得”等等几十个。忽略这些应删除词后,上述网页的相似度就变成了0.007,其中“原子能”贡献了 0.002,“应用”贡献了 0.005。细心的读者可能还会发现另一个小的漏洞。在汉语中,“应用”是个很通用的词,而“原子能”是个很专业的词,后者在相关性排名中比前者重要。因此我们需要给汉语中的每一个词给一个权重,这个权重的设定必须满足下面两个条件:
1.一个词预测主题能力越强,权重就越大,反之,权重就越小。我们在网页中看到“原子能”这个词,或多或少地能了解网页的主题。我们看到“应用”一次,对主题基本上还是一无所知。因此,“原子能“的权重就应该比应用大。
2. 应删除词的权重应该是零。我们很容易发现,如果一个关键词只在很少的网页中出现,我们通过它就容易锁定搜索目标,它的权重也就应该大。反之如果一个词在大量网页中出现,我们看到它仍然不很清楚要找什么内容,因此它应该小。概括地讲,假定一个关键词 w 在 Dw 个网页中出现过,那么 Dw 越大,w的权重越小,反之亦然。在信息检索中,使用最多的权重是“逆文本频率指数” (Inverse document frequency 缩写为IDF),它的公式为log(D/Dw)其中D是全部网页数。比如,我们假定中文网页数是D=10亿,应删除词“的”在所有的网页中都出现,即Dw=10亿,那么它的IDF=log(10亿/10亿)= log (1) = 0。假如专用词“原子能”在两百万个网页中出现,即Dw=200万,则它的权重IDF=log(500)=6.2。又假定通用词“应用”,出现在五亿个网页中,它的权重IDF= log(2)则只有 0.7。也就只说,在网页中找到一个“原子能”的比配相当于找到九个“应用”的匹配。利用 IDF,上述相关性计算个公式就由词频的简单求和变成了加权求和,即TF1*IDF1+TF2*IDF2 +... + TFN*IDFN。在上面的例子中,该网页和“原子能的应用”的相关性为 0.0161,其中“原子能”贡献了 0.0126,而“应用”只贡献了0.0035。这个比例和我们的直觉比较一致了。
余弦有这样的性质:余弦值越接近1,就表明夹角越接近0度,也就是两个向量越相似,夹角等于0,即两个向量相等,这就叫”余弦相似性”。 那么该怎么利用余弦来计算文本的相似性了?首先来看一个例子。
文本1:我们喜欢足球
文本2:我喜欢踢足球
大致思路是:我们认为用词越相似,则文本的相似度越高,所以计算文本相似性主要按照以下步骤进行:
分词
此处利用 ansj 分词工具进行分词,文本1和文本2的分词结果为:
文本1:我/喜欢/足球
文本2:我们/喜欢/踢/足球
列出所有的词
我, 喜欢, 踢, 我们, 足球
计算词频
文本1: 我:1,喜欢:1,踢:0,我们:0,足球:1
文本2: 我:0,喜欢:1,踢:1,我们:1,足球:1
转化为向量
文本1:[1, 1, 0, 0, 1]
文本2:[0, 1, 1, 1, 1]
5. 计算两个词向量的余弦相似度
以上结果是0.5773502691896258,经验证结果是正确的。
注意:以上程序只符合简单的应用情况,不适用复杂的情况。另外,余弦相似性还可以用来判别文档的相似性,大致思路是:首先求出文档的关键词(可以利用TF-IDF 方法),以后可以按照以上2,3,4步骤进行计算。
TF-IDF不足之处
TF-IDF算法是建立在这样一个假设之上的:对区别文档最有意义的词语应该是那些在文档中出现频率高,而在整个文档集合中出现频率少的词语,所以如果特征空间坐标系取TF词频作为测度,就可以提现同类文档的特点,另外考虑到单词区别不同类别的能力,TF-IDF认为一个单词出现的文档频数越小,它区别不同类别文档的能力就越大。因此引入了逆文档频度IDF的概念,以TF和IDF的乘积作为特征空间坐标系的取值测度并用它完成对权值TF的调整,调整权值得目的在于突出重要单词,抑制次要单词。
但是,本质上IDF是一种试图抑制噪声的加权,并且单纯地认为文档频率小的单词就越重要,文档频率大的单词就越无用,显然这并不是完全正确的(例如,对于一些生僻词,它们的文档频率小,但不一定有意义)。IDF的简单结构并不能有效反映单词的重要程度和特征词的分布情况,使其无法很好地完成对权值调整的功能,因此TF-IDF的精度并不是很高。
此外,在TF-IDF算法中并没有体现出单词的位置信息,对于Web文档而言,权重的计算方法应该体现出HTML的结构特征,特征词在不同的标记符中对文章内容的反映程度不同,其权重的计算方法也不相同,因此应该对处于网页不同位置的特征词分别赋予不同的系数,然后乘以特征词的词频,以提高文本表示的效果。
优点:是简单快速,结果比较符合实际情况。
缺点:单纯以"词频"衡量一个词的重要性,不够全面,有时重要的词可能出现次数并不多。而且,这种算法无法体现词的位置信息,出现位置靠前的词与出现位置靠后的词,都被视为重要性相同,这是不正确的。(一种解决方法是,对全文的第一段和每一段的第一句话,给予较大的权重。)
TF-IDF的缺陷
由于IDF值的公式,使其存在一些天然的缺陷:
词集模型 DictVectorizer:单词构成的集合,集合中每个元素只有一个,即词集中的每个单词都只有一个。
词袋模型 CountVectorizer:在词集的基础上加入了频率这个维度,即统计单词在文档中出现的次数(令牌化和出现频数统计),通常我们在应用中都选用词袋模型。
from sklearn.feature_extraction.text import CountVectorizer
#使用默认参数实例化分词对象
vec=CountVectorizer()
#查看词袋模型的参数
vec.get_params()
输出:
{'analyzer': 'word',
'binary': False,
'decode_error': 'strict',
'dtype': numpy.int64,
'encoding': 'utf-8',
'input': 'content',
'lowercase': True,
'max_df': 1.0,
'max_features': None,
'min_df': 1,
'ngram_range': (1, 1),
'preprocessor': None,
'stop_words': None,
'strip_accents': None,
'token_pattern': '(?u)\\b\\w\\w+\\b',
'tokenizer': None,
'vocabulary': None}
##让我们使用它对文本corpus进行简单文本全集令牌化,并统计词频:
corpus = [
... 'This is the first document.',
... 'This is the second second document.',
... 'And the third one.',
... 'Is this the first document?',
... ]
X = vec.fit_transform(corpus)
#在拟合期间发现的每个项都被分配一个与所得矩阵中的列对应的唯一整数索引
X
输出:
<4x9 sparse matrix of type ''
with 19 stored elements in Compressed Sparse Row format>
#获取特征名称(列名)
vec.get_feature_names()
输出:
['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']
X.toarray()
输出:
array([[0, 1, 1, 1, 0, 0, 1, 0, 1],
[0, 1, 0, 1, 0, 2, 1, 0, 1],
[1, 0, 0, 0, 1, 0, 1, 1, 0],
[0, 1, 1, 1, 0, 0, 1, 0, 1]], dtype=int64)
#获取词汇表(训练语料库),词汇表由特征名和出现频次构成
vec.vocabulary_
输出:
{'and': 0,
'document': 1,
'first': 2,
'is': 3,
'one': 4,
'second': 5,
'the': 6,
'third': 7,
'this': 8}
针对其他文本进行词袋处理时, 可以直接使用现有的词汇表
voc=vec.vocabulary_
new_vec=CountVectorizer(vocabulary=voc)
在将来的调用转换方法中,在训练语料库vocabulary_中未出现的词将被完全忽略:
vec.transform(['Something third new.']).toarray()
输出:
array([[0, 0, 0, 0, 0, 0, 0, 1, 0]])
以词袋模型为例2
from sklearn.feature_extraction.text import CountVectorizer
#词袋模型,这里的min_df取值为3,即该向量在整个payload中至少出现了三次
vec=CountVectorizer(min_df=3,ngram_range=(1,1))
content=[
'alert(1)X',
'\'>
vec2.vocabulary_
输出:
{'22': 0,
'29': 1,
'3c': 2,
'3cscript': 3,
'3d': 4,
'3e': 5,
'3ealert': 6,
'alert': 7,
'script': 8}
tf-idf的主要作用就是找出某个词或某些词用以区别于其它文本,而词袋模型恰好又是找出文本中出现频率高的词语,那我们可以试想:
如果我先用词袋模型筛选出一些高热度词汇,再用tf-idf计算其权值,我们将得到词袋模型中词汇的tf-idf值,值越高说明该词区分每条语句的效果越好。
import numpy as np
from sklearn import preprocessing
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
vec=CountVectorizer(min_df=3,ngram_range=(1,1))
content=[
'alert(1)X',
'\'>
由此得到词袋模型中词汇的tf-idf值,值越高说明该词区分每条语句的效果越好。
但我们做特征工程追求的是泛化能力,即寻找能更好的概括整体文本的特征的词汇,与tf-idf追求的结果恰恰相反,所以我们可以看到像alert、script这种在安全从业者看来明显的攻击特征在上面结果中的权值反而很低。
我们再回过头来看看tf-idf的缺陷,有助于我们对词袋模型中特征向量的优化(这个需要各位好好理解一下)。
那么我们正好可以利用这个特征来判断词袋模型中向量的泛化效果
即:tf-idf值越高其泛化能力越低,也就越不适合作为我们的特征向量。
从上面的结果中我们可以看出来,script、alert这两个向量相比于其它能更好的反映出我们整体攻击语句的特征,符合我们人工判断的结果。而在script和alert两者中alert显然泛化效果又更加的优秀。
两者结合使用,我们就可以自动化的从大文本中提取优质的特征向量,以减少人工干预,大大降低特征工程中的成本。
应用词袋模型将文章进行单词级别的划分有的时候未必是一种好的做法,例如:将general purpose intelligence(通用智能)一词,如果将general , purpose, intelligence这三个词拆开,所表达的意思与三个词连在一起时大相径庭。通常,可以将n个连续出现的单词()组成的词组(N-gram)也作为一个单独的特征放到向量表示中去,构成N-gram模型。另外,同一个词可能有多种词性变化,但是却有相似的含义。在实际应用中,,一般会对单词进行词干抽取(Word Stemming)处理,即将不同词性的单词统一称为同一词干的形式。
主题模型用于从文本库中发现有代表性的主题(得到每个主题上面词的分布特性),并能够计算出每篇文章的主题分布。
互信息(Mutual Information)是一有用的信息度量,它是指两个事件集合之间的相关性。两个离散随机事件X和Y的互信息定义为:
其中 p(x,y) 是 X 和 Y 的联合概率分布函数,而p(x)和p(y)分别是 X 和 Y 的边缘概率分布函数。
在连续随机变量的情形下,求和被替换成了二重定积分:
其中 p(x,y) 当前是 X 和 Y 的联合概率密度函数,而p(x)和p(y)分别是 X 和 Y 的边缘概率密度函数。
互信息量I(xi;yj)在联合概率空间P(XY)中的统计平均值。 平均互信息I(X;Y)克服了互信息量I(xi;yj)的随机性,成为一个确定的量。如果对数以 2 为基底,互信息的单位是bit。
直观上,互信息度量 X 和 Y 共享的信息:它度量知道这两个变量其中一个,对另一个不确定度减少的程度。例如,如果 X 和 Y 相互独立,则知道 X 不对 Y 提供任何信息,反之亦然,所以它们的互信息为零。在另一个极端,如果 X 是 Y 的一个确定性函数,且 Y 也是 X 的一个确定性函数,那么传递的所有信息被 X 和 Y 共享:知道 X 决定 Y 的值,反之亦然。因此,在此情形互信息与 Y(或 X)单独包含的不确定度相同,称作 Y(或 X)的熵。而且,这个互信息与 X 的熵和 Y 的熵相同。(这种情形的一个非常特殊的情况是当 X 和 Y 为相同随机变量时。)
互信息是 X 和 Y 联合分布相对于假定 X 和 Y 独立情况下的联合分布之间的内在依赖性。于是互信息以下面方式度量依赖性:I(X; Y) = 0 当且仅当 X 和 Y 为独立随机变量。从一个方向很容易看出:当 X 和 Y 独立时,p(x,y) = p(x) p(y),因此:
此外,互信息是非负的(即 I(X;Y) ≥ 0; 见下文),而且是对称的(即 I(X;Y) = I(Y;X))。
互信息又可以等价地表示成
其中H(X)和H(Y) 是边缘熵,H(X|Y)和H(Y|X)是条件熵,而H(X,Y)是X和Y的联合熵。注意到这组关系和并集、差集和交集的关系类似,用Venn图表示:
于是,在互信息定义的基础上使用琴生不等式,我们可以证明 I(X;Y) 是非负的,因此H(X)>=H(X|Y),这里我们给出 I(X;Y) = H(Y) - H(Y|X) 的详细推导:
H(X|Y)是条件熵(conditional entropy);x,y互信息与多元对数似然比检验以及皮尔森χ2校验有着密切的联系。 在处理分类问题提取特征的时候就可以用互信息来衡量某个特征和特定类别的相关性,如果信息量越大,那么特征和这个类别的相关性越大。反之也是成立的。
在通过互信息来选取词来建立空间向量模型。在选取之前需要做的一件事是把那些只在一个类别里的出现过的而且频次非常低的词需要去除,因为这些词注定和某个的互信息会很高而和其他类别的互信息会很低。分析发现,低词频对于互信息的影响还是蛮大的,一个词如果频次不够多,但是又主要出现在某个类别里,那么就会出现较高的互信息,从而给筛选带来噪音。所以为了避免出现这种情况可以采用先对词按照词频排序取然后按照互信息大小进行排序,然后再选择自己想要的词,这样就能比较好的解决这个问题。
特征项和类别的互信息体现了特征项与类别的相关程度,是一种广泛用于建立词关联统计模型的标准。互信息与期望交叉熵的不同在于没有考虑特征出现的频率,这样导致互信息评估函数不选择高频的有用词而有可能选择稀有词作为文本的最佳特征。因为对于每一主题来讲,特征t的互信息越大,说明它与该主题的共现概率越大,因此,以互信息作为提取特征的评价时应选互信息最大的若干个特征。
互信息特征选择算法的步骤
①划分数据集
②利用互信息对特征进行排序
③选择前n个特征利用SVM进行训练
④在测试集上评价特征子集计算错误率
1. https://blog.csdn.net/u012845311/article/details/73548882
2. https://blog.csdn.net/lzc4869/article/details/79758044
3. https://www.jianshu.com/p/0422853b57a8
4.https://blog.csdn.net/BigData_Mining/article/details/81279612 (重要)