【NLP 18、新词发现和TF·IDF】
目录
一、新词发现
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.新词发现的衡量标准
① 内部稳固
词的内部应该是稳固的,用内部稳固度衡量
内部稳固度:词语中几个字的固定搭配出现的次数除以词语中每个字单独出现的概率的乘积
公式:
② 外部多变
词的外部应该是多变的,用左右熵衡量
左右熵: 将词语外部出现的所有字再除以出现的总词频数,得到出现某个字的频率pi,代入公式进行求和后取反,得到词语两边的左右熵,词语的外部两侧出现一个固定字的频率应该较低,换句话说,词的外部应该是多变的,而不是固定的,左右熵的值大小可以衡量词的外部值是否多变,左右熵的值越大,词的外部越多变
用两个指标计算分数,根据分数衡量一些文字组合是否是新词
公式:
2.示例
① 初始化类 NewWordDetect
Ⅰ 初始化参数:
设置词语最高长度为5个字符
初始化三个字典:word_count 统计词频,left_neighbor 和 right_neighbor 分别记录每个词的左邻词和右邻词
Ⅱ 加载语料库:调用 load_corpus 方法加载语料库数据
Ⅲ 计算指标:计算互信息(PMI),熵,以及词的价值
class NewWordDetect:def __init__(self, corpus_path):# 设置词语最高长度 1 - 5 四个字的词语self.max_word_length = 5self.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()
② 加载语料信息,并进行统计
Ⅰ 打开文件:打开并读取指定路径的文件,编码为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
③ 统计指定长度的词频及其左右邻居字符词频
Ⅰ 遍历句子:通过循环遍历句子中的每个位置,提取长度为word_length的子串
Ⅱ 统计词频:将提取的子串作为键,更新其在self.word_count字典中的计数
Ⅲ 统计左邻居字符:如果当前子串有左邻居字符,则更新self.left_neighbor字典中该子串对应左邻居字符的计数
Ⅳ 统计右邻居字符:如果当前子串有右邻居字符,则更新self.right_neighbor字典中该子串对应右邻居字符的计数
#按照窗口长度取词,并记录左邻右邻出现过的字及次数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] += 1if i - 1 >= 0:char = sentence[i - 1]self.left_neighbor[word][char] = self.left_neighbor[word].get(char, 0) + 1if i + word_length < len(sentence):char = sentence[i +word_length]self.right_neighbor[word][char] = self.right_neighbor[word].get(char, 0) + 1return
④ 计算熵
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
⑤ 计算左右熵
Ⅰ 初始化空字典:初始化两个空字典 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)
⑥ 统计词长总数
Ⅰ 初始化:初始化一个默认值为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)] += countreturn
⑦ 计算互信息
Ⅰ 初始化:调用 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 = 1for 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
⑧ 计算每个词的价值
Ⅰ 初始化:初始化 self.word_values 为空字典
Ⅱ 遍历:
如果词长度小于2或包含逗号,则跳过该词
获取词的PMI值、左熵和右熵,若不存在则设为极小值(1e-3)
使用PMI、左熵和右熵综合评估词的价值,公式为 pmi * max(le, re)
def calc_word_values(self):self.word_values = {}for word in self.pmi:if len(word) < 2 or "," in word:continuepmi = 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 defaultdictclass NewWordDetect:def __init__(self, corpus_path):# 设置词语最高长度 1 - 5 四个字的词语self.max_word_length = 5self.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] += 1if i - 1 >= 0:char = sentence[i - 1]self.left_neighbor[word][char] = self.left_neighbor[word].get(char, 0) + 1if i + word_length < len(sentence):char = sentence[i +word_length]self.right_neighbor[word][char] = self.right_neighbor[word].get(char, 0) + 1return#计算熵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)] += countreturn#计算互信息(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 = 1for 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)returndef calc_word_values(self):self.word_values = {}for word in self.pmi:if len(word) < 2 or "," in word:continuepmi = 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 * reif __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])
二、挑选重要词
假如一个词在某类文本(假设为A类)中出现次数很多,而在其他类别文本(非A类)出现很少,那么这个词是A类文本的重要词(高权重词)
反之,如果一个词出现在很多领域,则其对于任意类别的重要性都很差
是否能够根据一个词来区分其属于哪个领域
1.数学角度刻画重要词
TF · IDF:刻画某一个词对于某一领域的重要程度
TF:词频,某个词在某类别中出现的次数/该类别词的总数
IDF:逆文档频率,N代表文本总数,dfi代表包含词qi的文本中的总数
逆文档频率高 ——> 该词很少出现在其他文档
和语料库的文档总数成正比,和包含这个词的文档总数成反比
例:
TF在某一分类的值越大,则TF项在某一分类中更为重要,例如:a只出现在A文档中,则a对A文档的标志性比较大
TF·IDF其他计算方式
TF:
IDF:
每个词对于每个类别都会得到一个TF·IDF值
TF·IDF高 -> 该词对于该领域重要程度高,低则相反
2.算法特点
1.tf · idf 的计算非常依赖分词结果,如果分词出错,统计值的意义会大打折扣
2.每个词,对于每篇文档,有不同的tf-idf值,所以不能脱离数据讨论tf·idf
3.假如只有一篇文本,不能计算tf·idf
4.类别数据均衡很重要
5.容易受各种特殊符号影响,最好做一些预处理
3.算法示例
① 构建TF·IDF字典
Ⅰ 初始化字典:
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] = 0tf_dict[text_index][word] += 1idf_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] = 0tf_dict[text_index][word] += 1idf_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_dictdef 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()
4.TF·IDF应用 —— 搜索引擎
① 对于已有的所有网页(文本),计算每个网页中,词的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(查询)进行分词
对于文档D,计算query中的词在文档D中的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 = 0for 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, corpusdef 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 = 0for 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 resif __name__ == "__main__":path = "news.json"tf_idf_dict, corpus = load_data(path)while True:query = input("请输入您要搜索的内容:")search_engine(query, tf_idf_dict, corpus)
5.TF·IDF应用 —— 文本摘要
抽取式摘要
① 加载文档数据,并计算每个文档的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 Noneresult = []for index, sentence in enumerate(sentences):sentence_score = 0words = 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,10important_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:continuecorpus[index] += "\n" + abstractres.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 Noneresult = []for index, sentence in enumerate(sentences):sentence_score = 0words = 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,10important_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:continuecorpus[index] += "\n" + abstractres.append({"标题":title, "正文":content, "摘要":abstract})return resif __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()
6.TF·IDF应用 —— 文本相似度计算
① 加载文档数据并计算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 0return 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 0return 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("--------------")
7.TF·IDF的优势
① 可解释性好
可以清晰地看到关键词
即使预测结果出错,也很容易找到原因
② 计算速度快
分词本身占耗时最多,其余为简单统计计算
③ 对标注数据依赖小
可以使用无标注语料完成一部分工作
④ 可以与很多算法组合使用
可以看做是词权重的体现
8.TF·IDF的劣势
① 受分词效果影响大
② 词与词之间没有语义相似度
同义词之间也不会进行关联,不会被同等的对待
③ 没有语序信息
TF·IDF本质上是一个词袋模型,计算搜索信息中每一个词的TF·IDF值的总和,作为搜索信息与文档信息相关性的得分
④ 能力范围有限
无法完成复杂任务,如机器翻译和实体挖掘等
深度学习可以处理几乎所有任务,只是效果好坏区别,同时可以考虑语序、考虑词与词之间的相似度、也不依赖分词的结果
⑤ 样本不均衡会对结果有很大影响
词的总数多少也会影响TF·IDF值的大小,影响结果的好坏
⑥ 类内样本间分布不被考虑
将每篇独立的文章混合在一起,导致TF·IDF值的计算有误差
相关文章:
【NLP 18、新词发现和TF·IDF】
目录 一、新词发现 1.新词发现的衡量标准 ① 内部稳固 ② 外部多变 2.示例 ① 初始化类 NewWordDetect ② 加载语料信息,并进行统计 ③ 统计指定长度的词频及其左右邻居字符词频 ④ 计算熵 ⑤ 计算左右熵 编辑 ⑥ 统计词长总数 ⑦ 计算互信息 ⑧ 计算每个词…...
windows服务器Oracle TNS 远程监听器中毒
修复Oracle TNS 监听器远程中毒漏洞 1.1 修改监听文件 如何快速找到listener.ora ? cmd输入 tnsping localhost 修改配置文件,路径以自己的实际路径为准,我都在D盘 listener.ora内容如下: #listener.ora Network Configuration F…...
GitLab的安装和使用
1.GitLab 环境说明 系统版本 CentOS 7.2 x86_64 软件版本 gitlab-ce-10.8.4 GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的web服务。可通过Web界面进行访问公开的或者私人项目。它拥有与Github类似的功能…...
常用的JVM启动参数有哪些?
大家好,我是锋哥。今天分享关于【常用的JVM启动参数有哪些?】面试题。希望对大家有帮助; 常用的JVM启动参数有哪些? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 JVM启动参数用于配置Java虚拟机(JVM)的运行时行为…...
MobaXterm 连接不上VMware 的Ubuntu 虚拟机
想在window11的笔记本上通过VMWare安装Ubuntu操作系统,但是在两个桌面见来回切换,十分的麻烦,于是通过远程服务访问客户端软件MateXterm来访问虚拟机的Linux系统,但是从CSDN上搜到的教程都没有成功,于是,尝…...
异步BUCK二极管损耗计算
异步BUCK工作原理 Q闭合时(Ton),输入电压Vin为电感L和输出电容Cout充电,同时为负载供电;Q断开时(Toff),电感L为负载供电,电流通过续流二极管D回流到电感L; 之…...
【WPF】把DockPanel的内容生成图像
要在WPF中将一个 DockPanel 的内容生成为图像并保存,可以按照与之前类似的步骤进行,但这次我们将专注于 DockPanel 控件而不是整个窗口。 DockPanel的使用 WPF(Windows Presentation Foundation)中的 DockPanel 是一种布局控件&…...
STM32定时器对象捕获功能测量市电频率
在很多嵌入式系统中,精确地测量外部信号的频率是一个常见需求,尤其是对于需要同步外部电源(如市电)的应用。市电频率(50Hz或60Hz)是电力系统中一个至关重要的参数。在许多场景下,特别是UPS&…...
[react]5、React脚手架
1、前端脚手架 1、Vue的脚手架:vue-cli 2、Angular的脚手架:angular-cli 3、React的脚手架:create-react-app 目前这些脚手架都是使用node编写的,并且都是基于webpack的,需要在电脑上安装node环境 脚手架的作用是帮助我…...
uni-app开发个人中心页面
目录 一:功能实现 二:功能实现 一:功能实现 个人中心主要展示用户的个人信息,订单信息以及其他模块信息包含收藏,我的地址,我的钱包等。页面分为三个部分,底部显示用户信息和个人设置等。中间部分显示订单信息可以点击查看订单列表,底部显示其他模块信息。 二:功…...
Ubuntu 20.04 卸载和安装 MySQL8.0
卸载 首先,检查一下系统安装的软件包有哪些,使用dpkg -l | grep mysql命令: 为了将MySQL卸载干净,这些文件都需要被删除。 在Ubuntu20.04系统下,卸载干净MySQL8.0以确保下一次安装不会出错,可以按照以下…...
【深度学习-论文】通俗易懂的理解多标签识别
文章目录 1. 文章主要内容2. 通俗易懂的理解多标签分类到底是如何实现的通俗易懂的多标签分类实现介绍实现步骤为什么这么做?小结论文题目:Rada r emitter multi-la bel recognition based on residual network 基于残差网络的雷达发射机多标签识别1. 文章主要内容 《基于残…...
“TA”说|表数据备份还原:SQLark 百灵连接助力项目部署验收
💬 南飞雁|应用开发工程师 有些重要项目的部署验收,会在生产环境完成,验收完成后,又需要把这部分数据清空。这时就需要对数据表进行备份和还原,虽然可以通过命令直接实现,但是有一些操作门槛&am…...
android studio方便快捷保存数据读取数据(SharedPreferences)
原理:会自动生成一个xml文件,然后保存参数。xml文件的名字就是要读取的文件的名字。可以创建多个这样的xml文件。(储存方式是键值对方式,一个名字 对应 一个值) 首先先创建两个对象 private SharedPreferences shar…...
31.设计模式
单例模式 比如工具类,进需要一个实例,即可以在各处处理。用以节省创建类对象的开销和内存的开销。 保证一个类只有一个实例,而客户可以从一个众所周知的访问点访问它。 实现一个简单的单例 在一个python文件中定义一个类,并创…...
RTOS之邮箱
邮箱 邮箱 (Mailbox) 服务是实时操作系统中一种常用的线程间通信机制。它提供了一种高效、低开销的消息传递方式,允许线程之间交换固定大小的数据。 1. 邮箱的应用场景 考虑一个简单的示例:线程 1 负责检测按键状态并将状态信息发送出去,线程…...
Linux setfacl 命令详解
文章目录 Linux setfacl 命令详解一、ACL 和 setfacl 简介二、基本语法三、常用操作1. 查看 ACL2. 为用户设置权限3. 为组设置权限4. 删除 ACL 条目5. 设置默认 ACL6. 递归设置 ACL 四、示例操作1. 创建示例目录和文件2. 设置 ACL3. 验证 ACL 五、注意事项六、总结 Linux setfa…...
OpenCV 学习记录:首篇
最近在学习机器视觉,希望能通过记录博客的形式来鞭策自己坚持学完,同时也把重要的知识点记录下来供参考学习。 1. OpenCV 介绍与模块组成 什么是 OpenCV? OpenCV (Open Source Computer Vision Library) 是一个开源的计算机视觉和机器学习软…...
Java游戏开发基础:从零开始制作一个简单的2D游戏
目录 游戏开发概述 开发工具 项目结构 1. 创建游戏窗口 2. 游戏面板 解释: 3. 玩家类 解释: 4. 障碍物类 解释: 5. 游戏循环与碰撞检测 总结 在现代游戏开发中,Java被广泛应用于创建各种类型的游戏,特别是…...
入门STL(map/multiset)
目录 编辑 1.map 输入 输出 样例 输入 输出 解题代码: 2.multiset 输入 输出 样例 输入 输出 解题代码: 留下你的足迹吧!谢谢。 1.map map函数是一个内置函数,它允许你对一个序列)的每个元素应用…...
【mysql】1205 -Lock wait timeout exceeded; try restarting transaction
问题: mysql8执行SQL提示下面错误: 1205 -Lock wait timeout exceeded; try restarting transaction 1205-超过锁定等待超时;尝试重新启动事务 可能的原因: 事务冲突:多个事务同时尝试修改同一行数据,导…...
【开源免费】基于SpringBoot+Vue.JS在线宠物用品交易网站(JAVA毕业设计)
本文项目编号 T 092 ,文末自助获取源码 \color{red}{T092,文末自助获取源码} T092,文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...
postman读取文件执行
要从文件获取的变量 text 在pre-request 中写从文件获取数据的脚本。脚本实现了,设置了text默认值,从文件读取text列,将text存入环境变量 //获取text参数 var text "济南天气"; if(data.text){ text data.text } pm.environment.…...
UDP系统控制器_音量控制、电脑关机、文件打开、PPT演示、任务栏自动隐藏
UDP系统控制器(ShuiYX) 帮助文档 概述 本程序设计用于通过UDP协议接收指令来远程控制计算机的音量、执行特定命令和其他功能。为了确保程序正常工作,请确认防火墙和网络设置允许UDP通信,并且程序启动后会最小化到托盘图标。 命令格式及说明 音量控制…...
pydantic BaseModel
1. Pydantic 是什么? Pydantic 是一个Python库,主要用于数据验证和设置管理。它通过定义数据模型(Model)来确保输入数据的类型和结构符合预期。 Pydantic 的核心功能是基于Python的类型提示(Type Hints)&a…...
[创业之路-202]:任正非管理华为的思想与毛泽东管理党、军队、国家的思想的相似性与差异性
目录 一、相似性 1、指导思想 2、管理策略 3、危机意识与自我否定 4、理想主义与奋斗精神 二、差异性 1、哲学基础与思想倾向 2、管理方法与策略 3、组织文化与价值观 一、相似性 任正非管理华为的思想与毛泽东管理党、军队、国家的思想在多个方面存在相似性。 以下…...
【渗透测试】|brupsuit的使用
一、 1.1爆破模块: 1、将拦截发送到intruder模块 2、在intruder模块设置pyaload位置 3、选择攻击类型 4、 5、设置好攻击类型和payload集就可以点击开始攻击,点击后弹出具体攻击详情 6、【payloads】模块相关 6.1 payload集为【简单列表】 添加&…...
MySQL三大日志-Binlog
Binlog简介 Redo Log 是属于InnoDB引擎所特有的日志,而MySQL Server也有自己的日志,即 Binary log(二进制日志),简称Binlog。Binlog是记录所有数据库表结构变更以及表数据修改的二进制日志,不会记录SELECT…...
vue.js 指令的修饰符
Vue.js 提供了一些指令修饰符,用于在指令的行为上添加额外的功能。下面详细解析一些常用的指令修饰符,并提供相应的代码实例。 .prevent:阻止默认事件 通过添加 .prevent 修饰符,可以阻止指令绑定的元素触发默认事件。 代码实例&a…...
重撸设计模式--代理模式
文章目录 定义UML图代理模式主要有以下几种常见类型:代理模式涉及的主要角色有:C 代码示例 定义 代理模式(Proxy Pattern)属于结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。 通过引入代理对象&am…...
“从零到一:揭秘操作系统的奇妙世界”【操作系统系统调用】
【1】定义 系统调用是用户空间程序请求操作系统服务的一种机制。系统调用的调用程序运行在用户态,被调用程序运行在内核态。系统调用可以嵌套使用。系统调用是通过中断机制实现的,并且一个OS的所有系统调用都通过一个中断入口来实现参数通常通过寄存器传…...
MQTT协议常见问题
在MQTT协议中,发送DISCONNECT报文与在TCP层调用network_disconnect(或类似的函数,具体名称可能因实现而异)之间存在重要的关系,这涉及到协议的正确性和资源的正确释放。 ### MQTT DISCONNECT报文 MQTT DISCONNECT报文…...
ArcGIS计算土地转移矩阵
在计算土地转移矩阵时,最常使用的方法就是在ArcGIS中将土地利用栅格数据转为矢量,然后采用叠加分析计算,但这种方法计算效率低。还有一种方法是采用ArcGIS中的栅格计算器,将一个年份的地类编号乘以个100或是1000再加上另一个年份的…...
数据结构十大排序之(冒泡,快排,并归)
接上期: 数据结十大排序之(选排,希尔,插排,堆排)-CSDN博客 前言: 在计算机科学中,排序算法是最基础且最重要的算法之一。无论是大规模数据处理还是日常的小型程序开发,…...
MySql:基本查询
✨✨作者主页:嶔某✨✨ ✨✨所属专栏:MySql✨✨ 本文的代码中, [ ] 里面的都可以省略 在 MySQL 中,CRUD 是数据库操作的核心,代表以下四种基本操作: C(Create):创建、插…...
28、基于springboot的房屋租赁系统
房屋是人类生活栖息的重要场所,随着城市中的流动人口的增多,人们对房屋租赁需求越来越高,为满足用户查询房屋、预约看房、房屋租赁的需求,特开发了本基于Spring Boot的房屋租赁系统。 本文重点阐述了房屋租赁系统的开发过程&…...
96 vSystem
vSystem系统 1 技术背景 网络虚拟化旨在构建出一套与网络底层物理拓扑相互独立的逻辑网络环境,提供给不同需求的用户使用。基于这种思想,诞生出了 VLAN 技术和 VPN 技术。近年来, 随着以 VMM(Virtual Machine Monitor,…...
[创业之路-197]:华为的发展路径启示
目录 前言: 一、由小公司走向大公司: 二、由农村包围城市: 三、由国内走向国际: 四、由代理商走向设备商,再到系统方案商,再到生态系统的搭建: 五、由随性到跟随,到赶超&#…...
两款Windows电脑便签,常用的电脑桌面便签小工具推荐
现在的职场环境中,效率高低会影响我们的去留以及晋升,而电脑便签无疑是提高效率的重要辅助工具。对于Windows电脑的用户来说,选择合适的电脑桌面便签小工具尤为重要。今天为大家推荐两款使用过且好用实用的Windows电脑便签,希望可…...
sql server索引优化语句
第一步 建一个测试表 --create table TestUsers --( -- Id int primary key identity(1,1), -- Username varchar(30) not null, -- Password varchar(10) not null, -- CreateDateTime datetime not null --)第二步 插入100w数据 大概1分钟执行时间 ----插入数据…...
从监控异常发现网络安全
前言 最近在前端异常监控系统中,发现一些异常信息,从中做了一些分析,得到一些体会,因此作文。 发现异常 某天早上打开监控系统发现,当天凌晨1点过测试环境有2个前端上报的异常,报错的原因都是由于没有获取…...
Android学习(七)-Kotlin编程语言-Lambda 编程
Lambda 编程 而 Kotlin 从第一个版本开始就支持了 Lambda 编程,并且 Kotlin 中的 Lambda 功能极为强大。Lambda 表达式使得代码更加简洁和易读。 2.6.1 集合的创建与遍历 集合的函数式 API 是入门 Lambda 编程的绝佳示例,但在开始之前,我们…...
中国人工智能学会技术白皮书
中国人工智能学会的技术白皮书具有多方面的重要作用,是极具权威性和价值的参考资料。 看看编委会和编写组的阵容,还是很让人觉得靠谱的 如何下载这份资料呢?下面跟着步骤来吧 步骤一:进入中国智能学会官网。百度搜索“中国智能学…...
【集合】Java 8 - Stream API 17种常用操作与案例详解
文章目录 Java8 Stream API 17种常用操作与案例详解1. collect():将流中的元素收集到集合中2. filter():根据条件过滤流中的元素3. map():元素映射为另一个值4. forEach():对流中的元素执行操作5. flatMap():将流中的元…...
Spring(三)-SpringWeb-概述、特点、搭建、运行流程、组件、接受请求、获取请求数据、特殊处理、拦截器
文章目录 一、SpringWeb概述 二、SpringWeb特点 三、搭建SpringWeb(在web项目中) 1、导包 2、在web.xml文件中配置统一拦截分发器 DispatcherServlet 3、开启 SpringWEB 注解 4、处理器搭建 四、SpringWeb运行流程 五、SpringWeb组件 1、前端控…...
uni-app商品搜索页面
目录 一:功能概述 二:功能实现 一:功能概述 商品搜索页面,可以根据商品品牌,商品分类,商品价格等信息实现商品搜索和列表展示。 二:功能实现 1:商品搜索数据 <view class="search-map padding-main bg-base"> <view class…...
基于Spring Boot的远程教育网站
一、系统背景与意义 随着互联网技术的飞速发展和普及,远程教育已成为现代教育体系中的重要组成部分。它打破了时间和空间的限制,让学习者可以随时随地进行学习。基于Spring Boot的远程教育网站正是为了满足这一需求而设计的,它利用互联网技术…...
降低Mobx技术债问题-React前端数据流方案调研整理
我们现在主要是使用Mobx,但是Mobx的易于上手和灵活度也带来了很多预期以外的问题,随着项目的增长我们的代码技术债变得愈加沉重,不同的模块杂糅一起、单一store无限膨胀。 为此我们的调研是希望能找到一个更好的state配置、数据流的约定方案。…...
Linux通信System V:消息队列 信号量
Linux通信System V:消息队列 & 信号量 一、信号量概念二、信号量意义三、操作系统如何管理ipc资源(2.36版本)四、如何对信号量资源进行管理 一、信号量概念 信号量本质上就是计数器,用来保护共享资源。多个进程在进行通信时&a…...
STM32, GD32 cubemx CAN 低速率125kbps 报文丢失,解决了
用STM32 CUBEMX生成的GD32的 can程序,在500K波特率时可以正常使用,没有发现丢包,但速率降到250k和125k时,发送138帧数据,会丢失5个包。(系统时钟168M,APB1的时钟42M) 试了各种方法无…...