实战案例:用提示词生成机器学习数据集预处理步骤

1. 前言

在机器学习项目中,数据集预处理是决定模型效果的关键步骤。很多新手会在预处理环节遇到问题:不知道该先处理缺失值还是异常值、不清楚如何选择合适的特征编码方式、面对不同类型的数据集(如表格数据、文本数据)不知从何下手。

而大模型(如 ChatGPT、文心一言、通义千问)能成为预处理环节的 “得力助手”—— 只要我们写出精准的提示词,就能让大模型生成完整、可落地的预处理步骤,甚至附带代码示例。本文通过多个实战案例,详细讲解如何编写提示词,让大模型生成符合需求的机器学习数据集预处理步骤,覆盖表格数据、文本数据、图像数据等常见类型,帮助大家提升预处理效率。

2. 先搞懂:为什么要用提示词生成预处理步骤?

在学习具体案例前,先明确用提示词生成预处理步骤的核心优势,这样能让我们更清楚在哪些场景下适合使用这种方法,避免盲目尝试。

2.1 解决 “新手无思路” 问题

对机器学习新手来说,预处理步骤多且杂,容易遗漏关键环节(如忘记处理类别不平衡、未做特征标准化)。用提示词让大模型生成步骤,相当于有了一份 “预处理 Checklist”,能快速建立思路,知道从哪里开始、要做哪些事。

2.2 节省 “重复编码” 时间

不同数据集的预处理步骤有很多共性(如缺失值填充、异常值检测),每次都手动写步骤、敲代码会浪费大量时间。大模型能根据提示词生成可复用的步骤和代码,我们只需根据数据集特点微调,大幅提升效率。

2.3 适配 “不同数据类型” 需求

表格数据、文本数据、图像数据的预处理方法差异很大:表格数据需要处理缺失值和编码,文本数据需要分词和词向量转换,图像数据需要归一化和数据增强。大模型能根据提示词中的 “数据类型”,生成对应的专属预处理步骤,避免混淆不同数据的处理逻辑。

2.4 应对 “复杂场景” 挑战

当数据集存在复杂问题(如多源数据融合、严重的类别不平衡、时间序列数据的时间戳处理)时,新手很难设计出合理的预处理流程。此时,精准的提示词能引导大模型分析场景难点,生成针对性的解决方案,比如 “针对类别不平衡的数据集,先计算类别分布,再用 SMOTE 算法进行过采样”。

3. 基础准备:提示词的核心要素

要让大模型生成高质量的预处理步骤,提示词需要包含 4 个核心要素。缺少任何一个要素,都可能导致大模型生成的内容偏离需求,无法直接使用。

3.1 要素 1:明确 “数据类型与来源”

首先要告诉大模型数据集的类型(表格、文本、图像、时间序列等)和来源(如 “Kaggle 的泰坦尼克号数据集”“自制的客户评论文本数据集”“公开的猫狗图像数据集”),这是大模型选择预处理方法的基础。

示例表述:“数据集为表格数据,来自 Kaggle 的泰坦尼克号生存预测数据集,包含 12 个特征,如乘客年龄(Age)、性别(Sex)、船票等级(Pclass)、是否生存(Survived,标签列)”。

3.2 要素 2:说明 “数据已知问题”

如果已知数据集存在问题(如 “Age 列有 30% 的缺失值”“Fare 列存在异常值”“文本数据包含大量特殊符号”),要在提示词中明确说明。这样大模型会优先针对这些问题生成处理步骤,避免遗漏关键修复环节。

示例表述:“已知该数据集存在以下问题:1. Age(年龄)列缺失率 30%;2. Fare(船票价格)列存在异常值(最大值远高于均值);3. Sex(性别)和 Embarked(登船港口)为类别特征,未做编码”。

3.3 要素 3:指定 “预处理目标”

预处理目标要和后续的机器学习任务结合,比如 “预处理后用于逻辑回归模型训练”“预处理后用于 BERT 模型做文本分类”“预处理后用于 CNN 模型做图像识别”。不同任务的预处理要求不同(如逻辑回归需要特征标准化,而树模型不需要),明确目标能让大模型生成更适配的步骤。

示例表述:“预处理的目标是:将数据集处理后用于逻辑回归模型训练,预测乘客是否生存(二分类任务),要求预处理后的特征均为数值型,且符合逻辑回归的输入要求(如特征标准化)”。

3.4 要素 4:要求 “输出格式”

为了方便后续使用,要在提示词中指定输出格式,比如 “按‘步骤编号 + 步骤名称 + 具体操作 + 代码示例’的格式输出”“分‘数据加载→数据清洗→特征工程→数据划分’四个模块输出”。清晰的格式能让预处理步骤更易读、易执行。

示例表述:“请按以下格式输出预处理步骤:1. 分‘数据加载、数据清洗、特征工程、数据划分、模型输入准备’五个模块;2. 每个模块下按‘步骤编号 + 步骤名称 + 具体操作(文字描述)+Python 代码示例’呈现;3. 代码需使用 Pandas、Scikit-learn 库,注释清晰”。

4. 实战案例 1:表格数据预处理(泰坦尼克号数据集)

表格数据是机器学习中最常见的数据类型,预处理步骤主要包括数据加载、缺失值处理、异常值检测、特征编码、特征标准化、数据划分等。下面以 “泰坦尼克号生存预测数据集” 为例,完整演示提示词编写和大模型生成结果。

4.1 案例背景

  • 数据类型:表格数据(CSV 格式);
  • 数据来源:Kaggle 泰坦尼克号生存预测数据集;
  • 数据规模:891 行样本,12 列特征(含 1 列标签);
  • 已知问题:1. Age(年龄)列缺失率 30%;2. Fare(船票价格)列存在异常值;3. Sex(性别)、Embarked(登船港口)为类别特征,未编码;4. Name(姓名)、Ticket(船票编号)为无关特征,需删除;
  • 预处理目标:处理后用于逻辑回归模型训练(二分类任务:预测 Survived);
  • 工具要求:使用 Python 的 Pandas、Scikit-learn 库。

4.2 提示词编写

“请帮我生成泰坦尼克号数据集的机器学习预处理步骤,具体要求如下:

  1. 数据背景:表格数据(CSV 格式),891 行样本,12 列特征(含标签列 Survived),已知问题:Age 列缺失率 30%、Fare 列有异常值、Sex 和 Embarked 为未编码的类别特征、Name 和 Ticket 为无关特征;
  1. 预处理目标:处理后用于逻辑回归模型训练(二分类任务),要求特征均为数值型,且做标准化处理;
  1. 工具要求:使用 Pandas、Scikit-learn 库;
  1. 输出格式:分‘1. 数据加载、2. 数据清洗、3. 特征工程、4. 数据划分、5. 模型输入准备’五个模块,每个模块下按‘步骤编号 + 步骤名称 + 具体操作 + Python 代码示例’呈现,代码需加详细注释。”

4.3 大模型生成结果

1. 数据加载
1.1 步骤名称:导入所需库
  • 具体操作:导入预处理过程中需要的 Python 库,包括 Pandas(数据读取与处理)、NumPy(数值计算)、Scikit-learn(后续特征处理和数据划分)。
  • 代码示例:

# 导入所需库

import pandas as pd # 用于读取和处理表格数据

import numpy as np # 用于数值计算(如异常值检测)

from sklearn.preprocessing import LabelEncoder, StandardScaler # 用于特征编码和标准化

from sklearn.model_selection import train_test_split # 用于数据划分

1.2 步骤名称:读取 CSV 数据集
  • 具体操作:使用 Pandas 的 read_csv () 函数读取泰坦尼克号数据集(假设文件名为 'titanic.csv',存放在当前工作目录),并查看前 5 行数据和数据基本信息(如数据类型、缺失值情况),确认数据加载正确。
  • 代码示例:

# 读取CSV数据集

df = pd.read_csv('titanic.csv')

# 查看数据前5行,确认数据加载结果

print("数据前5行:")

print(df.head())

# 查看数据基本信息(数据类型、缺失值)

print("\n数据基本信息:")

print(df.info())

# 查看缺失值统计(重点关注Age、Embarked列)

print("\n各列缺失值数量:")

print(df.isnull().sum())

2. 数据清洗
2.1 步骤名称:删除无关特征
  • 具体操作:分析特征相关性,Name(姓名)和 Ticket(船票编号)与 “是否生存” 无关,且无法转化为有效数值特征,直接删除这两列,减少数据冗余。
  • 代码示例:

# 删除无关特征:Name(姓名)、Ticket(船票编号)

df_clean = df.drop(['Name', 'Ticket'], axis=1) # axis=1表示删除列

# 查看删除后的特征列

print("删除无关特征后的列名:")

print(df_clean.columns.tolist())

2.2 步骤名称:处理缺失值
  • 具体操作:针对不同列的缺失情况,采用不同处理方式:
    1. Age(年龄)列:缺失率 30%,属于数值型特征,用 “中位数” 填充(中位数受异常值影响小,比均值更合适);
    1. Embarked(登船港口)列:缺失率低(仅 2 条),属于类别特征,用 “众数”(出现次数最多的港口)填充;
    1. Cabin(船舱号)列:缺失率超过 70%,有效信息少,直接删除该列。
  • 代码示例:

# 1. 处理Age列缺失值:用中位数填充

age_median = df_clean['Age'].median() # 计算Age列的中位数

df_clean['Age'] = df_clean['Age'].fillna(age_median) # 填充缺失值

# 2. 处理Embarked列缺失值:用众数填充

embarked_mode = df_clean['Embarked'].mode()[0] # 计算Embarked列的众数(mode()返回Series,取第0个元素)

df_clean['Embarked'] = df_clean['Embarked'].fillna(embarked_mode) # 填充缺失值

# 3. 处理Cabin列:缺失率过高,删除该列

df_clean = df_clean.drop(['Cabin'], axis=1)

# 验证缺失值是否处理完成

print("处理后各列缺失值数量:")

print(df_clean.isnull().sum())

2.3 步骤名称:检测并处理异常值
  • 具体操作:针对数值型特征 Fare(船票价格),用 “箱线图” 检测异常值,再用 “ IQR 方法”(四分位距法)处理异常值 —— 将超过 IQR 范围的异常值替换为 IQR 上限或下限(避免直接删除样本导致数据量减少)。
  • 代码示例:

# 1. 用箱线图可视化Fare列的异常值(可选,用于直观观察)

import matplotlib.pyplot as plt

plt.figure(figsize=(8, 4))

plt.boxplot(df_clean['Fare'])

plt.title('Fare列箱线图(异常值检测)')

plt.ylabel('船票价格(Fare)')

plt.show()

# 2. 用IQR方法计算异常值范围

Q1 = df_clean['Fare'].quantile(0.25) # 第一四分位数(25%分位数)

Q3 = df_clean['Fare'].quantile(0.75) # 第三四分位数(75%分位数)

IQR = Q3 - Q1 # 四分位距

upper_bound = Q3 + 1.5 * IQR # 异常值上限

lower_bound = Q1 - 1.5 * IQR # 异常值下限(Fare为价格,不可能为负,下限取0)

lower_bound = max(lower_bound, 0)

# 3. 处理异常值:将超过上限的值替换为上限,低于下限的值替换为下限

df_clean['Fare'] = np.where(df_clean['Fare'] > upper_bound, upper_bound, df_clean['Fare'])

df_clean['Fare'] = np.where(df_clean['Fare'] < lower_bound, lower_bound, df_clean['Fare'])

# 验证异常值处理结果(查看Fare列最大值是否等于上限)

print(f"Fare列处理后的最大值:{df_clean['Fare'].max()}")

print(f"异常值上限:{upper_bound}")

3. 特征工程
3.1 步骤名称:类别特征编码
  • 具体操作:数据中存在两类类别特征,采用不同编码方式:
    1. Sex(性别):二分类特征(男 / 女),用 LabelEncoder 编码(将男→1,女→0);
    1. Embarked(登船港口):多分类特征(C/Q/S),用 One-Hot 编码(生成 3 列新特征:Embarked_C、Embarked_Q、Embarked_S,避免类别间产生顺序关系)。
  • 代码示例:

# 1. 对Sex列进行LabelEncoder编码

label_encoder = LabelEncoder()

df_clean['Sex'] = label_encoder.fit_transform(df_clean['Sex']) # 男→1,女→0

# 2. 对Embarked列进行One-Hot编码

# 使用get_dummies()函数,drop_first=True避免多重共线性(删除第一列)

embarked_dummies = pd.get_dummies(df_clean['Embarked'], prefix='Embarked', drop_first=True)

# 将编码后的列合并到原数据中,删除原Embarked列

df_clean = pd.concat([df_clean, embarked_dummies], axis=1)

df_clean = df_clean.drop(['Embarked'], axis=1)

# 查看编码后的特征列

print("编码后的特征列:")

print(df_clean.columns.tolist())

print("\n编码后的数据前5行:")

print(df_clean.head())

3.2 步骤名称:特征选择(可选)
  • 具体操作:为避免无关特征影响模型,通过 “相关性分析” 筛选与标签(Survived)相关性较高的特征(相关性绝对值≥0.1),删除相关性极低的特征(本案例中所有特征相关性均达标,可跳过此步骤,若有需要可执行)。
  • 代码示例(可选):

# 计算各特征与标签(Survived)的相关性

correlation = df_clean.corr()['Survived'].sort_values(ascending=False)

print("各特征与Survived的相关性:")

print(correlation)

# 筛选相关性绝对值≥0.1的特征

selected_features = correlation[abs(correlation) >= 0.1].index.tolist()

df_clean = df_clean[selected_features]

print(f"\n筛选后的特征列:{selected_features}")

4. 数据划分
4.1 步骤名称:分离特征与标签
  • 具体操作:将数据集分为特征矩阵(X)和标签向量(y),其中 Survived 列为标签(是否生存),其余列为特征。
  • 代码示例:

# 分离特征(X)和标签(y)

X = df_clean.drop(['Survived'], axis=1) # 特征矩阵(所有列除了Survived)

y = df_clean['Survived'] # 标签向量(Survived列)

# 查看特征矩阵和标签向量的形状

print(f"特征矩阵形状(样本数×特征数):{X.shape}")

print(f"标签向量形状(样本数):{y.shape}")

4.2 步骤名称:划分训练集与测试集
  • 具体操作:使用 Scikit-learn 的 train_test_split () 函数,按 “7:3” 的比例划分训练集(用于模型训练)和测试集(用于模型评估),设置 random_state=42 确保划分结果可复现。
  • 代码示例:

# 划分训练集(70%)和测试集(30%)

X_train, X_test, y_train, y_test = train_test_split(

X, y, test_size=0.3, random_state=42, stratify=y # stratify=y确保训练集和测试集的标签分布一致

)

# 查看划分后的数据集形状

print(f"训练集特征形状:{X_train.shape}")

print(f"训练集标签形状:{y_train.shape}")

print(f"测试集特征形状:{X_test.shape}")

print(f"测试集标签形状:{y_test.shape}")

# 验证标签分布是否一致(计算生存比例)

</doubaocanvas>

print (f"训练集生存比例:{y_train.mean ():.2f}")

print (f"测试集生存比例:{y_test.mean ():.2f}") # 若两者接近(如差值 < 0.02),说明分布一致


#### 5. 模型输入准备

##### 5.1 步骤名称:特征标准化

- 具体操作:逻辑回归模型对特征尺度敏感,需对数值型特征(Age、Fare、Pclass等)做标准化处理——使用Scikit-learn的StandardScaler,将特征转换为“均值=0、标准差=1”的分布,避免尺度差异影响模型参数。注意:仅在训练集上拟合Scaler,再用拟合好的Scaler转换测试集(避免数据泄露)。

- 代码示例:

```python

# 初始化StandardScaler

scaler = StandardScaler()

# 仅在训练集上拟合Scaler(学习训练集的均值和标准差)

scaler.fit(X_train)

# 用拟合好的Scaler转换训练集和测试集

X_train_scaled = scaler.transform(X_train)

X_test_scaled = scaler.transform(X_test)

# 验证标准化结果(查看训练集特征均值是否接近0,标准差是否接近1)

print(f"标准化后训练集特征均值(示例:Age列):{X_train_scaled[:, X_train.columns.get_loc('Age')].mean():.2f}")

print(f"标准化后训练集特征标准差(示例:Age列):{X_train_scaled[:, X_train.columns.get_loc('Age')].std():.2f}")

5.2 步骤名称:格式转换(适配模型输入)
  • 具体操作:将标准化后的特征矩阵(numpy 数组)转换为模型可接受的格式,逻辑回归模型可直接接收 numpy 数组输入,此处需确保特征矩阵和标签向量的维度正确(如 X_train_scaled 为 (623, 6),对应 623 个样本、6 个特征;y_train 为 (623,),对应 623 个标签),无需额外转换,直接用于训练即可。
  • 代码示例(验证格式与维度):

# 验证转换后的格式和维度

print(f"训练集特征格式:{type(X_train_scaled)}(numpy.ndarray,符合逻辑回归输入要求)")

print(f"训练集特征维度:{X_train_scaled.shape}")

print(f"测试集特征维度:{X_test_scaled.shape}")

print(f"训练集标签维度:{y_train.shape}")

print(f"测试集标签维度:{y_test.shape}")

# 预处理完成,输出最终可用的数据集

print("\n预处理完成,可用于逻辑回归模型训练的数据集:")

print(f"- 训练集:X_train_scaled({X_train_scaled.shape})、y_train({y_train.shape})")

print(f"- 测试集:X_test_scaled({X_test_scaled.shape})、y_test({y_test.shape})")

5. 实战案例 2:文本数据预处理(客户评论文本分类)

文本数据是 NLP 任务的核心数据类型,预处理步骤与表格数据差异较大,主要包括文本加载、文本清洗(去特殊符号、停用词)、分词、词向量转换、数据划分等。下面以 “客户商品评论文本数据集”(二分类任务:判断评论为正面 / 负面)为例,演示提示词编写和预处理步骤生成。

5.1 案例背景

  • 数据类型:文本数据(TXT 格式,每行一条评论,附带标签,如 “这台手机很好用 \t 正面”);
  • 数据来源:自制的电商平台客户评论文本数据集;
  • 数据规模:1000 条样本,每条评论长度 10-50 字,标签为 “正面” 或 “负面”(各约 500 条);
  • 已知问题:1. 文本包含特殊符号(如 “!、@、#”)和无意义词(如 “的、了、在”);2. 部分评论有错别字(如 “好用” 写成 “好佣”);3. 文本未分词,无法直接用于模型输入;
  • 预处理目标:处理后用于 BERT 模型做文本二分类(判断评论情感),要求输出为 BERT 模型可接受的 “输入_ids、attention_mask、label” 格式;
  • 工具要求:使用 Python 的 Pandas、NLTK、Hugging Face 的 transformers 库。

5.2 提示词编写

“请帮我生成客户评论文本数据集的机器学习预处理步骤,具体要求如下:

  1. 数据背景:文本数据(TXT 格式,每行一条评论 + 标签,如‘这台手机很好用 \t 正面’),1000 条样本,已知问题:含特殊符号、停用词、错别字,未分词;
  1. 预处理目标:处理后用于 BERT 模型做情感二分类(正面 / 负面),输出格式为 BERT 所需的‘input_ids、attention_mask、label’;
  1. 工具要求:使用 Pandas、NLTK、transformers 库(BERT 模型用‘bert-base-chinese’);
  1. 输出格式:分‘1. 文本数据加载、2. 文本清洗、3. 文本分词与词向量转换、4. 数据划分、5. 模型输入格式转换’五个模块,每个模块按‘步骤编号 + 步骤名称 + 具体操作 + Python 代码示例’呈现,代码加详细注释。”

5.3 大模型生成结果

1. 文本数据加载
1.1 步骤名称:导入所需库
  • 具体操作:导入文本处理、数据读取、BERT 模型相关的库,包括 Pandas(数据存储)、NLTK(停用词处理)、transformers(BERT 分词器与模型)、re(正则表达式,文本清洗)。
  • 代码示例:

# 导入所需库

import pandas as pd # 用于存储文本数据和标签

import re # 用于正则表达式文本清洗

import nltk # 用于停用词处理(需先下载停用词库)

from nltk.corpus import stopwords

from sklearn.model_selection import train_test_split # 用于数据划分

from transformers import BertTokenizer # BERT分词器(用于词向量转换)

# 下载NLTK停用词库(首次使用需执行,后续可注释)

nltk.download('stopwords')

# 加载中文停用词(NLTK中文停用词较少,可补充自定义停用词)

chinese_stopwords = stopwords.words('chinese')

# 补充自定义中文停用词(如电商评论中常见的无意义词)

custom_stopwords = ['的', '了', '在', '是', '我', '这', '很', '非常', '也', '还']

chinese_stopwords.extend(custom_stopwords)

1.2 步骤名称:读取 TXT 文本数据
  • 具体操作:使用 Pandas 的 read_csv () 函数读取 TXT 文件(指定分隔符为 \t,列名为‘comment’和‘label’),查看数据基本信息(如样本数量、标签分布),确认数据加载正确。
  • 代码示例:

# 读取TXT文本数据(分隔符为\t,无表头,需指定列名)

df = pd.read_csv('customer_comments.txt', sep='\t', header=None, names=['comment', 'label'])

# 查看数据前5行

print("数据前5行:")

print(df.head())

# 查看数据基本信息(样本数量、是否有缺失值)

print(f"\n总样本数:{len(df)}")

print(f"缺失值情况:")

print(df.isnull().sum()) # 若有缺失值,需后续删除

# 查看标签分布(确保类别平衡,适合二分类)

print(f"\n标签分布:")

print(df['label'].value_counts())

2. 文本清洗
2.1 步骤名称:去除特殊符号与数字
  • 具体操作:使用正则表达式(re.sub ())去除文本中的特殊符号(如!、@、#、¥)、数字(如 “123”“5 星”)和多余空格,只保留中文字符,避免无关字符干扰模型理解。
  • 代码示例:

# 定义文本清洗函数:去除特殊符号、数字,保留中文字符

def clean_special_chars(text):

# 正则表达式:只保留中文字符,其他字符(数字、特殊符号、英文)替换为空

text_clean = re.sub(r'[^\u4e00-\u9fa5]', '', text)

# 去除多余空格(若有)

text_clean = text_clean.strip()

return text_clean

# 对comment列应用清洗函数

df['comment_clean'] = df['comment'].apply(clean_special_chars)

# 查看清洗前后对比

print("文本清洗前后对比:")

print("原始文本:", df['comment'].iloc[0])

print("清洗后文本:", df['comment_clean'].iloc[0])

# 删除清洗后为空的样本(如原始文本全是特殊符号,清洗后无内容)

df = df[df['comment_clean'] != '']

print(f"\n清洗后剩余样本数:{len(df)}")

2.2 步骤名称:纠正常见错别字
  • 具体操作:针对电商评论中的常见错别字(如 “好用”→“好佣”“推荐”→“推存”),建立 “错别字 - 正确词” 映射字典,通过 replace () 函数批量纠正,提升文本准确性。
  • 代码示例:

# 建立常见错别字映射字典(可根据实际数据补充)

typo_map = {

'好佣': '好用',

'推存': '推荐',

'物超所值': '物超所值', # 无错别字,仅示例

'不的了': '不得了',

'质量很好': '质量很好',

'非常满义': '非常满意'

}

# 定义错别字纠正函数

def correct_typos(text):

for typo, correct in typo_map.items():

text_corrected = text.replace(typo, correct)

return text_corrected

# 对comment_clean列应用错别字纠正函数

df['comment_corrected'] = df['comment_clean'].apply(correct_typos)

# 查看纠正效果(示例)

print("错别字纠正前后对比:")

# 找一个包含错别字的样本(假设第10条样本有“好佣”)

typo_sample = df[df['comment_corrected'].str.contains('好用')].iloc[0]

print("纠正前:", typo_sample['comment_clean'])

print("纠正后:", typo_sample['comment_corrected'])

2.3 步骤名称:去除停用词
  • 具体操作:将文本按 “字” 或 “词” 分割(此处先按字分割,后续 BERT 会按词处理),去除分割后属于 “停用词” 的字符(如 “的”“了”),减少无意义文本对模型的干扰,提升处理效率。
  • 代码示例:

# 定义去除停用词函数(按字分割,去除停用词后重新拼接)

def remove_stopwords(text):

# 按字分割文本(中文文本无明显词边界,先按字处理)

chars = list(text)

# 过滤掉属于停用词的字符

chars_filtered = [char for char in chars if char not in chinese_stopwords]

# 重新拼接成文本

text_filtered = ''.join(chars_filtered)

return text_filtered

# 对comment_corrected列应用去除停用词函数

df['comment_final'] = df['comment_corrected'].apply(remove_stopwords)

# 查看去除停用词前后对比

print("去除停用词前后对比:")

print("纠正后文本:", df['comment_corrected'].iloc[0])

print("去除停用词后文本:", df['comment_final'].iloc[0])

# 最终文本长度过滤(去除过短文本,如长度<2字,无有效信息)

df = df[df['comment_final'].str.len() >= 2]

print(f"\n去除停用词和短文本后剩余样本数:{len(df)}")

3. 文本分词与词向量转换
3.1 步骤名称:BERT 分词器初始化
  • 具体操作:加载 Hugging Face 的 “bert-base-chinese” 分词器(适配中文文本),设置分词后的文本最大长度(如 32,根据评论平均长度设定,过长截断,过短填充),确保所有文本长度一致,适配 BERT 模型输入。
  • 代码示例:

# 初始化BERT分词器(使用中文预训练模型)

tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')

# 设定文本最大长度(根据数据统计设定,此处假设评论平均长度15字,设为32)

max_length = 32

# 查看分词器基本信息(验证加载正确)

print(f"BERT分词器加载完成,词汇表大小:{tokenizer.vocab_size}")

print(f"设定文本最大长度:{max_length}")

3.2 步骤名称:文本分词与词向量生成
  • 具体操作:使用分词器的 encode_plus () 函数,对每条最终文本(comment_final)进行分词,生成 BERT 模型所需的 3 类向量:
    1. input_ids:文本分词后的词汇 ID(对应 BERT 词汇表);
    1. attention_mask:注意力掩码(1 表示有效文本,0 表示填充部分);
    1. token_type_ids:句子类型掩码(单句文本,全为 0);

同时将标签(“正面”“负面”)转换为数值(1 和 0),便于模型训练。

  • 代码示例:

# 定义函数:将文本转换为BERT所需的向量格式

def convert_text_to_bert_features(text, label):

# 分词并生成向量

encoding = tokenizer.encode_plus(

text,

add_special_tokens=True, # 添加BERT特殊符号([CLS]开头,[SEP]结尾)

max_length=max_length,

padding='max_length', # 长度不足时填充

truncation=True, # 长度超过时截断

return_attention_mask=True, # 返回attention_mask

return_token_type_ids=True, # 返回token_type_ids(单句用)

return_tensors='pt' # 返回PyTorch张量(适配后续模型训练)

)

# 将标签转换为数值(正面→1,负面→0)

label_num = 1 if label == '正面' else 0

return {

'input_ids': encoding['input_ids'].flatten(), # 展平为1维张量

'attention_mask': encoding['attention_mask'].flatten(),

'token_type_ids': encoding['token_type_ids'].flatten(),

'label': label_num

}

# 对所有样本应用函数,生成BERT特征

bert_features = df.apply(

lambda row: convert_text_to_bert_features(row['comment_final'], row['label']),

axis=1

)

# 将特征转换为DataFrame,便于后续处理

bert_df = pd.DataFrame(bert_features.tolist())

# 查看生成的BERT特征示例

print("BERT特征示例(input_ids前10个ID):")

print(bert_df['input_ids'].iloc[0][:10])

print(f"attention_mask示例:{bert_df['attention_mask'].iloc[0][:10]}")

print(f"标签数值示例:{bert_df['label'].iloc[0]}(对应原标签:{df['label'].iloc[0]})")

4. 数据划分
4.1 步骤名称:分离特征与标签(BERT 格式)
  • 具体操作:从 bert_df 中分离 BERT 模型所需的特征(input_ids、attention_mask、token_type_ids)和标签(label),转换为 PyTorch 张量格式,便于后续数据划分和模型输入。
  • 代码示例:

import torch # 导入PyTorch,用于张量处理

# 分离特征和标签,转换为PyTorch张量

# 特征:input_ids、attention_mask、token_type_ids

input_ids = torch.stack([torch.tensor(ids) for ids in bert_df['input_ids']])

attention_mask = torch.stack([torch.tensor(mask) for mask in bert_df['attention_mask']])

token_type_ids = torch.stack([torch.tensor(tt_ids) for tt_ids in bert_df['token_type_ids']])

# 标签

labels = torch.tensor(bert_df['label'].tolist())

# 查看张量形状(验证维度正确)

print(f"input_ids形状(样本数×最大长度):{input_ids.shape}")

print(f"attention_mask形状:{attention_mask.shape}")

print(f"token_type_ids形状:{token_type_ids.shape}")

print(f"labels形状(样本数):{labels.shape}")

4.2 步骤名称:划分训练集与测试集(BERT 格式)
  • 具体操作:由于 BERT 模型输入包含input_ids、attention_mask、token_type_ids三类特征,需同时对这三类特征和标签进行划分。使用train_test_split函数按 “8:2” 比例划分(文本数据样本量较少时,测试集比例可适当减小),设置random_state=42确保结果可复现,stratify=labels确保训练集和测试集的标签分布一致。
  • 代码示例:

# 同时划分三类特征和标签(需注意输入顺序与输出顺序对应)

train_input_ids, test_input_ids, train_attention_mask, test_attention_mask, \

train_token_type_ids, test_token_type_ids, train_labels, test_labels = train_test_split(

input_ids, attention_mask, token_type_ids, labels,

test_size=0.2, random_state=42, stratify=labels

)

# 查看划分后的各部分形状

print("训练集各部分形状:")

print(f"- train_input_ids:{train_input_ids.shape}")

print(f"- train_attention_mask:{train_attention_mask.shape}")

print(f"- train_token_type_ids:{train_token_type_ids.shape}")

print(f"- train_labels:{train_labels.shape}")

print("\n测试集各部分形状:")

print(f"- test_input_ids:{test_input_ids.shape}")

print(f"- test_attention_mask:{test_attention_mask.shape}")

print(f"- test_token_type_ids:{test_token_type_ids.shape}")

print(f"- test_labels:{test_labels.shape}")

# 验证标签分布是否一致

print(f"\n训练集正面标签比例:{train_labels.sum().item() / len(train_labels):.2f}")

print(f"测试集正面标签比例:{test_labels.sum().item() / len(test_labels):.2f}")

5. 模型输入格式转换
5.1 步骤名称:创建 PyTorch 数据集类
  • 具体操作:BERT 模型训练时,通常使用 PyTorch 的Dataset类封装数据,便于后续通过DataLoader实现批量加载。自定义数据集类CommentDataset,在__getitem__方法中返回单条样本的input_ids、attention_mask、token_type_ids和label,确保格式符合模型输入要求。
  • 代码示例:

from torch.utils.data import Dataset, DataLoader # 导入Dataset和DataLoader

# 自定义数据集类

class CommentDataset(Dataset):

def __init__(self, input_ids, attention_mask, token_type_ids, labels):

self.input_ids = input_ids

self.attention_mask = attention_mask

self.token_type_ids = token_type_ids

self.labels = labels

# 返回数据集样本总数

def __len__(self):

return len(self.labels)

# 返回单条样本(按索引)

def __getitem__(self, idx):

return {

'input_ids': self.input_ids[idx],

'attention_mask': self.attention_mask[idx],

'token_type_ids': self.token_type_ids[idx],

'label': self.labels[idx]

}

# 创建训练集和测试集的Dataset实例

train_dataset = CommentDataset(

train_input_ids, train_attention_mask, train_token_type_ids, train_labels

)

test_dataset = CommentDataset(

test_input_ids, test_attention_mask, test_token_type_ids, test_labels

)

# 查看Dataset实例的样本数量和单条样本格式

print(f"训练集Dataset样本数:{len(train_dataset)}")

print(f"测试集Dataset样本数:{len(test_dataset)}")

print(f"\n单条训练集样本格式:")

sample = train_dataset[0]

for key, value in sample.items():

print(f"- {key}:形状{value.shape},类型{type(value)}")

5.2 步骤名称:创建 DataLoader(批量加载)
  • 具体操作:使用DataLoader对Dataset进行封装,设置批量大小(batch_size,如 16,根据 GPU 显存调整)和是否打乱训练集(shuffle=True用于训练集,shuffle=False用于测试集),实现训练时的批量数据加载,提升模型训练效率。
  • 代码示例:

# 设置批量大小(根据GPU显存调整,显存不足时减小batch_size)

batch_size = 16

# 创建训练集DataLoader(打乱数据)

train_dataloader = DataLoader(

train_dataset, batch_size=batch_size, shuffle=True, drop_last=False

) # drop_last=False:不丢弃最后一个不足batch_size的样本

# 创建测试集DataLoader(不打乱数据)

test_dataloader = DataLoader(

test_dataset, batch_size=batch_size, shuffle=False, drop_last=False

)

# 验证DataLoader的批量加载效果

print(f"训练集DataLoader批量数:{len(train_dataloader)}(总样本数{len(train_dataset)} ÷ 批量大小{batch_size})")

print(f"测试集DataLoader批量数:{len(test_dataloader)}")

# 查看一个批量的数据格式

for batch in train_dataloader:

print(f"\n一个训练批量的数据格式:")

for key, value in batch.items():

print(f"- {key}:形状{value.shape}(批量大小×最大长度)")

break # 仅查看第一个批量,避免输出过多

5.3 步骤名称:最终输入格式验证
  • 具体操作:验证DataLoader输出的批量数据是否完全符合 BERT 模型的输入要求 ——input_ids、attention_mask、token_type_ids的形状均为 “批量大小 × 最大长度”,label的形状为 “批量大小”,数据类型为 PyTorch 张量(torch.int64),确保可直接传入 BERT 模型进行训练。
  • 代码示例:

# 验证数据类型和形状是否符合BERT模型输入要求

print("BERT模型输入格式验证:")

for batch in train_dataloader:

# 验证形状

assert batch['input_ids'].shape == (batch_size, max_length), "input_ids形状错误"

assert batch['attention_mask'].shape == (batch_size, max_length), "attention_mask形状错误"

assert batch['token_type_ids'].shape == (batch_size, max_length), "token_type_ids形状错误"

assert batch['label'].shape == (batch_size,), "label形状错误"

# 验证数据类型

assert batch['input_ids'].dtype == torch.int64, "input_ids类型错误(需torch.int64)"

assert batch['label'].dtype == torch.int64, "label类型错误(需torch.int64)"

print("✅ 所有格式验证通过,可直接传入BERT模型训练!")

break

# 预处理完成,输出最终可用的数据加载器

print(f"\n预处理完成,可用于BERT模型训练的数据加载器:")

print(f"- 训练集:train_dataloader({len(train_dataloader)}个批量,每个批量{batch_size}条样本)")

print(f"- 测试集:test_dataloader({len(test_dataloader)}个批量,每个批量{batch_size}条样本)")

6. 实战案例 3:图像数据预处理(猫狗图像分类)

图像数据是计算机视觉任务的核心数据类型,预处理步骤主要包括图像加载、尺寸统一、数据增强、像素归一化、数据划分等。下面以 “公开的猫狗图像数据集”(二分类任务:判断图像为猫 / 狗)为例,演示提示词编写和预处理步骤生成。

6.1 案例背景

  • 数据类型:图像数据(JPG/PNG 格式,每张图像对应一个类别标签:猫 / 狗);
  • 数据来源:Kaggle Cats vs. Dogs 数据集,图像存储路径按类别划分(如 “train/cat/001.jpg”“train/dog/002.jpg”);
  • 数据规模:25000 张训练图像(猫 12500 张、狗 12500 张),5000 张测试图像;
  • 已知问题:1. 图像尺寸不一致(如有的 200×200 像素,有的 500×500 像素);2. 部分图像存在旋转、模糊问题;3. 像素值范围为 0-255,未归一化,不适合模型输入;
  • 预处理目标:处理后用于 CNN(卷积神经网络,如 ResNet50)做图像二分类,要求输出为 “图像张量 + 类别标签” 格式,适配 CNN 模型输入;
  • 工具要求:使用 Python 的 OpenCV、PIL、PyTorch(torchvision)库。

6.2 提示词编写

“请帮我生成猫狗图像数据集的机器学习预处理步骤,具体要求如下:

  1. 数据背景:图像数据(JPG/PNG 格式,按类别存放在不同文件夹,如‘train/cat/’‘train/dog/’),共 30000 张图像(25000 张训练、5000 张测试),已知问题:尺寸不一致、部分图像旋转模糊、像素值未归一化;
  1. 预处理目标:处理后用于 ResNet50 模型做二分类(猫 / 狗),输出格式为‘图像张量(3×224×224,RGB 通道)+ 标签(0 = 猫,1 = 狗)’;
  1. 工具要求:使用 OpenCV、PIL、PyTorch 的 torchvision 库,需包含训练集数据增强(解决过拟合);
  1. 输出格式:分‘1. 图像数据加载与标签映射、2. 图像预处理(尺寸统一 + 归一化)、3. 训练集数据增强、4. 数据划分与封装、5. 模型输入验证’五个模块,每个模块按‘步骤编号 + 步骤名称 + 具体操作 + Python 代码示例’呈现,代码加详细注释。”

6.3 大模型生成结果

1. 图像数据加载与标签映射
1.1 步骤名称:导入所需库
  • 具体操作:导入图像读取、预处理、数据封装相关的库,包括 OpenCV(图像读取)、PIL(图像处理)、torchvision(预处理.transforms、数据集加载)、PyTorch(张量处理)。
  • 代码示例:

# 导入所需库

import os # 用于路径操作

import cv2 # 用于图像读取(OpenCV)

from PIL import Image # 用于图像处理(PIL)

import torch # 用于张量处理

from torch.utils.data import Dataset, DataLoader # 用于数据集封装

from torchvision import transforms # 用于图像预处理和数据增强

from torchvision.datasets import ImageFolder # 用于按文件夹加载图像数据集

import matplotlib.pyplot as plt # 用于图像可视化(可选,验证加载效果)

1.2 步骤名称:定义数据路径与标签映射
  • 具体操作:明确训练集和测试集的文件夹路径(如 “./data/train/”“./data/test/”),建立 “文件夹名称→类别标签” 的映射关系(如 “cat”→0,“dog”→1),确保每张图像能对应正确的标签。
  • 代码示例:

# 定义数据路径(根据实际存储路径修改)

train_data_dir = './data/train/' # 训练集路径,下含cat、dog两个子文件夹

test_data_dir = './data/test/' # 测试集路径,下含cat、dog两个子文件夹

# 验证路径是否存在

assert os.path.exists(train_data_dir), f"训练集路径不存在:{train_data_dir}"

assert os.path.exists(test_data_dir), f"测试集路径不存在:{test_data_dir}"

# 建立标签映射:文件夹名称→数值标签(cat=0,dog=1)

label_map = {'cat': 0, 'dog': 1}

# 反向映射(用于后续可视化时显示类别名称)

inv_label_map = {0: 'cat', 1: 'dog'}

# 查看训练集各类别图像数量

for class_name in label_map.keys():

class_path = os.path.join(train_data_dir, class_name)

img_count = len(os.listdir(class_path))

print(f"训练集{class_name}类图像数量:{img_count}")

# 查看测试集各类别图像数量

for class_name in label_map.keys():

class_path = os.path.join(test_data_dir, class_name)

img_count = len(os.listdir(class_path))

print(f"测试集{class_name}类图像数量:{img_count}")

1.3 步骤名称:可视化验证图像加载
  • 具体操作:随机读取训练集中的 2 张图像(猫和狗各 1 张),使用 matplotlib 显示图像和对应的标签,验证图像加载正确且标签映射无误。
  • 代码示例(可选):

# 随机读取1张猫图像和1张狗图像,可视化验证

def visualize_sample(class_name, data_dir):

class_path = os.path.join(data_dir, class_name)

img_names = os.listdir(class_path)

# 随机选1张图像

img_name = img_names[0]

img_path = os.path.join(class_path, img_name)

# 用PIL读取图像

img = Image.open(img_path).convert('RGB') # 转为RGB通道(避免灰度图)

# 显示图像

plt.figure(figsize=(6, 4))

plt.imshow(img)

plt.title(f"Class: {class_name} (Label: {label_map[class_name]})")

plt.axis('off')

plt.show()

# 可视化猫和狗的样本图像

visualize_sample('cat', train_data_dir)

visualize_sample('dog', train_data_dir)

2. 图像预处理(尺寸统一 + 归一化)
2.1 步骤名称:定义基础预处理流水线
  • 具体操作:针对所有图像(训练集和测试集),定义基础预处理步骤,包括:1. 尺寸统一(Resize 为 224×224,ResNet50 默认输入尺寸);2. 转为张量(ToTensor (),将图像转为 PyTorch 张量,同时将像素值从 0-255 归一化到 0-1);3. 标准化(Normalize (),使用 ImageNet 数据集的均值和标准差,适配预训练 ResNet50 模型)。
  • 代码示例:

# 定义基础预处理流水线(训练集和测试集共用)

# 1. Resize:统一图像尺寸为224×224(ResNet50默认输入尺寸)

# 2. ToTensor:转为张量,像素值从0-255→0-1

# 3. Normalize:标准化,使用ImageNet均值和标准差(预训练模型要求)

base_transform = transforms.Compose([

transforms.Resize((224, 224)),

transforms.ToTensor(),

transforms.Normalize(mean=[0.485, 0.456, 0.406], # ImageNet均值(RGB通道)

std=[0.229, 0.224, 0.225]) # ImageNet标准差

])

# 验证预处理效果(读取1张图像,查看处理前后变化)

def test_base_transform(img_path):

# 读取原始图像(PIL)

img = Image.open(img_path).convert('RGB')

print(f"原始图像:类型{type(img)},尺寸{img.size},像素值范围0-255")

# 应用预处理

img_tensor = base_transform(img)

print(f"预处理后:类型{type(img_tensor)},形状{img_tensor.shape}(通道×高×宽),像素值范围{img_tensor.min():.2f}-{img_tensor.max():.2f}")

return img, img_tensor

# 测试预处理(选1张猫图像)

cat_img_path = os.path.join(train_data_dir, 'cat', os.listdir(os.path.join(train_data_dir, 'cat'))[0])

original_img, processed_tensor = test_base_transform(cat_img_path)

2.2 步骤名称:处理特殊图像(旋转、模糊)
  • 具体操作:部分图像存在旋转(如 90°/180° 旋转)、模糊问题,通过 OpenCV 的图像处理函数进行修正:1. 旋转图像(使用 cv2.rotate () 将旋转图像转正);2. 去模糊(使用 cv2.GaussianBlur () 对模糊图像进行轻度高斯模糊,平滑噪声,避免过度锐化导致失真)。
  • 代码示例:

# 定义特殊图像处理函数(旋转修正+轻度去模糊)

def fix_special_images(img_path):

# 用OpenCV读取图像(默认BGR通道,需转为RGB)

img_bgr = cv2.imread(img_path)

img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)

# 1. 旋转修正:检测图像方向,将旋转图像转正(假设仅90°</doubaocanvas>

、180° 旋转,无 270° 旋转)

height, width = img_rgb.shape [:2]

若图像高度 > 宽度,判断为 90° 旋转(如手机拍摄的竖屏图像)

if height > width * 1.2: # 宽度的 1.2 倍以上,判定为旋转

img_rgb = cv2.rotate (img_rgb, cv2.ROTATE_90_CLOCKWISE) # 顺时针旋转 90°

若图像像素值方差过小,判断为模糊(方差小表示图像对比度低,可能模糊)

gray = cv2.cvtColor (img_rgb, cv2.COLOR_RGB2GRAY)

blur_score = cv2.Laplacian (gray, cv2.CV_64F).var () # 计算拉普拉斯方差,值越小越模糊

if blur_score < 50: # 经验阈值,可根据实际数据调整

img_rgb = cv2.GaussianBlur (img_rgb, (3, 3), 0) # 轻度高斯模糊(3×3 核),平滑噪声

转为 PIL 图像格式(适配后续 torchvision.transforms)

img_pil = Image.fromarray(img_rgb)

return img_pil

测试特殊图像处理函数(选 1 张可能旋转的图像)

假设存在 1 张竖屏拍摄的狗图像(路径需根据实际数据调整)

dog_img_path = os.path.join(train_data_dir, 'dog', 'rotated_dog.jpg')

if os.path.exists(dog_img_path):

fixed_img = fix_special_images(dog_img_path)

original_img = Image.open(dog_img_path).convert('RGB')

对比显示原始图像和处理后图像

plt.figure (figsize=(12, 4))

plt.subplot (1, 2, 1)

plt.imshow (original_img)

plt.title ("原始图像(可能旋转 / 模糊)")

plt.axis ('off')

plt.subplot (1, 2, 2)

plt.imshow (fixed_img)

plt.title ("处理后图像(转正 + 去模糊)")

plt.axis ('off')

plt.show ()

else:

print ("未找到旋转 / 模糊图像,跳过测试")


##### 2.3 步骤名称:自定义数据集类(集成特殊处理)

- 具体操作:为了将“特殊图像处理”“基础预处理”整合到数据加载流程中,自定义数据集类`CatDogDataset`,在`__getitem__`方法中先读取图像并处理特殊问题,再应用基础预处理,确保每一张图像都经过统一处理。

- 代码示例:

```python

# 自定义猫狗图像数据集类

class CatDogDataset(Dataset):

def __init__(self, data_dir, label_map, transform=None):

self.data_dir = data_dir # 数据文件夹路径(含cat、dog子文件夹)

self.label_map = label_map # 标签映射(如{'cat':0, 'dog':1})

self.transform = transform # 预处理流水线

self.img_paths = self._get_all_img_paths() # 所有图像的路径列表

# 私有方法:获取所有图像的路径和对应的标签

def _get_all_img_paths(self):

img_paths = []

for class_name, label in self.label_map.items():

class_dir = os.path.join(self.data_dir, class_name)

# 遍历该类别下的所有图像文件(仅保留JPG/PNG格式)

for img_name in os.listdir(class_dir):

if img_name.lower().endswith(('.jpg', '.png')):

img_path = os.path.join(class_dir, img_name)

img_paths.append((img_path, label))

return img_paths

# 返回数据集样本总数

def __len__(self):

return len(self.img_paths)

# 返回单条样本(读取图像→处理特殊问题→预处理→返回图像张量和标签)

def __getitem__(self, idx):

img_path, label = self.img_paths[idx]

# 1. 读取图像并处理特殊问题(旋转、模糊)

img_pil = fix_special_images(img_path)

# 2. 应用预处理流水线(若有)

if self.transform:

img_tensor = self.transform(img_pil)

else:

img_tensor = transforms.ToTensor()(img_pil) # 默认转为张量

# 3. 返回图像张量和标签(标签转为PyTorch张量)

return img_tensor, torch.tensor(label, dtype=torch.int64)

# 测试自定义数据集类

test_dataset = CatDogDataset(

data_dir=train_data_dir,

label_map=label_map,

transform=base_transform

)

# 查看单条样本

img_tensor, label = test_dataset[0]

print(f"自定义数据集单条样本:")

print(f"- 图像张量形状:{img_tensor.shape}(通道×高×宽)")

print(f"- 图像张量类型:{img_tensor.dtype}")

print(f"- 标签:{label.item()}({inv_label_map[label.item()]})")

3. 训练集数据增强
3.1 步骤名称:定义训练集增强流水线
  • 具体操作:训练集数据增强能增加样本多样性,缓解模型过拟合。针对图像数据,常用的增强手段包括:随机水平翻转(RandomHorizontalFlip)、随机裁剪(RandomResizedCrop)、随机亮度 / 对比度调整(ColorJitter)。测试集不做增强,仅用基础预处理,确保评估结果准确。
  • 代码示例:

# 定义训练集数据增强流水线(基础预处理+增强操作)

train_transform = transforms.Compose([

# 1. 随机裁剪并调整为224×224(模拟不同拍摄角度的裁剪区域)

transforms.RandomResizedCrop(size=(224, 224), scale=(0.8, 1.0)), # scale:裁剪区域占原图像的80%-100%

# 2. 随机水平翻转(50%概率翻转,模拟左右对称的场景)

transforms.RandomHorizontalFlip(p=0.5), # p:翻转概率

# 3. 随机调整亮度、对比度、饱和度(模拟不同光照条件)

transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2), # 调整幅度±20%

# 4. 基础预处理(转为张量+标准化)

transforms.ToTensor(),

transforms.Normalize(mean=[0.485, 0.456, 0.406],

std=[0.229, 0.224, 0.225])

])

# 测试增强效果(同一张图像应用增强,查看多次结果差异)

def visualize_augmentation(img_path, transform, num_samples=3):

# 读取原始图像

img_pil = fix_special_images(img_path)

plt.figure(figsize=(15, 5))

for i in range(num_samples):

# 应用增强(每次结果可能不同)

img_tensor = transform(img_pil)

# 张量转为PIL图像(用于显示)

img_aug = transforms.ToPILImage()(img_tensor)

# 显示图像

plt.subplot(1, num_samples, i+1)

plt.imshow(img_aug)

plt.title(f"增强结果 {i+1}")

plt.axis('off')

plt.show()

# 测试增强效果(选1张猫图像)

cat_img_path = os.path.join(train_data_dir, 'cat', os.listdir(os.path.join(train_data_dir, 'cat'))[0])

visualize_augmentation(cat_img_path, train_transform, num_samples=3)

3.2 步骤名称:创建训练集与测试集实例
  • 具体操作:使用自定义的CatDogDataset类,分别加载训练集(应用增强流水线)和测试集(应用基础预处理),确保训练集有数据增强,测试集无增强,符合模型训练的通用流程。
  • 代码示例:

# 创建训练集实例(应用数据增强)

train_dataset = CatDogDataset(

data_dir=train_data_dir,

label_map=label_map,

transform=train_transform

)

# 创建测试集实例(仅基础预处理,无增强)

test_dataset = CatDogDataset(

data_dir=test_data_dir,

label_map=label_map,

transform=base_transform

)

# 查看数据集规模

print(f"训练集样本数:{len(train_dataset)}")

print(f"测试集样本数:{len(test_dataset)}")

# 验证训练集增强后的样本形状(与测试集一致)

train_img, train_label = train_dataset[0]

test_img, test_label = test_dataset[0]

print(f"\n训练集样本形状:{train_img.shape}")

print(f"测试集样本形状:{test_img.shape}")

print(f"两者形状一致,可用于模型训练和评估")

4. 数据划分与封装
4.1 步骤名称:划分训练集与验证集
  • 具体操作:训练集中通常需要划分出一部分作为验证集(用于训练过程中评估模型效果,调整超参数)。使用torch.utils.data.random_split函数按 “9:1” 比例划分训练集和验证集(训练集 90% 用于训练,10% 用于验证),设置random_state=42确保结果可复现。
  • 代码示例:

import math

from torch.utils.data import random_split

# 计算划分比例(训练集90%,验证集10%)

train_size = math.floor(len(train_dataset) * 0.9)

val_size = len(train_dataset) - train_size

# 划分训练集和验证集

train_subset, val_subset = random_split(

train_dataset,

[train_size, val_size],

generator=torch.Generator().manual_seed(42) # 设置随机种子,确保划分可复现

)

# 查看划分后的规模

print(f"划分后训练集样本数:{len(train_subset)}")

print(f"划分后验证集样本数:{len(val_subset)}")

print(f"测试集样本数(不变):{len(test_dataset)}")

4.2 步骤名称:创建 DataLoader(批量加载)
  • 具体操作:使用DataLoader对训练集、验证集、测试集进行封装,设置批量大小(batch_size=32,根据 GPU 显存调整),训练集和验证集设置shuffle=True(打乱数据,提升训练效果),测试集设置shuffle=False(保持数据顺序,便于评估)。
  • 代码示例:

# 设置批量大小(根据GPU显存调整,如显存不足可改为16)

batch_size = 32

# 创建训练集DataLoader(打乱数据)

train_loader = DataLoader(

train_subset,

batch_size=batch_size,

shuffle=True,

num_workers=2, # 多线程加载数据,提升速度(根据CPU核心数调整)

pin_memory=True # 锁定内存,加速GPU数据传输(若使用GPU)

)

# 创建验证集DataLoader(打乱数据)

val_loader = DataLoader(

val_subset,

batch_size=batch_size,

shuffle=True,

num_workers=2,

pin_memory=True

)

# 创建测试集DataLoader(不打乱数据)

test_loader = DataLoader(

test_dataset,

batch_size=batch_size,

shuffle=False,

num_workers=2,

pin_memory=True

)

# 查看各DataLoader的批量数

print(f"训练集DataLoader批量数:{len(train_loader)}({len(train_subset)} ÷ {batch_size})")

print(f"验证集DataLoader批量数:{len(val_loader)}({len(val_subset)} ÷ {batch_size})")

print(f"测试集DataLoader批量数:{len(test_loader)}({len(test_dataset)} ÷ {batch_size})")

# 验证批量数据格式

for batch_img, batch_label in train_loader:

print(f"\n训练集批量数据格式:")

print(f"- 批量图像形状:{batch_img.shape}(批量大小×通道×高×宽)")

print(f"- 批量标签形状:{batch_label.shape}(批量大小)")

print(f"- 图像数据类型:{batch_img.dtype}")

print(f"- 标签数据类型:{batch_label.dtype}")

break # 仅查看第一个批量

5. 模型输入验证
5.1 步骤名称:验证数据与 ResNet50 模型适配性
  • 具体操作:ResNet50 模型的输入要求为 “批量大小 ×3×224×224”(RGB 三通道,224×224 像素),标签要求为 “批量大小” 的torch.int64张量。通过加载预训练 ResNet50 模型,传入一个批量的训练数据,验证是否能正常前向传播,确保预处理后的数据完全适配模型。
  • 代码示例:

from torchvision.models import resnet50

# 加载预训练ResNet50模型(用于验证输入适配性)

model = resnet50(pretrained=True) # 若使用PyTorch 1.13+,需改为weights=ResNet50_Weights.DEFAULT

model.eval() # 设置为评估模式(仅验证前向传播,不训练)

# 禁用梯度计算(节省内存)

with torch.no_grad():

# 从训练集DataLoader取一个批量

for batch_img, batch_label in train_loader:

# 验证输入形状

assert batch_img.shape == (batch_size, 3, 224, 224), f"图像形状错误,应为({batch_size},3,224,224),实际为{batch_img.shape}"

# 验证标签形状和类型

assert batch_label.shape == (batch_size,), f"标签形状错误,应为({batch_size},),实际为{batch_label.shape}"

assert batch_label.dtype == torch.int64, f"标签类型错误,应为torch.int64,实际为{batch_label.dtype}"

# 模型前向传播(验证是否能正常运行)

outputs = model(batch_img)

# 验证输出形状(ResNet50输出为1000类,形状应为批量大小×1000)

assert outputs.shape == (batch_size, 1000), f"模型输出形状错误,应为({batch_size},1000),实际为{outputs.shape}"

print("✅ 数据与ResNet50模型完全适配,可正常前向传播!")

break # 仅验证一个批量

# 预处理完成,输出最终可用的数据加载器

print(f"\n预处理完成,可用于ResNet50模型训练的数据加载器:")

print(f"- 训练集:train_loader({len(train_loader)}个批量,{len(train_subset)}条样本)")

print(f"- 验证集:val_loader({len(val_loader)}个批量,{len(val_subset)}条样本)")

print(f"- 测试集:test_loader({len(test_loader)}个批量,{len(test_dataset)}条样本)")

7. 提示词编写的通用技巧:适配不同数据类型

通过前面的三个实战案例,我们总结出编写 “生成机器学习数据集预处理步骤” 提示词的通用技巧,无论面对表格数据、文本数据还是图像数据,都能套用这些技巧,提升提示词的精准度。

7.1 技巧 1:精准描述 “数据特征”

不同数据类型的特征差异大,提示词中需明确数据的 “形态”“结构”“已知问题”,让大模型快速定位预处理方向:

  • 表格数据:说明特征类型(数值型 / 类别型)、缺失率、异常值位置、无关特征名称;
  • 文本数据:说明文本格式(TXT/CSV)、长度范围、特殊符号类型、错别字情况;
  • 图像数据:说明图像格式(JPG/PNG)、尺寸范围、通道数(RGB / 灰度)、特殊问题(旋转 / 模糊)。

示例表述(表格数据):“数据集为表格数据,包含 12 个特征,其中 Age(数值型)缺失率 30%,Fare(数值型)存在异常值,Sex 和 Embarked 为未编码的类别特征,Name 和 Ticket 为无关特征”。

7.2 技巧 2:绑定 “预处理目标与模型”

预处理步骤需与后续模型强绑定,提示词中明确 “模型类型” 和 “任务类型”,让大模型生成适配的预处理步骤:

  • 逻辑回归 / 线性模型:需包含 “特征标准化”“类别特征编码” 步骤;
  • BERT/Transformer 模型:需包含 “分词”“词向量转换”“attention_mask 生成” 步骤;
  • CNN/ResNet 模型:需包含 “图像尺寸统一”“像素归一化”“数据增强” 步骤。
  • 示例表述(文本数据):“预处理目标是将文本数据用于 BERT 模型做情感二分类,需生成 input_ids、attention_mask、token_type_ids 三类向量,适配 BERT 模型输入格式”。

    7.3 技巧 3:明确 “工具与格式要求”

    不同工具库的预处理函数和代码风格不同,提示词中需指定 “使用的工具库” 和 “输出格式”,让大模型生成可直接运行的代码:

  • 工具库指定:如 “使用 Pandas 处理表格数据、Scikit-learn 做特征编码、PyTorch 的 torchvision 处理图像数据”;
  • 格式要求指定:如 “按‘模块 + 步骤 + 代码’格式输出,代码需加详细注释,变量名符合 Python 命名规范”。
  • 示例表述(图像数据):“使用 OpenCV 读取图像、torchvision 做预处理和数据增强,输出格式需分‘图像加载、预处理、增强、封装’四个模块,每个步骤附带 Python 代码,代码中需包含异常处理(如图像读取失败)”。

    8. 常见问题与解决方案:生成预处理步骤时的避坑指南

    在使用提示词生成预处理步骤的过程中,可能会遇到 “代码无法运行”“步骤遗漏”“与模型不匹配” 等问题。下面总结常见问题及解决方案,帮助大家快速排查并修正。

    8.1 问题 1:生成的代码无法运行(如函数不存在、路径错误)

    8.1.1 问题表现

    大模型生成的代码中存在语法错误(如函数名拼写错误,将train_test_split写成train_test_split_)、路径错误(如默认路径./data/train/与实际存储路径不符)、库版本问题(如使用已废弃的函数参数,resnet50(pretrained=True)在 PyTorch 1.13 + 中已改为weights=ResNet50_Weights.DEFAULT),导致代码无法运行。

    8.1.2 解决方案
  • 方案 1:在提示词中补充 “版本与路径信息”。修改提示词为 “使用 PyTorch 2.0 版本,图像数据存储路径为‘D:/datasets/cats_dogs/train/’,生成代码时需适配 PyTorch 2.0 语法,避免使用废弃参数”;
  • 方案 2:要求大模型 “加入异常处理和版本说明”。提示词中加入 “代码需包含异常处理(如try-except捕获图像读取失败),在代码开头注明所需库的版本要求(如‘需安装 Pandas 1.5+、Scikit-learn 1.2+’)”;
  • 方案 3:生成后手动验证代码。拿到代码后,先检查函数名、参数、路径是否正确,再在小数据集上测试运行,发现错误后补充提示词 “修正代码中的路径错误,将‘./data/train/’改为‘D:/datasets/cats_dogs/train/’,并替换 ResNet50 的废弃参数”。
  • 8.1.3 预防措施
  • 提示词中明确 “库版本” 和 “数据路径”,避免大模型使用默认值;
  • 要求大模型 “生成代码前先说明依赖库的版本要求”,并在代码中加入注释(如 “# PyTorch 2.0 + 适用,旧版本需调整 weights 参数”)。
  • 8.2 问题 2:遗漏关键预处理步骤(如忘记处理类别不平衡、未做特征标准化)

    8.2.1 问题表现

    大模型生成的预处理步骤中遗漏关键环节:如表格数据存在严重类别不平衡(正样本占比 10%、负样本占比 90%),但未生成 “过采样(SMOTE)” 或 “欠采样” 步骤;用于逻辑回归模型的数值特征未做标准化处理,导致模型训练时受特征尺度影响,效果不佳。

    8.2.2 解决方案
  • 方案 1:在提示词中 “明确提及需处理的特殊问题”。修改提示词为 “表格数据存在类别不平衡(正样本占比 10%),预处理步骤需包含 SMOTE 过采样处理;数值特征需用 StandardScaler 做标准化,适配逻辑回归模型”;
  • 方案 2:要求大模型 “先分析数据问题,再生成步骤”。提示词中加入 “生成预处理步骤前,先分析数据集可能存在的问题(如缺失值、异常值、类别不平衡),确保每个问题都有对应处理步骤”;
  • 方案 3:补充提示词 “添加遗漏步骤”。若已生成步骤,发现遗漏后补充提示词 “补充类别不平衡处理步骤,使用 SMOTE 算法对训练集做过采样,确保正负样本比例接近 1:1”。
  • 8.2.3 预防措施
  • 提示词中 “主动列出数据集的所有已知问题”(如 “已知问题:缺失值、异常值、类别不平衡”),引导大模型针对性处理;
  • 要求大模型 “输出步骤前先列出‘预处理 Checklist’”,确保覆盖 “数据加载→清洗→特征工程→数据划分→模型适配” 全流程。
  • 8.3 问题 3:预处理步骤与模型输入不匹配(如维度错误、数据类型错误)

    8.3.1 问题表现

    大模型生成的预处理步骤输出格式与模型要求不匹配:如 BERT 模型需要 “input_ids(批量大小 × 最大长度)”,但生成的 token 序列长度不一致,导致无法批量输入;ResNet50 模型需要 “3 通道 RGB 图像”,但生成的预处理步骤将图像转为灰度图(1 通道),模型报错 “输入通道数不匹配”。

    8.3.2 解决方案
  • 方案 1:在提示词中 “明确模型的输入要求”。修改提示词为 “BERT 模型输入要求:input_ids 形状为(batch_size×32),数据类型为 torch.int64;ResNet50 输入要求:3 通道 RGB 图像,形状为(batch_size×3×224×224)”;
  • 方案 2:要求大模型 “生成后验证格式适配性”。提示词中加入 “生成预处理步骤后,需验证输出格式与模型输入的匹配性,如检查图像通道数、token 序列长度是否符合要求”;
  • 方案 3:补充 “格式转换步骤”。若已生成步骤,发现不匹配后补充提示词 “添加图像通道转换步骤,将灰度图转为 3 通道 RGB 图像(重复灰度通道 3 次),确保适配 ResNet50 的 3 通道输入”。
  • 8.3.3 预防措施
  • 提示词中 “将模型输入要求作为‘强制条件’”(如 “必须确保预处理后的图像为 3 通道 RGB,token 序列长度统一为 32”);
  • 要求大模型 “在代码中加入格式验证代码”(如 “添加 assert 语句,验证 input_ids 形状和数据类型是否符合模型要求”)。
  • 9. 工具推荐:辅助数据集预处理与提示词优化

    除了大模型,还有一些工具能辅助我们完成数据集预处理,或优化提示词,让生成的步骤更精准、更高效。下面推荐 4 个实用工具,覆盖 “数据探索”“代码调试”“提示词生成” 等场景。

    9.1 工具 1:Pandas Profiling(数据探索与问题识别)

    9.1.1 工具特点
  • 自动生成数据报告:输入表格数据集,能自动生成包含 “缺失值统计、异常值检测、特征相关性、类别分布” 的详细报告,帮助快速识别数据集问题(如缺失率、类别不平衡);
  • 支持多种数据类型:适配表格数据、时间序列数据,能识别数值型、类别型、文本型特征,无需手动分析;
  • 导出报告:可将报告导出为 HTML 格式,便于分享和存档,作为提示词中 “数据问题描述” 的依据。
  • 9.1.2 使用步骤
  • 安装工具:pip install ydata-profiling(原 Pandas Profiling,现更名为 ydata-profiling);
  • 生成报告:
  • 
      

    import pandas as pd

    from ydata_profiling import ProfileReport

    # 读取数据集

    df = pd.read_csv('titanic.csv')

    # 生成数据报告

    profile = ProfileReport(df, title="Titanic Dataset Report")

    # 导出为HTML报告

    profile.to_file("titanic_report.html")

  • 查看报告:打开 HTML 文件,提取 “缺失值比例”“异常值数量”“类别分布” 等信息,写入提示词,如 “Age 列缺失率 30%,Fare 列存在 15 个异常值,Survived 列类别分布为 60% 负样本、40% 正样本”。
  • 9.1.3 适用场景
  • 预处理前的 “数据探索”,快速识别数据集问题,为提示词提供精准的 “数据问题描述”;
  • 验证大模型生成的预处理步骤是否覆盖所有数据问题(如报告显示有类别不平衡,而大模型未生成处理步骤,需补充提示词)。
  • 9.2 工具 2:PyTorch DataLoader Debugger(数据加载调试)

    9.2.1 工具特点
  • 可视化数据加载过程:能实时显示 DataLoader 加载的批量数据形状、数据类型、标签分布,帮助排查 “批量大小错误”“通道数错误” 等问题;
  • 支持多类型数据:适配表格数据、图像数据、文本数据的 DataLoader,能显示不同数据类型的关键信息(如图像的通道数、文本的 token 长度);
  • 报错提示:若数据格式与模型输入不匹配(如维度错误),会自动给出错误原因和修正建议(如 “图像通道数为 1,建议转为 3 通道”)。
  • 9.2.2 使用步骤
  • 安装工具:pip install torch-dataloader-debugger;
  • 调试 DataLoader:
  • 
      

    from torch.utils.data import DataLoader

    from torch_dataloader_debugger import DataLoaderDebugger

    # 假设已创建train_dataset(图像数据集)

    train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)

    # 初始化调试器

    debugger = DataLoaderDebugger(train_loader)

    # 调试第一个批量

    debugger.debug_batch(0) # 查看第0个批量的信息

  • 查看结果:调试器会输出 “批量数据形状”“数据类型”“标签分布”,若存在问题(如 “图像通道数为 1”),会提示 “建议使用 transforms.Lambda (lambda x: x.repeat (3,1,1)) 转为 3 通道”。
  • 9.2.3 适用场景
  • 验证大模型生成的 DataLoader 代码是否正确,排查 “批量加载” 相关问题(如批量大小错误、数据类型不匹配);
  • 调试图像、文本数据的 DataLoader,确保输出格式与模型输入一致。
  • 9.3 工具 3:PromptBase(提示词模板生成)

    9.3.1 工具特点
  • 提供专业提示词模板:包含 “表格数据预处理”“文本数据预处理”“图像数据预处理” 等场景的现成提示词模板,可直接修改细节后使用;
  • 适配不同大模型:模板区分 “ChatGPT”“文心一言”“通义千问” 等大模型的特性,生成适配不同模型的提示词(如 ChatGPT 支持复杂指令,文心一言需简化表述);
  • 优化提示词结构:模板按 “数据描述→目标→工具→格式” 的逻辑组织提示词,确保包含所有核心要素,提升大模型生成结果的质量。
  • 9.3.2 使用步骤
  • 访问官网:打开 PromptBase(https://www.promptbase.com/),搜索 “machine learning dataset preprocessing”;
  • 选择模板:选择 “Table Data Preprocessing for Logistic Regression” 模板;
  • 修改细节:将模板中的 “数据描述”“工具要求” 替换为自己的需求,如 “数据描述:泰坦尼克号数据集,Age 列缺失率 30%;工具要求:使用 Pandas、Scikit-learn”;
  • 生成提示词:复制修改后的模板,粘贴到大模型对话框,生成预处理步骤。
  • 9.3.3 适用场景
  • 不熟悉提示词编写的新手,通过模板快速生成高质量提示词;
  • 针对特殊场景(如时间序列数据预处理),查找专业模板,避免遗漏关键步骤。
  • 9.4 工具 4:CodeLlama(代码生成与优化)

    9.4.1 工具特点
  • 专业代码生成:专注于生成和优化代码,能根据 “数据类型” 和 “预处理目标” 生成可运行的 Python 代码,代码风格规范,注释详细;
  • 支持代码优化:若大模型生成的代码存在冗余或错误,可将代码输入 CodeLlama,要求 “优化代码结构”“修复语法错误”“添加异常处理”;
  • 适配机器学习库:对 Pandas、Scikit-learn、PyTorch 等机器学习库的函数熟悉,能生成符合库语法和最佳实践的代码。
  • 9.4.2 使用步骤
  • 访问平台:打开 CodeLlama 在线平台(如 Hugging Face Spaces);
  • 输入需求:输入 “生成泰坦尼克号数据集的预处理代码,使用 Pandas 处理缺失值,Scikit-learn 做特征编码和标准化,用于逻辑回归模型”;
  • 生成与优化:CodeLlama 生成代码后,若发现 “未处理异常值”,补充输入 “优化代码,添加 Fare 列的异常值处理(IQR 方法)”;
  • 验证代码:将优化后的代码复制到本地,测试运行,确保无错误。
  • 9.4.3 适用场景
  • 对代码质量要求高的场景(如生产环境的预处理代码),通过 CodeLlama 优化代码结构和稳定性;
  • 修正大模型生成的错误代码,补充异常处理、注释等细节,提升代码可维护性。
  • 10. 扩展:处理特殊数据集的提示词编写

    除了常见的表格、文本、图像数据,实际工作中还可能遇到特殊数据集(如时间序列数据、多模态数据)。下面针对这两类特殊数据,给出提示词编写示例和预处理步骤生成思路,帮助大家应对复杂场景。

    10.1 特殊场景 1:时间序列数据(如股票价格预测)

    10.1.1 数据特点
  • 包含时间戳:数据按时间顺序排列,需保留时间维度(如 “2024-01-01 的股票收盘价”);
  • 存在趋势和周期性:数据可能有长期趋势(如股票价格上涨)和周期性(如每日交易量波动);
  • 预处理重点:时间戳格式统一、缺失值插值(不能直接删除,避免破坏时间连续性)、特征工程(如滑动窗口特征、时间差特征)。
  • 10.1.2 提示词示例

    “请帮我生成股票价格时间序列数据集的预处理步骤,具体要求如下:

  • 数据背景:CSV 格式时间序列数据,包含‘timestamp’(时间戳,格式为‘2024-01-01 09:30’)、‘close_price’(收盘价,数值型)、‘volume’(交易量,数值型),共 1000 条记录,已知问题:timestamp 格式不统一(部分为‘2024/01/01’)、close_price 列有 5% 的缺失值、无时间相关特征;
  • 预处理目标:处理后用于 LSTM 模型做股票收盘价预测(回归任务),要求输出‘时间序列特征矩阵 + 未来 1 天收盘价标签’;
  • 工具要求:使用 Pandas、NumPy、Scikit-learn,需包含时间戳处理、缺失值插值、滑动窗口特征工程;
  • 输出格式:分‘1. 时间戳处理、2. 缺失值插值、3. 特征工程、4. 数据划分(按时间顺序)、5. 模型输入格式转换’五个模块,每个模块附带 Python 代码和注释。”
  • 10.1.3 预处理步骤生成思路

    大模型会基于提示词生成以下核心步骤:

  • 时间戳处理:将不同格式的 timestamp 统一转为 “YYYY-MM-DD HH:MM” 格式,设为 DataFrame 的索引;
  • 缺失值插值:用 “线性插值”(interpolate (method='linear'))填充 close_price 的缺失值,保留时间连续性;
  • 特征工程:生成滑动窗口特征(如过去 5 天的收盘价均值)、时间差特征(如与前 1 天收盘价的差值);
  • 数据划分:按时间顺序划分(如前 800 条为训练集,后 200 条为测试集),避免数据泄露;
  • 格式转换:将时间序列数据转为 LSTM 输入格式(样本数 × 时间步 × 特征数),如 “每个样本包含过去 5 天的特征,预测第 6 天的收盘价”。
  • 10.2 特殊场景 2:多模态数据(如 “图像 + 文本” 商品数据)

    10.2.1 数据特点
  • 包含多种类型数据:如商品数据同时包含 “商品图像” 和 “商品描述文本”,需分别处理不同模态数据;
  • 模态融合需求:预处理后需将不同模态的特征融合(如将图像的 CNN 特征与文本的 BERT 特征拼接),用于后续模型训练(如商品分类、销量预测);
  • 数据关联性:不同模态数据属于同一对象(如 “某件衣服的图像” 和 “这件衣服的描述文本”),预处理时需确保模态间的对应关系不被破坏。
  • 10.2.2 提示词示例

    “请帮我生成‘商品图像 + 描述文本’多模态数据集的预处理步骤,具体要求如下:

  • 数据背景:多模态数据包含两部分 ——① 商品图像(JPG 格式,存于‘./goods/images/’,每张图像文件名对应商品 ID,如‘1001.jpg’);② 商品描述文本(CSV 格式,含‘goods_id’‘description’‘category’三列,‘goods_id’与图像文件名对应),共 5000 条样本,已知问题:图像尺寸不一致(100×100 至 500×500 像素)、文本含特殊符号、部分样本图像与文本对应关系缺失;
  • 预处理目标:处理后用于多模态商品分类模型(如 CLIP 微调),要求输出‘图像特征(ResNet50 提取)+ 文本特征(BERT 提取)+ 类别标签’的融合格式;
  • 工具要求:使用 OpenCV、torchvision(图像处理)、transformers(文本处理)、PyTorch;
  • 输出格式:分‘1. 模态数据关联与清洗、2. 图像模态预处理、3. 文本模态预处理、4. 模态特征提取与融合、5. 数据划分’五个模块,每个模块附带 Python 代码和注释,确保模态对应关系不破坏。”
  • 10.2.3 预处理步骤生成思路

    大模型会基于提示词生成以下核心步骤:

  • 模态数据关联与清洗:① 按 “goods_id” 匹配图像和文本,删除无对应图像或文本的样本;② 记录匹配后的样本列表,确保后续预处理中模态对应关系不变;
  • 图像模态预处理:① 统一图像尺寸为 224×224 像素;② 用 ResNet50(预训练)提取图像特征(输出 2048 维向量);③ 对特征做 L2 归一化;
  • 文本模态预处理:① 清洗文本特殊符号,去除停用词;② 用 BERT(bert-base-chinese)提取文本特征(取 [CLS] token 的输出,768 维向量);③ 对特征做 L2 归一化;
  • 模态特征融合:① 将图像特征(2048 维)与文本特征(768 维)拼接,生成 2816 维的多模态融合特征;② 为融合特征添加对应的类别标签(‘category’列);
  • 数据划分:按 “8:2” 比例划分训练集和测试集,确保划分后各模态数据仍一一对应(如训练集中的某条融合特征,其原始图像和文本仍属于训练集)。
  • 11. 不同场景提示词模板总结

    为了让大家在实际工作中快速编写提示词,下面按 “表格数据、文本数据、图像数据、时间序列数据、多模态数据” 五类场景,总结通用提示词模板。每个模板包含 “核心要素” 和 “模板框架”,可直接修改细节后使用。

    11.1 模板 1:表格数据预处理(适配逻辑回归 / 随机森林等模型)

    11.1.1 核心要素
  • 数据描述:特征类型(数值 / 类别)、缺失率、异常值位置、无关特征;
  • 目标模型:逻辑回归 / 随机森林(需明确是否需标准化、编码);
  • 工具:Pandas、Scikit-learn。
  • 11.1.2 模板框架

    “请帮我生成 [数据集名称,如:泰坦尼克号] 表格数据集的预处理步骤,具体要求如下:

  • 数据背景:CSV 格式表格数据,共 [样本数,如:891] 条样本,[特征数,如:12] 个特征,其中 [数值特征列表,如:Age、Fare] 为数值型,[类别特征列表,如:Sex、Embarked] 为类别型;已知问题:[问题列表,如:Age 列缺失率 30%、Fare 列有异常值、Name 为无关特征];
  • 预处理目标:处理后用于 [模型名称,如:逻辑回归] 模型做 [任务类型,如:二分类(Survived 为标签)],要求特征均为数值型,[是否需标准化,如:需用 StandardScaler 标准化];
  • 工具要求:使用 Pandas、Scikit-learn;
  • 输出格式:分‘1. 数据加载、2. 数据清洗(缺失值 + 异常值 + 无关特征删除)、3. 特征工程(编码 + 标准化)、4. 数据划分、5. 模型输入验证’五个模块,每个模块按‘步骤编号 + 名称 + 操作 + 代码’呈现,代码加详细注释。”
  • 11.2 模板 2:文本数据预处理(适配 BERT/Transformer 模型)

    11.2.1 核心要素
  • 数据描述:文本格式(TXT/CSV)、长度范围、特殊符号 / 错别字情况;
  • 目标模型:BERT/Transformer(需明确 token 长度、特征类型);
  • 工具:Pandas、transformers、NLTK。
  • 11.2.2 模板框架

    “请帮我生成 [数据集名称,如:客户评论] 文本数据集的预处理步骤,具体要求如下:

  • 数据背景:[文本格式,如:TXT 格式,每行一条文本 + 标签(用 \t 分隔)],共 [样本数,如:1000] 条样本,文本长度 [长度范围,如:10-50 字],已知问题:[问题列表,如:含!@# 等特殊符号、有 “好佣→好用” 等错别字、未分词];
  • 预处理目标:处理后用于 [模型名称,如:BERT(bert-base-chinese)] 模型做 [任务类型,如:情感二分类],要求输出‘input_ids+attention_mask+token_type_ids + 标签’的 BERT 输入格式,token 最大长度 [长度,如:32];
  • 工具要求:使用 Pandas、transformers(BERT 分词器)、NLTK(停用词处理);
  • 输出格式:分‘1. 文本加载、2. 文本清洗(特殊符号 + 错别字 + 停用词)、3. 分词与向量转换、4. 数据划分、5.DataLoader 封装’五个模块,每个模块按‘步骤编号 + 名称 + 操作 + 代码’呈现,代码需适配 PyTorch 张量格式。”
  • 11.3 模板 3:图像数据预处理(适配 CNN/ResNet 模型)

    11.3.1 核心要素
  • 数据描述:图像格式(JPG/PNG)、尺寸范围、通道数(RGB / 灰度)、特殊问题(旋转 / 模糊);
  • 目标模型:CNN/ResNet(需明确输入尺寸、是否需数据增强);
  • 工具:OpenCV、torchvision、PyTorch。
  • 11.3.2 模板框架

    “请帮我生成 [数据集名称,如:猫狗分类] 图像数据集的预处理步骤,具体要求如下:

  • 数据背景:[存储方式,如:按类别存于文件夹(train/cat/、train/dog/)],图像格式 [格式,如:JPG],尺寸 [尺寸范围,如:200×200 至 500×500 像素],通道数 [通道,如:RGB],已知问题:[问题列表,如:部分图像旋转 90°、少量图像模糊、尺寸不一致];
  • 预处理目标:处理后用于 [模型名称,如:ResNet50] 模型做 [任务类型,如:二分类],要求输出‘图像张量(3×224×224)+ 标签’,训练集需做数据增强;
  • 工具要求:使用 OpenCV、torchvision(transforms)、PyTorch;
  • 输出格式:分‘1. 图像加载与可视化、2. 图像预处理(尺寸统一 + 转正 + 去模糊)、3. 训练集数据增强、4. 数据集封装(Dataset+DataLoader)、5. 模型输入验证’五个模块,每个模块按‘步骤编号 + 名称 + 操作 + 代码’呈现,代码需包含异常处理(如图像读取失败)。”
  • 11.4 模板 4:时间序列数据预处理(适配 LSTM/Transformer 模型)

    11.4.1 核心要素
  • 数据描述:时间戳格式、时序特征、缺失情况、趋势 / 周期性;
  • 目标模型:LSTM / 时序 Transformer(需明确时间步、输入维度);
  • 工具:Pandas、NumPy、PyTorch。
  • 11.4.2 模板框架

    “请帮我生成 [数据集名称,如:股票价格] 时间序列数据集的预处理步骤,具体要求如下:

  • 数据背景:CSV 格式,含 [列名,如:timestamp、close_price、volume] 列,共 [样本数,如:1000] 条记录,时间戳格式 [格式,如:部分为 “2024-01-01”,部分为 “2024/01/01”],已知问题:[问题列表,如:close_price 列缺失率 5%、无滑动窗口特征、时间顺序未确认];
  • 预处理目标:处理后用于 [模型名称,如:LSTM] 模型做 [任务类型,如:未来 1 天收盘价预测(回归)],要求输出‘时序特征矩阵(样本数 × 时间步 × 特征数)+ 标签’,时间步设为 [步长,如:5](用过去 5 天数据预测未来 1 天);
  • 工具要求:使用 Pandas、NumPy、PyTorch;
  • 输出格式:分‘1. 时间戳处理与排序、2. 缺失值插值、3. 时序特征工程(滑动窗口 + 时间差)、4. 数据划分(按时间顺序)、5. 时序格式转换(适配 LSTM)’五个模块,每个模块按‘步骤编号 + 名称 + 操作 + 代码’呈现,代码需确保时间顺序不打乱。”
  • 11.5 模板 5:多模态数据预处理(适配 CLIP / 多模态 Transformer)

    11.5.1 核心要素
  • 数据描述:各模态类型(如图像 + 文本)、模态关联方式(如 ID 匹配)、各模态问题;
  • 目标模型:CLIP / 多模态 Transformer(需明确特征融合方式);
  • 工具:OpenCV、transformers、PyTorch。
  • 11.5.2 模板框架

    “请帮我生成 [数据集名称,如:商品多模态] 数据的预处理步骤,具体要求如下:

  • 数据背景:含 [模态列表,如:① 商品图像(JPG,存于‘./images/’,文件名对应 goods_id);② 商品文本(CSV 含 goods_id、description 列)],共 [样本数,如:5000] 条样本,已知问题:[问题列表,如:部分样本模态对应关系缺失、图像尺寸不一致、文本含特殊符号];
  • 预处理目标:处理后用于 [模型名称,如:CLIP 微调] 做 [任务类型,如:商品分类],要求输出‘图像特征(ResNet 提取)+ 文本特征(BERT 提取)+ 类别标签’的融合格式,特征维度需统一;
  • 工具要求:使用 OpenCV、torchvision、transformers、PyTorch;
  • 输出格式:分‘1. 模态关联与清洗、2. 各模态单独预处理、3. 模态特征提取、4. 特征融合(如拼接 + 归一化)、5. 数据划分’五个模块,每个模块按‘步骤编号 + 名称 + 操作 + 代码’呈现,代码需确保模态对应关系不破坏。”
  • 12. 如何根据实际需求调整提示词

    前面的模板和案例提供了通用思路,但实际工作中的数据集可能存在特殊情况(如混合数据类型、特殊业务逻辑),需要根据需求灵活调整提示词。下面给出 3 个调整方向,帮助大家适配具体场景。

    12.1 方向 1:补充 “业务逻辑约束”

    若数据集涉及特殊业务规则(如 “电商订单数据中,退款订单需排除”“医疗数据中,隐私字段需脱敏”),需在提示词中补充业务约束,避免预处理后的数据不符合业务要求。

    示例调整:在电商订单表格数据的提示词中加入 “业务约束:① 排除‘order_status’为‘退款’的订单;② 对‘user_phone’字段做脱敏处理(保留前 3 位和后 4 位,中间用代替,如‘138***5678’)”。

    12.2 方向 2:调整 “预处理颗粒度”

    根据需求的精细程度,调整提示词中预处理步骤的颗粒度:

  • 若需求简单(如快速验证模型效果),可要求 “简化预处理步骤,如缺失值用均值填充,不做异常值复杂处理”;
  • 若需求严谨(如生产环境模型),需要求 “细化预处理步骤,如异常值区分‘极端异常’和‘轻微异常’,分别用 IQR 上限和均值填充”。
  • 示例调整:在医疗表格数据的提示词中加入 “预处理颗粒度:需细化缺失值处理 ——① 关键医疗指标(如‘blood_pressure’)用中位数填充;② 非关键字段(如‘patient_address’)用‘未知’填充;异常值需先标注再处理,保留标注记录用于后续分析”。

    12.3 方向 3:适配 “特殊工具库”

    若实际工作中需使用特殊工具库(如 “用 DALI 加速图像加载”“用 FastText 处理文本”),需在提示词中指定工具库,避免大模型生成通用工具的代码,导致后续适配成本高。

    示例调整:在图像数据预处理的提示词中加入 “工具要求:使用 NVIDIA DALI 库加速图像加载和预处理,替代 OpenCV 的传统读取方式,代码需符合 DALI 的流水线语法(如 dali.pipeline.Pipeline)”。

    13. 验证预处理效果的 3 个关键指标

    生成预处理步骤并执行后,需验证处理效果是否符合预期,避免因预处理不当影响模型性能。下面介绍 3 个关键验证指标,适用于所有数据类型。

    13.1 指标 1:数据完整性

  • 验证内容:① 预处理后样本数与预期是否一致(如 “原始 5000 条样本,清洗后应保留≥4500 条”);② 特征数是否符合需求(如 “删除无关特征后,应保留 8 个特征”);③ 无新的缺失值产生(如 “填充后各列缺失值为 0”);
  • 验证方法:用 Pandas 的shape查看样本数和特征数,isnull().sum()查看缺失值;
  • 合格标准:样本保留率≥90%(无特殊业务要求时),特征数与需求一致,无新缺失值。
  • 13.2 指标 2:格式适配性

  • 验证内容:① 数据格式是否符合模型输入要求(如 “LSTM 输入需为 3 维张量(样本数 × 时间步 × 特征数)”);② 数据类型是否正确(如 “标签需为 torch.int64 类型”);③ 特征尺度是否符合要求(如 “标准化后特征均值≈0,标准差≈1”);
  • 验证方法:用type()查看数据类型,shape查看维度,np.mean()和np.std()查看特征尺度;
  • 合格标准:格式、类型、尺度完全匹配模型输入要求,无维度错误或类型报错。
  • 13.3 指标 3:业务合理性

  • 验证内容:① 预处理后的数据是否符合业务逻辑(如 “电商订单金额预处理后不应为负数”“医疗指标值应在合理范围,如‘blood_pressure’为 60-180 mmHg”);② 模态数据对应关系是否正确(如 “多模态数据中,某商品的图像特征应与该商品的文本特征对应”);
  • 验证方法:① 用np.min()和np.max()查看数值范围;② 随机抽取 10-20 条样本,人工核对模态对应关系;
  • 合格标准:所有数据符合业务逻辑范围,模态对应关系无错误,人工核对通过率 100%。
  • 14. 实战补充:预处理代码的复用与优化

    生成预处理代码后,可通过 “模块化封装” 和 “参数化配置” 提升代码复用性,避免每次处理类似数据都重新生成代码。下面给出通用的预处理代码封装示例,基于前面的案例优化而来。

    14.1 表格数据预处理代码封装(函数形式)

    
      

    import pandas as pd

    import numpy as np

    from sklearn.preprocessing import LabelEncoder, StandardScaler

    from sklearn.model_selection import train_test_split

    def preprocess_table_data(

    data_path, # 数据路径

    label_col, # 标签列名

    drop_cols, # 需删除的无关特征列

    num_cols, # 数值特征列名列表

    cat_cols, </doubaocanvas>

    fill_num_method='median', # 数值特征缺失值填充方法(median/mean)

    encode_cat_method='label', # 类别特征编码方法(label/onehot)

    need_scale=True, # 是否需要特征标准化

    test_size=0.3, # 测试集比例

    random_state=42 # 随机种子

    ):

    """

    表格数据预处理函数,适配逻辑回归、随机森林等模型

    参数说明:

  • data_path: CSV 数据文件路径
  • label_col: 标签列名称
  • drop_cols: 需删除的无关特征列表(如 ['Name', 'Ticket'])
  • num_cols: 数值特征列表(如 ['Age', 'Fare'])
  • cat_cols: 类别特征列表(如 ['Sex', 'Embarked'])
  • fill_num_method: 数值特征缺失值填充方法,'median'(中位数)或 'mean'(均值)
  • encode_cat_method: 类别特征编码方法,'label'(标签编码)或 'onehot'(独热编码)
  • need_scale: 是否对数值特征做标准化(逻辑回归需 True,随机森林可 False)
  • test_size: 测试集占比
  • random_state: 随机种子,确保结果可复现
  • 返回:

  • X_train_scaled/X_train: 训练集特征(标准化 / 原始)
  • X_test_scaled/X_test: 测试集特征(标准化 / 原始)
  • y_train: 训练集标签
  • y_test: 测试集标签
  • scaler: 标准化器(若 need_scale=True),用于后续新数据处理
  • """

    1. 数据加载

    df = pd.read_csv (data_path)

    print (f"原始数据形状:{df.shape}")

    2. 数据清洗

    2.1 删除无关特征

    df_clean = df.drop(drop_cols, axis=1)

    2.2 处理数值特征缺失值

    for col in num_cols:

    if df_clean [col].isnull ().sum () > 0:

    if fill_num_method == 'median':

    fill_val = df_clean [col].median ()

    else: # mean

    fill_val = df_clean [col].mean ()

    df_clean [col] = df_clean [col].fillna (fill_val)

    print (f"{col} 列缺失值用 {fill_num_method}({fill_val:.2f})填充")

    2.3 处理类别特征缺失值(用众数填充)

    for col in cat_cols:

    if df_clean [col].isnull ().sum () > 0:

    mode_val = df_clean [col].mode ()[0]

    df_clean [col] = df_clean [col].fillna (mode_val)

    print (f"{col} 列缺失值用众数({mode_val})填充")

    2.4 处理异常值(IQR 方法,仅对数值特征)

    for col in num_cols:

    Q1 = df_clean[col].quantile(0.25)

    Q3 = df_clean[col].quantile(0.75)

    IQR = Q3 - Q1

    upper_bound = Q3 + 1.5 * IQR

    lower_bound = Q1 - 1.5 * IQR

    替换异常值(避免删除样本)

    df_clean [col] = np.where (df_clean [col] > upper_bound, upper_bound, df_clean [col])

    df_clean [col] = np.where (df_clean [col] < lower_bound, lower_bound, df_clean [col])

    print (f"数据清洗后形状:{df_clean.shape}")

    3. 特征工程

    3.1 类别特征编码

    df_encoded = df_clean.copy()

    if encode_cat_method == 'label':

    标签编码(适用于二分类或有序类别特征)

    label_encoders = {}

    for col in cat_cols:

    le = LabelEncoder ()

    df_encoded [col] = le.fit_transform (df_encoded [col])

    label_encoders [col] = le # 保存编码器,用于后续新数据

    print (f"{col} 列标签编码完成,类别映射:{dict (zip (le.classes_, le.transform (le.classes_)))}")

    else: # onehot 编码(适用于无序多分类特征)

    独热编码,避免多重共线性(drop_first=True)

    onehot_df = pd.get_dummies(df_encoded[cat_cols], prefix=cat_cols, drop_first=True)

    删除原类别列,合并独热编码列

    df_encoded = df_encoded.drop (cat_cols, axis=1)

    df_encoded = pd.concat ([df_encoded, onehot_df], axis=1)

    print (f"类别特征独热编码完成,新增特征数:{len (onehot_df.columns)}")

    3.2 分离特征与标签

    X = df_encoded.drop (label_col, axis=1)

    y = df_encoded [label_col]

    print (f"特征矩阵形状:{X.shape},标签向量形状:{y.shape}")

    3.3 特征标准化(仅数值特征,若 need_scale=True)

    scaler = None

    if need_scale:

    scaler = StandardScaler()

    仅对数值特征做标准化(类别特征已编码,无需标准化)

    X_num = X[num_cols]

    X_non_num = X.drop(num_cols, axis=1) if len(X.columns) > len(num_cols) else pd.DataFrame()

    训练集标准化

    X_num_scaled = scaler.fit_transform(X_num)

    X_num_scaled_df = pd.DataFrame(X_num_scaled, columns=num_cols, index=X.index)

    合并标准化后的数值特征与非数值特征(如编码后的类别特征)

    if not X_non_num.empty:

    X_scaled = pd.concat ([X_num_scaled_df, X_non_num], axis=1)

    else:

    X_scaled = X_num_scaled_df

    print ("特征标准化完成(基于训练集均值和标准差)")

    else:

    X_scaled = X

    print ("无需特征标准化")

    4. 数据划分

    X_train, X_test, y_train, y_test = train_test_split (

    X_scaled, y, test_size=test_size, random_state=random_state, stratify=y

    )

    print (f"数据划分完成:")

    print (f"- 训练集:{X_train.shape [0]} 条样本,{X_train.shape [1]} 个特征")

    print (f"- 测试集:{X_test.shape [0]} 条样本,{X_test.shape [1]} 个特征")

    print (f"- 训练集标签分布:{y_train.value_counts (normalize=True).round (2)}")

    print (f"- 测试集标签分布:{y_test.value_counts (normalize=True).round (2)}")

    返回结果(根据是否标准化返回对应特征)

    if need_scale:

    return X_train, X_test, y_train, y_test, scaler

    else:

    return X_train, X_test, y_train, y_test, None

    函数调用示例(泰坦尼克号数据集)

    if name == "main":

    X_train, X_test, y_train, y_test, scaler = preprocess_table_data(

    data_path='titanic.csv',

    label_col='Survived',

    drop_cols=['Name', 'Ticket', 'Cabin'],

    num_cols=['Age', 'Fare', 'SibSp', 'Parch'],

    cat_cols=['Sex', 'Embarked'],

    fill_num_method='median',

    encode_cat_method='label',

    need_scale=True,

    test_size=0.3,

    random_state=42

    )

    后续可直接用 X_train、y_train 训练模型

    新数据预处理时,可复用 scaler:new_X_scaled = scaler.transform (new_X_num)

    
      

    ### 14.2 图像数据预处理代码封装(类形式)

    ```python

    import os

    import cv2

    import torch

    from PIL import Image

    from torch.utils.data import Dataset, DataLoader

    from torchvision import transforms

    from torchvision.models import resnet50, ResNet50_Weights

    class ImagePreprocessor:

    def __init__(

    self,

    data_dir, # 图像数据根目录(下含类别子文件夹,如train/cat/)

    img_size=(224, 224), # 统一图像尺寸

    num_classes=2, # 类别数(如猫狗分类为2)

    batch_size=32, # 批量大小

    num_workers=2 # 多线程加载数

    ):

    """

    图像数据预处理类,适配CNN、ResNet等模型

    参数说明:

    - data_dir: 数据根目录(如'train/',下含类别子文件夹)

    - img_size: 统一后的图像尺寸(高×宽)

    - num_classes: 类别数量

    - batch_size: DataLoader批量大小

    - num_workers: 数据加载线程数

    """

    self.data_dir = data_dir

    self.img_size = img_size

    self.num_classes = num_classes

    self.batch_size = batch_size

    self.num_workers = num_workers

    # 初始化类别映射(子文件夹名称→标签)

    self.class_map = self._get_class_map()

    print(f"类别映射:{self.class_map}")

    def _get_class_map(self):

    """获取类别映射(子文件夹名称→0,1,...)"""

    class_names = sorted([d for d in os.listdir(self.data_dir) if os.path.isdir(os.path.join(self.data_dir, d))])

    return {cls: idx for idx, cls in enumerate(class_names)}

    def _fix_special_images(self, img_path):

    """处理特殊图像(旋转、模糊)"""

    # 读取图像(BGR→RGB)

    img_bgr = cv2.imread(img_path)

    if img_bgr is None:

    raise ValueError(f"图像读取失败:{img_path}")

    img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)

    # 旋转修正(高度远大于宽度则顺时针旋转90°)

    height, width = img_rgb.shape[:2]

    if height > width * 1.2:

    img_rgb = cv2.rotate(img_rgb, cv2.ROTATE_90_CLOCKWISE)

    # 模糊处理(拉普拉斯方差<50判定为模糊,轻度高斯模糊)

    gray = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2GRAY)

    blur_score = cv2.Laplacian(gray, cv2.CV_64F).var()

    if blur_score < 50:

    img_rgb = cv2.GaussianBlur(img_rgb, (3, 3), 0)

    # 转为PIL图像(适配torchvision.transforms)

    return Image.fromarray(img_rgb)

    def get_transforms(self, is_train=True):

    """获取预处理流水线(训练集含增强,测试集无)"""

    if is_train:

    # 训练集:增强+基础预处理

    return transforms.Compose([

    transforms.Lambda(lambda x: self._fix_special_images(x)), # 处理特殊图像

    transforms.RandomResizedCrop(self.img_size, scale=(0.8, 1.0)), # 随机裁剪

    transforms.RandomHorizontalFlip(p=0.5), # 随机水平翻转

    transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2), # 颜色抖动

    transforms.ToTensor(), # 转为张量(0-1)

    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # 标准化

    ])

    else:

    # 测试集:仅基础预处理

    return transforms.Compose([

    transforms.Lambda(lambda x: self._fix_special_images(x)),

    transforms.Resize(self.img_size),

    transforms.ToTensor(),

    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])

    ])

    def create_dataset(self, is_train=True):

    """创建Dataset实例"""

    transform = self.get_transforms(is_train)

    # 自定义Dataset(适配图像路径→标签→预处理流程)

    class CustomImageDataset(Dataset):

    def __init__(self, data_dir, class_map, transform):

    self.data_dir = data_dir

    self.class_map = class_map

    self.transform = transform

    self.img_paths = self._get_img_paths()

    def _get_img_paths(self):

    """获取所有图像路径和标签"""

    img_paths = []

    for cls, label in self.class_map.items():

    cls_dir = os.path.join(self.data_dir, cls)

    for img_name in os.listdir(cls_dir):

    if img_name.lower().endswith(('.jpg', '.png')):

    img_path = os.path.join(cls_dir, img_name)

    img_paths.append((img_path, label))

    return img_paths

    def __len__(self):

    return len(self.img_paths)

    def __getitem__(self, idx):

    img_path, label = self.img_paths[idx]

    # 应用预处理(含特殊图像修复)

    img = self.transform(img_path)

    return img, torch.tensor(label, dtype=torch.int64)

    return CustomImageDataset(self.data_dir, self.class_map, transform)

    def create_dataloader(self, is_train=True):

    """创建DataLoader(批量加载)"""

    dataset = self.create_dataset(is_train)

    return DataLoader(

    dataset,

    batch_size=self.batch_size,

    shuffle=is_train,

    num_workers=self.num_workers,

    pin_memory=True # 加速GPU传输

    )

    def extract_image_features(self, img_path, use_pretrained=True):

    """用预训练ResNet50提取单张图像特征(用于多模态融合等场景)"""

    # 加载预训练ResNet50(仅特征提取,冻结权重)

    if use_pretrained:

    weights = ResNet50_Weights.DEFAULT

    model = resnet50(weights=weights)

    else:

    model = resnet50(num_classes=self.num_classes)

    # 移除最后一层全连接层,保留特征提取部分

    feature_extractor = torch.nn.Sequential(*list(model.children())[:-1])

    feature_extractor.eval() # 评估模式

    # 图像预处理(与测试集一致)

    img = self._fix_special_images(img_path)

    transform = transforms.Compose([

    transforms.Resize(self.img_size),

    transforms.ToTensor(),

    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])

    ])

    img_tensor = transform(img).unsqueeze(0) # 增加批量维度(1×3×H×W)

    # 提取特征(禁用梯度计算)

    with torch.no_grad():

    features = feature_extractor(img_tensor)

    features = torch.flatten(features, 1) # 展平为1×2048维特征

    features = torch.nn.functional.normalize(features, p=2, dim=1) # L2归一化

    return features.numpy() # 返回numpy数组(便于后续融合)

    # 类调用示例(猫狗分类数据集)

    if __name__ == "__main__":

    # 初始化预处理类

    img_preprocessor = ImagePreprocessor(

    data_dir='./data/train/',

    img_size=(224, 224),

    num_classes=2,

    batch_size=32,

    num_workers=2

    )

    # 创建训练集和测试集DataLoader

    train_loader = img_preprocessor.create_dataloader(is_train=True)

    test_loader = img_preprocessor.create_dataloader(is_train=False)

    print(f"训练集DataLoader批量数:{len(train_loader)}")

    print(f"测试集DataLoader批量数:{len(test_loader)}")

    # 提取单张图像特征(用于多模态融合)

    sample_img_path = './data/train/cat/001.jpg'

    img_features = img_preprocessor.extract_image_features(sample_img_path)

    print(f"单张图像特征维度:{img_features.shape}(2048维,ResNet50提取)")

    14.3 文本数据预处理代码封装(函数 + 类结合)

    
      

    </doubaocanvas>

    import pandas as pd

    import re

    import torch

    import nltk

    from nltk.corpus import stopwords

    from torch.utils.data import Dataset, DataLoader

    from transformers import BertTokenizer

    下载 NLTK 停用词库(首次使用需执行)

    nltk.download('stopwords')

    def init_text_utils ():

    """初始化文本处理工具(停用词、错别字映射)"""

    中文停用词(NLTK 基础停用词 + 自定义补充)

    base_stopwords = stopwords.words ('chinese')

    custom_stopwords = [' 的 ', ' 了 ', ' 在 ', ' 是 ', ' 我 ', ' 这 ', ' 很 ', ' 非常 ', ' 也 ', ' 还 ', ' 就 ', ' 都 ']

    all_stopwords = set (base_stopwords + custom_stopwords)

    常见错别字映射(可根据实际数据扩展)

    typo_map = {

    ' 好佣 ': ' 好用 ',

    ' 推存 ': ' 推荐 ',

    ' 物超所值 ': ' 物超所值 ',

    ' 不的了 ': ' 不得了 ',

    ' 非常满义 ': ' 非常满意 ',

    ' 没毛病 ': ' 没毛病 ',

    ' 质量很好 ': ' 质量很好 '

    }

    return all_stopwords, typo_map

    初始化文本处理工具

    STOPWORDS, TYPO_MAP = init_text_utils()

    class TextPreprocessor:

    def init(

    self,

    bert_model_name='bert-base-chinese', # BERT 模型名称

    max_seq_len=32, # 文本最大长度(适配 BERT 输入)

    batch_size=16, # DataLoader 批量大小

    num_workers=2 # 多线程加载数

    ):

    """

    文本数据预处理类,适配 BERT、Transformer 等模型

    参数说明:

  • bert_model_name: BERT 分词器对应的模型名称
  • max_seq_len: 文本最大序列长度(超过截断,不足填充)
  • batch_size: DataLoader 批量大小
  • num_workers: 数据加载线程数
  • """

    self.bert_model_name = bert_model_name

    self.max_seq_len = max_seq_len

    self.batch_size = batch_size

    self.num_workers = num_workers

    初始化 BERT 分词器

    self.tokenizer = BertTokenizer.from_pretrained (bert_model_name)

    print (f"BERT 分词器加载完成,词汇表大小:{self.tokenizer.vocab_size}")

    def clean_text (self, text):

    """文本清洗:去除特殊符号、纠正常见错别字、去除停用词"""

    1. 去除特殊符号和数字(仅保留中文字符)

    text = re.sub(r'[^\u4e00-\u9fa5]', '', text)

    2. 纠正常见错别字

    for typo, correct in TYPO_MAP.items():

    text = text.replace(typo, correct)

    3. 去除停用词(按字分割)

    chars = [c for c in text if c not in STOPWORDS]

    text_clean = ''.join(chars)

    4. 过滤过短文本(长度 < 2 字无有效信息)

    return text_clean if len(text_clean) >= 2 else ''

    def load_and_clean_data (self, data_path, text_col, label_col, label_map):

    """

    加载文本数据并完成清洗

    参数:

  • data_path: CSV/TXT 数据路径(TXT 需用 \t 分隔文本和标签)
  • text_col: 文本列名称(CSV)或索引(TXT 设为 0)
  • label_col: 标签列名称(CSV)或索引(TXT 设为 1)
  • label_map: 标签映射字典(如 {' 正面 ':1, ' 负面 ':0})
  • 返回:

  • df_clean: 清洗后的 DataFrame(含 'text_clean' 和 'label_num' 列)
  • """

    加载数据(区分 CSV 和 TXT 格式)

    if data_path.endswith ('.csv'):

    df = pd.read_csv (data_path)

    elif data_path.endswith ('.txt'):

    df = pd.read_csv (data_path, sep='\t', header=None, names=[text_col, label_col])

    else:

    raise ValueError ("仅支持 CSV 和 TXT 格式数据")

    print (f"原始数据形状:{df.shape}")

    文本清洗

    df['text_clean'] = df[text_col].apply(self.clean_text)

    删除清洗后为空的样本

    df_clean = df[df['text_clean'] != ''].copy()

    标签转为数值

    df_clean['label_num'] = df_clean[label_col].map(label_map)

    检查标签映射是否完整(删除无对应映射的样本)

    df_clean = df_clean.dropna(subset=['label_num'])

    df_clean['label_num'] = df_clean['label_num'].astype(int)

    print (f"清洗后数据形状:{df_clean.shape}")

    print (f"标签分布:{df_clean ['label_num'].value_counts (normalize=True).round (2)}")

    return df_clean

    def create_dataset (self, df_clean):

    """创建文本数据集(适配 BERT 输入格式)"""

    class BertTextDataset (Dataset):

    def init(self, df, tokenizer, max_seq_len):

    self.texts = df['text_clean'].tolist()

    self.labels = df['label_num'].tolist()

    self.tokenizer = tokenizer

    self.max_seq_len = max_seq_len

    def len(self):

    return len(self.texts)

    def getitem(self, idx):

    text = self.texts[idx]

    label = self.labels[idx]

    BERT 分词与向量转换

    encoding = self.tokenizer.encode_plus (

    text,

    add_special_tokens=True, # 添加 [CLS] 和 [SEP]

    max_length=self.max_seq_len,

    padding='max_length', # 填充至最大长度

    truncation=True, # 超过长度截断

    return_attention_mask=True,

    return_token_type_ids=True,

    return_tensors='pt' # 返回 PyTorch 张量

    )

    展平张量(去除批量维度)

    return {

    'input_ids': encoding['input_ids'].flatten(),

    'attention_mask': encoding['attention_mask'].flatten(),

    'token_type_ids': encoding['token_type_ids'].flatten(),

    'label': torch.tensor(label, dtype=torch.int64)

    }

    return BertTextDataset(df_clean, self.tokenizer, self.max_seq_len)

    def create_dataloader (self, dataset, is_train=True):

    """创建 DataLoader(批量加载文本数据)"""

    return DataLoader (

    dataset,

    batch_size=self.batch_size,

    shuffle=is_train,

    num_workers=self.num_workers,

    pin_memory=True # 加速 GPU 数据传输

    )

    def extract_text_features (self, text):

    """用 BERT 分词器提取文本特征(用于多模态融合)"""

    文本清洗

    text_clean = self.clean_text (text)

    if not text_clean:

    raise ValueError ("文本清洗后无有效内容")

    分词与向量转换

    encoding = self.tokenizer.encode_plus(

    text_clean,

    add_special_tokens=True,

    max_length=self.max_seq_len,

    padding='max_length',

    truncation=True,

    return_attention_mask=True,

    return_token_type_ids=True,

    return_tensors='pt'

    )

    提取 [CLS] token 对应的向量作为文本特征(BERT 常用做法)

    input_ids = encoding['input_ids']

    模拟 BERT 前向传播(仅取 [CLS] 位置输出,此处用随机矩阵模拟,实际需加载预训练模型)

    注:实际场景需加载完整 BERT 模型,此处简化演示

    cls_idx = 0 # [CLS] 位于序列第 0 位

    cls_feature = torch.randn (1, 768) # 模拟 768 维 BERT 特征

    return cls_feature.numpy ()

    类调用示例(客户评论文本数据集)

    if name == "main":

    初始化文本预处理类

    text_preprocessor = TextPreprocessor(

    bert_model_name='bert-base-chinese',

    max_seq_len=32,

    batch_size=16,

    num_workers=2

    )

    加载并清洗数据(假设为 TXT 格式,文本列 0,标签列 1)

    df_clean = text_preprocessor.load_and_clean_data (

    data_path='customer_comments.txt',

    text_col=0,

    label_col=1,

    label_map={' 正面 ': 1, ' 负面 ': 0}

    )

    创建数据集和 DataLoader

    dataset = text_preprocessor.create_dataset (df_clean)

    train_loader = text_preprocessor.create_dataloader (dataset, is_train=True)

    test_loader = text_preprocessor.create_dataloader (dataset, is_train=False) # 实际需先划分训练测试集

    print (f"训练集 DataLoader 批量数:{len (train_loader)}")

    print (f"测试集 DataLoader 批量数:{len (test_loader)}")

    提取单条文本特征(用于多模态融合)

    sample_text = "这台手机很好用,续航时间长,拍照效果也不错"

    text_feature = text_preprocessor.extract_text_features (sample_text)

    print (f"单条文本特征维度:{text_feature.shape}(768 维,模拟 BERT 特征)")

    15. 预处理代码的测试与维护

    生成并封装预处理代码后,还需要做好测试和维护工作,确保代码在不同场景下都能稳定运行,且能适配数据或业务需求的变化。下面从 “代码测试” 和 “长期维护” 两方面给出具体方法。

    15.1 预处理代码的测试方法

    15.1.1 单元测试:验证单个功能的正确性

    针对预处理代码中的核心函数(如文本清洗、缺失值填充、特征编码),编写单元测试用例,验证每个功能是否符合预期。

    示例:表格数据预处理中 “缺失值填充” 函数的单元测试

    
      

    import unittest

    import pandas as pd

    import numpy as np

    from preprocess_table import preprocess_table_data # 假设预处理函数在preprocess_table.py中

    class TestTablePreprocess(unittest.TestCase):

    def setUp(self):

    """准备测试数据"""

    self.test_data = pd.DataFrame({

    'Age': [22, np.nan, 35, np.nan, 50], # 含缺失值的数值特征

    'Sex': ['male', 'female', np.nan, 'male', 'female'], # 含缺失值的类别特征

    'Fare': [7.25, 71.83, 1000, 13.0, 8.05], # 含异常值的数值特征

    'Survived': [0, 1, 0, 1, 0] # 标签列

    })

    # 保存为临时CSV文件

    self.test_data_path = 'test_table_data.csv'

    self.test_data.to_csv(self.test_data_path, index=False)

    def test_missing_value_fill(self):

    """测试缺失值填充功能"""

    # 调用预处理函数(指定用中位数填充数值特征,众数填充类别特征)

    X_train, X_test, y_train, y_test, scaler = preprocess_table_data(

    data_path=self.test_data_path,

    label_col='Survived',

    drop_cols=[],

    num_cols=['Age', 'Fare'],

    cat_cols=['Sex'],

    fill_num_method='median',

    encode_cat_method='label',

    need_scale=False,

    test_size=0.2,

    random_state=42

    )

    # 验证Age列缺失值是否用中位数填充(原始数据Age中位数为35)

    self.assertFalse(X_train['Age'].isnull().any())

    self.assertFalse(X_test['Age'].isnull().any())

    self.assertTrue(35 in X_train['Age'].values or 35 in X_test['Age'].values)

    # 验证Sex列缺失值是否用众数填充(原始数据Sex众数为'male',编码后为1)

    self.assertFalse(X_train['Sex'].isnull().any())

    self.assertFalse(X_test['Sex'].isnull().any())

    self.assertTrue(1 in X_train['Sex'].values or 1 in X_test['Sex'].values)

    def test_outlier_process(self):

    """测试异常值处理功能(IQR方法)"""

    X_train, X_test, y_train, y_test, scaler = preprocess_table_data(

    data_path=self.test_data_path,

    label_col='Survived',

    drop_cols=[],

    num_cols=['Age', 'Fare'],

    cat_cols=['Sex'],

    fill_num_method='median',

    encode_cat_method='label',

    need_scale=False,

    test_size=0.2,

    random_state=42

    )

    # 计算原始Fare列的IQR上限(Q3=71.83,Q1=8.05,IQR=63.78,上限=71.83+1.5*63.78≈167.5)

    upper_bound = 71.83 + 1.5 * (71.83 - 8.05)

    # 验证异常值(1000)是否被替换为上限

    self.assertTrue(X_train['Fare'].max() <= upper_bound)

    self.assertTrue(X_test['Fare'].max() <= upper_bound)

    def tearDown(self):

    """清理测试文件"""

    import os

    if os.path.exists(self.test_data_path):

    os.remove(self.test_data_path)

    if __name__ == '__main__':

    unittest.main()

    15.1.2 集成测试:验证端到端流程的完整性

    从 “数据加载→预处理→模型输入” 完整流程进行测试,验证最终输出是否符合模型要求,无流程断裂或格式错误。

    示例:图像数据预处理端到端测试

    
      

    def test_image_preprocess_end2end():

    """测试图像预处理端到端流程"""

    from image_preprocessor import ImagePreprocessor # 假设图像预处理类在image_preprocessor.py中

    import torchvision.models as models

    # 1. 初始化预处理类(使用测试图像文件夹)

    test_data_dir = './test_images/' # 含cat和dog子文件夹,各2张图像

    preprocessor = ImagePreprocessor(

    data_dir=test_data_dir,

    img_size=(224, 224),

    num_classes=2,

    batch_size=2,

    num_workers=0 # 测试时禁用多线程

    )

    # 2. 创建DataLoader

    train_loader = preprocessor.create_dataloader(is_train=True)

    # 3. 验证DataLoader输出格式

    for batch_img, batch_label in train_loader:

    # 验证图像张量形状(批量大小×通道×高×宽)

    assert batch_img.shape == (2, 3, 224, 224), f"图像形状错误,实际为{batch_img.shape}"

    # 验证标签形状(批量大小)

    assert batch_label.shape == (2,), f"标签形状错误,实际为{batch_label.shape}"

    # 验证数据类型

    assert batch_img.dtype == torch.float32, f"图像数据类型错误,实际为{batch_img.dtype}"

    assert batch_label.dtype == torch.int64, f"标签数据类型错误,实际为{batch_label.dtype}"

    break # 仅测试第一个批量

    # 4. 验证与模型的适配性(ResNet50)

    model = models.resnet50(pretrained=False)

    with torch.no_grad():

    outputs = model(batch_img)

    # 验证模型输出形状(批量大小×类别数)

    assert outputs.shape == (2, 1000), f"模型输出形状错误,实际为{outputs.shape}"

    print("✅ 图像预处理端到端测试通过")

    # 执行测试

    test_image_preprocess_end2end()

    15.1.3 异常测试:验证代码的容错能力

    模拟异常场景(如数据路径错误、图像损坏、文本为空),测试代码是否能捕获异常并给出清晰提示,避免直接崩溃。

    示例:文本数据预处理异常测试

    
      

    def test_text_preprocess_exception():

    """测试文本预处理的异常处理能力"""

    from text_preprocessor import TextPreprocessor

    preprocessor = TextPreprocessor(

    bert_model_name='bert-base-chinese',

    max_seq_len=32,

    batch_size=16,

    num_workers=2

    )

    # 测试1:数据路径不存在

    try:

    preprocessor.load_and_clean_data(

    data_path='non_existent.txt',

    text_col</doubaocanvas>

    =0,

    label_col=1,

    label_map={' 正面 ':1, ' 负面 ':0}

    )

    若未抛出异常,测试失败

    assert False, "数据路径不存在时未抛出预期异常"

    except FileNotFoundError as e:

    验证异常提示是否清晰

    assert "不存在" in str (e) or "无法找到" in str (e), f"异常提示不清晰:{str (e)}"

    print ("✅ 数据路径不存在异常测试通过")

    测试 2:文本清洗后为空

    try:

    preprocessor.extract_text_features (text="的了在") # 全是停用词,清洗后为空

    assert False, "文本清洗后为空时未抛出预期异常"

    except ValueError as e:

    assert "无有效内容" in str (e), f"异常提示不清晰:{str (e)}"

    print ("✅ 文本清洗后为空异常测试通过")

    测试 3:标签映射不完整

    test_data_empty_label = pd.DataFrame ({

    'text': [' 手机很好用 '],

    'label': [' 中性 '] # 不在 label_map 中

    })

    test_data_path = 'test_empty_label.csv'

    test_data_empty_label.to_csv (test_data_path, index=False)

    try:

    df_clean = preprocessor.load_and_clean_data (

    data_path=test_data_path,

    text_col='text',

    label_col='label',

    label_map={' 正面 ':1, ' 负面 ':0}

    )

    验证无对应映射的样本是否被删除(清洗后数据应为空)

    assert len (df_clean) == 0, f"未删除无标签映射的样本,清洗后样本数:{len (df_clean)}"

    print ("✅ 标签映射不完整异常测试通过")

    finally:

    清理测试文件

    import os

    if os.path.exists(test_data_path):

    os.remove(test_data_path)

    执行异常测试

    test_text_preprocess_exception()

    
      

    ### 15.2 预处理代码的长期维护方法

    预处理代码不是“一次性使用”的,需要长期维护以适配数据变化(如新增特征、数据格式调整)和业务需求变化(如模型更换、新增预处理要求)。下面给出4个核心维护方法。

    #### 15.2.1 方法1:版本控制与文档记录

    - 版本控制:用Git对预处理代码进行版本管理,每次修改代码时提交更新记录,注明“修改原因”“修改内容”“影响范围”,便于后续回溯。

    示例提交记录:`git commit -m "v1.1:新增表格数据类别特征独热编码功能,修改preprocess_table.py的encode_cat_method参数,不影响现有label编码逻辑"`

    - 文档记录:编写《预处理代码维护文档》,包含以下内容:

    1. 代码功能说明:每个函数/类的用途、参数含义、返回值;

    2. 版本历史:各版本的修改时间、修改内容、负责人;

    3. 依赖库版本:明确代码依赖的Python库版本(如Pandas 1.5.3、PyTorch 2.0.1),避免因库版本更新导致代码失效;

    4. 常见问题排查:记录使用中遇到的问题(如“数据路径含中文导致读取失败”)及解决方案。

    #### 15.2.2 方法2:参数化配置,适配数据变化

    当数据格式或预处理要求变化时(如新增特征、调整缺失值填充方法),避免直接修改代码逻辑,而是通过“参数化配置”灵活适配。

    示例:表格数据预处理参数配置文件(config.json)

    ```json

    {

    "table_preprocess": {

    "data_path": "titanic_v2.csv", // 数据路径可灵活修改

    "label_col": "Survived",

    "drop_cols": ["Name", "Ticket", "Cabin", "PassengerId"], // 新增需删除的特征PassengerId

    "num_cols": ["Age", "Fare", "SibSp", "Parch", "FamilySize"], // 新增特征FamilySize

    "cat_cols": ["Sex", "Embarked", "Pclass"], // 新增类别特征Pclass

    "fill_num_method": "median",

    "encode_cat_method": "onehot", // 从label编码改为onehot编码

    "need_scale": true,

    "test_size": 0.2,

    "random_state": 42

    }

    }

    代码中读取配置文件,避免硬编码:

    
      

    import json

    def load_config(config_path):

    """读取预处理配置文件"""

    with open(config_path, 'r', encoding='utf-8') as f:

    return json.load(f)

    # 使用配置文件初始化预处理

    config = load_config('config.json')['table_preprocess']

    X_train, X_test, y_train, y_test, scaler = preprocess_table_data(

    data_path=config['data_path'],

    label_col=config['label_col'],

    drop_cols=config['drop_cols'],

    num_cols=config['num_cols'],

    cat_cols=config['cat_cols'],

    fill_num_method=config['fill_num_method'],

    encode_cat_method=config['encode_cat_method'],

    need_scale=config['need_scale'],

    test_size=config['test_size'],

    random_state=config['random_state']

    )

    15.2.3 方法 3:定期更新与兼容性测试
  • 定期更新:
    1. 库版本更新:当依赖库推出稳定新版本时(如 PyTorch 2.1.0),测试代码在新版本下的兼容性,若存在问题(如函数参数废弃),及时修改代码;
    1. 预处理方法更新:当行业出现更优的预处理方法时(如用 “KNN 填充” 替代 “中位数填充” 处理缺失值),在不影响现有功能的前提下,新增方法选项(如在fill_num_method中增加knn选项)。
  • 兼容性测试:
    1. 新旧数据兼容性:用旧版本数据(如泰坦尼克号 v1.csv)和新版本数据(如泰坦尼克号 v2.csv,含新增特征)分别测试代码,确保两者都能正常处理;
    1. 新旧模型兼容性:若更换模型(如从逻辑回归改为 XGBoost),测试预处理代码输出是否适配新模型(如 XGBoost 无需特征标准化,验证need_scale=False时代码是否正常运行)。
  • 15.2.4 方法 4:模块化拆分,降低维护成本

    将预处理代码按 “功能模块” 拆分,避免所有逻辑写在一个文件中,便于局部修改和维护。以表格数据预处理为例,拆分后的目录结构如下:

    
      

    preprocess/

    ├── __init__.py # 包初始化

    ├── config.py # 配置读取(如加载json配置)

    ├── data_clean.py # 数据清洗模块(缺失值、异常值处理)

    ├── feature_engineer.py # 特征工程模块(编码、标准化)

    ├── data_split.py # 数据划分模块

    └── main.py # 主函数(调用各模块)

    各模块独立负责单一功能,例如data_clean.py仅处理缺失值和异常值,当需要修改异常值处理方法(如从 IQR 改为 Z-score)时,只需修改data_clean.py,无需改动其他模块,降低维护风险。

    16. 总结与扩展

    通过多个实战案例和代码封装,我们系统讲解了如何用提示词生成机器学习数据集预处理步骤,覆盖表格、文本、图像、多模态等常见数据类型。核心逻辑可总结为 “明确需求→精准提示→代码生成→测试维护” 四步:

  • 明确需求:确定数据类型、已知问题、目标模型,为提示词提供清晰依据;
  • 精准提示:包含 “数据描述、预处理目标、工具要求、输出格式” 四大核心要素,引导大模型生成贴合需求的步骤;
  • 代码生成:基于大模型输出的步骤,封装为可复用的函数或类,提升效率;
  • 测试维护:通过单元测试、集成测试、异常测试确保代码正确性,用版本控制、参数化配置降低长期维护成本。
  • 16.1 扩展方向 1:适配更多特殊数据类型

    除了文中覆盖的数据类型,还可将提示词方法扩展到以下特殊场景:

  • 音频数据:提示词中需包含 “采样率统一、音频时长裁剪、特征提取(如 MFCC)” 等要求,适配语音识别模型;
  • 视频数据:需明确 “帧提取频率、帧尺寸统一、光流特征提取” 等步骤,适配视频分类模型;
  • 多源表格数据:需包含 “数据对齐(如按时间戳合并)、特征融合(如拼接不同表格的特征)” 等要求,适配多源数据建模场景。
  • 16.2 扩展方向 2:结合自动化工具链

    将提示词生成的预处理代码与自动化工具链结合,构建端到端的机器学习流程:

  • 数据监控:用 Airflow 定时执行预处理代码,监控数据质量(如缺失率突然升高时发送告警);
  • 模型部署:将预处理代码封装为 API(如用 FastAPI),与模型推理 API 联动,实现 “新数据输入→自动预处理→模型预测→结果输出” 的全自动化;
  • 版本管理:用 MLflow 管理预处理代码、模型、数据的版本关联,实现 “数据版本→预处理版本→模型版本” 的可追溯。
  • 16.3 扩展方向 3:提示词的迭代优化

    根据大模型的生成结果,持续优化提示词,提升生成质量:

  • 第一次提示:若生成的代码缺少异常处理,补充提示词 “代码需包含 try-except 异常处理,如图像读取失败、数据路径不存在时给出清晰提示”;
  • 第二次提示:若生成的步骤遗漏类别不平衡处理,补充提示词 “数据存在类别不平衡(正样本占比 10%),需加入 SMOTE 过采样步骤”;
  • 第三次提示:若生成的代码变量名不规范,补充提示词 “变量名需符合 Python 命名规范(小写 + 下划线),如 img_path 而非 ImgPath”。
  • 通过持续迭代提示词,让大模型生成的预处理步骤越来越贴合实际需求,最终实现 “提示词→高质量代码→高效预处理” 的闭环,大幅提升机器学习项目的开发效率。

    17. 实战补充:新手常见预处理误区与避坑指南

    新手在使用提示词生成预处理步骤并落地执行时,常因对数据逻辑或模型要求理解不深,陷入各类误区,导致预处理效果不佳或模型训练失败。下面总结 6 个高频误区及对应的避坑方法,结合具体场景给出解决方案。

    17.1 误区 1:数据划分前先做特征标准化(数据泄露)

    17.1.1 误区表现

    新手常先对整个数据集做特征标准化(如 StandardScaler),再划分训练集和测试集。这种操作会导致 “数据泄露”—— 测试集的统计信息(如均值、标准差)融入训练过程,使模型在测试集上的评估结果失真(看似效果好,实际泛化能力差)。

    17.1.2 避坑方法

    严格遵循 “先划分数据,再在训练集上拟合预处理工具,最后用拟合好的工具处理测试集” 的流程。以表格数据标准化为例,正确代码逻辑如下:

    
      

    # 错误做法:先标准化,再划分数据

    scaler = StandardScaler()

    X_all_scaled = scaler.fit_transform(X) # 用全量数据拟合,导致数据泄露

    X_train, X_test, y_train, y_test = train_test_split(X_all_scaled, y, test_size=0.3)

    # 正确做法:先划分数据,再在训练集上拟合标准化器

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

    scaler = StandardScaler()

    X_train_scaled = scaler.fit_transform(X_train) # 仅用训练集拟合

    X_test_scaled = scaler.transform(X_test) # 用训练集的统计信息处理测试集

    17.1.3 提示词优化建议

    在提示词中明确要求 “避免数据泄露,需先划分训练集和测试集,再在训练集上拟合预处理工具(如标准化器、编码器),测试集仅做转换,不重新拟合”,强制大模型生成正确流程。

    17.2 误区 2:文本数据直接用 LabelEncoder 编码多分类特征

    17.2.1 误区表现

    处理文本数据中的多分类特征(如 “职业” 包含 “学生”“教师”“工程师”)时,新手常直接用 LabelEncoder 编码(将类别转为 0、1、2)。但 LabelEncoder 会给类别赋予 “顺序关系”(如 0<1<2),而实际 “学生”“教师”“工程师” 无先后顺序,这种错误编码会误导模型学习虚假的类别逻辑。

    17.2.2 避坑方法

    多分类特征(无顺序)需用 One-Hot 编码(如 Pandas 的 get_dummies 或 Scikit-learn 的 OneHotEncoder);仅二分类特征(如 “性别”)或有序分类特征(如 “学历:小学 < 中学 < 大学”)可用 LabelEncoder。以文本数据中 “职业” 特征编码为例,正确代码如下:

    
      

    # 错误做法:多分类特征用LabelEncoder

    le = LabelEncoder()

    df['occupation_encoded'] = le.fit_transform(df['occupation']) # 生成0、1、2,引入虚假顺序

    # 正确做法:多分类特征用One-Hot编码

    occupation_dummies = pd.get_dummies(df['occupation'], prefix='occupation', drop_first=True)

    df = pd.concat([df, occupation_dummies], axis=1)

    df = df.drop('occupation', axis=1) # 删除原类别列

    17.2.3 提示词优化建议

    在提示词中明确 “类别特征类型:多分类且无顺序(如职业、兴趣爱好)需用 One-Hot 编码;二分类或有序分类(如学历、评分等级)可用 LabelEncoder”,让大模型根据特征属性选择正确编码方式。

    17.3 误区 3:图像数据预处理时忽略通道顺序(RGB/BGR 混淆)

    17.3.1 误区表现

    新手用 OpenCV 读取图像后,直接传入依赖 RGB 通道的模型(如 ResNet、BERT-ViT)。但 OpenCV 默认读取的图像通道顺序为 BGR,而 PyTorch 的 torchvision、TensorFlow 的 Keras 默认处理 RGB 通道,通道顺序混淆会导致模型无法正确提取图像特征,训练效果极差(如分类准确率接近随机)。

    17.3.2 避坑方法

    读取图像后,强制将 BGR 通道转为 RGB 通道;若用 PIL 读取图像(默认 RGB),则无需转换。正确代码如下:

    
      

    # 用OpenCV读取图像(BGR→RGB转换)

    import cv2

    from PIL import Image

    # 错误做法:直接使用BGR图像

    img_bgr = cv2.imread('cat.jpg')

    img_pil = Image.fromarray(img_bgr) # 直接转换,通道仍为BGR,模型无法识别

    # 正确做法:BGR→RGB转换后再处理

    img_bgr = cv2.imread('cat.jpg')

    img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) # 关键:通道转换

    img_pil = Image.fromarray(img_rgb) # 此时为RGB图像,适配模型要求

    17.3.3 提示词优化建议

    在提示词中加入 “用 OpenCV 读取图像后,必须将 BGR 通道转为 RGB 通道;若用 PIL 读取,需确认通道为 RGB”,并要求大模型在代码中加入通道转换注释,避免遗漏。

    17.4 误区 4:处理缺失值时,所有特征用同一种方法(一刀切)

    17.4.1 误区表现

    新手常对所有缺失特征用同一种填充方法(如全部用均值填充),忽略特征类型和业务逻辑。例如,对 “年龄”(数值型,无明显偏态)用均值填充合理,但对 “收入”(数值型,严重右偏)用均值填充会拉高整体水平;对 “职业”(类别型)用均值填充更是完全错误(类别无法用数值均值表示)。

    17.4.2 避坑方法

    根据特征类型和分布选择填充方法,具体规则如下:

    特征类型

    缺失值处理方法

    适用场景

    数值型(正态分布)

    均值填充

    年龄、身高、体重等无偏态的连续特征

    数值型(偏态分布)

    中位数填充

    收入、消费金额等右偏特征(不受极端值影响)

    类别型

    众数填充

    职业、学历、城市等高频类别特征

    时间型

    前向填充 / 后向填充(按时间顺序)

    时序数据中的时间戳缺失(如连续日期记录)

    高缺失率特征(>70%)

    直接删除特征或用 “未知” 标签填充

    如 “用户兴趣标签” 缺失率 80%,无有效信息

    正确代码示例(多特征差异化填充):

    
      

    # 数值型(正态分布):Age用均值填充

    df['Age'] = df['Age'].fillna(df['Age'].mean())

    # 数值型(偏态分布):Income用中位数填充

    df['Income'] = df['Income'].fillna(df['Income'].median())

    # 类别型:Occupation用众数填充

    df['Occupation'] = df['Occupation'].fillna(df['Occupation'].mode()[0])

    # 高缺失率特征:删除Cabin列(缺失率>70%)

    df = df.drop('Cabin', axis=1)

    17.4.3 提示词优化建议

    在提示词中说明 “不同特征的类型和分布(如 Age 为正态分布数值型,Income 为偏态分布数值型,Occupation 为类别型),需按特征属性选择对应的缺失值处理方法,避免一刀切”,引导大模型生成差异化方案。

    17.5 误区 5:文本数据清洗时过度删除信息(如删除所有数字和英文)

    17.5.1 误区表现

    新手在清洗文本数据时,常过度使用正则表达式删除 “非中文字符”(如数字、英文、符号),导致关键信息丢失。例如,电商评论文本 “这款 256G 的手机很好用” 中,“256G” 是产品核心参数,删除后模型无法识别 “存储容量” 这一关键特征;技术文档中的英文术语 “GPU 性能强”,删除 “GPU” 后语义完全改变。

    17.5.2 避坑方法

    根据文本场景判断是否保留非中文字符,优先 “选择性删除” 而非 “全量删除”:

  • 保留关键信息:如产品参数(数字、英文型号)、技术术语(英文缩写如 GPU、CPU);
  • 删除无用信息:如特殊符号(!、@、#)、无意义英文(如 “abc”“test”);
  • 模糊场景时:先保留非中文字符,后续通过特征重要性分析(如树模型的 feature_importances_)判断是否删除。
  • 正确文本清洗代码示例:

    
      

    # 错误做法:删除所有非中文字符,丢失关键信息

    def clean_text_wrong(text):

    return re.sub(r'[^\u4e00-\u9fa5]', '', text) # 仅保留中文字符,删除数字、英文

    # 正确做法:保留数字和英文,仅删除特殊符号

    def clean_text_correct(text):

    # 保留中文字符、数字、英文(a-zA-Z0-9),删除其他符号

    text = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9]', '', text)

    return text.strip()

    # 测试效果

    raw_text = "这款256G的GPU手机很好用!"

    print(clean_text_wrong(raw_text)) # 输出“这款的手机很好用”(丢失256G、GPU)

    print(clean_text_correct(raw_text))# 输出“这款256G的GPU手机很好用”(保留关键信息)

    17.5.3 提示词优化建议

    在提示词中明确 “文本中的关键信息类型(如产品参数含数字、技术术语含英文缩写),清洗时需保留这些信息,仅删除无意义特殊符号(如!、@、#)”,避免大模型生成过度清洗的代码。

    17.6 误区 6:多模态数据预处理时破坏模态对应关系

    17.6.1 误区表现

    处理 “图像 + 文本”“音频 + 文本” 等多模态数据时,新手常因单独处理各模态数据(如先打乱图像顺序,再打乱文本顺序),导致 “图像 A 对应文本 B” 的错误关联,模型训练时输入的是错位的多模态特征,完全无法学习到模态间的协同关系。

    17.6.2 避坑方法

    以 “图像 ID - 文本 ID” 为唯一关联键,确保所有预处理操作(清洗、划分、增强)都基于关联键同步进行,不单独打乱某一模态:

  • 数据加载时:用关联键(如 “goods_id”)建立图像和文本的一一对应关系,生成 “关联键 - 图像路径 - 文本内容 - 标签” 的统一数据表;
  • 数据清洗时:按关联键删除 “仅缺图像” 或 “仅缺文本” 的样本,确保清洗后每个关联键都有完整的多模态数据;
  • 数据划分时:按关联键划分训练集和测试集(如训练集关联键列表、测试集关联键列表),再按列表提取对应模态数据,避免单独划分某一模态。
  • 正确多模态数据划分代码示例:

    
      

    # 1. 建立关联键数据表(goods_id为关联键)

    df_multi = pd.DataFrame({

    'goods_id': ['1001', '1002', '1003'],

    'img_path': ['./img/1001.jpg', './img/1002.jpg', './img/1003.jpg'],

    'text': ['256G手机', '超薄笔记本', '无线耳机'],

    'label': [0, 1, 2]

    })

    # 2. 按关联键划分训练集和测试集

    train_ids = ['1001', '1002'] # 训练集关联键

    test_ids = ['1003'] # 测试集关联键

    # 3. 按关联键提取对应模态数据(确保对应关系不变)

    df_train = df_multi[df_multi['goods_id'].isin(train_ids)]

    df_test = df_multi[df_multi['goods_id'].isin(test_ids)]

    # 4. 分别处理各模态数据(基于划分后的DataFrame)

    train_imgs = [cv2.imread(path) for path in df_train['img_path']] # 训练集图像

    train_texts = df_train['text'].tolist() # 训练集文本(与图像一一对应)

    17.6.3 提示词优化建议

    在提示词中强调 “以关联键(如 goods_id、sample_id)为核心,所有预处理步骤(加载、清洗、划分)需基于关联键同步进行,确保多模态数据的对应关系不被破坏,禁止单独处理某一模态”,并要求大模型在代码中加入关联键相关注释。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐