简单理解TF-IDF算法

孤街醉人 提交于 2019-12-21 23:39:32

前言

  • 在对文本信息处理得过程中,我们会使用分词工具对文本字符串进行分词处理,然后进行频率统计,就会明白文本字符串中关键词的重要性占比。
  • 但是,问题来了,难道,诸如:“所以”、“也许”、“或者”… 这样的词能说明其很重要?答案当然是否!
  • 所以,TF-IDF算法就来解决了这一问题。

原理

  • Tf,也就是term frequency,它代表了词的频率(“词频”);
    可以这样计算 :词频 = 某词在文章中出现的次数/文章中总词的次数
  • idf,也就是inverse document frequency,代表了逆文档频率
    可以这样计算:逆文档频率 = log(总文档数/出现该词的文档数)
  • 该词的重要性就是:拿词频*逆文档频率即可。
    也就是:词的重要性 = Tf * idf
  • ps: 关于log,我多介绍一下,请先看这个链接:对数函数(log)
    根据log函数的单调性(此时e=a>1),它是单调递增的,于是得出,当一个词在所有文档中出现的次数越多,其越不重要,也就是诸如“所以”、“也许”、“或者”…会在数据分析的权重中被稀释掉。

实际应用

  • TfidfVectorizer()这个类实现了该算法
没有表现出“重要性”的代码片
# coding: utf-8
import jieba

from sklearn.feature_extraction.text import CountVectorizer


def cut_word():
    """
    使用jieba分词,实现中文特征值化
    :return: 分词之后的结果,list,
    """
    con1 = jieba.cut("胆小鬼连幸福都会害怕,碰到棉花都会受伤,有时还被幸福所伤。")  # 返回分词后的生成器
    con2 = jieba.cut("人啊,明明一点儿也不了解对方,错看对方,却视彼此为独一无二的挚友,一生不解对方的真性情,待一方撒手西去,还要为其哭泣,念诵悼词。")
    con3 = jieba.cut(
        "早晨,我睁眼醒来翻身下床,又变成了原来那个浅薄无知、善于伪装的滑稽角色。胆小鬼连幸福都会惧怕,碰到棉花都会受伤,有时也会被幸福所伤。趁着还没有受伤,我想就这样赶快分道扬镳。我又放出了惯用的逗笑烟幕弹。")

    # 转换成列表
    content1 = list(con1)
    content2 = list(con2)
    content3 = list(con3)

    # 把列表转化成以空格隔开的字符串
    c1 = ' '.join(content1)
    c2 = ' '.join(content2)
    c3 = ' '.join(content3)

    return c1, c2, c3


def hanzivec():
    """
    中文特征值化:普通的
    :return: None
    """
    c1, c2, c3 = cut_word()
    # print(c1, c2, c3)
    cv = CountVectorizer()
    data = cv.fit_transform([c1, c2, c3])
    # print(cv.get_feature_names())
    print(data.toarray())
    return None


if __name__ == '__main__':
    hanzivec()  # 普通的



# ['一方', '一点儿', '一生', '不解', '了解', '伪装', '分道扬镳', '却视', '原来', '受伤', '变成', '哭泣', '善于', '害怕', '对方', '幸福', '彼此', '念诵', '悼词', '惧怕', '惯用', '挚友', '撒手', '放出', '无知', '早晨', '明明', '有时', '棉花', '没有', '浅薄', '滑稽角色', '烟幕弹', '独一无二', '真性情', '睁眼', '碰到', '翻身', '胆小鬼', '赶快', '趁着', '还要', '这样', '逗笑', '那个', '醒来', '错看']
# [[0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 2 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
#   1 0 1 0 0 0 0 0 0 0 0]
#  [1 1 1 1 1 0 0 1 0 0 0 1 0 0 3 0 1 1 1 0 0 1 1 0 0 0 1 0 0 0 0 0 0 1 1 0
#   0 0 0 0 0 1 0 0 0 0 1]
#  [0 0 0 0 0 1 1 0 1 2 1 0 1 0 0 2 0 0 0 1 1 0 0 1 1 1 0 1 1 1 1 1 1 0 0 1
#   1 1 1 1 1 0 1 1 1 1 0]]


表现出“重要性”的代码片
# coding: utf-8
import jieba

from sklearn.feature_extraction.text import TfidfVectorizer


def cut_word():
    """
    使用jieba分词,实现中文特征值化
    :return: 分词之后的结果,list,
    """
    con1 = jieba.cut("胆小鬼连幸福都会害怕,碰到棉花都会受伤,有时还被幸福所伤。")  # 返回分词后的生成器
    con2 = jieba.cut("人啊,明明一点儿也不了解对方,错看对方,却视彼此为独一无二的挚友,一生不解对方的真性情,待一方撒手西去,还要为其哭泣,念诵悼词。")
    con3 = jieba.cut(
        "早晨,我睁眼醒来翻身下床,又变成了原来那个浅薄无知、善于伪装的滑稽角色。胆小鬼连幸福都会惧怕,碰到棉花都会受伤,有时也会被幸福所伤。趁着还没有受伤,我想就这样赶快分道扬镳。我又放出了惯用的逗笑烟幕弹。")

    # 转换成列表
    content1 = list(con1)
    content2 = list(con2)
    content3 = list(con3)

    # 把列表转化成以空格隔开的字符串
    c1 = ' '.join(content1)
    c2 = ' '.join(content2)
    c3 = ' '.join(content3)

    return c1, c2, c3


def tfidfvec():
    """
    中文特征值化:重要性
    :return: None
    """
    c1, c2, c3 = cut_word()

    # print(c1, c2, c3)
    tf = TfidfVectorizer()
    data = tf.fit_transform([c1, c2, c3])
    print(tf.get_feature_names())
    print(data.toarray())  # 此处得出来得值便是重要性了
    return None


if __name__ == '__main__':
    tfidfvec()
    
# 输出
# ['一方', '一点儿', '一生', '不解', '了解', '伪装', '分道扬镳', '却视', '原来', '受伤', '变成', '哭泣', '善于', '害怕', '对方', '幸福', '彼此', '念诵', '悼词', '惧怕', '惯用', '挚友', '撒手', '放出', '无知', '早晨', '明明', '有时', '棉花', '没有', '浅薄', '滑稽角色', '烟幕弹', '独一无二', '真性情', '睁眼', '碰到', '翻身', '胆小鬼', '赶快', '趁着', '还要', '这样', '逗笑', '那个', '醒来', '错看']
# [[0.         0.         0.         0.         0.         0.
#   0.         0.         0.         0.30529678 0.         0.
#   0.         0.40142857 0.         0.61059355 0.         0.
#   0.         0.         0.         0.         0.         0.
#   0.         0.         0.         0.30529678 0.30529678 0.
#   0.         0.         0.         0.         0.         0.
#   0.30529678 0.         0.30529678 0.         0.         0.
#   0.         0.         0.         0.         0.        ]
#  [0.19611614 0.19611614 0.19611614 0.19611614 0.19611614 0.
#   0.         0.19611614 0.         0.         0.         0.19611614
#   0.         0.         0.58834841 0.         0.19611614 0.19611614
#   0.19611614 0.         0.         0.19611614 0.19611614 0.
#   0.         0.         0.19611614 0.         0.         0.
#   0.         0.         0.         0.19611614 0.19611614 0.
#   0.         0.         0.         0.         0.         0.19611614
#   0.         0.         0.         0.         0.19611614]
#  [0.         0.         0.         0.         0.         0.18588519
#   0.18588519 0.         0.18588519 0.28274095 0.18588519 0.
#   0.18588519 0.         0.         0.28274095 0.         0.
#   0.         0.18588519 0.18588519 0.         0.         0.18588519
#   0.18588519 0.18588519 0.         0.14137048 0.14137048 0.18588519
#   0.18588519 0.18588519 0.18588519 0.         0.         0.18588519
#   0.14137048 0.18588519 0.14137048 0.18588519 0.18588519 0.
#   0.18588519 0.18588519 0.18588519 0.18588519 0.        ]]

补充

  • 代码片的输出是基于one-hot编码的,如果不了解的话,请参考:one-hot
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!