根据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%)? 非常感谢你提前
答案 0 :(得分:1)
首先:
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
答案 1 :(得分:0)
我知道这已经得到了正确回答,但我想提出另一个我认为也正确的解决方案,我发现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)),从而获得所需的结果。
如果有人喜欢较短的版本,也许这会有所帮助。