4. 特征提取技术:峰值检测、斜率变化点、积分面积比、主成分分析(PCA)
各位做刻蚀工艺的同行,咱们今天聊聊特征提取。说白了,就是从原始的光学发射光谱(OES)信号里,把那些能反映刻蚀终点的小特征给揪出来。
我刚开始做终点检测那会儿,总觉得原始信号挺干净的,直接设个阈值不就完了?后来被现实狠狠教育了一顿——等离子体噪声、腔室老化、气体流量波动,哪个都能把信号搞得面目全非。所以,特征提取这一步,其实比你想的重要得多。
4.1 峰值检测:最直观的终点信号
峰值检测,名字听着简单,做起来有讲究。我们通常关注的是特定波长的发射强度变化。比如刻蚀SiO₂时,我会盯着483nm的CO谱线——当氧化物被刻穿,CO信号会突然下降,形成一个明显的峰值拐点。
核心思路: 不是找最高点,而是找变化最剧烈的点。
我习惯用一阶导数来辅助判断。代码实现也不复杂:
import numpy as np
def peak_detection(signal, threshold=0.05):
"""
基于一阶导数的峰值检测
signal: 原始OES信号
threshold: 变化率阈值
"""
diff = np.diff(signal)
# 找导数由正转负的点
peaks = []
for i in range(1, len(diff)):
if diff[i-1] > threshold and diff[i] < -threshold:
peaks.append(i)
return peaks
嗯,这里要注意。阈值设得太小,噪声会被当成终点;设得太大,可能终点都过了还没触发。我一般会先用一段历史数据跑一遍,看看正常终点的导数幅值大概在什么范围。
实战技巧: 我曾经遇到过一个案例,信号里有个假峰,跟终点峰长得几乎一模一样。后来我加了宽度约束——真正的终点峰通常持续几十毫秒,而噪声尖峰一闪就没了。加个最小宽度过滤,效果立竿见影。
4.2 斜率变化点:捕捉细微的转折
有些刻蚀工艺,终点信号不是陡降,而是缓慢变化。比如深硅刻蚀,终点信号可能就是个平缓的斜坡。这时候峰值检测就不太灵了。
斜率变化点,说白了就是找信号斜率发生明显改变的位置。我常用的是滑动窗口线性拟合:
def slope_change_point(signal, window=10):
"""
滑动窗口计算斜率变化
"""
slopes = []
for i in range(len(signal) - window):
x = np.arange(window)
y = signal[i:i+window]
coeffs = np.polyfit(x, y, 1)
slopes.append(coeffs[0])
# 找斜率变化最大的位置
slope_diff = np.diff(slopes)
change_point = np.argmax(np.abs(slope_diff))
return change_point
你想想看,窗口大小怎么选?窗口太小,对噪声敏感;窗口太大,反应迟钝。我个人习惯窗口大小取采样率的1/10左右,比如采样率100Hz,窗口就设10个点。
避坑指南: 我曾经在刻蚀氮化硅时用过这个方法,结果发现斜率变化点总是滞后。后来排查发现,是因为窗口内包含了终点后的数据,把斜率拉平了。解决办法是只取终点前一段数据做拟合,或者用加权窗口,越靠近当前时刻权重越大。
4.3 积分面积比:抗噪声的利器
积分面积比,这招是我从老工程师那儿学来的。原理很简单:选两条谱线,一条对刻蚀过程敏感(比如反应物),一条相对稳定(比如载气)。然后计算它们的积分面积比值。
为什么这招好用?因为噪声通常是共模的——两条谱线同时受干扰,但比值变化不大。这就相当于做了个共模抑制。
| 谱线选择 | 敏感谱线 | 参考谱线 | 应用场景 |
|---|---|---|---|
| SiO₂刻蚀 | 483nm (CO) | 703nm (Ar) | 氧化物刻蚀终点 |
| Si刻蚀 | 288nm (Si) | 703nm (Ar) | 硅刻蚀终点 |
| 金属刻蚀 | 396nm (Al) | 750nm (Ar) | 铝刻蚀终点 |
def integral_ratio(signal_sensitive, signal_ref, window=50):
"""
计算积分面积比
"""
int_sensitive = np.sum(signal_sensitive[-window:])
int_ref = np.sum(signal_ref[-window:])
if int_ref == 0:
return 0
return int_sensitive / int_ref
我建议积分窗口不要太大,50个采样点左右就够。窗口太大,会把历史数据也卷进来,终点信号反而被稀释了。
4.4 主成分分析(PCA):降维的艺术
PCA,听起来高大上,其实核心就一句话:把多个波长的信号压缩成几个关键成分。你想想看,OES数据动辄几百个波长通道,每个通道都分析一遍,不现实。PCA能帮你找到那些「最能解释数据变化」的方向。
我做PCA的流程是这样的:
- 数据标准化:每个波长通道减去均值,除以标准差。这一步不能省,不然强信号通道会主导分析结果。
- 计算协方差矩阵:看看各通道之间的相关性。
- 特征值分解:找到主成分方向。
- 投影:把原始数据投影到前几个主成分上。
from sklearn.decomposition import PCA
def oes_pca(data, n_components=2):
"""
data: 形状为 (n_samples, n_wavelengths) 的OES数据
n_components: 保留的主成分数量
"""
# 标准化
data_std = (data - np.mean(data, axis=0)) / np.std(data, axis=0)
# PCA
pca = PCA(n_components=n_components)
transformed = pca.fit_transform(data_std)
# 查看各主成分的方差解释比例
explained_variance = pca.explained_variance_ratio_
print(f"前{n_components}个主成分解释了 {np.sum(explained_variance)*100:.1f}% 的方差")
return transformed, pca
关键点: 我一般保留前2-3个主成分。第一个主成分通常代表整体强度变化,第二个主成分往往能捕捉到终点信号。为什么?因为终点信号是局部变化,跟整体漂移是正交的。
我记得有一次,客户说他们的终点信号被腔室老化干扰得完全看不出来。我拿PCA一跑,第二主成分里终点信号清清楚楚。说白了,PCA帮你把「有用信号」和「干扰信号」分到了不同的通道里。
实战建议: PCA模型不是一劳永逸的。腔室条件变了、工艺配方改了,之前训练的主成分可能就不适用了。我习惯每周重新训练一次PCA模型,或者在新工艺验证时重新跑一遍。
4.5 四种方法的对比与选择
说了这么多,到底该用哪种?我整理了个对比表,方便你根据实际情况选:
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 峰值检测 | 简单直观,计算快 | 对噪声敏感,需要调参 | 信号变化剧烈的工艺 |
| 斜率变化点 | 能捕捉缓慢变化 | 窗口大小难选 | 深硅刻蚀等缓变工艺 |
| 积分面积比 | 抗噪声能力强 | 需要选两条合适的谱线 | 噪声大的工艺环境 |
| PCA | 自动降维,提取关键信息 | 需要训练数据,解释性差 | 多波长、复杂工艺 |
我个人习惯是:先用PCA看看数据里有没有明显的终点特征。如果有,再根据信号特点选峰值检测或斜率变化点。如果噪声大,就上积分面积比。四种方法不是互斥的,组合使用效果更好。
好了,特征提取这块就聊到这儿。下一节咱们会讲怎么把这些特征组合成最终的终点判决逻辑。记住,没有万能的方法,只有最适合你工艺的方法。
公众号:蓝海资料掘金营,微信deep3321