[英]bad result when using precomputed chi2 kernel with libsvm (matlab)
我正在嘗試libsvm,並按照該示例在軟件隨附的heart_scale數據上訓練svm。 我想使用我自己預先計算的chi2內核。 訓練數據的分類率降至24%。 我確定我正確地計算了內核,但是我想我一定做錯了。 代碼如下。 你能看到任何錯誤嗎? 幫助將不勝感激。
%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');
這是內核的預先計算方式:
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));
使用不同的svm實現(vlfeat),我獲得了大約90%的訓練數據分類率(是的,我對訓練數據進行了測試,只是為了查看發生了什么)。 所以我很確定libsvm結果是錯誤的。
在使用支持向量機時,將數據集規范化為預處理步驟非常重要。 規范化將屬性置於相同的比例,並防止具有較大值的屬性對結果造成偏倚。 它還提高了數值穩定性(最大程度地減少了由於浮點表示而引起的上溢和下溢的可能性)。
同樣准確地說,您對卡方內核的計算略有偏差。 相反,請采用以下定義,並對其使用以下更快的實現:
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
問題是以下行:
resHelper = sum(a./(b + eps));
它應該是:
resHelper = 1-sum(2*a./(b + eps));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.