繁体   English   中英

如何在sklearn类中更新fit方法?

[英]How to update fit method in a sklearn class?

我最近开始使用GridSearchCV,对面向对象的编程不太满意。

问题:我在一个预测变量中缺少一些数据,并且我要在适当的参数网格中使用一系列算法。 我想知道是否存在一种创建自定义类的方法,该类将在拟合数据之前以不同的方式插补数据中的缺失值,并针对我同时使用的任何算法尝试不同的属性组合。 可能吗?

感谢TON的帮助!

这是我为在房屋价格数据集的SQFT列中估算缺失值而创建的一个类:

class Impute_sqft():

    train_X = houses_dummies_copy.dropna(subset=['sqft']).drop(columns=['sqft', 'final_price'])
    train_Y = houses_dummies_copy.dropna(subset=['sqft'])['sqft']
    test_X = houses_dummies_copy[pd.isna(houses_dummies_copy.sqft)].drop(columns=['sqft', 'final_price'])


    def __init__(self, how='random forest'):
        self.how = how

    def impute(self):

        # replace missing values with the ones predicted by random forest
        if self.how == 'random forest':
            houses_dummies_copy = houses_dummies.copy()
            rf = RandomForestRegressor()
            rf.fit(train_X, train_Y)
            pred_Y = rf.predict(test_X)
            houses_dummies_copy.loc[test_X.index,'sqft'] = pred_Y
            return houses_dummies_copy[predictors]

        # replace missing values with the ones predicted by knn        
        if self.how == 'knn':
            houses_dummies_copy = houses_dummies.copy()
            import sys
            from impyute.imputation.cs import fast_knn
            sys.setrecursionlimit(100000) 
            knn_n = 30
            result = fast_knn(houses_dummies_copy[predictors], k=knn_n)
            result.columns = houses_dummies_copy[predictors].columns
            return result

        # replace missing values with the mean for every type of property     
        if self.how == 'mean':
            houses_dummies_copy = houses_dummies.copy()
            sqft_statistics = []
            for house_type in houses_types:
                statistic = houses_dummies_copy[houses_dummies_copy['type_' + house_type] == 1].sqft.mean(skipna=True)
                indexes = houses_dummies_copy[(houses_dummies_copy['type_' + house_type] == 1) & pd.isna(houses_dummies_copy.sqft)].index
                houses_dummies_copy.loc[indexes, 'sqft'] = statistic
            return houses_dummies_copy[predictors]



我对GridSearchCV有什么网格:

param_grid = [{
    'bootstrap': [True, False],
        'n_estimators': [3, 10],
        'max_features': [2, 3, 4]
    }]

我想要GridSearchCV的什么网格:

param_grid = [{
        'bootstrap': [True, False],
        'n_estimators': [3, 10],
        'max_features': [2, 3, 4],
        'sqft_imputer': ['random forest', 'knn', 'mean']

    }]

您需要创建一个自定义的Transformer ,并在Pipeline的估算器之前使用它。

自定义变压器:

看一下模板: TemplateTransformer

一些评论:

  • 您需要从BaseEstimator继承。
  • self.how的选择必须在类的__init__方法中定义。
  • 为正确起见,您需要在fit过程中估计统计量,并在transform过程中应用它们。 (另请参阅为什么sklearn Imputer需要安装?

管道

要链接自定义的估算者和估算器,可以使用scikit-learn Pipeline

  • 例如 ,请参见本示例 ,该示例Pipeline链接了PCALogisticRegression ,然后在GridSearchCV使用了它。
  • 您将需要使用管道中使用的名称来更改参数网格,例如
param_grid = [{
        'estimator__bootstrap': [True, False],
        'estimator__n_estimators': [3, 10],
        'estimator__max_features': [2, 3, 4],
        'imputer__how': ['random forest', 'knn', 'mean']

    }]

按照上面的答案。 现在一切正常。

from sklearn.base import BaseEstimator, TransformerMixin

class Impute_sqft(BaseEstimator, TransformerMixin):
    def __init__(self, how='random forest'):        
        self.how = how

    def fit(self, X, y=None):
        return self

    def transform(self, X):
        import sys
        sys.setrecursionlimit(100000) #Increase the recursion limit of the OS
        from impyute.imputation.cs import fast_knn, mice
        result = X.copy()

        if self.how == 'random forest':
            train_X = houses_dummies.dropna(subset=['sqft']).drop(columns=['sqft', 'final_price'])
            train_Y = houses_dummies.dropna(subset=['sqft'])['sqft']
            test_X = result[pd.isna(result.sqft)].drop(columns=['sqft'])

            rf = RandomForestRegressor()
            rf.fit(train_X, train_Y)
            pred_Y = rf.predict(test_X)
            result.loc[test_X.index,'sqft'] = pred_Y

        if self.how == 'knn':
            knn_n = 30
            result = fast_knn(houses_dummies[predictors], k=knn_n)
            result.columns = houses_dummies[predictors].columns
            result.index = houses_dummies[predictors].index
            result = result.loc[X.index,:]

        if self.how == 'mice':
            result = mice(houses_dummies[predictors])
            result.columns = houses_dummies[predictors].columns
            result.index = houses_dummies[predictors].index
            result = result.loc[X.index,:]

        if self.how == 'mean':
            result['sqft'] = houses_edited.groupby('type')['sqft'].transform(lambda x: x.fillna(x.mean(skipna=True)))

        if self.how == 'median':
            result['sqft'] = houses_edited.groupby('type')['sqft'].transform(lambda x: x.fillna(x.median(skipna=True)))

        if self.how == 'mode':
            result['sqft'] = houses_edited.groupby('type')['sqft'].transform(lambda x: x.fillna(x.mode()[0]))

        return result[predictors]
methods = ['random forest', 'knn', 'mice', 'mean', 'median', 'mode']

imputer = Impute_sqft()
rf = RandomForestRegressor()
pipe = Pipeline(steps=[
    ('imputer', imputer),
    ('rf', rf)
])

param_grid = [{
    'imputer__how':methods,
    'rf__max_depth':[1,2,None],
    'rf__bootstrap':[True, False]    
}]

houses_dummies_copy = houses_dummies.copy()

search = GridSearchCV(pipe, param_grid, iid=False, cv=5, scoring='neg_mean_absolute_error')
search.fit(houses_dummies_copy[predictors], houses_dummies_copy.final_price)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM