私はこの質問をCrossValidatedフォーラムに投稿しましたが、後で、代わりにstackoverlfowで適切なオーディエンスが見つかる可能性があることに気付きました。
python statsmodelから取得したfit
オブジェクト(結果)を使用して、scikit-learncross_validationメソッドのcross_val_score
にフィードする方法を探していますか?添付リンクはそれが可能かもしれないことを示唆していますが、私は成功していません。
次のエラーが発生します
estimatorは、「fit」メソッドを実装する推定器である必要があります。statsmodels.discrete.discrete_model.BinaryResultsWrapperオブジェクト(0x7fa6e801c590)が渡されました
実際、インターフェースが異なるため、statsmodels
オブジェクトでcross_val_score
を直接使用することはできません。statsmodelsで
ただし、statsmodels
オブジェクトをsklearn
推定量のように見せるための単純なラッパーを作成できます。
import statsmodels.api as sm
from sklearn.base import BaseEstimator, RegressorMixin
class SMWrapper(BaseEstimator, RegressorMixin):
""" A universal sklearn-style wrapper for statsmodels regressors """
def __init__(self, model_class, fit_intercept=True):
self.model_class = model_class
self.fit_intercept = fit_intercept
def fit(self, X, y):
if self.fit_intercept:
X = sm.add_constant(X)
self.model_ = self.model_class(y, X)
self.results_ = self.model_.fit()
def predict(self, X):
if self.fit_intercept:
X = sm.add_constant(X)
return self.results_.predict(X)
このクラスには、正しいfit
メソッドとpredict
メソッドが含まれており、sklearn
とともに使用できます。相互検証されているか、パイプラインに含まれています。ここみたいに:
from sklearn.datasets import make_regression
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LinearRegression
X, y = make_regression(random_state=1, n_samples=300, noise=100)
print(cross_val_score(SMWrapper(sm.OLS), X, y, scoring='r2'))
print(cross_val_score(LinearRegression(), X, y, scoring='r2'))
2つのモデルは両方ともOLSモデルであり、同じ方法で相互検証されているため、2つのモデルの出力は同じであることがわかります。
[0.28592315 0.37367557 0.47972639]
[0.28592315 0.37367557 0.47972639]
Davidの提案 (エラーが発生し、関数_get_parameters
_がないことについて不平を言っています)と scikit learnドキュメント に続いて、線形の次のラッパーを作成しました回帰。 _sklearn.linear_model.LinearRegression
_と同じインターフェースを備えていますが、さらに_statsmodels.OLS
_のように、p値、R2、およびその他の統計に関する情報を提供する関数summary()
も備えています。
_import statsmodels.api as sm
from sklearn.base import BaseEstimator, RegressorMixin
import pandas as pd
import numpy as np
from sklearn.utils.multiclass import check_classification_targets
from sklearn.utils.validation import check_X_y, check_is_fitted, check_array
from sklearn.utils.multiclass import unique_labels
from sklearn.utils.estimator_checks import check_estimator
class MyLinearRegression(BaseEstimator, RegressorMixin):
def __init__(self, fit_intercept=True):
self.fit_intercept = fit_intercept
"""
Parameters
------------
column_names: list
It is an optional value, such that this class knows
what is the name of the feature to associate to
each column of X. This is useful if you use the method
summary(), so that it can show the feature name for each
coefficient
"""
def fit(self, X, y, column_names=() ):
if self.fit_intercept:
X = sm.add_constant(X)
# Check that X and y have correct shape
X, y = check_X_y(X, y)
self.X_ = X
self.y_ = y
if len(column_names) != 0:
cols = column_names.copy()
cols = list(cols)
X = pd.DataFrame(X)
cols = column_names.copy()
cols.insert(0,'intercept')
print('X ', X)
X.columns = cols
self.model_ = sm.OLS(y, X)
self.results_ = self.model_.fit()
return self
def predict(self, X):
# Check is fit had been called
check_is_fitted(self, 'model_')
# Input validation
X = check_array(X)
if self.fit_intercept:
X = sm.add_constant(X)
return self.results_.predict(X)
def get_params(self, deep = False):
return {'fit_intercept':self.fit_intercept}
def summary(self):
print(self.results_.summary() )
_
使用例:
_cols = ['feature1','feature2']
X_train = df_train[cols].values
X_test = df_test[cols].values
y_train = df_train['label']
y_test = df_test['label']
model = MyLinearRegression()
model.fit(X_train, y_train)
model.summary()
model.predict(X_test)
_
列の名前を表示したい場合は、
_model.fit(X_train, y_train, column_names=cols)
_
Cross_validationで使用するには:
_from sklearn.model_selection import cross_val_score
scores = cross_val_score(MyLinearRegression(), X_train, y_train, cv=10, scoring='neg_mean_squared_error')
scores
_
参考までに、statsmodels
式APIを使用するか、fit_regularized
メソッドを使用する場合、この方法で@DavidDaleのラッパークラスを変更できます。
import pandas as pd
from sklearn.base import BaseEstimator, RegressorMixin
from statsmodels.formula.api import glm as glm_sm
# This is an example wrapper for statsmodels GLM
class SMWrapper(BaseEstimator, RegressorMixin):
def __init__(self, family, formula, alpha, L1_wt):
self.family = family
self.formula = formula
self.alpha = alpha
self.L1_wt = L1_wt
self.model = None
self.result = None
def fit(self, X, y):
data = pd.concat([pd.DataFrame(X), pd.Series(y)], axis=1)
data.columns = X.columns.tolist() + ['y']
self.model = glm_sm(self.formula, data, family=self.family)
self.result = self.model.fit_regularized(alpha=self.alpha, L1_wt=self.L1_wt, refit=True)
return self.result
def predict(self, X):
return self.result.predict(X)
これは技術的にはscikit-learnではないと思いますが、statsmodelをラップし、scikit-learnのようなインターフェイスを提供するパッケージ pmdarima があります。