【测AI】第12篇:NLP / CV / 语音 —— 三大 AI 方向速通

写在前面

第 11 篇我们理解了神经网络的基本原理。但"神经网络"只是一个通用框架------就像"交通工具"是一个通用概念,但自行车、汽车、飞机的使用方式完全不同。

AI 领域也是如此。同样是深度学习,处理文字的 NLP、处理图片的 CV、处理语音的语音技术,它们的输入数据不同、核心架构不同、"容易翻车"的地方不同。

你作为测试人员,需要根据被测模型属于哪个方向,来设计针对性的测试方案。一篇测试报告写"准确率 95%"毫无意义------你需要知道这个 95% 是在什么方向、什么任务、什么数据上取得的。

环境准备

本篇需要以下 Python 库,开始前先在终端执行:

bash 复制代码
pip install numpy matplotlib jieba -i https://pypi.tuna.tsinghua.edu.cn/simple

如果觉得每次加 -i 太麻烦,可以先执行一次 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple 配置默认镜像,以后安装任何包都自动加速。

本篇文件结构

本篇代码放在 ai-test/ch12_domains/ 文件夹下:

文件名 用途 创建方式
nlp_demo.py NLP 核心概念演示 三、新建
cv_demo.py CV 核心概念演示 四、新建
domain_test_plan.py 三大方向测试方案生成 六、新建
charts/ 图片输出目录(自动生成) 不需要手动创建

一、为什么测试人员需要了解不同 AI 方向?

先想一个场景。你接了一个测试任务:

"请测试我们新上线的 AI 模型。"

你的第一个问题应该是:这是什么类型的模型?

  • 如果是文本分类(比如情感分析、垃圾邮件检测),你需要关注否定词、反讽、语序等文本特有的问题
  • 如果是图像识别(比如人脸检测、医学影像),你需要关注图片旋转、缩放、遮挡等图像特有的问题
  • 如果是语音识别(比如语音转文字),你需要关注口音、噪声、语速等语音特有的问题

测试方法、测试数据、评估指标都不一样。所以你必须先搞清楚"这是什么方向的模型",才能开始设计测试方案。

三大方向在整个 AI 产品中的占比大致是:

方向 典型应用 产品中占比 测试复杂度
NLP(自然语言处理) 文本分类、对话机器人、翻译、摘要 最高(约 50%+) 中等
CV(计算机视觉) 图像识别、人脸识别、OCR、医学影像 高(约 30%) 中等
语音 语音转文字、语音助手、声纹识别 中等(约 15%) 较高(涉及多模态)

加上现在大模型时代,很多产品是多模态的(同时处理文字+图片+语音),测试就更复杂了。但不管多模态还是单模态,你都是从这三个基本方向来理解的。


二、三大方向全景图

在深入每个方向之前,先用一张表把三个方向的核心差异摆出来:

维度 NLP CV 语音
输入数据 文本(字符/词) 图片(像素矩阵) 音频(声波采样)
数据预处理 分词、去停用词 缩放、归一化 降噪、分帧
核心架构 Transformer CNN / ViT RNN / Transformer
典型任务 分类、生成、翻译、问答 分类、检测、分割、生成 识别、合成、声纹
核心指标 准确率、BLEU、ROUGE 准确率、IoU、mAP WER、CER、MOS
典型失败 否定词、反讽、幻觉 旋转、遮挡、光照 噪声、口音、语速
测试数据 文本语料 图片数据集 音频数据集

每个方向下面详细展开。


三、NLP ------ 让机器"理解"文字

3.1 NLP 在做什么

NLP(Natural Language Processing,自然语言处理)的目标是让机器理解和生成人类语言。你天天在用的搜索引擎、翻译软件、聊天机器人、语音助手,背后都有 NLP。

NLP 的典型任务:

  • 文本分类:给一段文字打标签。比如"这条评论是正面还是负面?"
  • 文本生成:给一个开头,让模型续写。比如 ChatGPT 写文章
  • 机器翻译:中文翻英文、英文翻中文
  • 问答系统:根据一段资料回答问题
  • 文本摘要:把长文章压缩成短摘要
  • 命名实体识别:从文本中提取人名、地名、机构名

3.2 第一步:分词(Tokenization)------ 把文字切成"块"

机器不像人一样天生能理解文字。它看到的是一串字符或者编码。第一步就是把文字切成小块,这个过程叫分词。

对英文来说,分词比较直观------按空格切就行:

"I love AI testing" → "I", "love", "AI", "testing"

对中文来说,分词更复杂,因为中文没有空格分隔:

"我喜欢AI测试" → "我", "喜欢", "AI", "测试"

分词的结果叫 Token(令牌)。大语言模型中经常听到"Token 限制"、"Token 计费",说的就是这个。

3.3 第二步:词嵌入(Embedding)------ 把词变成数字

计算机不认识文字,只认识数字。所以分词之后,要把每个 Token 转成一个数字向量------这个过程叫词嵌入(Word Embedding)。

核心思想:含义相近的词,向量也相近。

"猫" 的向量 ≈ "狗" 的向量(都是动物)

"猫" 的向量 ✗ "汽车" 的向量(差得很远)

这就像给每个词分配了一个"坐标",在坐标空间中含义相近的词靠得近。

3.4 第三步:注意力机制(Attention)------ 该重点关注什么

Transformer 架构(第 11 篇提过)的核心是注意力机制。它的作用是让模型知道"处理当前这个词的时候,该重点关注输入中的哪些部分"。

举个例子:

输入:"小明把苹果放在桌子上,然后它被吃掉了"

问题:"它"指的是什么?

模型需要知道"它"应该重点关注"苹果"而不是"小明"或"桌子"。注意力机制就是让模型自动学到这种"看哪里"的能力。

3.5 动手演示:NLP 核心概念

【新建文件】 在 ai-test/ch12_domains/ 文件夹下新建 nlp_demo.py,写入以下代码:

python 复制代码
"""
NLP 核心概念演示
分词、词嵌入的直觉理解
"""

import numpy as np

print("=" * 60)
print("NLP 核心概念演示")
print("=" * 60)


# ========== 1. 分词演示 ==========

print("\n--- 1. 分词(Tokenization) ---")

import jieba

texts = [
    "我喜欢AI测试工程师这个职业",
    "大语言模型正在改变软件测试的方式",
    "Python是AI测试的第一技能",
]

for text in texts:
    tokens = list(jieba.cut(text))
    print(f"\n  原文: {text}")
    print(f"  分词: {tokens}")
    print(f"  Token数: {len(tokens)}")

print(f"\n  分词的意义:机器只能逐个 Token 处理,Token 的划分方式会影响模型理解")
print(f"  比如'AI测试'如果被切成['AI', '测试'],模型理解为两个概念")
print(f"  如果被切成['AI测', '试'],模型理解就完全跑偏了")


# ========== 2. 词嵌入演示 ==========

print(f"\n--- 2. 词嵌入(Word Embedding) ---")
print(f"核心思想:含义相近的词,向量空间中距离也相近")

# 用简化的向量来演示(真实模型的向量通常有几百到几千维)
words = {
    "猫":   np.array([0.9, 0.1, 0.8]),
    "狗":   np.array([0.85, 0.15, 0.75]),
    "汽车": np.array([0.1, 0.9, 0.2]),
    "卡车": np.array([0.15, 0.85, 0.25]),
    "小明": np.array([0.5, 0.3, 0.6]),
}

def cosine_similarity(a, b):
    """余弦相似度:衡量两个向量的相似程度(-1到1,越接近1越相似)"""
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

print(f"\n  词向量(简化为3维):")
for word, vec in words.items():
    print(f"    {word}: {vec}")

print(f"\n  余弦相似度:")
pairs = [("猫", "狗"), ("猫", "汽车"), ("汽车", "卡车"), ("猫", "小明"), ("狗", "卡车")]
for w1, w2 in pairs:
    sim = cosine_similarity(words[w1], words[w2])
    bar = "█" * int(sim * 20)
    print(f"    {w1} ↔ {w2}: {sim:.3f}  {bar}")

print(f"\n  观察:猫↔狗 和 汽车↔卡车 的相似度都很高(同类事物)")
print(f"        猫↔汽车 的相似度很低(不同类事物)")


# ========== 3. 注意力机制的直觉理解 ==========

print(f"\n--- 3. 注意力机制(Attention)的直觉 ---")

# 简化演示:当模型处理"它"这个词时,应该关注句中的哪个词
sentence = ["小明", "把", "苹果", "放在", "桌子", "上", "然后", "它", "被", "吃掉"]
target_word = "它"

# 模拟注意力权重(实际中由模型学习得到)
attention_weights = {
    "小明": 0.05,
    "把": 0.01,
    "苹果": 0.65,    # 注意力高度集中在"苹果"上
    "放在": 0.03,
    "桌子": 0.12,
    "上": 0.01,
    "然后": 0.02,
    "它": 0.02,
    "被": 0.01,
    "吃掉": 0.08,
}

print(f"\n  句子:{' '.join(sentence)}")
print(f"  当模型处理 '{target_word}' 时,注意力分布:")
for word, weight in sorted(attention_weights.items(), key=lambda x: x[1], reverse=True):
    bar = "█" * int(weight * 50)
    print(f"    {word:<6s} {weight:.2f}  {bar}")

print(f"\n  模型把大部分注意力放在'苹果'上------正确!'它'指的就是苹果")
print(f"  这就是注意力机制的作用:自动学会'该看哪里'")

【运行】 在终端执行:

bash 复制代码
python nlp_demo.py

运行后输出(不同版本的 jieba 分词结果可能略有差异):

复制代码
--- 1. 分词(Tokenization) ---

  原文: 我喜欢AI测试工程师这个职业
  分词: ['我', '喜欢', 'AI', '测试","工程师', '这个', '职业']
  Token数: 6

  原文: 大语言模型正在改变软件测试的方式
  分词: ['大', '语言', '模型', '正在', '改变', '软件', '测试', '的', '方式']
  Token数: 9

--- 2. 词嵌入(Word Embedding) ---

  余弦相似度:
    猫 ↔ 狗: 0.998  ████████████████████
    猫 ↔ 汽车: 0.543  ██████████
    汽车 ↔ 卡车: 0.998  ████████████████████

--- 3. 注意力机制(Attention)的直觉 ---

  句子:小明 把 苹果 放在 桌子 上 然后 它 被 吃掉
  当模型处理 '它' 时,注意力分布:
    苹果   0.65  ███████████████████████████████
    桌子   0.12  ██████

3.6 NLP 测试要点

测试维度 具体关注点 测试方法
否定词处理 "不是很好"不等于"好" 构造否定句测试
反讽识别 "真是好极了才怪"是负面 收集讽刺/反语样本
多语言混合 中英混排、方言、口语 构造混合语言输入
长文本处理 超长输入是否截断、丢失信息 逐步增加文本长度
语序依赖 "猫追狗"和"狗追猫"意思不同 交换词序测试
幻觉检测 生成不存在的事实 对照知识库验证
Token 限制 超出最大长度怎么办 测试边界长度

四、CV ------ 让机器"看"图片

4.1 CV 在做什么

CV(Computer Vision,计算机视觉)的目标是让机器理解和分析图像。你手机的人脸解锁、医院的 AI 辅助诊断、自动驾驶的障碍物识别,背后都是 CV。

CV 的典型任务:

  • 图像分类:这张图是什么?(猫?狗?汽车?)
  • 目标检测:图中有哪些物体?在哪里?(画框标出来)
  • 图像分割:图中每个像素属于什么?(把人和背景分开)
  • OCR(光学字符识别):图片中的文字是什么?
  • 图像生成:根据文字描述生成图片(比如 DALL-E、Midjourney)

4.2 图片在计算机眼中是什么

你看到一张猫的照片,大脑瞬间就认出来了。但计算机看到的是什么?

一张图片在计算机中就是一个数字矩阵。一张灰度图片是二维矩阵(每个格子一个数字,代表灰度值 0~255),一张彩色图片是三维矩阵(每个格子三个数字,代表红绿蓝三个通道)。

一张 28×28 的灰度图片 = 一个 28×28 的矩阵 = 784 个数字

一张 1920×1080 的彩色图片 = 一个 1920×1080×3 的矩阵 = 约 620 万个数字

AI 模型要从这几百上千万个数字中"看出"这是一只猫。这比你想象的难得多。

4.3 卷积(Convolution)------ 提取局部特征

CV 模型最核心的操作是卷积 。用一个叫卷积核(也叫滤波器)的小矩阵,在图片上从左到右、从上到下滑动,每到一个位置就做一次"加权求和",提取出该位置的局部特征。

类比:你用一个 3×3 的小窗口(放大镜)在图片上滑动扫描。每个窗口看一小块区域,提取出"这里有没有边缘?""这里有没有纹理?"

不同的卷积核提取不同的特征:

  • 有的核专门提取水平边缘
  • 有的核专门提取垂直边缘
  • 有的核专门提取特定纹理(毛茸茸、光滑等)
  • 更深的层把简单特征组合成复杂特征(边缘 → 形状 → 物体部件 → 完整物体)

4.4 动手演示:卷积操作

【新建文件】 在 ai-test/ch12_domains/ 文件夹下新建 cv_demo.py,写入以下代码:

python 复制代码
"""
CV 核心概念演示
卷积操作的直觉理解与可视化
"""

import numpy as np
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rcParams["font.sans-serif"] = ["Microsoft YaHei"]
matplotlib.rcParams["axes.unicode_minus"] = False

import os
os.makedirs("charts", exist_ok=True)

print("=" * 60)
print("CV 核心概念演示")
print("=" * 60)


# ========== 1. 图片 = 数字矩阵 ==========

print("\n--- 1. 图片就是数字矩阵 ---")

# 创建一个简单的 8x8 图片(模拟一个简单的"笑脸")
# 0 = 黑色,1 = 白色
image = np.zeros((8, 8))
image[1:7, 1:7] = 1       # 一个白色方块
image[3, 3] = 0           # 左眼(黑点)
image[3, 4] = 0           # 右眼(黑点)
image[5, 2:6] = 0          # 嘴巴(黑色横线)

print(f"  图片尺寸: {image.shape}")
print(f"  图片数据(0=黑, 1=白):")
for row in image:
    print(f"    {' '.join('█' if v > 0.5 else '·' for v in row)}")


# ========== 2. 卷积操作 ==========

print(f"\n--- 2. 卷积操作演示 ---")
print(f"用一个 3x3 的卷积核在图片上滑动,提取局部特征")

def convolve2d(image, kernel):
    """
    手写一个 2D 卷积操作
    理解卷积到底在做什么
    """
    kh, kw = kernel.shape
    ih, iw = image.shape
    oh, ow = ih - kh + 1, iw - kw + 1

    output = np.zeros((oh, ow))

    for i in range(oh):
        for j in range(ow):
            # 取出当前位置的 3x3 小区域
            region = image[i:i+kh, j:j+kw]
            # 加权求和
            output[i, j] = np.sum(region * kernel)

    return output


# 定义三种不同的卷积核
kernels = {
    "水平边缘检测": np.array([[-1, -1, -1],
                              [ 0,  0,  0],
                              [ 1,  1,  1]]),

    "垂直边缘检测": np.array([[-1,  0,  1],
                              [-1,  0,  1],
                              [-1,  0,  1]]),

    "锐化": np.array([[ 0, -1,  0],
                      [-1,  5, -1],
                      [ 0, -1,  0]]),
}

print(f"\n  定义了 {len(kernels)} 种卷积核,分别提取不同的特征")

# 对图片应用每种卷积核
feature_maps = {}
for name, kernel in kernels.items():
    feature_map = convolve2d(image, kernel)
    feature_maps[name] = feature_map
    print(f"\n  [{name}]")
    print(f"  卷积核:")
    for row in kernel:
        print(f"    {' '.join(f'{v:>3d}' for v in row)}")
    print(f"  特征图(提取结果):")
    for row in feature_map:
        print(f"    {' '.join(f'{v:>5.1f}' for v in row)}")


# ========== 3. 可视化:原图和特征图 ==========

print(f"\n--- 3. 可视化 ---")

fig, axes = plt.subplots(1, 4, figsize=(16, 4))

# 原图
axes[0].imshow(image, cmap="gray", vmin=0, vmax=1)
axes[0].set_title("原图(8x8 灰度图)", fontsize=12)
axes[0].axis("off")

# 各个特征图
for idx, (name, fmap) in enumerate(feature_maps.items(), 1):
    axes[idx].imshow(fmap, cmap="RdBu_r")
    axes[idx].set_title(f"特征图:{name}", fontsize=12)
    axes[idx].axis("off")

plt.suptitle("卷积操作:从原图中提取不同特征", fontsize=15, fontweight="bold")
plt.tight_layout()
plt.savefig("charts/cv_convolution.png", dpi=150, bbox_inches="tight")
plt.close()

print(f"  卷积可视化已保存到 charts/cv_convolution.png")


# ========== 4. 特征层级概念 ==========

print(f"\n--- 4. 特征层级(从简单到复杂) ---")
print(f"""
  CNN 的深层结构就像一个"特征组装工厂":

  第 1 层(低级特征):
    提取边缘、线条、颜色块
    → 相当于看到图片中最基本的视觉元素

  第 2 层(中级特征):
    把边缘组合成纹理、形状
    → 毛茸茸的纹理、圆形的眼睛、三角形的耳朵

  第 3 层(高级特征):
    把形状组合成物体部件
    → 猫脸、猫爪、猫尾巴

  第 4 层(最终判断):
    把部件组合成完整概念
    → "这是一只猫",置信度 92%

  每一层提取的特征越来越抽象,越来越接近人类理解的"概念"
""")

【运行】 在终端执行:

bash 复制代码
python cv_demo.py

运行后你会看到一个 8×8 的"笑脸"图片被三种不同的卷积核处理,产生了三张特征图:

  • 水平边缘检测:突出了嘴巴(水平线)和方块的上下边缘
  • 垂直边缘检测:突出了方块的左右边缘
  • 锐化:增强了边缘和细节

同时生成的 charts/cv_convolution.png 可以直观看到原图和三种特征图的对比。

4.5 CV 测试要点

测试维度 具体关注点 测试方法
旋转不变性 图片旋转 15 度还认识吗? 对测试图片做旋转增强
缩放不变性 图片放大/缩小还认识吗? 不同分辨率测试
遮挡鲁棒性 物体被部分遮挡还能识别吗? 随机遮挡测试
光照变化 过亮、过暗、阴影下的表现 不同亮度/对比度测试
噪声容忍 加噪声后结果是否稳定 添加高斯噪声、椒盐噪声
对抗攻击 微小像素扰动能骗过模型吗? 对抗样本测试(第 14 篇)
分辨率边界 极小/极大图片的处理 测试边界分辨率
背景干扰 复杂背景下的表现 多样化背景测试

五、语音 ------ 让机器"听"懂声音

5.1 语音技术在做什么

语音技术让机器能"听"和"说"。你手机的语音助手(Siri、小爱同学)、会议自动转录、智能客服,背后都是语音技术。

两大核心任务:

  • ASR(Automatic Speech Recognition,自动语音识别):把语音转成文字。你说"今天天气怎么样",机器输出文字"今天天气怎么样"
  • TTS(Text-to-Speech,语音合成):把文字转成语音。机器读出文字内容,听起来像真人说话

5.2 声波在计算机眼中是什么

就像图片是数字矩阵一样,声音在计算机中是时间序列的数字。

人说话产生声波,麦克风把声波转换成电信号,再采样成一串数字。常见的采样率是 16kHz,即每秒采样 16000 个数字。

处理语音时,通常会把连续的声波切成一小段一小段的帧(通常每帧 25 毫秒),每帧提取出一组特征(比如梅尔频谱系数 MFCC)。这些特征序列就送入模型处理。

5.3 ASR 的处理流程

一个完整的语音识别流程:

音频输入 → 预处理(降噪、分帧) → 特征提取(MFCC/梅尔频谱) → 声学模型(识别音素) → 语言模型(组合成词/句) → 文字输出

用类比来理解:

你听到一句英文"Hello world",你的大脑是这样处理的:

  1. 耳朵接收声波(音频输入)
  2. 大脑过滤掉背景噪音(预处理)
  3. 大脑识别出一个个音节:"hel-lo" "wor-ld"(声学模型)
  4. 大脑根据语境组合成词:"hello" "world"(语言模型)
  5. 你理解了这句话的意思(文字输出)

5.4 语音测试要点

语音测试比 NLP 和 CV 更复杂,因为它涉及多模态------既要有音频质量的考量,又要有文本识别准确性的考量。

测试维度 具体关注点 测试方法
说话人多样性 不同性别、年龄、口音的识别率 多说话人数据集测试
噪声鲁棒性 安静、街道、餐厅环境下的表现 叠加不同环境噪声
语速变化 快速说话、慢速说话 不同语速的录音测试
音量变化 大声、小声的识别率 不同音量级别测试
方言/口音 标准普通话 vs 各地方言 方言数据集测试
专业术语 行业词汇(医学、法律、IT) 领域词汇测试
WER(词错误率) 识别的文字错多少 和人工转写对比
TTS 自然度 合成的语音听起来自然吗 主观评分(MOS)

语音测试的核心指标是 WER(Word Error Rate,词错误率):

WER = (替换 + 删除 + 插入) / 参考文本的词数

翻译:识别出来的文字和正确答案之间,错了多少个词

WER 越低越好。行业水平大致是:

  • WER < 5%:优秀(安静环境、标准口音)
  • WER 5%~15%:良好(一般环境)
  • WER 15%~30%:一般(嘈杂环境或方言)
  • WER > 30%:需要优化

六、三大方向测试方案生成

理解了三大方向的原理和测试要点之后,我们用一个脚本来生成每个方向的测试方案模板。以后你接到任何 AI 测试任务,先跑这个脚本生成测试框架,再往里面填充具体用例。

【新建文件】 在 ai-test/ch12_domains/ 文件夹下新建 domain_test_plan.py,写入以下代码:

python 复制代码
"""
三大 AI 方向测试方案生成器
根据模型类型,自动生成测试维度和建议用例
"""

print("=" * 60)
print("AI 测试方案生成器")
print("=" * 60)


# ========== 测试维度定义 ==========

test_plans = {
    "NLP": {
        "典型任务": ["文本分类", "情感分析", "机器翻译", "文本生成", "问答系统"],
        "核心指标": ["准确率", "精确率", "召回率", "F1", "BLEU", "ROUGE"],
        "测试维度": {
            "正常功能": {
                "描述": "验证核心功能是否正常",
                "用例方向": [
                    "典型正面/负面/中性文本分类",
                    "标准问题的问答准确性",
                    "常见句式的翻译质量",
                ],
                "样本数建议": "10-20 个",
            },
            "否定与反讽": {
                "描述": "测试模型对否定词、反讽的处理",
                "用例方向": [
                    "简单否定:'不是很好'",
                    "双重否定:'不是不满意'",
                    "反讽:'真是好极了才怪'",
                    "反问:'这能好到哪去?'",
                ],
                "样本数建议": "8-15 个",
            },
            "边界情况": {
                "描述": "测试模糊、暧昧的输入",
                "用例方向": [
                    "褒贬混合的文本",
                    "极短文本(1-2个字)",
                    "极长文本(超长输入)",
                    "模糊中性表达",
                ],
                "样本数建议": "5-10 个",
            },
            "异常输入": {
                "描述": "测试模型对异常输入的容错",
                "用例方向": [
                    "空字符串",
                    "纯数字/纯符号",
                    "非目标语言(英文/日文等)",
                    "特殊字符和 emoji",
                ],
                "样本数建议": "5-8 个",
            },
            "鲁棒性": {
                "描述": "测试输入微小变化后的稳定性",
                "用例方向": [
                    "同义词替换后结果是否一致",
                    "加入语气词后结果是否一致",
                    "语序变化后结果是否一致",
                ],
                "样本数建议": "5-10 个",
            },
            "生成质量(如果涉及生成)": {
                "描述": "测试文本生成的质量和安全性",
                "用例方向": [
                    "事实准确性(是否生成虚假信息)",
                    "上下文一致性(多轮对话是否矛盾)",
                    "有害内容检测",
                ],
                "样本数建议": "10-15 个",
            },
        },
    },

    "CV": {
        "典型任务": ["图像分类", "目标检测", "图像分割", "OCR"],
        "核心指标": ["准确率", "Precision", "Recall", "mAP", "IoU"],
        "测试维度": {
            "正常功能": {
                "描述": "标准图片的识别能力",
                "用例方向": [
                    "清晰、标准角度的图片",
                    "不同类别的典型样本",
                    "不同场景的代表性图片",
                ],
                "样本数建议": "20-50 个(每个类别至少 5 个)",
            },
            "变换鲁棒性": {
                "描述": "图片变换后的识别稳定性",
                "用例方向": [
                    "旋转(15°、30°、45°、90°)",
                    "缩放(放大 2 倍、缩小 0.5 倍)",
                    "裁剪(去掉边缘 10%、30%)",
                    "翻转(水平翻转、垂直翻转)",
                ],
                "样本数建议": "每种变换 5-10 个",
            },
            "光照与色彩": {
                "描述": "不同光照条件下的表现",
                "用例方向": [
                    "过亮/过暗的图片",
                    "不同色调(偏红、偏蓝)",
                    "阴影和高光",
                ],
                "样本数建议": "每种条件 5 个",
            },
            "噪声与模糊": {
                "描述": "图片质量下降后的表现",
                "用例方向": [
                    "高斯噪声(不同强度)",
                    "运动模糊",
                    "低分辨率(像素化)",
                ],
                "样本数建议": "每种退化 5 个",
            },
            "异常输入": {
                "描述": "非正常图片输入的处理",
                "用例方向": [
                    "纯黑/纯白图片",
                    "非图片文件(文本改后缀名)",
                    "极小图片(1x1 像素)",
                    "极大图片(超高分辨率)",
                ],
                "样本数建议": "5-8 个",
            },
            "对抗鲁棒性": {
                "描述": "对抗样本攻击的抵抗能力",
                "用例方向": [
                    "FGSM 对抗样本",
                    "像素扰动攻击",
                    "语义对抗(加贴纸、改纹理)",
                ],
                "样本数建议": "10-15 个(第 14 篇详细展开)",
            },
        },
    },

    "语音": {
        "典型任务": ["语音识别(ASR)", "语音合成(TTS)", "声纹识别", "关键词检测"],
        "核心指标": ["WER", "CER", "MOS", "准确率"],
        "测试维度": {
            "正常功能": {
                "描述": "标准语音的识别/合成能力",
                "用例方向": [
                    "标准普通话、标准语速的录音",
                    "安静环境下的语音输入",
                    "常见词汇和句式",
                ],
                "样本数建议": "20-30 条",
            },
            "说话人多样性": {
                "描述": "不同说话人的表现",
                "用例方向": [
                    "男声/女声",
                    "不同年龄段(儿童、青年、老年)",
                    "不同口音/方言",
                ],
                "样本数建议": "每类说话人 5-10 条",
            },
            "环境鲁棒性": {
                "描述": "不同噪声环境下的表现",
                "用例方向": [
                    "安静环境(基准)",
                    "办公室环境(键盘声、交谈声)",
                    "街道环境(车流、人群)",
                    "餐厅环境(餐具、音乐)",
                ],
                "样本数建议": "每种环境 5-10 条",
            },
            "语音特征变化": {
                "描述": "语音本身变化时的表现",
                "用例方向": [
                    "快速说话",
                    "慢速说话",
                    "大声说话/小声说话",
                    "停顿和犹豫(嗯、啊)",
                ],
                "样本数建议": "每种变化 5 条",
            },
            "专业领域": {
                "描述": "领域词汇的识别能力",
                "用例方向": [
                    "医学术语",
                    "技术术语(IT/编程)",
                    "人名/地名/品牌名",
                ],
                "样本数建议": "每领域 10 条",
            },
        },
    },
}


# ========== 生成测试方案 ==========

def generate_plan(domain):
    """为指定方向生成测试方案"""
    if domain not in test_plans:
        print(f"未知方向:{domain}")
        return

    plan = test_plans[domain]

    print(f"\n{'=' * 60}")
    print(f"{domain} 测试方案")
    print(f"{'=' * 60}")

    print(f"\n  典型任务:{'、'.join(plan['典型任务'])}")
    print(f"  核心指标:{'、'.join(plan['核心指标'])}")

    total_cases = 0

    for dimension, info in plan["测试维度"].items():
        print(f"\n  {'─' * 50}")
        print(f"  【{dimension}】")
        print(f"  描述:{info['描述']}")
        print(f"  样本数建议:{info['样本数建议']}")
        print(f"  用例方向:")

        for direction in info["用例方向"]:
            print(f"    - {direction}")

        total_cases += len(info["用例方向"])

    print(f"\n  {'─' * 50}")
    print(f"  测试维度总数:{len(plan['测试维度'])}")
    print(f"  最少用例数:约 {total_cases} 个(每个方向至少 1 个样本)")

    return plan


# ========== 主程序 ==========
if __name__ == "__main__":
    print(f"\n支持的方向:NLP、CV、语音")
    print(f"将依次生成三个方向的完整测试方案\n")

    all_plans = {}
    for domain in ["NLP", "CV", "语音"]:
        plan = generate_plan(domain)
        all_plans[domain] = plan

    # 总结对比
    print(f"\n{'=' * 60}")
    print(f"三大方向测试方案对比总结")
    print(f"{'=' * 60}")
    print(f"\n  {'方向':<6s} {'测试维度数':>8s} {'核心指标':<30s} {'测试复杂度':>8s}")
    print(f"  {'─' * 58}")

    complexity = {"NLP": "中等", "CV": "中等", "语音": "较高"}
    for domain, plan in all_plans.items():
        dims = len(plan["测试维度"])
        metrics = "、".join(plan["核心指标"][:3])
        print(f"  {domain:<6s} {dims:>8d} {metrics:<30s} {complexity[domain]:>8s}")

    print(f"\n  通用测试维度(三个方向都要测):")
    print(f"    - 正常功能测试")
    print(f"    - 异常输入测试")
    print(f"    - 鲁棒性测试")
    print(f"    - 性能测试(延迟、并发、资源)")
    print(f"    - 置信度合理性测试")

【运行】 在终端执行:

bash 复制代码
python domain_test_plan.py

运行后会依次输出 NLP、CV、语音三个方向的完整测试方案,包含每个维度的描述、用例方向和样本数建议。最后还有一个三大方向的对比总结。

这份输出可以直接作为你测试计划的起点------拿到一个模型,先看它是哪个方向的,然后套用对应方案,再根据实际业务场景调整。


七、三大方向测试策略总结

最后把三大方向的测试策略浓缩成一张对比表:

测试环节 NLP CV 语音
测试数据准备 文本语料(标注情感/类别) 图片数据集(标注类别/框/分割) 音频数据(标注转写文本)
数据增强方法 同义替换、加噪声词、回译 旋转、缩放、加噪声、遮挡 加背景噪声、变速、变调
核心评估指标 Accuracy、F1、BLEU、ROUGE Accuracy、mAP、IoU WER、CER、MOS
特有测试项 否定词、反讽、幻觉 旋转/缩放不变性、光照 口音、噪声、语速
对抗攻击类型 文本扰动、Prompt 注入 FGSM、像素扰动、贴纸 对抗音频、超声波
性能测试重点 Token 处理速度、长文本延迟 图片推理延迟、GPU 显存 实时性要求(< 300ms)
典型业务场景 客服机器人、内容审核 人脸检测、医学影像 语音助手、会议转录

通用原则(不管哪个方向都适用):

  1. 先确认模型属于哪个方向、什么任务
  2. 选择对应的评估指标(不要用准确率一个指标打天下)
  3. 按测试维度系统设计用例(正常 → 边界 → 异常 → 对抗 → 鲁棒性)
  4. 关注该方向特有的失败模式
  5. 结合业务场景定义"合格标准"

八、本篇小结

本篇的核心收获:

  • NLP 的核心流程:分词(Token)→ 词嵌入(Embedding)→ 注意力机制(Attention)→ 模型输出
  • CV 的核心操作:卷积(Convolution)提取局部特征,层级结构从边缘到物体
  • 语音的处理流程:音频输入 → 预处理 → 特征提取 → 声学模型 → 语言模型 → 文字输出
  • 三大方向的差异:输入数据不同、核心架构不同、评估指标不同、失败模式不同
  • 测试方案生成器:根据模型方向,系统地生成测试维度和用例方向
  • 测试策略对比:每个方向该关注什么、该用什么指标、该设计什么用例

你现在可以根据"这是什么方向的模型"快速设计针对性的测试方案了。接下来进入 AI 测试核心的下一个主题------数据质量测试。AI 模型的质量有一半取决于数据的质量,"垃圾进垃圾出"是 AI 系统最常见也最容易被忽视的问题。


下一篇:【测AI】第13篇:AI 模型性能测试 ------ 速度、资源与并发

  • 模型推理延迟怎么测?
  • 吞吐量(QPS)与并发压力测试
  • 内存 / GPU 资源占用监控
  • 实战:对一个模型 API 做完整的性能压测
  • 产出性能测试报告
相关推荐
Gu_WenYun1 小时前
基金被套后,如何调整投资策略
人工智能·金融
SEO_juper1 小时前
给网页做可引用性评分:判断内容够不够让 AI 引用(GEO 工具,附代码)
开发语言·人工智能·爬虫·python·seo·独立站
甲维斯1 小时前
戒断Claude之后,被GLM5.3蠢哭了!
人工智能
龙孚信息1 小时前
搜索算法的保质期,正在被AI刷新
人工智能·chatgpt
结构化知识课堂1 小时前
Axure产品原型设计:AI能画原型了,为什么你还得懂这些术语?
人工智能·axure·原型设计·ai产品经理
YH_Analytics1 小时前
2026 年二氧化碳气体回收设备产业链分析报告市场洞察
大数据·人工智能
橙色云-智橙协同研发1 小时前
电子高科技行业:机械与电子(MCAD & ECAD)如何协同?
大数据·运维·服务器·人工智能·安全
AI直播技术杂谈1 小时前
无人直播中控的硬件底线,旧电脑要满足哪些条件
网络·python·ai·云计算
美团技术团队1 小时前
SLM 生成式高并发推理引擎:延迟约束下的有效吞吐优化
人工智能