作者|Rashida Nasrin Sucky
编译|VK
起源|Towards Datas Science
异样检测能够作为异样值剖析的一项统计工作来解决。然而如果咱们开发一个机器学习模型,它能够像平常一样自动化,能够节俭很多工夫。
异样检测有很多用例。信用卡欺诈检测、故障机器检测或基于异样特色的硬件零碎检测、基于医疗记录的疾病检测都是很好的例子。还有更多的用例。异样检测的利用只会越来越多。
在本文中,我将解释在Python中从头开始开发异样检测算法的过程。
公式和过程
与我之前解释过的其余机器学习算法相比,这要简略得多。该算法将应用均值和方差来计算每个训练数据的概率。
如果一个训练实例的概率很高,这是失常的。如果某个训练实例的概率很低,那就是一个异样的例子。对于不同的训练集,高概率和低概率的定义是不同的。咱们当前再探讨。
如果我要解释异样检测的工作过程,这很简略。
- 应用以下公式计算平均值:
这里m是数据集的长度或训练数据的数量,而$x^i$是一个独自的训练例子。如果你有多个训练特色,大多数状况下都须要计算每个特色能的平均值。
- 应用以下公式计算方差:
这里,mu是上一步计算的平均值。
- 当初,用这个概率公式计算每个训练例子的概率。
不要被这个公式中的求和符号弄糊涂了!这实际上是Sigma代表方差。
稍后咱们将实现该算法时,你将看到它的样子。
- 咱们当初须要找到概率的临界值。正如我后面提到的,如果一个训练例子的概率很低,那就是一个异样的例子。
低概率有多大?
这没有广泛的限度。咱们须要为咱们的训练数据集找出这个。
咱们从步骤3中失去的输入中获取一系列概率值。对于每个概率,通过阈值的设置失去数据是否异样
而后计算一系列概率的精确度、召回率和f1分数。
精度可应用以下公式计算
召回率的计算公式如下:
在这里,True positives(真正例)是指算法检测到一个异样的例子的数量,而它真实情况也是一个异样。
False Positives(假正例)当算法检测到一个异样的例子,但在理论状况中,它不是异样的,就会呈现误报。
False Negative(假反例)是指算法检测到的一个例子不是异样的,但实际上它是一个异样的例子。
从下面的公式你能够看出,更高的精确度和更高的召回率总是好的,因为这意味着咱们有更多的真正的正例。但同时,假正例和假反例起着至关重要的作用,正如你在公式中看到的那样。这须要一个平衡点。依据你的行业,你须要决定哪一个对你来说是能够忍耐的。
一个好方法是取平均数。计算平均值有一个独特的公式。这就是f1分数。f1得分公式为:
这里,P和R别离示意精确性和召回率。
我不想具体阐明为什么这个公式如此独特。因为这篇文章是对于异样检测的。如果你对这篇文章更感兴趣的话,能够查看:https://towardsdatascience.co...
依据f1分数,你须要抉择你的阈值概率。
异样检测算法
我将应用Andrew Ng的机器学习课程的数据集,它具备两个训练特色。我没有在本文中应用实在的数据集,因为这个数据集非常适合学习。它只有两个特色。在任何实在的数据集中,都不可能只有两个特色。
有两个个性的益处是能够可视化数据,这对学习者十分有用。请随便从该链接下载数据集,而后持续:
https://github.com/rashida048...
首先,导入必要的包
import pandas as pd import numpy as np
导入数据集。这是一个excel数据集。在这里,训练数据和穿插验证数据存储在独自的表中。所以,让咱们把训练数据带来。
df = pd.read_excel('ex8data1.xlsx', sheet_name='X', header=None)df.head()
让咱们将第0列与第1列进行比拟。
plt.figure()plt.scatter(df[0], df[1])plt.show()
你可能通过看这张图晓得哪些数据是异样的。
查看此数据集中有多少个训练示例:
m = len(df)
计算每个特色的平均值。这里咱们只有两个特色:0和1。
s = np.sum(df, axis=0)mu = s/mmu
输入:
0 14.1122261 14.997711dtype: float64
依据下面“公式和过程”局部中形容的公式,让咱们计算方差:
vr = np.sum((df - mu)**2, axis=0)variance = vr/mvariance
输入:
0 1.8326311 1.709745dtype: float64
当初把它做成对角线形态。正如我在概率公式前面的“公式和过程”一节中所解释的,求和符号实际上是方差
var_dia = np.diag(variance)var_dia
输入:
array([[1.83263141, 0. ], [0. , 1.70974533]])
计算概率:
k = len(mu)X = df - mup = 1/((2*np.pi)**(k/2)*(np.linalg.det(var_dia)**0.5))* np.exp(-0.5* np.sum(X @ np.linalg.pinv(var_dia) * X,axis=1))p
训练局部曾经实现。
下一步是找出阈值概率。如果概率低于阈值概率,则示例数据为异样数据。但咱们须要为咱们的非凡状况找出那个阈值。
对于这一步,咱们应用穿插验证数据和标签。
对于你的案例,你只需保留一部分原始数据以进行穿插验证。
当初导入穿插验证数据和标签:
cvx = pd.read_excel('ex8data1.xlsx', sheet_name='Xval', header=None)cvx.head()
标签如下:
cvy = pd.read_excel('ex8data1.xlsx', sheet_name='y', header=None)cvy.head()
我将把'cvy'转换成NumPy数组,因为我喜爱应用数组。不过,数据帧也不错。
y = np.array(cvy)
输入:
# 数组的一部分array([[0], [0], [0], [0], [0], [0], [0], [0], [0],
这里,y值0示意这是一个失常的例子,y值1示意这是一个异样的例子。
当初,如何抉择一个阈值?
我不想只查看概率表中的所有概率。这可能是不必要的。让咱们再检查一下概率值。
p.describe()
输入:
count 3.070000e+02mean 5.905331e-02std 2.324461e-02min 1.181209e-2325% 4.361075e-0250% 6.510144e-0275% 7.849532e-02max 8.986095e-02dtype: float64
如图所示,咱们没有太多异样数据。所以,如果咱们从75%的值开始,这应该是好的。但为了平安起见,我会从平均值开始。
因而,咱们将从平均值和更低的概率范畴。咱们将查看这个范畴内每个概率的f1分数。
首先,定义一个函数来计算真正例、假正例和假反例:
def tpfpfn(ep): tp, fp, fn = 0, 0, 0 for i in range(len(y)): if p[i] <= ep and y[i][0] == 1: tp += 1 elif p[i] <= ep and y[i][0] == 0: fp += 1 elif p[i] > ep and y[i][0] == 1: fn += 1 return tp, fp, fn
列出低于或等于均匀概率的概率。
eps = [i for i in p if i <= p.mean()]
检查一下列表的长度
len(eps)
输入:
133
依据后面探讨的公式定义一个计算f1分数的函数:
def f1(ep): tp, fp, fn = tpfpfn(ep) prec = tp/(tp + fp) rec = tp/(tp + fn) f1 = 2*prec*rec/(prec + rec) return f1
所有函数都筹备好了!
当初计算所有epsilon或咱们之前抉择的概率值范畴的f1分数。
f = []for i in eps: f.append(f1(i))f
输入:
[0.14285714285714285, 0.14035087719298248, 0.1927710843373494, 0.1568627450980392, 0.208955223880597, 0.41379310344827586, 0.15517241379310345, 0.28571428571428575, 0.19444444444444445, 0.5217391304347826, 0.19718309859154928, 0.19753086419753085, 0.29268292682926833, 0.14545454545454545,
这是f分数表的一部分。长度应该是133。
f分数通常在0到1之间,其中f1得分越高越好。所以,咱们须要从方才计算的f分数列表中取f的最高分数。
当初,应用“argmax”函数来确定f分数值最大值的索引。
np.array(f).argmax()
输入:
131
当初用这个索引来失去阈值概率。
e = eps[131]e
输入:
6.107184445968581e-05
找出异样实例
咱们有临界概率。咱们能够从中找出咱们训练数据的标签。
如果概率值小于或等于该阈值,则数据为异样数据,否则为失常数据。咱们将失常数据和异样数据别离示意为0和1,
label = []for i in range(len(df)): if p[i] <= e: label.append(1) else: label.append(0)label
输入:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
这是标签列表的一部分。
我将在下面的训练数据集中增加此计算标签:
df['label'] = np.array(label)df.head()
我在标签为1的中央用红色绘制数据,在标签为0的中央用彩色绘制。以下是后果。
有情理吗?
是的,对吧?红色的数据显著异样。
论断
我试图一步一步地解释开发异样检测算法的过程,我心愿这是能够了解的。如果你仅仅通过浏览就无奈了解,我倡议你运行每一段代码。那就很分明了。
原文链接:https://towardsdatascience.co...
欢送关注磐创AI博客站:
http://panchuang.net/
sklearn机器学习中文官网文档:
http://sklearn123.com/
欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/