4、数据清洗与预处理:缺失值处理、异常值检测、数据标准化与归一化
各位工程师,咱们接着聊。上一章我们把数据从FDC、EES、测试机这些源头拽了进来,但说实话,这些数据直接扔进模型里,十有八九要出问题。为什么?因为半导体产线的数据,脏得很。
我见过太多新手,拿到数据就急着跑算法,结果模型一塌糊涂。其实,数据清洗和预处理才是整个良率分析里最耗时的环节,没有之一。我个人习惯,花在这个阶段的时间,至少要占到整个项目的60%以上。你想想看,垃圾进,垃圾出,这个道理在半导体行业尤其残酷。
4.1 缺失值处理:产线数据的老大难
产线数据缺失,太常见了。传感器偶尔掉线、机台维护期间数据没记录、或者某些参数在特定工艺步骤本来就不采集。嗯,这里要注意,处理缺失值之前,你得先搞清楚它为什么缺失。
我把它分成三类:
- 完全随机缺失:比如某个传感器突然被干扰了一下,丢了一个数据点。这种最省心。
- 随机缺失:比如某个机台在特定Recipe下,某个参数经常不记录。这跟其他变量有关,但跟它自己没关系。
- 非随机缺失:这个最麻烦。比如当晶圆缺陷密度过高时,检测机台直接报错不输出数据。缺失本身就跟良率相关,处理不好会引入偏差。
怎么处理?我常用的方法有这几种:
4.1.1 直接删除法
简单粗暴。如果某个参数缺失比例超过70%,我一般直接扔掉这个特征。如果某条记录(某片晶圆)的关键参数缺失太多,也直接删掉。
4.1.2 填充法
对于缺失比例不高的数据,填充是主流。我常用的填充策略:
| 填充方法 | 适用场景 | 我的经验 |
|---|---|---|
| 均值/中位数填充 | 数据分布较对称,且缺失比例<5% | 简单,但会降低方差,适合快速预览 |
| 前向/后向填充 | 时间序列数据,如机台腔体温度 | 产线数据常用,但要注意机台切换Recipe时的断点 |
| KNN填充 | 特征间相关性较强 | 效果好,但计算量大,我一般只用在关键参数上 |
| 模型预测填充 | 缺失值与其他特征有明确关系 | 比如用其他机台参数预测某个缺失的膜厚值 |
代码示例,用Python的pandas和sklearn做个简单演示:
import pandas as pd
from sklearn.impute import KNNImputer
# 假设df是我们的良率数据
# 先用中位数填充简单的缺失
df['Temperature'].fillna(df['Temperature'].median(), inplace=True)
# 对于关键参数,用KNN填充
imputer = KNNImputer(n_neighbors=5)
df[['Pressure', 'Gas_Flow', 'RF_Power']] = imputer.fit_transform(df[['Pressure', 'Gas_Flow', 'RF_Power']])
4.2 异常值检测:揪出产线上的“坏孩子”
异常值,说白了就是那些跟大多数数据格格不入的点。在半导体产线里,异常值往往意味着机台报警、工艺偏移或者测量错误。我个人习惯,异常值检测不是一次性工作,而是迭代的。
常用的方法:
4.2.1 基于统计的方法
最经典的就是3σ原则。假设数据服从正态分布,超过均值±3个标准差的数据就是异常。但说实话,产线数据很多并不服从正态分布,这时候我会用箱线图法(IQR)。
4.2.2 基于距离的方法
比如LOF(局部异常因子)。这个方法适合发现局部异常点。我记得有一次,某个机台的整体参数都在正常范围内,但LOF算法揪出了几个点,后来一查,是那个批次的晶圆在腔体里停留时间长了3秒。这种全局看正常、局部看异常的情况,LOF特别好用。
4.2.3 基于模型的方法
比如孤立森林。这个方法速度快,适合高维数据。我经常用它来做第一轮粗筛。
代码示例:
from sklearn.ensemble import IsolationForest
# 孤立森林检测异常
iso_forest = IsolationForest(contamination=0.05, random_state=42)
df['anomaly'] = iso_forest.fit_predict(df[['Pressure', 'Temperature', 'Gas_Flow']])
# -1表示异常,1表示正常
anomaly_data = df[df['anomaly'] == -1]
print(f"发现 {len(anomaly_data)} 个异常点")
4.3 数据标准化与归一化:让所有参数站在同一起跑线
为什么要做这一步?你想想看,温度是几百度,压力是几十帕,气体流量是几千sccm。这些数值的量纲完全不同。如果你直接拿原始数据跑模型,那些数值大的特征会主导模型,数值小的特征就被淹没了。
我常用的两种方法:
4.3.1 归一化(Min-Max Scaling)
把数据缩放到[0, 1]区间。公式很简单:
X_scaled = (X - X_min) / (X_max - X_min)
适合数据有明确边界的情况,比如温度范围0-500℃。但要注意,如果数据里有异常值,归一化会把正常数据压缩到很小的区间里。
4.3.2 标准化(Z-score Scaling)
把数据变成均值为0,标准差为1的分布。公式:
X_scaled = (X - μ) / σ
这个我用的最多。它不依赖数据的最大值最小值,对异常值的鲁棒性更好。而且很多机器学习算法(比如SVM、PCA)都假设数据是标准化的。
代码示例:
from sklearn.preprocessing import StandardScaler, MinMaxScaler
# 标准化
scaler_std = StandardScaler()
df_std = scaler_std.fit_transform(df[['Pressure', 'Temperature']])
# 归一化
scaler_mm = MinMaxScaler()
df_mm = scaler_mm.fit_transform(df[['Pressure', 'Temperature']])
好了,数据清洗和预处理这块,核心就是这三板斧:缺失值处理、异常值检测、标准化/归一化。做扎实了,后面的建模工作才能事半功倍。下一章,我们聊聊特征工程,那才是真正考验工程师经验的地方。