python TF-IDF进行文本特征提取的源码实现,及与sklearn的比较

TF-IDF特征提取的实现

1 TF-IDF的计算公式

TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。TFIDF实际上是:TF * IDF,TF词频(Term Frequency),IDF逆向文件频率(Inverse Document Frequency)。
TF-IDF的原始公式为:

python TF-IDF进行文本特征提取的源码实现,及与sklearn的比较_第1张图片

公式中各个变量的含义在此不再赘述,与网上的TF-IDF公式一致。但是第二个公式由于分母可能为0,因此此次我们采用平滑处理后的TF-IDF公式:

python TF-IDF进行文本特征提取的源码实现,及与sklearn的比较_第2张图片

作为源码实现所依据的公式。

2 python 源码实现TF-IDF

1 python源码实现

# TF_IDF_weight函数功能:传入corpus,返回其特征向量值向量
# 输入的corpus格式:["我 来到 中国 旅游", "中国 欢迎 你","我 喜欢 来到 中国 天安门"]
def TF_IDF_weight(corpus):
	# 词库的构建
	import math
    weight_long = [eve.split() for eve in corpus]
    word_all = []
    for eve in weight_long:
        for x in eve:
            if len(x)>1:
                word_all.append(x)
    word_all = list(set(word_all))  # 集合去重词库 
    # 开始计算tf-idf
    weight = [[] for i in corpus]
    weight_idf = [[] for i in corpus]
    for word in word_all:
        for i in range(len(corpus)):
            temp_list = corpus[i].split()
            n1 = temp_list.count(word)
            n2 = len(temp_list)
            tf = n1/n2
            n3 = len(corpus)
            n4 = 0
            for eve in corpus:
                temp_list_ = eve.split()
                if word in temp_list_:
                    n4 += 1
            idf = math.log(((n3+1)/(n4+1))+1,10)
            weight_idf[i].append(idf)
            weight[i].append(tf*idf)
    # L2范式归一化过程
    l2_weight = [[] for i in range(len(corpus))]
    for e in range(len(weight)):
        all2plus = 0
        for ev in weight[e]:
            all2plus += ev**2
        for ev in weight[e]:
            l2_weight[e].append(ev/(all2plus**0.5))
    return l2_weight  # 返回最终结果

对源码的几点说明:
a.在构建词库的过程中,词的前后顺序没有要求,但是词语不能有重复。
b.在得到tf-idf计算结果之后,需要对其进行归一化操作,才能为分类等后续操作使用。
c.在此处将长度小于1的词语去掉了,如“我”,“你”。

2 源码的测试

使用分完词的汉语语料corpus,传入上面的函数TF_IDF_weight中:

corpus = ["我 来到 中国 旅游", "中国 欢迎 你","我 喜欢 来到 中国 天安门"]
result_list = TF_IDF_weight(corpus)
for weight in result_list:
    print(weight)

输出结果:

[0.0, 0.44692991362032153, 0.5463237392780342, 0.7083671535387552, 0.0, 0.0]
[0.8457366985068379, 0.5336004467752572, 0.0, 0.0, 0.0, 0.0]
[0.0, 0.3646999329959496, 0.44580643415615906, 0.0, 0.5780357178140985, 0.5780357178140985]

3 sklearn中的TF-IDF方法

使用同样的语料数据,调用sklearn下的方法求TF-IDF:

from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer()  # 实例化
transformer = TfidfTransformer()
corpus = ["我 来到 中国 旅游", "中国 欢迎 你","我 喜欢 来到 中国 天安门"]
result_list2 = transformer.fit_transform(vectorizer.fit_transform(corpus)).toarray().tolist()
for weight in result_list2:
    print(weight)

输出结果:

[0.4254405389711991, 0.0, 0.0, 0.7203334490549893, 0.5478321549274363, 0.0]
[0.5085423203783267, 0.0, 0.0, 0.0, 0.0, 0.8610369959439764]
[0.34520501686496574, 0.5844829010200651, 0.5844829010200651, 0.0, 0.444514311537431, 0.0]

4 两种TF-IDF实现的对比

对于同一个语料数据corpus而言,现在按照第一句话 “我 来到 中国 旅游” 对比两种方法得到的向量值。

词语 自实现的TF-IDF sklearn中的TF-IDF
去掉 去掉
来到 0.5463237392780342 0.5478321549274363
中国 0.44692991362032153 0.4254405389711991
旅游 0.7083671535387552 0.7203334490549893

可以看到二者得到的向量值非常类似,但是不完全一致。除了这一点以外,sklearn中的TF-IDF方法运行速度较快。

你可能感兴趣的:(NLP)