【问题标题】:Iregular plot of k-means clustering, outlier removalk-means 聚类的不规则图,异常值去除
【发布时间】:2012-07-07 13:26:45
【问题描述】:

您好,我正在尝试从 1999 年 darpa 数据集中对网络数据进行聚类。不幸的是,我并没有真正使用相同的技术和方法获得聚类数据,而不是与一些文献相比。

我的数据是这样出来的:

如您所见,它不是很集群。这是由于数据集中存在大量异常值(噪声)。我已经查看了一些异常值删除技术,但到目前为止我没有尝试过真正清理数据。我尝试过的方法之一:

%% When an outlier is considered to be more than three standard deviations away from the mean, determine the number of outliers in each column of the count matrix:

    mu = mean(data)
    sigma = std(data)
    [n,p] = size(data);
    % Create a matrix of mean values by replicating the mu vector for n rows
    MeanMat = repmat(mu,n,1);
    % Create a matrix of standard deviation values by replicating the sigma vector for n rows
    SigmaMat = repmat(sigma,n,1);
    % Create a matrix of zeros and ones, where ones indicate the location of outliers
    outliers = abs(data - MeanMat) > 3*SigmaMat;
    % Calculate the number of outliers in each column
    nout = sum(outliers) 
    % To remove an entire row of data containing the outlier
    data(any(outliers,2),:) = [];

在第一次运行中,它从从完整数据集中选择的 1000 个标准化随机行中删除了 48 行。

这是我在数据上使用的完整脚本:

    %% load data
        %# read the list of features
        fid = fopen('kddcup.names','rt');
        C = textscan(fid, '%s %s', 'Delimiter',':', 'HeaderLines',1);
        fclose(fid);

        %# determine type of features
        C{2} = regexprep(C{2}, '.$','');              %# remove "." at the end
        attribNom = [ismember(C{2},'symbolic');true]; %# nominal features

        %# build format string used to read/parse the actual data
        frmt = cell(1,numel(C{1}));
        frmt( ismember(C{2},'continuous') ) = {'%f'}; %# numeric features: read as number
        frmt( ismember(C{2},'symbolic') ) = {'%s'};   %# nominal features: read as string
        frmt = [frmt{:}];
        frmt = [frmt '%s'];                           %# add the class attribute

        %# read dataset
        fid = fopen('kddcup.data_10_percent_corrected','rt');
        C = textscan(fid, frmt, 'Delimiter',',');
        fclose(fid);

        %# convert nominal attributes to numeric
        ind = find(attribNom);
        G = cell(numel(ind),1);
        for i=1:numel(ind)
            [C{ind(i)},G{i}] = grp2idx( C{ind(i)} );
        end

        %# all numeric dataset
        fulldata = cell2mat(C);

%% dimensionality reduction 
columns = 6
[U,S,V]=svds(fulldata,columns);

%% randomly select dataset
rows = 1000;
columns = 6;

%# pick random rows
indX = randperm( size(fulldata,1) );
indX = indX(1:rows)';

%# pick random columns
indY = indY(1:columns);

%# filter data
data = U(indX,indY);

% apply normalization method to every cell
maxData = max(max(data));
minData = min(min(data));
data = ((data-minData)./(maxData));

% output matching data
dataSample = fulldata(indX, :)

%% When an outlier is considered to be more than three standard deviations away from the mean, use the following syntax to determine the number of outliers in each column of the count matrix:

mu = mean(data)
sigma = std(data)
[n,p] = size(data);
% Create a matrix of mean values by replicating the mu vector for n rows
MeanMat = repmat(mu,n,1);
% Create a matrix of standard deviation values by replicating the sigma vector for n rows
SigmaMat = repmat(sigma,n,1);
% Create a matrix of zeros and ones, where ones indicate the location of outliers
outliers = abs(data - MeanMat) > 2.5*SigmaMat;
% Calculate the number of outliers in each column
nout = sum(outliers) 
% To remove an entire row of data containing the outlier
data(any(outliers,2),:) = [];

%% generate sample data
K = 6;
numObservarations = size(data, 1);
dimensions = 3;

%% cluster
opts = statset('MaxIter', 100, 'Display', 'iter');
[clustIDX, clusters, interClustSum, Dist] = kmeans(data, K, 'options',opts, ...
'distance','sqEuclidean', 'EmptyAction','singleton', 'replicates',3);

%% plot data+clusters
figure, hold on
scatter3(data(:,1),data(:,2),data(:,3), 5, clustIDX, 'filled')
scatter3(clusters(:,1),clusters(:,2),clusters(:,3), 100, (1:K)', 'filled')
hold off, xlabel('x'), ylabel('y'), zlabel('z')
grid on
view([90 0]);

%% plot clusters quality
figure
[silh,h] = silhouette(data, clustIDX);
avrgScore = mean(silh);

这是来自输出的两个不同的集群:

如您所见,数据看起来比原始数据更清晰、更集中。但是我仍然认为可以使用更好的方法。

例如观察整体聚类,我仍然有很多来自数据集的噪音(异常值)。可以在这里看到:

我需要将异常行放入单独的数据集中以供以后分类(仅从聚类中删除)

这里是 darpa 数据集的链接,请注意 10% 数据集的列显着减少,大部分有 0 或 1 的列已被删除(42 列到 6 列) :

http://kdd.ics.uci.edu/databases/kddcup99/kddcup99.html

编辑

数据集中保留的列是:

src_bytes: continuous.

dst_bytes: continuous.

count: continuous.

srv_count: continuous.  

dst_host_count: continuous.

dst_host_srv_count: continuous.         

重新编辑:

根据与 Anony-Mousse 的讨论和他的回答,可能有一种方法可以使用 K-Medoids http://en.wikipedia.org/wiki/K-medoids 减少聚类中的噪音。我希望我目前拥有的代码没有太大变化,但到目前为止我还不知道如何实现它来测试这是否会显着降低噪音。因此,只要有人可以向我展示一个工作示例,这将被接受为答案。

【问题讨论】:

  • 您的数据似乎不是很聚集......似乎是一个大斑点,周围有一些点。你期望聚类算法做什么?如果您想将中间值与异常值分开,也许层次聚类会做得更好。
  • 你能提供一个关于这些数据的例子的链接吗?我不熟悉它。
  • @Ran hey 更新了带有数据链接的问题。
  • @JungleBoogie:你自己试过什么?上面的大部分代码只是reusingpreviousanswers。虽然这很好,但您现在基本上要求我们为您实施异常值检测。您所说的问题并未显示您在寻找解决方案时可能付出的努力。不幸的是,发布巨额奖励并不能改变这一事实。
  • @JungleBoogie:您得到的错误是因为您在从数据集中删除行后没有更新numObservarations。 FWIW 不需要整个“将数据分配给集群”部分,我只是在原始帖子中使用它来展示如何计算实例和质心之间的距离。该信息已由 kmeansclustIDX 参数中提供

标签: matlab plot data-mining cluster-analysis k-means


【解决方案1】:

请注意,不鼓励使用此数据集

该数据集有错误:KDD Cup '99 dataset (Network Intrusion) considered harmful

重新考虑使用不同的算法。 k-means 并不真正适合混合类型的数据,其中许多属性是离散的,并且具有非常不同的尺度。 K-means 需要能够计算 sensible 均值。对于二元向量,“0.5”不是一个合理的平均值,它应该是 0 或 1。

另外,k-means 不太喜欢异常值。

绘制时,请确保等比例缩放它们,否则结果会看起来不正确。您的 X 轴长度约为 0.9,而您的 y 轴只有 0.2 - 难怪它们看起来被压扁了。

总的来说,也许数据集没有 k-means 样式的集群?​​您绝对应该尝试基于密度的方法(因为这些可以处理异常值),例如 DBSCAN。但是从你添加的可视化来看,我会说它最多有 4-5 个集群,它们并不是很有趣。它们可能可以在某些维度上通过多个阈值来捕获。

这是 z 归一化后数据集的可视化,以平行坐标可视化,包含 5000 个样本。亮绿色是正常的。

您可以清楚地看到数据集的特殊属性。所有攻击在属性 3 和 4(count 和 srv_count)上明显不同,并且最集中在 dst_host_count 和 dst_host_srv_count。

我也在这个数据集上运行了 OPTICS。它发现了许多集群,其中大多数是酒红色的攻击模式。但它们并不是很有趣。如果你有 10 台不同的主机 ping-flooding,它们将形成 10 个集群。

您可以清楚地看到OPTICS 成功地聚集了许多此类攻击。它错过了所有橙色的东西(也许如果我将 minpts 设置得更低,它会相当分散),但它甚至发现了葡萄酒色攻击中的*结构),将其分解为许多单独的事件。

真正理解这个数据集,您应该从特征提取开始,例如将此类 ping 洪水连接尝试合并到一个聚合事件中。

另请注意,这是一个不现实的场景

  1. 攻击中有一些众所周知的模式,尤其是端口扫描。这些最好用专门的端口扫描检测器检测,而不是通过学习
  2. 模拟数据中有很多完全没有意义的“攻击”模拟。比如90年代的Smurf attack,是>50%的数据集,Syn flood是另外20%;而正常流量是
  3. 对于这类攻击,有众所周知的特征。
  4. 许多现代攻击(例如 SQL 注入)使用通常的 HTTP 流量进行传输,并且不会在原始流量模式中显示异常。

只是不要将此数据用于分类或异常值检测。只是不要。

引用上面的 KDNuggets 链接:

因此,我们强烈建议

(1) 所有研究人员都停止使用 KDD Cup '99 数据集,

(2) KDD Cup 和 UCI 网站在 KDD Cup '99 数据集网页上包含警告,告知研究人员该数据集存在已知问题,并且

(3) 会议和期刊的同行审稿人 ding 论文(甚至直接拒绝它们,这在网络安全社区中很常见),其结果仅来自 KDD Cup '99 数据集。

这既不是真实也不是现实数据。去买点别的吧。

【讨论】:

  • 另外请注意,数据中没有 TTL,也没有攻击的数据属性,导致大多数攻击的数量为 253 或 126。如果你也看看他的参考资料,他们也不能证实他对 darpa 训练集的攻击。
  • 实际上我只知道“k-means 不适用于具有异常值的数据”的说法,如果您有异常值,您应该尝试使用 k-medians 或 k-medoids。
  • 异常值被定义为噪声观察,它不适合生成数据的假设模型。在聚类中,异常值被认为是应该删除的观察值,以使聚类更可靠。使用异常值检测和聚类的组合视角可以提高检测异常值的能力。一些聚类算法,例如 DBSCAN 和 ROCK,将异常值作为特殊观察处理,但它们主要关注的是对数据集进行聚类,而不是检测异常值。 Kmeans outlier detection
  • 我只是不适合告诉每个人我正在做的一切,我只想要一个简单的方法来消除 Kmeans 中的一些噪音,哈哈
  • @JungleBoogie:不要太快做出判断。我自己试过了,它的工作原理和宣传的一样……我不知道你在说什么 Javascript,code 就在你面前!你不喜欢,我可以在google search 的第一页看到其他三个实现。更好的是实现你自己的......
【解决方案2】:

首先要做的是:您在这里要求很多。供将来参考:尝试将您的问题分解为更小的部分,并发布几个问题。这会增加您获得答案的机会(并且不会花费您 400 点声望!)。

幸运的是,我理解你的困境,我就是喜欢这样的问题!

除了这个数据集在 k-means 上可能存在的问题之外,这个问题仍然足够通用,也适用于其他数据集(因此 Google 员工最终会在这里寻找类似的东西),所以让我们继续解决这个问题。

我的建议是我们编辑此答案,直到您获得相当满意的结果。

集群数量

任何聚类问题的第 1 步:选择多少个聚类?我知道有几种方法可以用来选择适当数量的集群。有一个很好的wiki page 与此相关,包含以下所有方法(以及更多方法)。

外观检查

这可能看起来很愚蠢,但如果您有分离良好的数据,一个简单的图表就可以告诉您(大约)您需要多少个集群,只需查看即可。

优点:

  • 快速
  • 简单
  • 在相对较小的数据集中分离良好的集群上效果很好

缺点:

  • 又脏又脏
  • 需要用户交互
  • 很容易错过较小的集群
  • 使用这种方法很难处理具有不太良好或大量分离的簇的数据
  • 这完全是主观的 - 下一个人可能会选择与您不同的金额。

剪影图

如您的other questions 之一所示,制作silhouettes 图将帮助您更好地决定数据中的正确聚类数量。

优点:

  • 比较简单
  • 通过使用统计方法降低主观性
  • 表示选择质量的直观方式

缺点:

  • 需要用户交互
  • 在极限情况下,如果您采用与数据点一样多的集群,则剪影图会告诉您 是最佳选择
  • 它仍然是相当主观的,不是基于统计手段
  • 计算成本可能很高

肘法

与轮廓图方法一样,您重复运行kmeans,每次使用大量集群,您会看到数据中的总方差中有多少是由此kmeans 运行选择的集群解释的.将有许多集群,其中解释方差的数量会突然增加很多,比之前选择的集群数量(“肘部”)要少得多。从统计上讲,肘部是集群数量的最佳选择。

优点:

  • 无需用户交互——可以自动选择肘部
  • 在统计上比上述任何一种方法都更可靠

缺点:

  • 有点复杂
  • 仍然主观,因为“肘部”的定义取决于主观选择的参数
  • 计算成本可能很高

异常值

一旦您使用上述任何方法选择了集群的数量,就可以进行异常值检测以查看集群的质量是否有所提高。

我将从使用肘部方法的两步迭代方法开始。在伪 Matlab 中:

data = your initial dataset
dataMod = your initial dataset

MAX = the number of clusters chosen by visual inspection

while (forever)

    for N = MAX-5 : MAX+5
        if (N < 1), continue, end
        perform k-means with N clusters on dataMod
        if (variance explained shows a jump)
            break
    end

    if (you are satisfied)
        break
    end

    for i = 1:N
        extract all points from cluster i 
        find the centroid (let k-means do that)
        calculate the standard deviation of distances to the centroid
        mark points further than 3 sigma as possible outliers
    end

    dataMod = data with marked points removed

end

困难的部分显然是确定you are satisfied。 这是算法有效性的关键。粗略的结构 这部分

if (you are satisfied)
    break
end

应该是这样的

if (situation has improved)
    data = dataMod

elseif (situation is same or worse)
    dataMod = data
    break            
end

当异常值较少时的situation has improved,或方差 解释N 的所有选择比while 中的前一个循环更好。这也是要摆弄的东西。

无论如何,我不会称之为第一次尝试。 如果有人在这里看到不完整、缺陷或漏洞,请 评论或编辑。

【讨论】:

  • 您可能会通过这种“异常值删除”从数据集中删除正常数据。正常数据更加分散;攻击数据来自大规模爆发(占数据集的 80%),在一定程度上会聚集在一起,而且自相似性更高。
猜你喜欢
  • 2012-12-08
  • 2013-08-08
  • 2015-04-11
  • 2019-05-04
  • 2016-02-04
  • 2011-08-13
  • 2013-02-14
  • 2018-01-14
  • 2018-11-11
相关资源
最近更新 更多