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