作者|Rashida Nasrin Sucky
编译|VK
起源|Towards Datas Science

异样检测能够作为异样值剖析的一项统计工作来解决。然而如果咱们开发一个机器学习模型,它能够像平常一样自动化,能够节俭很多工夫。

异样检测有很多用例。信用卡欺诈检测、故障机器检测或基于异样特色的硬件零碎检测、基于医疗记录的疾病检测都是很好的例子。还有更多的用例。异样检测的利用只会越来越多。

在本文中,我将解释在Python中从头开始开发异样检测算法的过程。

公式和过程

与我之前解释过的其余机器学习算法相比,这要简略得多。该算法将应用均值和方差来计算每个训练数据的概率。

如果一个训练实例的概率很高,这是失常的。如果某个训练实例的概率很低,那就是一个异样的例子。对于不同的训练集,高概率和低概率的定义是不同的。咱们当前再探讨。

如果我要解释异样检测的工作过程,这很简略。

  1. 应用以下公式计算平均值:

这里m是数据集的长度或训练数据的数量,而$x^i$是一个独自的训练例子。如果你有多个训练特色,大多数状况下都须要计算每个特色能的平均值。

  1. 应用以下公式计算方差:

这里,mu是上一步计算的平均值。

  1. 当初,用这个概率公式计算每个训练例子的概率。

不要被这个公式中的求和符号弄糊涂了!这实际上是Sigma代表方差。

稍后咱们将实现该算法时,你将看到它的样子。

  1. 咱们当初须要找到概率的临界值。正如我后面提到的,如果一个训练例子的概率很低,那就是一个异样的例子。

低概率有多大?

这没有广泛的限度。咱们须要为咱们的训练数据集找出这个。

咱们从步骤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/