2017-07-12 15 views
5

मैंने scikit-learn मॉडल बनाया और मैं एक दैनिक पायथन क्रॉन जॉब (एनबी में पुन: उपयोग करना चाहता हूं: कोई अन्य प्लेटफार्म शामिल नहीं है - कोई आर, कोई जावा & सी)।scikit- सीखने मॉडल दृढ़ता: अचार बनाम pmml बनाम ...?

मैं pickled (वास्तव में, मैंने अपना खुद का ऑब्जेक्ट उठाया जिसका एक क्षेत्र GradientBoostingClassifier है), और मैं इसे क्रॉन नौकरी में अन-पिकल करता हूं। अब तक बहुत अच्छा है (और Save classifier to disk in scikit-learn और Model persistence in Scikit-Learn? में चर्चा की गई है)।

हालांकि, मैं sklearn उन्नत बनाया है और अब मैं इन चेतावनियों मिलती है:

.../.local/lib/python2.7/site-packages/sklearn/base.py:315: 
UserWarning: Trying to unpickle estimator DecisionTreeRegressor from version 0.18.1 when using version 0.18.2. This might lead to breaking code or invalid results. Use at your own risk. 
UserWarning) 
.../.local/lib/python2.7/site-packages/sklearn/base.py:315: 
UserWarning: Trying to unpickle estimator PriorProbabilityEstimator from version 0.18.1 when using version 0.18.2. This might lead to breaking code or invalid results. Use at your own risk. 
UserWarning) 
.../.local/lib/python2.7/site-packages/sklearn/base.py:315: 
UserWarning: Trying to unpickle estimator GradientBoostingClassifier from version 0.18.1 when using version 0.18.2. This might lead to breaking code or invalid results. Use at your own risk. 
UserWarning) 

अब मुझे क्या करना चाहिए?

  • मैं 0.18.1 को downgrage और इसके साथ छड़ी जब तक मैं मॉडल के पुनर्निर्माण के लिए तैयार हूँ कर सकते हैं। विभिन्न कारणों से मुझे यह अस्वीकार्य लगता है।

  • मैं फ़ाइल को अनदेखा कर सकता हूं और इसे फिर से उठा सकता हूं। यह 0.18.2 के साथ काम किया, लेकिन 0.19 के साथ टूटता है। NFG। joblib कोई बेहतर नहीं दिखता है।

  • मेरी इच्छा है कि मैं डेटा को एक संस्करण-स्वतंत्र ASCII प्रारूप (उदा।, JSON या XML) में सहेज सकूं। यह स्पष्ट रूप से इष्टतम समाधान है, लेकिन ऐसा करने के लिए NO ऐसा लगता है (Sklearn - model persistence without pkl file भी देखें)।

  • मैं PMML के मॉडल को बचा सकता है, लेकिन इसके समर्थन गुनगुना है पर सबसे अच्छा: मैं मॉडल बचाने को sklearn2pmml उपयोग कर सकते हैं (हालांकि नहीं आसानी से), और augustus/lightpmmlpredictorपर लागू होते हैं (नहीं हालांकि भार) मॉडल। हालांकि, उनमें से कोई भी pip पर सीधे उपलब्ध नहीं है, जो तैनाती को एक दुःस्वप्न बनाता है। इसके अलावा, augustus & lightpmmlpredictor परियोजनाएं मरने लगती हैं। Importing PMML models into Python (Scikit-learn) - नहीं।

  • उपर्युक्त का एक संस्करण: sklearn2pmml का उपयोग करके पीएमएमएल को सहेजें, और स्कोरिंग के लिए openscoring का उपयोग करें। बाहरी प्रक्रिया के साथ इंटरफेसिंग की आवश्यकता है। युक।

सुझाव?

उत्तर

2

विज्ञान-शिक्षा के विभिन्न संस्करणों में मॉडल दृढ़ता आम तौर पर असंभव है। कारण स्पष्ट है: आप एक परिभाषा के साथ Class1 उठाते हैं, और इसे अन्य परिभाषा के साथ Class2 में अनपिक करना चाहते हैं।

आप कर सकते हैं:

  • फिर भी sklearn में से एक संस्करण के लिए छड़ी की कोशिश करो।
  • चेतावनियों को अनदेखा करें और आशा करें कि Class1 के लिए क्या काम किया गया Class2 के लिए भी काम करेगा।
  • अपनी खुद की कक्षा लिखें जो आपके GradientBoostingClassifier को क्रमबद्ध कर सकती है और इसे इस धारावाहिक रूप से पुनर्स्थापित कर सकती है, और उम्मीद है कि यह अचार की तुलना में बेहतर काम करेगी।

मैं कैसे आप एक शुद्ध सूची और dict प्रारूप, पूरी तरह से JSON-संगत में एक भी DecisionTreeRegressor में बदल सकते हैं, और इसे वापस बहाल करने का एक उदाहरण बना दिया।

import numpy as np 
from sklearn.tree import DecisionTreeRegressor 
from sklearn.datasets import make_classification 

### Code to serialize and deserialize trees 

LEAF_ATTRIBUTES = ['children_left', 'children_right', 'threshold', 'value', 'feature', 'impurity', 'weighted_n_node_samples'] 
TREE_ATTRIBUTES = ['n_classes_', 'n_features_', 'n_outputs_'] 

def serialize_tree(tree): 
    """ Convert a sklearn.tree.DecisionTreeRegressor into a json-compatible format """ 
    encoded = { 
     'nodes': {}, 
     'tree': {}, 
     'n_leaves': len(tree.tree_.threshold), 
     'params': tree.get_params() 
    } 
    for attr in LEAF_ATTRIBUTES: 
     encoded['nodes'][attr] = getattr(tree.tree_, attr).tolist() 
    for attr in TREE_ATTRIBUTES: 
     encoded['tree'][attr] = getattr(tree, attr) 
    return encoded 

def deserialize_tree(encoded): 
    """ Restore a sklearn.tree.DecisionTreeRegressor from a json-compatible format """ 
    x = np.arange(encoded['n_leaves']) 
    tree = DecisionTreeRegressor().fit(x.reshape((-1,1)), x) 
    tree.set_params(**encoded['params']) 
    for attr in LEAF_ATTRIBUTES: 
     for i in range(encoded['n_leaves']): 
      getattr(tree.tree_, attr)[i] = encoded['nodes'][attr][i] 
    for attr in TREE_ATTRIBUTES: 
     setattr(tree, attr, encoded['tree'][attr]) 
    return tree 

## test the code 

X, y = make_classification(n_classes=3, n_informative=10) 
tree = DecisionTreeRegressor().fit(X, y) 
encoded = serialize_tree(tree) 
decoded = deserialize_tree(encoded) 
assert (decoded.predict(X)==tree.predict(X)).all() 

इस के बाद, आप को क्रमानुसार करने पर जाने के लिए और deserialize कर सकते हैं पूरे GradientBoostingClassifier:

from sklearn.ensemble import GradientBoostingClassifier 
from sklearn.ensemble.gradient_boosting import PriorProbabilityEstimator 

def serialize_gbc(clf): 
    encoded = { 
     'classes_': clf.classes_.tolist(), 
     'max_features_': clf.max_features_, 
     'n_classes_': clf.n_classes_, 
     'n_features_': clf.n_features_, 
     'train_score_': clf.train_score_.tolist(), 
     'params': clf.get_params(), 
     'estimators_shape': list(clf.estimators_.shape), 
     'estimators': [], 
     'priors':clf.init_.priors.tolist() 
    } 
    for tree in clf.estimators_.reshape((-1,)): 
     encoded['estimators'].append(serialize_tree(tree)) 
    return encoded 

def deserialize_gbc(encoded): 
    x = np.array(encoded['classes_']) 
    clf = GradientBoostingClassifier(**encoded['params']).fit(x.reshape(-1, 1), x) 
    trees = [deserialize_tree(tree) for tree in encoded['estimators']] 
    clf.estimators_ = np.array(trees).reshape(encoded['estimators_shape']) 
    clf.init_ = PriorProbabilityEstimator() 
    clf.init_.priors = np.array(encoded['priors']) 
    clf.classes_ = np.array(encoded['classes_']) 
    clf.train_score_ = np.array(encoded['train_score_']) 
    clf.max_features_ = encoded['max_features_'] 
    clf.n_classes_ = encoded['n_classes_'] 
    clf.n_features_ = encoded['n_features_'] 
    return clf 

# test on the same problem 
clf = GradientBoostingClassifier() 
clf.fit(X, y); 
encoded = serialize_gbc(clf) 
decoded = deserialize_gbc(encoded) 
assert (decoded.predict(X) == clf.predict(X)).all() 

यह scikit सीखने v0.19 के लिए काम करता है, लेकिन मुझसे पूछते हैं कि क्या में आ जाएगा इस कोड को तोड़ने के लिए अगले संस्करण। मैं न तो एक नबी हूं और न ही sklearn के डेवलपर हूँ।

यदि आप sklearn के नए संस्करणों से पूरी तरह से स्वतंत्र होना चाहते हैं, तो सबसे सुरक्षित बात यह है कि एक धारावाहिक पेड़ का पता चलता है और एक स्केलेर्न पेड़ को फिर से बनाने के बजाय भविष्यवाणी करता है।

+0

यह अचार की तुलना में अधिक विश्वसनीय कैसे है? अचार के साथ समस्या यह है कि यदि 'sklearn' कक्षा परिभाषा को बदलता है (उदाहरण के लिए, स्लॉट ड्रॉप या नाम बदलता है), तो मुझे 'serialize_ *' और 'deserialize_ *' फ़ंक्शन को फिर से लिखना होगा और, अधिक महत्वपूर्ण, deserializer लिखना होगा जो परिवर्तित करता है _old_ संस्करण के _old_ संस्करण में serialization। मैं मानता हूं कि यह शायद अचार दुःस्वप्न से बेहतर है, लेकिन शायद ही कभी। – sds

+0

यह गारंटी नहीं दे सकता कि आप sklearn के 20, या 200 संस्करण के साथ संगत होंगे। लेकिन यह कम से कम आपको स्थिति पर अधिक नियंत्रण देता है। जैसे यदि sklearn पूरी तरह से अपने '' वर्गीकरण लॉस फ़ंक्शन'' को फिर से लिखता है, तो आप प्रभावित नहीं होंगे। –

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