这段用于标准化数据的代码是如何工作的?
How does this code for standardizing data work?
我为机器学习课程提供了一个 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
此代码接受大小为 M x N
的数据矩阵,其中 M
是该矩阵中一个数据样本的维数,N
是样本总数。因此,这个矩阵的一列是一个数据样本。数据样本都是水平堆叠的,都是列的。
现在,此代码的真正目的是获取矩阵的所有列并对数据进行标准化/规范化,以便每个数据样本显示zero mean and unit variance .这意味着在这个转换之后,如果你找到这个矩阵中任何一列的平均值,它会是 0,方差会是 1。这是统计分析、机器学习和计算机视觉中标准化值的一种非常标准的方法.
这个其实来自统计分析中的z-score。具体来说,归一化方程为:
给定一组数据点,我们用这些数据点的平均值减去相关值,然后除以各自的标准差。您如何调用此代码如下。给定这个我们称之为 X
的矩阵,您可以通过两种方式调用此代码:
- 方法一:
[X, mean_X, std_X] = standardize(X);
- 方法#2:
[X, mean_X, std_X] = standardize(X, mu, sigma);
第一种方法自动推断出X
每列的均值和X
每列的标准差。 mean_X
和 std_X
都是 return 1 x N
向量,它们为您提供矩阵 X
中每一列的均值和标准差。第二种方法允许您为 X
的每一列手动指定平均值 (mu
) 和标准偏差 (sigma
)。这可能用于调试,但在这种情况下,您可以将 mu
和 sigma
指定为 1 x N
向量。 mean_X
和 std_X
的 return 与 mu
和 sigma
相同。
恕我直言,代码写得有点糟糕,因为你当然可以实现这种矢量化,但代码的要点是它找到矩阵的每一列的平均值 X
如果我们正在使用方法#1,复制这个向量,使其成为 M x N
矩阵,然后我们用 X
减去这个矩阵。这将减去每一列各自的平均值。我们还在均值减法之前计算每列的标准差。
一旦我们这样做了,我们就会通过将每一列除以其各自的标准差来标准化我们的 X
。顺便说一句,做 std_X(:, i)
是多余的,因为 std_X
已经是一个 1 x N
向量。 std_X(:, i)
表示获取第 i
th 列的所有行。如果我们已经有了一个 1 x N
向量,可以简单地用 std_X(i)
替换它——对我来说有点过分了。
方法 #2 执行与方法 #1 相同的操作,但我们为 X
.
的每一列提供了我们自己的均值和标准差
为了文档,我会这样评论代码:
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
如果我能建议另一种编写此代码的方法,我会使用强大的 bsxfun
函数。这避免了必须对元素进行任何重复,我们可以在后台进行。我会重写这个函数,让它看起来像这样:
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
我认为上面的新代码比使用 for
和 repmat
快得多。事实上,众所周知 bsxfun
比前一种方法更快 - 特别是对于较大的矩阵。
我为机器学习课程提供了一个 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
此代码接受大小为 M x N
的数据矩阵,其中 M
是该矩阵中一个数据样本的维数,N
是样本总数。因此,这个矩阵的一列是一个数据样本。数据样本都是水平堆叠的,都是列的。
现在,此代码的真正目的是获取矩阵的所有列并对数据进行标准化/规范化,以便每个数据样本显示zero mean and unit variance .这意味着在这个转换之后,如果你找到这个矩阵中任何一列的平均值,它会是 0,方差会是 1。这是统计分析、机器学习和计算机视觉中标准化值的一种非常标准的方法.
这个其实来自统计分析中的z-score。具体来说,归一化方程为:
给定一组数据点,我们用这些数据点的平均值减去相关值,然后除以各自的标准差。您如何调用此代码如下。给定这个我们称之为 X
的矩阵,您可以通过两种方式调用此代码:
- 方法一:
[X, mean_X, std_X] = standardize(X);
- 方法#2:
[X, mean_X, std_X] = standardize(X, mu, sigma);
第一种方法自动推断出X
每列的均值和X
每列的标准差。 mean_X
和 std_X
都是 return 1 x N
向量,它们为您提供矩阵 X
中每一列的均值和标准差。第二种方法允许您为 X
的每一列手动指定平均值 (mu
) 和标准偏差 (sigma
)。这可能用于调试,但在这种情况下,您可以将 mu
和 sigma
指定为 1 x N
向量。 mean_X
和 std_X
的 return 与 mu
和 sigma
相同。
恕我直言,代码写得有点糟糕,因为你当然可以实现这种矢量化,但代码的要点是它找到矩阵的每一列的平均值 X
如果我们正在使用方法#1,复制这个向量,使其成为 M x N
矩阵,然后我们用 X
减去这个矩阵。这将减去每一列各自的平均值。我们还在均值减法之前计算每列的标准差。
一旦我们这样做了,我们就会通过将每一列除以其各自的标准差来标准化我们的 X
。顺便说一句,做 std_X(:, i)
是多余的,因为 std_X
已经是一个 1 x N
向量。 std_X(:, i)
表示获取第 i
th 列的所有行。如果我们已经有了一个 1 x N
向量,可以简单地用 std_X(i)
替换它——对我来说有点过分了。
方法 #2 执行与方法 #1 相同的操作,但我们为 X
.
为了文档,我会这样评论代码:
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
如果我能建议另一种编写此代码的方法,我会使用强大的 bsxfun
函数。这避免了必须对元素进行任何重复,我们可以在后台进行。我会重写这个函数,让它看起来像这样:
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
我认为上面的新代码比使用 for
和 repmat
快得多。事实上,众所周知 bsxfun
比前一种方法更快 - 特别是对于较大的矩阵。