Saya baru mengenal pipa sk-learn dan ingin menggunakan bentuk binning diskrit saya sendiri. Saya perlu membuang kolom nilai berdasarkan jumlah kumulatif kolom lain yang terkait dengan kolom asli. Saya memiliki fungsi kerja:

def dynamic_bin(df, column, weight, minimum):
    """
    

    Parameters
    ----------
    df : dataframe
    column : column to be binned
    weight : column that will dictate the bin
    minimum : minimum weight per bin

    Returns
    -------
    df : dataframe with new binned column

    """
    bins = [-np.inf]
    labels = [] 
    hold_over = []
    for i in sorted(df[column].unique()):
        g = df[df[column] == i].groupby(column).agg({weight:'sum'}).reset_index()
        
        if g[weight].values[0] < minimum:
            if hold_over is None:
                hold_over.append(g[weight].values[0])
                
            elif (sum(hold_over) + g[weight].values[0]) < minimum:
                hold_over.append(g[weight].values[0])
 
                
            elif (sum(hold_over) + g[weight].values[0]) >= minimum:
                hold_over.clear()
                bins.append(g[column].values[0])
                labels.append(g[column].values[0])
                
            
        elif g[weight].values[0] >= minimum:
            bins.append(g[column].values[0])
            labels.append(g[column].values[0])
    
    bins.pop()
    bins.append(np.inf)
    
    
    str_column = str(column)+str("_binned")
    # print(str_column)
    df[str_column] = pd.cut(df[column],
                            bins = bins,
                            labels = labels)
    

    return df

Ini adalah bagaimana saya mencoba untuk membuat kelas.

from sklearn.base import  BaseEstimator, TransformerMixin

class dynamic_bin(BaseEstimator, TransformerMixin):
    def __init__(self, weight, minimum):
        self.weight = weight
        self.minimum = minimum
    def fit(self, X, y=None):
        return self
    def tranform(self, X):
        """
    

        Parameters
        ----------
        df : dataframe
        column : column to be binned
        weight : column that will dictate the bin
        minimum : minimum weight per bin
    
        Returns
        -------
        df : dataframe with new binned column
    
        """
        bins = [-np.inf]
        labels = [] 
        hold_over = []
        for i in sorted(df[column].unique()):
            g = df[df[column] == i].groupby(column).agg({weight:'sum'}).reset_index()
            
            if g[weight].values[0] < minimum:
                if hold_over is None:
                    hold_over.append(g[weight].values[0])
                    
                elif (sum(hold_over) + g[weight].values[0]) < minimum:
                    hold_over.append(g[weight].values[0])
     
                    
                elif (sum(hold_over) + g[weight].values[0]) >= minimum:
                    hold_over.clear()
                    bins.append(g[column].values[0])
                    labels.append(g[column].values[0])
                    
                
            elif g[weight].values[0] >= minimum:
                bins.append(g[column].values[0])
                labels.append(g[column].values[0])
        
        bins.pop()
        bins.append(np.inf)
        
        
        str_column = str(column)+str("_binned")
        # print(str_column)
        df[str_column] = pd.cut(df[column],
                                bins = bins,
                                labels = labels)
        
    
        return df[str_column]

Ketika saya mencoba menerapkannya dengan cara berikut, saya mendapatkan kesalahan di bawahnya:

column_trans = ColumnTransformer(
    [
        ("binned_numeric", dynamic_bin(weight = 'Exposure', minimum = 1000),
            ["VehAge", "DrivAge"]),
        ("onehot_categorical", OneHotEncoder(),
            ["VehBrand", "VehPower", "VehGas", "Region", "Area"]),
        ("passthrough_numeric", "passthrough",
            ["BonusMalus"]),
        ("log_scaled_numeric", log_scale_transformer,
            ["Density"]),
    ],
    remainder="drop",
)
X = column_trans.fit_transform(df)

TypeError: All estimators should implement fit and transform, or can be 'drop' or 'passthrough' specifiers. 'dynamic_bin(minimum=1000, weight='Exposure')' (type <class 'dynamic_bin.dynamic_bin'>) doesn't.

Saya membaca yang berikut tetapi saya tidak benar-benar mengikutinya.
Menempatkan fungsi yang disesuaikan di pipeline Sklearn

Apakah ada yang melihat kesalahan yang saya buat?

0
Jordan 24 Mei 2021, 21:33

1 menjawab

Jawaban Terbaik

Kesalahan itu sendiri disebabkan oleh kesalahan ketik dalam deklarasi metode Anda. Anda menerapkan fungsi yang disebut tranform (perhatikan 's' yang hilang) di kelas transformator khusus Anda. Itulah sebabnya penerjemah mengeluh bahwa trafo khusus Anda belum menerapkan transform.

Meskipun ini akan menjadi perbaikan sederhana, Anda juga harus menyadari bahwa Anda belum menyesuaikan fungsi kustom Anda untuk digunakan di kelas yang Anda tetapkan. Sebagai contoh:

  • variabel df harus diganti namanya menjadi X
  • weight dan minimum sekarang menjadi atribut objek dan perlu dirujuk sebagai self.weight dan self.minimum
  • variabel column tidak dideklarasikan

Anda juga perlu memperbaiki masalah ini. Sehubungan dengan hal ini, perlu diketahui bahwa ColumnTransformer hanya akan melewatkan subset kolom ke transformator yang dimaksudkan untuk ditransformasikan oleh transformator khusus ini. Itu berarti jika Anda hanya meneruskan kolom VehAge dan DrivAge ke dynamic_bin, kolom tersebut tidak dapat mengakses Exposure.

0
afsharov 25 Mei 2021, 13:38