基于语义的NLP任务去重:大语言模型应用与实践
引言
在自然语言处理(NLP)任务中,数据质量是模型性能的关键因素之一。重复或冗余的数据会导致模型过度拟合或浪费计算资源,特别是在大语言模型(如 BERT、GPT 系列等)训练和推理阶段。传统的基于字符匹配的去重方法(如字符串哈希或编辑距离)在面对语义相似的文本时表现有限,而语义相似度算法则能更好地捕获文本之间的深层语义关系。
本文将介绍一种基于语义表示的去重方法,通过大语言模型生成的嵌入向量结合高效的相似度计算工具(如 FAISS),对大规模文本数据进行去重。此方法不仅适用于数据清洗,还可以应用在搜索引擎、推荐系统等需要衡量语义相似度的场景。
原理与方法
1. 传统去重方法的局限性
在 NLP 任务中,传统的去重方法包括:
- 字符串哈希:
基于文本的哈希值进行判重,适合完全重复的文本,但无法处理语义相似但表达不同的情况,例如:- 文本 A:我喜欢吃苹果。
- 文本 B:苹果是我最喜欢的水果。
虽然两者语义相近,但哈希值完全不同。
- 编辑距离(Levenshtein Distance):
衡量两个字符串的编辑代价,适合处理少量字符差异的文本,但无法捕捉深层语义关系。
上述方法对文本的语义相似性缺乏鲁棒性,特别是在短文本或同义表达常见的场景下。例如,问答生成、文档去重、语料清洗等任务中,语义相似的重复数据可能会严重影响模型性能。
2. 基于语义嵌入的去重
语义嵌入(Semantic Embedding)是一种将文本映射到高维向量空间的技术,向量的物理距离或角度可以反映文本语义的相似程度。常见的嵌入生成模型包括:
- BERT、RoBERTa、GPT 等大语言模型:能够生成上下文相关的语义表示。
- Sentence-BERT(SBERT):专为语义相似度任务设计,提升了嵌入的语义表达能力。
基本流程:
-
- 文本嵌入生成:
使用大语言模型将文本转化为固定维度的向量表示(如 768 维)。
- 文本嵌入生成:
-
- 相似度计算:
通过数学距离(如余弦相似度或内积)衡量文本向量之间的相似性。
- 相似度计算:
-
- 去重判断:
基于相似度阈值判断文本是否为重复内容。
- 去重判断:
3. 相似度计算方法对比
在语义嵌入的基础上,常用的相似度计算方法包括:
3.1. 余弦相似度(Cosine Similarity)
余弦相似度衡量两个向量的夹角余弦值,范围为 [ − 1 , 1 ] [-1, 1] [−1,1],归一化后范围为 [ 0 , 1 ] [0, 1] [0,1]。公式如下:
Cosine Similarity ( A , B ) = A ⋅ B ∥ A ∥ ∥ B ∥ \text{Cosine Similarity}(A, B) = \frac{A \cdot B}{\|A\| \|B\|} Cosine Similarity(A,B)=∥A∥∥B∥A⋅B
- 优点:消除向量模长的影响,只关注向量方向。
- 缺点:计算开销稍高。
3.2. 内积相似度(Inner Product Similarity)
内积相似度直接计算两向量的点积值:
Inner Product ( A , B ) = A ⋅ B \text{Inner Product}(A, B) = A \cdot B Inner Product(A,B)=A⋅B
- 优点:计算简单,速度快。
- 缺点:受向量模长影响,需要确保输入向量已归一化(模长为 1),否则结果不等价于余弦相似度。
欧几里得距离(Euclidean Distance)
衡量两个向量在高维空间中的直线距离:
Euclidean Distance ( A , B ) = ∑ i = 1 n ( A i − B i ) 2 \text{Euclidean Distance}(A, B) = \sqrt{\sum_{i=1}^n (A_i - B_i)^2} Euclidean Distance(A,B)=i=1∑n(Ai−Bi)2
- 优点:适合绝对位置相关的任务。
- 缺点:不适合捕获方向性的语义相似度。
4. 高效的大规模相似度计算
直接比较所有嵌入向量的相似度在大规模数据中效率低下(复杂度为 O ( n 2 ) O(n^2) O(n2))。为此,我们借助 FAISS(Facebook AI Similarity Search)工具,能够在百万级甚至亿级数据中高效实现近似最近邻搜索。
4.1. FAISS 简介
FAISS 是一个高效的相似度搜索库,专为高维向量的最近邻搜索设计,支持以下特性:
- 多种索引结构:
- Flat:暴力搜索,适合中小规模数据。
- IVF(倒排文件索引):适合大规模数据。
- PQ(分组量化):进一步压缩内存占用。
- GPU 加速:支持 GPU 版本,在大规模数据上极大提升搜索速度。
- 灵活的距离度量:支持内积、余弦、欧几里得距离等。
4.2. 使用 FAISS 的语义去重流程
- 初始化 FAISS 索引:选择适合任务的数据结构(如 IndexFlatIP)。
- 添加向量:将嵌入向量添加到索引。
- 查询相似度:对每个新向量,查找与索引中最近的向量,判断是否重复。
代码实现
import json
from transformers import BertTokenizer, BertModel
import torch
from tqdm import tqdm
import faiss
from typing import List, Dict, Unionclass TextDeduplicatorWithFAISS:"""使用 FAISS 索引实现的文本去重类(基于余弦相似度)。"""def __init__(self, model_name: str = 'bert-base-chinese', device: str = None) -> None:"""初始化文本去重类。参数:- model_name: 使用的预训练模型名称,默认为 'bert-base-chinese'。- device: 指定运行设备('cpu' 或 'cuda'),默认为自动检测。"""self.tokenizer = BertTokenizer.from_pretrained(model_name)self.model = BertModel.from_pretrained(model_name)self.device = device if device else ('cuda' if torch.cuda.is_available() else 'cpu')self.model = self.model.to(self.device)# 初始化 FAISS 索引self.embedding_dim = 768 # BERT 输出嵌入维度self.index = faiss.IndexFlatIP(self.embedding_dim) # 使用内积(IP)作为相似度度量self.index_ids = [] # 存储对应嵌入的 ID,方便后续处理def get_embeddings(self, texts: List[str]) -> torch.Tensor:"""计算文本的嵌入表示,并进行归一化。参数:- texts: 要计算嵌入的一组文本列表。返回:- 归一化后的文本嵌入张量,形状为 (batch_size, hidden_size)。"""inputs = self.tokenizer(texts, return_tensors="pt", padding=True, truncation=True, max_length=512)inputs = inputs.to(self.device) # 将输入张量移动到指定设备with torch.no_grad(): # 禁用梯度计算以节省内存outputs = self.model(**inputs)embeddings = outputs.last_hidden_state[:, 0, :].cpu() # 获取 [CLS] 的嵌入并移动到 CPU# 对嵌入进行归一化处理(实现余弦相似度)embeddings = embeddings / torch.norm(embeddings, dim=1, keepdim=True)return embeddingsdef is_duplicate(self, embedding: torch.Tensor, threshold: float = 0.9) -> bool:"""检查一个嵌入是否与 FAISS 索引中的嵌入重复。参数:- embedding: 待检查的嵌入向量,形状为 (1, hidden_size)。- threshold: 相似度的阈值,默认为 0.9。返回:- 是否为重复项(True / False)。"""if self.index.ntotal == 0: # 如果索引为空,肯定不是重复return False# 通过 FAISS 查找最近的向量及其相似度embedding_np = embedding.numpy() # 转为 NumPy 格式distances, _ = self.index.search(embedding_np, k=1) # 查找最近的 1 个向量# 检查最近向量的相似度是否高于阈值max_similarity = distances[0][0] # FAISS 返回的是归一化向量的内积(等价于余弦相似度)return max_similarity >= thresholddef add_to_index(self, embedding: torch.Tensor, doc_id: int) -> None:"""将新的嵌入添加到 FAISS 索引中。参数:- embedding: 要添加的嵌入向量,形状为 (1, hidden_size)。- doc_id: 该嵌入对应的文档 ID。"""embedding_np = embedding.numpy() # 转为 NumPy 格式self.index.add(embedding_np) # 添加到索引中self.index_ids.append(doc_id) # 保存对应的文档 IDdef process_and_save(self, input_path: str, output_path: str, threshold: float = 0.9) -> None:"""处理输入文件,去除相似文本并保存到输出文件。参数:- input_path: 输入 JSONL 文件路径。- output_path: 输出 JSONL 文件路径。- threshold: 去重的相似度阈值,默认值为 0.9。"""doc_id = 0 # 用于标记每条文档的唯一 IDwith open(input_path, 'r', encoding='utf-8') as infile, open(output_path, 'w', encoding='utf-8') as outfile:for line in tqdm(infile, desc="Processing lines"):item: Dict[str, Union[str, int, float]] = json.loads(line) # 从 JSONL 文件中读取一条数据output_text: str = item['output'] # 获取文本内容# 获取当前文本的嵌入current_embedding = self.get_embeddings([output_text])# 检查是否为重复if not self.is_duplicate(current_embedding, threshold):# 如果不重复,保存文本,并将嵌入添加到索引outfile.write(json.dumps(item, ensure_ascii=False) + '\n')self.add_to_index(current_embedding, doc_id)doc_id += 1# 使用示例
if __name__ == "__main__":# 初始化去重器deduplicator = TextDeduplicatorWithFAISS(model_name='bert-base-chinese')# 去重并保存结果deduplicator.process_and_save(input_path='=./processed_unique_data-5.jsonl',output_path='=./processed_unique_data-6.jsonl',threshold=0.95)
数据示例:
{"id": 1, "output": "什么是人工智能?人工智能是指让机器具备人类智能的技术。"}
{"id": 2, "output": "人工智能的定义是什么?人工智能是赋予机器类似人类智能的能力。"}
总结
本文介绍了一种基于语义嵌入的大规模文本去重方法,通过结合大语言模型(如 BERT)和高效相似度搜索工具(FAISS),实现了对语料库的语义级去重。该方法具有以下优点:
- 高精度:捕捉语义相似性,避免遗漏同义表达的重复数据。
- 高扩展性:支持大规模数据处理,适用于百万级文本的去重任务。
- 通用性强:不仅适用于去重,还可扩展至相似文本检索、推荐系统等任务。
相关文章:

基于语义的NLP任务去重:大语言模型应用与实践
引言 在自然语言处理(NLP)任务中,数据质量是模型性能的关键因素之一。重复或冗余的数据会导致模型过度拟合或浪费计算资源,特别是在大语言模型(如 BERT、GPT 系列等)训练和推理阶段。传统的基于字符匹配的…...

使用阿里云Certbot-DNS-Aliyun插件自动获取并更新免费SSL泛域名(通配符)证书
进入nginx docker,一般是Alpine Linux系统 1. 依次执行命令: sudo docker-compose exec nginx bashapk updateapk add certbot apk add --no-cache python3 python3-dev build-baseapk add python3 py3-pippip3 install --upgrade pippip3 install certbot-dns-ali…...

Node.js安装配置+Vue环境配置+创建一个VUE项目
目录 安装Node.js搭建VUE环境 安装Node.js 下载 测试是否安装成功 在目录下新建两个文件夹 管理员打开cmd npm config set prefix "D:\Software\nodejs\node_global" npm config set cache "D:\Software\nodejs\node_cache"将默认的 C 盘下【 AppData\…...

“TA”说|表数据备份还原:SQLark 百灵连接助力项目部署验收
💬 南飞雁|应用开发工程师 有些重要项目的部署验收,会在生产环境完成,验收完成后,又需要把这部分数据清空。这时就需要对数据表进行备份和还原,虽然可以通过命令直接实现,但是有一些操作门槛&am…...

【FFmpeg】解封装 ① ( 封装与解封装流程 | 解封装函数简介 | 查找码流标号和码流参数信息 | 使用 MediaInfo 分析视频文件 )
文章目录 一、解封装1、封装与解封装流程2、解封装 常用函数 二、解封装函数简介1、avformat_alloc_context 函数2、avformat_free_context 函数3、avformat_open_input 函数4、avformat_close_input 函数5、avformat_find_stream_info 函数6、av_read_frame 函数7、avformat_s…...

Spring Boot 集成 MyBatis 全面讲解
Spring Boot 集成 MyBatis 全面讲解 MyBatis 是一款优秀的持久层框架,与 Spring Boot 集成后可以大大简化开发流程。本文将全面讲解如何在 Spring Boot 中集成 MyBatis,包括环境配置、基础操作、高级功能和最佳实践。 一、MyBatis 简介 1. SqlSession …...

C语言小练习-打印字母倒三角
编写一个程序,在用户输入某个大写字母后,产生一个金字塔图案。 #include <stdio.h>int main(int argc,char *argv[]) {char ch; loop:printf("请输入大写字母!\n");scanf("%c",&ch);getchar();if(ch < A ||…...

Linux -- 线程控制相关的函数
目录 pthread_create -- 创建线程 参数 返回值 代码 -- 不传 args: 编译时带 -lpthread 运行结果 为什么输出混杂? 如何证明两个线程属于同一个进程? 如何证明是两个执行流? 什么是LWP? 代码 -- 传 args&a…...

基于quasar,只选择年度与月份的组件
为什么要做 quasar是个基于vue的强大的UI开发库,它提供了非常多的组件,比如日期选择。但是有些时候只需要选择到月份就可以了,quasar中没有,所以自己动手写了一个。因为对界面编程我不熟悉,所以,如果你有更…...

健康养生:拥抱生活的艺术
健康养生:拥抱生活的艺术 在快节奏的现代生活中,健康已成为我们最宝贵的财富。健康养生,不仅仅是一种生活方式的选择,更是一种对待生活的态度,它关乎于如何在日常中寻找到平衡,让身心得以滋养,…...

注意力机制+时空特征融合!组合模型集成学习预测!LSTM-Attention-Adaboost多变量时序预测
注意力机制时空特征融合!组合模型集成学习预测!LSTM-Attention-Adaboost多变量时序预测 目录 注意力机制时空特征融合!组合模型集成学习预测!LSTM-Attention-Adaboost多变量时序预测效果一览基本介绍程序设计参考资料 效果一览 基…...

uniapp 微信小程序 均分数据展示
效果图 数据展示,可自行搭配 html <view class"num-wrapper"><view class"num-item" click.stop"routerGo(跳转的地址)"><text class"num">¥{{ 要展示的数据 || 0}}</text><view…...

Nacos 3.0 考虑升级到 Spring Boot 3 + JDK 17 了!
Nacos 由阿里开源,是 Spring Cloud Alibaba 中的一个重要组件,主要用于发现、配置和管理微服务。 由于 Spring Boot 2 的维护已于近期停止,Nacos 团队考虑升级到 Spring Boot 3 JDK 17,目前正在征求意见和建议。 这其实是一件好…...

跟沐神学读论文-论文阅读管理
摘要 近期有读论文的需求,就需要去了解一下论文到底要怎么读,同一个系列之间的论文如何作整理和归纳,之前也有了解过市面上有成熟的论文阅读工具,但是对于学生党来讲没什么性价比,在B站上看到沐神有讲解他的思路Typor…...

Python 参数配置使用 XML 文件的教程 || Python打包 || 模型部署
当配置项存储在外部文件(如 XML、JSON)时,修改配置无需重新编译和发布代码。通过更新 XML 文件即可调整参数,无需更改源代码,从而提升开发效率和代码可维护性。 1. 为什么选择 XML 配置文件 XML 配置文件具有多种优点…...

[SV]如何在UVM环境中使用C Model
在UVM环境中使用C Memory 一、C语言实现Memory 1.1 代码说明 Memory 初始化: memory_init() 函数将内存空间初始化为 0,并初始化互斥锁。AXI 写操作 (axi_write): 检查地址范围是否合法。使用 memcpy 将数据从输入缓冲区写入模拟内存。使用互斥锁保证线程安全。AXI 读操作 …...

十大开源的Cursor AI替代方案
随着AI的兴起,所使用的工具也在不断进步。Cursor AI 作为一个强大的编码助手,已经成为开发人员不可或缺的工具。开源替代方案提供了透明性、个性化和成本效益。本文深入探讨了Cursor AI 的十大开源替代方案,这些方案将丰富您的编码体验&#…...

相机光学(四十六)——镜头马达(VCM)控制策略模式
One Step Mode、Linear Slope Control(LSC)和Acceleration Control是三种不同的控制模式,它们在控制策略和应用场景上有所区别。这些控制模式在VCM中的应用是为了提高其性能,减少振动,加快响应速度,并提高定…...

专业140+总分410+浙江大学842信号系统与数字电路考研经验浙大电子信息与通信工程,真题,大纲,参考书。
考研落幕,本人本中游211,如愿以偿考入浙江大学,专业课842信号系统与数字电路140,总分410,和考前多次模考预期差距不大(建议大家平时做好定期模考测试,直接从实战分数中,找到复习的脉…...

了解ARM的千兆以太网——RK3588
1. 简介 本文并不重点讲解调试内容,重点了解以太网在ARM设计中的框架以及在设备树以及驱动的一个整体框架。了解作为一个驱动开发人员当拿到一款未开发过的ARM板卡应该怎么去把网卡配置使用起来。 2. 基础知识介绍 在嵌入式ARM中实现以太网的解决方案通常有以下两种…...

JavaFX使用jfoenix的UI控件
jfoenix还是一个不错的样式,推荐使用,而且也可以支持scene builder中的拖拖拽拽 需要注意的是过高的javafx版本可能会使得某些样式或控件无法使用 比如alert控件,亲测javaFX 19版本可以正常使用 1.在pom.xml中引入依赖 GitHub地址https://gi…...

Linux(Ubuntu)命令大全——已分类整理,学习、查看更加方便直观!(2024年最新编制)
Hello! 认真好学的小伙伴们,大家好呀(Respect~)!我是 H u a z z i Huazzi Huazzi,欢迎观看本篇博客,接下来让我们一起来学习 Ubuntu命令大全 吧!祝你有所收获! 文章目录 前言&#x…...

单片机:实现教学上下课的自动打玲(附带源码)
单片机实现教学上下课的自动打铃 在学校或其他教育机构中,定时的打铃系统被广泛应用,用于提醒学生和老师上下课的时间。一个简单的自动打铃系统可以通过单片机实现,结合蜂鸣器和定时器控制,可以在设定的时间点自动打铃࿰…...

进程通信方式---共享映射区(无血缘关系用的)
5.共享映射区(无血缘关系用的) 文章目录 5.共享映射区(无血缘关系用的)1.概述2.mmap&&munmap函数3.mmap注意事项4.mmap实现进程通信父子进程练习 无血缘关系 5.mmap匿名映射区 1.概述 原理:共享映射区是将文件…...

深度学习实战智能交通计数
本文采用YOLOv8作为核心算法框架,结合PyQt5构建用户界面,使用Python3进行开发。YOLOv8以其高效的实时检测能力,在多个目标检测任务中展现出卓越性能。本研究针对车辆目标数据集进行训练和优化,该数据集包含丰富的车辆目标图像样本…...

【MySQL】MySQL表的操作
【MySQL】MySQL表的操作 🥕个人主页:开敲🍉 🔥所属专栏:MySQL🍋 🌼文章目录🌼 1. 创建表 2. 查看表结构 3. 修改表 4. 删除表 1. 创建表 create table table_name(表名称)( fiel…...

Redis篇-12--数据结构篇4--Hash内存模型(数组,链表,压缩列表zipList,哈希表,短结构)
Redis的Hash数据结构用于存储键值对(key-value形式)的集合(类似java中HashMap或对象)。为了在保证高效性能的同时节省内存,Redis对Hash的底层实现进行了多种优化。特别是通过使用压缩列表(ziplistÿ…...

二、windows环境下vscode使用wsl教程
本篇文件介绍了在windows系统使用vscode如何连接使用wsl,方便wsl在vscode进行开发。 1、插件安装 双击桌面vscode,按快捷键CtrlShiftX打开插件市场,搜索【WSL】点击安装即可。 2、开启WSL的linux子系统 点击左下方图标【Open a Remote Win…...

Qwen2-VL微调体验
1.配置环境 2.数据集准备 3.模型下载 4.注册SwanLab 5.微调 6.训练过程可视化 1.配置环境 本博客使用的是2B模型,所以仅用了单卡3090,若大一点的模型,自行根据实际情况准备显卡 安装Python>3.8 安装Qwen2-VL必要的库 pip install…...

论文的模拟环境和实验环境
模拟环境和实验环境 在撰写SCI计算机领域论文时,模拟环境和实验环境是两个重要的概念,它们之间存在显著的差异。 模拟环境主要是利用计算机、数学方法等手段对实际系统进行描述和分析的过程。在计算机科学中,模拟环境可以用于模拟各种算法、系统或网络的行为,以便在不需要…...