Performance 提高嵌套循环MATLAB的性能

Performance 提高嵌套循环MATLAB的性能,performance,matlab,vectorization,nested-loops,Performance,Matlab,Vectorization,Nested Loops,我试图分析大量数据,这使得我的程序运行速度非常慢。 我正在将数据集从.txt文件读入单元格数组。 我正在使用一个单元格数组,因为为了对我的数据进行分类,它是两个属性的形式,我需要的类是字符 我想使用最近的平均值分类器来查找重新替换错误。 我有一个主要的外部循环,它循环通过我的数据集的每一行(成千上万)。每一行依次删除,每次迭代一行。在每次迭代中,删除线后,重新计算两个属性的平均值。主要挂起点似乎是下一节,我要计算数据集中的每一行: 该行上的数据(2个属性值)与 我每门课的平均分 然后我想记录属

我试图分析大量数据,这使得我的程序运行速度非常慢。 我正在将数据集从.txt文件读入单元格数组。 我正在使用一个单元格数组,因为为了对我的数据进行分类,它是两个属性的形式,我需要的类是字符

我想使用最近的平均值分类器来查找重新替换错误。 我有一个主要的外部循环,它循环通过我的数据集的每一行(成千上万)。每一行依次删除,每次迭代一行。在每次迭代中,删除线后,重新计算两个属性的平均值。主要挂起点似乎是下一节,我要计算数据集中的每一行:

  • 该行上的数据(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
errorCount=0;
对于l=1:20000
最近值=100;
类别=0;
attribute1=d{2}(l);
attribute2=d{3}(l);
对于m=1:numel(类)
dist=sqrt((attribute1-meansattr1(m))*(attribute1-meansattr1(m))+(attribute2-meansattr2(m))*(attribute2-meansattr2(m));
如果距离<最近
最近的=距离;
类别=m;
结束
结束
如果strcmp(d{1}(l),类(class))
%正确的
其他的
errorCount=errorCount+1;
结束
结束
d
是我的单元格数组,其中
d{2}
是保存属性1值的列。对于该列的第一行,我使用
d{1}(1)
访问这些值

是我的数据集中唯一的类,因此对于我的每个类,我计算到它的欧几里德距离

meansattr1
meansattr2
是包含我的每个属性的平均值的数组。当删除一条线时,这些将在外部循环的每次迭代中更新


希望这能帮助您理解我的代码。非常感谢在优化和加速这些计算方面的任何帮助

最简单的速度改进是删除
sqrt
调用。找到最近距离的平方与最近距离完全相同

接下来,可以对内部循环进行矢量化。我已经很久没有使用MatLab了,所以我可能会弄错下面的代码,但是我的想法是将这两个属性转换成一个长度
numel(classes)
的向量。然后您可以直接计算差异并将其平方

大概是这样的:

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

顺便说一句,使用
class
作为变量不是一个好主意(如果可以的话)。这是一个保留字。

我从paddy的解决方案开始,简单地替换变量名:

[closest, cl] = min( (d{2}(m) - meansattr1).^2 +(d{3}(m) - meansattr2).^
2);
因此,我们有一个单行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))

注意:不要将“class”或任何其他保留字用于其他目的。

您实际上是在优化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
errorCount
closestDistance
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);

将这一切都放在jj=1:MAXITER的
while errorCount>THRESH
中,你应该得到你想要的。

最简单的速度改进是删除
sqrt
调用。查找最近距离的平方与最近距离完全相同。如果使用了距离,则缺少“最近的=strt(最近的)”。变量包含平方距离。当然,但原始代码也没有显示使用该距离的位置。在所有的循环之后,使用
sqrt
是很容易的。谢谢,通过这种方式,性能得到了一定的提高。我将不得不看看我的程序的其他方面,看看我可以在哪里做类似的增强。
% 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);