1

プログラムの実行を非常に遅くしている多くのデータを分析しようとしています。.txt ファイルからセル配列にデータセットを読み込んでいます。2 つの属性の形式であるデータを分類するために、セル配列を使用しています。文字であるクラスが必要です。

最も近い平均分類器を使用して再代入誤差を見つけたい。データセットの各行 (数万) をループするメインの外部ループがあります。各行は、反復ごとに 1 つずつ順番に削除されます。2 つの属性の平均は、行が削除された各反復で再計算されます。主なハング ポイントは、データセットの各行について計算したい次のセクションのようです。

  • その行のデータ (2 つの属性値) と各クラスの平均との間のユークリッド距離。
  • 次に、属性の平均値が最も近いクラスを記録したいと思います。これが割り当てられたクラスになります。
  • 最後に、この割り当てられたクラスが正しいクラスかどうかを確認したいと思います。

現在、このループは次のようになっています。

errorCount = 0;
for l = 1:20000
    closest = 100;
    class = 0;
    attribute1 = d{2}(l);
    attribute2 = d{3}(l);
    for m = 1:numel(classes)
        dist = sqrt((attribute1-meansattr1(m))*(attribute1-meansattr1(m)) + (attribute2-meansattr2(m))*(attribute2-meansattr2(m)));
        if dist < closest
            closest = dist;
            class = m;
        end
    end

    if strcmp(d{1}(l),classes(class))
        %correct
    else
        errorCount = errorCount + 1;
    end
end

dはセル配列で、d{2}はアトリビュート 1 の値を保持する列です。d{1}(1)その列の最初の行でこれらの値にアクセスします。

classesはデータセットからの一意のクラスであるため、クラスごとにユークリッド距離を計算します。

meansattr1meansattr2は、各属性の平均値を含む配列です。これらは、行が削除されると、外側のループの反復ごとに更新されます。

私が持っているコードを理解するのに役立つことを願っています。これらの計算を最適化し、高速化するための助けをいただければ幸いです。

4

3 に答える 3

2

sqrt最も簡単な速度改善は、通話を削除することです。最も近い距離の二乗を求めることは、最も近い距離とまったく同じです。

次に、内側のループをベクトル化できます。私がMatLabをやったのはとても久しぶりなので、次のコードは間違っているかもしれませんが、アイデアはこれら2つの属性を長さのベクトルにすることですnumel(classes)。次に、差を直接計算して二乗できます。

このようなもの:

d1 = attribute1 - meansattr1;
d2 = attribute2 - meansattr2;
[closest, class] = min( d1 .* d1 + d2 .* d2 );

ところで、class変数として使用するのは良い考えではありません (できたとしても)。予約語です。

于 2013-10-21T22:36:13.303 に答える
1

基本的に、k-means アルゴリズムの反復部分を最適化しているため、これをベクトル化する方法については、以前のソリューションを参照できます。ただし、問題とデータ形式に対してどのように行うかを次に示します。

次のようなランダムなデータセットを取得します。

numClasses = 5;
numPoints = 20e3;
numDims = 2;

classes = strsplit(num2str(1:numClasses));

% generate random data (expected error rate of (numClasses-1)/numClasses)
d{1} = classes(randi(numClasses,numPoints,1));
d{2} = rand(numPoints,1);
d{3} = rand(numPoints,1);

% random initial class centers
meansattr1 = rand(5,1);
meansattr2 = rand(5,1);

各ポイントの最も近いクラス ID とそのクラスまでの距離を圧縮して保存するコードは次のようになります。

closestDistance = zeros(numPoints,1);  nearestCluster = zeros(numPoints,1);
errorCount = 0;
for l = 1:numPoints
    closest = 100; iclass = 0;
    attribute1 = d{2}(l); attribute2 = d{3}(l);

    for m = 1:numel(classes)
        dist = sqrt((attribute1-meansattr1(m))*(attribute1-meansattr1(m)) + ...
            (attribute2-meansattr2(m))*(attribute2-meansattr2(m)));
        if dist < closest
            closest = dist; closestDistance(l) = closest;
            iclass = m; nearestCluster(l) = iclass;
        end
    end

    if ~strcmp(d{1}(l),classes(iclass))
        errorCount = errorCount + 1;
    end
end

上記のベクトル化されたバージョンは次のようになります。

data = [d{2}(:) d{3}(:)];
meansattr = [meansattr1(:) meansattr2(:)];

kdiffs = bsxfun(@minus,data,permute(meansattr,[3 2 1]));

allDistances = sqrt(sum(kdiffs.^2,2)); % no need to do sqrt
allDistances = squeeze(allDistances); % Nx1xK => NxK

[closestDistance,nearestCluster] = min(allDistances,[],2); % Nx1

correctClassIds = str2num(char(d{1}(:)));
errorCount = nnz(nearestCluster ~= correctClassIds);

errorCountclosestDistanceおよびの結果は、nearestCluster前の解と同等です。コードのコメントが示すように、sqrt を削除してerrorCountとで同じ結果を得ることができます。nearestCluster

更新の次のステップを実行したいとしmeansattr1ますmeansattr2

% Calculate the NEW cluster centers (mean the data)
meansattr_new = zeros(numClasses,numDims);
clustersizes = zeros(numClasses,1);
for ii=1:numClasses,
    indk = nearestCluster==ii;
    clustersizes(ii) = nnz(indk);
    meansattr_new(ii,:) = mean(data(indk,:))';
end

meansattr1_next = meansattr_new(:,1);
meansattr2_next = meansattr_new(:,2);

これをすべてwhile errorCount>THRESHまたはfor jj = 1:MAXITERに入れると、目的のものが得られるはずです。

于 2013-10-22T00:44:50.870 に答える
0

私は水田のソリューション、変数名の単純な置き換えから始めました:

[closest, cl] = min( (d{2}(m) - meansattr1).^2 +(d{3}(m) - meansattr2).^
2);

したがって、1 行の for ループ、一般的な戦略があります。関数を作成し、それを arrayfun に入れます。

f=@(x)min( (d{2}(x) - meansattr1).^2 +(d{3}(x) - meansattr2).^2)
[sqclosest,cl]=arrayfun(f,1:numel(d{2}));

%If necessary real distances could be calculated:
%closest=sqrt(sqclosest)

errorCount=sum(arrayfun(@(x,c)(1-strcmp(x,classes(c))),d{1},cl))

注: 「クラス」またはその他の予約語を他の目的で使用しないでください。

于 2013-10-21T23:42:05.250 に答える