异常检测是发现偏离规范的数据点。换句话说,这些点不符合预期模式。异常值和异常是用于描述异常数据的术语。异常检测在各个领域都很重要,因为它提供了有价值且可操作的见解。例如,核磁共振成像扫描中的异常可能表明大脑中存在肿瘤区域,而制造厂传感器的异常读数可能表明组件损坏。
完成本教程后,小普希望您能够了解:
- 定义并理解异常检测。
- 实施异常检测算法以分析和解释结果。
- 查看任何数据中可能导致异常行为的隐藏模式。
让我们开始吧。
什么是异常检测?
异常值只是一个数据点,它与特定数据集中的其余数据点有很大的偏差。类似地,异常检测是帮助我们识别数据异常值的过程,或者与大量其他数据点有很大偏差的点。
当涉及到大型数据集时,可能包含非常复杂的模式,这些模式无法通过简单地查看数据来检测。因此,为了实现关键的机器学习应用,异常检测的研究具有重要意义。
异常类型
在数据科学领域,我们有三种不同的方法来对异常进行分类。正确理解它们可能会对您处理异常的方式产生重大影响。
- 点或全局异常:对应于与其余数据点显着不同的数据点,全局异常被认为是最常见的异常形式。通常,发现全局异常与任何数据分布的平均值或中位数相距甚远。
- 上下文或条件异常:这些异常的值与同一上下文中其他数据点的值有很大不同。一个数据集中的异常可能不是另一个数据集中的异常。
- 集体异常:由于具有相同的异常特征而紧密聚集的异常对象被称为集体异常。例如,您的服务器并非每天都受到网络攻击,因此,它会被视为异常值。
虽然有许多用于异常检测的技术,但让我们实现一些以了解它们如何用于各种用例。
隔离森林
就像随机森林一样,隔离森林也是使用决策树构建的。它们以无监督的方式实现,因为没有预定义的标签。隔离森林的设计理念是异常是数据集中“少数且不同”的数据点。
回想一下,决策树是使用诸如基尼指数或熵之类的信息标准构建的。明显不同的组在树的根部被分开,在树枝的更深处,更细微的区别被识别出来。基于随机挑选的特征,隔离森林以树状结构处理随机二次采样的数据。深入到树中并需要更多切割来分离它们的样本很少有可能是异常的。同样,在树的较短分支上发现的样本更有可能是异常,因为树发现更容易将它们与其他数据区分开来。
在本次会议中,我们将在 Python 中实现隔离林,以了解它如何检测数据集中的异常情况。我们都知道令人难以置信的 scikit-learn API,它提供了各种 API 以便于实现。因此,我们将使用它来应用隔离森林来证明其对异常检测的有效性。
首先,让我们加载必要的库和包。
from sklearn.datasets import make_blobs
from numpy import quantile, random, where
from sklearn.ensemble import IsolationForest
import matplotlib.pyplot as plt
数据准备
我们将使用make_blob()
函数来创建一个包含随机数据点的数据集。
random.seed(3)
X, _ = make_blobs(n_samples=300, centers=1, cluster_std=.3, center_box=(20, 5))
让我们可视化数据集图以查看样本空间中随机分离的数据点。
plt.scatter(X[:, 0], X[:, 1], marker="o", c=_, s=25, edgecolor="k")
定义和拟合隔离森林模型以进行预测
如前所述,我们将使用IsolationForest
scikit-learn API 中的类来定义我们的模型。在类参数中,我们将设置估计器的数量和污染值。然后我们将使用该fit_predict()
函数通过将其拟合到模型来获取数据集的预测。
IF = IsolationForest(n_estimators=100, contamination=.03)
predictions = IF.fit_predict(X)
现在,让我们将负值提取为异常值,并用颜色突出显示异常来绘制结果。
outlier_index = where(predictions==-1)
values = X[outlier_index]
plt.scatter(X[:,0], X[:,1])
plt.scatter(values[:,0], values[:,1], color='y')
plt.show()
将所有这些放在一起,以下是完整的代码:
from sklearn.datasets import make_blobs
from numpy import quantile, random, where
from sklearn.ensemble import IsolationForest
import matplotlib.pyplot as plt
random.seed(3)
X, _ = make_blobs(n_samples=300, centers=1, cluster_std=.3, center_box=(20, 5))
plt.scatter(X[:, 0], X[:, 1], marker="o", c=_, s=25, edgecolor="k")
IF = IsolationForest(n_estimators=100, contamination=.03)
predictions = IF.fit_predict(X)
outlier_index = where(predictions==-1)
values = X[outlier_index]
plt.scatter(X[:,0], X[:,1])
plt.scatter(values[:,0], values[:,1], color='y')
plt.show()
核密度估计
如果我们认为数据集的范数应该适合某种概率分布,那么异常就是我们应该很少看到它们的那些异常,或者以非常低的概率。核密度估计是一种在样本空间中随机估计数据点的概率密度函数的技术。使用密度函数,我们可以检测数据集中的异常。
为了实现,我们将通过创建均匀分布来准备数据,然后应用KernelDensity
scikit-learn 库中的类来检测异常值。
首先,我们将加载必要的库和包。
from sklearn.neighbors import KernelDensity
from numpy import where, random, array, quantile
from sklearn.preprocessing import scale
import matplotlib.pyplot as plt
from sklearn.datasets import load_boston
准备和绘制数据
让我们编写一个简单的函数来准备数据集。随机生成的数据将用作目标数据集。
random.seed(135)
def prepData(N):
X = []
for i in range(n):
A = i/1000 + random.uniform(-4, 3)
R = random.uniform(-5, 10)
if(R >= 8.6):
R = R + 10
elif(R < (-4.6)):
R = R +(-9)
X.append([A + R])
return array(X)
n = 500
X = prepData(n)
让我们可视化绘图以检查数据集。
x_ax = range(n)
plt.plot(x_ax, X)
plt.show()
准备和拟合核密度函数以进行预测
我们将使用 scikit-learn API 来准备和拟合模型。然后使用score_sample()
函数获取数据集中样本的分数。接下来,我们将使用quantile()
函数来获取阈值。
kern_dens = KernelDensity()
kern_dens.fit(X)
scores = kern_dens.score_samples(X)
threshold = quantile(scores, .02)
print(threshold)
-5.676136054971186
将检测得分等于或低于获得的阈值的样本,然后用颜色突出显示的异常进行可视化:
idx = where(scores <= threshold)
values = X[idx]
plt.plot(x_ax, X)
plt.scatter(idx,values, color='r')
plt.show()
将所有这些放在一起,以下是完整的代码:
from sklearn.neighbors import KernelDensity
from numpy import where, random, array, quantile
from sklearn.preprocessing import scale
import matplotlib.pyplot as plt
from sklearn.datasets import load_boston
random.seed(135)
def prepData(N):
X = []
for i in range(n):
A = i/1000 + random.uniform(-4, 3)
R = random.uniform(-5, 10)
if(R >= 8.6):
R = R + 10
elif(R < (-4.6)):
R = R +(-9)
X.append([A + R])
return array(X)
n = 500
X = prepData(n)
x_ax = range(n)
plt.plot(x_ax, X)
plt.show()
kern_dens = KernelDensity()
kern_dens.fit(X)
scores = kern_dens.score_samples(X)
threshold = quantile(scores, .02)
print(threshold)
idx = where(scores <= threshold)
values = X[idx]
plt.plot(x_ax, X)
plt.scatter(idx,values, color='r')
plt.show()