自然语言处理:文本聚类
介绍
大家好,博主又来和大家分享自然语言处理领域的知识了。今天给大家分享的内容是自然语言处理中的文本聚类。
文本聚类在自然语言处理领域占据着重要地位,它能将大量无序的文本按照内容的相似性自动划分成不同的类别,极大地提高了文本处理和信息提取的效率。就好比在一个大型图书馆中,文本聚类能够像智能管理员一样,把各种书籍按照主题分类摆放,方便读者快速找到所需资料。
而实现文本聚类的方法有很多,其中k均值聚类算法、基于高斯混合模型的最大期望值算法,以及无监督朴素贝叶斯模型是比较常用的。好了,话不多说,我们直接进入正题。
文本聚类
k均值聚类算法
k均值聚类算法是一种简单且经典的聚类算法。它的核心思想就像是在一群人中寻找几个代表,让其他人都围绕着这些代表“站队”。
具体来说,我们首先要确定聚类的数量k,这个k就像是我们设定的几个“代表小组”的数量。然后随机选择k个文本作为初始的聚类中心,就好像是先选了几个有代表性的人。接下来,计算每个文本与这k个聚类中心的距离,把文本分配到距离最近的聚类中心所代表的类别中。之后,不断地重新计算每个类别中所有文本的中心位置,也就是更新聚类中心,就像代表们根据自己所在小组的人员情况调整位置一样。重复这个过程,直到聚类中心不再变化或者变化很小,此时就完成了文本聚类。
这种算法的优点是简单易懂、计算效率高,对于大规模文本数据的处理有较好的可扩展性。但它也有一些缺点,比如需要预先指定聚类的数量k,这个k值如果选择不当,可能会导致聚类结果不理想;而且它对初始聚类中心的选择比较敏感,不同的初始中心可能会得到不同的聚类结果。
接下来,我们将着手实现k均值算法,以此来开展文本聚类的工作。此次所运用的数据集涵盖了大约1万本图书的相关信息,并且这些图书被划分为3种不同的主题类别。在这个数据集中,我们所关注的文本内容并非图书的标题,而是图书的摘要部分。我们用代码来演示:
预处理完整代码
nlp_book_data_collection.py
# 导入用于处理JSON数据的库
import json
# 导入defaultdict类,用于创建具有默认值的字典
from collections import defaultdict
# 导入spaCy库,用于自然语言处理
import spacy
# 从spaCy的中文停用词模块中导入停用词集合
from spacy.lang.zh.stop_words import STOP_WORDS
# 导入tqdm库,用于显示进度条
from tqdm import tqdm# 加载中文语言模型
nlp_model = spacy.load('zh_core_web_sm')# 定义一个类,用于收集和处理书籍数据
class BookDataCollection:# 类的初始化方法def __init__(self):# 训练集和测试集的文件名self.training_file, self.testing_file = 'train_original.jsonl', 'test_original.jsonl'self.init_data()# 定义一个内部函数,用于读取JSONL文件def read_json_file(self, file_path):# 以只读模式打开文件,并指定编码为UTF-8with open(file_path, 'r', encoding='utf-8') as file:# 将文件的每一行读取为一个列表json_lines = list(file)# 初始化一个空列表,用于存储解析后的JSON数据data_list = []# 遍历每一行JSON数据for json_str in json_lines:# 将JSON字符串解析为Python对象,并添加到数据列表中data_list.append(json.loads(json_str))# 返回解析后的数据列表return data_listdef init_data(self):# 调用read_json_file函数读取训练集和测试集数据self.training_data, self.testing_data = self.read_json_file(self.training_file), self.read_json_file(self.testing_file)# 打印训练集和测试集的大小print('训练集大小 =', len(self.training_data), ', 测试集大小 =', len(self.testing_data))# 初始化两个空字典,用于存储标签到ID和ID到标签的映射self.label_to_id, self.id_to_label = {}, {}# 遍历训练集和测试集数据for data_group in [self.training_data, self.testing_data]:# 遍历每个数据项for data_item in data_group:# 获取数据项的类别标签category = data_item['class']# 如果类别标签不在标签到ID的映射中if category not in self.label_to_id:# 生成一个新的IDindex = len(self.label_to_id)# 将类别标签和对应的ID添加到标签到ID的映射中self.label_to_id[category] = index# 将ID和对应的类别标签添加到ID到标签的映射中self.id_to_label[index] = category# 获取类别标签对应的IDlabel_index = self.label_to_id[category]# 在数据项中添加标签ID字段data_item['label'] = label_index# 定义一个方法,用于对文本进行分词处理def tokenize_text(self, attribute='book'):# 遍历训练集和测试集数据for data_group in [self.training_data, self.testing_data]:# 使用tqdm显示进度条,遍历每个数据项for data_item in tqdm(data_group):# 获取数据项指定属性的文本内容,并转换为小写text_content = data_item[attribute].lower()# 使用spaCy模型对文本进行处理,过滤掉停用词,并提取词元tokens = [token.text for token in nlp_model(text_content) if token.text not in STOP_WORDS]# 在数据项中添加分词结果字段data_item['tokens'] = tokens# 定义一个方法,用于创建词汇表def create_vocabulary(self, min_frequency=3, min_length=2, max_vocab_size=None):# 初始化一个defaultdict,用于统计词元的频率word_frequency = defaultdict(int)# 遍历训练集数据for data_item in self.training_data:# 获取数据项的分词结果tokens = data_item['tokens']# 遍历每个词元for token in tokens:# 统计词元的频率word_frequency[token] += 1# 打印唯一词元数量、总词元数量、最大词频和最小词频print(f'唯一词元数量 = {len(word_frequency)}, 总词元数量 = {sum(word_frequency.values())}, 'f'最大词频 = {max(word_frequency.values())}, 最小词频 = {min(word_frequency.values())}')# 初始化两个空字典,用于存储词元到ID和ID到词元的映射self.token_to_id = {}self.id_to_token = {}# 初始化总词频为0total_frequency = 0# 按词频从高到低对词元进行排序,并遍历for token, freq in sorted(word_frequency.items(), key=lambda x: -x[1]):# 如果指定了最大词汇表大小,且当前词汇表大小已达到最大值if max_vocab_size and len(self.token_to_id) >= max_vocab_size:# 跳出循环break# 如果词元的频率大于最小频率if freq > min_frequency:# 如果未指定最小词长,或者词元长度大于等于最小词长if (min_length is None) or (min_length and len(token) >= min_length):# 将词元添加到词元到ID的映射中,并分配一个新的IDself.token_to_id[token] = len(self.token_to_id)# 将ID添加到ID到词元的映射中,并关联对应的词元self.id_to_token[len(self.id_to_token)] = token# 累加词元的频率到总词频中total_frequency += freqelse:# 跳出循环break# 打印最小词频、最小词长、最大词汇表大小、剩余词元数量和词表内词元占比print(f'最小词频 = {min_frequency}, 最小词长 = {min_length}, 最大词表大小 = {max_vocab_size}, 'f'剩余词元数量 = {len(self.token_to_id)}, 'f'词表内词元占比 = {total_frequency / sum(word_frequency.values())}')# 定义一个方法,用于将词元转换为对应的IDdef convert_tokens_to_indices(self):# 遍历训练集和测试集数据for data_group in [self.training_data, self.testing_data]:# 遍历每个数据项for data_item in data_group:# 初始化一个空列表,用于存储词元对应的IDdata_item['token_indices'] = []# 遍历数据项的分词结果for token in data_item['tokens']:# 如果词元在词元到ID的映射中if token in self.token_to_id:# 将词元对应的ID添加到列表中data_item['token_indices'].append(self.token_to_id[token])
nlp_text_clustering.py
# 从book_data_container模块导入BookDataContainer类
from nlp_book_data_collection import BookDataCollection# 定义一个用于自然语言处理文本聚类的类
class NLPTextClustering:def __init__(self):passdef text_clustering(self):# 创建书籍数据集对象book_dataset = BookDataCollection()# 打印标签到ID的映射print(book_dataset.id_to_label)# 对文本进行分词处理book_dataset.tokenize_text(attribute='abstract')# 创建词汇表book_dataset.create_vocabulary(min_frequency=3)# 将词元转换为索引book_dataset.convert_tokens_to_indices()# 程序入口,当作为脚本直接运行时执行以下代码
if __name__ == "__main__":# 创建NLPTextClustering类的一个实例nlp_text_clustering = NLPTextClustering()# 调用实例的text_clustering方法进行文本聚类操作nlp_text_clustering.text_clustering()
预处理运行结果
训练集大小 = 8626 , 测试集大小 = 2156
{0: '计算机类', 1: '艺术传媒类', 2: '经管类'}
100%|██████████| 8626/8626 [02:29<00:00, 57.74it/s]
100%|██████████| 2156/2156 [00:37<00:00, 56.76it/s]
唯一词元数量 = 34251, 总词元数量 = 806791, 最大词频 = 19194, 最小词频 = 1
最小词频 = 3, 最小词长 = 2, 最大词表大小 = None, 剩余词元数量 = 9504, 词表内词元占比 = 0.8910448926673699进程已结束,退出代码为 0
然后,我们引入实现TF-IDF算法的相关函数,并把经过处理的数据集输入至该函数内,从而获取文档的特征信息。我们用代码来演示:
特征信息完整代码
nlp_tfidf_transformer.py
# 导入numpy库,用于进行数值计算
import numpy as np# 定义一个类,用于进行TF-IDF转换
class TFIDFTransformer:# 类的初始化方法def __init__(self, vocabulary_size, normalization='l2', smooth_idf_flag=True, sublinear_tf_flag=True):# 存储词汇表大小self.vocabulary_size = vocabulary_size# 存储归一化方法self.normalization = normalization# 存储是否进行平滑IDF计算的标志self.smooth_idf_flag = smooth_idf_flag# 存储是否进行子线性TF计算的标志self.sublinear_tf_flag = sublinear_tf_flag# 定义一个方法,用于拟合数据,计算IDF值def fit_data(self, input_data):# 初始化一个全零数组,用于存储每个词元的文档频率document_frequency = np.zeros(self.vocabulary_size, dtype=np.float64)# 遍历输入数据for data_item in input_data:# 遍历数据项中唯一的词元IDfor token_index in set(data_item):# 统计词元的文档频率document_frequency[token_index] += 1# 根据平滑IDF标志,对文档频率进行平滑处理document_frequency += int(self.smooth_idf_flag)# 计算样本数量,并根据平滑IDF标志进行调整num_samples = len(input_data) + int(self.smooth_idf_flag)# 计算每个词元的IDF值self.idf = np.log(num_samples / document_frequency) + 1# 定义一个方法,用于对输入数据进行转换def transform_data(self, input_data):# 确保已经计算了IDF值assert hasattr(self, 'idf')# 初始化一个全零矩阵,用于存储词频矩阵term_frequency = np.zeros((len(input_data), self.vocabulary_size), dtype=np.float64)# 遍历输入数据for i, data_item in enumerate(input_data):# 遍历数据项中的词元IDfor token in data_item:# 统计词元的词频term_frequency[i, token] += 1# 如果启用了子线性TF计算if self.sublinear_tf_flag:# 对词频矩阵进行子线性变换term_frequency = np.log(term_frequency + 1)# 计算TF-IDF矩阵transformed_data = term_frequency * self.idf# 如果启用了归一化if self.normalization:# 计算每行的L2范数row_norm = (transformed_data ** 2).sum(axis=1)# 将范数为0的行的范数设为1,避免除零错误row_norm[row_norm == 0] = 1# 对TF-IDF矩阵进行归一化处理transformed_data /= np.sqrt(row_norm)[:, None]# 返回转换后的矩阵return transformed_data# 定义一个方法,用于拟合数据并进行转换def fit_and_transform(self, input_data):# 调用fit_data方法拟合数据self.fit_data(input_data)# 调用transform_data方法进行转换return self.transform_data(input_data)
nlp_text_clustering.py
# 从nlp_book_data_collection模块导入BookDataCollection类
from nlp_book_data_collection import BookDataCollection
# 从nlp_tfidf_transformer模块导入TFIDFTransformer类
from nlp_tfidf_transformer import TFIDFTransformer# 定义一个用于自然语言处理文本聚类的类
class NLPTextClustering:def __init__(self):passdef text_clustering(self):# 创建书籍数据集对象book_dataset = BookDataCollection()# 打印标签到ID的映射print(book_dataset.id_to_label)# 对文本进行分词处理book_dataset.tokenize_text(attribute='abstract')# 创建词汇表book_dataset.create_vocabulary(min_frequency=3)# 将词元转换为索引book_dataset.convert_tokens_to_indices()# 获取训练集和测试集数据training_data, testing_data = book_dataset.training_data, book_dataset.testing_data# 获取词汇表大小vocabulary_size = len(book_dataset.token_to_id)# 初始化训练输入列表training_input = []# 遍历训练数据for data_item in training_data:# 将词元索引添加到训练输入列表training_input.append(data_item['token_indices'])# 创建TF-IDF转换器对象tfidf_transformer = TFIDFTransformer(vocabulary_size, normalization='l2', smooth_idf_flag=True,sublinear_tf_flag=True)# 拟合训练数据tfidf_transformer.fit_data(training_input)# 转换训练数据training_features = tfidf_transformer.transform_data(training_input)# 打印训练特征的形状print(training_features.shape)# 程序入口,当作为脚本直接运行时执行以下代码
if __name__ == "__main__":# 创建NLPTextClustering类的一个实例nlp_text_clustering = NLPTextClustering()# 调用实例的text_clustering方法进行文本聚类操作nlp_text_clustering.text_clustering()
特征信息运行结果
训练集大小 = 8626 , 测试集大小 = 2156
{0: '计算机类', 1: '艺术传媒类', 2: '经管类'}
100%|██████████| 8626/8626 [02:29<00:00, 57.74it/s]
100%|██████████| 2156/2156 [00:37<00:00, 56.76it/s]
唯一词元数量 = 34251, 总词元数量 = 806791, 最大词频 = 19194, 最小词频 = 1
最小词频 = 3, 最小词长 = 2, 最大词表大小 = None, 剩余词元数量 = 9504, 词表内词元占比 = 0.8910448926673699
(8626, 9504)进程已结束,退出代码为 0
当获取到数据后,便可运用k均值聚类算法对文本展开聚类操作。在此过程中,一个关键的前提是要预先设定簇数。为了便于与实际的标签数据进行对照分析,此次设定
值为 3。下面,我们用代码来演示:
聚类操作完整代码
nlp_kmeans_clusterer.py
# 导入NumPy库,用于数值计算
import numpy as np# 定义一个类,用于实现K-Means聚类算法
class KMeansClusterer:# 类的初始化方法def __init__(self, num_clusters, data_dimension, stop_threshold=1e-4, max_steps=100):# 存储聚类的数量self.num_clusters = num_clusters# 存储数据的维度self.data_dimension = data_dimension# 存储停止迭代的阈值self.stop_threshold = stop_threshold# 存储最大迭代步数self.max_steps = max_steps# 定义一个方法,用于更新聚类中心def update_cluster_centers(self, input_data):# 初始化一个全零矩阵,用于存储聚类中心cluster_centers = np.zeros([self.num_clusters, self.data_dimension])# 遍历每个聚类for k in range(self.num_clusters):# 获取属于当前聚类的数据点cluster_data = input_data[self.cluster_assignments == k]# 如果当前聚类中有数据点if len(cluster_data) > 0:# 计算当前聚类的中心cluster_centers[k] = cluster_data.mean(axis=0)# 返回更新后的聚类中心return cluster_centers# 定义一个方法,用于拟合模型def fit_model(self, input_data):# 打印初始化信息print('-----------初始化-----------')# 获取输入数据的样本数量num_samples = len(input_data)# 获取输入数据的维度data_dim = len(input_data[0])# 随机初始化每个数据点的聚类分配self.cluster_assignments = np.random.randint(0, self.num_clusters, num_samples)# 调用update_cluster_centers方法更新聚类中心self.cluster_centers = self.update_cluster_centers(input_data)# 打印初始化完成信息print('-----------初始化完成-----------')# 初始化当前迭代步数为0current_step = 0# 当当前迭代步数小于最大迭代步数时,继续迭代while current_step < self.max_steps:# 迭代步数加1current_step += 1# 初始化每个数据点的聚类分配为0self.cluster_assignments = np.zeros(num_samples, int)# 遍历每个数据点for i, data_point in enumerate(input_data):# 计算每个数据点和每个簇中心的L2距离distances = np.linalg.norm(data_point[None, :] - self.cluster_centers, ord=2, axis=-1)# 找到每个数据点所属新的聚类self.cluster_assignments[i] = distances.argmin(-1)# 调用update_cluster_centers方法更新聚类中心new_cluster_centers = self.update_cluster_centers(input_data)# 计算聚类中心的平均移动距离center_movement = np.linalg.norm(new_cluster_centers - self.cluster_centers, ord=2, axis=-1).mean()# 打印当前迭代步数和聚类中心的平均移动距离print(f"第{current_step}步,中心点平均移动距离:{center_movement}")# 如果聚类中心的平均移动距离小于停止迭代的阈值if center_movement < self.stop_threshold:# 打印停止迭代信息print("中心点不再移动,退出程序")# 跳出循环break# 更新聚类中心self.cluster_centers = new_cluster_centers
nlp_text_clustering.py
# 从nlp_book_data_collection模块导入BookDataCollection类
from nlp_book_data_collection import BookDataCollection
# 从nlp_tfidf_transformer模块导入TFIDFTransformer类
from nlp_tfidf_transformer import TFIDFTransformer
# 从nlp_kmeans_clusterer模块导入KMeansClusterer类
from nlp_kmeans_clusterer import KMeansClusterer# 聚类的数量
num_clusters = 3# 定义一个用于自然语言处理文本聚类的类
class NLPTextClustering:def __init__(self):passdef text_clustering(self):# 创建书籍数据集对象book_dataset = BookDataCollection()# 打印标签到ID的映射print(book_dataset.id_to_label)# 对文本进行分词处理book_dataset.tokenize_text(attribute='abstract')# 创建词汇表book_dataset.create_vocabulary(min_frequency=3)# 将词元转换为索引book_dataset.convert_tokens_to_indices()# 获取训练集和测试集数据training_data, testing_data = book_dataset.training_data, book_dataset.testing_data# 获取词汇表大小vocabulary_size = len(book_dataset.token_to_id)# 初始化训练输入列表training_input = []# 遍历训练数据for data_item in training_data:# 将词元索引添加到训练输入列表training_input.append(data_item['token_indices'])# 创建TF-IDF转换器对象tfidf_transformer = TFIDFTransformer(vocabulary_size, normalization='l2', smooth_idf_flag=True,sublinear_tf_flag=True)# 拟合训练数据tfidf_transformer.fit_data(training_input)# 转换训练数据training_features = tfidf_transformer.transform_data(training_input)# 打印训练特征的形状print(training_features.shape)# 创建K-Means聚类器对象kmeans_clusterer = KMeansClusterer(num_clusters, training_features.shape[1])# 拟合训练特征kmeans_clusterer.fit_model(training_features)# 程序入口,当作为脚本直接运行时执行以下代码
if __name__ == "__main__":# 创建NLPTextClustering类的一个实例nlp_text_clustering = NLPTextClustering()# 调用实例的text_clustering方法进行文本聚类操作nlp_text_clustering.text_clustering()
训练集大小 = 8626 , 测试集大小 = 2156
{0: '计算机类', 1: '艺术传媒类', 2: '经管类'}
100%|██████████| 8626/8626 [03:05<00:00, 46.54it/s]
100%|██████████| 2156/2156 [00:36<00:00, 58.80it/s]
唯一词元数量 = 34251, 总词元数量 = 806791, 最大词频 = 19194, 最小词频 = 1
最小词频 = 3, 最小词长 = 2, 最大词表大小 = None, 剩余词元数量 = 9504, 词表内词元占比 = 0.8910448926673699
(8626, 9504)
-----------初始化-----------
-----------初始化完成-----------
第1步,中心点平均移动距离:0.06890890571733081
第2步,中心点平均移动距离:0.05478241286369078
第3步,中心点平均移动距离:0.018892396863314006
第4步,中心点平均移动距离:0.013429342825043227
第5步,中心点平均移动距离:0.013566480916429499
第6步,中心点平均移动距离:0.013989222795632706
第7步,中心点平均移动距离:0.011440477943083664
第8步,中心点平均移动距离:0.007103963059848575
第9步,中心点平均移动距离:0.006074946365616077
第10步,中心点平均移动距离:0.00477369638045405
第11步,中心点平均移动距离:0.0037873833801874888
第12步,中心点平均移动距离:0.003169778238863545
第13步,中心点平均移动距离:0.0026544650799152428
第14步,中心点平均移动距离:0.0029003953549483793
第15步,中心点平均移动距离:0.002845907460494008
第16步,中心点平均移动距离:0.0029565530700650586
第17步,中心点平均移动距离:0.0046409302413431995
第18步,中心点平均移动距离:0.007601779316323283
第19步,中心点平均移动距离:0.008556943854755123
第20步,中心点平均移动距离:0.007326270837156583
第21步,中心点平均移动距离:0.004774654456463306
第22步,中心点平均移动距离:0.004131223162570739
第23步,中心点平均移动距离:0.0034665383237183632
第24步,中心点平均移动距离:0.0028326750163131242
第25步,中心点平均移动距离:0.0024085910806691804
第26步,中心点平均移动距离:0.0025467882048793647
第27步,中心点平均移动距离:0.0024867293424594233
第28步,中心点平均移动距离:0.00232851482144344
第29步,中心点平均移动距离:0.002858996918517763
第30步,中心点平均移动距离:0.0027176858630063097
第31步,中心点平均移动距离:0.0024908107307621374
第32步,中心点平均移动距离:0.002725824149863784
第33步,中心点平均移动距离:0.0029918663142641765
第34步,中心点平均移动距离:0.0021179114918197877
第35步,中心点平均移动距离:0.0019590759238497786
第36步,中心点平均移动距离:0.0021350571707413643
第37步,中心点平均移动距离:0.0029617190015900938
第38步,中心点平均移动距离:0.0033936270370122233
第39步,中心点平均移动距离:0.0029231439612436316
第40步,中心点平均移动距离:0.0032854686271343914
第41步,中心点平均移动距离:0.0031848632066834794
第42步,中心点平均移动距离:0.003748152169792271
第43步,中心点平均移动距离:0.0034990023467288468
第44步,中心点平均移动距离:0.003588666039850141
第45步,中心点平均移动距离:0.003444720739168902
第46步,中心点平均移动距离:0.004132389860665119
第47步,中心点平均移动距离:0.0042080010326193
第48步,中心点平均移动距离:0.004440204058509182
第49步,中心点平均移动距离:0.002555459672126323
第50步,中心点平均移动距离:0.0025740606612964256
第51步,中心点平均移动距离:0.0017377711466915063
第52步,中心点平均移动距离:0.001173105458515561
第53步,中心点平均移动距离:0.0014038477302960907
第54步,中心点平均移动距离:0.002010183332161079
第55步,中心点平均移动距离:0.0025465099651279664
第56步,中心点平均移动距离:0.003412787991913555
第57步,中心点平均移动距离:0.00491581405490893
第58步,中心点平均移动距离:0.006009725805675484
第59步,中心点平均移动距离:0.0030275349972018945
第60步,中心点平均移动距离:0.0023261247949924505
第61步,中心点平均移动距离:0.0019728143627690867
第62步,中心点平均移动距离:0.0021625513846364737
第63步,中心点平均移动距离:0.001665616845718412
第64步,中心点平均移动距离:0.000931590997003939
第65步,中心点平均移动距离:0.001013041855168734
第66步,中心点平均移动距离:0.0008405371362220621
第67步,中心点平均移动距离:0.001367543177768866
第68步,中心点平均移动距离:0.0014425643303775304
第69步,中心点平均移动距离:0.001116963591121085
第70步,中心点平均移动距离:0.001491048450742236
第71步,中心点平均移动距离:0.002040608920857972
第72步,中心点平均移动距离:0.0036833183433489704
第73步,中心点平均移动距离:0.010667221023078093
第74步,中心点平均移动距离:0.022518116498817724
第75步,中心点平均移动距离:0.019497945687248934
第76步,中心点平均移动距离:0.012781228163674337
第77步,中心点平均移动距离:0.006360174137399897
第78步,中心点平均移动距离:0.004201484107008095
第79步,中心点平均移动距离:0.0035826113950724998
第80步,中心点平均移动距离:0.0037105073591507513
第81步,中心点平均移动距离:0.00219649791629415
第82步,中心点平均移动距离:0.0015802391154533663
第83步,中心点平均移动距离:0.001539134331937778
第84步,中心点平均移动距离:0.0
中心点不再移动,退出程序进程已结束,退出代码为 0
为了能更直观地呈现聚类效果,我们定义了display_clusters()函数,它的作用是展示每个真实分类下各个簇的占比情况。接下来,我们会利用这个函数展示k均值算法的聚类结果,借此观察3个标签中不同簇的占比情况。 我们用代码来演示:
聚类结果完整代码
nlp_text_clustering.py
# 从nlp_book_data_collection模块导入BookDataCollection类
from nlp_book_data_collection import BookDataCollection
# 从nlp_tfidf_transformer模块导入TFIDFTransformer类
from nlp_tfidf_transformer import TFIDFTransformer
# 从nlp_kmeans_clusterer模块导入KMeansClusterer类
from nlp_kmeans_clusterer import KMeansClusterer# 聚类的数量
num_clusters = 3# 定义一个用于自然语言处理文本聚类的类
class NLPTextClustering:def __init__(self):passdef display_clusters(self, cluster_assignments, num_clusters, book_dataset, labels_list):# 初始化标签聚类字典label_clusters = {label_id: {} for label_id in book_dataset.id_to_label}# 初始化每个标签下每个聚类的计数为0for k, v in label_clusters.items():label_clusters[k] = {i: 0 for i in range(num_clusters)}# 遍历标签和聚类分配for label_id, cluster_id in zip(labels_list, cluster_assignments):# 增加对应标签和聚类的计数label_clusters[label_id][cluster_id] += 1# 按标签ID排序遍历for label_id in sorted(book_dataset.id_to_label.keys()):# 初始化聚类信息字符串cluster_str = book_dataset.id_to_label[label_id] + ':\t{ '# 遍历每个聚类for cluster_id in range(num_clusters):# 获取当前聚类的计数count = label_clusters[label_id][cluster_id]# 计算总数total = sum(label_clusters[label_id].values())# 拼接聚类信息cluster_str += f'{str(cluster_id)}: {count}({count / total:.2f}), '# 结束聚类信息字符串cluster_str += '}'# 打印聚类信息print(cluster_str)def text_clustering(self):# 创建书籍数据集对象book_dataset = BookDataCollection()# 打印标签到ID的映射print(book_dataset.id_to_label)# 对文本进行分词处理book_dataset.tokenize_text(attribute='abstract')# 创建词汇表book_dataset.create_vocabulary(min_frequency=3)# 将词元转换为索引book_dataset.convert_tokens_to_indices()# 获取训练集和测试集数据training_data, testing_data = book_dataset.training_data, book_dataset.testing_data# 获取词汇表大小vocabulary_size = len(book_dataset.token_to_id)# 初始化训练输入列表training_input = []# 遍历训练数据for data_item in training_data:# 将词元索引添加到训练输入列表training_input.append(data_item['token_indices'])# 创建TF-IDF转换器对象tfidf_transformer = TFIDFTransformer(vocabulary_size, normalization='l2', smooth_idf_flag=True,sublinear_tf_flag=True)# 拟合训练数据tfidf_transformer.fit_data(training_input)# 转换训练数据training_features = tfidf_transformer.transform_data(training_input)# 打印训练特征的形状print(training_features.shape)# 创建K-Means聚类器对象kmeans_clusterer = KMeansClusterer(num_clusters, training_features.shape[1])# 拟合训练特征kmeans_clusterer.fit_model(training_features)# 初始化标签列表labels_list = []# 遍历训练数据for data_item in training_data:# 将标签添加到标签列表labels_list.append(data_item['label'])# 打印标签列表的长度print(len(labels_list))# 获取K-Means聚类结果cluster_assignments = kmeans_clusterer.cluster_assignments# 显示K-Means聚类结果self.display_clusters(cluster_assignments, num_clusters, book_dataset, labels_list)# 程序入口,当作为脚本直接运行时执行以下代码
if __name__ == "__main__":# 创建NLPTextClustering类的一个实例nlp_text_clustering = NLPTextClustering()# 调用实例的text_clustering方法进行文本聚类操作nlp_text_clustering.text_clustering()
聚类结果运行结果
训练集大小 = 8626 , 测试集大小 = 2156
{0: '计算机类', 1: '艺术传媒类', 2: '经管类'}
100%|██████████| 8626/8626 [03:00<00:00, 47.89it/s]
100%|██████████| 2156/2156 [00:36<00:00, 58.84it/s]
唯一词元数量 = 34251, 总词元数量 = 806791, 最大词频 = 19194, 最小词频 = 1
最小词频 = 3, 最小词长 = 2, 最大词表大小 = None, 剩余词元数量 = 9504, 词表内词元占比 = 0.8910448926673699
(8626, 9504)
-----------初始化-----------
-----------初始化完成-----------
第1步,中心点平均移动距离:0.07187923654672244
第2步,中心点平均移动距离:0.044157507688436216
第3步,中心点平均移动距离:0.022896531888343605
第4步,中心点平均移动距离:0.0159488039593934
第5步,中心点平均移动距离:0.012182250613021412
第6步,中心点平均移动距离:0.012091131336056611
第7步,中心点平均移动距离:0.011953069179042916
第8步,中心点平均移动距离:0.007551366337940332
第9步,中心点平均移动距离:0.00607274740895354
第10步,中心点平均移动距离:0.0051005041228621905
第11步,中心点平均移动距离:0.0037475278494419353
第12步,中心点平均移动距离:0.002873947676155657
第13步,中心点平均移动距离:0.0032856197227294393
第14步,中心点平均移动距离:0.0037597515304094073
第15步,中心点平均移动距离:0.005154214384698833
第16步,中心点平均移动距离:0.01429702264635499
第17步,中心点平均移动距离:0.011662801294254196
第18步,中心点平均移动距离:0.01061592695683227
第19步,中心点平均移动距离:0.01964312337838108
第20步,中心点平均移动距离:0.012665767903761787
第21步,中心点平均移动距离:0.005392861470868378
第22步,中心点平均移动距离:0.002772730322582759
第23步,中心点平均移动距离:0.0018288923370850228
第24步,中心点平均移动距离:0.0014922387193858154
第25步,中心点平均移动距离:0.0010964808376660166
第26步,中心点平均移动距离:0.0011809417903345324
第27步,中心点平均移动距离:0.0008189027391701968
第28步,中心点平均移动距离:0.0008794506802535549
第29步,中心点平均移动距离:0.0003873751480754425
第30步,中心点平均移动距离:0.00023008235702405927
第31步,中心点平均移动距离:0.0
中心点不再移动,退出程序
8626
计算机类: { 0: 397(0.10), 1: 845(0.22), 2: 2600(0.68), }
艺术传媒类: { 0: 177(0.08), 1: 2115(0.92), 2: 7(0.00), }
经管类: { 0: 2408(0.97), 1: 36(0.01), 2: 41(0.02), }进程已结束,退出代码为 0
基于高斯混合模型的最大期望值算法
基于高斯混合模型的最大期望值算法则是另一种强大的文本聚类方法。高斯混合模型认为文本数据是由多个高斯分布混合而成的,就好像是把不同颜色的颜料混合在一起。
最大期望值算法通过不断地迭代,分为期望步骤和最大化步骤。在期望步骤中,根据当前的模型参数,计算每个文本属于不同高斯分布的概率,就像是猜测每个文本更可能属于哪一种“颜料”;在最大化步骤中,利用期望步骤得到的概率,重新计算模型的参数,比如高斯分布的均值、方差和权重,就像调整颜料的混合比例。通过这样反复迭代,让模型更好地拟合文本数据,从而实现文本聚类。
这种算法的优势在于能够灵活地拟合复杂的数据分布,对于多模态的数据聚类效果很好,而且它有完善的理论基础。不过,它也存在一些问题,比如计算复杂度比较高,对超参数的选择很敏感,像高斯分布的数量、协方差类型等,而且容易陷入局部最优解,就像在一个复杂的迷宫中,容易被困在某个局部区域,找不到全局最优的聚类结果。
下面,我们来演示怎样运用高斯混合模型进行聚类操作。需要注意的是,高斯混合模型会计算每个数据点属于各个簇的概率分布,在实际应用中,我们通常把概率最高的簇作为最终的聚类输出结果。通过这种方式,我们就能依据数据点的概率分布情况,将它们划分到最合适的簇中,实现文本数据的有效聚类。我们用代码来演示:
高斯混合聚类完整代码
nlp_gaussian_mixture_model.py
# 导入NumPy库,用于数值计算
import numpy as np
# 从scipy库中导入多元正态分布函数
from scipy.stats import multivariate_normal as gaussian# 定义高斯混合模型类
class GaussianMixtureModel:# 初始化方法,设置聚类数量、数据维度和最大迭代次数def __init__(self, num_clusters, data_dimension, max_iterations=100):# 存储聚类数量self.num_clusters = num_clusters# 存储数据维度self.data_dimension = data_dimension# 存储最大迭代次数self.max_iterations = max_iterations# 初始化混合系数,每个聚类初始权重相同self.mixing_coefficients = np.ones(num_clusters) / num_clusters# 随机初始化每个聚类的均值self.means = np.random.rand(num_clusters, data_dimension) * 2 - 1# 初始化协方差矩阵为全零矩阵self.covariances = np.zeros((num_clusters, data_dimension, data_dimension))# 遍历每个聚类for i in range(num_clusters):# 将每个聚类的协方差矩阵设为单位矩阵self.covariances[i] = np.eye(data_dimension)# 期望步骤,计算每个数据点属于每个聚类的概率def expectation_step(self, input_data):# 遍历每个聚类for i in range(self.num_clusters):# 计算每个数据点属于当前聚类的概率self.responsibilities[:, i] = self.mixing_coefficients[i] * gaussian.pdf(input_data, mean=self.means[i],cov=self.covariances[i])# 对概率进行归一化处理self.responsibilities /= self.responsibilities.sum(axis=1, keepdims=True)# 最大化步骤,更新模型参数def maximization_step(self, input_data):# 计算每个聚类的责任权重总和responsibility_sum = self.responsibilities.sum(axis=0)# 更新混合系数self.mixing_coefficients = responsibility_sum / self.num_samples# 更新每个聚类的均值self.means = np.matmul(self.responsibilities.T, input_data) / responsibility_sum[:, None]# 遍历每个聚类for i in range(self.num_clusters):# 计算数据点与当前聚类均值的差值delta = np.expand_dims(input_data, axis=1) - self.means[i]# 计算协方差矩阵covariance = np.matmul(delta.transpose(0, 2, 1), delta)# 更新当前聚类的协方差矩阵self.covariances[i] = np.matmul(covariance.transpose(1, 2, 0), self.responsibilities[:, i]) / \responsibility_sum[i]# 计算对数似然值def log_likelihood_value(self, input_data):# 初始化对数似然值为0log_likelihood = 0# 遍历每个数据点for data_point in input_data:# 初始化概率为0probability = 0# 遍历每个聚类for i in range(self.num_clusters):# 累加数据点属于当前聚类的概率probability += self.mixing_coefficients[i] * gaussian.pdf(data_point, mean=self.means[i],cov=self.covariances[i])# 累加对数概率log_likelihood += np.log(probability)# 返回平均对数似然值return log_likelihood / self.num_samples# 拟合模型def fit_model(self, input_data):# 存储输入数据的样本数量self.num_samples = len(input_data)# 初始化责任矩阵为全零矩阵self.responsibilities = np.zeros((self.num_samples, self.num_clusters))# 计算初始对数似然值log_likelihood = self.log_likelihood_value(input_data)# 打印开始迭代信息print('开始迭代')# 开始迭代for i in range(self.max_iterations):# 执行期望步骤self.expectation_step(input_data)# 执行最大化步骤self.maximization_step(input_data)# 计算新的对数似然值new_log_likelihood = self.log_likelihood_value(input_data)# 打印当前迭代步数和对数似然值print(f'第{i}步, log-likelihood = {new_log_likelihood:.4f}')# 如果对数似然值变化小于阈值,停止迭代if new_log_likelihood - log_likelihood < 1e-4:print('log-likelihood不再变化,退出程序')breakelse:# 更新对数似然值log_likelihood = new_log_likelihood# 转换数据,返回每个数据点所属的聚类def transform_data(self, input_data):# 确保责任矩阵已计算且长度与输入数据一致assert hasattr(self, 'responsibilities') and len(self.responsibilities) == len(input_data)# 返回每个数据点所属的聚类索引return np.argmax(self.responsibilities, axis=1)# 拟合并转换数据def fit_and_transform(self, input_data):# 拟合模型self.fit_model(input_data)# 转换数据return self.transform_data(input_data)
和k均值聚类方法相似,在运用基于最大期望值法的高斯混合模型时,我们来观察一下在Books数据集中,3个真实类别里不同簇各自所占的比例情况:
nlp_text_clustering.py
# 从nlp_book_data_collection模块导入BookDataCollection类
from nlp_book_data_collection import BookDataCollection
from nlp_gaussian_mixture_model import GaussianMixtureModel
# 从nlp_tfidf_transformer模块导入TFIDFTransformer类
from nlp_tfidf_transformer import TFIDFTransformer
# 从nlp_kmeans_clusterer模块导入KMeansClusterer类
from nlp_kmeans_clusterer import KMeansClusterer
# 从sklearn库中导入主成分分析(PCA)类
from sklearn.decomposition import PCA# 聚类的数量
num_clusters = 3# 定义一个用于自然语言处理文本聚类的类
class NLPTextClustering:def __init__(self):passdef display_clusters(self, cluster_assignments, num_clusters, book_dataset, labels_list):# 初始化标签聚类字典label_clusters = {label_id: {} for label_id in book_dataset.id_to_label}# 初始化每个标签下每个聚类的计数为0for k, v in label_clusters.items():label_clusters[k] = {i: 0 for i in range(num_clusters)}# 遍历标签和聚类分配for label_id, cluster_id in zip(labels_list, cluster_assignments):# 增加对应标签和聚类的计数label_clusters[label_id][cluster_id] += 1# 按标签ID排序遍历for label_id in sorted(book_dataset.id_to_label.keys()):# 初始化聚类信息字符串cluster_str = book_dataset.id_to_label[label_id] + ':\t{ '# 遍历每个聚类for cluster_id in range(num_clusters):# 获取当前聚类的计数count = label_clusters[label_id][cluster_id]# 计算总数total = sum(label_clusters[label_id].values())# 拼接聚类信息cluster_str += f'{str(cluster_id)}: {count}({count / total:.2f}), '# 结束聚类信息字符串cluster_str += '}'# 打印聚类信息print(cluster_str)def text_clustering(self):# 创建书籍数据集对象book_dataset = BookDataCollection()# 打印标签到ID的映射print(book_dataset.id_to_label)# 对文本进行分词处理book_dataset.tokenize_text(attribute='abstract')# 创建词汇表book_dataset.create_vocabulary(min_frequency=3)# 将词元转换为索引book_dataset.convert_tokens_to_indices()# 获取训练集和测试集数据training_data, testing_data = book_dataset.training_data, book_dataset.testing_data# 获取词汇表大小vocabulary_size = len(book_dataset.token_to_id)# 初始化训练输入列表training_input = []# 遍历训练数据for data_item in training_data:# 将词元索引添加到训练输入列表training_input.append(data_item['token_indices'])# 创建TF-IDF转换器对象tfidf_transformer = TFIDFTransformer(vocabulary_size, normalization='l2', smooth_idf_flag=True,sublinear_tf_flag=True)# 拟合训练数据tfidf_transformer.fit_data(training_input)# 转换训练数据training_features = tfidf_transformer.transform_data(training_input)# 打印训练特征的形状print(training_features.shape)# 创建K-Means聚类器对象kmeans_clusterer = KMeansClusterer(num_clusters, training_features.shape[1])# 拟合训练特征kmeans_clusterer.fit_model(training_features)# 初始化标签列表labels_list = []# 遍历训练数据for data_item in training_data:# 将标签添加到标签列表labels_list.append(data_item['label'])# 打印标签列表的长度print(len(labels_list))# 获取K-Means聚类结果cluster_assignments = kmeans_clusterer.cluster_assignments# 显示K-Means聚类结果self.display_clusters(cluster_assignments, num_clusters, book_dataset, labels_list)# 创建PCA降维器对象pca_reducer = PCA(n_components=50)# 对训练特征进行降维training_pca = pca_reducer.fit_transform(training_features)# 创建高斯混合模型对象gmm_model = GaussianMixtureModel(num_clusters, data_dimension=training_pca.shape[1])# 拟合并转换训练数据cluster_assignments = gmm_model.fit_and_transform(training_pca)# 打印高斯混合模型聚类结果print(cluster_assignments)# 显示高斯混合模型聚类结果self.display_clusters(cluster_assignments, num_clusters, book_dataset, labels_list)# 程序入口,当作为脚本直接运行时执行以下代码
if __name__ == "__main__":# 创建NLPTextClustering类的一个实例nlp_text_clustering = NLPTextClustering()# 调用实例的text_clustering方法进行文本聚类操作nlp_text_clustering.text_clustering()
高斯混合聚类运行结果
训练集大小 = 8626 , 测试集大小 = 2156
{0: '计算机类', 1: '艺术传媒类', 2: '经管类'}
100%|██████████| 8626/8626 [02:36<00:00, 54.95it/s]
100%|██████████| 2156/2156 [00:36<00:00, 59.32it/s]
唯一词元数量 = 34251, 总词元数量 = 806791, 最大词频 = 19194, 最小词频 = 1
最小词频 = 3, 最小词长 = 2, 最大词表大小 = None, 剩余词元数量 = 9504, 词表内词元占比 = 0.8910448926673699
(8626, 9504)
-----------初始化-----------
-----------初始化完成-----------
第1步,中心点平均移动距离:0.07821463876668384
第2步,中心点平均移动距离:0.05703827383757104
第3步,中心点平均移动距离:0.0227878128221168
第4步,中心点平均移动距离:0.012985270767233279
第5步,中心点平均移动距离:0.010560323354748833
第6步,中心点平均移动距离:0.011526155533891311
第7步,中心点平均移动距离:0.014447526451567915
第8步,中心点平均移动距离:0.01480361614434264
第9步,中心点平均移动距离:0.007805741764265261
第10步,中心点平均移动距离:0.004696899248898042
第11步,中心点平均移动距离:0.003858954772666219
第12步,中心点平均移动距离:0.0037634051652670757
第13步,中心点平均移动距离:0.0036342433215190346
第14步,中心点平均移动距离:0.004037746948698562
第15步,中心点平均移动距离:0.0037074902463420808
第16步,中心点平均移动距离:0.0025126860295755764
第17步,中心点平均移动距离:0.0017742952721109479
第18步,中心点平均移动距离:0.001311558516669006
第19步,中心点平均移动距离:0.0008183675564787064
第20步,中心点平均移动距离:0.0011545852276947674
第21步,中心点平均移动距离:0.0006864544106957334
第22步,中心点平均移动距离:0.0009260959472041178
第23步,中心点平均移动距离:0.0004974572613901904
第24步,中心点平均移动距离:0.00047763554726450624
第25步,中心点平均移动距离:0.000561811847711657
第26步,中心点平均移动距离:0.00030713124482862106
第27步,中心点平均移动距离:0.0
中心点不再移动,退出程序
8626
计算机类: { 0: 1233(0.32), 1: 2572(0.67), 2: 37(0.01), }
艺术传媒类: { 0: 74(0.03), 1: 282(0.12), 2: 1943(0.85), }
经管类: { 0: 26(0.01), 1: 2452(0.99), 2: 7(0.00), }
开始迭代
第0步, log-likelihood = 77.2117
第1步, log-likelihood = 87.3795
第2步, log-likelihood = 90.4587
第3步, log-likelihood = 91.7301
第4步, log-likelihood = 92.7042
第5步, log-likelihood = 93.5868
第6步, log-likelihood = 94.6852
第7步, log-likelihood = 95.8890
第8步, log-likelihood = 96.4726
第9步, log-likelihood = 96.8001
第10步, log-likelihood = 96.9560
第11步, log-likelihood = 97.0857
第12步, log-likelihood = 97.5848
第13步, log-likelihood = 97.5959
第14步, log-likelihood = 97.6033
第15步, log-likelihood = 97.6140
第16步, log-likelihood = 97.6341
第17步, log-likelihood = 97.6695
第18步, log-likelihood = 97.6801
第19步, log-likelihood = 97.6888
第20步, log-likelihood = 97.7062
第21步, log-likelihood = 97.7420
第22步, log-likelihood = 97.7711
第23步, log-likelihood = 97.8122
第24步, log-likelihood = 97.8207
第25步, log-likelihood = 97.8232
第26步, log-likelihood = 97.8244
第27步, log-likelihood = 97.8255
第28步, log-likelihood = 97.8284
第29步, log-likelihood = 97.8330
第30步, log-likelihood = 97.8486
第31步, log-likelihood = 97.9543
第32步, log-likelihood = 98.0578
第33步, log-likelihood = 98.0620
第34步, log-likelihood = 98.0625
第35步, log-likelihood = 98.0626
第36步, log-likelihood = 98.0628
第37步, log-likelihood = 98.0628
log-likelihood不再变化,退出程序
[0 2 0 ... 2 0 2]
计算机类: { 0: 2742(0.71), 1: 299(0.08), 2: 801(0.21), }
艺术传媒类: { 0: 9(0.00), 1: 421(0.18), 2: 1869(0.81), }
经管类: { 0: 829(0.33), 1: 1625(0.65), 2: 31(0.01), }进程已结束,退出代码为 0
无监督朴素贝叶斯模型
无监督朴素贝叶斯模型也是文本聚类的有力工具。它基于贝叶斯定理和特征条件独立假设,认为文本中的各个词之间是相互独立的,就好像每个人都是独立行动的个体。在文本聚类时,它通过统计文本中词的出现频率,结合贝叶斯定理,计算文本属于不同主题(类别)的概率,然后把概率相近的文本归为一类。
这种算法的优点是简单高效,对数据量的要求相对较低,可扩展性也不错。然而,它的特征条件独立假设在实际情况中往往不太符合,因为文本中的词之间其实是有语义关联的;而且它对多义词的处理能力有限,可能会把不同含义的同一个词都当作相同的来处理,影响聚类的准确性;此外,模型的性能很大程度上依赖于文本的表示方式,如果文本表示不准确,聚类效果也会受到影响。
接下来,为大家展示基于朴素贝叶斯模型的聚类算法具体是如何实现的:
朴素贝叶斯模型聚类完整代码
nlp_unsupervised_naive_bayes_classifier.py
# 导入NumPy库,用于数值计算
import numpy as np
# 从scipy库中导入对数求和指数函数
from scipy.special import logsumexp# 定义无监督朴素贝叶斯分类器类
class UnsupervisedNaiveBayesClassifier:# 初始化方法,设置聚类数量、数据维度和最大迭代次数def __init__(self, num_clusters, data_dimension, max_iterations=100):# 存储聚类数量self.num_clusters = num_clusters# 存储数据维度self.data_dimension = data_dimension# 存储最大迭代次数self.max_iterations = max_iterations# 初始化先验概率,每个聚类初始概率相同self.prior_probabilities = np.ones(num_clusters) / num_clusters# 随机初始化条件概率self.conditional_probabilities = np.random.random((num_clusters, data_dimension))# 对条件概率进行归一化处理self.conditional_probabilities /= self.conditional_probabilities.sum(axis=1, keepdims=True)# 期望步骤,计算每个数据点属于每个聚类的概率def expectation_step(self, input_data):# 遍历每个数据点for i, data_point in enumerate(input_data):# 计算对数概率self.responsibilities[i, :] = np.log(self.prior_probabilities) + (np.log(self.conditional_probabilities) * data_point).sum(axis=1)# 减去对数求和指数,避免数值溢出self.responsibilities[i, :] -= logsumexp(self.responsibilities[i, :])# 计算概率self.responsibilities[i, :] = np.exp(self.responsibilities[i, :])# 最大化步骤,更新模型参数def maximization_step(self, input_data):# 计算每个聚类的责任权重总和self.prior_probabilities = self.responsibilities.sum(axis=0) / self.num_samples# 对先验概率进行归一化处理self.prior_probabilities /= self.prior_probabilities.sum()# 遍历每个聚类for i in range(self.num_clusters):# 更新条件概率self.conditional_probabilities[i] = (self.responsibilities[:, i:i + 1] * input_data).sum(axis=0) / \(self.responsibilities[:, i] * input_data.sum(axis=1)).sum()# 避免条件概率为0self.conditional_probabilities += 1e-10# 对条件概率进行归一化处理self.conditional_probabilities /= self.conditional_probabilities.sum(axis=1, keepdims=True)# 计算对数似然值def log_likelihood_value(self, input_data):# 初始化对数似然值为0log_likelihood = 0# 遍历每个数据点for data_point in input_data:# 存储每个聚类的对数概率log_probabilities = []# 遍历每个聚类for i in range(self.num_clusters):# 计算对数概率log_probabilities.append(np.log(self.prior_probabilities[i]) + (np.log(self.conditional_probabilities[i]) * data_point).sum())# 累加对数求和指数log_likelihood += logsumexp(log_probabilities)# 返回平均对数似然值return log_likelihood / len(input_data)# 拟合模型def fit_model(self, input_data):# 存储输入数据的样本数量self.num_samples = len(input_data)# 初始化责任矩阵为全零矩阵self.responsibilities = np.zeros((self.num_samples, self.num_clusters))# 计算初始对数似然值log_likelihood = self.log_likelihood_value(input_data)# 打印初始对数似然值print(f'初始化log-likelihood = {log_likelihood:.4f}')# 打印开始迭代信息print('开始迭代')# 开始迭代for i in range(self.max_iterations):# 执行期望步骤self.expectation_step(input_data)# 执行最大化步骤self.maximization_step(input_data)# 计算新的对数似然值new_log_likelihood = self.log_likelihood_value(input_data)# 打印当前迭代步数和对数似然值print(f'第{i}步, log-likelihood = {new_log_likelihood:.4f}')# 如果对数似然值变化小于阈值,停止迭代if new_log_likelihood - log_likelihood < 1e-4:print('log-likelihood不再变化,退出程序')breakelse:# 更新对数似然值log_likelihood = new_log_likelihood# 转换数据,返回每个数据点所属的聚类def transform_data(self, input_data):# 确保责任矩阵已计算且长度与输入数据一致assert hasattr(self, 'responsibilities') and len(self.responsibilities) == len(input_data)# 返回每个数据点所属的聚类索引return np.argmax(self.responsibilities, axis=1)# 拟合并转换数据def fit_and_transform(self, input_data):# 拟合模型self.fit_model(input_data)# 转换数据return self.transform_data(input_data)
nlp_text_clustering.py
# 从nlp_book_data_collection模块导入BookDataCollection类
from nlp_book_data_collection import BookDataCollection
from nlp_gaussian_mixture_model import GaussianMixtureModel
# 从nlp_tfidf_transformer模块导入TFIDFTransformer类
from nlp_tfidf_transformer import TFIDFTransformer
# 从nlp_kmeans_clusterer模块导入KMeansClusterer类
from nlp_kmeans_clusterer import KMeansClusterer
# 从sklearn库中导入主成分分析(PCA)类
from sklearn.decomposition import PCA
# 从nlp_unsupervised_naive_bayes_classifier模块导入UnsupervisedNaiveBayesClassifier类
from nlp_unsupervised_naive_bayes_classifier import UnsupervisedNaiveBayesClassifier
# 导入NumPy库,用于数值计算
import numpy as np# 聚类的数量
num_clusters = 3# 定义一个用于自然语言处理文本聚类的类
class NLPTextClustering:def __init__(self):passdef display_clusters(self, cluster_assignments, num_clusters, book_dataset, labels_list):# 初始化标签聚类字典label_clusters = {label_id: {} for label_id in book_dataset.id_to_label}# 初始化每个标签下每个聚类的计数为0for k, v in label_clusters.items():label_clusters[k] = {i: 0 for i in range(num_clusters)}# 遍历标签和聚类分配for label_id, cluster_id in zip(labels_list, cluster_assignments):# 增加对应标签和聚类的计数label_clusters[label_id][cluster_id] += 1# 按标签ID排序遍历for label_id in sorted(book_dataset.id_to_label.keys()):# 初始化聚类信息字符串cluster_str = book_dataset.id_to_label[label_id] + ':\t{ '# 遍历每个聚类for cluster_id in range(num_clusters):# 获取当前聚类的计数count = label_clusters[label_id][cluster_id]# 计算总数total = sum(label_clusters[label_id].values())# 拼接聚类信息cluster_str += f'{str(cluster_id)}: {count}({count / total:.2f}), '# 结束聚类信息字符串cluster_str += '}'# 打印聚类信息print(cluster_str)def text_clustering(self):# 创建书籍数据集对象book_dataset = BookDataCollection()# 打印标签到ID的映射print(book_dataset.id_to_label)# 对文本进行分词处理book_dataset.tokenize_text(attribute='abstract')# 创建词汇表book_dataset.create_vocabulary(min_frequency=3)# 将词元转换为索引book_dataset.convert_tokens_to_indices()# 获取训练集和测试集数据training_data, testing_data = book_dataset.training_data, book_dataset.testing_data# 获取词汇表大小vocabulary_size = len(book_dataset.token_to_id)# 初始化训练输入列表training_input = []# 遍历训练数据for data_item in training_data:# 将词元索引添加到训练输入列表training_input.append(data_item['token_indices'])# 创建TF-IDF转换器对象tfidf_transformer = TFIDFTransformer(vocabulary_size, normalization='l2', smooth_idf_flag=True,sublinear_tf_flag=True)# 拟合训练数据tfidf_transformer.fit_data(training_input)# 转换训练数据training_features = tfidf_transformer.transform_data(training_input)# 打印训练特征的形状print(training_features.shape)# 创建K-Means聚类器对象kmeans_clusterer = KMeansClusterer(num_clusters, training_features.shape[1])# 拟合训练特征kmeans_clusterer.fit_model(training_features)# 初始化标签列表labels_list = []# 遍历训练数据for data_item in training_data:# 将标签添加到标签列表labels_list.append(data_item['label'])# 打印标签列表的长度print(len(labels_list))# 获取K-Means聚类结果cluster_assignments = kmeans_clusterer.cluster_assignments# 显示K-Means聚类结果self.display_clusters(cluster_assignments, num_clusters, book_dataset, labels_list)# 创建PCA降维器对象pca_reducer = PCA(n_components=50)# 对训练特征进行降维training_pca = pca_reducer.fit_transform(training_features)# 创建高斯混合模型对象gmm_model = GaussianMixtureModel(num_clusters, data_dimension=training_pca.shape[1])# 拟合并转换训练数据cluster_assignments = gmm_model.fit_and_transform(training_pca)# 打印高斯混合模型聚类结果print(cluster_assignments)# 显示高斯混合模型聚类结果self.display_clusters(cluster_assignments, num_clusters, book_dataset, labels_list)# 初始化训练计数矩阵training_count_matrix = np.zeros((len(training_input), vocabulary_size))# 遍历训练输入for i, data_item in enumerate(training_input):# 遍历词元索引for token_index in data_item:# 增加对应位置的计数training_count_matrix[i, token_index] += 1# 创建无监督朴素贝叶斯分类器对象naive_bayes_classifier = UnsupervisedNaiveBayesClassifier(num_clusters, data_dimension=vocabulary_size,max_iterations=100)# 拟合并转换训练数据cluster_assignments = naive_bayes_classifier.fit_and_transform(training_count_matrix)# 打印无监督朴素贝叶斯分类器聚类结果print(cluster_assignments)# 显示无监督朴素贝叶斯分类器聚类结果self.display_clusters(cluster_assignments, num_clusters, book_dataset, labels_list)# 程序入口,当作为脚本直接运行时执行以下代码
if __name__ == "__main__":# 创建NLPTextClustering类的一个实例nlp_text_clustering = NLPTextClustering()# 调用实例的text_clustering方法进行文本聚类操作nlp_text_clustering.text_clustering()
朴素贝叶斯模型聚类运行结果
训练集大小 = 8626 , 测试集大小 = 2156
{0: '计算机类', 1: '艺术传媒类', 2: '经管类'}
100%|██████████| 8626/8626 [02:36<00:00, 54.95it/s]
100%|██████████| 2156/2156 [00:36<00:00, 59.32it/s]
唯一词元数量 = 34251, 总词元数量 = 806791, 最大词频 = 19194, 最小词频 = 1
最小词频 = 3, 最小词长 = 2, 最大词表大小 = None, 剩余词元数量 = 9504, 词表内词元占比 = 0.8910448926673699
(8626, 9504)
-----------初始化-----------
-----------初始化完成-----------
第1步,中心点平均移动距离:0.07821463876668384
第2步,中心点平均移动距离:0.05703827383757104
第3步,中心点平均移动距离:0.0227878128221168
第4步,中心点平均移动距离:0.012985270767233279
第5步,中心点平均移动距离:0.010560323354748833
第6步,中心点平均移动距离:0.011526155533891311
第7步,中心点平均移动距离:0.014447526451567915
第8步,中心点平均移动距离:0.01480361614434264
第9步,中心点平均移动距离:0.007805741764265261
第10步,中心点平均移动距离:0.004696899248898042
第11步,中心点平均移动距离:0.003858954772666219
第12步,中心点平均移动距离:0.0037634051652670757
第13步,中心点平均移动距离:0.0036342433215190346
第14步,中心点平均移动距离:0.004037746948698562
第15步,中心点平均移动距离:0.0037074902463420808
第16步,中心点平均移动距离:0.0025126860295755764
第17步,中心点平均移动距离:0.0017742952721109479
第18步,中心点平均移动距离:0.001311558516669006
第19步,中心点平均移动距离:0.0008183675564787064
第20步,中心点平均移动距离:0.0011545852276947674
第21步,中心点平均移动距离:0.0006864544106957334
第22步,中心点平均移动距离:0.0009260959472041178
第23步,中心点平均移动距离:0.0004974572613901904
第24步,中心点平均移动距离:0.00047763554726450624
第25步,中心点平均移动距离:0.000561811847711657
第26步,中心点平均移动距离:0.00030713124482862106
第27步,中心点平均移动距离:0.0
中心点不再移动,退出程序
8626
计算机类: { 0: 1233(0.32), 1: 2572(0.67), 2: 37(0.01), }
艺术传媒类: { 0: 74(0.03), 1: 282(0.12), 2: 1943(0.85), }
经管类: { 0: 26(0.01), 1: 2452(0.99), 2: 7(0.00), }
开始迭代
第0步, log-likelihood = 77.2117
第1步, log-likelihood = 87.3795
第2步, log-likelihood = 90.4587
第3步, log-likelihood = 91.7301
第4步, log-likelihood = 92.7042
第5步, log-likelihood = 93.5868
第6步, log-likelihood = 94.6852
第7步, log-likelihood = 95.8890
第8步, log-likelihood = 96.4726
第9步, log-likelihood = 96.8001
第10步, log-likelihood = 96.9560
第11步, log-likelihood = 97.0857
第12步, log-likelihood = 97.5848
第13步, log-likelihood = 97.5959
第14步, log-likelihood = 97.6033
第15步, log-likelihood = 97.6140
第16步, log-likelihood = 97.6341
第17步, log-likelihood = 97.6695
第18步, log-likelihood = 97.6801
第19步, log-likelihood = 97.6888
第20步, log-likelihood = 97.7062
第21步, log-likelihood = 97.7420
第22步, log-likelihood = 97.7711
第23步, log-likelihood = 97.8122
第24步, log-likelihood = 97.8207
第25步, log-likelihood = 97.8232
第26步, log-likelihood = 97.8244
第27步, log-likelihood = 97.8255
第28步, log-likelihood = 97.8284
第29步, log-likelihood = 97.8330
第30步, log-likelihood = 97.8486
第31步, log-likelihood = 97.9543
第32步, log-likelihood = 98.0578
第33步, log-likelihood = 98.0620
第34步, log-likelihood = 98.0625
第35步, log-likelihood = 98.0626
第36步, log-likelihood = 98.0628
第37步, log-likelihood = 98.0628
log-likelihood不再变化,退出程序
[0 2 0 ... 2 0 2]
计算机类: { 0: 2742(0.71), 1: 299(0.08), 2: 801(0.21), }
艺术传媒类: { 0: 9(0.00), 1: 421(0.18), 2: 1869(0.81), }
经管类: { 0: 829(0.33), 1: 1625(0.65), 2: 31(0.01), }
初始化log-likelihood = -779.6002
开始迭代
第0步, log-likelihood = -589.5137
第1步, log-likelihood = -583.1897
第2步, log-likelihood = -579.2382
第3步, log-likelihood = -577.0352
第4步, log-likelihood = -575.8822
第5步, log-likelihood = -575.3356
第6步, log-likelihood = -574.8611
第7步, log-likelihood = -574.5028
第8步, log-likelihood = -574.2625
第9步, log-likelihood = -574.1030
第10步, log-likelihood = -573.9690
第11步, log-likelihood = -573.7704
第12步, log-likelihood = -573.6187
第13步, log-likelihood = -573.4686
第14步, log-likelihood = -573.3280
第15步, log-likelihood = -573.2186
第16步, log-likelihood = -573.1160
第17步, log-likelihood = -572.9857
第18步, log-likelihood = -572.8356
第19步, log-likelihood = -572.7076
第20步, log-likelihood = -572.4683
第21步, log-likelihood = -572.3301
第22步, log-likelihood = -572.2375
第23步, log-likelihood = -572.0611
第24步, log-likelihood = -571.8587
第25步, log-likelihood = -571.7117
第26步, log-likelihood = -571.6412
第27步, log-likelihood = -571.6158
第28步, log-likelihood = -571.5863
第29步, log-likelihood = -571.5397
第30步, log-likelihood = -571.5281
第31步, log-likelihood = -571.5163
第32步, log-likelihood = -571.4902
第33步, log-likelihood = -571.4693
第34步, log-likelihood = -571.4604
第35步, log-likelihood = -571.4457
第36步, log-likelihood = -571.4339
第37步, log-likelihood = -571.4301
第38步, log-likelihood = -571.4288
第39步, log-likelihood = -571.4272
第40步, log-likelihood = -571.4257
第41步, log-likelihood = -571.4254
第42步, log-likelihood = -571.4176
第43步, log-likelihood = -571.4060
第44步, log-likelihood = -571.4028
第45步, log-likelihood = -571.4027
log-likelihood不再变化,退出程序
[0 1 0 ... 1 0 1]
计算机类: { 0: 2266(0.59), 1: 1479(0.38), 2: 97(0.03), }
艺术传媒类: { 0: 64(0.03), 1: 703(0.31), 2: 1532(0.67), }
经管类: { 0: 2237(0.90), 1: 117(0.05), 2: 131(0.05), }进程已结束,退出代码为 0
结束
好了,以上就是本次分享的全部内容了。不知道大家是否对自然语言处理中的文本聚类有了更深入的了解呢?
本次分享主要围绕文本聚类展开,介绍了几种常见的文本聚类方法,包括 k 均值聚类算法、基于高斯混合模型的最大期望值算法和无监督朴素贝叶斯模型。
- k均值聚类算法:简单且经典,计算效率高,但需要预先指定聚类数量 k,对初始聚类中心的选择比较敏感。
- 基于高斯混合模型的最大期望值算法:能够灵活地拟合复杂的数据分布,对于多模态的数据聚类效果较好,但计算复杂度高,对超参数的选择敏感,容易陷入局部最优解。
- 无监督朴素贝叶斯模型:简单高效,对数据量的要求相对较低,可扩展性不错,但特征条件独立假设在实际情况中往往不太符合,对多义词的处理能力有限,模型性能依赖于文本的表示方式。
文本聚类在自然语言处理领域有着广泛的应用前景,如信息检索、文本分类、情感分析等。随着技术的不断发展,未来可能会出现更高效、更准确的文本聚类算法。同时,结合深度学习等技术,也有望进一步提升文本聚类的效果。
那么本次分享就到这里了。最后,博主还是那句话:请大家多去大胆的尝试和使用,成功总是在不断的失败中试验出来的,敢于尝试就已经成功了一半。如果大家对博主分享的内容感兴趣或有帮助,请点赞和关注。大家的点赞和关注是博主持续分享的动力🤭,博主也希望让更多的人学习到新的知识。
相关文章:
自然语言处理:文本聚类
介绍 大家好,博主又来和大家分享自然语言处理领域的知识了。今天给大家分享的内容是自然语言处理中的文本聚类。 文本聚类在自然语言处理领域占据着重要地位,它能将大量无序的文本按照内容的相似性自动划分成不同的类别,极大地提高了文本处…...
【MySQL】基本操作 —— DDL
目录 DDLDDL 常用操作对数据库的常用操作查看所有数据库创建数据库切换、显示当前数据库删除数据库修改数据库编码 对表的常用操作创建表数据类型数值类型日期和时间类型字符串类型 查看当前数据库所有表查看指定表的创建语句查看指定表结构删除表 对表结构的常用操作给表添加字…...
玩转python:通俗易懂掌握高级数据结构:collections模块之namedtuple
引言 namedtuple是Python中collections模块提供的一个强大工具,用于创建具有字段名的元组。它不仅具备元组的不可变性,还能通过字段名访问元素,极大地提高了代码的可读性和可维护性。本文将详细介绍namedtuple的关键用法和特性,并…...
[GHCTF 2025]SQL??? 【sqlite注入】
梳理一下SQLite注入 常见指令 查看版本:sqlite_version() 列出附加数据库中的所有表:.tables 注入步骤 先查字段: 1 order by 5 # 三板斧: 0 union select 1,2,sql from sqlite_master; sql字段存储创建该数据库对象时所使…...
spring boot 发送邮件验证码
一、前置需求 1、准备邮箱 2、登录授权码 qq邮箱在–>设置–>账号POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 开启服务 二、发送邮件 1、简单邮件 包含邮件标题、邮件正文 2、引入mail启动器 <dependency><groupId>org.springframework.boot</groupI…...
[项目]基于FreeRTOS的STM32四轴飞行器: 二.项目搭建及移植FreeRTOS
基于FreeRTOS的STM32四轴飞行器: 二.项目搭建及debug模块 一.项目搭建二.移植FreeRTOS 一.项目搭建 先配置SYS系统滴答定时器来源为默认,因为其他定时器用来驱动电机了只能与FreeRTOS共用: 之后选择RCC配置芯片的时钟来源: 配置时钟树&am…...
Amazon RDS ProxySQL 探索(一)
:::info 💡 在日常开发中,开发者们会涉及到数据库的连接,在使用Amazon RDS数据库时,若使用集群模式或者多数据库时,会出现一写多读多个Endpoint,在实际开发中, 开发者们配置数据库连接通常希望走…...
高速PCB设计(布线设计)
以下是针对高速PCB布线设计的综合笔记,结合用户提供的设计规范及行业通用原则整理而成: 一、关键信号布线原则 布线优先级 顺序:射频信号>中/低频信号>时钟信号>高速信号射频信号需包地处理,线…...
《探秘人工智能与鸿蒙系统集成开发的硬件基石》
在科技飞速发展的当下,人工智能与鸿蒙系统的集成开发开辟了创新的前沿领域。这一融合不仅代表着技术的演进,更预示着智能设备生态的全新变革。而在这场技术盛宴的背后,坚实的硬件配置是确保开发顺利进行的关键,它就像一座大厦的基…...
使用Langflow和AstraDB构建AI助手:从架构设计到与NocoBase的集成
本文由 Leandro Martins 编写,最初发布于 Building an AI Assistant with Langflow and AstraDB: From Architecture to Integration with NocoBase。 引言 本文的目标是演示如何创建一个集成了 NocoBase、LangFlow 和 VectorDB 工具的 AI 助手。作为基础…...
【零基础入门unity游戏开发——unity3D篇】3D物理系统之 —— 3D刚体组件Rigidbody
考虑到每个人基础可能不一样,且并不是所有人都有同时做2D、3D开发的需求,所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】:主要讲解C#的基础语法,包括变量、数据类型、运算符、流程控制、面向对象等,适合没有编程基础的…...
工程化与框架系列(30)--前端日志系统实现
前端日志系统实现 📝 引言 前端日志系统是应用监控和问题诊断的重要工具。本文将深入探讨前端日志系统的设计与实现,包括日志收集、处理、存储和分析等方面,帮助开发者构建完整的前端日志解决方案。 日志系统概述 前端日志系统主要包括以…...
小爱音箱控制家里的NAS将影片在电视上播放-deepseek帮助下实现-慎入openmanux
天始规划 我给ai一个任务,不过我没那么多能力,听说AI代理很行,这个任务我打算交给它.就用现在火的,openmanu,功能简单,我来安装openmanus,并规划任务. 进入openmanu首页 https://github.com/wjcroom/OpenManus openusa推荐使用uv管理,打算安装在家里的nas虚拟机.uv和python环…...
jQuery EasyUI 扩展
jQuery EasyUI 扩展 引言 jQuery EasyUI 是一个基于 jQuery 的易于使用的界面扩展库,它简化了网页界面的开发过程。随着 Web 技术的不断发展,越来越多的开发者开始寻求对 jQuery EasyUI 的扩展,以满足不同场景下的需求。本文将详细介绍 jQuery EasyUI 的扩展方法、技巧以及…...
笔试刷题专题(一)
文章目录 最小花费爬楼梯(动态规划)题解代码 数组中两个字符串的最小距离(贪心(dp))题解代码 点击消除题解代码 最小花费爬楼梯(动态规划) 题目链接 题解 1. 状态表示࿱…...
使用Docker部署前端应用到生产环境
前期准备 安装 Docker:确保你的开发机器和生产服务器都已经安装了 Docker。可以参考 Docker 官方安装指南 完成安装。准备前端项目:保证你的前端项目代码完整,并且能够在本地正常构建。 编写 Dockerfile Dockerfile 是用于构建 Docker 镜像…...
ES6(1) 简介与基础概念
1. ES6 简介 ES6(ECMAScript 6)是 JavaScript 的一个重要版本,它在 ES5 的基础上进行了扩展和优化。ES6 主要应用于现代 Web 开发,提高了 JavaScript 的编程效率和可读性。 2. ES6 与 JavaScript 的关系 JavaScript 是一种基于 E…...
redis数据库的介绍以及安装部署
一.redis数据库的介绍 借助nginx的upstream模块实现后端服务的负载均衡,如果后端服务采用的是会话的机制来识别客户端的身份,如果使用的调度算法是轮询算法的话,其中我们需要去做的就是实现后端服务的会话保持。 第一种换调度算法ÿ…...
MySQL数据库复杂的增删改查操作
在前面的文章中,我们主要学习了数据库的基础知识以及基本的增删改查的操作。接下去将以一个比较实际的公司数据库为例子,进行讲解一些较为复杂且现时需求的例子。 基础知识: 一文清晰梳理Mysql 数据库基础知识_字段变动如何梳理清楚-CSDN博…...
tomcat部署springboot+vue(不使用nginx)
1、首先将springboot项目打包为war包。 注意:将application.yml文件中添加以下信息: spring.jmx.enabledfalse 避免tomcat下部署多个项目,出现org.springframework.jmx.export.UnableToRegisterMBeanException:影响项目启动。 2、前段项目打…...
Flutter 从入门到进阶:构建跨平台应用的最佳实践
引言 Flutter 是 Google 推出的一款开源 UI 框架,能够帮助开发者使用 Dart 语言构建高性能、跨平台的移动、桌面和 Web 应用。它以 “一次编写,到处运行” 的特点吸引了众多开发者。Flutter 采用自绘 UI 渲染引擎(Skia)ÿ…...
ROS实践(三)机器人描述文件xacro(urdf扩展)
目录 一、定义 二、xacro 文件常见组成部分 1. 命名空间声明 2. 定义宏 3. 调用宏 4. 定义参数 5. 条件语句 6. 转换 xacro 文件为 urdf 7. gazebo标签 三、代码示例 1. gazebo标签使用(仿真参数配置) 2. 引用仿真配置并定义机器人模型&#x…...
微信小程序从右向左无限滚动组件封装(类似公告)
组件代码 wxml代码 <view class"container"><view class"text-wrapper"><!-- 这两个都不能删除,用来放无限滚动的,第一个滚完第二个接上,第二个滚完第一个又接上了 --><text class"scroll-text text1" style"left: …...
前端面试:axios 请求的底层依赖是什么?
在前端开发中,Axios 是一个流行的 JavaScript 库,用于发送 HTTP 请求。它简化了与 RESTful APIs 的交互,并提供了许多便利的方法与配置选项。要理解 Axios 的底层依赖,需要从以下几个方面进行分析: 1. Axios 基于 XML…...
【小白向】Ubuntu|VMware 新建虚拟机后打开 SSH 服务、在主机上安装vscode并连接、配置 git 的 ssh
常常有人问VMware-Tools装了也复制粘贴不了怎么办,这个东西影响因素太多了,具体解决办法你们可以参考一下:【经验】VMware|虚拟机只能使用鼠标无法使用键盘、装不了或装了VMware-Tools无法复制粘贴的可能解决办法_增强型键盘驱动程…...
UVC摄像头命令推流,推到rv1126里面去
ffmpeg命令查询UVC设备 .\ffmpeg.exe -list_devices true -f dshow -i dummy 上图是查询UVC设备的效果图,画红框的部分是UVC设备的设备名称"USB2.0 PC CAMERA"和设备号 "device_pnp_\\?\usb#vid_1908&pid_2310&mi_00#8&39abfe5&0&a…...
Node.js 与 MongoDB:高效的企业级应用开发
Node.js 与 MongoDB:高效的企业级应用开发 引言 随着互联网技术的飞速发展,企业级应用开发的需求日益增长。作为现代Web开发的重要工具,Node.js凭借其高性能、轻量级的特点,已经成为构建高效、可扩展后端服务的首选技术之一。而MongoDB作为一种流行的NoSQL数据库,以其灵…...
【大模型学习】第十九章 什么是迁移学习
目录 1. 迁移学习的起源背景 1.1 传统机器学习的问题 1.2 迁移学习的提出背景 2. 什么是迁移学习 2.1 迁移学习的定义 2.2 生活实例解释 3. 技术要点与原理 3.1 迁移学习方法分类 3.1.1 基于特征的迁移学习(Feature-based Transfer) 案例说明 代码示例 3.1.2 基于…...
sql-labs less-1-5wp
目录标题 less-1判断列数查找数据库和版本信息查找数据库中的表爆破users表的列爆破xx表xx列的数据 Less-2判断类型判断注释符和回显点爆破数据库和版本信息爆破security数据库的表爆破users表的列名爆破表中数据 Less-3判断类型判断注释符和回显点爆破爆破版本号和数据库爆数据…...
Unity开发的抖音小游戏接入抖音开放平台中的流量主(抖音小游戏接入广告)
前言:作者在进行小游戏审核版本的过程中,碰到了下列问题,所以对这个抖音小游戏接入广告研究了下。 还有就是作者的TTSDK版本号是6.2.6,使用的Unity版本是Unity2022.3.29f1,最好和作者的两个版本号保持一致,因为我发现TTSDK旧版的很多函数在新版中就已经无法正常使用了,必…...
在Simulink中将Excel数据导入可变负载模块的方法介绍
文章目录 数据准备与格式要求Excel数据格式MATLAB预处理数据导入方法使用From Spreadsheet模块(直接导入Excel)通过MATLAB工作区中转(From Workspace模块)使用1-D Lookup Table模块(非线性负载映射)Signal Builder模块(变载工况导入)可变负载模块配置注意事项与调试在S…...
Html5记忆翻牌游戏开发经验分享
H5记忆翻牌游戏开发经验分享 这里写目录标题 H5记忆翻牌游戏开发经验分享前言项目概述技术要点解析1. 页面布局(HTML CSS)响应式设计 2. 翻牌动画效果3. 游戏逻辑实现状态管理卡片配对检测 开发技巧总结1. 模块化设计2. 性能优化3. 用户体验 踩坑经验扩…...
Centos离线安装openssl-devel
文章目录 Centos离线安装openssl-devel1. openssl-devel是什么?2. openssl-devel下载地址3. openssl-devel安装4. 安装结果验证 Centos离线安装openssl-devel 1. openssl-devel是什么? openssl-devel 是 Linux 系统中与 OpenSSL 加密库相关的开发包&…...
Spring Boot项目中集成sa-token实现认证授权和OAuth 2.0第三方登录
OAuth 2.0第三方登录 OAuth 2.0 是一种授权协议,允许第三方应用在不暴露用户密码的情况下访问用户的资源。它通常用于第三方登录场景,例如使用GitHub、Google等社交平台进行登录。 在sa-token框架中,OAuth 2.0第三方登录可以通过集成sa-tok…...
【机器学习】迁移学习(Transfer Learning)
迁移学习(Transfer Learning)作为一种机器学习方法,主要通过将源域中学到的知识迁移到目标域,解决目标域中数据不足或标注困难的问题,尤其在无监督学习如聚类任务中具有显著优势。迁移学习的关键思想包括领域适应、知识…...
接入手机后,DeepSeek难“转正”
2025开年之后,手机圈掀起了一场诡异的AI军备竞赛——争相接入DeepSeek。随着时间的推移,这股年初的狂热已然降温。 当潮水退去之后,暴露出手机AI领域的残酷真相:市面上手机自带的AI能力,没能像DeepSeek一样,…...
全链条自研可控|江波龙汽车存储“双轮驱动”体系亮相MemoryS 2025
3月12日,MemoryS 2025在深圳盛大开幕,汇聚了存储行业的顶尖专家、企业领袖以及技术先锋,共同探讨存储技术的未来发展方向及其在商业领域的创新应用。江波龙董事长、总经理蔡华波先生受邀出席,并发表了题为《存储商业综合创新》的主…...
宇树ROS1开源模型在ROS2中Gazebo中仿真
以GO1为例 1. CMakelists.txt更新语法 cmake_minimum_required(VERSION 3.8) project(go1_description) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies find…...
ubuntu 24 安装 python3.x 教程
目录 注意事项 一、安装不同 Python 版本 1. 安装依赖 2. 下载 Python 源码 3. 解压并编译安装 二、管理多个 Python 版本 1. 查看已安装的 Python 版本 2. 配置环境变量 3. 使用 update-alternatives 管理 Python 版本 三、使用虚拟环境为项目指定特定 Python 版本…...
Python数据类型进阶——详解
—— 小 峰 编 程 目录 1.整型 1.1 定义 1.2 独有功能 1.3 公共功能 1.4 转换 1.5 其他 1.5.1 长整型 1.5.2 地板除(除法) 2. 布尔类型 2.1 定义 2.2 独有功能 2.3 公共功能 2.4 转换 2.5 其他 做条件自动转换 3.字符串类型 3.1 定义 3.2 独有功能…...
Flutter 按钮组件 TextButton 详解
目录 1. 引言 2. TextButton 的基本用法 3. 主要属性 4. 自定义按钮样式 4.1 修改文本颜色 4.2 添加背景色 4.3 修改按钮形状和边距 4.4 样式定制 5. 高级应用技巧 5.1 图标文本组合 5.2 主题统一配置 5.3 动态交互 6. 性能优化与注意事项 6.1 点击区域优化 6.…...
设置IDEA的内存
如何设置 IntelliJ IDEA 的内存以提升性能 一、引言 IntelliJ IDEA 是一款功能强大的集成开发环境(IDE),广泛应用于 Java、Kotlin、Scala 等多种编程语言的开发。它以其丰富的功能、智能的代码提示和高效的项目管理能力深受开发者喜爱。然而&…...
python编写的一个打砖块小游戏
游戏介绍 打砖块是一款经典的街机游戏,玩家控制底部的挡板,使球反弹以击碎上方的砖块。当球击中砖块时,砖块消失,球反弹;若球碰到挡板,则改变方向继续运动;若球掉出屏幕底部,玩家失…...
MySQL异常SQL排查
0、明确数据库异常SQL执行时间段,正常情况下耗时,当前耗时,如何感知到数据库慢的,是哪种类型的SQL,近期有做过相关的变更吗 1、检查数据库服务器的io iostat //查看延迟、读、写流量 sar -d /var/log/sa/sar日期 …...
AI智能代码疫苗技术,赋能数字化应用内生安全自免疫
“DevSecOps市占率持续领先,IAST探针覆盖率十倍增长,代码疫苗技术已成功帮助上千家行业用户成功抵御‘Log4j2.x’等重大未知漏洞的利用攻击。”子芽在腾讯专访中透露。 这是2021年悬镜安全交出的一张成绩单。悬镜安全是DevSecOps敏捷安全先行者…...
ASP.NET Webform和ASP.NET MVC 后台开发 大概80%常用技术
本文涉及ASP.NET Webform和ASP.NET MVC 后台开发大概80%技术 2019年以前对标 深圳22K左右 广州18K左右 武汉16K左右 那么有人问了2019年以后的呢? 答:吉祥三宝。。。 So 想继续看下文的 得有自己的独立判断能力。 C#.NET高级笔试题 架构 优化 性能提…...
计算机视觉领域开源数据集资源整理
1. 目标检测数据集 1.1 COCO2017 数据集 COCO2017 是 2017 年发布的 COCO 数据集的一个版本,主要用于 COCO 在 2017 年后持有的物体检测任务、关键点检测任务和全景分割任务。 1.2 火焰和烟雾图像数据集 数据集链接:http://m6z.cn/6fzn0f 该数据集由…...
idea更新git代码报错No Git Roots
idea更新git代码报错: No Git Roots None of configured Git roots are under Git. The configured directory must have ".git directory in it.但是本地项目里是存在.git文件的,就是突然间不能更新代码了 然后尝试重新拉新项目代码提示: Git i…...
flutter EventBus 的使用介绍
一、EventBus 初识 EventBus 是一个只有20多行的代码库, 通常用它来做事件分发。 EventBus 遵从 publish/subscribe 模式,即发布/订阅模式;简化了模块之间通信,对于项目的解耦很实用; 组件地址: https://github.com/marcojakob/dart-event-bus 源码: class EventBus…...
Spring Boot 整合 Keycloak
1、概览 本文将带你了解如何设置 Keycloak 服务器,以及如何使用 Spring Security OAuth2.0 将Spring Boot应用连接到 Keycloak 服务器。 2、Keycloak 是什么? Keycloak是针对现代应用和服务的开源身份和访问管理解决方案。 Keycloak 提供了诸如单点登…...