系列文章目录
Python异常检测- Isolation Forest(孤立森林)
python异常检测 - 随机离群选择Stochastic Outlier Selection (SOS)
python异常检测-局部异常因子(LOF)算法
Python异常检测- DBSCAN
Python异常检测- 单类支持向量机(One-Class SVM)
Python异常检测-3Sigma
文章目录
前言
kNN算法(k--NearestNeighbor算法),又称k-近邻算法。KNN是一种非参数学习算法,通过基于距离来度量异常的算法,简单来说就是近朱者赤近墨者黑。
一、KNN算法原理
KNN算法是一种基于统计的机器学习方法,用于异常值检测的核心原理是通过计算一个数据点与其K个最近邻居的距离,通过这些距离来判断该数据点是否为异常值。具体是依次计算每个样本点与它最近的K个样本的平均距离,再利用计算的距离与阈值进行比较,如果大于阈值,则认为是异常点。简单来说,就是异常点是指远离大部分正常点的样本点,再直白点说,异常点一定是跟大部分的样本点都隔得很远。
二、KNN的实现步骤
基于kNN的对数据进行分类的过程分为三步:
1.计算距离:对于数据集中的每一个点,计算它与所有其他点的距离。通常计算距离来衡量两点之间的相似度。
2.排序选择:将所有计算出的距离按照从小到大的顺序进行排序。
3.确定邻域:选择距离最小的K个点作为当前点的邻居。
4.计算异常值:根据这K个邻域的和预设值的阈值比较来判定当前点是否为异常值。如果这个值超过了阈值,则认为该点是异常值。
阈值的定义
KNN方法使用三种类型的距离度量之一作为异常分数的阈值:最大值、平均值和中位数。
"最大值"使用到k个邻居的最大距离作为异常分数。
"平均值"和"中位数"分别使用平均值和中位数作为异常分数。
距离计算一般有如下几种计算方法:
- 欧氏距离公式
计算在二维空间中两点之间的距离,公式如下:
powershell
|AB| = √[(x1-x2)² + (y1-y2)²]
- 曼哈顿距离
适用于网格布局的城市距离计算,公式如下:
powershell
|AB| = |x2-x1| + |y2-y1|
- 切比雪夫距离
两个点之间各坐标数值差绝对值的最大值,公式如下:
powershell
max(|x2-x1|, |y2-y1|)
- 闵氏距离
是欧氏距离的推广,公式如下:
powershell
|AB| = [∑(ai-bi)q]^(1/q)
其中a和b是两点在空间中的坐标,i表示维度,q是一个变参数2
三、KNN算法的优缺点
KNN算法当前主要使用距离度量法,即根据距离的远近,对近邻的点进行判断,距离越近则权重越大(权重为距离平方的倒数)。
优点:易于实现,无需估计参数,无需训练,支持增量学习,能对超多边形的复杂决策空间建模;
缺点:就是计算量较大,分析速度慢;
四、Python实现
python代码如下:
powershell
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
# 生成模拟数据集
X, y = make_moons(n_samples=500, noise=0.1, random_state=42)
X = StandardScaler().fit_transform(X) # 标准化数据
# 分割训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建KNN模型,这里设置n_neighbors为5,意味着考虑每个点的5个最近邻居
knn = KNeighborsClassifier(n_neighbors=5)
# 训练模型
knn.fit(X_train, y_train)
# 使用训练好的模型预测测试集上的标签
y_pred = knn.predict(X_test)
# 计算异常得分,可以是到最近邻居的距离或其他度量方式
distances, indices = knn.kneighbors(X_test)
anomaly_scores = distances.mean(axis=1) # 对每个样本取平均距离作为异常分数
# 打印前几个测试样本及其异常分数
for i in range(len(anomaly_scores)):
print(f"Sample {i}: Anomaly Score: {anomaly_scores[i]}")
# 设置阈值以区分正常和异常数据点
threshold = np.percentile(anomaly_scores, 95) # 取前95%的数据作为正常范围
# 标记异常数据点
anomalies = [score > threshold for score in anomaly_scores]
print("Anomalies:", anomalies)