目录
EX8 异常检测与推荐系统的练习 1.异常检测-Anomaly detection2.推荐系统 在本练习中,首先将异常检测算法应用于检测网络中的故障服务器。 在第二部分中,将使用协作过滤来构建电影推荐系统。
在本节练习中,将实施异常检测算法来检测服务器计算机中的异常行为。该功能测量每个服务器的响应的吞吐量-throughput(mb / s)和延迟-latency(ms)。当服务器正在运行时,共收集了m = 307个例子,说明它们的行为方式,因此有一个未标记的数据集{\(x^{(1)},...,x^{(m)}\)}。这里绝大多数是正常运行的(非异常)示例,但也可能存在一些在此数据集中异常运行的服务器示例。
我们将使用高斯模型来检测数据集中的异常示例。首先从2D数据集开始,因为它可以更方便地可视化算法正在做什么。在该数据集上,高斯分布的模型是适合的,然后找到具有非常低概率的值,从而可以将其视为异常。之后,我们会将异常检测算法应用于具有许多维度的较大数据集。
首先,可视化数据集如下:
为了实行异常检测,我们首先需要拟合适合数据集分布的模型,给定训练集{\(x^{(1)},...,x^{(m)}\)}(其中\(x^{(i)}\in \mathbb{R}^n\)),要估计每个特征x_i的高斯分布。 对于每个特征i = 1,...,n,需要找到拟合第i维数据的参数\(\mu_i\)和\(\sigma_i^2\)。高斯分布公式如下:(其中\(\mu\)为均值,\(\sigma^2\)表示方差)
我们可以使用下面的式子来估计参数(\(\mu_i,\sigma_i^2\)),如为了估计均值有:\(\mu_i=\frac{1}{m}\Sigma_{j=1}^mx_i^{(j)}\),为了估计方差有:\(\sigma_i^2=\frac{1}{m}\Sigma_{j=1}^m(x_i^{(j)}-\mu_i)^2\)。
完成estimateGaussian.m的代码,该函数将数据矩阵X作为输入,并输出保持所有n个特征的平均值的n维向量mu,以及保存所有特征的方差的n维向量sigma2。代码如下:
% Useful variables [m, n] = size(X); % You should return these values correctly mu = zeros(n, 1); sigma2 = zeros(n, 1); % ====================== YOUR CODE HERE ====================== % Instructions: Compute the mean of the data and the variances % In particular, mu(i) should contain the mean of % the data for the i-th feature and sigma2(i) % should contain variance of the i-th feature. % for i=1:n mu(i)=1/m*sum(X(:,i)); end for i=1:n for j=1:m sigma2(i) = sigma2(i)+(X(j,i)-mu(i))^2; end sigma2(i) = sigma2(i)/m; end 运行后如下图,可以看出,大部分的例子都是在最高概率的地区,而异常的例子是在概率较低的地区。
现在已经估计了高斯参数,可以调查哪些示例在给定此分布的情况下具有非常高的概率,哪些示例的概率非常低,低概率的例子更有可能是我们数据集中的异常现象。 确定哪些示例是异常的一种方法是基于交叉验证集来选择阈值。 在这部分练习中,将使用交叉验证集上的F1分数来实施一个算法以选择阈值。
完成代码selectThreshold.m。我们将使用交叉验证集{\((x_{cv}^{(1)},y_{cv}^{(1)}),..,(x_{cv}^{(m_{cv})},y_{cv}^{(m_{cv})})\)},其中标签y = 1对应于异常示例,并且y = 0对应于正常示例。 对于每个交叉验证示例,我们将计算\(p(x_{cv}^{(i)})\)。 所有这些概率\(p(x_{cv}^{(1)}),p(x_{cv}^{(2)}),...,p(x_{cv}^{(m_{cv})})\)以向量的形式被传递给向量pval中, 相应的标签\(y_{cv}^{(1)},y_{cv}^{(2)},...,y_{cv}^{(m_{cv})}\)被传递给向量yval中。
函数selectThreshold.m应该返回两个值; 第一个是所选择的阈值$\varepsilon $ ,如果一个例子x具有低概率$P(x)<\varepsilon $,则被认为是异常。 第二个应该返回F1分数,在给定一定的阈值时,通过计算当前阈值正确和不正确地分类样本以计算得到的F1分数,它说明在寻找异常方面做得效果如何。
F_1的计算用到了预测(prec)和召回(rec),具体公式为:\(F_1=\frac{2prec*rec}{prec+rec}\),对预测和召回值得计算按照:\(prec = \frac{tp}{tp+fp}\)和\(rec = \frac{tp}{tp+fn}\) 。
tp是真阳的数量(true positive):标签说这是一个异常同时我们的算法将其也正确地分类为异常。
fp是假阳-误报的数量(false positive):标签说这不是一个异常,但我们的算法将其分类为异常。
fn是假阴-漏报的数量(false negative):标签说是一个异常,而我们的算法将其分类为正常。
关于fn和fp的理解
函数selectThreshold.m代码如下:
bestEpsilon = 0; bestF1 = 0; F1 = 0; stepsize = (max(pval) - min(pval)) / 1000; for epsilon = min(pval):stepsize:max(pval) % ====================== YOUR CODE HERE ====================== % Instructions: Compute the F1 score of choosing epsilon as the % threshold and place the value in F1. The code at the % end of the loop will compare the F1 score for this % choice of epsilon and set it to be the best epsilon if % it is better than the current choice of epsilon. % % Note: You can use predictions = (pval < epsilon) to get a binary vector % of 0's and 1's of the outlier predictions cvPredictions = (pval < epsilon); tp = sum((cvPredictions == 1) & (yval == 1)); fp = sum((cvPredictions == 1) & (yval == 0)); fn = sum((cvPredictions == 0) & (yval == 1)); prec = tp/(tp+fp); rec = tp/(tp+fn); F1 = (2*prec*rec)/(prec+rec); % ============================================================= if F1 > bestF1 bestF1 = F1; bestEpsilon = epsilon; end end 运行后,最佳的epsilon值为8.99e-05,最大的F1值为0.875,选定最佳epsilon后识别异常过的图形如下:
这里其实还需要补充一点,对于主程序中有以下代码段: % 通过数据集估计参数 [mu sigma2] = estimateGaussian(X); % 训练训练集模型 p = multivariateGaussian(X, mu, sigma2); % 训练交叉验证集模型(用来选择最终的epsilon) pval = multivariateGaussian(Xval, mu, sigma2); % Find the best threshold [epsilon F1] = selectThreshold(yval, pval); 其中multivariateGaussian函数的定义如下:
function p = multivariateGaussian(X, mu, Sigma2) n = length(mu); %Sigma2若为列向量或行向量时,将其变换为对角阵 if (size(Sigma2, 2) == 1) || (size(Sigma2, 1) == 1) Sigma2 = diag(Sigma2); end X = bsxfun(@minus, X, mu(:)');% X := X-mu p = (2 * pi) ^ (- n / 2) * det(Sigma2) ^ (-0.5) * ... exp(-0.5 * sum(bsxfun(@times, X * pinv(Sigma2), X), 2));