2010-04-20 3 views
0

Я использую PYML для создания многоклассовой линейной векторной машины (SVM). После обучения SVM я хотел бы сохранить классификатор, чтобы на последующих запусках я мог сразу использовать классификатор без переподготовки. К сожалению, функция .save() не выполняется для этого классификатора, и пытается законсервировать его (как со стандартным рассолом и cPickle) дают следующее сообщение об ошибке:Сохранить объект PyML.classifiers.multi.OneAgainstRest (SVM())?

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

Кто-нибудь знает способ обойти это или альтернативной библиотеки без этой проблемы? Благодарю.

Edit/Update
Я сейчас обучение и попытки сохранить классификатор со следующим кодом:

 
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); 

Обратите внимание, что я теперь спасительной с PyML сохранить механизм, а не с травлением, и что я прошел «saveSpace = False» в функцию обучения. Тем не менее, я до сих пор gettting ошибку:

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

Однако я передаю saveSpace = False ... так, как я сохранить классификатор (ы)?

P.S.
Проект, в котором я использую это, - pyimgattr, в случае, если вам нужен полный тестовый пример ... программа запускается с «./pyimgattr.py train» ..., которая доставит вам эту ошибку. Кроме того, записка на информацию о версии:

 
[[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 

ответ

0

Получить новую версию PyML. Начиная с версии 0.7.4, можно сохранить классификатор OneAgainstRest (с .save() и .load()); до этой версии сохранение/загрузка классификатора является нетривиальным и подверженным ошибкам.

2

В multi.py на линии 96 «self.classifiers [я] .train (Datai)» вызывается без передачи «** арг», так что, если вы звоните msgstr "mc.train (data, saveSpace = False)", этот аргумент saveSpace теряется. Вот почему вы получаете сообщение об ошибке, если вы пытаетесь сохранить классификаторы в вашем мультиклассическом классификаторе отдельно. Но если вы измените эту строку, чтобы передать все аргументы, вы можете сохранить каждый классификатор по отдельности:

#!/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

@ephes, извините, не могли бы вы немного разъяснить? Что я должен пройти, чтобы тренироваться; saveSpace = True или saveSpace = False? Кроме того, как насчет загрузки классификаторов ... если я загружаю их по отдельности, как вы предлагаете, как вернуть их в один мультиклассический классификатор? –

+0

saveSpace = False (странные вещи ...) Абстракции PyMLs действительно просачиваются. Хорошо, я изменил исходный образец, чтобы перечитать модели и построить новый многоклассовый классификатор и пересчитать баллы для тестовых данных. – ephes

+0

Спасибо. Похоже, ваш OneAgainstRestFixed идентичен оригинальному OneAgainstRest, за исключением того, что вы используете «self.classifiers [i] .train (datai, ** args)», в то время как оригинал случайно отключает параметр «** args». Вещи сохраняются, но загрузка работает неправильно. Я создам для вас следующий вопрос. –