对于LIBSVM的测试数据缩放:MATLAB实现

10

我目前使用MATLAB版本的LIBSVM支持向量机对我的数据进行分类。 LIBSVM文档提到,在应用SVM之前进行缩放非常重要,我们必须使用相同的方法来缩放训练和测试数据。

“相同的缩放方法”解释如下: 例如,假设我们将训练数据的第一个属性从 [-10,+10] 缩放到 [-1,+ 1]。如果测试数据的第一个属性在范围 [-11,+8] 内,则必须将测试数据缩放为 [-1.1,+0.8]

可以使用以下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))

但是我不知道如何正确地缩放测试数据。

非常感谢您的帮助。


我的问题是,如果训练数据在[a,b]范围内进行归一化到[0,1]的范围,那么测试数据在[c,d]范围内应该归一化到哪个范围? - Lily
2个回答

16

你提供的代码本质上是减去最小值再除以范围。 你需要存储训练数据特征的最小值和范围。

minimums = min(data, [], 1);
ranges = max(data, [], 1) - minimums;

data = (data - repmat(minimums, size(data, 1), 1)) ./ repmat(ranges, size(data, 1), 1);

test_data = (test_data - repmat(minimums, size(test_data, 1), 1)) ./ repmat(ranges, size(test_data, 1), 1);

@Richante:您的回答非常有用。我只想澄清一下,“data”在这里是指训练数据,“test_data”是指测试数据吗? - Sid
很抱歉,您的代码将会在所有观测值都相同时输出 NaN(如果您的数据是稀疏的话可能会发生这种情况)。例如,数据 = [1 2 3; 5 2 8; 7 2 100]。 - Dang Manh Truong

0

很不幸,Richante的代码在存在所有观测值都相同的列(如果数据稀疏可能会发生)时是不正确的。一个例子:

>> data = [1 2 3; 5 2 8; 7 2 100]

data =

     1     2     3
     5     2     8
     7     2   100

>> test_data = [1 2 3; 4 5 6; 7 8 9];
>> minimums = min(data,[],1);
>> ranges = max(data, [], 1) - minimums;
>> data = (data - repmat(minimums, size(data, 1), 1)) ./ repmat(ranges, size(data, 1), 1);
>> data

data =

         0       NaN         0
    0.6667       NaN    0.0515
    1.0000       NaN    1.0000

因此,您必须检查是否存在仅具有一个单一值的列。但是,如果整个训练集中只有一个单一值,而测试集中有几个值呢?在留一法的情况下,如果测试集中只有一个观察值,那么如果训练集中某一列的所有值都为0,并且测试集中相应的值为100,我们该怎么办?这些确实是退化的情况,但可能会发生。然而,当我检查Libsvm库中的svm_scale.c文件时,我注意到了这部分内容:

 void output(int index, double value)
{
    /* skip single-valued attribute */
    if(feature_max[index] == feature_min[index])
        return;

    if(value == feature_min[index])
        value = lower;
    else if(value == feature_max[index])
        value = upper;
    else
        value = lower + (upper-lower) * 
            (value-feature_min[index])/
            (feature_max[index]-feature_min[index]);

    if(value != 0)
    {
        printf("%d:%g ",index, value);
        new_num_nonzeros++;
    }
}

那么我们应该忽略这些情况吗?我不是很确定。正如我所说,我对这个问题并不是权威,所以我会等待另一个答案,最好是来自Libsvm的作者本人,以澄清事情......


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接