当前位置: 首页 > news >正文

吴恩达机器学习课程(PyTorch 适配)学习笔记:3.1 无监督学习基础

3.1 无监督学习基础

3.1.1 无监督学习概述

无监督学习(Unsupervised Learning)是机器学习的重要分支,其核心特点是从无标签数据中自动发现潜在的模式、结构或规律。与监督学习依赖人工标注的标签不同,无监督学习更接近人类认知世界的方式——通过观察和归纳自主形成概念。

核心特点
  • 输入数据没有标签(XXX 存在,yyy 不存在)
  • 目标是发现数据的内在结构而非预测
  • 常作为数据探索的第一步,为后续分析提供基础
  • 结果的解释性往往需要领域知识辅助
与监督学习的关键区别
维度无监督学习监督学习
数据要求仅需特征数据 XXX需要特征 XXX + 标签 yyy
核心任务发现结构、模式、关联学习映射 f:X→yf: X \rightarrow yf:Xy
评估方式主观(领域知识)+ 间接指标客观(预测准确率等)
典型应用聚类、降维、异常检测分类、回归、序列预测
数据依赖对数据量要求高,质量敏感对标签质量要求高
主要应用领域
  • 数据探索与可视化(如降维分析)
  • 客户分群与市场细分
  • 异常检测与欺诈识别
  • 特征学习与表示学习
  • 推荐系统中的用户/物品聚类
常见算法分类
  1. 聚类算法:K均值、层次聚类、DBSCAN、谱聚类等
  2. 降维与可视化:PCA、t-SNE、UMAP、自编码器等
  3. 异常检测:基于统计的方法、孤立森林、One-Class SVM等
  4. 关联规则学习:Apriori、FP-Growth等
  5. 生成模型:高斯混合模型、变分自编码器、生成对抗网络等

3.1.2 聚类任务(定义 + 场景)

定义

聚类(Clustering)是无监督学习的核心任务之一,其目标是将数据集划分为若干个簇(Cluster),使得同一簇内的样本具有较高的相似性,而不同簇的样本具有较低的相似性。

数学描述:给定数据集 X={x1,x2,...,xn}X = \{x_1, x_2, ..., x_n\}X={x1,x2,...,xn},聚类算法将其划分为 kkk 个不相交的子集 C1,C2,...,CkC_1, C_2, ..., C_kC1,C2,...,Ck,满足:

  • ⋃i=1kCi=X\bigcup_{i=1}^{k} C_i = Xi=1kCi=X
  • Ci⋂Cj=∅C_i \bigcap C_j = \emptysetCiCj=i≠ji \neq ji=j
  • 对于任意 x,y∈Cix, y \in C_ix,yCi,相似度 sim(x,y)sim(x, y)sim(x,y) 较大
  • 对于任意 x∈Ci,y∈Cjx \in C_i, y \in C_jxCi,yCji≠ji \neq ji=j),相似度 sim(x,y)sim(x, y)sim(x,y) 较小
相似度度量

聚类效果高度依赖于相似度(或距离)的定义,常用度量方式:

  1. 欧氏距离(Euclidean Distance)
    d(x,y)=∑i=1d(xi−yi)2d(x, y) = \sqrt{\sum_{i=1}^{d} (x_i - y_i)^2}d(x,y)=i=1d(xiyi)2
    适用于连续型特征,对异常值敏感

  2. 曼哈顿距离(Manhattan Distance)
    d(x,y)=∑i=1d∣xi−yi∣d(x, y) = \sum_{i=1}^{d} |x_i - y_i|d(x,y)=i=1dxiyi
    对异常值的鲁棒性优于欧氏距离

  3. 余弦相似度(Cosine Similarity)
    sim(x,y)=x⋅y∣∣x∣∣⋅∣∣y∣∣sim(x, y) = \frac{x \cdot y}{||x|| \cdot ||y||}sim(x,y)=∣∣x∣∣∣∣y∣∣xy
    适用于高维稀疏数据(如文本),关注方向而非大小

  4. 杰卡德系数(Jaccard Index)
    J(A,B)=∣A⋂B∣∣A⋃B∣J(A, B) = \frac{|A \bigcap B|}{|A \bigcup B|}J(A,B)=ABAB
    适用于二进制特征或集合数据

典型应用场景
  1. 客户分群与精准营销

    • 根据购买历史、浏览行为等将客户分为不同群体
    • 针对不同群体设计个性化营销策略
    • 例:电商平台识别高价值客户群体与潜在流失客户群体
  2. 文本主题聚类

    • 对新闻、评论等文本数据自动归类主题
    • 例:将新闻分为政治、经济、体育等类别
  3. 图像分割与目标识别

    • 对图像像素进行聚类,实现前景与背景分离
    • 例:医学影像中肿瘤区域的自动识别
  4. 异常检测

    • 识别与大多数样本差异显著的离群点
    • 例:信用卡欺诈交易检测、网络入侵检测
  5. 特征工程辅助

    • 将聚类结果作为新特征加入模型
    • 例:将用户聚类ID作为特征用于推荐系统
聚类算法分类
类别代表算法核心思想优点缺点
划分式K均值、K中心点先确定簇数,再优化样本分配高效、适合大规模数据需预先指定K、对初始值敏感
层次式凝聚聚类、分裂聚类构建聚类树,自底向上或自顶向下无需指定K、提供层次结构计算复杂度高、不适合大规模数据
密度式DBSCAN、OPTICS基于样本密度划分,发现任意形状簇可发现任意形状簇、抗噪声对密度参数敏感、不适合高维数据
模型式高斯混合模型假设数据来自多个概率分布的混合提供概率解释、软聚类假设较强、计算复杂
谱聚类谱聚类基于图论,利用相似度矩阵特征值适合高维数据、聚类效果好计算复杂、参数敏感

3.1.3 K均值算法(原理 + 优化目标 + 初始化 + 聚类数选择)

K均值(K-means)是最经典的划分式聚类算法,由MacQueen于1967年提出,以其简单高效的特点成为工业界最常用的聚类算法之一。

原理与流程

K均值算法的核心思想是:通过迭代方式将数据集划分为K个簇,使得簇内样本相似度高,簇间样本相似度低。

算法流程

  1. 初始化:随机选择K个样本作为初始聚类中心(Centroid)
  2. 分配样本:计算每个样本与各聚类中心的距离,将样本分配到最近的簇
  3. 更新中心:计算每个簇内所有样本的均值,作为新的聚类中心
  4. 收敛判断:若聚类中心变化小于阈值或达到最大迭代次数,则停止;否则返回步骤2
优化目标

K均值的优化目标是最小化簇内平方和(Within-Cluster Sum of Squares, WCSS),也称为惯性(Inertia):

J=∑k=1K∑x∈Ck∣∣x−μk∣∣2J = \sum_{k=1}^{K} \sum_{x \in C_k} ||x - \mu_k||^2J=k=1KxCk∣∣xμk2

其中:

  • CkC_kCk 是第 kkk 个簇
  • μk\mu_kμk 是第 kkk 个簇的中心(均值向量)
  • ∣∣x−μk∣∣2||x - \mu_k||^2∣∣xμk2 是样本 xxx 与簇中心 μk\mu_kμk 的欧氏距离平方

该目标函数衡量了簇内样本的紧密程度,值越小表示聚类效果越好。

初始化方法

K均值算法对初始聚类中心的选择非常敏感,不好的初始化可能导致收敛到局部最优解。

  1. 随机初始化

    • 从数据集中随机选择K个样本作为初始中心
    • 优点:简单
    • 缺点:可能导致聚类效果差,需要多次运行取最优结果
  2. K-means++ 初始化(推荐)

    • 由Arthur和Vassilvitskii于2007年提出,旨在选择距离较远的初始中心
    • 步骤:
      1. 随机选择一个样本作为第一个中心
      2. 计算每个样本与最近已选中心的距离 d(x)2d(x)^2d(x)2
      3. 以与 d(x)2d(x)^2d(x)2 成正比的概率选择下一个中心
      4. 重复步骤2-3,直到选择K个中心
    • 优点:提高了聚类质量和稳定性,减少了对初始值的依赖
聚类数K的选择

聚类数K是K均值算法的关键超参数,如何选择合适的K是实际应用中的常见难题。

  1. 肘部法(Elbow Method)

    • 原理:随着K增大,WCSS会逐渐减小;当K超过真实聚类数后,WCSS下降速度会明显减缓,形成"肘部"
    • 步骤:
      1. 尝试不同的K值(如1到10)
      2. 对每个K计算WCSS
      3. 绘制K-WCSS曲线,选择肘部对应的K值
    • 缺点:肘部可能不明显,主观性强
  2. 轮廓系数法(Silhouette Score)

    • 原理:衡量样本与自身簇的相似度(a)和与最近其他簇的相似度(b),轮廓系数 s=(b−a)/max(a,b)s = (b - a)/max(a, b)s=(ba)/max(a,b)
    • 取值范围:[-1, 1],越接近1表示聚类效果越好
    • 步骤:
      1. 计算不同K值下的平均轮廓系数
      2. 选择系数最大的K值
    • 优点:提供了更明确的判断标准
    • 缺点:计算成本高,对凸形簇更有效
  3. Gap统计量(Gap Statistic)

    • 原理:比较实际数据的聚类效果与参考分布(如随机数据)的聚类效果
    • 步骤:
      1. 生成参考分布数据(与原始数据同分布的随机数据)
      2. 计算实际数据与参考数据的Gap统计量
      3. 选择Gap统计量稳定时的K值
    • 优点:更客观,适用于各种数据分布
    • 缺点:计算复杂,耗时较长
  4. 领域知识

    • 结合业务场景确定K值,例如:
      • 客户分群通常选择3-5个群体
      • 颜色聚类根据实际需求确定(如RGB三原色)
PyTorch实现
import torch
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs# 生成模拟数据
def generate_data(n_samples=300, n_features=2, centers=3, random_state=42):X, y_true = make_blobs(n_samples=n_samples, n_features=n_features,centers=centers, cluster_std=0.60, random_state=random_state)return torch.tensor(X, dtype=torch.float32), y_true# K-means++初始化
def kmeans_plus_plus_initialization(X, k):n_samples, n_features = X.shapecenters = torch.zeros((k, n_features), dtype=X.dtype, device=X.device)# 随机选择第一个中心centers[0] = X[torch.randint(0, n_samples, (1,))]# 选择剩余的中心for i in range(1, k):# 计算每个样本到最近中心的距离平方distances = torch.min(torch.cdist(X, centers[:i])**2, dim=1).values# 计算概率分布probabilities = distances / torch.sum(distances)# 按概率选择下一个中心idx = torch.multinomial(probabilities, 1)centers[i] = X[idx]return centers# K-means算法实现
def kmeans(X, k, max_iter=100, tol=1e-4):n_samples, n_features = X.shapedevice = X.device# 初始化聚类中心centers = kmeans_plus_plus_initialization(X, k)for iter in range(max_iter):# 计算每个样本到各中心的距离distances = torch.cdist(X, centers)  # 形状: [n_samples, k]# 分配样本到最近的簇labels = torch.argmin(distances, dim=1)  # 形状: [n_samples]# 计算新的聚类中心new_centers = torch.zeros_like(centers)for i in range(k):cluster_points = X[labels == i]if len(cluster_points) > 0:new_centers[i] = torch.mean(cluster_points, dim=0)else:# 如果簇为空,重新随机选择一个样本作为中心new_centers[i] = X[torch.randint(0, n_samples, (1,))]# 检查收敛center_shift = torch.sum(torch.abs(new_centers - centers))if center_shift < tol:print(f"在第{iter+1}轮迭代收敛")breakcenters = new_centers# 计算最终的WCSSwcss = 0.0for i in range(k):cluster_points = X[labels == i]if len(cluster_points) > 0:wcss += torch.sum(torch.cdist(cluster_points, centers[i:i+1])**2)return labels, centers, wcss# 可视化聚类结果
def plot_clusters(X, labels, centers, title):X_np = X.numpy()centers_np = centers.numpy()plt.figure(figsize=(8, 6))plt.scatter(X_np[:, 0], X_np[:, 1], c=labels, cmap='viridis', s=50, alpha=0.7)plt.scatter(centers_np[:, 0], centers_np[:, 1], c='red', s=200, marker='X', label='聚类中心')plt.title(title)plt.xlabel('特征1')plt.ylabel('特征2')plt.legend()plt.grid(True, alpha=0.3)plt.show()# 肘部法选择最佳K值
def elbow_method(X, k_range):wcss_values = []for k in k_range:_, _, wcss = kmeans(X, k)wcss_values.append(wcss.item())print(f"K={k}, WCSS={wcss.item():.2f}")plt.figure(figsize=(8, 6))plt.plot(k_range, wcss_values, 'bo-')plt.xlabel('聚类数K')plt.ylabel('WCSS')plt.title('肘部法选择最佳K值')plt.grid(True, alpha=0.3)plt.show()# 主函数
def main():# 生成数据X, y_true = generate_data(n_samples=300, centers=4)print(f"数据形状: {X.shape}")# 展示原始数据plt.figure(figsize=(8, 6))plt.scatter(X[:, 0], X[:, 1], c=y_true, cmap='viridis', s=50, alpha=0.7)plt.title('原始数据分布')plt.xlabel('特征1')plt.ylabel('特征2')plt.grid(True, alpha=0.3)plt.show()# 使用肘部法确定最佳K值elbow_method(X, range(1, 11))# 使用最佳K值进行聚类best_k = 4  # 根据肘部法结果选择labels, centers, wcss = kmeans(X, best_k)print(f"最佳K值={best_k}, 最终WCSS={wcss.item():.2f}")# 可视化聚类结果plot_clusters(X, labels, centers, f'K-means聚类结果 (K={best_k})')if __name__ == "__main__":main()
优缺点与注意事项

优点

  • 算法简单易懂,实现容易
  • 计算效率高,适合大规模数据集
  • 收敛速度快,对高维数据有一定适应性

缺点

  • 需要预先指定聚类数K
  • 对初始聚类中心敏感,可能收敛到局部最优
  • 只能发现凸形簇,对非球形分布数据效果差
  • 对异常值敏感
  • 不适合处理类别不平衡的数据

注意事项与易错点

  1. 特征标准化:K均值基于距离计算,不同量级的特征会影响聚类结果,需先进行标准化(如Z-score)
  2. 异常值处理:异常值会严重影响聚类中心,建议先进行异常检测和处理
  3. 多次运行:即使使用K-means++,也建议多次运行取最优结果
  4. 簇的解释性:聚类结果需要结合业务知识解释,避免为聚类而聚类
  5. 高维数据:高维空间中距离度量的意义减弱,建议先降维再聚类
  6. 空簇处理:当某个簇没有分配到样本时,需要重新初始化该簇中心

3.1.4 异常检测(场景 + 高斯分布基础)

异常检测定义

异常检测(Anomaly Detection)是识别与大多数数据显著不同的观测值或模式的过程。这些异常值也被称为离群点(Outliers)、异常样本(Anomalies)或异常事件(Novelties)。

异常的本质特征:

  • 稀有性:异常样本在数据集中占比通常较低
  • 差异性:与正常样本具有显著不同的特征模式
  • 上下文依赖性:同一数据在不同场景下可能被视为正常或异常(如信用卡大额交易在节假日可能正常)
典型应用场景
  1. 欺诈检测

    • 信用卡/银行欺诈交易检测
    • 保险欺诈索赔识别
    • 网络诈骗行为分析
  2. 工业故障诊断

    • 设备传感器异常读数检测
    • 生产过程中的质量异常监控
    • 预测性维护中的早期故障识别
  3. 网络安全

    • 网络入侵检测
    • 异常登录行为识别
    • DDoS攻击检测
  4. 医疗诊断

    • 疾病早期预警(如心电图异常检测)
    • 医疗影像异常区域识别
    • 患者生命体征异常监测
  5. 其他领域

    • 零售业中的异常退货行为
    • 能源消耗异常监测
    • 文本中的异常内容过滤
高斯分布(正态分布)基础

基于统计的异常检测方法广泛使用高斯分布(Gaussian Distribution)来建模正常数据的分布特征。

  1. 单变量高斯分布

若随机变量 xxx 服从均值为 μ\muμ、方差为 σ2\sigma^2σ2 的高斯分布,记为 x∼N(μ,σ2)x \sim \mathcal{N}(\mu, \sigma^2)xN(μ,σ2),其概率密度函数为:

p(x;μ,σ2)=12πσ2exp⁡(−(x−μ)22σ2)p(x; \mu, \sigma^2) = \frac{1}{\sqrt{2\pi\sigma^2}} \exp\left(-\frac{(x - \mu)^2}{2\sigma^2}\right)p(x;μ,σ2)=2πσ21exp(2σ2(xμ)2)

其中:

  • μ\muμ 是均值(期望),表示数据的中心位置
  • σ2\sigma^2σ2 是方差,表示数据的离散程度
  • σ=σ2\sigma = \sqrt{\sigma^2}σ=σ2 是标准差
  1. 参数估计

对于给定的数据集 x1,x2,...,xmx_1, x_2, ..., x_mx1,x2,...,xm,可以通过最大似然估计得到参数:

μ=1m∑i=1mxi\mu = \frac{1}{m} \sum_{i=1}^{m} x_iμ=m1i=1mxi
σ2=1m∑i=1m(xi−μ)2\sigma^2 = \frac{1}{m} \sum_{i=1}^{m} (x_i - \mu)^2σ2=m1i=1m(xiμ)2

  1. 多变量高斯分布

对于 nnn 维特征向量 x=(x1,x2,...,xn)Tx = (x_1, x_2, ..., x_n)^Tx=(x1,x2,...,xn)T,多变量高斯分布记为 x∼N(μ,Σ)x \sim \mathcal{N}(\mu, \Sigma)xN(μ,Σ),其概率密度函数为:

p(x;μ,Σ)=1(2π)n/2∣Σ∣1/2exp⁡(−12(x−μ)TΣ−1(x−μ))p(x; \mu, \Sigma) = \frac{1}{(2\pi)^{n/2} |\Sigma|^{1/2}} \exp\left(-\frac{1}{2}(x - \mu)^T \Sigma^{-1} (x - \mu)\right)p(x;μ,Σ)=(2π)n/2∣Σ1/21exp(21(xμ)TΣ1(xμ))

其中:

  • μ\muμnnn 维均值向量
  • Σ\SigmaΣn×nn \times nn×n 协方差矩阵,描述特征间的相关性
  • ∣Σ∣|\Sigma|∣Σ∣ 是协方差矩阵的行列式
  • Σ−1\Sigma^{-1}Σ1 是协方差矩阵的逆

3.1.5 异常检测算法(流程 + 评估 + 与监督学习对比)

基于高斯分布的异常检测算法流程

基于高斯分布的异常检测是一种经典的统计方法,其核心思想是:假设正常数据服从高斯分布,通过计算样本的概率密度来判断是否为异常。

算法流程

  1. 数据准备

    • 收集主要包含正常样本的训练数据(异常样本比例应极低)
    • 选择合适的特征(见3.1.6节特征选择)
    • 对特征进行预处理(标准化、归一化等)
  2. 参数估计

    • 对每个特征 xjx_jxj,计算均值 μj\mu_jμj 和方差 σj2\sigma_j^2σj2
      μj=1m∑i=1mxj(i)\mu_j = \frac{1}{m} \sum_{i=1}^{m} x_j^{(i)}μj=m1i=1mxj(i)
      σj2=1m∑i=1m(xj(i)−μj)2\sigma_j^2 = \frac{1}{m} \sum_{i=1}^{m} (x_j^{(i)} - \mu_j)^2σj2=m1i=1m(xj(i)μj)2
    • (可选)使用多变量高斯分布时,计算协方差矩阵 Σ\SigmaΣ
  3. 计算概率密度

    • 对每个样本 xxx,计算其概率密度:
      p(x)=∏j=1np(xj;μj,σj2)p(x) = \prod_{j=1}^{n} p(x_j; \mu_j, \sigma_j^2)p(x)=j=1np(xj;μj,σj2)
      (单变量高斯分布假设特征独立)
    • 或使用多变量高斯分布计算联合概率密度
  4. 确定阈值 ϵ\epsilonϵ

    • 使用验证集确定阈值 ϵ\epsilonϵ
    • p(x)<ϵp(x) < \epsilonp(x)<ϵ 时,判定为异常
  5. 异常检测

    • 对新样本计算 p(x)p(x)p(x)
    • 根据与阈值的比较结果判断是否为异常
异常检测算法实现(PyTorch)
import torch
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs# 生成包含异常值的数据集
def generate_anomaly_data(n_normal=500, n_anomalies=20, n_features=2, random_state=42):# 生成正常样本(服从高斯分布)normal_data, _ = make_blobs(n_samples=n_normal,n_features=n_features,centers=1,cluster_std=0.6,random_state=random_state)# 生成异常样本(远离正常样本的随机点)np.random.seed(random_state)anomalies = np.random.uniform(low=normal_data.min() - 2,high=normal_data.max() + 2,size=(n_anomalies, n_features))# 合并数据并创建标签(0表示正常,1表示异常)X = np.vstack([normal_data, anomalies])y = np.hstack([np.zeros(n_normal), np.ones(n_anomalies)])# 打乱数据shuffle_idx = np.random.permutation(len(X))X = X[shuffle_idx]y = y[shuffle_idx]return torch.tensor(X, dtype=torch.float32), torch.tensor(y, dtype=torch.float32)# 分割训练集(主要是正常样本)、验证集和测试集
def split_data(X, y, train_ratio=0.6, val_ratio=0.2):n_samples = len(X)n_train = int(n_samples * train_ratio)n_val = int(n_samples * val_ratio)# 训练集尽量选择正常样本normal_indices = (y == 0).nonzero().squeeze()anomaly_indices = (y == 1).nonzero().squeeze()# 训练集中包含大部分正常样本n_train_normal = min(n_train, len(normal_indices))train_normal_idx = normal_indices[:n_train_normal]train_indices = train_normal_idx# 剩余样本用于验证集和测试集remaining_normal_idx = normal_indices[n_train_normal:]remaining_indices = torch.cat([remaining_normal_idx, anomaly_indices])np.random.shuffle(remaining_indices.numpy())val_indices = remaining_indices[:n_val]test_indices = remaining_indices[n_val:]X_train, y_train = X[train_indices], y[train_indices]X_val, y_val = X[val_indices], y[val_indices]X_test, y_test = X[test_indices], y[test_indices]print(f"训练集: {len(X_train)} 样本, 异常比例: {y_train.mean():.2%}")print(f"验证集: {len(X_val)} 样本, 异常比例: {y_val.mean():.2%}")print(f"测试集: {len(X_test)} 样本, 异常比例: {y_test.mean():.2%}")return X_train, y_train, X_val, y_val, X_test, y_test# 估计高斯分布参数
def estimate_gaussian_parameters(X):"""计算每个特征的均值和方差"""mu = torch.mean(X, dim=0)  # 均值向量sigma2 = torch.var(X, dim=0, unbiased=False)  # 方差向量(使用有偏估计)return mu, sigma2# 计算概率密度
def multivariate_gaussian(X, mu, sigma2):"""计算样本的概率密度(假设特征独立)"""n = X.shape[1]sigma_diag = torch.diag(sigma2)sigma_inv = torch.inverse(sigma_diag)X_mu = X - mu# 计算概率密度term1 = 1.0 / torch.pow(2 * torch.tensor(np.pi), n / 2)term2 = 1.0 / torch.sqrt(torch.det(sigma_diag))term3 = torch.exp(-0.5 * torch.diag(torch.matmul(torch.matmul(X_mu, sigma_inv), X_mu.T)))return term1 * term2 * term3# 选择最佳阈值
def select_threshold(y_val, p_val):"""根据验证集选择最佳阈值y_val: 验证集标签(0=正常,1=异常)p_val: 验证集样本的概率密度"""best_epsilon = 0.0best_f1 = 0.0f1 = 0.0# 尝试不同的阈值step_size = (torch.max(p_val) - torch.min(p_val)) / 1000for epsilon in torch.arange(torch.min(p_val), torch.max(p_val), step_size):# 预测标签predictions = (p_val < epsilon).float()# 计算精确率、召回率和F1分数tp = torch.sum((predictions == 1) & (y_val == 1)).item()fp = torch.sum((predictions == 1) & (y_val == 0)).item()fn = torch.sum((predictions == 0) & (y_val == 1)).item()# 避免除零错误precision = tp / (tp + fp) if (tp + fp) > 0 else 0recall = tp / (tp + fn) if (tp + fn) > 0 else 0# 计算F1分数if precision + recall > 0:f1 = 2 * precision * recall / (precision + recall)else:f1 = 0# 更新最佳阈值if f1 > best_f1:best_f1 = f1best_epsilon = epsilon.item()return best_epsilon, best_f1# 评估模型
def evaluate_model(y_true, p, epsilon):"""评估异常检测模型性能"""predictions = (p < epsilon).float()# 计算各类指标tp = torch.sum((predictions == 1) & (y_true == 1)).item()tn = torch.sum((predictions == 0) & (y_true == 0)).item()fp = torch.sum((predictions == 1) & (y_true == 0)).item()fn = torch.sum((predictions == 0) & (y_true == 1)).item()# 计算评估指标precision = tp / (tp + fp) if (tp + fp) > 0 else 0recall = tp / (tp + fn) if (tp + fn) > 0 else 0f1 = 2 * precision * recall / (precision + recall) if (precision + recall) > 0 else 0accuracy = (tp + tn) / (tp + tn + fp + fn) if (tp + tn + fp + fn) > 0 else 0print(f"评估指标:")print(f"精确率 (Precision): {precision:.4f}")print(f"召回率 (Recall): {recall:.4f}")print(f"F1分数: {f1:.4f}")print(f"准确率 (Accuracy): {accuracy:.4f}")print(f"真正例 (TP): {tp}, 真负例 (TN): {tn}")print(f"假正例 (FP): {fp}, 假负例 (FN): {fn}")return {'precision': precision,'recall': recall,'f1': f1,'accuracy': accuracy,'tp': tp, 'tn': tn, 'fp': fp, 'fn': fn}# 可视化异常检测结果
def plot_anomaly_detection(X, y_true, p, epsilon):"""可视化异常检测结果"""X_np = X.numpy()y_pred = (p < epsilon).float().numpy()# 绘制所有样本plt.figure(figsize=(10, 8))# 正常样本normal_mask = (y_true == 0)plt.scatter(X_np[normal_mask, 0], X_np[normal_mask, 1],c='blue', label='正常样本', alpha=0.6, s=50)# 真实异常样本anomaly_mask = (y_true == 1)plt.scatter(X_np[anomaly_mask, 0], X_np[anomaly_mask, 1],c='red', label='真实异常', alpha=0.8, s=80, marker='X')# 预测的异常样本pred_anomaly_mask = (y_pred == 1)plt.scatter(X_np[pred_anomaly_mask, 0], X_np[pred_anomaly_mask, 1],c='none', edgecolors='green', label='预测异常', s=150, linewidth=2)# 绘制概率等高线x1_min, x1_max = X_np[:, 0].min() - 1, X_np[:, 0].max() + 1x2_min, x2_max = X_np[:, 1].min() - 1, X_np[:, 1].max() + 1xx1, xx2 = np.meshgrid(np.linspace(x1_min, x1_max, 100), np.linspace(x2_min, x2_max, 100))grid_points = torch.tensor(np.c_[xx1.ravel(), xx2.ravel()], dtype=torch.float32)mu = torch.mean(X, dim=0)sigma2 = torch.var(X, dim=0, unbiased=False)p_grid = multivariate_gaussian(grid_points, mu, sigma2)p_grid = p_grid.reshape(xx1.shape)plt.contour(xx1, xx2, p_grid, levels=[epsilon], linewidths=2, colors='black', linestyles='dashed')plt.title('异常检测结果可视化')plt.xlabel('特征1')plt.ylabel('特征2')plt.legend()plt.grid(True, alpha=0.3)plt.show()# 主函数
def main():# 生成数据X, y = generate_anomaly_data(n_normal=500, n_anomalies=30, n_features=2)# 分割数据X_train, y_train, X_val, y_val, X_test, y_test = split_data(X, y)# 估计高斯分布参数mu, sigma2 = estimate_gaussian_parameters(X_train)print(f"估计的均值: {mu.numpy()}")print(f"估计的方差: {sigma2.numpy()}")# 计算概率密度p_train = multivariate_gaussian(X_train, mu, sigma2)p_val = multivariate_gaussian(X_val, mu, sigma2)p_test = multivariate_gaussian(X_test, mu, sigma2)# 选择最佳阈值epsilon, f1 = select_threshold(y_val, p_val)print(f"最佳阈值 ε: {epsilon:.6f}, 对应的F1分数: {f1:.4f}")# 在测试集上评估print("\n测试集性能:")evaluate_model(y_test, p_test, epsilon)# 可视化结果plot_anomaly_detection(X_test, y_test, p_test, epsilon)if __name__ == "__main__":main()
异常检测评估方法

异常检测的评估面临特殊挑战:数据高度不平衡(异常样本通常只占1%-5%),传统的准确率指标会产生误导。

  1. 混淆矩阵(Confusion Matrix)

    预测/实际正常(0)异常(1)
    正常(0)真负例(TN)假负例(FN)
    异常(1)假正例(FP)真正例(TP)
  2. 核心评估指标

    • 精确率(Precision):预测为异常的样本中真正异常的比例
      Precision=TPTP+FP\text{Precision} = \frac{TP}{TP + FP}Precision=TP+FPTP
      关注"少误报",适用于FP成本高的场景(如信用卡欺诈检测)

    • 召回率(Recall):所有真实异常中被正确检测出的比例
      Recall=TPTP+FN\text{Recall} = \frac{TP}{TP + FN}Recall=TP+FNTP
      关注"少漏报",适用于FN成本高的场景(如疾病诊断)

    • F1分数:精确率和召回率的调和平均
      F1=2×Precision×RecallPrecision+RecallF1 = 2 \times \frac{\text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}}F1=2×Precision+RecallPrecision×Recall
      综合评价指标,适用于需要平衡精确率和召回率的场景

    • ROC曲线与AUC

      • ROC曲线:不同阈值下假正例率(FPR)与真正例率(TPR)的关系
      • AUC:ROC曲线下面积,取值范围[0,1],越大表示检测效果越好
  3. 评估注意事项

    • 避免使用准确率(Accuracy)作为主要指标
    • 异常检测中,召回率通常比精确率更重要
    • 阈值选择需根据业务场景中FP和FN的成本权衡
    • 建议使用交叉验证评估模型稳定性
与监督学习的对比

异常检测与监督学习在处理异常问题时各有优劣,选择需根据具体场景:

维度异常检测(无监督/半监督)监督学习(分类)
数据要求主要需要正常样本,异常样本可很少需要大量标注的正常和异常样本
异常类型可检测未知类型的异常只能检测训练过的已知异常类型
适应性对新出现的异常类型有一定适应性对新异常类型适应性差
标注成本低(无需标注或少量标注)高(需要大量标注数据)
应用场景异常样本少、类型多变的场景(如欺诈检测)异常类型固定、样本充足的场景(如垃圾邮件分类)
算法特点建模正常模式,偏离者为异常同时建模正常和异常模式
典型算法基于高斯分布、孤立森林、One-Class SVM逻辑回归、随机森林、神经网络

何时选择异常检测而非监督学习

  1. 异常样本非常稀少(<5%)
  2. 异常类型不断变化(如网络攻击方式)
  3. 标注异常样本成本高或困难
  4. 需要检测未知类型的异常

3.1.6 异常检测特征选择(思路)

特征选择是异常检测成功的关键步骤,高质量的特征能显著提升检测效果。异常检测的特征选择有其特殊性,需要重点关注能区分正常与异常的特征。

特征选择的核心原则
  1. 区分性原则:选择正常样本与异常样本差异显著的特征
  2. 稳定性原则:选择在正常样本中表现稳定,在异常样本中表现不稳定的特征
  3. 相关性原则:避免高度相关的冗余特征,选择信息互补的特征
  4. 可解释性原则:优先选择具有业务解释性的特征,便于后续结果分析
特征选择思路与方法
  1. 基于领域知识的特征选择

    • 结合业务理解选择与异常相关的特征
    • 例:
      • 信用卡欺诈检测:交易金额、交易频率、异地交易、新设备交易等
      • 设备故障检测:温度、压力、振动频率、能耗等
    • 优势:直接有效,减少无效特征
    • 注意:需与领域专家密切合作
  2. 基于统计分析的特征选择

    • 分析特征在正常样本和异常样本中的分布差异
    • 常用方法:
      • 均值差异分析:比较特征在两类样本中的均值差异
      • 方差分析:异常样本通常具有更大的方差
      • 分布检验:使用KS检验等方法检验分布是否存在显著差异
    • 实现示例:
      def analyze_feature_distributions(X, y):"""分析特征在正常和异常样本中的分布差异"""n_features = X.shape[1]normal_mask = (y == 0)for i in range(n_features):# 分离正常和异常样本的特征值normal_vals = X[normal_mask, i]anomaly_vals = X[~normal_mask, i]# 计算基本统计量normal_mean = torch.mean(normal_vals)anomaly_mean = torch.mean(anomaly_vals)mean_diff = torch.abs(normal_mean - anomaly_mean)normal_std = torch.std(normal_vals)# 打印统计信息print(f"特征 {i+1}:")print(f"  正常样本: 均值={normal_mean:.4f}, 标准差={normal_std:.4f}, 样本数={len(normal_vals)}")print(f"  异常样本: 均值={anomaly_mean:.4f}, 样本数={len(anomaly_vals)}")print(f"  均值差异: {mean_diff:.4f}, 差异倍数: {mean_diff/normal_std:.2f}x")print("-" * 50)# 绘制分布直方图plt.figure(figsize=(8, 4))plt.hist(normal_vals.numpy(), bins=20, alpha=0.5, label='正常样本')plt.hist(anomaly_vals.numpy(), bins=20, alpha=0.5, label='异常样本')plt.axvline(normal_mean, color='blue', linestyle='dashed', linewidth=1)plt.axvline(anomaly_mean, color='orange', linestyle='dashed', linewidth=1)plt.title(f'特征 {i+1} 分布')plt.xlabel('特征值')plt.ylabel('频率')plt.legend()plt.show()
      
  3. 基于特征重要性的选择

    • 使用树模型或线性模型评估特征重要性
    • 方法:
      • 随机森林的特征重要性得分
      • 线性模型的系数绝对值
      • 特征消除法(递归删除重要性低的特征)
    • 注意:需使用有标签的验证集进行评估
  4. 基于异常检测性能的选择

    • 评估特征对异常检测性能的贡献
    • 方法:
      • 逐一移除特征,观察模型性能变化
      • 组合不同特征子集,选择性能最佳的组合
      • 使用特征选择算法(如遗传算法、粒子群优化)搜索最优特征子集
    • 示例流程:
      1. 初始化包含所有特征的集合
      2. 计算当前特征集合的检测性能(如F1分数)
      3. 移除一个特征,计算新集合的性能
      4. 保留性能提升或下降最小的特征集合
      5. 重复步骤2-4,直到达到预设特征数量
特征工程技巧
  1. 特征转换

    • 对偏态分布的特征进行对数、平方根等转换
    • 标准化或归一化特征,消除量纲影响
    • 对时间序列数据,可提取滚动统计特征(如滑动窗口均值、方差)
  2. 特征组合

    • 创建比率特征(如交易金额/平均交易金额)
    • 创建交互特征(如时间×地点)
    • 创建聚合特征(如用户过去24小时的交易次数)
  3. 时间相关特征

    • 对于时间序列数据,添加时间差特征(如距上次交易的时间)
    • 添加周期性特征(如是否周末、是否节假日)
    • 添加趋势特征(如最近7天的交易增长率)
注意事项与常见错误
  1. 过度依赖高维特征:高维特征可能导致"维度灾难",降低检测效果
  2. 忽略特征相关性:高度相关的特征会引入冗余,放大噪声影响
  3. 忽视特征稳定性:选择在正常情况下稳定的特征,避免受无关因素影响
  4. 特征太少或太多:特征太少可能丢失信息,特征太多可能引入噪声
  5. 不考虑特征时效性:某些特征的分布可能随时间变化,需定期重新评估

特征选择检查清单

  • 特征是否与异常检测目标相关?
  • 特征在正常样本和异常样本中是否有显著差异?
  • 特征是否具有业务解释性?
  • 特征是否稳定可靠,不受噪声干扰?
  • 特征之间是否存在冗余?

通过精心的特征选择和工程,可以显著提升异常检测模型的性能,减少误报和漏报,使模型更具实用价值。

http://www.dtcms.com/a/458631.html

相关文章:

  • 做移动类网站的书推荐2014个人网站备案
  • Trea国际版|海外版下载
  • 宝德科技专业嘉兴网站建设网站姐姐做床戏网站
  • 河池公司做网站最近在线观看免费完整版高清电影
  • 网站开发代理江苏如可建设淘宝链接网站
  • 长治网站运营百度seo学院
  • 如何在百度里建网站国内免备案
  • 中华山河诗卷:省域经纬,城乡弦歌
  • 响应式模板网站建设哪家好wordpress 底部友情链接
  • 深圳网站建设10强网站托管共享服务器费用一年多少钱
  • 中小企业建网站哪个好seo外链网站大全
  • 网站开发财务费用广东网站建设系统怎么样
  • cubemx f103c8t6 串口一 DMA 简单配置和实现
  • 哈尔滨专业做网站公司wordpress 是免费的嘛
  • 西安哪里做网站最大交换机做网站
  • 榆中建设局网站下载优化大师并安装
  • 有没有哪种网站推荐一下wordpress google ad
  • 古董手表网站30天网站建设
  • 做网站交接需要哪些权限企业信用公示信息系统(全国)官网
  • 【论文学习】交互式图像分割顶会论文
  • 网站主办单位负责人网站竞价如何做
  • 吴恩达机器学习课程(PyTorch 适配)学习笔记:3.2 降维技术详解(PCA)
  • 一元购网站建设多少钱手机网站生成代码
  • 天津免费做网站公司网站建设30元
  • 天津智能网站建设制作做电商要关注哪些网站
  • 商店网站源码淮安做网站
  • Effective STL 第4条:调用empty()而不是检查size()是否为0
  • 家具网站开发环境与工具铜陵市网站建设
  • Mysql初阶第三讲:Mysql数据类型
  • 网络营销价格北京seo公司工作