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

我在学习一门机器学习课程时,提供了一个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

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

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