Трубопровод Scikit-Learn: возможность агрегирования строк (pandas groupby)? - PullRequest
0 голосов
/ 28 января 2019

Я хочу запустить все задачи предварительной обработки и оптимизации модели в одном конвейере, выполнив следующие шаги:

  1. однотонное кодирование
  2. уменьшение размера SVD
  3. агрегация (pandas groupby)
  4. Моделирование случайного леса

мои входные переменные:

  • X_train с 349 строками, которые после шага 3 (агрегация) станут 338 строками
  • y_train с 338 строками

Я получаю ошибку «Найдены входные переменные с непоследовательным количеством образцов».

Это потому, что sklearn не допускает разницыномер строки между X_train и y_train.

Знаете ли вы другой способ, если возможно, для агрегации в конвейере?

вот мой код:

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder
from sklearn.decomposition import TruncatedSVD
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.compose import ColumnTransformer

# does nothing, but is here to collect numerical columns
class nothing(BaseEstimator, TransformerMixin):

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

        return self

    def transform(self, X):          

        return X


class Aggregator(BaseEstimator, TransformerMixin):

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

    def transform(self, X):
        X = pd.DataFrame(X)
        X = X.rename(columns = {0 :'InvoiceNo', 1 : 'amount', 2:'Quantity', 
                                3:'UnitPrice',4:'CustomerID' })
        X['InvoiceNo'] =  X['InvoiceNo'].astype('int')
        X['Quantity'] = X['Quantity'].astype('float64')
        X['UnitPrice'] = X['UnitPrice'].astype('float64')
        aggregations = dict()
        for col in range(5, X.shape[1]-1) :
            aggregations[col] = 'max'

        aggregations.update({ 'CustomerID' : 'first',
                            'amount' : "sum",'Quantity' : 'mean', 'UnitPrice' : 'mean'})

        # aggregating all basket lines
        result = X.groupby('InvoiceNo').agg(aggregations)

        # add number of lines in the basket
        result['lines_nb'] = X.groupby('InvoiceNo').size()
        return result

 numeric_features = ['InvoiceNo','amount', 'Quantity', 'UnitPrice', 
                           'CustomerID']
 numeric_transformer = Pipeline(steps=[('nothing', nothing())])

 categorical_features = ['StockCode', 'Country']   

 preprocessor =  ColumnTransformer(
        [
        # 'num' transformer does nothing, but is here to  
        # collect numerical columns
        ('num', numeric_transformer ,numeric_features ),
        ('cat', Pipeline([
            ('onehot', OneHotEncoder(handle_unknown='ignore')),
            ('best', TruncatedSVD(n_components=100)),
         ]), categorical_features)        
          ]
          )           

pipe = Pipeline(steps=[
                      ('preprocessor', preprocessor),
                      ('aggregator', Aggregator()),
                      ('rf', RandomForestClassifier(n_estimators=400, 
                        max_features='auto',                                         
                        class_weight=class_weights)),
                     ])

X_train_transformed = pipe.fit_transform(X_train)

ValueError: Found input variables with inconsistent numbers of samples: [349, 338]

более подробно, чтобы ответить на комментарий @desertnaut:

пример:

X_train содержит 4 строки: customer_num: 1 article_ref: 1 money: 10 $customer_num: 1 article_ref: 2 money:15 $ customer_num: 2 article_ref: 5 money: 5 $ customer_num: 3 article_ref: 4 money: 11 $

Я объединяю 4 строки с pandas groupby = cucstomer_num, результирующий кадр данных, X_train_transformed , имеет 3 строки, по одной на клиента

y_train имеет 3 строки, содержащие группу (метка для прогнозирования) для customer_num 1, customer_num 2 и customer_num 3.

Стандартный метод:

конвейер 1: преобразовать X_train (4 строки) в X_train_transformed (3 строки)
конвейер 2: подогнать модель к (X_train_transformed (3 строки), y_train (3 строки))

Я хочу иметь один конвейер для обработки трубопровода 1 и трубопровода 2

...