spdiags 和功能缩放
spdiags and features scaling
根据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% 对 60%)?
非常感谢你
首先:
libsvm
中描述的代码与您的代码有所不同:
它将每一列独立映射到区间[0,1]
。
但是,您的代码使用全局 min
和 max
来映射所有列,使用相同的仿射变换而不是对每一列进行单独的变换。
第一个代码按以下方式工作:
(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 除以第 i
列的最大值与最小值之差: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的写法是这样的:
- 划分:
- 区别在于:
- 每列及其各自的最小值
- 每列的
max
和min
的差值。
我知道这个问题已经得到正确回答,但我想提出另一种我认为也是正确的解决方案,而且我发现 intuitive/shorther 比 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)),获得所需结果.
如果有人喜欢较短的版本,也许这会有所帮助。
根据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% 对 60%)? 非常感谢你
首先:
libsvm
中描述的代码与您的代码有所不同:
它将每一列独立映射到区间[0,1]
。
但是,您的代码使用全局 min
和 max
来映射所有列,使用相同的仿射变换而不是对每一列进行单独的变换。
第一个代码按以下方式工作:
(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 除以第i
列的最大值与最小值之差: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的写法是这样的:
- 划分:
- 区别在于:
- 每列及其各自的最小值
- 每列的
max
和min
的差值。
- 区别在于:
我知道这个问题已经得到正确回答,但我想提出另一种我认为也是正确的解决方案,而且我发现 intuitive/shorther 比 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)),获得所需结果.
如果有人喜欢较短的版本,也许这会有所帮助。