我有一个提供standardize
函数的机器学习课程没有很好的文档记录,我还是MATLAB的新手,所以我只是试图打破这个功能。对语法的任何解释或标准化的一般概念都会有很大帮助。我们使用此功能来标准化大矩阵中提供的一组训练数据。分解代码片段的大多数行会对我有很大帮助。非常感谢。
function [X, mean_X, std_X] = standardize(varargin)
switch nargin
case 1
mean_X = mean(varargin{1});
std_X = std(varargin{1});
X = varargin{1} - repmat(mean_X, [size(varargin{1}, 1) 1]);
for i = 1:size(X, 2)
X(:, i) = X(:, i) / std(X(:, i));
end
case 3
mean_X = varargin{2};
std_X = varargin{3};
X = varargin{1} - repmat(mean_X, [size(varargin{1}, 1) 1]);
for i = 1:size(X, 2)
X(:, i) = X(:, i) / std_X(:, i);
end
end
答案 0 :(得分:2)
此代码接受大小为M x N
的数据矩阵,其中M
是此矩阵中一个数据样本的维度,N
是样本总数。因此,该矩阵的一列是一个数据样本。数据样本全部水平堆叠并且是列。
现在,此代码的真正目的是获取矩阵的所有列并标准化/规范化数据,以便每个数据样本都显示zero mean and unit variance。这意味着在此变换之后,如果您找到此矩阵中任何列的平均值,它将为0,方差将为1.这是在统计分析,机器学习和计算机视觉中标准化值的非常标准的方法
这实际上来自统计分析中的z-score。具体而言,归一化的等式是:
给定一组数据点,我们通过这些数据点的平均值减去所讨论的值,然后除以相应的标准偏差。您如何调用此代码如下。给定此矩阵,我们将其称为X
,您可以通过两种方式调用此代码:
[X, mean_X, std_X] = standardize(X);
[X, mean_X, std_X] = standardize(X, mu, sigma);
第一种方法自动推断X
每列的平均值和X
每列的标准差。 mean_X
和std_X
都会返回1 x N
个向量,这些向量会为您提供矩阵X
中每列的均值和标准差。第二种方法允许您为mu
的每列手动指定平均值(sigma
)和标准差(X
)。这可能用于调试,但在这种情况下,您可以将mu
和sigma
指定为1 x N
向量。 mean_X
和std_X
返回的内容与mu
和sigma
相同。
代码写得有点糟糕恕我直言,因为你当然可以实现这个矢量化,但代码的要点是如果我们正在使用方法#它找到矩阵X
的每一列的平均值1,复制此向量使其成为M x N
矩阵,然后我们用X
减去此矩阵。这将按各自的平均值减去每列。我们还在平均减法之前计算每列的标准偏差。
一旦我们这样做,我们就会通过将每列除以各自的标准偏差来标准化X
。顺便说一下,std_X(:, i)
执行std_X
是多余的,因为1 x N
已经是std_X(:, i)
向量。 i
表示抓取1 x N
th 列中的所有行。如果我们已经有std_X(i)
向量,那么可以简单地将其替换为X
- 根据我的口味有点矫枉过正。
方法#2执行与方法#1相同的操作,但我们为function [X, mean_X, std_X] = standardize(varargin)
switch nargin %// Check how many input variables we have input into the function
case 1 %// If only one variable - this is the input matrix
mean_X = mean(varargin{1}); %// Find mean of each column
std_X = std(varargin{1}); %// Find standard deviation of each column
%// Take each column of X and subtract by its corresponding mean
%// Take mean_X and duplicate M times vertically
X = varargin{1} - repmat(mean_X, [size(varargin{1}, 1) 1]);
%// Next, for each column, normalize by its respective standard deviation
for i = 1:size(X, 2)
X(:, i) = X(:, i) / std(X(:, i));
end
case 3 %// If we provide three inputs
mean_X = varargin{2}; %// Second input is a mean vector
std_X = varargin{3}; %// Third input is a standard deviation vector
%// Apply the code as seen in the first case
X = varargin{1} - repmat(mean_X, [size(varargin{1}, 1) 1]);
for i = 1:size(X, 2)
X(:, i) = X(:, i) / std_X(:, i);
end
end
的每列提供了我们自己的均值和标准差。
为了便于记录,这就是我对代码进行评论的方式:
function [X, mean_X, std_X] = standardize(varargin)
switch nargin
case 1
mean_X = mean(varargin{1}); %// Find mean of each column
std_X = std(varargin{1}); %// Find std. dev. of each column
X = bsxfun(@minus, varargin{1}, mean_X); %// Subtract each column by its respective mean
X = bsxfun(@rdivide, X, std_X); %// Take each column and divide by its respective std dev.
case 3
mean_X = varargin{2};
std_X = varargin{3};
%// Same code as above
X = bsxfun(@minus, varargin{1}, mean_X);
X = bsxfun(@rdivide, X, std_X);
end
如果我可以建议另一种编写此代码的方法,我会使用强大而强大的bsxfun
函数。这避免了必须进行任何元素重复,我们可以在幕后进行。我会重写这个函数,使它看起来像这样:
for
我认为上面的新代码比使用repmat
和bsxfun
要快得多。事实上,众所周知{{1}}比前一种方法更快 - 特别是对于更大的矩阵。