Невозможно воспроизвести оценки вероятности из сохраненного XGBClassifier, несмотря на установку случайного состояния и начального числа - PullRequest
0 голосов
/ 05 апреля 2019

Я пытаюсь повторно использовать сохраненный XGBClassifer, который после обучения делает следующие прогнозы с помощью метода .predict_proba ():

ID - баллы

1 - 0,072253475

2 - 0,165827038

3 - 0,098182471

4 - 0,148302316

Однако после перезагрузки объекта после его травления или использования модуля Skleans Joblib прогнозы полностью отключаются даже после использования точно такого же набора тестов:

ID - баллы

1 - 0,46986327

2 - 0,63513994

3 - 0,45958066

4 - 0,8958819

Это классификатор:

XGBClassifier(base_score=0.5, booster='gbtree',colsample_bylevel=1, 
colsample_bytree=0.8, gamma=1, learning_rate=0.01, max_delta_step=0,
   max_depth=4, min_child_weight=1, missing=nan, n_estimators=1500,
   n_jobs=-1, nthread=None, objective='binary:logistic',
   random_state=777, reg_alpha=2, reg_lambda=1,
   scale_pos_weight=0.971637216356233, seed=777, silent=True,
   subsample=0.6, verbose=2)

Я выбираю объект, используя два разных метода: Joblib, предоставляемый в пакете sklearn, и стандартный pickle.dump, использующий эти функции:

def save_as_pickled_object(obj, filepath):
    import pickle
    import os
    import sys
    """
    This is a defensive way to write pickle.write, allowing for very large files on all platforms
    """
    max_bytes = 2**31 - 1
    """
    Adding protocol = 4 as an argument to pickle.dumps because it allows for seralizing data greater than 4GB
    reference link: https://stackoverflow.com/questions/29704139/pickle-in-python3-doesnt-work-for-large-data-saving
    """    
    bytes_out = pickle.dumps(obj, protocol=4)
    n_bytes = sys.getsizeof(bytes_out)
    with open(filepath, 'wb') as f_out:
        for idx in range(0, n_bytes, max_bytes):
            f_out.write(bytes_out[idx:idx+max_bytes])

def try_to_load_as_pickled_object_or_None(filepath):
    import pickle
    import os
    import sys
    """
    This is a defensive way to write pickle.load, allowing for very large files on all platforms
    """
    max_bytes = 2**31 - 1
    try:
        input_size = os.path.getsize(filepath)
        bytes_in = bytearray(0)
        with open(filepath, 'rb') as f_in:
            for _ in range(0, input_size, max_bytes):
                bytes_in += f_in.read(max_bytes)
        obj = pickle.loads(bytes_in)
    except:
        return None
    return obj

Независимо от того, как я сохраняю файл (JobLib или Pickle), результаты одинаковы; то есть прогнозируемые оценки проба полностью отличаются от того, когда я использую метод на объекте XGBClassifier сразу после обучения.

С другой стороны, на том же ядре я делаю то же самое, используя SGDClassifier, для которого у меня нет такой же проблемы.

Одна странная вещь, которую я заметил, заключается в том, что если я сохраню классификатор после обучения, а затем загрузлю его в течение того же сеанса кернала (используя Jupyterlab), вероятности будут одинаковыми. Однако, если я перезапущу ядро ​​и загрузлю объект одним из двух способов, описанных выше, я больше не получу одинаковые вероятности.

Я ожидаю, что я получу одинаковые или почти идентичные вероятности, используя метод предиката вероятности в XGBClassifier.

Спасибо

1 Ответ

0 голосов
/ 07 апреля 2019

Полагаю, в том, как вы выгружаете и читаете модель, есть что-то смешное, или это особенность используемой вами версии xgboost.

Я могу полностью воспроизвести предсказанные вероятности, используя простую загрузку сохраненной модели XGB со следующим кодом в записную книжку (повторяя раздел «Загрузка модели» и первоначальный импорт после перезапуска ядра)

import os
import numpy as np
import pandas as pd
import pickle
import joblib
import xgboost as xgb


## Training a model
np.random.seed(312)
train_X = np.random.random((10000,10))
train_y = np.random.randint(0,2, train_X.shape[0])
val_X = np.random.random((10000,10))
val_y = np.random.randint(0,2, train_y.shape[0])

xgb_model_mpg = xgb.XGBClassifier(max_depth= 3)
_ = xgb_model_mpg.fit(train_X, train_y)
print(xgb_model_mpg.predict_proba(val_X))


## Save the model
with open('m.pkl', 'wb') as fout:
    pickle.dump(xgb_model_mpg, fout)

joblib_dump(xgb_model_mpg, 'm.jlib')


## Load the model
m_jlb = joblib.load('m.jlib')
m_pkl = pickle.load( open( "m.pkl", "rb" ) )

print(m_jlb.predict_proba(val_X))
print(m_pkl.predict_proba(val_X))

Я использую xgboost 0.71 и joblib 0.12.4 в обычном ноутбуке Jupyter в python 3.5.5

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...