You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

小尺寸向量中异常值(尖峰)定位方法求助

小样本向量尖峰检测的可行方案

针对样本量极小(5-7个数据点)、尖峰数量可能占比极高的场景,固定阈值的方法显然无法适配变化的数据分布,下面提供几个更灵活的解决方案:

方法1:基于相邻差值突变的自适应截断

核心思路是:尖峰和非尖峰数据之间的差值,会远大于非尖峰内部的波动差值。通过排序后找差值突变点,就能自动区分两类数据。

代码实现

import numpy as np

def find_spikes(p, k=1.5):
    sorted_p = np.sort(p)
    diffs = np.diff(sorted_p)
    # 用中位数判断差值突变,避免极端值干扰
    diff_median = np.median(diffs)
    # 找到第一个超过k倍中位数的差值位置
    split_idx = np.argmax(diffs > k * diff_median) + 1  # +1对应排序后数据的分界索引

    # 处理无突变的情况:要么全是尖峰,要么全是噪声
    if split_idx == len(sorted_p):
        # 用最大最小值比值判断:比值小则全是噪声,否则全是尖峰
        if sorted_p[-1] / sorted_p[0] < 1.5:
            return np.zeros_like(p)
        else:
            return np.ones_like(p)
    
    # 提取尖峰阈值并生成结果
    spike_threshold = sorted_p[split_idx]
    return np.where(p >= spike_threshold, 1, 0)

测试效果

  • 对向量[13.45, 0.3, 1.4, 0.8, 11.1]:排序后差值突变点清晰,会正确标记两个尖峰
  • 对向量[13.45, 0.3, 1.4, 0.8, 7.1]:k=1.5时,会识别出7.1和13.45为尖峰,不会漏检
  • k值可根据噪声调整:噪声大时调大(比如2),噪声小时调小(比如1.2)

方法2:基于剩余数据统计量的动态阈值

不用固定比例,而是用去掉最大值后的剩余数据计算统计阈值,能更好适配数据波动。

代码实现

import numpy as np

def find_spikes_dynamic(p, m=1.5):
    max_p = np.max(p)
    rest_p = p[p != max_p]
    
    # 处理全是最大值的情况(全尖峰)
    if len(rest_p) == 0:
        return np.ones_like(p)
    
    mean_rest = np.mean(rest_p)
    std_rest = np.std(rest_p)
    threshold = mean_rest + m * std_rest
    # 可选:限制阈值不超过最大值的80%,避免误判接近最大值的噪声
    threshold = min(threshold, max_p * 0.8)

    spikes = np.where(p >= threshold, 1, 0)
    # 过滤误判:如果标记的尖峰过多,判断是噪声还是全尖峰
    if np.sum(spikes) > len(p) - 2:
        if np.std(p) / np.mean(p) < 0.1:  # 变异系数小说明数据波动小,是全尖峰
            return np.ones_like(p)
        else:
            return np.zeros_like(p)
    return spikes

方法3:基于聚类的自动分类

用K-means把数据分成两类,自动区分尖峰和非尖峰,适合数据分布明显分成两组的场景。

代码实现

from sklearn.cluster import KMeans
import numpy as np

def find_spikes_cluster(p):
    X = p.reshape(-1, 1)
    # 强制分成两类
    kmeans = KMeans(n_clusters=2, random_state=0, n_init='auto').fit(X)
    labels = kmeans.labels_
    centers = kmeans.cluster_centers_.flatten()

    # 判断类间差异是否足够大:差异小则是噪声或全尖峰
    if centers[np.argmax(centers)] / centers[np.argmin(centers)] < 1.3:
        if np.std(p) / np.mean(p) < 0.1:
            return np.ones_like(p)
        else:
            return np.zeros_like(p)
    
    # 标记中心值更大的类为尖峰
    spike_label = np.argmax(centers)
    return np.where(labels == spike_label, 1, 0)

调参建议

所有方法中的参数(k、m、类间比值阈值)都需要用你的真实数据验证微调:

  • 噪声大时,调大区分阈值(比如k=2),减少假阳性
  • 噪声小时,调小阈值,避免漏检

内容的提问来源于stack exchange,提问作者user2751530

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 19:41:23