NLP入门:结合代码理解TF-IDF

释放双眼,带上耳机,听听看~!
本文将结合实际代码对TF-IDF进行深入理解,通过Python进行文本分析和数据处理,适合对自然语言处理感兴趣的初学者。

本文正在参加【NLP】入门(三):TF-IDF(理论篇) 中,已经对 TF-IDF 进行了理论介绍,那么接下来,让我们结合代码,对 TF-IDF 有更加深刻的理解吧;

本篇博文的源码来源 此处,非博主所写!

分析

1、首先是导入要用到的包;

import itertools
import numpy as np
from collections import Counter

from visual import show_tfidf 

其中 visual.py 的源码地址 点这,下面将要用到的 show_tfidf 函数代码粘贴出来了:

def show_tfidf(tfidf, vocab, filename):
    # [n_doc, n_vocab]
    plt.imshow(tfidf, cmap="YlGn", vmin=tfidf.min(), vmax=tfidf.max())
    plt.xticks(np.arange(tfidf.shape[1]), vocab, fontsize=6, rotation=90)
    plt.yticks(np.arange(tfidf.shape[0]), np.arange(1, tfidf.shape[0]+1), fontsize=6)
    plt.tight_layout()
    # creating the output folder 
    output_folder = './visual/results/'
    os.makedirs(output_folder, exist_ok=True)
    plt.savefig(os.path.join(output_folder, '%s.png') % filename, format="png", dpi=500)
    plt.show()

visual.py 中又导入了一个自定义的包 utils.py,源码地址 点这

2、罗列文档并转换形式;

假设有15篇文档,在实际中的文档一般都很长,为了举例方便,这里用短句代替:

docs = [
    "it is a good day, I like to stay here",
    "I am happy to be here",
    "I am bob",
    "it is sunny today",
    "I have a party today",
    "it is a dog and that is a cat",
    "there are dog and cat on the tree",
    "I study hard this morning",
    "today is a good day",
    "tomorrow will be a good day",
    "I like coffee, I like book and I like apple",
    "I do not like it",
    "I am kitty, I like bob",
    "I do not care who like bob, but I like kitty",
    "It is coffee time, bring your cup",
]

将文档的单词转换成 ID 形式,这样便于后续通过 ID 进行统计。

# 切割文档,将文档分割成一个个单词
docs_words = [d.replace(",", "").split(" ") for d in docs]
# 转换类型,利用集合的特性进行去重
vocab = set(itertools.chain(*docs_words))
# 转成键值对,{v:i}
v2i = {v: i for i, v in enumerate(vocab)}
# 转成键值对,{i:v}
i2v = {i: v for v, i in v2i.items()}

哪里不懂的话,可以打印一番看看,比如:

NLP入门:结合代码理解TF-IDF

3、计算 TF;

TFTF 表示词频 (Term Frequency),即某个词在某篇文档中出现的总次数 (频数)。通常,需要对其进行归一化统一量纲 (词频 = 词频数 / 文档总词数),以避免词频因文档长度不同而产生偏差 (词频,因长文档具有的词数多就相对高、因短文档具有的词数少就相对低,将导致无法真正衡量词的重要性)。

设某个词 tt 在文档 dd 中出现的总次数为 Nd,tN_{d,t},且文档 dd 的总词数为 NdN_{d},则词 tt 相对于文档 dd 的词频 TFTF 为:

TF=Nd,tNdTF = frac{N_{d,t}}{N_{d}}

tf_methods = {
        "log": lambda x: np.log(1+x),
        "augmented": lambda x: 0.5 + 0.5 * x / np.max(x, axis=1, keepdims=True),
        "boolean": lambda x: np.minimum(x, 1),
        "log_avg": lambda x: (1 + safe_log(x)) / (1 + safe_log(np.mean(x, axis=1, keepdims=True))),
    }


def get_tf(method="log"):
    # term frequency: how frequent a word appears in a doc
    # 建立矩阵,用于统计每个单词在每篇文档中的频率
    _tf = np.zeros((len(vocab), len(docs)), dtype=np.float64)    # [n_vocab, n_doc]
    for i, d in enumerate(docs_words):
        # 例:Counter({'it': 1, ..., 'here': 1})
        counter = Counter(d)
        for v in counter.keys():
            # 计算 TF
            # counter.most_common(1)[0][1] 获取这个 counter 中单个单词的最大出现次数
            _tf[v2i[v], i] = counter[v] / counter.most_common(1)[0][1]

    weighted_tf = tf_methods.get(method, None)
    if weighted_tf is None:
        raise ValueError
    # 计算 TF
    return weighted_tf(_tf)

4、计算 IDF;

IDFIDF 表示逆文档频率 (Inverse Document Frequency),被用作 IFIF 的权重,其大小与一个词的常见程度成反比。

设某一文档集共有 MM 篇文档,其中包含词 tt 的文档数为 MtM_t,则词 tt 的逆文档频率 IDFIDF 为:

IDF=log⁡(MMt+1)IDF = log(frac{M}{M_t+1})

其中,分母部分 +1 避免除 Mt=0M_t=0,即预防没有文档包含词 tt 的他啥情况;

idf_methods = {
        "log": lambda x: 1 + np.log(len(docs) / (x+1)),
        "prob": lambda x: np.maximum(0, np.log((len(docs) - x) / (x+1))),
        "len_norm": lambda x: x / (np.sum(np.square(x))+1),
    }


def get_idf(method="log"):
    # inverse document frequency: low idf for a word appears in more docs, mean less important
    df = np.zeros((len(i2v), 1))
    for i in range(len(i2v)):
        d_count = 0
        for d in docs_words:
            # 统计包含该词的文档数
            d_count += 1 if i2v[i] in d else 0
        df[i, 0] = d_count

    idf_fn = idf_methods.get(method, None)
    if idf_fn is None:
        raise ValueError
    # 计算 IDF
    return idf_fn(df)

5、计算 TF-IDF;

TF−IDF=TF×IDF=Nd,tNd×log⁡(MMt+1)TF-IDF = TF times IDF = frac{N_{d,t}}{N_{d}} times log(frac{M}{M_t+1})

tf = get_tf()           # [n_vocab, n_doc]
idf = get_idf()         # [n_vocab, 1]
tf_idf = tf * idf       # [n_vocab, n_doc]

NLP入门:结合代码理解TF-IDF

后记

以上就是 【NLP】入门(四):TF-IDF(代码篇) 的全部内容了。

本文简单地从代码上介绍了 TF-IDF,那不妨思考一下,除了搜索匹配之外,TF-IDF 还能干些什么有意思的事情呢?下一篇博文 【NLP】入门(五):TF-IDF(拓展篇) 将揭晓这一答案,敬请期待,希望本篇博文对大家有所帮助!

📝 上篇精讲:【NLP】入门(三):TF-IDF(理论篇)

💖 我是 𝓼𝓲𝓭𝓲𝓸𝓽,期待你的关注;

👍 创作不易,请多多支持;

🔥 系列专栏:AI NLP

本网站的内容主要来自互联网上的各种资源,仅供参考和信息分享之用,不代表本网站拥有相关版权或知识产权。如您认为内容侵犯您的权益,请联系我们,我们将尽快采取行动,包括删除或更正。
AI教程

ChatGPT使用指南:如何利用AI助手为小红书生成文案

2023-12-20 15:34:14

AI教程

Github Copilot解析及逆向分析

2023-12-20 15:45:14

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索