29

すべての依存関係 (コード + データ) がアーティファクトにパッケージ化され、このアーティファクトを使用してモデルを初期化し、予測できるように、scikit-learn/statsmodels モデルをシリアル化する必要があります。pickle の使用はmoduleオプションではありません。これは、データの依存関係のみを処理するためです (コードはパッケージ化されません)。ということで、ディルで実験をしてきました。私の質問をより正確にするために、モデルを構築して永続化する例を次に示します。

from sklearn import datasets
from sklearn import svm
from sklearn.preprocessing import Normalizer
import dill

digits = datasets.load_digits()
training_data_X = digits.data[:-5]
training_data_Y = digits.target[:-5]
test_data_X = digits.data[-5:]
test_data_Y = digits.target[-5:]

class Model:
    def __init__(self):
        self.normalizer = Normalizer()
        self.clf = svm.SVC(gamma=0.001, C=100.)
    def train(self, training_data_X, training_data_Y):
        normalised_training_data_X = normalizer.fit_transform(training_data_X)
        self.clf.fit(normalised_training_data_X, training_data_Y)
    def predict(self, test_data_X):
        return self.clf.predict(self.normalizer.fit_transform(test_data_X))  

model = Model()
model.train(training_data_X, training_data_Y)
print model.predict(test_data_X)
dill.dump(model, open("my_model.dill", 'w'))

これに対応して、永続化されたモデルを (新しいセッションで) 初期化し、予測を行う方法を次に示します。このコードは明示的に初期化したり、class Model.

import dill
from sklearn import datasets

digits = datasets.load_digits()
training_data_X = digits.data[:-5]
training_data_Y = digits.target[:-5]
test_data_X = digits.data[-5:]
test_data_Y = digits.target[-5:]

with open("my_model.dill") as model_file:
    model = dill.load(model_file)

print model.predict(test_data_X)

このようにディルを使った人はいますか?データ サイエンティストがModelWrapper class実装する各モデルを拡張し、モデルを永続化するインフラストラクチャを構築し、モデルをサービスとして展開し、モデルのライフサイクル全体を管理するという考え方です。

class ModelWrapper(object):
    __metaclass__ = abc.ABCMeta
    def __init__(self, model):
        self.model = model
    @abc.abstractmethod
    def predict(self, input):
        return
    def dumps(self):
        return dill.dumps(self)
    def loads(self, model_string):
        self.model = dill.loads(model_string)

セキュリティへの影響 (任意のコードの実行) とscikit-learn、モデルを提供するマシンにモジュールをインストールする必要があるという要件以外に、このアプローチには落とし穴がありますか? コメントやアドバイスの言葉は最も役に立ちます。

YHatDatoは同様のアプローチを取っていると思いますが、同様の目的で独自の Dill の実装を展開しています。

4

3 に答える 3

39

私はdill著者です。 dillあなたがしていることを正確に行うために構築されました…(統計のためにクラスインスタンス内の数値適合を維持するため)これらのオブジェクトは異なるリソースに分散され、恥ずかしいほど並列に実行されます。したがって、答えはイエスです。 mysticand/orを使用して、あなたのようなコードを実行しsklearnました。

の作成者の多くは、オブジェクトの並列計算を有効にするためにsklearn使用し、 . よりも多くのタイプのオブジェクトをピクルできますが、クロージャの一部としてグローバル ディクショナリへの参照を作成するオブジェクトをピクルする場合は(この記事の執筆時点では) わずかに優れています。ただし、のように動作するモードがあるため、このモードを使用する場合の違いはわずかです。(モードを有効にするには、 を実行するか、 のフラグとして使用します)。もう 1 つの小さな違いは、 や などの特別なサポートが含まれていることです。cloudpicklesklearndilldillcloudpicklecloudpickledillcloudpickledill"recurse"cloudpickle"recurse"dill.settings['recurse'] = Truerecurse=Truedill.dumpcloudpicklescikits.timeseriesPIL.Imagedillではない。

プラス面でdillは、参照によってクラスをピクルしないため、クラス インスタンスをピクルすることによって、クラス オブジェクト自体をシリアル化します。これは、分類子、モデルなどの派生クラスのインスタンスをそれらのオブジェクトからシリアル化するため、大きな利点ですsklearn。ピッキング時の正確な状態…クラスオブジェクトに変更を加えた場合でも、インスタンスは正しくアンピッキングされます。dilloverには、オブジェクトの範囲が広いこと (通常は pickle が小さいこと) 以外に、他にも利点がありますがcloudpickle、ここではそれらを挙げません。あなたは落とし穴を求めたので、違いは落とし穴ではありません。

主な落とし穴:

  • クラスが参照するものはすべてリモート マシンにインストールする必要がありdillますcloudpickle

  • クラスとクラス メソッドをできるだけ自己完結型にするようにしてください (たとえば、クラスからグローバル スコープで定義されたオブジェクトを参照しないでください)。

  • sklearnオブジェクトは大きくなる可能性があるため、それらの多くを単一のピクルに保存することは常に良い考えとは限りません.キャッシュとアーカイブへのインターフェースをklepto 持ち、各キーと値のペアを保存するようにアーカイブインターフェースを構成できる which を使用することをお勧めします.dict個別に (たとえば、ファイルごとに 1 つのエントリ)。

于 2015-10-03T17:49:10.980 に答える
10

まず、あなたのサンプルコードでpickleは問題なく動作する可能性があります。モデルを別のサーバーに直接送信したり、ファイルを保存したりしない限り、モデルをパッケージ化して後で使用するために常に pickle を使用していinterpreter stateますDill。できpickleません。また、コード、使用するタイプなどにも依存し、pickle失敗する可能性があり、Dillより安定しています。

Dill主に基づいてpickleいるため、それらは非常に似ています。考慮/検討する必要があるいくつかの点:

  1. の制限Dill

    framegeneratortraceback標準タイプは同梱できません。

  2. cloudpickleあなたの問題にも良い考えかもしれません。オブジェクトのピクルス化のサポートが優れており(ピクルスよりも、ディルよりも優れているわけではありません)、コードを簡単にピクルすることもできます。

ターゲット マシンに正しいライブラリがロードされると (コードがバグる可能性があるため、異なるバージョンにも注意してください)、サポートされていない標準型を使用しない限り、 と の両方pythonですべてが正常に動作するはずです。Dillcloudpickle

お役に立てれば。

于 2015-09-29T07:59:51.760 に答える
2

を使用してガウス過程 (GP) をパッケージ化scikit-learnpickleます。

主な理由は、GP のビルドに時間がかかり、.NET を使用するとはるかに高速にロードされるためpickleです。したがって、コードの初期化では、モデルのデータ ファイルが更新されたかどうかを確認し、必要に応じてモデルを再生成しpickleます。

pickle, dill,cloudpickleをそれぞれの順序で使用します。

pickleキーワード引数が含まれていることに注意してください。protocol一部の値は、メモリ使用量を大幅に高速化および削減できます。最後に、必要に応じて CPython STL からの圧縮で pickle コードをラップします。

于 2015-10-03T12:37:14.817 に答える