朴素贝叶斯分类器和判别分析的准确性是远离的

时间:2012-11-18 07:34:49

标签: matlab statistics cluster-analysis bayesian naivebayes

所以我有两种分类方法,判别分析的直线分类(朴素贝叶斯)和matlab中实现的纯朴朴贝叶斯分类器,整个数据集中有23个类。第一种方法判别分析:

%% Classify Clusters using Naive Bayes Classifier and classify
training_data = Testdata; 
target_class = TestDataLabels;

[class, err]  = classify(UnseenTestdata, training_data, target_class,'diaglinear')

cmat1 = confusionmat(UnseenTestDataLabels, class);
acc1 = 100*sum(diag(cmat1))./sum(cmat1(:));
fprintf('Classifier1:\naccuracy = %.2f%%\n', acc1);
fprintf('Confusion Matrix:\n'), disp(cmat1)

81.49%的混淆矩阵产生精确度,错误率(err 0.5040 (不知道如何解释)。

第二种方法Naive Bayes分类器:

%% Classify Clusters using Naive Bayes Classifier
training_data = Testdata; 
target_class = TestDataLabels;
%# train model
nb = NaiveBayes.fit(training_data, target_class, 'Distribution', 'mn');

%# prediction
class1 = nb.predict(UnseenTestdata); 

%# performance
cmat1 = confusionmat(UnseenTestDataLabels, class1);
acc1 = 100*sum(diag(cmat1))./sum(cmat1(:));
fprintf('Classifier1:\naccuracy = %.2f%%\n', acc1);
fprintf('Confusion Matrix:\n'), disp(cmat1)

准确度 81.89%

我只进行了一轮交叉验证,我在matlab和监督/无监督算法上都是新的,所以我自己做了交叉验证我基本上只拿了10%的数据并将它放在一边用于测试目的,因为它是一个随机设置每次我可以多次通过它并取平均准确度,但结果将用于解释目的。

所以问题就是我的问题。

在我对当前方法的文献综述中,许多研究人员发现,将单一分类算法与聚类算法相结合,可以获得更好的准确度结果。他们通过为他们的数据找到最佳聚类数量并使用分配的聚类(应该更相似)通过分类算法运行每个单独的聚类来实现这一点。一个过程,您可以将无监督算法的最佳部分与监督分类算法结合使用。

现在我正在使用在文献中多次使用过的数据集,并尝试在我的任务中尝试与其他人不同的方法。

我首先使用简单的K-Means聚类,它具有很好的聚类数据的能力。输出如下:

enter image description here

查看每个群集(K1,K2 ... K12)类标签:

%% output the class labels of each cluster
     K1 = UnseenTestDataLabels(indX(clustIDX==1),:)

我发现主要是每个集群在9个集群中有一个类标签,而3个集群包含多个类标签。表明K-means非常适合数据。

问题然而,一旦我拥有每个群集数据(cluster1,cluster2 ... cluster12):

 %% output the real data of each cluster
     cluster1 = UnseenTestdata(clustIDX==1,:)

我将每个群集放在朴素的贝叶斯或判别分析中,如下所示:

class1  = classify(cluster1, training_data, target_class, 'diaglinear');
class2  = classify(cluster2, training_data, target_class, 'diaglinear');
class3  = classify(cluster3, training_data, target_class, 'diaglinear');
class4  = classify(cluster4, training_data, target_class, 'diaglinear');
class5  = classify(cluster5, training_data, target_class, 'diaglinear');
class6  = classify(cluster6, training_data, target_class, 'diaglinear');
class7  = classify(cluster7, training_data, target_class, 'diaglinear');
class8  = classify(cluster8, training_data, target_class, 'diaglinear');
class9  = classify(cluster9, training_data, target_class, 'diaglinear');
class10  = classify(cluster10, training_data, target_class, 'diaglinear'); 
class11  = classify(cluster11, training_data, target_class, 'diaglinear');
class12  = classify(cluster12, training_data, target_class, 'diaglinear');

准确性变得可怕,50%的聚类被分类为0%准确度,每个分类聚类(acc1,acc2,... acc12)都有自己相应的混淆矩阵,你可以在这里看到每个聚类的准确性: / p>

enter image description here

所以我的问题/问题是我哪里出错了,我首先想到的可能是我的数据/标签混合了群集,但我上面发布的内容看起来是正确的我无法看到它的问题。

为什么第一个实验中使用的数据完全相同,看不见的10%数据会对同一个看不见的聚类数据产生如此奇怪的结果?我的意思是应该注意到NB是一个稳定的分类器,并且不应该容易过度拟合并且看到训练数据是巨大的而被分类的群集是并发过度拟合不应该发生?

修改

根据评论的要求,我已将cmat文件包含在第一个测试示例中,其精确度为 81.49%,错误为 0.5040

enter image description here

此外还要求提供K,类和相关cmat的片段(cluster4),准确度 3.03%

enter image description here

看到有大量的课程(总共23个)我决定减少课程,如1999 KDD Cup中所述,这只是应用领域知识的提升,因为一些攻击比其他攻击更相似并且在一个总括任期内。

然后我训练了分类器444,000条记录,同时阻止10%用于测试目的。

准确度更差 73.39%错误率也更差 0.4261

enter image description here

unseendata分解为其类:

DoS: 39149
Probe: 405
R2L: 121
U2R: 6
normal.: 9721

班级或机密标签(判别分析的结果)

DoS: 28135
Probe: 10776
R2L: 1102
U2R: 1140
normal.: 8249

训练数据由以下部分组成:

DoS: 352452
Probe: 3717
R2L: 1006
U2R: 49
normal.: 87395

我担心如果我将训练数据降低到具有类似的恶意活动感,那么分类器就没有足够的预测能力来区分类别,但是看一些其他文献我注意到一些研究人员删除了U2R,因为没有足够的数据用于成功分类。

我到目前为止尝试过的方法是一个类分类器,我训练分类器只预测一个类(无效),对单个集群进行分类(精度更差),减少类标签(第二最佳)并保持完整23类标签(最佳准确性)。

5 个答案:

答案 0 :(得分:1)

正如其他人正确指出的那样,这里至少有一个问题是:

class1  = classify(cluster1, training_data, target_class, 'diaglinear');
...

您正在使用所有training_data训练分类器,但仅在子群集上对其进行评估。要使数据聚类以产生任何影响,您需要在每个子聚类中训练 中的不同分类器。有时这可能非常困难 - 例如,来自Y类的集群C中可能只有很少(或没有!)示例。这是尝试进行联合聚类和学习所固有的。

您的问题的一般框架如下:

Training data:
   Cluster into C clusters
   Within each cluster, develop a classifier

Testing data:
   Assign observation into one of the C clusters (either "hard", or "soft")
   Run the correct classifier (corresponding to that cluster)

class1  = classify(cluster1, training_data, target_class, 'diaglinear');

不这样做。

答案 1 :(得分:1)

这是一个非常简单的例子,它准确地说明了这应该如何工作以及出了什么问题

%% Generate data and labels for each class
x11 = bsxfun(@plus,randn(100,2),[2 2]);
x10 = bsxfun(@plus,randn(100,2),[0 2]);

x21 = bsxfun(@plus,randn(100,2),[-2 -2]);
x20 = bsxfun(@plus,randn(100,2),[0 -2]);

%If you have the PRT (shameless plug), this looks nice:
%http://www.mathworks.com/matlabcentral/linkexchange/links/2947-pattern-recognition-toolbox
% ds = prtDataSetClass(cat(1,x11,x21,x10,x20),prtUtilY(200,200));

x = cat(1,x11,x21,x10,x20);
y = cat(1,ones(200,1),zeros(200,1));

clusterIdx = kmeans(x,2); %make 2 clusters
xCluster1 = x(clusterIdx == 1,:);
yCluster1 = y(clusterIdx == 1);
xCluster2 = x(clusterIdx == 2,:);
yCluster2 = y(clusterIdx == 2);


%Performance is terrible:
yOut1  = classify(xCluster1, x, y, 'diaglinear');
yOut2  = classify(xCluster2, x, y, 'diaglinear');

pcCluster = length(find(cat(1,yOut1,yOut2) == cat(1,yCluster1,yCluster2)))/size(y,1)

%Performance is Good:
yOutCluster1  = classify(xCluster1, xCluster1, yCluster1, 'diaglinear');
yOutCluster2  = classify(xCluster2, xCluster2, yCluster2, 'diaglinear');

pcWithinCluster = length(find(cat(1,yOutCluster1,yOutCluster2) == cat(1,yCluster1,yCluster2)))/size(y,1)

%Performance is Bad (using all data):
yOutFull  = classify(x, x, y, 'diaglinear');
pcFull = length(find(yOutFull == y))/size(y,1)

答案 2 :(得分:-1)

查看第一个示例的cmat1数据(准确度为81.49%),您获得高精度的主要原因是您的分类器获得了大量class 1class 4正确。几乎所有其他类都表现不佳(获得零正确预测)。这与你的上一个例子(首先使用k-means)一致,对于cluster7,你获得的acc7为56.9698。

修改: 似乎在cmat1中,我们没有超过一半类的测试数据(查看全零线)。因此,您只能知道14这样的类的一般性能是好的,并且如果您先进行群集,则会获得类似的性能。但对于其他课程,这并不能证明它能正常运作。

答案 3 :(得分:-1)

对数据进行群集后,是否要为每个群集培训分类器?如果你不这样做,那么这可能是你的问题。

尝试这样做。首先,对数据进行聚类并保留质心。然后,使用训练数据,按群集训练分类器。对于分类阶段,找到要分类的对象的最近质心,并使用相应的分类器。

单个分类器不是一个好主意,因为它可以学习整个数据集的模式。但是,群集时所需的是学习描述每个群集的本地模式。

答案 4 :(得分:-1)

考虑这个函数调用:

classify(cluster1, training_data, target_class, 'diaglinear');

training_data是整个要素空间的示例。那意味着什么?您正在训练的分类模型将尝试最大化整个特征空间的分类精度。这意味着如果您显示与训练数据具有相同行为的测试样本,您将获得分类结果。

重点是您没有显示与训练数据具有相同行为的测试样本。实际上,cluster1只是特征空间的一个分区的示例。更具体地说,cluster1中的实例对应于特征空间的样本,这些样本比其余的质心更接近cluster1的质心,这可能会降低分类器的性能。

所以我建议你:

  1. 对训练集进行聚类并保留质心
  2. 使用训练数据,训练每个群集的分类器。也就是说,仅使用属于该群集的实例来训练分类器。
  3. 对于分类阶段,找到要分类的对象的最近质心,并使用相应的分类器。