数か月前にクラスタリングを行っているときに、同様の問題に遭遇しました。私は組み込みのソリューションを長い間検索しませんでしたが (それらが存在するに違いないと確信していますが)、見つけたラベルをグラウンド トゥルースと最適に一致させるための独自の小さなスクリプトを作成することになりました。コードは非常に粗雑ですが、開始する必要があります。
これは、可能な限りすべてのラベルの再配置を試みて、真理ベクトルに最適なウィッチを確認することに基づいています。つまり、 Ground Truthyte = [3 3 2 1]
を使用したクラスタリング結果が与えられるy = [1 1 2 3]
と、スクリプトは との一致を試みて最適な一致[3 3 2 1], [3 3 1 2], [2 2 3 1], [2 2 1 3], [1 1 2 3] and [1 1 3 2]
をy
見つけようとします。
perms()
これは、10 を超える固有のクラスターを処理できない組み込みスクリプト ウィッチの使用に基づいています。複雑さが階乗として成長するため、コードは 7 ~ 10 個の一意のクラスターでも遅くなる傾向があります。
function [accuracy, true_labels, CM] = calculateAccuracy(yte, y)
%# Function for calculating clustering accuray and matching found
%# labels with true labels. Assumes yte and y both are Nx1 vectors with
%# clustering labels. Does not support fuzzy clustering.
%#
%# Algorithm is based on trying out all reorderings of cluster labels,
%# e.g. if yte = [1 2 2], try [1 2 2] and [2 1 1] so see witch fit
%# the truth vector the best. Since this approach makes use of perms(),
%# the code will not run for unique(yte) greater than 10, and it will slow
%# down significantly for number of clusters greater than 7.
%#
%# Input:
%# yte - result from clustering (y-test)
%# y - truth vector
%#
%# Output:
%# accuracy - Overall accuracy for entire clustering (OA). For
%# overall error, use OE = 1 - OA.
%# true_labels - Vector giving the label rearangement witch best
%# match the truth vector (y).
%# CM - Confusion matrix. If unique(yte) = 4, produce a
%# 4x4 matrix of the number of different errors and
%# correct clusterings done.
N = length(y);
cluster_names = unique(yte);
accuracy = 0;
maxInd = 1;
perm = perms(unique(y));
[pN pM] = size(perm);
true_labels = y;
for i=1:pN
flipped_labels = zeros(1,N);
for cl = 1 : pM
flipped_labels(yte==cluster_names(cl)) = perm(i,cl);
end
testAcc = sum(flipped_labels == y')/N;
if testAcc > accuracy
accuracy = testAcc;
maxInd = i;
true_labels = flipped_labels;
end
end
CM = zeros(pM,pM);
for rc = 1 : pM
for cc = 1 : pM
CM(rc,cc) = sum( ((y'==rc) .* (true_labels==cc)) );
end
end
例:
[acc newLabels CM] = calculateAccuracy([3 2 2 1 2 3]',[1 2 2 3 3 3]')
acc =
0.6667
newLabels =
1 2 2 3 2 1
CM =
1 0 0
0 2 0
1 1 1