Как я могу получить коэффициенты / interecept для каждой группы / модели, чтобы я мог построить подходящую линию для каждой группы? - PullRequest
1 голос
/ 07 ноября 2019

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

Вызов стандарта .coef_ или.get_params методы не работают, потому что элементы, которые эти методы пытаются получить, являются объектами groupby. В качестве альтернативы я попытался ввести следующее:

def get_coefs():
    coefs_dict = {}
    for name, values in dataframe.groupby(self.groupby_column):
        coefs_dict[name] = self.drugs_dict[name].coefs_ 
    return coefs_dict

Но получилось следующее:

<bound method GroupbyEstimator.get_coefs of GroupbyEstimator(groupby_column='ndc',
                 pipeline_factory=<function pipeline_factory at 0x0000018DAD207268>)>

Вот класс, который я написал:

from sklearn import base
import numpy as np 
import pandas as pd

class GroupbyEstimator(base.BaseEstimator, base.RegressorMixin):

    def __init__(self, groupby_column, pipeline_factory):
        self.groupby_column = groupby_column
        self.pipeline_factory = pipeline_factory


    def fit(self, dataframe, label):
        self.drugs_dict = {}
        self.label = label

        dataframe = pd.get_dummies(dataframe)

        for name, values in dataframe.groupby(self.groupby_column):
            y = values[label]
            X = values.drop(columns = [label, self.groupby_column], axis = 1)
            self.drugs_dict[name] = self.pipeline_factory().fit(X, y)
        return self  

    def get_coefs():
        self.coefs_dict = {}        
        self.coefs_dict[name] = self.drugs_dict[name].named_steps["lin_reg"].coef_
        return self.coefs_dict


    def predict(self, test_data):
        price_pred_list = []

        for idx, row in test_data.iterrows():
            name = row[self.groupby_column]
            regression_coefs = self.drugs_dict[name]
            row = pd.DataFrame(row).T
            X = row.drop(columns = [self.label, self.groupby_column], axis = 1).values.reshape(1, -1)  

            drug_price_pred = regression_coefs.predict(X)     
            price_pred_list.append([name, drug_price_pred])
        return price_pred_list

ОжидаетсяВ результате получается словарь в формате:

{drug_a: [coefficient_1, coefficient_2,...coefficient_n],
 drug_b: [coefficient_1, coefficient_2,...coefficient_n],
 drug_c: [coefficient_1, coefficient_2,...coefficient_n]}

Фабрика конвейеров выглядит следующим образом. Я буду строить это с помощью альтернативных регрессоров, pca, gridsearchcv и т. Д. Позже (при условии, что я смогу получить параметры из объектов groupby для отдельных регрессий.

def pipeline_factory():
    from sklearn.pipeline import Pipeline
    from sklearn.linear_model import LinearRegression

    return Pipeline([
                     ('lin_reg', LinearRegression())
                    ])

EDIT: Добавлен метод get_coefs, как было предложено. К сожалению, как показано выше, он все еще возвращает ту же ошибку.

Ответы [ 2 ]

1 голос
/ 08 ноября 2019

В то время как @Parthasarathy Subburaj привел меня к правильному ответу, вот законченный код для любого, кто может искать подобное решение:

from sklearn import base
import numpy as np 
import pandas as pd

class GroupbyEstimator(base.BaseEstimator, base.RegressorMixin):


    def __init__(self, groupby_column, pipeline_factory):
        # column is the value to group by; estimator_factory can be called to produce estimators
        self.groupby_column = groupby_column
        self.pipeline_factory = pipeline_factory


    def fit(self, dataframe, label):
        # Create an estimator and fit it with the portion in each group (create and fit a model per city
        self.drugs_dict = {}
        self.label = label
        self.coefs_dict = {} 

        dataframe = pd.get_dummies(dataframe)                                 #onehot encoder had problems with the data, so I'm getting the dummies with pandas here

        for name, values in dataframe.groupby(self.groupby_column):
            y = values[label]
            X = values.drop(columns = [label, self.groupby_column], axis = 1)
            self.drugs_dict[name] = self.pipeline_factory().fit(X, y)
            self.coefs_dict[name] = self.drugs_dict[name].named_steps["lin_reg"].coef_
        return self


    def get_coefs(self):       
        return self.coefs_dict


    def predict(self, test_data):
        price_pred_list = []

        for idx, row in test_data.iterrows():
            name = row[self.groupby_column]                                 #get drug name from drug column
            regression_coefs = self.drugs_dict[name]                        #get coefficients from fitting in drugs_dict
            row = pd.DataFrame(row).T
            X = row.drop(columns = [self.label, self.groupby_column], axis = 1).values.reshape(1, -1)            

            drug_price_pred = regression_coefs.predict(X)     #Use regression coefficients from dictionary (key = drug name) to predict
            price_pred_list.append([name, drug_price_pred])
        return price_pred_list

TL; DR комментариев - словарь, содержащийИмена моделей и коэффициенты должны быть созданы в методе подгонки с использованием sklearn's .named_steps в нужной части конвейера, а затем возвращены отдельным методом (в данном случае get_coefs).

1 голос
/ 08 ноября 2019

Проблема в self.drugs_dict, который является словарем Pipeline объектов, поэтому вы не можете использовать coef_ непосредственно для них. coef_ - это атрибут, связанный с объектом оценки, который в вашем случае является объектом LinearRegression. Таким образом, правильный способ доступа к коэффициентам будет self.drugs_dict[name].named_steps["lin_reg"].coef_ вместо self.drugs_dict[name].coefs_ в вашем get_coefs() методе.

Надеюсь, это поможет!

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