LibSVM

6

के साथ मीन/स्टडीडेव जोयर में निकटतम मिलान की गणना करना मैं एसवीएम के लिए नया हूं, और मैं पाइथन इंटरफ़ेस का उपयोग libsvm पर एक नमूना और stddev युक्त नमूना वर्गीकृत करने का प्रयास कर रहा हूं। हालांकि, मुझे बकवास परिणाम मिल रहे हैं।LibSVM

क्या यह कार्य SVMs के लिए अनुचित है या libsvm के उपयोग में कोई त्रुटि है? नीचे परीक्षण करने के लिए उपयोग की जा रही सरल पायथन लिपि है:

#!/usr/bin/env python 
# Simple classifier test. 
# Adapted from the svm_test.py file included in the standard libsvm distribution. 
from collections import defaultdict 
from svm import * 
# Define our sparse data formatted training and testing sets. 
labels = [1,2,3,4] 
train = [ # key: 0=mean, 1=stddev 
    {0:2.5,1:3.5}, 
    {0:5,1:1.2}, 
    {0:7,1:3.3}, 
    {0:10.3,1:0.3}, 
] 
problem = svm_problem(labels, train) 
test = [ 
    ({0:3, 1:3.11},1), 
    ({0:7.3,1:3.1},3), 
    ({0:7,1:3.3},3), 
    ({0:9.8,1:0.5},4), 
] 

# Test classifiers. 
kernels = [LINEAR, POLY, RBF] 
kname = ['linear','polynomial','rbf'] 
correct = defaultdict(int) 
for kn,kt in zip(kname,kernels): 
    print kt 
    param = svm_parameter(kernel_type = kt, C=10, probability = 1) 
    model = svm_model(problem, param) 
    for test_sample,correct_label in test: 
     pred_label, pred_probability = model.predict_probability(test_sample) 
     correct[kn] += pred_label == correct_label 

# Show results. 
print '-'*80 
print 'Accuracy:' 
for kn,correct_count in correct.iteritems(): 
    print '\t',kn, '%.6f (%i of %i)' % (correct_count/float(len(test)), correct_count, len(test)) 

डोमेन काफी सरल लगता है। मैं उम्मीद करता हूं कि अगर इसे 2.5 का मतलब है लेबल 1 का मतलब जानने के लिए प्रशिक्षित किया गया है, तो जब यह 2.4 का मतलब देखता है, तो उसे सबसे अधिक वर्गीकृत वर्गीकरण के रूप में लेबल 1 वापस करना चाहिए। हालांकि, प्रत्येक कर्नेल में 0% की शुद्धता होती है। ऐसा क्यों है?

कुछ पक्ष नोट्स, टर्मिनल में libsvm द्वारा छोड़े गए सभी वर्बोज़ प्रशिक्षण आउटपुट को छिपाने का कोई तरीका है? मैंने libsvm के दस्तावेज़ और कोड की खोज की है, लेकिन मुझे इसे बंद करने का कोई तरीका नहीं मिल रहा है।

इसके अलावा, मैं अपने स्पैस डेटासेट (जैसे {'mean': 2.5, 'stddev': 3.5}) में चाबियों के रूप में सरल तारों का उपयोग करना चाहता था। दुर्भाग्यवश, libsvm केवल पूर्णांक का समर्थन करता है। मैंने स्ट्रिंग के लंबे पूर्णांक प्रतिनिधित्व का उपयोग करने की कोशिश की (उदा। 'माध्य' == 110 9110110971110), लेकिन libsvm सामान्य 32-बिट पूर्णांक में इसे छोटा कर देता है। एकमात्र कामकाज जो मैं देखता हूं वह एक अलग "कुंजी" फ़ाइल को बनाए रखना है जो प्रत्येक स्ट्रिंग को एक पूर्णांक ('mean' = 0, 'stddev' = 1) पर मैप करता है। लेकिन जाहिर है कि यह दर्द होगा क्योंकि मुझे धारावाहिक वर्गीकृत के साथ दूसरी फ़ाइल को बनाए रखना और जारी रखना होगा। क्या कोई आसान तरीका देखता है?

+0

आपका कोड काम करता प्रतीत होता है, यदि आप संभाव्यता अनुमान हटाते हैं (यानी, "संभावना = 1" हटाएं, predict_probability को केवल पूर्वानुमानित करने के लिए बदलें, और pred_probability को हटाएं)। – dmcer

+0

@ डमसर, शानदार। इसके विपरीत, ऐसा प्रतीत होता है कि जब तक मेरे पास प्रत्येक लेबल के लिए कम से कम दो नमूने हैं, तब तक मैं संभाव्यता अनुमान रख सकता हूं। अजीब यह प्रति लेबल सिर्फ एक नमूना के लिए काम नहीं करेगा। यदि आप अपनी टिप्पणी को उत्तर के रूप में पोस्ट करते हैं, तो मैं इसे स्वीकृत उत्तर के रूप में चिह्नित करूंगा। – Cerin

उत्तर

5

समस्या संभाव्यता अनुमानों के साथ मल्टीक्लास पूर्वानुमान के संयोजन से आ रही है।

यदि आप अपने कोड को कॉन्फ़िगरेशन अनुमान बनाने के लिए कॉन्फ़िगर नहीं करते हैं, तो यह वास्तव में काम करता है, उदाहरण के लिए:

<snip> 
# Test classifiers. 
kernels = [LINEAR, POLY, RBF] 
kname = ['linear','polynomial','rbf'] 
correct = defaultdict(int) 
for kn,kt in zip(kname,kernels): 
    print kt 
    param = svm_parameter(kernel_type = kt, C=10) # Here -> rm probability = 1 
    model = svm_model(problem, param) 
    for test_sample,correct_label in test: 
     # Here -> change predict_probability to just predict 
     pred_label = model.predict(test_sample) 
     correct[kn] += pred_label == correct_label 
</snip> 

इस बदलाव के साथ, मैं मिलता है:

-------------------------------------------------------------------------------- 
Accuracy: 
     polynomial 1.000000 (4 of 4) 
     rbf 1.000000 (4 of 4) 
     linear 1.000000 (4 of 4) 

संभावना अनुमान के साथ भविष्यवाणी, काम करता है अगर आप प्रशिक्षण में डेटा को दोगुना सेट (यानी, शामिल प्रत्येक डेटा दो बार बात) । हालांकि, मैं मॉडल को पैरामीट्रिज करने के लिए वैसे भी नहीं ढूंढ पाया, ताकि संभावनाओं के साथ मल्टीक्लास भविष्यवाणी केवल मूल चार प्रशिक्षण बिंदुओं के साथ काम करेगी।

3

यदि आप ऐसा करने के एक अलग तरीके से रुचि रखते हैं, तो आप निम्न कार्य कर सकते हैं। इस तरह सैद्धांतिक रूप से अधिक ध्वनि है, हालांकि सीधा नहीं है।

माध्य और std का उल्लेख करके, ऐसा लगता है कि आप उस डेटा को संदर्भित करते हैं जिसे आप किसी भी तरीके से वितरित करने के लिए मानते हैं। उदा।, आपके द्वारा पर्यवेक्षक डेटा गॉसियन वितरित किया जाता है। फिर आप उन वितरणों के बीच दूरी माप के रूप में Symmetrised Kullback-Leibler_divergence का उपयोग कर सकते हैं। इसके बाद आप वर्गीकरण के लिए जैसे कुछ का उपयोग कर सकते हैं।

दो संभाव्यता घनत्व पी और क्यू के लिए, आपके पास केवल केएल (पी, क्यू) = 0 है यदि पी और क्यू समान हैं। हालांकि, केएल सममित नहीं है - तो आदेश में एक उचित दूरी को मापने के लिए, आप

दूरी (P1, P2) = केएल (P1, P2) + केएल (P1, P2)

उपयोग कर सकते हैं Gaussians के लिए , केएल (पी 1, पी 2) = {(μ1 - μ2)^2 + σ1^2 - σ2^2}/(2.σ2^2) + एलएन (σ2/σ1)। (मैं चुरा लिया कि here है, जहां आप भी एक विचलन :)

लंबी कहानी कम मिल सकता है से:

(मतलब है, एसटीडी, वर्ग) tuples के प्रशिक्षण सेट डी और एक नया पी = देखते हुए (मतलब है, std) जोड़ी, उस क्यू में डी को ढूंढें जिसके लिए दूरी (डी, पी) न्यूनतम है और उस वर्ग को वापस कर दें।

मेरे लिए जो कई कर्नेल के साथ एसवीएम दृष्टिकोण के रूप में बेहतर महसूस करता है, क्योंकि वर्गीकरण के तरीके इतने मनमानी नहीं हैं।

+0

धन्यवाद। मैंने सोचा कि शायद सामान्य/गाऊसी वितरण के लिए एसवीएम से कुछ बेहतर था। हालांकि, मैं इन मनोवैज्ञानिक सुविधाओं को अन्य मनमानी विशेषताओं के साथ शामिल करना चाहता हूं, इसलिए एक विशेष दूरी माप का उपयोग करके के-एनएन उपयुक्त नहीं होगा। – Cerin

+0

कक्षा लेबल से ऐसे दूरी उपायों को सीखने के वास्तव में तरीके हैं। शायद आप नेबरहुड घटक विश्लेषण पर सैम रोवेस के काम की जांच करना चाहते हैं। – bayer

संबंधित मुद्दे