При работе с машинами опорных векторов очень важно нормализовать набор данных как этап предварительной обработки. Нормализация размещает атрибуты в одном масштабе и не позволяет атрибутам с большими значениями смещать результат.Это также улучшает числовую стабильность (сводит к минимуму вероятность переполнений и переполнений из-за представления с плавающей запятой).
Также, если быть точным, ваше вычисление ядра хи-квадрат немного отклонено.Вместо этого возьмите определение ниже и используйте для этого более быструю реализацию:
function D = chi2Kernel(X,Y)
D = zeros(size(X,1),size(Y,1));
for i=1:size(Y,1)
d = bsxfun(@minus, X, Y(i,:));
s = bsxfun(@plus, X, Y(i,:));
D(:,i) = sum(d.^2 ./ (s/2+eps), 2);
end
D = 1 - D;
end
Теперь рассмотрим следующий пример, использующий тот же набор данных, что и вы (код, адаптированный из предыдущий ответ моего):
%# read dataset
[label,data] = libsvmread('./heart_scale');
data = full(data); %# sparse to full
%# normalize data to [0,1] range
mn = min(data,[],1); mx = max(data,[],1);
data = bsxfun(@rdivide, bsxfun(@minus, data, mn), mx-mn);
%# split into train/test datasets
trainData = data(1:150,:); testData = data(151:270,:);
trainLabel = label(1:150,:); testLabel = label(151:270,:);
numTrain = size(trainData,1); numTest = size(testData,1);
%# compute kernel matrices between every pairs of (train,train) and
%# (test,train) instances and include sample serial number as first column
K = [ (1:numTrain)' , chi2Kernel(trainData,trainData) ];
KK = [ (1:numTest)' , chi2Kernel(testData,trainData) ];
%# view 'train vs. train' kernel matrix
figure, imagesc(K(:,2:end))
colormap(pink), colorbar
%# train model
model = svmtrain(trainLabel, K, '-t 4');
%# test on testing data
[predTestLabel, acc, decVals] = svmpredict(testLabel, KK, model);
cmTest = confusionmat(testLabel,predTestLabel)
%# test on training data
[predTrainLabel, acc, decVals] = svmpredict(trainLabel, K, model);
cmTrain = confusionmat(trainLabel,predTrainLabel)
Результат по данным тестирования:
Accuracy = 84.1667% (101/120) (classification)
cmTest =
62 8
11 39
и по данным обучения, мы получаем точность около 90%, как вы ожидали:
Accuracy = 92.6667% (139/150) (classification)
cmTrain =
77 3
8 62