赞
踩
2022.03.10开始第十五章的学习,先开个头,看样子肯定还要花不少时间。咱家这两天成中高风险区了,不出意外的话以后要待在宿舍上网课了。
2022.03.11把书本从研究院搬到了宿舍上课,继续学习
2022.03.12公寓封了。。。继续学习
2022.03.14真的是有些无语,事情多到不休息都做不完,现在这才先放下一些活回来学一下
2022.03.22继续学习
2022.03.23继续学习
2022.03.24继续学习
2022.03.25继续学习
2022.04.04最近好忙呀,但是我知道这并不是极限,还是要静下心来,认真把事情做好,少休息一会,多学一些,不亏
2022.04.06挤点时间,能学一会是一会
2022.04.24天天写实验报告都写麻了,十几份是有了,每份都不少写
2022.05.03五一假期,准备考试复习累了来写一会
2022.05.05时间大概是不够用了,这种笔记记法很费时,后面的内容会以简洁为主(配图会在文章发布后逐渐重新制作并替换)
2022.06.21考完试了,有时间了!学!
2022.06.22继续学习
2022.07.07继续学习
2022.07.17事情还是好多,晚上睡觉前学一会这个
2022.07.24继续学习,争取四天之内弄完
2022.07.25继续学习
2022.07.26继续学习
2022.07.27继续学习
2022.07.28结束这一章!
那么什么是异常检测,为了理解这个概念,先举一个例子:
A
i
r
c
r
a
f
t
e
n
g
i
n
e
f
e
a
t
u
r
e
s
:
x
1
=
h
e
a
t
g
e
n
e
r
a
t
e
d
x
2
=
v
i
b
r
a
t
i
o
n
i
n
t
e
n
s
i
t
y
.
.
.
D
a
t
a
s
e
t
:
{
x
(
1
)
,
x
(
2
)
,
.
.
.
,
x
(
m
)
}
N
e
w
e
n
g
i
n
e
:
x
t
e
s
t
假如你是个飞机引擎制造商,当在生产线上生产飞机引擎时,需要进行质量控制测试,而作为这个测试的一部分,测试了飞机引擎的一些特征变量,比如测量了引擎运转时产生的热量,或者引擎的震动等等。在实际工作中,我们确实会从真实的飞机引擎采集这些特征变量,于是就有了一个数据集,从 x(1) 到 x(m),如果我们生产了 m 个引擎的话,可以将数据对应地画成图(下图左):
其中每个叉都是无标签数据,这样,异常检测问题可以定义如下:
假设后来有一天,有一个新的飞机引擎从生产线上生产出来,而你的新飞机引擎有一个特征变量集 xtest,所谓的异常检测问题就是我们希望知道这个新的飞机引擎是否有某种异常,或者说,我们希望判断这个引擎是否需要进一步测试,因为如果它看起来像一个正常的引擎,那么可以直接送出去,而不需要进一步的测试。比如说,如果新的引擎对应的点落在这里(上图右绿色样本),那么可以认为它看起来像是之前见过的引擎,因此可以直接认为它是正常的;然而,如果新飞机引擎对应点在外面(上图右蓝色样本),那么可以认为这是一个异常,也许需要在发货之前做进一步检测,这个引擎和之前见过的其它飞机引擎看起来不一样。
下面是更正式的定义异常检测问题:
Density
estimation:
D
a
t
a
s
e
t
:
{
x
(
1
)
,
x
(
2
)
,
.
.
.
,
x
(
m
)
}
I
s
x
t
e
x
t
a
n
o
m
a
l
o
u
s
?
M
o
d
e
l
p
(
x
)
x
t
e
s
t
{
p
(
x
t
e
s
t
)
<
ϵ
⟶
f
l
a
g
a
n
o
r
m
a
l
y
p
(
x
t
e
s
t
)
≥
ϵ
⟶
O
K
有一些数据,从 x(1) 到 x(m),我们通常假定这 m 个样本都是正常的(或者说都不是异常的),然后我们需要一个算法检测一个新的样本数据 xtest 是否是异常,我们要采取的方法是,给定无标签的训练集,我们将对数据建模,即 p(x),也就是说,我们将对 x 的分布概率建模,其中 x 是飞机引擎的一系列特征变量。因此,当我们建立了 x 的概率模型之后,如果对于新的飞机引擎,也就是 xtest 的概率 p 低于阈值 ε,那么我们就将其标记为异常。
因此,当看到一个新的引擎,在根据训练数据得到的 p(x) 模型中,这个点出现的概率非常低时,我们就将其标记为异常;反之,如果 xtest 的概率 p 大于等于给定的阈值 ε,我们就认为是正常的。
给定图中这样的训练集,如果你建立了一个模型,你将很可能发现飞机引擎对应的模型 p(x) 将会认为在中心区域的这些点概率相当大,这些点将是正常的,而稍微远离中心区域的点概率会小一些,更远的地方的点,它们的概率将更小,这些外面的点将成为异常点。
Fraud
detection:
x
(
i
)
=
f
e
a
t
u
r
e
s
o
f
u
s
e
r
i
′
s
a
c
t
i
v
i
t
i
e
s
M
o
d
e
l
p
(
x
)
f
r
o
m
d
a
t
a
I
d
e
n
t
i
f
y
u
n
u
s
u
a
l
u
s
e
r
s
b
y
c
h
e
c
k
i
n
g
w
h
i
c
h
h
a
v
e
p
(
x
)
<
ϵ
Manufacturing
Monitoring
computers
in
a
data
center:
x
(
i
)
=
f
e
a
t
u
r
e
s
o
f
m
a
c
h
i
n
e
i
x
1
=
m
e
m
o
r
y
u
s
e
x
2
=
n
u
m
b
e
r
o
f
d
i
s
k
a
c
c
e
s
s
e
s
/
s
e
c
x
3
=
C
P
U
l
o
a
d
x
4
=
C
P
U
l
o
a
d
/
n
e
t
w
o
r
k
t
r
a
f
f
i
c
.
.
.
假设 x 是一个实数的随机变量,如果 x 的概率分布服从高斯分布,其中均值为 μ,方差为 σ 的平方,那么将它记作:
x
∼
N
(
μ
,
σ
2
)
其中的波浪号叫做什么的分布(distributed as),为了表示高斯分布,有时用大写字母 N 来表示(也就是正态分布,二者是同义词)。如果我们将高斯分布的概率密度函数绘制出来,它看起来将是这样一个钟形的曲线(下图),它由两个参数控制,分别是 μ 和 σ ,其中 μ 控制这个钟形曲线的中心位置, σ 控制这个钟形曲线的宽度,因此参数 σ 有时也称作一个标准差(one standard deviation)。
这条钟形曲线决定了 x 取不同值的概率,因此 x 取中间这些值的时候输出的概率相当大,因为高斯分布的概率密度在中间位置很大,而 x 取远处和更远处的值时,概率将逐渐降低直至消失。
最后为了讲述的完整性,下面给出高斯分布的数学公式:
p
(
x
;
μ
,
σ
2
)
=
1
2
π
σ
e
x
p
(
−
(
x
−
μ
)
2
2
σ
2
)
p
(
x
)
=
p
(
x
1
)
p
(
x
2
)
p
(
x
3
)
.
.
.
p
(
x
n
)
那么,如何对 p(x1)、p(x2) 等等这些项建模呢?假定特征 x1 是分散的,它服从高斯正态分布,它有某个期望,可以写为 μ1,以及某个方差,用 σ12 表示。这样 p(x1) 就可以写成这样一个高斯分布,N(μ1, σ12),同样,假设 x2 也服从高斯分布,一直到 xn 也是如此。
x
1
∼
N
(
μ
1
,
σ
1
2
)
x
2
∼
N
(
μ
2
,
σ
2
2
)
x
3
∼
N
(
μ
3
,
σ
3
2
)
.
.
.
进而我们就在原式的基础上进一步细化,得到了我们要说的模型(下式)。下面这个等式实际上等同于一个 x1 到 xn 上的独立假设。不过在实践中,结果表明,我们将要介绍的这个算法它的效果还不错,无论这些特征量是否近乎独立,并且即使这个独立假设不成立,这个算法也能正常运行。最后,我们来将这个式子写成一个乘积的形式(更紧凑一些)。
p
(
x
)
=
p
(
x
1
;
μ
1
,
σ
1
2
)
p
(
x
2
;
μ
2
,
σ
2
2
)
p
(
x
3
;
μ
3
,
σ
3
2
)
.
.
.
p
(
x
n
;
μ
n
,
σ
n
2
)
=
∏
j
=
1
n
p
(
x
j
;
μ
j
,
σ
j
2
)
假定我们有如下数据集,看一下特征量 x1 以及这个数据集,它看起来比较平均, x1 特征量中均值为 5,并且有标准差。如果我们只看数据集中的 x1 方向的数值,其标准差可能为 2,也就是 σ1 ;对应地,纵轴所测量的特征值 x2 ,它的平均值可能是 3,并且标准差的值为 1 。如果用这个数据集来估计 μ1 、μ 2 、σ1 、σ2 ,这些就是我们可以得到的。
p( x1; μ1, σ12 ) 和 p( x2; μ2, σ22 ) ,它们看起来像是下图的两个分布。
实际上,如果绘制出 p(x) 的图像的话,也就是上面两个方向上的 p(x) 的乘积,我们会得到一个类似于下图的曲面图,这就是 p(x) 的图示,它的高度就是它所落在的曲面上那一点的高度,也就是说,给定一个特定的 x1 和 x2 的值,在曲面中对应点的高度的数值就是 p(x1) 乘以 p(x2)。
现在我们就得出了如何对这些数据拟合出参数值,再来看一些新的案例,假定在数据集中有两个新例子(下图绿色样本),那么这两个例子是否异常呢?处理这个问题的方法是,对 ε 设置某个值,假如选定 ε = 0.02(之后会讲到如何选取ε的值)。
先讲第一个例子,称作是 x(1)test,同时第二个例子称作是 x(2)test,接下来我们计算出 p(x(1)test),用这个公式来进行计算:
p
(
x
)
=
p
(
x
1
;
μ
1
,
σ
1
2
)
p
(
x
2
;
μ
2
,
σ
2
2
)
不难发现这是一个相当大的数,特别地,这个值可能大于等于 ε,因此这是个相当大的概率,至少比 ε 大,因此我们就说 x(1)test 没有异常;然而,如果计算 x(2)test 的值,它会是一个更加小的值(比 ε 小),因此说它确实出现了异常,因为它比选定的 ε 值小很多。
事实上,我们可以改良这个方法,从这个三维曲面图可以看出所有的 x1 和 x2 值,所在位置都是比较高的点对应的就是无异常情况,或者说是一个正常例子;相反,所有那些更远的点的概率值都相当小,所以我们会将这些点标注为异常。因此,我们可以定义某个范围,在这之外的(上图左粉色阴影区域)都会标注为异常,对于上面我们给出的例子,x(1) 是非异常的,而 x(2) 是异常的。
在之前的内容中,我们已经介绍了实数评估的重要性,它的主要思想是,当你为某个应用开发一个学习算法时,你需要进行一系列的选择,比如选择使用什么特征等等,如果你有某种方法,通过返回一个实数来评估你的算法,那么对这些选择作出决定往往会容易得多。
比如你需要决定该不该把想到的一个额外的特征纳入当前的特征中,如果你分别在纳入该特征和不纳入该特征情况下运行算法,然后算法返回一个数字,来告诉你这个特征对算法的影响是好是坏,这样的话,你就能更简单地决定要不要纳入这个特征。
有一个方法来评估异常检测系统(anomaly detection system) 对于快速地开发出这样一个系统是非常有帮助的。为了实现这一点(评估一个异常检测系统),假如有一些带标签的数据,到目前为止,我们都把异常检测看作是一个无监督学习问题(因为用的是无标签的数据),但是如果你有一些带标签的数据,来指明哪些是异常样本,哪些是正常样本,这也就是我们认为的可以评估异常检测算法的标准方法。
还是用飞机引擎的例子,假如有一些带标签的数据代表异常样本,代表这批引擎是异常的;同时还有一些无异常的样本。用 y = 0 来表示这些无异常或者正常的样本,用 y = 1 来代表异常样本。
那么异常检测算法的开发过程以及评估算法如下所示:
Training
set:
x
(
1
)
,
x
(
2
)
,
.
.
.
,
x
(
m
)
(
a
s
s
u
m
e
n
o
r
m
a
l
e
x
a
m
p
l
e
s
/
n
o
t
a
n
o
m
a
l
o
u
s
)
Cross
validation
set:
(
x
c
v
(
1
)
,
y
c
v
(
1
)
)
,
.
.
.
,
(
x
c
v
(
m
c
v
)
,
y
c
v
(
m
c
v
)
)
Test
set:
(
x
t
e
s
t
(
1
)
,
y
t
e
s
t
(
1
)
)
,
.
.
.
,
(
x
t
e
s
t
(
m
t
e
s
t
)
,
y
t
e
s
t
(
m
t
e
s
t
)
)
我们先假设有一训练集,并把该训练集看作是无标签的,所以它是一个很大的正常样本(或无异常样本)的集合。通常来说,把它们看作是无异常样本,即使溜进了一些异常样本也没关系。接下来我们要定义一个交叉验证集和测试集,用来评估这个异常检测算法。具体来说,对交叉验证集和测试集,假设在交叉验证集和测试集中,包含一些已知是异常的样本,所以在测试集中,有一些标签是 y = 1 的样本(代表异常的飞机引擎)。
举一个具体的例子,数据集如下:
Aircraft
rngines
motivating
example
10000
g
o
o
d
(
n
o
r
m
a
l
)
e
n
g
i
n
e
s
20
f
l
a
w
e
d
e
n
g
i
n
e
s
(
a
n
o
m
a
l
o
u
s
)
所有数据如下:制造了10000个引擎来作为样本(正常的完好的飞机引擎),并且,即使有一些异常的引擎混入了这10000个样本也没有关系。
假设这10000个样本绝大多数都是正常的引擎,其中包含20个异常引擎。对于典型的异常检测应用来说,异常样本的数量,也就是这些 y = 1 的样本,大概是20到50个,这是一个很常见的 y = 1 样本数量的范围,而且通常来说,正样本的数量还要大得多。
有了这组数据,我们要把数据分离到训练集、交叉验证集和测试集,一种典型的方法如下:
T
r
a
i
n
i
n
g
s
e
t
:
6000
g
o
o
d
e
n
g
i
n
e
s
C
V
:
2000
g
o
o
d
e
n
g
i
n
e
s
(
y
=
0
)
,
10
a
n
o
m
a
l
o
u
s
(
y
=
1
)
T
e
s
t
:
2000
g
o
o
d
e
n
g
i
n
e
s
(
y
=
0
)
,
10
a
n
o
m
a
l
o
u
s
(
y
=
1
)
把这 10000 个正常引擎其中 6000 个放到无标签训练集中(虽然我们把它叫做无标签数据集,但实际上这些样本都对应标签 y = 0),我们要用它们来拟合p(x):
p
(
x
)
=
p
(
x
1
;
μ
1
;
σ
1
2
)
.
.
.
p
(
x
n
;
μ
n
;
σ
n
2
)
用这6000个样本来评估参数 μ1, σ12,…, μn, σn2,这些就是正常或者说大多数正常的样本所在的训练集。然后把剩下的正常的引擎中的一些放到交叉验证集中,再放一些到测试集中。我们还有 20 个异常的飞机引擎,也把它们进行分离,其中 10 个放到交叉验证集中,10 个放到测试集中。
上面用到的是比较推荐的划分带标签和无标签的数据的方法,即采用 6:2:2 的比例来分配正常样本,而对于异常样本,我们只把它们放在交叉验证集和测试集中。之后将说明这样分的理由。
但是在应用异常检测算法时,也存在着不恰当的划分方法:
A
l
t
e
r
n
a
t
i
v
e
:
T
r
a
i
n
i
n
g
s
e
t
:
6000
g
o
o
d
e
n
g
i
n
e
s
C
V
:
4000
g
o
o
d
e
n
g
i
n
e
s
(
y
=
0
)
,
10
a
n
o
m
a
l
o
u
s
(
y
=
1
)
T
e
s
t
:
4000
g
o
o
d
e
n
g
i
n
e
s
(
y
=
0
)
,
10
a
n
o
m
a
l
o
u
s
(
y
=
1
)
把10000个正常引擎中的 6000 个放在训练集中,然后把剩下的 4000 个样本同时用作交叉验证集和测试集。
我们通常认为,交叉验证集和测试集是两个完全不同的数据集,但在异常检测中,有时可能会看到别人把一部分正常的引擎同时用作交叉验证集和测试集,有时还可能看到别人把异常飞机引擎也同时用于交叉验证集和测试集。总之,所有这样的想法都是不太好的做法,也是很不推荐的做法,把同样的数据同时用于交叉验证集和测试集,这种方法在机器学习中是不好的做法。
得到训练集、交叉验证集和测试集之后,下面介绍如何推导和评估算法:
Algorithm
evaluation
F
i
t
m
o
d
e
l
p
(
x
)
o
n
t
r
a
i
n
i
n
g
s
e
t
{
x
(
1
)
,
.
.
.
,
x
(
m
)
}
O
n
a
c
r
o
s
s
v
a
l
i
d
a
t
i
o
n
/
t
e
s
t
e
x
a
m
p
l
e
x
,
p
r
e
d
i
c
t
y
=
{
1
i
f
p
(
x
)
<
ε
(
a
n
o
m
a
l
y
)
0
i
f
p
(
x
)
≥
ε
(
n
o
r
m
a
l
y
)
首先,使用训练集拟合模型 p(x),也就是把这 m 个无标签样本都用高斯函数来拟合。虽然在这里把它们称作无标签样本,但实际上我们假设这些样本是正常的飞机引擎。
我们的异常检测算法实际上要进行预测,所以在交叉验证集和测试集中,假如有一个样本x,算法在 p(x) < ε 时,会预测 y = 1;而 p(x) ≥ ε 时,会预测 y = 0(即给出x的值,算法将预测出 y 的值,y = 1 对应异常样本,y = 0 对应正常样本)。
随后对于给定的训练集、交叉验证集和测试集,我们如何来推倒这个算法呢?更具体地说,应当如何来评估一个异常检测算法?
第一步是用无标签训练数据来拟合模型 p(x)(和前面一样,虽然说是无标签,但实际上我们假设这些样本绝大多数都是正常的飞机引擎),然后要拟合模型 p(x),用高斯函数拟合这些参数。
接下来,对于交叉验证集和测试集,我们要让异常检测算法来预测 y 的值,于是对每一个测试样本,有 x(i)_test 和 y(i)_test,其中 y = 1 或 0 取决于该样本是否为正常样本,所以给定训练集中的x作为输入,异常检测算法将进行对应的预测:当 p(x) < ε 时,有 y = 1(当概率p很小的时候,会预测y=1),并且想要算法在 p(x) ≥ ε时,预测出 y = 0(也就是当p(x)很大的时候,会预测该样本为正常样本)。
所以现在我们可以把异常检测算法看成是对交叉验证集和测试集中的 y 标签进行预测,这和我们在监督学习中所做的非常相似,即我们的测试集是带标签的,而我们的算法要对这些标签作出预测,所以可以通过算法预测成功的次数来对算法进行评估。当然,这些标签会很倾斜,因为 y = 0 的情况,也就是正常的样本会比 y = 1 的异常样本常见得多。这跟在监督学习中用到的评价指标非常接近。
那么,什么是一个好的评价指标呢?
P
o
s
s
i
b
l
e
e
v
a
l
u
a
t
i
o
n
m
e
t
r
i
c
s
:
−
T
r
u
e
p
o
s
i
t
i
v
e
,
f
a
l
s
e
p
o
s
i
t
i
v
e
,
f
a
l
s
e
n
e
g
a
t
i
v
e
,
t
r
u
e
n
e
g
a
t
i
v
e
−
P
r
e
c
i
t
i
o
n
/
R
e
c
a
l
l
−
F
1
−
s
c
o
r
e
C
a
n
a
l
s
o
u
s
e
c
r
o
s
s
v
a
l
i
d
a
t
i
o
n
s
e
t
t
o
c
h
o
o
s
e
p
a
r
a
m
e
t
e
r
ϵ
因为我们的数据很倾斜(即 y = 0 的情况很常见),那么分类正确率就不是一个好的评价指标。在之前的文章中也介绍过,如果你有一个很倾斜的数据集,y = 0 的情况占了绝大多数,那么分类正确率就会一直都很高。
相比之下,如果我们用的是计算真阳性、假阳性、假阴性以及真阴性的比例,或者计算出算法的精度以及召回率,或者计算出像 F1-score(它是一个实数),来总结和反映精度以及召回率。通过这些方法,就可以评估异常检测算法在交叉验证和测试集样本中的表现。
最后一点,之前在异常检测算法中,我们还有一个参数 ε,这个 ε 是我们用来决定什么时候把一个样本当作是异常样本的一个阈值。所以,如果你有一个交叉验证集,一个选择参数 ε 的方法就是尝试去使用许多不同的 ε 值,该 ε 值能够最大化 F1-score 或者在其他方面有良好表现的 ε 值。
一般来说,使用训练集、交叉验证集和测试集的方法是:当进行决策时(比如决定要不要纳入某个特征,或者定义参数 ε 作为阈值),我们会在交叉验证集中评估算法,然后做出决策(例如用哪些特征,怎么设置 ε 值,用这个上面介绍的评价方法在交叉验证集中评估算法),当选择好特征,找到合适的 ε 值以后,我们就能用最后的模型来评估算法在测试集中对算法进行最后的评估。
|
|
---|---|
①Very small number of positive examples (y=1). (0-20 is common) | ③Large number of positive and negative examples |
②Large number of negative (y=0) examples | |
④Many different “types” of anomalies. Hard for any algorithm to learn from positive examples what the anomalies look like | ⑥Enough positive examples for algorithm to get a sense of what positive examples are like, future positive examples likely to be similar to ones in training set |
⑤future anomalies may look nothing like any of the anomalous examples we’ve seen so far |
①如果你遇到了一个问题,它的正常例子数量很少(记住y=1时这些例子为异常样例),那么你可以考虑使用一个异常检测算法。典型情况下,我们有 0 到 20 个,可能最多到 50 个正样本,通常情况下,我们只有非常少量的正样本,接下来我们保存这些正样本用于交叉验证集和测试集。
②与此相反,在一个典型的异常检测中,我们经常会有一个比起正常样本(正常的航空发动机)数量更大的负样本,那么我们可以用这些庞大数量的负样本来拟合出 p(x) 的值,因此在许多异常检测应用中,有这样一个思想:如果有很少的正样本和很多的负样本,当我们在处理估计 p(x) 的值拟合所有的高斯参数的过程中,只需要负样本就够了。所以如果有大量的负样本,我们仍然可以很好的拟合 p(x) 的值。
③对于监督学习来说,更为典型的情况是在合理范围内会有大量的正样本和负样本,所以这是一种考虑问题的方式,来决定我们是应该使用一个异常检测算法还是一个监督学习算法。
④还有另一种人们经常考虑异常检测算法的方法,对于异常检测应用来说,经常有许多不同类型的异常,比如航空发动机,有很多不同途径导致发动机异常,也有许多部件可能出问题导致航空发动机宕机。因此,如果是这种情况,你有很少数量的正样本,那么对一个算法就很难去从小数量的正样本中去学习异常是什么。
⑤特别地,未来可能出现的异常看起来可能会与已有的截然不同,所以可能在正样本中,你可能已经了解 5 个或 10 个或 20 个航空发动机发生故障的情况,但是可能到了明天,你需要检测一个全新的集合、一种新类型异常、一种全新的飞机发动机出现故障的情况,而且之前从来就没有见过。如果是这样的情况,那么我们就更应该对负样本用高斯分布模型 p(x) 来建模,而不是费尽心思对正样本建模,因为明天的异常可能与迄今为止见过的情况完全不同。
⑥相反,在一些其它问题中,你有足够数量的正样本或是一个已经能识别正样本的算法,尤其是,假如你认为未来可能出现的正样本与你当前训练集中的正样本类似,那么这种情况下使用一个监督学习算法会更合理,它能够查看大量正样本和大量负样本来学到相应特征,并且能够尝试区分正样本和负样本。
总结: 当遇到一个特定问题时,我们应该能够判断出是用异常检测算法还是监督学习算法。二者的关键不同在于,在异常检测中,我们通常只有很少量的正样本,因此对于一个学习算法而言,它是不可能从这些正样本这学习到足够的知识的,所以我们要做的是使用大量负样本,让这个学习算法学到足够多的内容,从那些负样本中学习 p(x) 的值,比如说是飞机发动机故障的情况,我们保留小数量的正样本,用来评估我们的算法,这个算法用于交叉验证集或测试集。
顺便提一句,这些不同类型的异常,我们在之前的文章中曾讨论过垃圾邮件的例子,这些例子中,实际有许多不同类型的垃圾邮件,有些垃圾邮件企图向你兜售商品,有些企图偷取你的密码(钓鱼邮件),还有许多不同类型的垃圾邮件,但是对于垃圾邮件问题,通常有足够的垃圾邮件例子,垃圾邮件有许多不同类型,因为我们有大量垃圾邮件的例子,这就是为什么我们通常把垃圾邮件问题看成一个监督学习问题,即使有许多不同类型的垃圾邮件。
Anomaly detection | Supervised learning |
---|---|
Fraud detection | Email spam classification |
Manufacturing (e.g. aircraft engines) | Weather prediction (sunny/rainy/etc) |
Monitoring machines in a data center | Cancer classification |
在异常检测算法中,我们经常做的一件事是使用高斯分布来对特征建模,假设其函数 xi 的期望是 μi ,方差是 σi2。
p
(
x
i
;
μ
i
,
σ
i
2
)
我们经常做的一件事就是画出数据,或者用直方图表示数据,以确保这些数据在进入异常检测算法前,看上去比较接近于高斯分布。当然,这只是一种很好的卫生检查(sanitary check),即使我们数据并不是高斯分布,算法往往也能正常运行。但是,如果我们的数据画出来,看起来是像这样的直方图:
我们可以使用 Octave 中的 hist 指令画出上面的直方图,该图看上去近似于高斯分布,如果我们的特征是这样的话,那么我们将会很乐意将其输入到算法中,如果我们的数据直方图画出来是这样的(下图左),一点也不像一条钟形曲线,这是一个非常不均匀的分布,它的峰值分散在一边。如果数据是这样的话,我们通常会对数据进行一些不同的转换,使得它看上去更接近高斯分布,即使我们不这么做,算法也能运行,但如果我们使用这些转换,使数据更接近高斯分布,那么算法也许能运行的更好。
所以,假设所给的是这样的数据集,我们通常会对数据进行一次对数转换(log transformation),当我们这么做之后并重新画出直方图(上图右),在这个特殊的例子中,会得到一个像这样的直方图,这样看起来更像高斯分布了(典型的钟形曲线),这样我们就能拟合出期望和方差的参数了。
我们所说的进行对数转换的意思就是,如果有一些特征 x1,并且 x1的直方图是上图左那样的,那么可以将特征 x1 替换成 log(x1),这就会形成一个新的 x1 ,将它的直方图画在右边,这看起来更像高斯分布了。
x
1
⟵
l
o
g
(
x
1
)
x
2
⟵
l
o
g
(
x
2
+
1
)
l
o
g
(
x
2
+
c
)
x
3
⟵
x
3
=
x
3
1
2
x
4
⟵
x
4
1
3
除了取对数变换之外,还有别的一些方法也可以用,假设有一个不同的特征 x2,现在我们用log(x2+1)来取代 x2 ,或者更一般地,用 log(x2+c),这个常数 c 可以任意调整,使得图形尽可能接近高斯分布;或者对于另一个特征 x3 ,可以用它自身的平方根来取代,x3 的平方根也就是 x3 的 1/2 次方;而这个 1/2 又是另一个可以调整的参数,所以还有 x4 ,可以用其它数字来替换 x4 的指数,比如说 1/3 次幂。所有这些参数(指数参数或是常数参数 c),都是可以调整的参数,目的就是为了让我们的数据看上去更接近高斯分布。
下面我们要介绍的第二个问题是我们如何得到异常检测算法的特征。通常用的办法是,通过一个误差分析步骤,这跟之前讨论监督学习算法时误差分析步骤是类似的,先完整地训练出一个算法,然后在一组交叉验证集上运行算法,然后找出那些预测出错的样本,并看看我们能否找到一些其它的特征来帮助学习算法,让那些在交叉验证集中判断出错的样本表现得更好。
让我们通过一个例子来解释一下刚才说的这一过程:
Error
analysis
for
anomaly
detection
W
a
n
t
p
(
x
)
l
a
r
g
e
f
o
r
n
o
r
m
a
l
e
x
a
m
p
l
e
s
x
.
p
(
x
)
s
m
a
l
l
f
o
r
a
n
o
m
a
l
o
u
s
e
x
a
m
p
l
e
s
x
.
M
o
s
t
c
o
m
m
o
n
p
r
o
b
l
e
m
:
p
(
x
)
i
s
c
o
m
p
a
r
a
b
l
e
(
s
a
y
,
b
o
t
h
l
a
r
g
e
)
f
o
r
n
o
r
m
a
l
a
n
d
a
n
o
m
a
l
o
u
s
e
x
a
m
p
l
e
s
在异常检测中,我们希望 p(x) 的值在正常样本的情况下比较大,在异常样本的情况下比较小。一个很常见的问题是,如果 p(x) 是可比较的,当样本正常和异常时,p(x) 的值都比较大。我们来看一个具体点的例子,假设我们的无标签数据只有一个特征 x1,要用一个高斯分布来拟合它,假设我们的数据拟合出的高斯分布是这样的(下图上):
现在假如我们有一个异常样本,并且假设这个异常样本 x 的取值为 2.5,我们画出异常样本(上图绿色标记),不难发现,它看起来被淹没在一堆正常样本中,它有很高的概率(概率用蓝色曲线的高度表示),而算法没能把它标记为异常样本。如果这代表飞机引擎的制造或者别的什么。那么我们需要做的是看看训练样本,然后看看到底是哪一个具体的飞机引擎出错了,看看通过这个样本能不能启发想出一个新的特征 x2,来帮助算法找出异常的样本与剩下的红色(正常)的样本的区别,或者说正常的飞机引擎样本。
如果我们这样做的话,我们希望的是,能否创建一个新的特征 x2,使得当我们重新画数据时,如果我们把训练集中的所有正常样本拿出来,应该就会发现,所有的训练样本都是这里(上图下)的红叉了,也希望能看到,对于异常样本,这个特征 x2 能发现不寻常的值,因此对于这个绿色的样本,也就是异常样本 x1 的值仍然是 2.5,那么 x2 很有可能是一个比较大的值,比如 3.5,或者一个非常小的值。
现在如果我们再来给数据建模,我们会发现异常检测算法在中间区域的数据有较高的概率,然后越到外层概率越小,到了绿色样本处时,我们的算法会给出很低的概率,所以过程实际就是看看哪里出了错,看看这个算法没有标记出来的异常样本,看看它是否能够启发我们创造一些新特征,所以要找到飞机引擎一些不寻常的地方,并利用它来创造一个新特征,有了这些新的特征,就更容易的将异常样本从正常样本中区别出来,这就是误差分析的过程以及如何为异常检测算法建立新的特征。
首先我们来看一个例子:
假设我们有上图这些没有标签的数据,我们要使用数据中心的监控计算机的例子;两个特征变量分别是 x1 是 CPU 的负载, x2 可能是内存使用量,所以如果我们把这两个特征变量 x1 和 x2 当做高斯分布来建模,上图右上是特征变量 x1 绘制的图,上图右下是特征变量 x2 的图,如果我们用高斯分布来拟合,得到如下的两个对应分布:
p
(
x
1
;
μ
1
,
σ
1
2
)
p
(
x
2
;
μ
2
,
σ
2
2
)
异常检测算法给 x1 和 x2 建模以后,现在假设在测试集中,有一个这样的样本,在图中绿色叉的位置,它的 x1 的值是 0.4 左右, x2 的值是 1.5 左右,现在观察这些数据,看起来它们大部分都在这个范围内(上图左蓝色圈出范围内),所以这个绿色叉离这里看到的任何数据都很远,看起来它应该被当做一个异常数据。在好的样本数据中,看起来 CPU 负载和内存使用量是彼此线性增长的关系,所以如果我们有一台机器 CPU 使用量很高,那么内存使用量也会很高,但是这个绿色样本看起来 CPU 负载很低,但是内存使用量很高,与训练集中的其它样本都不同,看起来它应该是异常的。
我们来看一下异常检测算法会怎么做。对于 CPU 负载,这个绿色叉差不多在 0.5 这里,有比较高的可能性它距离其它样本不远,而对于内存使用量,它差不多在 1.5 处,它在这个高斯分布的尾部(上图右下),但是这里的值与看到的其它样本没有太大差别,所以 p(x1) 会比较高,p(x2) 也会比较高。但是在上图右上中这个绿叉看起来并没那么差,右下方图中这个绿叉的位置看起来也不那么差。因为有的样本,内存使用量比绿叉对应的样本更高,或者 CPU 使用量更低,所以这个点看起来不是很异常,因此异常检测算法不会将这个点标记为异常。
可以发现,异常检测算法不能意识到之上图左中蓝色椭圆所表示的好样本概率高的范围,相反,它认为这部分样本(粉色最小圆范围)是高概率的,外面一些的圈里面的样本是好样本的概率低一些,更外的样本概率更低,它认为那里的绿色叉是好样本的概率挺高,具体来说,它倾向于认为所有在这区域(中等粉圈)中的样本都具有相同的概率,它并不能意识到下边紫色叉位置的其实比上边紫色叉位置的概率要低得多。
为了解决这个问题,我们要开发一种改良版的异常检测算法,要用到多元高斯分布或者叫多元正态分布,下面是具体做法:
Multivariate
Gaussian
(Normal)
distribution
x
∈
R
n
.
D
o
n
’
t
m
o
d
e
l
p
(
x
1
)
,
p
(
x
2
)
,
.
.
.
,
e
t
c
.
s
e
p
a
r
a
t
e
l
y
.
M
o
d
e
l
p
(
x
)
a
l
l
i
n
o
n
e
g
o
.
P
a
r
a
m
e
t
e
r
s
:
μ
∈
R
n
,
Σ
∈
R
n
×
n
(
c
o
v
a
r
i
a
n
c
e
m
a
t
r
i
x
)
我们有特征变量 x,它属于 Rn,不要为 p(x1)和p(x2)分别建模,而是要建立一个整体的 p(x) 模型,就是为所有 p(x) 建立统一的模型。多元高斯分布的参数是向量 μ 和一个 n×n 的矩阵 Σ,Σ 被称为协方差矩阵,它类似于我们之前在学习 PCA(主成分分析算法)的时候所见到的协方差矩阵。为了完整起见,下面写出多元高斯分布的公式,确定 x 的概率的参数是 μ 和 Σ:
p
(
x
;
μ
,
Σ
)
=
1
(
2
π
)
n
2
∣
Σ
∣
1
2
e
x
p
(
−
1
2
(
x
−
μ
)
⊤
Σ
−
1
(
x
−
μ
)
)
|Σ| 是 Σ 的行列式,我们可以在 Octave 中使用 det(Σ) 来计算它,在上面的式子中,Σ 是一个 n×n 的矩阵,而不是求和符号。
Σ
:
S
i
g
m
a
∑
:
s
u
m
上面这些就是这就是 p(x) 的公式,但是对我们来说,更有趣、更重要的是,p(x) 到底是什么样子,我们来看一下多元高斯分布的例子。
我们来看一个二维的例子:
如果 n 等于 2,有两个特征变量 x1 和 x2,我们让 μ 等于 0,让 Σ 等于上图左对应的单位矩阵(对角线上的值为 1,费对角线上的值为 0),在这个情况下,p(x) 看起来是如上图左所示那样的。对于一个特定的 x1 和一个特定的 x2,三维图形中对应的高度就是 p(x) 的值,所以在这个参数设定下,p(x) 在 x1 和 x2 都等于 0 时,取到最高值,那就是高斯分布的峰值,然后这个概率,这个二元高斯分布随着这个二维钟形的面衰减,下面的平面图和三维图是一样的,但它是用等高线,或者说不同颜色画的图,所以中间很深的暗红色对应的是最高值,然后这个值降低,黄色表示低一点儿的值,青色表示更低一些的值,深蓝色表示的是最低的值,所以这个其实是同一张图,不过使用了俯视的角度,并且用颜色来区别。所以从这个分布我们可以看出,大部分概率都在 (0,0) 附近,然后,随着 (0,0) 这个点往外延伸, x1 和 x2 的概率下降。
现在来试试改变一些参数,会发生什么,假设我们缩小一下 Σ,Σ 是一个协方差矩阵,所以它衡量的是方差,或者说特征变量 x1 和 x2 的变化量,所以如果缩小 Σ,那么结果就是,这个鼓包的宽度会减小,高度会增加一些,因为在这个面以下的区域等于 1,所以这个面以下的体积积分等于 1,因为概率分布的积分必须等于 1。如果我们缩小方差,相当于缩小 Σ 的平方,会得到一个窄一些,高一些的分布。从平面图(上图中)中我们也看到,这些同心椭圆也缩小了一些。
相反,如果把 Σ 对角线上的值增加到 2,那么最后会得到一个更宽更扁的高斯分布(上图右),虽然很难看出来,但是它还是一个钟形的鼓包,它只是扁平了很多,他变得更宽了,所以 x1 和 x2 的方差或者变化量变大了。
下面再举几个例子(上图),现在我们试一下一次改变 Σ 的一个元素,假如我们把 Σ 改为 0.6 和 1(上图中),它所做事情是减小第一个特征变量 x1 的方差,同时保持第二个特征变量 x2 的方差不变,在这个参数设置下,就可以给这样的东西建模, x1 有小一些的方差,而 x2 有大一些的方差,而如果再换一种做法,把 Σ 矩阵设为 2 和 1(上图右),那么我们也可以建立这样的模型, x1 的变化范围比较大,而 x2 的变化范围则窄一些,它也被反映到上面的图上了,这个分布随着 x1 远离 0,下降得更缓慢,而随着 x2 远离 0,下降得非常快。
类似地,如果我们改变 Σ 矩阵对角线上别的元素,类似于上一张图片,我们可以得到线面这张图:
我们可以发现现在 x2 的变化区间比原来的例子要小很多(上图中),通过将 Σ 矩阵对角线上相应的元素改成 2,我们就可以得到 比较大的 x2 的变化区间(上图右)。
多元高斯分布的一个很棒的事情是,你可以用它给数据的相关性建立模型,我们可以用它来给 x1 和 x2 高度相关的情况建立模型,所以具体来说,如果我们改变协方差矩阵非对角线上的元素,我们会得到一种不同的高斯分布(上图中),所以当我们将非对角线的元素从 0.5 增加到 0.8 时,我们会得到一个更加窄和高的,沿着 x = y 这条线的分布,然后这个等高图告诉我们 x 和 y 看起来是一起增加的,概率高的地方是这样的,要么 x1 很大 x2 也很大,或者 x1 很小 x2 也很小,或者是这两者之间,然后随着这个值 0.8 变大,得到的高斯分布概率分布落在这个狭窄的区域(x 接近于 y),这在 x 接近 y 的区间内是一个很高很细的分布,几乎都在中间(上图右)。
这是当我们把这些元素设置为正值时。相反,如果我们把它们设置为负值,然后把这个值减少到 -0.5 或者减少到 -0.8,然后得到的模型是大部分的概率都在 x1 和 x2 负相关这样一个区域(上图中)。所以大多数概率都落在 x1=-x2 附近的区域(而不是 x1=x2),因此这个捕捉到了 x1 和 x2 的负相关。
上面的讲解主要说明了多元高斯分布能捕捉到的不同的分布,到目前为止我们一直在改变协方差矩阵,另外我们还可以改变平均参数 μ,一开始我们有 μ 中的元素全为 0,所以分布集中在 x1 = 0,x2 = 0 这个点周围,所以这个分布的峰值在图像的中心处(上图左);如果改变μ的值,它就会改变这个分布的峰值,如果 μ 等于 0、 0.5,这个峰值就在 x1 = 0,x2 = 0.5,峰值的位置就发生了改变(上图中),如果再次改变 μ ,那么峰值就会移动到另一个位置(上图右),所以改变参数 μ 的值,就是在移动整个分布的中心。
多元高斯分布所能描述的概率分布最重要的优势就是能够让我们描述两个特征变量之间可能存在正相关或者是负相关的情况。
下一节我们将把多元高斯分布函数应用到异常检测中。
首先回顾一下多元高斯(正态)分布:
Parameters
μ
,
Σ
p
(
x
;
μ
,
Σ
)
=
1
(
2
π
)
n
2
∣
Σ
∣
1
2
e
x
p
(
−
1
2
(
x
−
μ
)
T
Σ
−
1
(
x
−
μ
)
)
有两个参数 μ 和 Σ,其中 μ 是 n 维变量,而 Σ 是个 n×n 的协方差矩阵,而这里的公式 p(x) 参数为 μ 和 Σ ,我们可以通过改变 μ 和 Σ 来得到范围内一个不同的分布,这里的三个样本在上一节学习过学习过。
Anomaly
detection
with
the
multivariate
Gaussian
1.
F
i
t
m
o
d
e
l
p
(
x
)
b
y
s
e
t
t
i
n
g
μ
=
1
m
∑
i
=
1
m
x
(
i
)
Σ
=
1
m
∑
i
=
1
m
(
x
(
i
)
−
μ
)
(
x
(
i
)
−
μ
)
T
首先用我们的数据集来拟合该模型,通过设定 μ 和 Σ 来拟合 p(x)。
接下来当我们有一个新样本 x,即一个测试样本,假设这里是我们的新样本(下图绿色叉),同时也是测试样本:
得到这个样本 x 后,我们需要用这个多元高斯分布的公式来计算 p(x),如果得到 p(x) 很小(即 p(x) < ε),就标记该样本为异常,如果 p(x) 大于参数 ε,就不进行异常标记。
2.
G
i
v
e
n
a
n
e
w
e
x
a
m
p
l
e
x
,
c
o
m
p
u
t
e
p
(
x
)
=
1
(
2
π
)
n
2
∣
Σ
∣
1
2
e
x
p
(
−
1
2
(
x
−
μ
)
T
Σ
−
1
(
x
−
μ
)
)
F
l
a
g
a
n
a
n
o
m
a
l
y
i
f
p
(
x
)
<
ε
如果我们将多元高斯分布拟合到数据集中,也就是这些红色的叉中,而不包括绿色的叉,会得到一个高斯分布,该分布在数据中央的区域,有很大的概率值,每往外一些概率就减少一些,到了最外层一圈,它对应的概率已经很低了,如果我们将多元高斯分布应用到这个样本上,它就能正确标记出这个样本(绿色叉)确实是一个异常。
最后,有必要再说几句,多元高斯分布模型和原始模型有着怎样的关系呢?
Original
model
:
p
(
x
)
=
p
(
x
1
;
μ
1
,
σ
1
2
)
×
p
(
x
2
;
μ
2
,
σ
2
2
)
×
⋅
⋅
⋅
×
p
(
x
n
;
μ
n
,
σ
n
2
)
原始模型就是 p(x1) p(x2) 到 p(xn) 的乘积。事实上我们可以用数学方法来推倒多元高斯模型和这个原始模型之间的区别,特别是,原始模型对比多元高斯模型,多元高斯模型的等高线总是轴对齐的,事实上下面 3 个服从高斯分布的样本我们都可以用原始模型来拟合。
实际上,对于多元高斯分布,这些椭圆的分布轮廓(等高线),这种模型实际上对应一种特殊情况下的多元高斯分布。这种特殊情况是通过限制 p(x) 的分布,即 p(x) 的多元高斯分布来定义的,所以这个轮廓由这个概率分布方程得到的椭圆是轴对齐的,所以能得到 p(x)。注意到,在这3个例子中,这些椭圆形它们的轴都是与 x1 和 x2 轴对齐的,而不是前面那种矩阵非对角线有非零元素、图像的轴有倾斜的情况。
实际上,可以用数学来证明,上面这个模型(原始模型)实际上就是某种特殊情况下的多元高斯分布:
Corresponds
to
multivariate
Gaussian
:
p
(
x
;
μ
,
Σ
)
=
1
(
2
π
)
n
2
∣
Σ
∣
1
2
e
x
p
(
−
1
2
(
x
−
μ
)
T
Σ
−
1
(
x
−
μ
)
)
w
h
e
r
e
Σ
=
[
σ
1
2
0
0
0
0
σ
2
2
0
0
0
0
.
.
.
0
0
0
0
σ
n
2
]
这个情形就是当它的协方差矩阵 Σ 在非对角线上都是 0 的时候(如上面矩阵所示),如果把原始模型中的 σ2 放进上面的协方差矩阵中,这时这两个模型就会完全相同,也就是说如果这个用了多元高斯分布的新模型比起之前旧的模型,如果它的协方差矩阵 Σ 在非主对角线都是 0,那么这个新的对应高斯分布的模型,它的分布方程的轮廓(平面图中的等高线)就是轴对齐的,所以我们不能对不同特征之间的关系进行建模,这个意义上的原始模型只是高斯模型的一种特殊情况。
|
|
---|---|
①Manually create features to capture anomalies where x1,x2 take unusual combinations of values. | ②Automatically captures correlations between features |
③Computationally cheaper ( alternatively, scales beger to large n ). | ④Computationally more expensive |
⑤OK even if m (training set size) is small | ⑥Must have m>n, or else Σ is non-invertible. |
那么如何在两个模型间进行选择呢?什么时候应该用原始模型,什么时候又该用多元高斯模型呢?其实原始模型被使用得更频繁一些,反之多元高斯模型用的要少一些,但是它在捕捉特征间的关系方面有着很多优点。
假设我们进行异常检测,有一些不同的特征 x1,x2 等,我们想通过异常的组合值来捕捉异常样本。比如,在之前的例子中,我们有这样的样本,它出现异常通常是在 CPU 负载以及内存使用有着异常的组合值的时候。①如果我们用原始模型来捕捉这一点,我们就需要创建一个额外的特征,比如令新特征 x3 = x1/x2,它可能等于 CPU 负载除以内存使用,或者别的东西,我们需要创建这样的新特征来捕捉异常的组合值,因为 x1 和 x2 组合值出现异常的时候,可能 x1 本身和 x2 本身看起来都是很正常的值。如果我们花费时间来手动创建这样一个新特征,原始模型就能运行得很好,②相比之下,多元高斯模型就能自动地捕捉这种不同特征之间的关系。
③不过原始模型也有它自己优点,原始模型的一个巨大优势就是它的计算成本比较低,换一种说法就是它能适应巨大规模的 n,即适应数量巨大的特征,当 n = 10000,甚至 n = 100000 的时候,原始模型都能运行得很好。④而对于多元高斯模型,需要计算 Σ 矩阵的逆矩阵,而 Σ 是一个 n×n 矩阵,如果它计算的 Σ 是个 100000×100000 的矩阵,那么计算成本将会非常高昂,所以多元高斯模型能适应的 n 值的范围比较小。
⑤最后,对于原始模型,即使我们有一个较小的有一定相关性的训练集也能顺利运行,这是一个较小的无标签样本,用来拟合模型 p(x),即使 n 的值只有 50、100 这样,它也能工作得很好,⑥而对于多元高斯分布,这个算法有一些数学性质,也就是必须保证 m>n,也就是样本的数量要大于特征的数量。如果在估计参数时,我们不能满足这个数学性质(即如果 m ≤ n),那么这个矩阵 Σ 就会是不可逆的(或者说是个奇异矩阵),我们无法使用多元高斯模型,除非我们对它进行修改。
在这个方面我们有一个原则,就是我们会使用多元高斯模型,当且仅当 m 远大于 n 时,这算是一种狭义的数学要求。在实践中,我们会用多元高斯模型,仅当 m 远大于 n 的时候,所以如果m ≥ 10n,那么这时候我们就可以用多元高斯分布了,如果不能满足这一点,那么多元高斯模型就会有很多参数,因为这个协方差矩阵 Σ 是个 n×n 的矩阵,所以它大概会有 n 的平方个参数,因为它是个对称矩阵,实际上参数的数量更接近于 n 的平方除以 2,但这还是很多,所以要确保我们有一个相当大的 m 值,确保我们有足够的数据来拟合这些变量,所以 m ≥ 10n 算是一个合理的使用原则来确保它能够很好地去估计协方差矩阵 Σ 。
因此在实践中,原始模型会用的多一些,如果我们觉得需要捕捉具有相关性的特征,这时人们常常做的是手动设计一些像上面提到的 x3 这样的新特征来捕捉那些异常的组合值,但是当我们有一个很大的训练集或说 m 很大而 n 不是很大的时候,这时多元高斯模型会更值得考虑,有更好的效果,可以节省我们在手动创建这些额外变量所花费的时间去捕捉这些能用异常的组合值来体现的异常样本。
最后想简明地再提一下,一个技术上的问题,如果我们在拟合多元高斯模型的时候,发现协方差矩阵 Σ 是奇异的(不可逆),那么通常是两种情况,一种是我们没有满足 m > n 的条件,第二种是我们存在冗余的特征(也就是存在两个变量线性相关),虽然不可逆的情况很少发生,但是万一我们实现一个多元高斯模型时,我们发现 Σ 不可逆,这时首先确保 m 远大于 n,其次检查一下有没有冗余特征,如果有两个重复特征,那么就去掉一个。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。