如何理解标准化数据的代码?

我在学习一门机器学习课程时,提供了一个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是样本总数。因此,矩阵的一列就是一个数据样本。数据样本都是水平堆叠的,每一列都是一个样本。

现在,这段代码的真正目的是获取矩阵的所有列,并对数据进行标准化/归一化处理,使每个数据样本具有零均值和单位方差。这意味着经过这种转换后,如果你计算任何一列的均值,它将为0,方差将为1。这是统计分析、机器学习和计算机视觉中标准化值的标准方法。

这实际上源自统计分析中的z-score。具体来说,归一化的方程是:

给定一组数据点,我们用这些数据点的均值减去所需的值,然后除以相应的标准差。调用这段代码的方式如下。假设我们有一个矩阵,称之为X,有两种调用方式:

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

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

在我看来,这段代码写得有点不好,因为你完全可以用向量化方式实现,但代码的核心是,如果我们使用方法#1,它会找到矩阵X的每一列的均值,复制这个向量使其成为M x N的矩阵,然后用X减去这个矩阵。这将使每一列减去其各自的均值。我们还在均值减法之前计算了每一列的标准差。

一旦我们这样做了,我们接着通过将每一列除以其各自的标准差来归一化我们的X。顺便说一下,执行std_X(:, i)是多余的,因为std_X已经是一个1 x N的向量。std_X(:, i)意味着获取第i列的所有行。如果我们已经有一个1 x N的向量,这可以简单地替换为std_X(i) – 对我来说有点过分了。

方法#2与方法#1执行相同的操作,但我们为X的每一列提供了自己的均值和标准差。

为了文档的目的,这是我对代码的注释方式:

function [X, mean_X, std_X] = standardize(varargin)switch nargin %// 检查输入到函数中的变量数量    case 1 %// 如果只有一个变量 - 这是输入矩阵        mean_X = mean(varargin{1}); %// 查找每一列的均值        std_X = std(varargin{1}); %// 查找每一列的标准差        %// 取X的每一列并减去其对应的均值        %// 取mean_X并在垂直方向上复制M次        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

如果我可以建议另一种编写这段代码的方式,我会使用强大而有力的bsxfun函数。这避免了任何元素的复制,我们可以在幕后完成。我会重写这个函数,使其看起来像这样:

function [X, mean_X, std_X] = standardize(varargin)switch nargin    case 1        mean_X = mean(varargin{1}); %// 查找每一列的均值        std_X = std(varargin{1}); %// 查找每一列的标准差        X = bsxfun(@minus, varargin{1}, mean_X); %// 用各自的均值减去每一列        X = bsxfun(@rdivide, X, std_X); %// 取每一列并除以其各自的标准差    case 3        mean_X = varargin{2};        std_X = varargin{3};        %// 与上面的代码相同        X = bsxfun(@minus, varargin{1}, mean_X);        X = bsxfun(@rdivide, X, std_X);end

我认为上面的新代码比使用forrepmat要快得多。事实上,已知bsxfun比前一种方法更快 – 特别是对于较大的矩阵。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注