我可以通过在matlab中使用:operator来避免使用for循环来规范化数据吗?

时间:2015-10-24 11:47:35

标签: matlab regression vectorization

以下是我正在使用的代码 -

mu = mean(X);
sigma = std(X);

for iter = 1:size(X, 1)
  X_norm(iter,:)=((X(iter,:)-mu)./sigma)
end

我想知道是否有办法在不使用循环并仅使用基本运算符的情况下执行此操作,我可以通过这些运算符添加X中的每一行并将其除以sigma。

X和X_norm是矩阵。 我发现的一种方法是 - (虽然它使用函数)

one= ones(size(X, 1), 1);
X_norm = (X - one*(mean(X)))./(one*std(X));

请注意,我想了解有关使用基本操作符的更多信息,因此请不要提供任何库或工具包。

如果您要发布一个函数,也可以发布它的实现

4 个答案:

答案 0 :(得分:3)

使用bsxfun -

X_norm = bsxfun(@rdivide,bsxfun(@minus,X,mu),sigma)

您还可以使用ones()心爱的运算符: 进行复制,如Loren's blog中所述,然后执行所述操作,就像这样 -

M = size(X,1);
X_norm = (X - mu(ones(M,1),:))./sigma(ones(M,1),:)

为了表现,我会随时使用bsxfun

答案 1 :(得分:3)

注意: @Divakar使用bsxfun发布了一个非常优雅的答案,我建议使用这种方法。不过,我发布了这个答案(因为我已经在发布其他答案时已经写了大部分内容),所以你可以看到现有代码出了什么问题。

由于您的目标是将矩阵X的每个规范化为零均值和方差1,因此您的版本无法按预期工作。正如@Dan在评论中所说,通过使用/进行除法,您可以在两个行向量之间进行矩阵划分,从而创建标量作为结果。因此,循环的输出是一个n x 1列向量(我不知道它实际包含的是什么......)。

首先,要意识到mean返回一个行向量,其中每个条目都包含相应的平均值。要逐行标准化,您必须获取每个的平均值,这可以通过mean(X,2)完成。 std也是如此,即使用std(X,[],2)

mu = mean(X,2);
sigma = std(X,[],2);

使用for循环的版本现在是

X_norm = zeros(size(X));
for k= 1:size(X, 1)
  X_norm(k,:) = (X(k,:)-mu(k)) ./ sigma(k);
end

即。遍历所有行并减去行的平均值,然后除以标准差。 通过使用mu(k),您可以为每一行使用正确的mean / std dev。

另外,出于性能原因,请不要忘记预先分配矩阵X_norm

答案 2 :(得分:2)

使用repmat的另一种解决方案是

(X - repmat(mu, length(X), 1)) ./ repmat(sigma, length(X), 1)

这可能比bsxfun更容易理解。我已发布此解决方案,以证明您需要执行您需要复制向量的操作musigma:无法使用repmat

补充阅读:Colon Operator in MATLAB

虽然,我建议使用bsxfun

答案 3 :(得分:2)

如果您拥有Statistics Toolbox,则可以使用内置函数zscore()

X_norm = zscore(X);