2011-08-24 10 views
6

Próbuję libsvm i podążam za przykładem szkolenia svm na danych heart_scale, które są dostarczane wraz z oprogramowaniem. Chcę używać jądra chi2, które sam sobie komponuję. Klasyfikacja na danych treningowych spada do 24%. Jestem pewien, że poprawnie obliczyć jądro, ale chyba muszę zrobić coś złego. Kod znajduje się poniżej. Czy widzisz jakieś błędy? Pomoc byłaby bardzo ceniona.Zły wynik przy użyciu prekomputowanego jądra chi2 z libsvm (matlab)

%read in the data: 
[heart_scale_label, heart_scale_inst] = libsvmread('heart_scale'); 
train_data = heart_scale_inst(1:150,:); 
train_label = heart_scale_label(1:150,:); 

%read somewhere that the kernel should not be sparse 
ttrain = full(train_data)'; 
ttest = full(test_data)'; 

precKernel = chi2_custom(ttrain', ttrain'); 
model_precomputed = svmtrain2(train_label, [(1:150)', precKernel], '-t 4'); 

ten sposób jądro precomputed:

function res=chi2_custom(x,y) 
a=size(x); 
b=size(y); 
res = zeros(a(1,1), b(1,1)); 
for i=1:a(1,1) 
    for j=1:b(1,1) 
     resHelper = chi2_ireneHelper(x(i,:), y(j,:)); 
     res(i,j) = resHelper; 
    end 
end 
function resHelper = chi2_ireneHelper(x,y) 
a=(x-y).^2; 
b=(x+y); 
resHelper = sum(a./(b + eps)); 

Z innej implementacji SVM (vlfeat) ja uzyskania stawki zaszeregowania w danych treningowych (tak, przetestowany na danych treningowych, po prostu aby zobaczyć, co się dzieje) około 90%. Więc jestem całkiem pewny, że wynik libsvm jest błędny.

Odpowiedz

0

Problem jest następujący wiersz:

resHelper = sum(a./(b + eps)); 

powinno być:

resHelper = 1-sum(2*a./(b + eps)); 
+0

dzięki za odpowiedź na moje pytanie, właśnie teraz widział swoją odpowiedź. – Sallos

+0

@Sallos: chociaż twoja formuła była nieco wyłączona, prawdziwym problemem jest normalizacja danych .. Zobacz moją odpowiedź – Amro

15

Podczas pracy maszyn wektorów nośnych, to jest bardzo ważne, aby znormalizować zestaw danych jako etap wstępnego przetwarzania . Normalizacja umieszcza atrybuty na tej samej skali i zapobiega obciążaniu wyniku przez atrybuty z dużymi wartościami. Poprawia także stabilność numeryczną (minimalizuje prawdopodobieństwo przekroczenia i niedomiarów z powodu reprezentacji zmiennoprzecinkowej).

Dokładniej, twoje obliczenia jądra Chi-kwadrat są nieznacznie wyłączone. Zamiast przyjąć definicję poniżej i używać tej szybszą realizację dla niego:

chi_squared_kernel

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 

Teraz rozważmy następujący przykład za pomocą tego samego zestawu danych, jak (kod adaptacja previous answer kopalni):

%# 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) 

wynik na danych testowych:

Accuracy = 84.1667% (101/120) (classification) 
cmTest = 
    62  8 
    11 39 

i na danych treningowych, otrzymujemy dokładność około 90% zgodnie z oczekiwaniami:

Accuracy = 92.6667% (139/150) (classification) 
cmTrain = 
    77  3 
    8 62 

train_train_kernel_matrix

+1

oh, cool - to jest szczegółowa odpowiedź. Dziękuję za poświęcenie czasu na przemyślenie mojego problemu. To na pewno pomogło. – Sallos

+2

@Sallos: cieszę się, że mogę pomóc, proszę rozważyć [przyjęcie] (http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) odpowiedzi, jeśli rozwiąże ona problem – Amro

Powiązane problemy