Loading

异常值检测算法学习

1. 基于分布的异常检测

1.1 3σ准则 (3-Sigma Rule)

原理:基于正态分布假设,认为距离均值3个标准差之外的数据点为异常值

数学表达式

python

def three_sigma_detection(data):
    mean = np.mean(data)
    std = np.std(data)
    lower_bound = mean - 3 * std
    upper_bound = mean + 3 * std
    outliers = [x for x in data if x < lower_bound or x > upper_bound]
    return outliers

优缺点

  • ✅ 简单直观,计算效率高

  • ✅ 对正态分布数据效果良好

  • ❌ 依赖正态分布假设

  • ❌ 对偏态分布敏感

  • ❌ 只能检测全局异常

适用场景:质量控制、金融收益率分析

1.2 Z-Score 方法

原理:计算数据点与均值的标准差距离

数学表达式

def z_score_detection(data, threshold=3):
    z_scores = np.abs((data - np.mean(data)) / np.std(data))
    return data[z_scores > threshold]

改进版本

  • 修正Z-Score:使用中位数和MAD(Median Absolute Deviation)
    def modified_z_score(data, threshold=3.5):
        median = np.median(data)
        mad = np.median(np.abs(data - median))
        modified_z_scores = 0.6745 * (data - median) / mad  # 0.6745为调整系数
        return data[np.abs(modified_z_scores) > threshold]
    

1.3 箱线图法 (Boxplot)

原理:基于四分位数和IQR(Interquartile Range)识别异常值

实现

def boxplot_detection(data):
    Q1 = np.percentile(data, 25)
    Q3 = np.percentile(data, 75)
    IQR = Q3 - Q1
    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR
    outliers = [x for x in data if x < lower_bound or x > upper_bound]
    return outliers

阈值选择

  • 温和异常值:1.5×IQR

  • 极端异常值:3×IQR

2. 基于距离的异常检测

2.1 K-最近邻 (K-Nearest Neighbors)

原理:计算每个点与其k个最近邻的距离,距离较大的点视为异常

实现

python

from sklearn.neighbors import NearestNeighbors

def knn_outlier_detection(X, k=5, threshold=1.5):
neigh = NearestNeighbors(n_neighbors=k)
neigh.fit(X)
distances, indices = neigh.kneighbors(X)

# 计算平均距离
avg_distances = np.mean(distances, axis=1)

# 基于百分位数设置阈值
if threshold <= 1:
    threshold_value = np.percentile(avg_distances, threshold * 100)
else:
    threshold_value = np.mean(avg_distances) + threshold * np.std(avg_distances)

return avg_distances > threshold_value

优缺点

  • ✅ 无需分布假设

  • ✅ 可发现任意形状的异常

  • ❌ 计算复杂度高 O(n²)

  • ❌ 对参数k敏感

  • ❌ 高维数据效果差(维度灾难)

2.2 局部异常因子 (LOF - Local Outlier Factor)

原理:比较点的局部密度与其邻居的局部密度

实现

from sklearn.neighbors import LocalOutlierFactor
def lof_detection(X, contamination=0.1):
    lof = LocalOutlierFactor(contamination=contamination)
    return lof.fit_predict(X)

核心概念

  • k-距离:点到第k个最近邻的距离

  • 可达距离:max(k-距离(p), 两点间距离)

  • 局部可达密度:k个近邻的平均可达距离的倒数

  • LOF值:近邻的局部可达密度与当前点密度的比值

LOF值解释

  • ≈1:与邻居密度相似

  • <1:密度高于邻居(可能是内点)

  • 1:密度低于邻居(可能是异常点)

3. 基于密度的异常检测

3.1 DBSCAN-based 异常检测

原理:基于密度的聚类,将不属于任何簇的点标记为异常

实现

from sklearn.cluster import DBSCAN

def dbscan_outlier_detection(X, eps=0.5, min_samples=5):
    dbscan = DBSCAN(eps=eps, min_samples=min_samples)
    labels = dbscan.fit_predict(X)
    return labels == -1  # -1表示噪声点(异常)

参数选择

  • eps:邻域半径
  • min_samples:核心点所需的最小邻居数

3.2 局部异常概率 (LoOP - Local Outlier Probability)

原理:基于局部邻域的统计检验计算异常概率

特点

  • 提供0-1之间的异常概率
  • 对局部密度变化更鲁棒

4. 基于树的异常检测

4.1 孤立森林 (Isolation Forest)

原理:异常点更容易被随机划分孤立

实现

from sklearn.ensemble import IsolationForest

def isolation_forest_detection(X, contamination=0.1):
    iso_forest = IsolationForest(
        contamination=contamination,
        random_state=42
    )
    return iso_forest.fit_predict(X)

算法流程

  1. 随机选择特征和分割值构建孤立树

  2. 计算每个点的路径长度(从根节点到该点的边数)

  3. 计算异常分数:$s(x,n) = 2^{-\frac{E(h(x))}{c(n)}}$

    • $E(h(x))$:路径长度的期望

    • $c(n)$:平均路径长度,用于标准化

异常分数解释

  • 接近1:很可能是异常

  • 远小于0.5:很可能是正常点

  • 所有点约0.5:没有明显异常

优缺点

  • ✅ 处理高维数据效果好

  • ✅ 线性时间复杂度

  • ✅ 无需距离或密度计算

  • ❌ 对局部异常检测效果有限

5. 其他重要方法

5.1 一类支持向量机 (One-Class SVM)

原理:在特征空间中找到最优超平面,使大部分数据位于同一侧

from sklearn.svm import OneClassSVM

def one_class_svm_detection(X, nu=0.1):
    oc_svm = OneClassSVM(nu=nu)
    return oc_svm.fit_predict(X)

5.2 自编码器 (Autoencoder)

原理:基于重构误差检测异常

from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Dense

def autoencoder_detection(X, encoding_dim=32, threshold=0.1):
    # 构建自编码器
    input_layer = Input(shape=(X.shape[1],))
    encoded = Dense(encoding_dim, activation='relu')(input_layer)
    decoded = Dense(X.shape[1], activation='sigmoid')(encoded)
    
    autoencoder = Model(input_layer, decoded)
    autoencoder.compile(optimizer='adam', loss='mse')
    
    # 训练并计算重构误差
    autoencoder.fit(X, X, epochs=50, batch_size=256, verbose=0)
    reconstructions = autoencoder.predict(X)
    mse = np.mean(np.power(X - reconstructions, 2), axis=1)
    
    return mse > threshold

6. 方法选择指南

方法 数据量 维度 异常类型 计算复杂度 是否需要标签
3σ/Z-Score 小-大 全局 O(n)
箱线图 小-大 全局 O(n log n)
KNN 小-中 低-中 全局 O(n²)
LOF 小-中 低-中 局部 O(n²)
孤立森林 全局 O(n log n)
One-Class SVM 中-高 全局 O(n²)-O(n³)
自编码器 复杂模式 O(epochs×n)

7. 最佳实践建议

  1. 数据预处理

    • 处理缺失值和标准化

    • 考虑数据分布特性

  2. 多方法结合

    def ensemble_anomaly_detection(X, methods=['isolation_forest', 'lof']):
        scores = []
        if 'isolation_forest' in methods:
            if_scores = IsolationForest().fit(X).score_samples(X)
            scores.append(if_scores)
        if 'lof' in methods:
            lof_scores = LocalOutlierFactor().fit(X).negative_outlier_factor_
            scores.append(lof_scores)
        
        # 组合分数
        combined_scores = np.mean(scores, axis=0)
        return combined_scores
    
  3. 阈值选择策略

    • 基于业务知识
    • 基于历史数据分布
    • 使用自适应阈值
  4. 验证与调优

    • 使用有标签数据验证(如有)
    • 结合业务场景调整参数
    • 定期重新训练模型
posted @ 2025-10-23 09:31  GIPV  阅读(6)  评论(0)    收藏  举报