4、空间分析实战:缺陷密度图绘制、热点图解读、空间相关性分析、聚类算法应用
各位工程师,欢迎来到空间分析实战这一讲。
说实话,在良率分析里,我最怕的就是那种「查了半天,电性参数都正常,但良率就是上不去」的案子。这时候,空间分析往往能一针见血地指出问题。为什么?因为缺陷在晶圆上的分布从来不是随机的——它背后一定藏着某个物理机制。
4.1 缺陷密度图绘制——先看全局
我个人习惯,拿到一批晶圆的缺陷数据,第一件事就是画缺陷密度图。说白了,就是把晶圆划分成一个个小格子,统计每个格子里的缺陷数量,然后用颜色深浅表示出来。
代码其实不复杂,我常用的方法是这样的:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# 假设你有缺陷坐标数据
def plot_defect_density(defect_df, bin_size=50):
"""
defect_df: 包含 'x', 'y' 两列的DataFrame
bin_size: 每个格子的尺寸,单位微米
"""
x_bins = np.arange(0, 30000, bin_size) # 假设晶圆直径30000um
y_bins = np.arange(0, 30000, bin_size)
density, xedges, yedges = np.histogram2d(
defect_df['x'], defect_df['y'],
bins=[x_bins, y_bins]
)
plt.figure(figsize=(10, 8))
plt.imshow(density.T, origin='lower', cmap='hot',
extent=[xedges[0], xedges[-1], yedges[0], yedges[-1]])
plt.colorbar(label='Defect Count')
plt.xlabel('X (um)')
plt.ylabel('Y (um)')
plt.title('Defect Density Map')
plt.show()
这里有个小细节——bin_size的选择很关键。选太大了,热点会被抹平;选太小了,图会变得很稀疏。我在项目中一般先用50um试一下,如果热点不明显,再调小到20um。
4.2 热点图解读——从图案看根因
画完密度图,接下来就是解读了。嗯,这里才是真正考验经验的地方。
常见的缺陷分布图案和对应的根因,我整理了一个表格:
| 分布图案 | 可能根因 | 我的经验 |
|---|---|---|
| 边缘密集 | 刻蚀不均匀、CMP边缘效应 | 先查刻蚀腔体的气体分布,大概率是边缘气流不足 |
| 中心热点 | 光刻胶涂布不均匀、显影液残留 | 我遇到过两次,最后发现是旋涂机的喷嘴堵塞了 |
| 条纹状 | 机械手臂划伤、传送带污染 | 这种最头疼,因为往往不是单一机台的问题 |
| 随机散点 | 颗粒污染、环境因素 | 先查洁净室的粒子计数器,看看是不是HEPA出了问题 |
| 晶圆级对称 | 离子注入角度偏移、退火温度梯度 | 这种通常需要做DOE实验来验证 |
为什么会形成这些图案?你想想看,每个工艺步骤都有它的「指纹」。刻蚀机的气体喷嘴位置是固定的,所以缺陷会集中在某个区域;CMP的抛光垫磨损不均匀,所以边缘和中心会有差异。说白了,热点图就是工艺设备的「X光片」。
4.3 空间相关性分析——量化缺陷之间的「默契」
有时候,光看密度图还不够。比如你发现两个缺陷靠得很近,它们是同一个原因造成的,还是碰巧?这时候就需要空间相关性分析。
我最常用的工具是Ripley's K函数。它的原理很简单:计算在给定距离范围内,缺陷点的平均数量,然后和随机分布做比较。
from scipy.spatial import distance
import numpy as np
def ripleys_k(points, r_max, n_permutations=100):
"""
points: 缺陷坐标数组,shape=(n, 2)
r_max: 最大分析距离
"""
n = len(points)
area = 30000 * 30000 # 晶圆面积
# 计算所有点对之间的距离
dist_matrix = distance.pdist(points)
dist_matrix = distance.squareform(dist_matrix)
# 计算K函数
r_values = np.linspace(0, r_max, 50)
K_obs = []
for r in r_values:
# 统计每个点半径r内的邻居数
count = np.sum(dist_matrix < r, axis=1) - 1 # 减去自身
K = np.sum(count) * area / (n * (n - 1))
K_obs.append(K)
# 随机化检验
K_rand = []
for _ in range(n_permutations):
rand_points = np.random.uniform(0, 30000, (n, 2))
dist_rand = distance.pdist(rand_points)
dist_rand = distance.squareform(dist_rand)
K_r = []
for r in r_values:
count = np.sum(dist_rand < r, axis=1) - 1
K = np.sum(count) * area / (n * (n - 1))
K_r.append(K)
K_rand.append(K_r)
K_rand = np.array(K_rand)
upper = np.percentile(K_rand, 97.5, axis=0)
lower = np.percentile(K_rand, 2.5, axis=0)
return r_values, K_obs, upper, lower
解读结果时,如果K_obs曲线在置信区间之上,说明缺陷在空间上呈聚集分布——它们之间有「默契」。如果在区间之内,那就是随机分布。如果在区间之下,嗯,这种情况很少见,说明缺陷在互相「排斥」,可能是某个区域被保护起来了。
4.4 聚类算法应用——自动发现缺陷群
说到聚类,这是空间分析里最实用的工具之一。当晶圆上有几百上千个缺陷时,人工看热点图已经不够了,我们需要算法来自动识别「缺陷群」。
我个人最推荐DBSCAN算法。为什么?因为它不需要预先指定聚类的数量,而且能自动识别噪声点——说白了,那些孤立的缺陷会被标记为「异常」,不参与聚类。
from sklearn.cluster import DBSCAN
import matplotlib.pyplot as plt
def defect_clustering(defect_df, eps=50, min_samples=5):
"""
eps: 两个样本被视为邻居的最大距离
min_samples: 一个核心点的最小邻居数
"""
coords = defect_df[['x', 'y']].values
# DBSCAN聚类
clustering = DBSCAN(eps=eps, min_samples=min_samples).fit(coords)
labels = clustering.labels_
# 可视化
n_clusters = len(set(labels)) - (1 if -1 in labels else 0)
n_noise = list(labels).count(-1)
plt.figure(figsize=(12, 5))
# 左图:原始缺陷分布
plt.subplot(1, 2, 1)
plt.scatter(defect_df['x'], defect_df['y'], s=10, c='blue')
plt.title(f'Original Defects (n={len(defect_df)})')
plt.xlabel('X')
plt.ylabel('Y')
# 右图:聚类结果
plt.subplot(1, 2, 2)
unique_labels = set(labels)
colors = plt.cm.Spectral(np.linspace(0, 1, len(unique_labels)))
for k, col in zip(unique_labels, colors):
if k == -1:
# 噪声点用灰色
col = [0.5, 0.5, 0.5, 1.0]
class_member_mask = (labels == k)
xy = coords[class_member_mask]
plt.scatter(xy[:, 0], xy[:, 1], s=10, c=[col],
label=f'Cluster {k}' if k != -1 else 'Noise')
plt.title(f'DBSCAN Clusters (n={n_clusters}, noise={n_noise})')
plt.xlabel('X')
plt.ylabel('Y')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
plt.show()
return labels
这里有两个参数需要调:eps和min_samples。我的经验是:
- eps:一般取50-200um。太小了会把一个缺陷群拆成很多小块;太大了会把不同来源的缺陷合并到一起。
- min_samples:一般取3-10。这个值越小,越容易形成小聚类;越大,聚类越少但更可靠。
我记得有一次,一个客户说他们的良率突然掉了5%。我拿数据跑了一遍DBSCAN,发现晶圆中心有一个直径约2mm的缺陷群。顺着这个线索查下去,最后发现是光刻机的掩模版上沾了一颗微尘。你看,一个聚类分析,直接省了三天的排查时间。
好了,空间分析这一块,核心就是三步走:先画密度图看全局,再用相关性分析量化聚集程度,最后用聚类算法自动识别缺陷群。每一步都有它的价值,缺一不可。
下一讲,我们会聊聊时间序列分析——缺陷是怎么随着工艺步骤累积的。到时候见。