2010-04-20 27 views
0

J'utilise PYML pour construire une machine de vecteur de support linéaire multicouche (SVM). Après l'entraînement du SVM, j'aimerais pouvoir sauvegarder le classifieur, de sorte que lors des courses suivantes, je puisse utiliser le classificateur tout de suite sans rééducation. Malheureusement, la fonction .save() ne sont pas mis en œuvre pour ce classificateur, et tenter de le décaper (à la fois avec cornichon standard et cPickle) donnent le message d'erreur suivant:Enregistrer l'objet PyML.classifiers.multi.OneAgainstRest (SVM())?

 
pickle.PicklingError: Can't pickle : it's not found as __builtin__.PySwigObject 

Est-ce que quelqu'un sait d'une façon de contourner cela ou d'une bibliothèque alternative sans ce problème? Merci.

Modifier/Mettre à jour
Je suis maintenant la formation et de tenter de sauver le classificateur avec le code suivant:

 
mc = multi.OneAgainstRest(SVM()); 
mc.train(dataset_pyml,saveSpace=False); 
    for i, classifier in enumerate(mc.classifiers): 
     filename=os.path.join(prefix,labels[i]+".svm"); 
     classifier.save(filename); 

Notez que je suis en train gardais avec le mécanisme PyML sauver plutôt que de décapage et que j'ai passé "saveSpace = False" à la fonction d'entraînement. Cependant, je suis gettting encore une erreur:

 
ValueError: in order to save a dataset you need to train as: s.train(data, saveSpace = False) 

Cependant, je passe saveSpace = Faux ... Alors, comment puis-je enregistrer le classificateur (s)?

P.S.
Le projet dans lequel j'utilise ceci est pyimgattr, au cas où vous voudriez un exemple complet testable ... le programme est exécuté avec "./pyimgattr.py train" ... qui vous obtiendra cette erreur. En outre, une note sur les informations de version:

 
[[email protected] /Volumes/Storage/classes/cse559/pyimgattr]$ python 
Python 2.6.1 (r261:67515, Feb 11 2010, 00:51:29) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import PyML 
>>> print PyML.__version__ 
0.7.0 

Répondre

0

obtenir une version plus récente de PyML. Depuis la version 0.7.4, il est possible de sauvegarder le classificateur OneAgainstRest (avec .save() et .load()); avant cette version, enregistrer/charger le classificateur est non trivial et sujet aux erreurs.

2

Dans multi.py en ligne 96 "self.classifiers [i] .train (datai)" est appelée sans passer "** args", de sorte que si vous appelez "mc.train (data, saveSpace = False)", cet argument saveSpace est perdu. C'est pourquoi vous obtenez un message d'erreur si vous essayez d'enregistrer les classificateurs dans votre classificateur multiclass individuellement. Mais si vous changez cette ligne pour passer tous les arguments, vous pouvez enregistrer chaque classificateur individuellement:

#!/usr/bin/python 

import numpy 

from PyML.utils import misc 
from PyML.evaluators import assess 
from PyML.classifiers.svm import SVM, loadSVM 
from PyML.containers.labels import oneAgainstRest 
from PyML.classifiers.baseClassifiers import Classifier 
from PyML.containers.vectorDatasets import SparseDataSet 
from PyML.classifiers.composite import CompositeClassifier 

class OneAgainstRestFixed(CompositeClassifier) : 

    '''A one-against-the-rest multi-class classifier''' 

    def train(self, data, **args) : 
     '''train k classifiers''' 

     Classifier.train(self, data, **args) 

     numClasses = self.labels.numClasses 
     if numClasses <= 2: 
      raise ValueError, 'Not a multi class problem' 

     self.classifiers = [self.classifier.__class__(self.classifier) 
          for i in range(numClasses)] 

     for i in range(numClasses) : 
      # make a copy of the data; this is done in case the classifier modifies the data 
      datai = data.__class__(data, deepcopy = self.classifier.deepcopy) 
      datai = oneAgainstRest(datai, data.labels.classLabels[i]) 

      self.classifiers[i].train(datai, **args) 

     self.log.trainingTime = self.getTrainingTime() 

    def classify(self, data, i): 

     r = numpy.zeros(self.labels.numClasses, numpy.float_) 
     for j in range(self.labels.numClasses) : 
      r[j] = self.classifiers[j].decisionFunc(data, i) 

     return numpy.argmax(r), numpy.max(r) 

    def preproject(self, data) : 

     for i in range(self.labels.numClasses) : 
      self.classifiers[i].preproject(data) 

    test = assess.test 

train_data = """ 
0 1:1.0 2:0.0 3:0.0 4:0.0 
0 1:0.9 2:0.0 3:0.0 4:0.0 
1 1:0.0 2:1.0 3:0.0 4:0.0 
1 1:0.0 2:0.8 3:0.0 4:0.0 
2 1:0.0 2:0.0 3:1.0 4:0.0 
2 1:0.0 2:0.0 3:0.9 4:0.0 
3 1:0.0 2:0.0 3:0.0 4:1.0 
3 1:0.0 2:0.0 3:0.0 4:0.9 
""" 
file("foo_train.data", "w").write(train_data.lstrip()) 

test_data = """ 
0 1:1.1 2:0.0 3:0.0 4:0.0 
1 1:0.0 2:1.2 3:0.0 4:0.0 
2 1:0.0 2:0.0 3:0.6 4:0.0 
3 1:0.0 2:0.0 3:0.0 4:1.4 
""" 
file("foo_test.data", "w").write(test_data.lstrip()) 

train = SparseDataSet("foo_train.data") 
mc = OneAgainstRestFixed(SVM()) 
mc.train(train, saveSpace=False) 

test = SparseDataSet("foo_test.data") 
print [mc.classify(test, i) for i in range(4)] 

for i, classifier in enumerate(mc.classifiers): 
    classifier.save("foo.model.%d" % i) 

classifiers = [] 
for i in range(4): 
    classifiers.append(loadSVM("foo.model.%d" % i)) 

mcnew = OneAgainstRestFixed(SVM()) 
mcnew.labels = misc.Container() 
mcnew.labels.addAttributes(test.labels, ['numClasses', 'classLabels']) 
mcnew.classifiers = classifiers 
print [mcnew.classify(test, i) for i in range(4)] 
+0

@phes, je suis désolé, pourriez-vous clarifier un peu? Que devrais-je passer pour m'entraîner? saveSpace = True ou saveSpace = False? En outre, qu'en est-il du chargement des classificateurs ... si je les charge individuellement comme vous le suggérez, comment les remettre dans le classificateur multiclasse unique? –

+0

saveSpace = Faux (trucs bizarres ...) Les abstractions PyMLs ont vraiment des fuites. Ok, j'ai changé l'exemple de source pour relire les modèles et construire un nouveau classificateur multiclass et recalculer les scores pour les données de test. – ephes

+0

Merci. Il semble que votre OneAgainstRestFixed soit identique à OneAgainstRest d'origine, sauf que vous utilisez "self.classifiers [i] .train (datai, ** args)" alors que l'original omet accidentellement le paramètre "** args". Les choses économisent maintenant, mais le chargement ne fonctionne pas correctement. Je vais créer une question de suivi pour cela. –