使用PaddleClas完成半导体晶圆图谱缺陷种类识别 - 学习笔记
1. 项目概述
- 目标: 利用飞桨(PaddlePaddle)的PaddleClas图像分类套件,对半导体晶圆缺陷图谱进行自动分类识别。
- 意义: 通过深度学习技术识别晶圆图谱的缺陷模式,辅助工程师快速定位半导体制造过程中产生缺陷的根源,从而改进工艺,提升良品率,助力智能制造。
- 技术栈: PaddlePaddle 2.3.2, PaddleClas, Python 3, JupyterLab。
- 数据集: WM-811K (项目内已预处理)。
2. 项目背景
- 半导体晶圆: 制造集成电路(芯片)的基础载体。
- 制造过程: 极其复杂,包含薄膜、光刻、刻蚀等重复步骤,任何环节异常都可能导致晶圆缺陷。
- 晶圆图谱 (Wafer Map): 对晶圆上每个芯片进行电性测试后,将测试结果(正常/异常)可视化展示的图。异常芯片的空间分布模式往往能反映特定的制造问题。
- 例如: 图谱中出现长条状的连续失效芯片,可能由物理划伤(Scratch)导致。
- 缺陷分类的重要性: 准确识别图谱模式(如中心缺陷 Center、边缘局部缺陷 Edge-Loc、甜甜圈状缺陷 Donut 等)有助于追溯问题工序。
3. 数据集介绍与准备 (WM-811K)
-
来源: MIR Lab 公开数据集 (http://mirlab.org/dataSet/public/)。
-
原始格式: MATLAB
.mat
文件和 Python.pkl
文件。 -
规模: 原始包含 811,457 张图,其中 172,950 张带有 9 种缺陷类别标签 (0-8)。
-
项目使用数据:
- 从
.pkl
文件转换得到的.jpg
图像格式。 - 选取了部分带标签数据制作成 PaddleClas 要求的格式。
- 位于项目路径
/home/aistudio/data/data188959/waferMap.zip
。
- 从
-
数据解压:
# 查看数据集压缩包 !ls /home/aistudio/data/data188959/ # 输出应为: waferMap.zip # 解压到工作目录 !unzip /home/aistudio/data/data188959/waferMap.zip -d /home/aistudio/work/
-
数据集结构 (PaddleClas 标准格式):
# 查看解压后的目录结构 !tree -L 1 /home/aistudio/work/ # 输出应类似: # /home/aistudio/work/ # ├── img # 存放所有训练和验证用的 jpg 图片 # ├── label_list.txt # 标签 ID 到标签名称的映射文件 # ├── test # 存放用于推理测试的 jpg 图片 # ├── train.txt # 训练集列表,每行: "图片相对路径 标签ID" # └── val.txt # 验证集列表,格式同 train.txt
-
标签文件格式 (
train.txt
,val.txt
):# 查看 train.txt 前 10 行 !head -10 /home/aistudio/work/train.txt # 输出示例: # Center_101787.jpg 0 # Center_106264.jpg 0 # ... (图片文件名 空格 类别数字ID)
-
标签映射文件 (
label_list.txt
): (内容未在项目中直接展示,但根据代码推断其格式应为)0 Center 1 Donut 2 Edge-Loc 3 Edge-Ring 4 Loc 5 Random 6 Scratch 7 Near-full # 注意:原始数据集有9类 (0-8),但项目中实际可视化的只有8类 (0-7),可能第8类样本较少或未包含在子集中。
4. 数据预览
-
目的:直观了解不同缺陷类别的图谱特征。
-
方法:从
label_list.txt
获取类别名称,然后在img
目录下随机选取每个类别的若干图片进行可视化。 -
可视化代码:
# 导入必要的库 import os import random import matplotlib.pyplot as plt import cv2 %matplotlib inline # 在Jupyter中显示图像 # 缺陷类别字典 (根据项目代码和 label_list.txt 推断) defect_dict = {0: "Center", 1:"Donut", 2:"Edge-Loc", 3:"Edge-Ring", 4:"Loc", 5:"Random", 6:"Scratch", 7:"Near-full"} img_dir = "/home/aistudio/work/img" img_list = os.listdir(img_dir) # 从每种缺陷中随机选取 N 张图片 single_defect_num = 3 # 每类选3张 select_list = [] print("Selecting images for visualization...") for defect_id, defect_name in defect_dict.items(): count = 0 # 筛选出属于当前类别的图片 candidate_images = [img for img in img_list if img.startswith(defect_name + "_")] if not candidate_images: print(f"Warning: No images found for defect type {defect_name}") continue # 随机选择不重复的图片 selected_for_defect = random.sample(candidate_images, min(len(candidate_images), single_defect_num)) select_list.extend(selected_for_defect) print(f"Selected {len(selected_for_defect)} images for {defect_name}") print("\nSelected image list:", select_list) # 可视化选择的图片 num_classes = len(defect_dict) plt.figure(figsize=(10, 2*num_classes)) # 调整图像大小以便更好显示 for index, img_name in enumerate(select_list): img_path = os.path.join(img_dir, img_name) try: img_data = cv2.imread(img_path) if img_data is None: print(f"Warning: Could not read image {img_path}") continue plt.subplot(num_classes, single_defect_num, index + 1) plt.imshow(cv2.cvtColor(img_data, cv2.COLOR_BGR2RGB)) # Matplotlib 使用 RGB plt.title(img_name, fontsize=8) # 调整字体大小 plt.axis("off") except Exception as e: print(f"Error processing image {img_path}: {e}") plt.tight_layout() # 调整子图间距 plt.show()
-
缺陷模式观察:
- Center: 缺陷芯片集中在晶圆中心区域。
- Donut: 缺陷芯片呈环状分布,像甜甜圈。
- Edge-Loc: 缺陷芯片集中在晶圆边缘的某个局部区域。
- Edge-Ring: 缺陷芯片沿着晶圆边缘形成一个环。
- Loc: 缺陷芯片在某个局部区域聚集(非中心、非边缘)。
- Random: 缺陷芯片随机分布,无明显模式。
- Scratch: 缺陷芯片呈线状或条带状分布,通常由划伤引起。
- Near-full: 晶圆大部分区域都是缺陷芯片。
5. 开发环境准备 (PaddleClas)
-
安装PaddleClas:
- PaddleClas是飞桨官方的图像识别套件,包含丰富的模型库和工具。
- 推荐从 Gitee 克隆(国内速度更快)或使用项目提供的压缩包。
# 切换到工作目录 %cd /home/aistudio # 解压项目提供的 PaddleClas 压缩包 (假设已上传或存在) # !unzip -q /home/aistudio/PaddleClas.zip # -q 表示静默模式 # 或者,从 Gitee 克隆 (如果网络允许) # !git clone https://gitee.com/paddlepaddle/PaddleClas.git
-
安装依赖库:
# 进入 PaddleClas 目录 %cd /home/aistudio/PaddleClas # 安装依赖,使用国内镜像加速 !pip install --upgrade -r requirements.txt -i https://mirror.baidu.com/pypi/simple
6. 模型训练
- PaddleClas优势: 提供预定义好的模型结构和训练流程,用户主要通过修改
.yaml
配置文件来适配自己的任务。 - 选用模型:
- ResNet50: 经典的深度残差网络,性能较好,常用于服务器端。
- MobileNetV3_large_x0_75: 轻量级网络,速度快,适合移动端或资源受限场景。
6.1 ResNet50 模型训练
-
配置文件:
/home/aistudio/PaddleClas/ppcls/configs/ImageNet/ResNet/ResNet50.yaml
-
关键配置修改: (在原始 ResNet50.yaml 基础上)
# Global settings Global: ... epochs: 200 # 训练轮数 print_batch_step: 10 # 每隔多少个 batch 打印一次日志 use_visualdl: True # 启用 VisualDL 进行训练过程可视化 ... # Optimizer settings Optimizer: name: Momentum momentum: 0.9 lr: name: Piecewise # 学习率衰减策略:分段衰减 learning_rate: 0.01 # 初始学习率 decay_epochs: [50, 100, 150] # 在这些 epoch 节点进行衰减 values: [0.01, 0.005, 0.001, 0.0005] # 对应各阶段的学习率 ... # DataLoader settings for Training DataLoader: Train: dataset: name: ImageNetDataset # 数据集读取器类型 image_root: /home/aistudio/work/img/ # 图片存放根目录 cls_label_path: /home/aistudio/work/train.txt # 训练集标签文件路径 ... # DataLoader settings for Evaluation Eval: dataset: name: ImageNetDataset image_root: /home/aistudio/work/img/ # 图片存放根目录 cls_label_path: /home/aistudio/work/val.txt # 验证集标签文件路径 ... # Inference settings (for prediction phase) Infer: infer_imgs: /home/aistudio/work/test # 推理时默认读取的图片或目录 batch_size: 10 # 推理时的批大小 ... PostProcess: name: Topk topk: 5 # 推理时输出 Top-5 结果 class_id_map_file: /home/aistudio/work/label_list.txt # 标签映射文件,用于显示类别名称 ...
- 注意: 上述 YAML 代码块是根据原文描述的关键修改点进行的重组,并非完整文件。核心是修改数据集路径、学习率策略和训练轮数等。
-
启动训练:
# 确保在 PaddleClas 目录下 %cd /home/aistudio/PaddleClas # 运行训练脚本 !python tools/train.py \ -c ppcls/configs/ImageNet/ResNet/ResNet50.yaml \ -o Global.output_dir="output/ResNet50_wafer" # (可选)指定输出目录
- 训练日志会显示 Loss、Accuracy 等指标。如果
use_visualdl: True
,可以在 AI Studio 左侧 “可视化” 面板查看训练曲线。 - PiecewiseDecay: 学习率在指定
decay_epochs
时跳变下降,简单直接。
- 训练日志会显示 Loss、Accuracy 等指标。如果
6.2 MobileNetV3 模型训练
-
配置文件:
/home/aistudio/PaddleClas/ppcls/configs/ImageNet/MobileNetV3/MobileNetV3_large_x0_75.yaml
-
关键配置修改 (与 ResNet50 类似,但有不同):
- Arch: 模型结构已是 MobileNetV3_large_x0_75。
- LR Scheduler: 通常使用
Cosine
(余弦衰减) 配合Warmup
。base_lr
: 0.5 (相对较大,因为常配合大学习率策略)warmup_epoch
: 5 (前 5 个 epoch 学习率逐渐从 0 增长到base_lr
)epochs
: 360 (轻量模型可能需要更多轮次)batch_size
: 128 (需要较大显存,如 V100 32G。若显存不足,需减小此值)
- DataLoader/Infer: 同样需要修改
image_root
,cls_label_path
,infer_imgs
,class_id_map_file
的路径指向晶圆数据集。
-
启动训练:
# 确保在 PaddleClas 目录下 %cd /home/aistudio/PaddleClas # 运行训练脚本 !python tools/train.py \ -c ppcls/configs/ImageNet/MobileNetV3/MobileNetV3_large_x0_75.yaml \ -o DataLoader.Train.sampler.batch_size=128 \ -o DataLoader.Eval.sampler.batch_size=128 \ -o Global.epochs=360 \ # (其他路径和学习率相关的修改建议直接在 YAML 文件中完成,或用 -o 逐一指定) -o Global.output_dir="output/MobileNetV3_large_x0_75_wafer"
- CosineDecay + Warmup: 学习率先从小增到设定值(Warmup),然后按余弦曲线平滑下降到接近 0。Warmup 有助于训练初期稳定。
- 显存问题: 如果遇到
Shared Memory
或 OOM (Out of Memory) 错误,首要尝试是减小-o DataLoader.Train.sampler.batch_size
和-o DataLoader.Eval.sampler.batch_size
的值。
7. 模型评估
-
目的: 在验证集 (val.txt) 上评估训练好的模型的性能指标。
-
方法: 使用
tools/eval.py
脚本,指定配置文件和训练得到的最佳模型权重 (best_model.pdparams
)。 -
关注指标: Top-1 Accuracy (最常用的分类精度指标), Loss,
-
评估 ResNet50:
%cd /home/aistudio/PaddleClas/ !python tools/eval.py \ -c ppcls/configs/ImageNet/ResNet/ResNet50.yaml \ -o Global.pretrained_model=output/ResNet50_wafer/best_model # 指定训练保存的最佳模型路径
-
评估 MobileNetV3:
%cd /home/aistudio/PaddleClas/ !python tools/eval.py \ -c ppcls/configs/ImageNet/MobileNetV3/MobileNetV3_large_x0_75.yaml \ -o Global.pretrained_model=output/MobileNetV3_large_x0_75_wafer/best_model # 指定训练保存的最佳模型路径
- 评估结果会输出 Top-1 Acc, Top-5 Acc 等。
8. 模型预测
-
目的: 使用训练好的模型对新的、未知的图片(如此处的
test
目录下的图片)进行分类预测。 -
方法: 使用
tools/infer.py
脚本。 -
使用 ResNet50 进行单张图片预测:
%cd /home/aistudio/PaddleClas/ !python tools/infer.py \ -c ppcls/configs/ImageNet/ResNet/ResNet50.yaml \ -o Global.pretrained_model=output/ResNet50_wafer/best_model \ -o Infer.infer_imgs=/home/aistudio/work/test/Center_85238.jpg # 指定要预测的单张图片
- 输出会包含预测的类别 ID、置信度分数和对应的类别名称(如果配置了
class_id_map_file
)。
- 输出会包含预测的类别 ID、置信度分数和对应的类别名称(如果配置了
9. 模型导出
-
目的: 将训练好的模型(包含模型结构和权重)转换成适合部署的推理模型 (Inference Model)。推理模型是固化后的模型,加载速度更快,且不包含训练相关的操作。
-
方法: 使用
tools/export_model.py
脚本。 -
导出文件:
inference.pdmodel
: 存储模型网络结构。inference.pdiparams
: 存储模型权重。inference.pdiparams.info
: 存储参数信息(分类任务通常可忽略)。
-
导出 ResNet50 推理模型:
%cd /home/aistudio/PaddleClas/ !python tools/export_model.py \ -c ppcls/configs/ImageNet/ResNet/ResNet50.yaml \ -o Global.pretrained_model=output/ResNet50_wafer/best_model \ -o Global.save_inference_dir=deploy/models/ResNet50_wafer_deploy # 指定导出模型的保存路径
-
导出 MobileNetV3 推理模型:
%cd /home/aistudio/PaddleClas/ !python tools/export_model.py \ -c ppcls/configs/ImageNet/MobileNetV3/MobileNetV3_large_x0_75.yaml \ -o Global.pretrained_model=output/MobileNetV3_large_x0_75_wafer/best_model \ -o Global.save_inference_dir=deploy/models/MobileNetV3_wafer_deploy # 指定导出模型的保存路径
-
查看导出结果:
!tree -L 2 deploy/models/ResNet50_wafer_deploy # 输出应包含 inference.pdmodel, inference.pdiparams 等文件 !tree -L 2 deploy/models/MobileNetV3_wafer_deploy # 输出应包含 inference.pdmodel, inference.pdiparams 等文件
10. 推理部署 (使用导出的模型)
- 目的: 使用导出的推理模型进行批量预测,模拟实际部署场景。
- 脚本: PaddleClas 提供了专门的推理脚本
deploy/python/predict_cls.py
。 - 配置: 需要修改推理配置文件
deploy/configs/inference_cls.yaml
。
10.1 使用 ResNet50 导出模型进行推理
-
修改
inference_cls.yaml
:Global.inference_model_dir
: 修改为 ResNet50 导出模型的路径 (deploy/models/ResNet50_wafer_deploy
)。Global.infer_imgs
: 修改为测试图片目录 (/home/aistudio/work/test
)。PostProcess.Topk.class_id_map_file
: 修改为标签映射文件路径 (/home/aistudio/work/label_list.txt
)。PreProcess
: 确保预处理步骤与训练时一致 (Resize, Crop, Normalize)。
-
运行推理脚本:
%cd /home/aistudio/PaddleClas/deploy !python python/predict_cls.py -c configs/inference_cls.yaml
- 脚本会遍历
infer_imgs
目录下的所有图片,并输出每张图片的 Top-k 预测结果。 - 原文分析指出,在测试集(75张图)上,ResNet50 模型预测错了 5 张。
- 脚本会遍历
10.2 使用 MobileNetV3 导出模型进行推理
-
创建/修改配置文件: 建议复制
inference_cls.yaml
为inference_cls_mobilenetv3.yaml
,然后修改:Global.inference_model_dir
: 修改为 MobileNetV3 导出模型的路径 (deploy/models/MobileNetV3_wafer_deploy
)。- 其他路径 (
Global.infer_imgs
,PostProcess.Topk.class_id_map_file
) 确认与 ResNet50 推理时一致。 PostProcess.Topk.topk
: 可以改为 1,只看 Top-1 预测结果。
-
运行推理脚本:
%cd /home/aistudio/PaddleClas/deploy !python python/predict_cls.py -c configs/inference_cls_mobilenetv3.yaml
- 原文分析指出,MobileNetV3 在测试集上仅预测错误 3 张,准确率达到 96%。
11. 推理结果分析与可视化
-
目的: 分析模型预测错误的样本,找出模型可能的弱点或数据本身的挑战。
-
方法: 将推理过程中判断错误的图片及其错误预测标签进行可视化展示。
-
错误样本可视化代码 (以 ResNet50 为例):
import os import pandas as pd # 如果需要处理表格化的预测结果 import cv2 import matplotlib.pyplot as plt %matplotlib inline img_root = "/home/aistudio/work/test" # 测试图片目录 # ResNet50 预测错误的图片列表 (根据原文记录) wrong_list_resnet = ['Edge-Loc_48272.jpg', 'Edge-Loc_58508.jpg', 'Edge-Loc_7413.jpg', 'Loc_87266.jpg', 'Scratch_355662.jpg'] # ResNet50 对应的错误预测标签 (根据原文记录) wrong_label_resnet = ['Loc','Edge-Ring','Loc','Donut','Loc'] print("Visualizing ResNet50 Misclassified Images:") plt.figure(figsize=(15, 4)) # 调整图像大小 for i in range(len(wrong_list_resnet)): img_path = os.path.join(img_root, wrong_list_resnet[i]) try: img = cv2.imread(img_path) if img is None: continue plt.subplot(1, len(wrong_list_resnet), i + 1) plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) # 从文件名获取真实标签 true_label = wrong_list_resnet[i].split('_')[0] plt.xlabel(f"True: {true_label}\nFile: {wrong_list_resnet[i]}", fontsize=9) plt.title(f"Predicted: {wrong_label_resnet[i]}", fontsize=10) plt.xticks([]) # 隐藏 x 轴刻度 plt.yticks([]) # 隐藏 y 轴刻度 except Exception as e: print(f"Error plotting {wrong_list_resnet[i]}: {e}") plt.tight_layout() plt.show() # MobileNetV3 预测错误的图片列表 (根据原文记录) wrong_list_mobilenet = ['Donut_7334.jpg', 'Edge-Loc_48272.jpg', 'Loc_94941.jpg'] # MobileNetV3 对应的错误预测标签 (根据原文记录) wrong_label_mobilenet = ['Random','Loc','Donut'] print("\nVisualizing MobileNetV3 Misclassified Images:") plt.figure(figsize=(9, 4)) # 调整图像大小 for i in range(len(wrong_list_mobilenet)): img_path = os.path.join(img_root, wrong_list_mobilenet[i]) try: img = cv2.imread(img_path) if img is None: continue plt.subplot(1, len(wrong_list_mobilenet), i + 1) plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) true_label = wrong_list_mobilenet[i].split('_')[0] plt.xlabel(f"True: {true_label}\nFile: {wrong_list_mobilenet[i]}", fontsize=9) plt.title(f"Predicted: {wrong_label_mobilenet[i]}", fontsize=10) plt.xticks([]) plt.yticks([]) except Exception as e: print(f"Error plotting {wrong_list_mobilenet[i]}: {e}") plt.tight_layout() plt.show()
-
分析:
- 观察发现,模型较容易混淆
Loc
,Edge-Loc
,Center
等类别。 - 原因推测: 晶圆图谱分类与缺陷的空间位置强相关(例如,同样的局部聚集,在中心是Center,在边缘是Edge-Loc),这与传统图像分类任务追求的位置不变性有所不同。模型可能难以精确学习这种严格的位置依赖关系,特别是当不同类别的模式在视觉上相似时。
- 改进方向:
- 增加数据: 收集更多易混淆类别的样本,特别是边界情况的样本。
- 数据增强: 设计更针对性的数据增强策略,模拟位置变化。
- 模型结构: 探索是否可以引入位置信息或使用更适合捕捉空间关系的注意力机制等。
- 后处理: 结合规则或先验知识进行后处理判断。
- 观察发现,模型较容易混淆
12. 总结
- 本项目成功演示了如何使用 PaddleClas 套件快速搭建一个针对半导体晶圆图谱缺陷的图像分类解决方案,覆盖了从数据准备、模型训练、评估、预测到模型导出和部署推理的完整流程。
- 结果表明,ResNet50 和 MobileNetV3 都能在该任务上取得较好的效果(MobileNetV3 在此数据集子集上表现更优,达到 96% 测试准确率),验证了深度学习在半导体智能制造领域应用的潜力。
- 项目也揭示了晶圆图谱分类任务的特点(位置敏感性),并为后续优化指明了方向。
- PaddleClas 作为一个强大的图像识别开发套件,极大地简化了模型开发和实验的流程。