【NLP 18、新词发现和TF·IDF】

news2025/1/7 23:08:25

目录

一、新词发现

1.新词发现的衡量标准 

① 内部稳固 

② 外部多变 

2.示例 

① 初始化类 NewWordDetect

② 加载语料信息,并进行统计

③  统计指定长度的词频及其左右邻居字符词频

④ 计算熵

⑤ 计算左右熵

  ​编辑

⑥ 统计词长总数

⑦ 计算互信息

⑧  计算每个词的价值

⑨ 新词检测

​编辑

二、挑选重要词

1.数学角度刻画重要词

例:

​编辑

TF·IDF其他计算方式

2.算法特点

3.算法示例

① 构建TF·IDF字典

② 根据tf值和idf值计算tf·idf

③ 计算给定语料库中每个文档的TF-IDF值

④ 提取每个文本的前top个高频词

⑤ tf·idf的计算和使用 

4.TF·IDF应用 —— 搜索引擎

① 对于已有的所有网页(文本),计算每个网页中,词的TF·IDF值

② 对于一个输入query(查询)进行分词

③ TF·IDF实现简单搜索引擎

5.TF·IDF应用 —— 文本摘要

① 加载文档数据,并计算每个文档的TF·IDF值

② 计算生成每一篇文章的摘要

 ③ 生成文档摘要,并将摘要添加到原始文档中

④ TF·IDF实现简单文本摘要 

6.TF·IDF应用 —— 文本相似度计算

① 加载文档数据并计算TF-IDF值

② 将文章转换为向量

③  文档转换为向量表示

④ 计算两个向量间的余弦相似度

⑤ 计算输入文本与语料库所有文档的相似度

⑥ TF·IDF实现文本相似度计算 

7.TF·IDF的优势

① 可解释性好

② 计算速度快

③ 对标注数据依赖小

④ 可以与很多算法组合使用

8.TF·IDF的劣势

① 受分词效果影响大

② 词与词之间没有语义相似度

③ 没有语序信息

④ 能力范围有限

⑤ 样本不均衡会对结果有很大影响

⑥ 类内样本间分布不被考虑


死亡不是生命的终点,被遗忘才是

                                               —— 24.12.21

一、新词发现

引言

假设没有词表,如何从文本中发现新词?

随着时间的推移,新词会不断地出现,固有词表会过时

补充词表有利于下游任务

相当于一种固定搭配

1.新词发现的衡量标准 

① 内部稳固 

词的内部应该是稳固的,用内部稳固度/互信息衡量

内部稳固度/互信息:词语中几个字的固定搭配出现的次数除以词语中每个字单独出现的概率的乘积

公式:

n:词语中字的个数,词语的长度;

p(W):词语中几个字的固定搭配词语的出现次数;

p(c1)…p(cn):词语中每个字在词表中单独出现的概率

② 外部多变 

词的外部应该是多变的,用左右熵衡量

左右熵: 将词语外部出现的所有字再除以出现的总词频数,得到出现某个字的频率pi,代入公式进行求和后取反,得到词语两边的左右熵,词语的外部两侧出现一个固定字的频率应该较低,换句话说,词的外部应该是多变的,而不是固定的,左右熵的值大小可以衡量词的外部值是否多变左右熵的值越大,词的外部越多变

两个指标计算分数,根据分数衡量一些文字组合是否是新词  

公式:

pi:词语后出现某个字的频率,词语外部出现的所有字除以出现的总词频数


2.示例 

① 初始化类 NewWordDetect

Ⅰ 初始化参数:

        设置词语最高长度max_word_;ength为5个字符

        初始化三个字典word_count 统计词频left_neighborright_neighbor 分别记录每个词的左邻词右邻词

Ⅱ 加载语料库:调用 load_corpus 方法加载语料库数据

Ⅲ 计算指标:计算calc_pmi互信息(内部稳固度),calc_entropy熵,以及cal_word_values词的价值

class NewWordDetect:
    def __init__(self, corpus_path):
        # 设置词语最高长度 1 - 5 四个字的词语
        self.max_word_length = 5
        self.word_count = defaultdict(int)
        self.left_neighbor = defaultdict(dict)
        self.right_neighbor = defaultdict(dict)
        self.load_corpus(corpus_path)
        self.calc_pmi()
        self.calc_entropy()
        self.calc_word_values()

② 加载语料信息,并进行统计 load_corpus

Ⅰ 打开文件:打开并读取指定路径的文件,编码为UTF-8

Ⅱ 处理文件:对文件中的每一行进行处理,去除首尾空白字符

Ⅲ 句子统计:对每个句子不同长度(从1到self.max_word_length)进行n-gram统计

Ⅳ 计数操作:调用self.ngram_count方法进行具体的n-gram计数操作

    #加载语料数据,并进行统计
    def load_corpus(self, path):
        with open(path, encoding="utf8") as f:
            for line in f:
                sentence = line.strip()
                for word_length in range(1, self.max_word_length):
                    self.ngram_count(sentence, word_length)
        return

③  统计指定长度的词频及其左右邻居字符词频 ngram_count

Ⅰ 遍历句子:通过循环遍历句子中的每个可能的n-gram

Ⅱ 提取n-gram:当前索引位置提取长度为word_length的子串作为n-gram

Ⅲ 更新词频:将该n-gram的计数加1

Ⅳ 更新左邻居字符:如果存在左邻居字符,更新该n-gram的左邻居字符频率

Ⅴ 更新右邻居字符:如果存在右邻居字符,更新该n-gram的右邻居字符频率、

    #按照窗口长度取词,并记录左邻右邻出现过的字及次数
    def ngram_count(self, sentence, word_length):
        for i in range(len(sentence) - word_length + 1):
            word = sentence[i:i + word_length]
            self.word_count[word] += 1
            if i - 1 >= 0:
                char = sentence[i - 1]
                self.left_neighbor[word][char] = self.left_neighbor[word].get(char, 0) + 1
            if i + word_length < len(sentence):
                char = sentence[i +word_length]
                self.right_neighbor[word][char] = self.right_neighbor[word].get(char, 0) + 1
        return

④ 计算熵 calc_entropy_by_word_count_dict

sum():通过 sum(word_count_dict.values()) 计算所有单词的总出现次数

计算熵:遍历每个单词的出现次数,使用公式 -(c / total) * math.log((c / total), 10) 计算每个单词对熵的贡献,并累加这些值

返回熵值:将计算得到的熵值返回

    #计算熵
    def calc_entropy_by_word_count_dict(self, word_count_dict):
        total = sum(word_count_dict.values())
        entropy = sum([-(c / total) * math.log((c / total), 10) for c in word_count_dict.values()])
        return entropy

⑤ 计算左右熵 calc_entropy

  

Ⅰ 初始化空字典:初始化两个空字典 self.word_left_entropy 和 self.word_right_entropy 

Ⅱ 计算左熵:遍历 self.left_neighbor,对每个词调用 calc_entropy_by_word_count_dict 计算左熵,并存入 self.word_left_entropy

Ⅲ 计算右熵:遍历 self.right_neighbor,对每个词调用 calc_entropy_by_word_count_dict 计算右熵,并存入 self.word_right_entropy

    #计算左右熵
    def calc_entropy(self):
        self.word_left_entropy = {}
        self.word_right_entropy = {}
        for word, count_dict in self.left_neighbor.items():
            self.word_left_entropy[word] = self.calc_entropy_by_word_count_dict(count_dict)
        for word, count_dict in self.right_neighbor.items():
            self.word_right_entropy[word] = self.calc_entropy_by_word_count_dict(count_dict)

⑥ 统计不同词长下的词总数 calc_total_count_by_length

Ⅰ 初始化:初始化一个默认值为0的字典 self.word_count_by_length

Ⅱ 更新不同词长下的词总数:遍历 self.word_count,对于每个单词和它的计数,根据单词长度更新 self.word_count_by_length

    #统计每种词长下的词总数
    def calc_total_count_by_length(self):
        self.word_count_by_length = defaultdict(int)
        for word, count in self.word_count.items():
            self.word_count_by_length[len(word)] += count
        return

⑦ 计算稳固度/互信息 calc_pmi

Ⅰ 初始化:调用 calc_total_count_by_length 方法,计算不同长度的词频总数

Ⅱ 初始化 PMI 字典:创建一个空字典 self.pmi

Ⅲ 遍历词语:遍历 self.word_count 中的每个词语及其出现次数

Ⅳ 计算词语概率:计算词语的概率 p_word

Ⅴ 计算字符概率乘积:计算组成该词语的每个字符的概率乘积 p_chars

Ⅵ 计算 PMI 值:根据公式 math.log(p_word / p_chars, 10) / len(word) 计算 PMI内部稳固度,并存入 self.pmi

    #计算互信息(pointwise mutual information 凝固度)
    def calc_pmi(self):
        self.calc_total_count_by_length()
        self.pmi = {}
        for word, count in self.word_count.items():
            p_word = count / self.word_count_by_length[len(word)]
            p_chars = 1
            for char in word:
                p_chars *= self.word_count[char] / self.word_count_by_length[1]
            self.pmi[word] = math.log(p_word / p_chars, 10) / len(word)
        return

⑧  计算每个词的价值 calc_word_values

Ⅰ 初始化:初始化 self.word_values 为空字典

Ⅱ 遍历:

        如果:① 词长度小于2   包含逗号 或 ③ 包含句号,则跳过该词

        获取词的PMI值、左熵和右熵,若不存在则设为极小值(1e-3)

        使用PMI、左熵和右熵综合评估词的价值计算公式 pmi * max(le, re)

    def calc_word_values(self):
        self.word_values = {}
        # 过滤掉长度小于2的词,以及包含中文逗号和句号的词
        for word in self.pmi:
            if len(word) < 2 or "," in word or "。" in word:
                continue
            pmi = self.pmi.get(word, 1e-3)
            le = self.word_left_entropy.get(word, 1e-3)
            re = self.word_right_entropy.get(word, 1e-3)
            # 通过三个指标综合评估词的价值
            self.word_values[word] = pmi + le + re
            # self.word_values[word] = pmi * min(le, re)
            # self.word_values[word] = pmi * max(le, re)
            # self.word_values[word] = pmi + le * re
            # self.word_values[word] = pmi * le * re

⑨ 新词检测

Ⅰ 初始化:创建 NewWordDetect 对象,加载语料库

Ⅱ 计算特征:计算词语的频率、左右邻词、PMI、左右熵等特征

Ⅲ 排序并输出:根据总分对词语进行排序,分别输出长度为2、3、4的前十个高分词

import math
from collections import defaultdict

class NewWordDetect:
    def __init__(self, corpus_path):
        # 设置词语最高长度 1 - 5 四个字的词语
        self.max_word_length = 5
        self.word_count = defaultdict(int)
        self.left_neighbor = defaultdict(dict)
        self.right_neighbor = defaultdict(dict)
        self.load_corpus(corpus_path)
        self.calc_pmi()
        self.calc_entropy()
        self.calc_word_values()


    #加载语料数据,并进行统计
    def load_corpus(self, path):
        with open(path, encoding="utf8") as f:
            for line in f:
                sentence = line.strip()
                for word_length in range(1, self.max_word_length):
                    self.ngram_count(sentence, word_length)
        return

    #按照窗口长度取词,并记录左邻右邻出现过的字及次数
    def ngram_count(self, sentence, word_length):
        for i in range(len(sentence) - word_length + 1):
            word = sentence[i:i + word_length]
            self.word_count[word] += 1
            if i - 1 >= 0:
                char = sentence[i - 1]
                self.left_neighbor[word][char] = self.left_neighbor[word].get(char, 0) + 1
            if i + word_length < len(sentence):
                char = sentence[i +word_length]
                self.right_neighbor[word][char] = self.right_neighbor[word].get(char, 0) + 1
        return

    #计算熵
    def calc_entropy_by_word_count_dict(self, word_count_dict):
        total = sum(word_count_dict.values())
        entropy = sum([-(c / total) * math.log((c / total), 10) for c in word_count_dict.values()])
        return entropy

    #计算左右熵
    def calc_entropy(self):
        self.word_left_entropy = {}
        self.word_right_entropy = {}
        for word, count_dict in self.left_neighbor.items():
            self.word_left_entropy[word] = self.calc_entropy_by_word_count_dict(count_dict)
        for word, count_dict in self.right_neighbor.items():
            self.word_right_entropy[word] = self.calc_entropy_by_word_count_dict(count_dict)


    #统计每种词长下的词总数
    def calc_total_count_by_length(self):
        self.word_count_by_length = defaultdict(int)
        for word, count in self.word_count.items():
            self.word_count_by_length[len(word)] += count
        return

    #计算互信息(pointwise mutual information 凝固度)
    def calc_pmi(self):
        self.calc_total_count_by_length()
        self.pmi = {}
        for word, count in self.word_count.items():
            p_word = count / self.word_count_by_length[len(word)]
            p_chars = 1
            for char in word:
                p_chars *= self.word_count[char] / self.word_count_by_length[1]
            self.pmi[word] = math.log(p_word / p_chars, 10) / len(word)
        return

    def calc_word_values(self):
        self.word_values = {}
        for word in self.pmi:
            if len(word) < 2 or "," in word:
                continue
            pmi = self.pmi.get(word, 1e-3)
            le = self.word_left_entropy.get(word, 1e-3)
            re = self.word_right_entropy.get(word, 1e-3)
            # 通过三个指标综合评估词的价值
            # self.word_values[word] = pmi + le + re
            # self.word_values[word] = pmi * min(le, re)
            self.word_values[word] = pmi * max(le, re)
            # self.word_values[word] = pmi + le * re
            # self.word_values[word] = pmi * le * re

if __name__ == "__main__":
    nwd = NewWordDetect("sample_corpus.txt")
    value_sort = sorted([(word, count) for word, count in nwd.word_values.items()], key=lambda x:x[1], reverse=True)
    print([x for x, c in value_sort if len(x) == 2][:10])
    print([x for x, c in value_sort if len(x) == 3][:10])
    print([x for x, c in value_sort if len(x) == 4][:10])


从词到理解 

有了分词能力后,需要利用词来完成对文本的理解

首先可以想到的,就是从文章中挑选重要词

二、挑选重要词

1.何为重要词

假如一个词在某类文本(假设为A类)中出现次数很多,而在其他类别文本(非A类)出现很少,那么这个词是A类文本的重要词(高权重词 

例:恒星、黑洞 ——> 天文 

反之,如果一个词出现在很多领域,则其对于任意类别的重要性都很差

例:中国 ——> 政治?/地理?/经济?/足球?        你好 ——> ?/?/?/?

是否能够根据一个词区分其属于哪个领域


2.数学角度刻画重要词

TF · IDF:刻画某一个词对于某一领域的重要程度

TF:词频某个词在某类别中出现的次数 / 该类别词的总数

IDF(N/df):逆文档频率N:代表文本总数dfi:代表包含词qi的文本中的总数

逆文档频率高该词很少出现在其他文档

,分母+1是为了避免分母为0的情况

语料库的文档总数正比,和包含这个词的文档总数反比

例:

TF在某一分类的值越大,则TF项在某一分类中更为重要,例如:a只出现在A文档中,则a对A文档的标志性比较大

TF·IDF的其他计算公式:

TF:

IDF:

每个对于每个类别都会得到一个TF·IDF

TF·IDF高 -> 对于该领域重要程度高,低则相反


3.算法特点

1.tf · idf 的计算非常依赖分词结果,如果分词出错,统计值的意义会大打折扣

2.每个词,对于每篇文档,有不同的 tf-idf 值,所以不能脱离数据讨论 tf·idf

3.假如只有一篇文本,不能计算tf·idf

4.类别数据数量均衡很重要

5.容易受各种特殊符号影响,最好做一些预处理


4.算法示例

① 构建TF·IDF字典 

Ⅰ 初始化字典:

defaultdict: 是 Python 内置的 collection 模块中的一个类,它是 dict 的子类,提供了一种方便的方式来处理键不存在的情况。当你尝试访问 defaultdict 中不存在的键时,它会自动使用一个预先设定的工厂函数创建一个默认值作为该键的值,而不是像普通 dict 那样引发 KeyError 异常。

tf_dict:记录每个文档中每个词的出现频率

idf_dict:记录每个词出现在多少个文档中

Ⅱ 遍历语料库:

对于每篇文档,遍历其中的每个词,更新tf_dict和idf_dict

Ⅲ 转换idf_dict:

将idf_dict中的集合转换为文档数量

Ⅳ 返回结果:

返回tf_dict和idf_dict

#统计tf和idf值
def build_tf_idf_dict(corpus):
    tf_dict = defaultdict(dict)  #key:文档序号,value:dict,文档中每个词出现的频率
    idf_dict = defaultdict(set)  #key:词, value:set,文档序号,最终用于计算每个词在多少篇文档中出现过
    for text_index, text_words in enumerate(corpus):
        for word in text_words:
            if word not in tf_dict[text_index]:
                tf_dict[text_index][word] = 0
            tf_dict[text_index][word] += 1
            idf_dict[word].add(text_index)
    idf_dict = dict([(key, len(value)) for key, value in idf_dict.items()])
    return tf_dict, idf_dict

② 根据tf值和idf值计算tf·idf

Ⅰ 初始化:

创建一个默认字典 tf_idf_dict 来存储每个文本中每个词的TF-IDF值

Ⅱ 遍历文本:

遍历输入的 tf_dict,其中键是文本索引,值是该文本中每个词的词频计数字典

Ⅲ 计算TF:

对于每个词,计算其在当前文本中的词频(TF),即该词出现次数除以该文本中所有词的总次数

Ⅳ 计算TF·IDF:

根据公式 tf · idf = tf * log(D / (idf + 1)) 计算TF·IDF值,其中 D 是文本总数,idf 是逆文档频率

Ⅴ 存储结果:

将计算得到的TF-IDF值存入 tf_idf_dict 中

Ⅵ 返回结果:

返回包含所有文本中每个词的TF-IDF值的字典

#根据tf值和idf值计算tfidf
def calculate_tf_idf(tf_dict, idf_dict):
    tf_idf_dict = defaultdict(dict)
    for text_index, word_tf_count_dict in tf_dict.items():
        for word, tf_count in word_tf_count_dict.items():
            tf = tf_count / sum(word_tf_count_dict.values())
            #tf-idf = tf * log(D/(idf + 1))
            tf_idf_dict[text_index][word] = tf * math.log(len(tf_dict)/(idf_dict[word]+1))
    return tf_idf_dict

③ 计算给定语料库中每个文档的TF-IDF值

Ⅰ分词处理:

使用jieba.lcut对语料库中的每个文本进行分词

Ⅱ 构建TF和IDF字典:

调用build_tf_idf_dict函数,生成每个文档的词频(TF)字典和逆文档频率(IDF)字典

Ⅲ 计算TF-IDF:

调用calculate_tf_idf函数,根据TF和IDF字典计算每个文档的TF-IDF值

Ⅳ 返回结果:

返回包含每个文档TF-IDF值的字典。

#输入语料 list of string
def calculate_tfidf(corpus):
    #先进行分词
    corpus = [jieba.lcut(text) for text in corpus]
    tf_dict, idf_dict = build_tf_idf_dict(corpus)
    tf_idf_dict = calculate_tf_idf(tf_dict, idf_dict)
    return tf_idf_dict

④ 提取每个文本的前top个高频词

Ⅰ 初始化:

创建一个空字典topk_dict用于存储结果

Ⅱ 遍历文本:

遍历输入的tfidf_dict,对每个文本的TF-IDF值进行排序,取前top个词存入topk_dict

Ⅲ 打印输出:

如果print_word为真,则打印当前文本索引、路径及前top个词

Ⅳ 返回结果:

返回包含每个文本前top个高频词的字典

#根据tfidf字典,显示每个领域topK的关键词
def tf_idf_topk(tfidf_dict, paths=[], top=10, print_word=True):
    topk_dict = {}
    for text_index, text_tfidf_dict in tfidf_dict.items():
        word_list = sorted(text_tfidf_dict.items(), key=lambda x:x[1], reverse=True)
        topk_dict[text_index] = word_list[:top]
        if print_word:
            print(text_index, paths[text_index])
            for i in range(top):
                print(word_list[i])
            print("----------")
    return topk_dict

⑤ tf·idf的计算和使用 

import jieba
import math
import os
import json
from collections import defaultdict

"""
tfidf的计算和使用
"""

#统计tf和idf值
def build_tf_idf_dict(corpus):
    tf_dict = defaultdict(dict)  #key:文档序号,value:dict,文档中每个词出现的频率
    idf_dict = defaultdict(set)  #key:词, value:set,文档序号,最终用于计算每个词在多少篇文档中出现过
    for text_index, text_words in enumerate(corpus):
        for word in text_words:
            if word not in tf_dict[text_index]:
                tf_dict[text_index][word] = 0
            tf_dict[text_index][word] += 1
            idf_dict[word].add(text_index)
    idf_dict = dict([(key, len(value)) for key, value in idf_dict.items()])
    return tf_dict, idf_dict

#根据tf值和idf值计算tfidf
def calculate_tf_idf(tf_dict, idf_dict):
    tf_idf_dict = defaultdict(dict)
    for text_index, word_tf_count_dict in tf_dict.items():
        for word, tf_count in word_tf_count_dict.items():
            tf = tf_count / sum(word_tf_count_dict.values())
            #tf-idf = tf * log(D/(idf + 1))
            tf_idf_dict[text_index][word] = tf * math.log(len(tf_dict)/(idf_dict[word]+1))
    return tf_idf_dict

#输入语料 list of string
#["xxxxxxxxx", "xxxxxxxxxxxxxxxx", "xxxxxxxx"]
def calculate_tfidf(corpus):
    #先进行分词
    corpus = [jieba.lcut(text) for text in corpus]
    tf_dict, idf_dict = build_tf_idf_dict(corpus)
    tf_idf_dict = calculate_tf_idf(tf_dict, idf_dict)
    return tf_idf_dict

#根据tfidf字典,显示每个领域topK的关键词
def tf_idf_topk(tfidf_dict, paths=[], top=10, print_word=True):
    topk_dict = {}
    for text_index, text_tfidf_dict in tfidf_dict.items():
        word_list = sorted(text_tfidf_dict.items(), key=lambda x:x[1], reverse=True)
        topk_dict[text_index] = word_list[:top]
        if print_word:
            print(text_index, paths[text_index])
            for i in range(top):
                print(word_list[i])
            print("----------")
    return topk_dict

def main():
    dir_path = r"category_corpus/"
    corpus = []
    paths = []
    for path in os.listdir(dir_path):
        path = os.path.join(dir_path, path)
        if path.endswith("txt"):
            corpus.append(open(path, encoding="utf8").read())
            paths.append(os.path.basename(path))
    tf_idf_dict = calculate_tfidf(corpus)
    tf_idf_topk(tf_idf_dict, paths)

if __name__ == "__main__":
    main()


5.TF·IDF应用 —— 搜索引擎

1.对于已有的所有网页(文本),计算每个网页中,词的TFIDF值

2.对于一个输入query进行分词

3.对于文档X,计算query中的词在文档X中的TFIDF值总和,作为query和文档的相关性得分 

① 对于已有的所有网页(文本),计算每个网页中,词的TF·IDF值

Ⅰ 初始化:

调用 jieba.initialize() 初始化分词工具

Ⅱ 读取文件:

打开指定路径的文件,并读取其中的 JSON 数据

Ⅲ 构建语料库:

遍历每个文档,将标题和内容拼接成一个字符串,并添加到语料库列表中

Ⅳ 计算 TF-IDF:

调用 calculate_tfidf 函数,传入构建好的语料库,计算每个文档的 TF-IDF 值

Ⅴ 返回结果:

返回计算好的 TF-IDF 字典和语料库

#根据tfidf字典,显示每个领域topK的关键词
def tf_idf_topk(tfidf_dict, paths=[], top=10, print_word=True):
    topk_dict = {}
    for text_index, text_tfidf_dict in tfidf_dict.items():
        word_list = sorted(text_tfidf_dict.items(), key=lambda x:x[1], reverse=True)
        topk_dict[text_index] = word_list[:top]
        if print_word:
            print(text_index, paths[text_index])
            for i in range(top):
                print(word_list[i])
            print("----------")
    return topk_dict

② 对于一个输入query(查询)进行分词

对于文档X,计算query中的词在文档X中的TF·IDF值总和,作为query和文档的相关性得分 

Ⅰ分词查询:使用 jieba.lcut 对输入的查询进行分词

Ⅱ 计算得分:遍历 tf_idf_dict 中的每篇文档,根据查询词在文档中的 TF-IDF 值累加得分

Ⅲ 排序结果:将所有文档按得分从高到低排序

Ⅳ 输出结果:打印得分最高的前 top 篇文档内容,并返回包含所有文档及其得分的结果列表。

def search_engine(query, tf_idf_dict, corpus, top=3):
    query_words = jieba.lcut(query)
    res = []
    for doc_id, tf_idf in tf_idf_dict.items():
        score = 0
        for word in query_words:
            score += tf_idf.get(word, 0)
        res.append([doc_id, score])
    res = sorted(res, reverse=True, key=lambda x:x[1])
    for i in range(top):
        doc_id = res[i][0]
        print(corpus[doc_id])
        print("--------------")
    return res

③ TF·IDF实现简单搜索引擎

import jieba
import math
import os
import json
from collections import defaultdict
from calculate_tfidf import calculate_tfidf, tf_idf_topk
"""
基于tfidf实现简单搜索引擎
"""

jieba.initialize()

#加载文档数据(可以想象成网页数据),计算每个网页的tfidf字典
def load_data(file_path):
    corpus = []
    with open(file_path, encoding="utf8") as f:
        documents = json.loads(f.read())
        for document in documents:
            corpus.append(document["title"] + "\n" + document["content"])
        tf_idf_dict = calculate_tfidf(corpus)
    return tf_idf_dict, corpus

def search_engine(query, tf_idf_dict, corpus, top=3):
    query_words = jieba.lcut(query)
    res = []
    for doc_id, tf_idf in tf_idf_dict.items():
        score = 0
        for word in query_words:
            score += tf_idf.get(word, 0)
        res.append([doc_id, score])
    res = sorted(res, reverse=True, key=lambda x:x[1])
    for i in range(top):
        doc_id = res[i][0]
        print(corpus[doc_id])
        print("--------------")
    return res

if __name__ == "__main__":
    path = "news.json"
    tf_idf_dict, corpus = load_data(path)
    while True:
        query = input("请输入您要搜索的内容:")
        search_engine(query, tf_idf_dict, corpus)

总结:搜索引擎是要提前将所有的网页数据进行爬取得到词表,然后再在搜索引擎内进行搜索,但是这会被所谓的数据孤岛而影响 


6.TF·IDF应用 —— 文本摘要

抽取式摘要

1.通过计算TF-IDF值得到每个文本的关键词

2.将包含关键词多的句子,认为是关键句

3.挑选若干关键句,作为文本的摘要

① 加载文档数据,并计算每个文档的TF·IDF值

Ⅰ 初始化:调用 jieba.initialize() 初始化分词工具

Ⅱ 读取文件:打开并读取文件内容,解析为JSON格式的文档列表

Ⅲ 数据处理:遍历每个文档,确保标题和内容中不包含换行符,然后将标题和内容拼接成一个字符串并加入语料库

Ⅳ 计算TF-IDF:使用 calculate_tfidf 函数计算语料库的TF-IDF值

Ⅴ 返回结果:返回TF-IDF字典和语料库 

jieba.initialize()

#加载文档数据(可以想象成网页数据),计算每个网页的tfidf字典
def load_data(file_path):
    corpus = []
    with open(file_path, encoding="utf8") as f:
        documents = json.loads(f.read())
        for document in documents:
            assert "\n" not in document["title"]
            assert "\n" not in document["content"]
            corpus.append(document["title"] + "\n" + document["content"])
        tf_idf_dict = calculate_tfidf(corpus)
    return tf_idf_dict, corpus

② 计算生成每一篇文章的摘要

Ⅰ 句子分割:将文章按句号、问号、感叹号分割成句子列表

Ⅱ 过滤短文章:如果文章少于5个句子,返回None,因为太短的文章不适合做摘要

Ⅲ 计算句子得分:对每个句子进行分词,并根据TF-IDF词典计算句子得分

Ⅳ 排序并选择重要句子:根据句子得分排序,选择得分最高的前top个句子,并按原文顺序排列

Ⅴ 返回摘要:将选中的句子拼接成摘要返回

#计算每一篇文章的摘要
#输入该文章的tf_idf词典,和文章内容
#top为人为定义的选取的句子数量
#过滤掉一些正文太短的文章,因为正文太短在做摘要意义不大
def generate_document_abstract(document_tf_idf, document, top=3):
    sentences = re.split("?|!|。", document)
    #过滤掉正文在五句以内的文章
    if len(sentences) <= 5:
        return None
    result = []
    for index, sentence in enumerate(sentences):
        sentence_score = 0
        words = jieba.lcut(sentence)
        for word in words:
            sentence_score += document_tf_idf.get(word, 0)
        sentence_score /= (len(words) + 1)
        result.append([sentence_score, index])
    result = sorted(result, key=lambda x:x[0], reverse=True)
    #权重最高的可能依次是第10,第6,第3句,将他们调整为出现顺序比较合理,即3,6,10
    important_sentence_indexs = sorted([x[1] for x in result[:top]])
    return "。".join([sentences[index] for index in important_sentence_indexs])

 ③ 生成文档摘要,并将摘要添加到原始文档中

Ⅰ 初始化结果列表:创建一个空列表 res 用于存储最终的结果

Ⅱ 遍历文档:通过 tf_idf_dict.items() 遍历每个文档的TF-IDF字典

Ⅲ 分割标题和内容:从 corpus 中获取当前文档的内容,并按换行符分割为标题和正文

Ⅳ 生成摘要:调用 generate_document_abstract 函数生成摘要,如果摘要为空则跳过该文档

Ⅴ 更新文档并保存结果:生成的摘要添加到原始文档中,并将标题、正文和摘要存入结果列表

Ⅵ 返回结果:返回包含所有文档摘要的信息列表

#生成所有文章的摘要
def generate_abstract(tf_idf_dict, corpus):
    res = []
    for index, document_tf_idf in tf_idf_dict.items():
        title, content = corpus[index].split("\n")
        abstract = generate_document_abstract(document_tf_idf, content)
        if abstract is None:
            continue
        corpus[index] += "\n" + abstract
        res.append({"标题":title, "正文":content, "摘要":abstract})
    return res

④ TF·IDF实现简单文本摘要 

import jieba
import math
import os
import random
import re
import json
from collections import defaultdict
from calculate_tfidf import calculate_tfidf, tf_idf_topk
"""
基于tfidf实现简单文本摘要
"""

jieba.initialize()

#加载文档数据(可以想象成网页数据),计算每个网页的tfidf字典
def load_data(file_path):
    corpus = []
    with open(file_path, encoding="utf8") as f:
        documents = json.loads(f.read())
        for document in documents:
            assert "\n" not in document["title"]
            assert "\n" not in document["content"]
            corpus.append(document["title"] + "\n" + document["content"])
        tf_idf_dict = calculate_tfidf(corpus)
    return tf_idf_dict, corpus

#计算每一篇文章的摘要
#输入该文章的tf_idf词典,和文章内容
#top为人为定义的选取的句子数量
#过滤掉一些正文太短的文章,因为正文太短在做摘要意义不大
def generate_document_abstract(document_tf_idf, document, top=3):
    sentences = re.split("?|!|。", document)
    #过滤掉正文在五句以内的文章
    if len(sentences) <= 5:
        return None
    result = []
    for index, sentence in enumerate(sentences):
        sentence_score = 0
        words = jieba.lcut(sentence)
        for word in words:
            sentence_score += document_tf_idf.get(word, 0)
        sentence_score /= (len(words) + 1)
        result.append([sentence_score, index])
    result = sorted(result, key=lambda x:x[0], reverse=True)
    #权重最高的可能依次是第10,第6,第3句,将他们调整为出现顺序比较合理,即3,6,10
    important_sentence_indexs = sorted([x[1] for x in result[:top]])
    return "。".join([sentences[index] for index in important_sentence_indexs])

#生成所有文章的摘要
def generate_abstract(tf_idf_dict, corpus):
    res = []
    for index, document_tf_idf in tf_idf_dict.items():
        title, content = corpus[index].split("\n")
        abstract = generate_document_abstract(document_tf_idf, content)
        if abstract is None:
            continue
        corpus[index] += "\n" + abstract
        res.append({"标题":title, "正文":content, "摘要":abstract})
    return res


if __name__ == "__main__":
    path = "news.json"
    tf_idf_dict, corpus = load_data(path)
    res = generate_abstract(tf_idf_dict, corpus)
    writer = open("abstract.json", "w", encoding="utf8")
    writer.write(json.dumps(res, ensure_ascii=False, indent=2))
    writer.close()


7.TF·IDF应用 —— 文本相似度计算

1.对所有文本计算tfidf后,从每个文本选取tfidf较高的前n个词,得到一个词的集合S。

2.对于每篇文本D,计算S中的每个词的词频,将其作为文本的向量。

3.通过计算向量夹角余弦值,得到向量相似度,作为文本的相似度

4.向量夹角余弦值计算:

① 加载文档数据并计算TF-IDF值

Ⅰ 读取文件:从指定路径读取JSON格式的文档数据

Ⅱ 构建语料库:将每个文档的标题和内容拼接成一个字符串,存入语料库列表

Ⅲ 计算TF-IDF:调用calculate_tfidf函数计算语料库的TF-IDF值

Ⅳ 提取重要词:调用tf_idf_topk函数提取每篇文档中TF-IDF值最高的前5个词

Ⅴ 构建词汇表:将所有文档的重要词去重后存入集合,最终转换为列表

Ⅵ 返回结果:返回TF-IDF字典、词汇表和语料库。

jieba.initialize()

#加载文档数据(可以想象成网页数据),计算每个网页的tfidf字典
#之后统计每篇文档重要在前10的词,统计出重要词词表
#重要词词表用于后续文本向量化
def load_data(file_path):
    corpus = []
    with open(file_path, encoding="utf8") as f:
        documents = json.loads(f.read())
        for document in documents:
            corpus.append(document["title"] + "\n" + document["content"])
    tf_idf_dict = calculate_tfidf(corpus)
    topk_words = tf_idf_topk(tf_idf_dict, top=5, print_word=False)
    vocab = set()
    for words in topk_words.values():
        for word, score in words:
            vocab.add(word)
    print("词表大小:", len(vocab))
    return tf_idf_dict, list(vocab), corpus

② 将文章转换为向量

Ⅰ 初始化:初始化一个长度为词汇表大小的零向量 vector

Ⅱ 分词:使用 jieba.lcut 将文章分词为一个词语列表 passage_words

Ⅲ 更新词表:遍历词汇表中的每个词,计算其在文章中的出现频率,并更新到 vector 中

Ⅳ 返回结果:返回最终的向量

#passage是文本字符串
#vocab是词列表
#向量化的方式:计算每个重要词在文档中的出现频率
def doc_to_vec(passage, vocab):
    vector = [0] * len(vocab)
    passage_words = jieba.lcut(passage)
    for index, word in enumerate(vocab):
        vector[index] = passage_words.count(word) / len(passage_words)
    return vector

③  文档转换为向量表示

Ⅰ 输入参数:

corpus:一个包含多个文档的列表,每个文档是一个字符串

vocab:词汇表,一个包含所有可能单词的列表

Ⅱ 处理逻辑:

使用列表推导式遍历语料库中的每个文档 c,调用 doc_to_vec 函数将其转换为向量

doc_to_vec 函数会根据词汇表 vocab 计算文档中每个词的频率,并返回一个向量表示

最终返回一个包含所有文档向量的列表 corpus_vectors

#先计算所有文档的向量
def calculate_corpus_vectors(corpus, vocab):
    corpus_vectors = [doc_to_vec(c, vocab) for c in corpus]
    return corpus_vectors

④ 计算两个向量间的余弦相似度

计算点积:通过 zip 函数将两个向量对应元素相乘并求和,得到点积 x_dot_y

计算模长:分别计算两个向量的模长 sqrt_x 和 sqrt_y

处理特殊情况:如果任一向量的模长为0,返回0

计算相似度:返回点积除以两个模长的乘积,并加上一个小常数 1e-7 防止分母为0

#计算向量余弦相似度
def cosine_similarity(vector1, vector2):
    x_dot_y = sum([x*y for x, y in zip(vector1, vector2)])
    sqrt_x = math.sqrt(sum([x ** 2 for x in vector1]))
    sqrt_y = math.sqrt(sum([x ** 2 for x in vector2]))
    if sqrt_y == 0 or sqrt_y == 0:
        return 0
    return x_dot_y / (sqrt_x * sqrt_y + 1e-7)

⑤ 计算输入文本与语料库所有文档的相似度

Ⅰ 将输入文本转换为向量:调用 doc_to_vec 方法,将输入文本 passage 转换为词频向量 input_vec

Ⅱ 计算相似度:遍历语料库中的每个文档向量,使用 cosine_similarity 方法计算输入向量与每个文档向量的余弦相似度

 向量夹角余弦值计算公式:

Ⅲ 排序并返回结果:将所有相似度分数按降序排列,返回前4个最相似的文档索引及其相似度分数

#输入一篇文本,寻找最相似文本
def search_most_similar_document(passage, corpus_vectors, vocab):
    input_vec = doc_to_vec(passage, vocab)
    result = []
    for index, vector in enumerate(corpus_vectors):
        score = cosine_similarity(input_vec, vector)
        result.append([index, score])
    result = sorted(result, reverse=True, key=lambda x:x[1])
    return result[:4]

⑥ TF·IDF实现文本相似度计算 

#coding:utf8
import jieba
import math
import os
import json
from collections import defaultdict
from calculate_tfidf import calculate_tfidf, tf_idf_topk

"""
基于tfidf实现文本相似度计算
"""

jieba.initialize()

#加载文档数据(可以想象成网页数据),计算每个网页的tfidf字典
#之后统计每篇文档重要在前10的词,统计出重要词词表
#重要词词表用于后续文本向量化
def load_data(file_path):
    corpus = []
    with open(file_path, encoding="utf8") as f:
        documents = json.loads(f.read())
        for document in documents:
            corpus.append(document["title"] + "\n" + document["content"])
    tf_idf_dict = calculate_tfidf(corpus)
    topk_words = tf_idf_topk(tf_idf_dict, top=5, print_word=False)
    vocab = set()
    for words in topk_words.values():
        for word, score in words:
            vocab.add(word)
    print("词表大小:", len(vocab))
    return tf_idf_dict, list(vocab), corpus


#passage是文本字符串
#vocab是词列表
#向量化的方式:计算每个重要词在文档中的出现频率
def doc_to_vec(passage, vocab):
    vector = [0] * len(vocab)
    passage_words = jieba.lcut(passage)
    for index, word in enumerate(vocab):
        vector[index] = passage_words.count(word) / len(passage_words)
    return vector

#先计算所有文档的向量
def calculate_corpus_vectors(corpus, vocab):
    corpus_vectors = [doc_to_vec(c, vocab) for c in corpus]
    return corpus_vectors

#计算向量余弦相似度
def cosine_similarity(vector1, vector2):
    x_dot_y = sum([x*y for x, y in zip(vector1, vector2)])
    sqrt_x = math.sqrt(sum([x ** 2 for x in vector1]))
    sqrt_y = math.sqrt(sum([x ** 2 for x in vector2]))
    if sqrt_y == 0 or sqrt_y == 0:
        return 0
    return x_dot_y / (sqrt_x * sqrt_y + 1e-7)


#输入一篇文本,寻找最相似文本
def search_most_similar_document(passage, corpus_vectors, vocab):
    input_vec = doc_to_vec(passage, vocab)
    result = []
    for index, vector in enumerate(corpus_vectors):
        score = cosine_similarity(input_vec, vector)
        result.append([index, score])
    result = sorted(result, reverse=True, key=lambda x:x[1])
    return result[:4]


if __name__ == "__main__":
    path = "news.json"
    tf_idf_dict, vocab, corpus = load_data(path)
    corpus_vectors = calculate_corpus_vectors(corpus, vocab)
    passage = "WGT"
    for corpus_index, score in search_most_similar_document(passage, corpus_vectors, vocab):
        print("相似文章:\n", corpus[corpus_index].strip())
        print("得分:", score)
        print("--------------")

总结: TFIDF的计算是事先完成的,并不是实时计算,得到TFIDF的值,实际在任务中,我们需要运算的是对文档进行分词,然后将候选词的TFIDF值相加进行筛选


8.TF·IDF的优势

① 可解释性好

有具体的数据和分数,可以清晰地看到关键词

即使预测结果出错,也很容易找到原因

② 计算速度快

分词本身占耗时最多其余为简单统计计算

③ 对标注数据依赖小

可以使用无标注语料完成一部分工作

④ 可以与很多算法组合使用

可以看做是词权重的体现


9.TF·IDF的劣势

① 受分词效果影响大

分词错误会造成较大的影响

② 词与词之间没有语义相似度

同义词之间也不会进行关联,不会被同等的对待

③ 没有语序信息

TF·IDF本质上是一个词袋模型,计算搜索信息中每一个词的TF·IDF值的总和,作为搜索信息与文档信息相关性的得分

④ 能力范围有限

无法完成复杂任务,如机器翻译和实体挖掘等

深度学习可以处理几乎所有任务,只是效果好坏区别,同时可以考虑语序、考虑词与词之间的相似度、也不依赖分词的结果

⑤ 样本不均衡会对结果有很大影响

词的总数多少也会影响TF·IDF值的大小,影响结果的好坏

⑥ 类内样本间分布不被考虑

将每篇独立的文章混合在一起,导致TF·IDF值的计算有误差

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2272891.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GitLab创建用户,设置访问SSH Key

继上一篇 Linux Red Hat 7.9 Server安装GitLab-CSDN博客 安装好gitlab&#xff0c;启用管理员root账号后&#xff0c;开始创建用户账户 1、创建用户账户 进入管理后台页面 点击 New User 输入用户名、邮箱等必填信息和登录密码 密码最小的8位&#xff0c;不然会不通过 拉到…

计算机网络--路由表的更新

一、方法 【计算机网络习题-RIP路由表更新-哔哩哔哩】 二、举个例子 例1 例2

C语言 数组编程练习

1.将数组A的内容和数组B中的内容进行交换。&#xff08;数组一样大&#xff09; 2.创建一个整形数组&#xff0c;完成对数组的操作 实现函数Init()初始化数组全为0 实现print()打印数组的每个元素 实现reverse()函数完成数组元素的逆置 //2.创建一个整形数组&#xff0c;完…

H7-TOOL固件2.27发布,新增加40多款芯片脱机烧录,含多款车轨芯片,发布LUA API手册,CAN助手增加负载率,错误状态信息检测

H7-TOOL详细介绍&#xff08;含操作手册&#xff09;&#xff1a;H7-TOOL开发工具&#xff0c;1拖4/16脱机烧录&#xff0c;高速DAPLINK&#xff0c;RTOS Trace&#xff0c;CAN/串口助手, 示波器, RTT等&#xff0c;支持WiFi&#xff0c;以太网&#xff0c;高速USB和手持 - H7-…

基于Matlab的变压器仿真模型建模方法(13):单相升压自耦变压器的等效电路和仿真模型

1.单相升压自耦变压器的基本方程和等效电路 单相升压自耦变压器的接线原理图如图1所示。在建立自耦变压器的基本方程时,仍然把它看成是从双绕组变压器演变而来。在图1中,设节点a到节点b部分的绕组的匝数为,对应于双绕组变压器的原边绕组;节点c到节点a部分的绕组的绕组匝数为…

Linux——查看并修改文件夹可读可写等权限

一、查看当前文件夹下的所有文件夹的权限 ls -l二、命令 drwxrwxr-x&#xff1a;只有所有者有可读可写可执行权限&#xff0c;其他用户只有可读可执行权限。 sudo chmod -R 775 文件夹名字drwxrwxrwx&#xff1a;所有用户都有可读可写可执行权限。 sudo chmod -R 777 文件夹…

【C++面向对象——类的多态性与虚函数】计算图像面积(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 1. 纯虚函数 一、特点 二、使用场景 三、作用 四、注意事项 五、相关概念对比 2. 抽象类的使用 一、定义与概念 二、使用场景 编程要求 测试说明 通关代码 测试结果 任务描述 本关任务&#xff1a;设计一个矩形类、一个圆形…

杰发科技——使用ATCLinkTool解除读保护

0. 原因 在jlink供电电压不稳定的情况下&#xff0c;概率性出现读保护问题&#xff0c;量产时候可以通过离线烧录工具避免。代码中开了读保护&#xff0c;但是没有通过can/uart/lin/gpio控制等方式进行关闭&#xff0c;导致无法关闭读保护。杰发所有芯片都可以用本方式解除读保…

【pytorch-lightning】架构一览

pytorch-lightning是基于pytorch的一个套壳项目&#xff0c;适配pytorch的版本同步更新速度很快。 它将训练的几个主要流程模块化&#xff0c;减少重复工作&#xff0c;同时让支持分布式训练&#xff0c;不同平台的训练迁移变得更加简单。 官网链接

时空遥感影像智能解译软件(基础版)

一、时空遥感影像智能解译软件&#xff08;基础版&#xff09;简概 “时空遥感影像智能解译软件&#xff08;基础版&#xff09;”&#xff0c;该软件基于Python高级编程语言与PyQt5界面设计框架开发&#xff0c;依赖于sys、os系统库以及OpenCV、GDAL、Numpy、Math、Random、Ma…

Chapter4.3:Implementing a feed forward network with GELU activations

4 Implementing a GPT model from Scratch To Generate Text 4.3 Implementing a feed forward network with GELU activations 本节即将实现子模块&#xff0c;用于transformer block&#xff08;变换器块&#xff09;的一部分。为此&#xff0c;我们需要从激活函数开始。 深…

常见加密算法附JAVA代码案例

1、对称加密算法(AES、DES、3DES) 对称加密算法是指加密和解密采用相同的密钥,是可逆的(即可解密)。 AES加密算法是密码学中的高级加密标准,采用的是对称分组密码体制,密钥长度的最少支持为128。AES加密算法是美国联邦政府采用的区块加密标准,这个标准用来替代原先的…

SwiftUI 撸码常见错误 2 例漫谈

概述 在 SwiftUI 日常撸码过程中&#xff0c;头发尚且还算茂盛的小码农们经常会犯这样那样的错误。虽然犯这些错的原因都很简单&#xff0c;但有时想要快速准确的定位它们却并不容易。 况且这些错误还可能在模拟器和 Xcode 预览&#xff08;Preview&#xff09;表现的行为不甚…

linux系统(ubuntu,uos等)连接鸿蒙next(mate60)设备

以前在linux上是用adb连接&#xff0c;现在升级 到了鸿蒙next&#xff0c;adb就不好用了。得用Hdc来了&#xff0c;在windows上安装了hisuit用的好好的&#xff0c;但是到了linux(ubuntu2204)下载安装了 下载中心 | 华为开发者联盟-HarmonyOS开发者官网&#xff0c;共建鸿蒙生…

2024年12月HarmonyOS应用开发者高级认证全新题库

注意事项&#xff1a;切记在考试之外的设备上打开题库进行搜索&#xff0c;防止切屏三次考试自动结束&#xff0c;题目是乱序&#xff0c;每次考试&#xff0c;选项的顺序都不同&#xff0c;作者已于2024年12月15日又更新了一波题库&#xff0c;题库正确率99%&#xff01; 新版…

Anaconda安装(2024最新版)

安装新的anaconda需要卸载干净上一个版本的anaconda&#xff0c;不然可能会在新版本安装过程或者后续使用过程中出错&#xff0c;完全卸载干净anaconda的方法&#xff0c;可以参考我的博客&#xff01; 第一步&#xff1a;下载anaconda安装包 官网&#xff1a;Anaconda | The O…

docker中使用Volume完成数据共享

情景概述 在一个docker中&#xff0c;部署两个MySQL容器&#xff0c;假如它们的数据都存储在自己容器内部的data目录中。这样的存储方式会有以下问题&#xff1a; 1.无法保证两个MySQL容器中的数据同步。 2.容器删除后&#xff0c;数据就会丢失。 基于以上问题&#xff0c;容…

Mac软件介绍之录屏软件Filmage Screen

软件介绍 Filmage Screen 是一款专业的视频录制和编辑软件&#xff0c;适用于 Mac 系统 可以选择4k 60fps&#xff0c;可以选择录制电脑屏幕&#xff0c;摄像头录制&#xff0c;可以选择区域录制。同时也支持&#xff0c;简单的视频剪辑。 可以同时录制电脑麦克风声音 标准…

【Redis经典面试题七】Redis的事务机制是怎样的?

目录 一、Redis的事务机制 二、什么是Redis的Pipeline&#xff1f;和事务有什么区别&#xff1f; 三、Redis的事务和Lua之间有哪些区别&#xff1f; 3.1 原子性保证 3.2 交互次数 3.3 前后依赖 3.4 流程编排 四、为什么Lua脚本可以保证原子性&#xff1f; 五、为什么R…

【C++面向对象——群体类和群体数据的组织】实现含排序功能的数组类(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 1. 相关排序和查找算法的原理 2. C 类与成员函数的定义 3. 数组作为类的成员变量的处理 4. 函数参数传递与返回值处理 编程要求 测试说明 通关代码 测试结果 任务描述 本关任务&#xff1a; 将直接插入排序、直接选择排序、冒泡…