这个标准化数据的代码如何工作?

时间:2015-02-24 06:56:17

标签: matlab machine-learning standardized

我有一个提供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

1 个答案:

答案 0 :(得分:2)

此代码接受大小为M x N的数据矩阵,其中M是此矩阵中一个数据样本的维度,N是样本总数。因此,该矩阵的一列是一个数据样本。数据样本全部水平堆叠并且是列。

现在,此代码的真正目的是获取矩阵的所有列并标准化/规范化数据,以便每个数据样本都显示zero mean and unit variance。这意味着在此变换之后,如果您找到此矩阵中任何列的平均值,它将为0,方差将为1.这是在统计分析,机器学习和计算机视觉中标准化值的非常标准的方法

这实际上来自统计分析中的z-score。具体而言,归一化的等式是:

给定一组数据点,我们通过这些数据点的平均值减去所讨论的值,然后除以相应的标准偏差。您如何调用此代码如下。给定此矩阵,我们将其称为X,您可以通过两种方式调用此代码:

  • 方法#1:[X, mean_X, std_X] = standardize(X);
  • 方法#2:[X, mean_X, std_X] = standardize(X, mu, sigma);

第一种方法自动推断X每列的平均值和X每列的标准差。 mean_Xstd_X都会返回1 x N个向量,这些向量会为您提供矩阵X中每列的均值和标准差。第二种方法允许您为mu的每列手动指定平均值(sigma)和标准差(X)。这可能用于调试,但在这种情况下,您可以将musigma指定为1 x N向量。 mean_Xstd_X返回的内容与musigma相同。

代码写得有点糟糕恕我直言,因为你当然可以实现这个矢量化,但代码的要点是如果我们正在使用方法#它找到矩阵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

我认为上面的新代码比使用repmatbsxfun要快得多。事实上,众所周知{{1}}比前一种方法更快 - 特别是对于更大的矩阵。