Week9 异常检测与推荐系统
基于吴恩达《机器学习》课程
参考黄海广的笔记
本篇博客为第九周的内容。
异常检测(Anomaly detection)是机器学习算法的一个常见应用。虽然它主要用于无监督学习问题,但又类似于一些监督学习问题。
给定无标签数据集 x ( 1 ) , x ( 2 ) , . . , x ( m ) x^{(1)},x^{(2)},..,x^{(m)} x(1),x(2),..,x(m)(如下图红点),我们假使数据集是正常的,我们希望知道新的数据 x t e s t x_{test} xtest (如绿点)是不是异常的,即这个测试数据不属于该组数据的几率如何。我们所构建的模型应该能根据该测试数据的位置告诉我们其属于这组数据的可能性 p ( x ) p(x) p(x)。
上图中,在蓝色圈内的数据属于该组数据的可能性较高,而越是偏远的数据,其属于该组数据的可能性就越低。这种方法称为密度估计。
i f p ( x ) { < ε a n o m a l y > = ε n o r m a l if \quad p(x) \begin{cases} <\varepsilon & anomaly \\>=\varepsilon & normal \end{cases} ifp(x){<ε>=εanomalynormal
异常检测主要用来进行欺诈检测。用用户操作时的特征建立模型,通过 p ( x ) < ε p(x) < \varepsilon p(x)<ε检测非正常用户。
也可以用于数据中心检测服务器是否出现异常。
如果变量 x x x 符合高斯分布 x ∼ N ( μ , σ 2 ) x \sim N(\mu, \sigma^2) x∼N(μ,σ2)则其概率密度函数为:
p ( x , μ , σ 2 ) = 1 2 π σ e ( − ( x − μ ) 2 2 σ 2 ) p(x,\mu,\sigma^2)=\frac{1}{\sqrt{2\pi}\sigma}e^{\left(-\frac{(x-\mu)^2}{2\sigma^2}\right)} p(x,μ,σ2)=2πσ1e(−2σ2(x−μ)2)
平均值 μ μ μ决定对称轴的位置,方差 σ 2 σ^2 σ2决定宽度,计算方法如下:
μ = 1 m ∑ i = 1 m x ( i ) \mu=\frac{1}{m}\sum\limits_{i=1}^{m}x^{(i)} μ=m1i=1∑mx(i)
σ 2 = 1 m ∑ i = 1 m ( x ( i ) − μ ) 2 \sigma^2=\frac{1}{m}\sum\limits_{i=1}^{m}(x^{(i)}-\mu)^2 σ2=m1i=1∑m(x(i)−μ)2
注:机器学习中对于方差我们通常只除以 m m m而非统计学中的 ( m − 1 ) (m-1) (m−1),在机器学习实际使用中这两种区别很小。
1、选择特征得到 m m m个数据 x ( 1 ) , x ( 2 ) , . . . , x ( m ) x^{(1)},x^{(2)},...,x^{(m)} x(1),x(2),...,x(m),对每一个特征计算 μ \mu μ 和 σ 2 \sigma^2 σ2 的值。
μ j = 1 m ∑ i = 1 m x j ( i ) \mu_j=\frac{1}{m}\sum\limits_{i=1}^{m}x_j^{(i)} μj=m1i=1∑mxj(i)
σ j 2 = 1 m ∑ i = 1 m ( x j ( i ) − μ j ) 2 \sigma_j^2=\frac{1}{m}\sum\limits_{i=1}^m(x_j^{(i)}-\mu_j)^2 σj2=m1i=1∑m(xj(i)−μj)2
若使用向量化的方法,则: μ = [ μ 1 . . . μ m ] = 1 m ∑ i = 1 m x ( i ) {\mu}=\begin{bmatrix} {\mu_{1}} \\...\\{\mu_{m}} \end{bmatrix}=\frac{1}{m}\sum\limits_{i=1}^{m}x^{(i)} μ=⎣⎡μ1...μm⎦⎤=m1i=1∑mx(i)
2、对于一个新的训练实例,根据模型计算 p ( x ) p(x) p(x),即各个维度的 p ( x , μ , σ 2 ) p(x,\mu,\sigma^2) p(x,μ,σ2)相乘:
p ( x ) = ∏ j = 1 n p ( x j ; μ j , σ j 2 ) = ∏ j = 1 1 1 2 π σ j e ( − ( x j − μ j ) 2 2 σ j 2 ) p(x)=\prod\limits_{j=1}^np(x_j;\mu_j,\sigma_j^2)=\prod\limits_{j=1}^1\frac{1}{\sqrt{2\pi}\sigma_j}e^{(-\frac{(x_j-\mu_j)^2}{2\sigma_j^2})} p(x)=j=1∏np(xj;μj,σj2)=j=1∏12πσj1e(−2σj2(xj−μj)2)
3、选择一个 ε \varepsilon ε,将 p ( x ) = ε p(x) = \varepsilon p(x)=ε作为我们的判定边界,当 p ( x ) > ε p(x) > \varepsilon p(x)>ε时预测数据为正常数据,否则为异常。
异常检测是无监督学习算法,无法根据真实标签 y y y的值来判断是否异常。
为了评估这个算法,需要一些带标签的的数据,选择一部分正常数据用于构建训练集,然后用剩下的正常异常混合的数据构成交叉检验集和测试集(一般按照 6 : 2 : 2 6:2:2 6:2:2比例)。具体过程如下:
根据测试集数据,我们估计特征的平均值和方差并构建 p ( x ) p(x) p(x)函数
对交叉检验集,我们尝试使用不同的 ε \varepsilon ε值作为阀值,并预测数据是否异常,根据 F 1 F1 F1值或者查准率与查全率的比例来选择 ε \varepsilon ε。
选出 ε \varepsilon ε后,针对测试集进行预测,计算异常检验系统的 F 1 F1 F1值,或者查准率与查全率之比。
这里使用带标签数据与监督学习有些相似,下面的对比有助于选择采用监督学习还是异常检测:
异常检测 | 监督学习 |
---|---|
非常少量的正向类(异常数据 y = 1 y=1 y=1), 大量的负向类( y = 0 y=0 y=0) | 同时有大量的正向类和负向类。 |
异常种类很多且复杂,需要根据非常少量的异常数据来训练算法。 | 有足够多的正向类用于训练算法。 |
未来遇到的异常可能与已掌握的异常非常不同。 | 未来遇到的正向类实例与训练集中的非常近似。 |
例如: 欺诈行为检测、生产(例如飞机引擎)、检测数据中心的计算机运行状况。 | 例如:邮件过滤器 天气预报 肿瘤分类 |
异常检测一般需要特征符合高斯分布,如果数据的分布不是高斯分布,异常检测算法也能工作,但是最好还是将数据转换成高斯分布。
例如使用对数函数: x = l o g ( x + c ) x= log(x+c) x=log(x+c),其中 c c c 为非负常数; 或者 x = x c x=x^c x=xc, c c c为 0-1 之间的一个分数,等方法。
(在python中,通常用np.log1p()
函数, l o g 1 p log1p log1p就是 l o g ( x + 1 ) log(x+1) log(x+1),可以避免出现负数结果,反向函数就是np.expm1()
)
一些异常的数据可能也会有较高的 p ( x ) p(x) p(x),因而被算法判定是正常的。这时可以分析那些被误判数据,找出一些问题。我们可能能从问题中发现我们需要增加一些新的特征。
通常可以将一些相关的特征组合,来获得一些新的更好的特征(异常数据的该特征值异常地大或小),例如,在检测数据中心的计算机状况的例子中,我们可以用CPU负载与网络通信量的比作为一个新的特征,如果该值异常地大,便有可能意味着该服务器陷入死循环。
或者也可以使用多元高斯分布。
在一般的高斯分布模型中,我们计算 p ( x ) p(x) p(x) 的方法是: 通过分别计算每个特征维度的几率然后将其累乘起来。对于多个相关的特征,这可能不能很好地识别异常数据。
下图中洋红色的线(根据ε的不同其范围可大可小)是一般的高斯分布模型获得的判定边界,很明显绿色的X所代表的数据点很可能是异常值,但是其 p ( x ) p(x) p(x)值却仍然在正常范围内。
在多元高斯分布模型中,我们将构建特征的协方差矩阵,用所有的特征一起来计算 p ( x ) p(x) p(x)。多元高斯分布将创建像图中蓝色曲线所示的判定边界。
我们首先计算所有特征的平均值,然后再计算协方差矩阵:
μ = 1 m ∑ i = 1 m x ( i ) \mu=\frac{1}{m}\sum_{i=1}^mx^{(i)} μ=m1∑i=1mx(i)
Σ = 1 m ∑ i = 1 m ( x ( i ) − μ ) ( x ( i ) − μ ) T = 1 m ( X − μ ) T ( X − μ ) \Sigma = \frac{1}{m}\sum_{i=1}^m(x^{(i)}-\mu)(x^{(i)}-\mu)^T=\frac{1}{m}(X-\mu)^T(X-\mu) Σ=m1∑i=1m(x(i)−μ)(x(i)−μ)T=m1(X−μ)T(X−μ)
其中 μ \mu μ是一个向量,其每一个单元都是原特征矩阵中一行数据的均值。
最后我们计算多元高斯分布的 p ( x ) p\left( x \right) p(x):
p ( x ) = 1 ( 2 π ) n 2 ∣ Σ ∣ 1 2 e ( − 1 2 ( x − μ ) T Σ − 1 ( x − μ ) ) p(x)=\frac{1}{(2\pi)^{\frac{n}{2}}|\Sigma|^{\frac{1}{2}}}e^{\left(-\frac{1}{2}(x-\mu)^T\Sigma^{-1}(x-\mu)\right)} p(x)=(2π)2n∣Σ∣211e(−21(x−μ)TΣ−1(x−μ))
其中:
∣ Σ ∣ |\Sigma| ∣Σ∣是矩阵行列式,在 Octave 中用 det(sigma)
计算
Σ − 1 \Sigma^{-1} Σ−1 是其逆矩阵,
下面我们来看看协方差矩阵 Σ \Sigma Σ是如何影响模型的:
上图是5个不同的模型,从左往右依次分析:
是一个一般的高斯分布模型
通过协方差矩阵,令特征1拥有较小的偏差,同时保持特征2的偏差
通过协方差矩阵,令特征2拥有较大的偏差,同时保持特征1的偏差
通过协方差矩阵,在不改变两个特征的原有偏差的基础上,增加两者之间的正相关性
通过协方差矩阵,在不改变两个特征的原有偏差的基础上,增加两者之间的负相关性
原本的高斯分布模型是多元高斯分布模型的一个子集,即像上图中的第1、2、3,3个例子所示,如果协方差矩阵只在对角线的单位上有非零的值时,即为原本的高斯分布模型了。
原高斯分布模型 | 多元高斯分布模型 |
---|---|
不能捕捉特征之间的相关性,但可以通过将特征组合的方法来解决。 | 自动捕捉特征之间的相关性。 |
计算代价低,能适应大规模的特征。 | 计算代价较高,训练集 m m m较小时适用。 |
训练集 m m m很小时也能使用。 | 必须要有 m > n m>n m>n,不然的话协方差矩阵 Σ \Sigma Σ不可逆的,通常需要 m > 10 n m>10n m>10n。另外特征冗余也会导致协方差矩阵不可逆。 |
原高斯分布模型使用更广泛。一般如果特征之间在某种程度上存在相互关联的情况,我们可以通过构造新新特征的方法来捕捉这些相关性。
如果训练集不是太大,且 m m m远大于 n n n时,我们可以使用多元高斯分布模型。
假使我们是一个电影供应商,我们有 5 部电影和 4 个用户,我们要求用户为电影打分。
前三部电影是爱情片,后两部则是动作片,我们可以看出Alice和Bob似乎更倾向与爱情片, 而 Carol 和 Dave 似乎更倾向与动作片。并且没有一个用户给所有的电影都打过分。我们希望构建一个算法来预测他们每个人可能会给他们没看过的电影打多少分,并以此作为推荐的依据。
引入一些标记:
n u n_u nu 代表用户user的数量
n m n_m nm 代表电影movie的数量
r ( i , j ) r(i, j) r(i,j) 如果用户 j j j 给电影 i i i 评过分则 r ( i , j ) = 1 r(i,j)=1 r(i,j)=1
y ( i , j ) y^{(i, j)} y(i,j) 代表用户 j j j 给电影 i i i的评分
m j m_j mj代表用户 j j j 评过分的电影的总数
θ ( j ) \theta^{(j)} θ(j)表示用户 j j j 的参数向量
x ( i ) x^{(i)} x(i)电影 i i i 的特征向量
在上面的例子中,假设每部电影都有两个特征,如 x 1 x_1 x1代表电影的浪漫程度, x 2 x_2 x2 代表电影的动作程度。则每部电影都有一个特征向量,如 x ( 1 ) x^{(1)} x(1)是第一部电影的特征向量为 [ 0.9 0 ] [0.9 \ \ 0] [0.9 0]。
可以针对每一个用户都训练一个线性回归模型,如 θ ( 1 ) {{\theta }^{(1)}} θ(1)是第一个用户的模型的参数。
对于用户 j j j 和电影 i i i,我们预测评分为: ( θ ( j ) ) T x ( i ) (\theta^{(j)})^T x^{(i)} (θ(j))Tx(i)
针对用户 j j j,该线性回归模型的代价函数加上正则化项为:
min θ ( j ) 1 2 ∑ i : r ( i , j ) = 1 ( ( θ ( j ) ) T x ( i ) − y ( i , j ) ) 2 + λ 2 ( θ k ( j ) ) 2 \min_{\theta (j)}\frac{1}{2}\sum_{i:r(i,j)=1}\left((\theta^{(j)})^Tx^{(i)}-y^{(i,j)}\right)^2+\frac{\lambda}{2}\left(\theta_{k}^{(j)}\right)^2 θ(j)min21i:r(i,j)=1∑((θ(j))Tx(i)−y(i,j))2+2λ(θk(j))2
其中 i : r ( i , j ) i:r(i,j) i:r(i,j)表示我们只计算那些用户 j j j 评过分的电影。
在一般的线性回归模型中,误差项和正则项应该都是乘以 1 / 2 m 1/2m 1/2m,在这里我们将 m m m去掉。并且我们不对 θ 0 \theta_0 θ0进行正则化处理。
为了学习所有用户,我们将所有用户的代价函数求和:
min θ ( 1 ) , . . . , θ ( n u ) 1 2 ∑ j = 1 n u ∑ i : r ( i , j ) = 1 ( ( θ ( j ) ) T x ( i ) − y ( i , j ) ) 2 + λ 2 ∑ j = 1 n u ∑ k = 1 n ( θ k ( j ) ) 2 \min_{\theta^{(1)},...,\theta^{(n_u)}} \frac{1}{2}\sum_{j=1}^{n_u}\sum_{i:r(i,j)=1}\left((\theta^{(j)})^Tx^{(i)}-y^{(i,j)}\right)^2+\frac{\lambda}{2}\sum_{j=1}^{n_u}\sum_{k=1}^{n}(\theta_k^{(j)})^2 θ(1),...,θ(nu)min21j=1∑nui:r(i,j)=1∑((θ(j))Tx(i)−y(i,j))2+2λj=1∑nuk=1∑n(θk(j))2
计算代价函数的偏导数后得到梯度下降的更新公式为:
θ k ( j ) : = θ k ( j ) − α ∑ i : r ( i , j ) = 1 ( ( θ ( j ) ) T x ( i ) − y ( i , j ) ) x k ( i ) ( for k = 0 ) \theta_k^{(j)}:=\theta_k^{(j)}-\alpha\sum_{i:r(i,j)=1}((\theta^{(j)})^Tx^{(i)}-y^{(i,j)})x_{k}^{(i)} \quad (\text{for} \, k = 0) θk(j):=θk(j)−α∑i:r(i,j)=1((θ(j))Tx(i)−y(i,j))xk(i)(fork=0)
θ k ( j ) : = θ k ( j ) − α ( ∑ i : r ( i , j ) = 1 ( ( θ ( j ) ) T x ( i ) − y ( i , j ) ) x k ( i ) + λ θ k ( j ) ) ( for k ≠ 0 ) \theta_k^{(j)}:=\theta_k^{(j)}-\alpha\left(\sum_{i:r(i,j)=1}((\theta^{(j)})^Tx^{(i)}-y^{(i,j)})x_{k}^{(i)}+\lambda\theta_k^{(j)}\right) \quad (\text{for} \, k\neq 0) θk(j):=θk(j)−α(∑i:r(i,j)=1((θ(j))Tx(i)−y(i,j))xk(i)+λθk(j))(fork=0)
得到用户的参数 θ ( j ) \theta^{(j)} θ(j)以后,就可以用 ( θ ( j ) ) T x ( i ) (\theta^{(j)})^T x^{(i)} (θ(j))Tx(i)对其未评分的电影做出评分预测。
这就是基于电影内容特征推测用户喜好,再予以预测和推荐。
对于每一部电影,我们已知了内容的特征,使用这些特征训练出了每一个用户的参数。相反地,如果我们拥有用户的参数,我们可以学习得出电影的特征:
m i n x ( 1 ) , . . . , x ( n m ) 1 2 ∑ i = 1 n m ∑ j r ( i , j ) = 1 ( ( θ ( j ) ) T x ( i ) − y ( i , j ) ) 2 + λ 2 ∑ i = 1 n m ∑ k = 1 n ( x k ( i ) ) 2 \mathop{min}\limits_{x^{(1)},...,x^{(n_m)}}\frac{1}{2}\sum_{i=1}^{n_m}\sum_{j{r(i,j)=1}}((\theta^{(j)})^Tx^{(i)}-y^{(i,j)})^2+\frac{\lambda}{2}\sum_{i=1}^{n_m}\sum_{k=1}^{n}(x_k^{(i)})^2 x(1),...,x(nm)min21i=1∑nmjr(i,j)=1∑((θ(j))Tx(i)−y(i,j))2+2λi=1∑nmk=1∑n(xk(i))2
如果我们既没有用户的参数,也没有电影的特征,那就可以随机初始化特征 x x x,然后学习 θ \theta θ,再学习 x x x…… 到都收敛到代价函数最小,这就是协同过滤。
或者同时学习这两者,将优化目标便改为同时针对 x x x和 θ \theta θ进行。
代价函数 J ( x ( 1 ) , . . . x ( n m ) , θ ( 1 ) , . . . , θ ( n u ) ) = J(x^{(1)},...x^{(n_m)},\theta^{(1)},...,\theta^{(n_u)})= J(x(1),...x(nm),θ(1),...,θ(nu))=
1 2 ∑ ( i : j ) : r ( i , j ) = 1 ( ( θ ( j ) ) T x ( i ) − y ( i , j ) ) 2 + λ 2 ∑ i = 1 n m ∑ k = 1 n ( x k ( j ) ) 2 + λ 2 ∑ j = 1 n u ∑ k = 1 n ( θ k ( j ) ) 2 \frac{1}{2}\sum_{(i:j):r(i,j)=1}((\theta^{(j)})^Tx^{(i)}-y^{(i,j)})^2+\frac{\lambda}{2}\sum_{i=1}^{n_m}\sum_{k=1}^{n}(x_k^{(j)})^2+\frac{\lambda}{2}\sum_{j=1}^{n_u}\sum_{k=1}^{n}(\theta_k^{(j)})^2 21(i:j):r(i,j)=1∑((θ(j))Tx(i)−y(i,j))2+2λi=1∑nmk=1∑n(xk(j))2+2λj=1∑nuk=1∑n(θk(j))2
对代价函数求偏导数后使用梯度下降:
x k ( i ) : = x k ( i ) − α ( ∑ j : r ( i , j ) = 1 ( ( θ ( j ) ) T x ( i ) − y ( i , j ) θ k j + λ x k ( i ) ) x_k^{(i)}:=x_k^{(i)}-\alpha\left(\sum_{j:r(i,j)=1}((\theta^{(j)})^Tx^{(i)}-y^{(i,j)}\theta_k^{j}+\lambda x_k^{(i)}\right) xk(i):=xk(i)−α(∑j:r(i,j)=1((θ(j))Tx(i)−y(i,j)θkj+λxk(i))
θ k ( i ) : = θ k ( i ) − α ( ∑ i : r ( i , j ) = 1 ( ( θ ( j ) ) T x ( i ) − y ( i , j ) x k ( i ) + λ θ k ( j ) ) \theta_k^{(i)}:=\theta_k^{(i)}-\alpha\left(\sum_{i:r(i,j)=1}((\theta^{(j)})^Tx^{(i)}-y^{(i,j)}x_k^{(i)}+\lambda \theta_k^{(j)}\right) θk(i):=θk(i)−α(∑i:r(i,j)=1((θ(j))Tx(i)−y(i,j)xk(i)+λθk(j))
在协同过滤从算法中,我们通常不使用方差项,所以不用考虑两种情况。如果需要的话,算法会自动学得。
协同过滤算法使用步骤如下:
初始 x ( 1 ) , x ( 2 ) , . . . x ( n m ) , θ ( 1 ) , θ ( 2 ) , . . . , θ ( n u ) x^{(1)},x^{(2)},...x^{(n_m)},\ \theta^{(1)},\theta^{(2)},...,\theta^{(n_u)} x(1),x(2),...x(nm), θ(1),θ(2),...,θ(nu)为一些随机小值;
使用梯度下降算法最小化代价函数;
在训练完算法后,我们预测 ( θ ( j ) ) T x ( i ) (\theta^{(j)})^Tx^{(i)} (θ(j))Tx(i)为用户 j j j 给电影 i i i 的评分。
协同过滤学习后获得的特征矩阵 x x x包含了有关电影的重要特征数据,虽然不一定有具体意义,但是可以用这些数据作为给用户推荐电影的依据。
例如,如果一位用户正在观看电影 x ( i ) x^{(i)} x(i),我们可以寻找另一部相似电影 x ( j ) x^{(j)} x(j),依据两部电影的特征向量之间的距离 ∣ x ( i ) − x ( j ) ∣ \left| {{x}^{(i)}}-{{x}^{(j)}} \right| ∣∣x(i)−x(j)∣∣的大小。
我们有五部电影,以及四位用户,将这些电影的用户评分数据都存在矩阵里,那么这个矩阵 Y Y Y 就是一个5行4列的矩阵:
所有电影的特征矩阵 X = [ x ( 1 ) T x ( 2 ) T . . . x ( n m ) T ] X=\begin{bmatrix} {x^{(1)}}^T \\{x^{(2)}}^T \\...\\{x^{(n_m)}}^T \end{bmatrix} X=⎣⎢⎢⎢⎡x(1)Tx(2)T...x(nm)T⎦⎥⎥⎥⎤,用户的参数矩阵 Θ = [ θ ( 1 ) T θ ( 2 ) T . . . θ ( n u ) T ] \Theta=\begin{bmatrix} {\theta^{(1)}}^T \\{\theta^{(2)}}^T \\...\\{\theta^{(n_u)}}^T \end{bmatrix} Θ=⎣⎢⎢⎢⎡θ(1)Tθ(2)T...θ(nu)T⎦⎥⎥⎥⎤
推测评分结果的矩阵为: X Θ T = X \Theta^T= XΘT=
X Θ T X \Theta^T XΘT即为低秩矩阵分解。
当用户在喜欢某部电影 i i i 的时候,为了能给用户推荐新电影,你需要做的是找出电影 j j j,与电影 i i i 的距离 ∣ x ( i ) − x ( j ) ∣ \left| {{x}^{(i)}}-{{x}^{(j)}} \right| ∣∣x(i)−x(j)∣∣最小。
如果我们新增一个用户 Eve,并且 Eve 没有为任何电影评分,那么我们以什么为依据为Eve推荐电影呢?如果直接用 Y Y Y矩阵算,则Eve的参数全为0,预测结果也全为0。
这时候我们首先要对结果 Y Y Y矩阵进行均值归一化处理,将每一个用户对某一部电影的评分减去所有用户对该电影评分的平均值:
然后我们利用这个新的 Y Y Y 矩阵来训练算法。
用新训练出的算法来预测评分时,需要将平均值重新加回去,预测结果为 ( θ ( j ) ) T x ( i ) + μ i (\theta^{(j)})^T x^{(i)}+\mu_i (θ(j))Tx(i)+μi,对于Eve,我们的新模型会认为她给每部电影的评分都是该电影的平均分。
这个步骤作为协同过滤算法的数据预处理,目的是让新用户与老用户的计算方式统一。