推荐算法课程学习笔记2:文本特征提取基础

发布于:2022-12-22 ⋅ 阅读:(283) ⋅ 点赞:(0)

本次课主要讲解文本特征提取的基础方法:Count Vector和TF-IDF Vector。我们假设一个语料库中有N篇文章,词典(所有文章中出现的不重复单词)的单词(token)数量为M,这两种方法都是将N篇文章的文本转化为长度为M的向量,从而得到一个N×M维度的结构化数据。后续可以根据此结构化数据建立机器学习模型,进行文本分类等应用。

在提取特征前,一般需要对每一文章进行去除前后空格、分词和小写转换的预处理。

目录

一、Count Vector

1、原理

2、优缺点与改进

二、TF-IDF Vector

1、理解

2、原理

(1)TF部分,同Count Vector

(2)IDF部分

(3)TF-IDF = 词频(TF) * 反文档频率(IDF)

3、优缺点

三、词向量的应用

1、作为文本分类任务的自变量

2、计算文章间的相似度

(1)计算相似度的三种常用方法

 (2)总体流程

四、作业

1、“皮靴”case的Counter Vector的案例代码

 2、基于jieba开源工具库,运行TF*IDF案例

 3、项目已代码写出来,提交截图


一、Count Vector

1、原理

某文章的Count Vector就是该文章中每个token的词频,即出现次数,对于词典中没有出现在该文章中的单词,记为0。

该方法思路简洁清晰,用每篇文章中的词频出现频数作为特征。在实际中,通常需要进行行归一化,以防止每篇文章单词量不同的的影响。具体做法有两种:①用每个单词的词频除以该文章的单词数量的和,此时其实就得到了每个单词的在该文章中的频率。②用每个单词的词频除以该文章中出现次数最多的单词的频数。

2、优缺点与改进

优点:简单,好理解,利用单词频率作为特征。

缺点:通常语料库巨大,单词库一般以万为单位,这就造成每个词向量的维度为几万,而每篇文章中出现的单词数量远小于几万,形成稀疏矩阵,不利于后续的计算。

改进方法:对于每篇文章,取词频最高的前m个单词形成文章top m子词库,将所有文章的top m子词库汇总得到一个总的子词库,再统计每篇文章在该子词库的词频或者频率。

二、TF-IDF Vector

1、理解

如果说词向量代表的是个单词在该文章中的重要程度,那Count Vector就是用每个单词在文章中出现的频率衡量其重要性,出现频率越高,该单词在文章中越重要。

而TF-IDF 还在此基础上考虑单词在其他文章中的出现情况,如果该单词在其他文章中出现得少,则越重要,如果该单词在其他文章中出现得多,则不重要,也就是说一个常用词即使在某文章中出现次数多,但也不一定就因此重要。

2、原理

(1)TF部分,同Count Vector

(2)IDF部分

反文档词频IDF的计算部分如下:

反文档频率(IDF)= log( 语料库的文档总数 / (包含该词的文档数 + 1) )

(3)TF-IDF = 词频(TF) * 反文档频率(IDF)

3、优缺点

优点:相比于Count Vector,更符合实际意义,出现频率高,且在其他文章中出现少的词更重要。

缺点:首先,TF中利“词频”大小并不一定很好反映重要性;其次,这两种方法都没有考虑单词出现的顺序,如果把一篇文章的单次顺序打乱,还是会得到相同的词向量。

三、词向量的应用

通过以上两种方法,将文本转化为了词向量。在应用层面,词向量一般有两种应用。

1、作为文本分类任务的自变量

每篇文章的标签为一个分类变量,特征就是词向量的每一个维度,可以进行机器学习建模。

2、计算文章间的相似度

(1)计算相似度的三种常用方法

①余弦相似度:衡量空间中两个向量夹角的大小,取值为[-1,1]

 ②Jaccard相似度

两篇文章中出现的单词的交集单词数量除以并集数量,取值[0,1]

 ③欧氏距离

衡量空间中两个向量顶点绝对距离的大小,取值[0,+无穷]。

 (2)总体流程

四、作业

1、“皮靴”case的Counter Vector的案例代码

import jieba
import numpy as np
import pandas as pd

seq1 = '这只皮靴号码大了,那只号码合适'
seq2 = '这只皮靴号码不小,那只更合适'

# jieba基础操作学习
print(jieba.cut(seq1))
print(list(jieba.cut(seq1)))
print(' '.join(jieba.cut(seq1)))
print([i for i in jieba.cut(seq1)])
print(jieba.lcut(seq1))


def similarity(seq1, seq2, method):
    # jieba分词得到token列表
    seq1_list = jieba.lcut(seq1)
    seq2_list = jieba.lcut(seq2)

    # token列表去重得到set
    seq1_set = set(seq1_list)
    seq2_set = set(seq2_list)

    # 总词库set
    word_set = seq1_set.union(seq2_set)

    # 句子总词库字典
    word_dict1 = dict.fromkeys(word_set, 0)
    word_dict2 = dict.fromkeys(word_set, 0)
    for i in seq1_list:
        word_dict1[i] += 1
    for i in seq2_list:
        word_dict2[i] += 1

    # Count Vector
    vec_seq1 = np.array(list(word_dict1.values()))
    vec_seq2 = np.array(list(word_dict2.values()))

    if method == "cos":
        return (vec_seq1 * vec_seq2 / ((vec_seq1 ** 2).sum() ** 0.5 * (vec_seq2 ** 2).sum() ** 0.5)).sum()
    elif method == 'Eur':
        return ((vec_seq1 - vec_seq2) ** 2).sum() ** 0.5
    elif method == 'Jac':
        return len(seq1_set.intersection(seq2_set)) / (len(seq1_set) + len(seq2_set) - len(seq1_set.intersection(seq2_set)))


print(similarity(seq1, seq2, 'cos'))  # 余弦相似度
print(similarity(seq1, seq2, 'Eur'))  # 欧氏距离
print(similarity(seq1, seq2, 'Jac'))  # Jaccard相似度

结果见下面截图: 

 2、基于jieba开源工具库,运行TF*IDF案例

tfidf = jieba.analyse.TFIDF()
tfidf.STOP_WORDS = set()
tfidf.extract_tags(seq1, withWeight=True, topK=11)
tfidf.extract_tags(seq2, withWeight=True, topK=11)

结果见下面截图: 

 3、项目已代码写出来,提交截图

 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到