【问题标题】:spdiags and features scalingspdiags 和功能缩放
【发布时间】:2015-05-12 08:53:32
【问题描述】:

根据libsvm faqs,下面一行代码将每个特征在Matlab中缩放到[0,1]的范围

(data - repmat(min(data,[],1),size(data,1),1))*spdiags(1./(max(data,[],1)-min(data,[],1))',0,size(data,2),size(data,2))

所以我正在使用这个代码:

v_feature_trainN=(v_feature_train - repmat(mini,size(v_feature_train,1),1))*spdiags(1./(maxi-mini)',0,size(v_feature_train,2),size(v_feature_train,2));
 v_feature_testN=(v_feature_test - repmat(mini,size(v_feature_test,1),1))*spdiags(1./(maxi-mini)',0,size(v_feature_test,2),size(v_feature_test,2));

我用第一个来训练分类器,第二个用来分类...

在我看来,缩放应该由以下人员执行:

即:

v_feature_trainN2=(v_feature_train -min(v_feature_train(:)))./(max(v_feature_train(:))-min((v_feature_train(:))));
v_feature_test_N2=(v_feature_test  -min(v_feature_train(:)))./(max(v_feature_train(:))-min((v_feature_train(:))));

现在我比较了使用这两种缩放方法的分类结果,第一种优于第二种。 问题是: 1)第一种方法到底是什么?我不明白。 2) 为什么 libsvm 建议的代码优于第二个(例如 80% vs 60%)? 提前非常感谢您

【问题讨论】:

  • 变量名能保持一致吗?第二个版本也可以使用data
  • Protip:你应该定义一个函数,而不是用稍微不同的变量名编写两次完全相同的代码。你甚至可以使用这样的匿名函数。 normalize = @(D) (D-min(D(:)))./(max(D(:))-min(D(:))); 然后使用:v_feature_trainN = normalize(v_feature_train)

标签: matlab scaling libsvm


【解决方案1】:

首先: libsvm 中描述的代码与您的代码不同:

它将每一列独立映射到区间[0,1]。 但是,您的代码使用全局 minmax 来映射所有列,使用相同的仿射变换,而不是为每列单独变换。


第一个代码的工作方式如下:

  • (data - repmat(min(data,[],1),size(data,1),1))
    这会从整列中减去每列的最小值。它通过计算最小值min(data,[],1) 的行向量来做到这一点,然后复制该行向量以构建与data 大小相同的矩阵。然后从data中减去。

  • spdiags(1./(max(data,[],1)-min(data,[],1))',0,size(data,2),size(data,2))
    这会生成一个对角矩阵。这个矩阵的条目(i,i)是1除以ith列的最大值和最小值之差:max(data(:,i))-min(data(:,i))

  • 这个对角矩阵的右乘表示:将左矩阵的每一列与对应的对角项相乘。这有效地将列 i 除以 max(data(:,i))-min(data(:,i))


您可以使用bsxfun 更有效地做到这一点,而不是使用稀疏对角矩阵:

bsxfun(@rdivide, ...
       bsxfun(@minus, ...
              data, min(data,[],1)), ...
       max(data,[],1)-min(data,[],1))

matlab的写法是什么:

  • 除法:
    • 的区别:
      • 每列及其各自的最小值
    • 每列的maxmin 的差异。

【讨论】:

  • @Kevin:我不知道您使用的算法是基于什么,因为您没有以任何方式提及它。因此,缩放整个矩阵与缩放单个列一样有意义。
  • 将每列按各自的最小值和最大值缩放是正确的方法,因为每个特征(列)都将跨越不同的值范围。假设您有两列:年龄和血压。年龄将跨越 18-80 的范围,但血压可能在 70 到 180 之间。此外,您必须考虑这些值将用于 SVM(即核函数)和某些指标(例如欧几里得)中的差异度量将在不同的范围内对不同的特征进行加权。这就是为什么每一列都必须在 [0;1] 范围内(即用其最小值-最大值进行归一化)
【解决方案2】:

我知道这已经得到了正确的回答,但我想提出另一种我认为也是正确的解决方案,我发现比 knedlsepp 提出的解决方案更直观/更短。我是 matlab 新手,在研究 knedlsepp 解决方案时,我发现使用以下公式解决这个问题更直观:

function [ output ] = feature_scaling( y)

output = (y - repmat(min(y),size(y,1),1)) * diag(1./(max(y) - min(y)));

end

我发现以这种方式使用 diag 而不是 spdiags 更容易一些,但我相信它会产生与本练习相同的结果。

将第一项乘以第二项,有效地将矩阵的每个成员 (Y-min(Y)) 除以标量值 1/(max(y)-min(y)),从而获得所需的结果。

如果有人喜欢更短的版本,也许这会有所帮助。

【讨论】:

    猜你喜欢
    • 2012-08-25
    • 1970-01-01
    • 2021-01-26
    • 2016-05-25
    • 2011-09-13
    • 1970-01-01
    • 2022-08-23
    • 1970-01-01
    • 2011-12-18
    相关资源
    最近更新 更多