当前位置: 首页 > news >正文

自然语言处理NLP的数据预处理:从原始文本到模型输入(MindSpore版)

自然语言处理(NLP)任务中,数据预处理的质量直接影响模型性能。即使是最先进的大模型,在未经处理的原始文本上也难以发挥作用。本文将详细介绍 NLP 数据预处理的核心步骤,并基于 MindSpore 框架提供代码实现,帮助你构建完整的预处理流水线。

为什么数据预处理至关重要?

原始文本数据通常存在噪声(如错别字、特殊符号)、格式不一致(如大小写混合)、冗余信息(如重复段落)等问题。预处理的目标是:

  • 统一数据格式,降低模型学习难度
  • 去除噪声,减少干扰信息
  • 将文本转化为模型可理解的数值形式
  • 适应特定任务需求(如分类、翻译、摘要)

下面以情感分析任务为例(输入文本,输出正面 / 负面标签),演示完整预处理流程。

数据预处理核心步骤

1. 数据加载与探索

首先需要加载数据并初步探索,了解数据分布(如文本长度、标签分布),为后续处理提供依据。

示例数据格式(CSV)

text,label
"这部电影太精彩了!推荐大家去看",1
"剧情拖沓,浪费时间...",0
"演员演技在线,但结局有点仓促",1
...

MindSpore 加载代码

import mindspore.dataset as ds
import pandas as pd
import matplotlib.pyplot as plt# 加载CSV数据
df = pd.read_csv("reviews.csv")
print(f"数据集规模:{len(df)}条")
print(f"标签分布:{df['label'].value_counts().to_dict()}")# 可视化文本长度分布
df["text_len"] = df["text"].apply(lambda x: len(x))
plt.hist(df["text_len"], bins=50)
plt.title("文本长度分布")
plt.xlabel("长度")
plt.ylabel("数量")
plt.show()# 转换为MindSpore数据集
dataset = ds.NumpySlicesDataset(df[["text", "label"]].values, column_names=["text", "label"])

2. 文本清洗

去除无关字符、统一格式,减少噪声干扰。常见操作包括:

  • 去除特殊符号、标点
  • 大小写转换(通常转为小写)
  • 去除多余空格
  • 处理中英文混合场景(如保留中文,清理无意义符号)

清洗函数实现

import redef clean_text(text):# 去除URLtext = re.sub(r"http\S+", "", text)# 去除特殊符号和标点(保留中文、字母、数字)text = re.sub(r"[^\u4e00-\u9fa5a-zA-Z0-9\s]", "", text)# 转为小写(英文)text = text.lower()# 去除多余空格text = re.sub(r"\s+", " ", text).strip()return text# 应用清洗函数
dataset = dataset.map(operations=lambda x: (clean_text(x[0]), x[1]), input_columns=["text", "label"])

3. 分词(Tokenization)

将连续文本拆分为最小语义单位(词语或子词),是 NLP 的基础步骤。中文通常使用 jieba、THULAC 等工具,英文可直接按空格分词(或使用更复杂的子词分词)。

中文分词实现

import jiebadef tokenize(text):# 中文分词,过滤空字符串tokens = [token for token in jieba.cut(text) if token.strip()]return tokens# 应用分词
dataset = dataset.map(operations=lambda x: (tokenize(x[0]), x[1]), input_columns=["text", "label"])

示例效果

  • 原始文本:"这部电影太精彩了!推荐大家去看"
  • 清洗后:"这部电影太精彩了推荐大家去看"
  • 分词后:["这部", "电影", "太", "精彩", "了", "推荐", "大家", "去看"]

4. 去除停用词

停用词是指在文本中频繁出现但语义贡献小的词(如 “的”、“是”、“在”),去除它们可以减少冗余,提升效率。

停用词处理

# 加载停用词表(可自定义或使用公开表)
with open("stopwords.txt", "r", encoding="utf-8") as f:stopwords = set(f.read().splitlines())def remove_stopwords(tokens):return [token for token in tokens if token not in stopwords]# 应用去停用词
dataset = dataset.map(operations=lambda x: (remove_stopwords(x[0]), x[1]), input_columns=["text", "label"])

示例效果

  • 分词后:["这部", "电影", "太", "精彩", "了", "推荐", "大家", "去看"]
  • 去停用词后:["电影", "精彩", "推荐", "大家"]

5. 词表构建与数值映射

模型无法直接处理文本,需要将词语转换为数值。这一步需要:

  • 构建词表(记录词语与索引的映射)
  • 将分词后的文本转换为索引序列

词表构建实现

from collections import Counter# 收集所有词,统计频率
all_tokens = []
for data in dataset.create_dict_iterator():all_tokens.extend(data["text"])# 按频率排序,保留前5000个词(超参数)
word_counts = Counter(all_tokens).most_common(5000)
# 构建词表:预留0(PAD)、1(UNK)
vocab = {"<PAD>": 0, "<UNK>": 1}
for word, _ in word_counts:vocab[word] = len(vocab)print(f"词表大小:{len(vocab)}")# 保存词表
import json
with open("vocab.json", "w", encoding="utf-8") as f:json.dump(vocab, f, ensure_ascii=False)

数值映射

def tokens_to_ids(tokens):# 未在词表中的词用<UNK>代替return [vocab.get(token, 1) for token in tokens]# 应用映射
dataset = dataset.map(operations=lambda x: (tokens_to_ids(x[0]), x[1]), input_columns=["text", "label"])

示例效果

  • 去停用词后:["电影", "精彩", "推荐", "大家"]
  • 数值映射后:[56, 128, 34, 92](假设词表中对应索引)

6. 序列长度对齐(Padding/Truncation)

模型输入需要固定长度,因此需对序列进行截断(超长)或填充(不足)。

长度对齐实现

import mindspore.dataset.transforms as C
import mindspore.dataset.vision as vision# 设定最大长度(根据前面的长度分布统计结果)
max_seq_len = 32def pad_sequence(ids):# 截断超长序列if len(ids) > max_seq_len:return ids[:max_seq_len]# 填充短序列(用<PAD>的索引0)else:return ids + [0] * (max_seq_len - len(ids))# 应用长度对齐
dataset = dataset.map(operations=lambda x: (pad_sequence(x[0]), x[1]), input_columns=["text", "label"])

7. 数据划分与格式转换

最后将数据集划分为训练集、验证集,并转换为模型可接受的格式(如 Tensor)。

最终处理步骤

# 划分训练集(80%)和验证集(20%)
dataset = dataset.shuffle(buffer_size=len(df))  # 打乱数据
train_size = int(0.8 * len(df))
train_dataset, val_dataset = dataset.split([train_size, len(df) - train_size])# 转换为Tensor格式
train_dataset = train_dataset.map(operations=C.TypeCast(mstype.int32), input_columns=["text"])
train_dataset = train_dataset.map(operations=C.TypeCast(mstype.int32), input_columns=["label"])
val_dataset = val_dataset.map(operations=C.TypeCast(mstype.int32), input_columns=["text"])
val_dataset = val_dataset.map(operations=C.TypeCast(mstype.int32), input_columns=["label"])# 批量处理(设置batch_size)
train_dataset = train_dataset.batch(batch_size=32)
val_dataset = val_dataset.batch(batch_size=32)# 查看最终数据格式
for batch in train_dataset.create_dict_iterator():print("文本张量形状:", batch["text"].shape)  # (32, 32)print("标签张量形状:", batch["label"].shape)  # (32,)break

完整预处理流水线总结

将上述步骤整合,可构建一个可复用的预处理函数:

def preprocess_pipeline(file_path, max_seq_len=32, vocab_path=None):# 1. 加载数据df = pd.read_csv(file_path)dataset = ds.NumpySlicesDataset(df[["text", "label"]].values, column_names=["text", "label"])# 2. 文本清洗dataset = dataset.map(operations=lambda x: (clean_text(x[0]), x[1]), input_columns=["text", "label"])# 3. 分词dataset = dataset.map(operations=lambda x: (tokenize(x[0]), x[1]), input_columns=["text", "label"])# 4. 去停用词dataset = dataset.map(operations=lambda x: (remove_stopwords(x[0]), x[1]), input_columns=["text", "label"])# 5. 词表构建/加载与映射if vocab_path:with open(vocab_path, "r", encoding="utf-8") as f:vocab = json.load(f)else:all_tokens = []for data in dataset.create_dict_iterator():all_tokens.extend(data["text"])word_counts = Counter(all_tokens).most_common(5000)vocab = {"<PAD>": 0, "<UNK>": 1}for word, _ in word_counts:vocab[word] = len(vocab)with open("vocab.json", "w", encoding="utf-8") as f:json.dump(vocab, f, ensure_ascii=False)dataset = dataset.map(operations=lambda x: (tokens_to_ids(x[0]), x[1]), input_columns=["text", "label"])# 6. 长度对齐dataset = dataset.map(operations=lambda x: (pad_sequence(x[0], max_seq_len), x[1]), input_columns=["text", "label"])# 7. 划分与转换dataset = dataset.shuffle(buffer_size=len(df))train_size = int(0.8 * len(df))train_dataset, val_dataset = dataset.split([train_size, len(df) - train_size])train_dataset = train_dataset.map(operations=C.TypeCast(mstype.int32), input_columns=["text", "label"]).batch(32)val_dataset = val_dataset.map(operations=C.TypeCast(mstype.int32), input_columns=["text", "label"]).batch(32)return train_dataset, val_dataset, vocab

注意事项

  1. 预处理的任务相关性:不同任务(如机器翻译、命名实体识别)可能需要调整步骤(如翻译需保留句子结构,NER 需保留特殊符号)。
  2. 超参数调整:max_seq_len、词表大小等需根据数据分布调整,过长会增加计算量,过短会丢失信息。
  3. 效率优化:MindSpore 的 map 操作支持多线程加速(通过num_parallel_workers参数),大规模数据可开启。
  4. 可复现性:保存词表等中间结果,确保测试 / 部署时使用相同的预处理规则。

http://www.dtcms.com/a/511041.html

相关文章:

  • 清空显存占用
  • UNTER++模型简介
  • PHP Error 处理指南
  • Linux学习笔记(十)--进程替换与创建一个自己的简易版shell
  • go语言实现 基于 Session 和 Redis 实现短信验证码登录
  • 福建网站建设制作阿里巴巴旗下跨境电商平台有哪些
  • 潇洒郎:最佳完美——Windows防火墙与端口管理工具——支持ipv6、ipv4端口转发管理
  • Elastic MCP 服务器:向任何 AI agent 暴露 Agent Builder 工具
  • 小说网站建设详细流程游戏开发有前途吗
  • echarts tooltip数据太长导致显示不全
  • 用户选剧情,AI写故事:Trae Solo+GLM-4.6实现沉浸式小说创作体验
  • 【Linux】初始Linux和Linux下基本指令:ls pwd cd touch mkdir rmdir rm 指令
  • 《Linux系统编程之入门基础》【Linux基础 理论+命令】(下)
  • 农业网站建设招标书网站导航条内容
  • LLAMA Factory 微调Qwen2.0-VL-2B视觉大模型
  • 婚纱网站建设案例wordpress默认主题twenty
  • 网站访问者qq企业网站备案名称窍门
  • 个人网站源码下载有口皆碑的域名备案加急
  • 农用地转建设用地结果查询网站苏州品牌网站设计
  • 做外贸的网站怎么建立wordpress建网站主页
  • 建设部网站中天人建筑工程有限公司网站设计是怎么做的
  • 网站建设管理工作经验介绍建美食网站有哪些原因
  • 电子商务网站后台功能wordpress thesis 开发
  • 自已做的网站怎么做域名解析沐众科技网站建设
  • 一款app开发需要多少钱郑州seo网络营销技术
  • 做动漫的网站合肥seo公司
  • 免费商城网站制作网站建设制度
  • 网站开发个人博客深圳企业年报网上申报入口
  • 企业营销型网站的内容网站开发设计总结
  • 深圳加盟网站建设wordpress路由正则