Last answered:

22 May 2024

Posted on:

04 Feb 2023

2

Resolved: Solution Sci kit learn

Solution : what worked for me

python - sklearn - AttributeError: 'CustomScaler' object has no attribute 'copy' - Stack Overflow

Ben reiniger

No attribute copy error
This is only being thrown when trying to display the html representation of the transformer, after fitting has already succeeded, which is why you're able to continue and transform successfully.

But the issue is more serious than that if you want to make use of the transformer in pipelines, grid searches, etc. In order to clone properly, you need to follow the specific guidance of the sklearn API, or else provide your own get_params and set_params. The __init__ method should set an attribute for every parameter, and only those attributes. So here it should be

    def __init__(self, columns, copy=True, with_mean=True, with_std=True):
        self.columns = columns
        self.copy = copy
        self.with_mean = with_mean
        self.with_std = with_std

And then make the contained StandardScaler at fit time:

    def fit(self, X, y=None):
        self.scaler = StandardScaler(copy=self.copy, with_mean=self.with_mean, with_std=self.with_std)
        self.scaler.fit(X[self.columns], y)
        self.mean_ = np.mean(X[self.columns])
        self.var_ = np.var(X[self.columns])
        return self

Hope this can help you.


Full solution

class CustomScaler(BaseEstimator, TransformerMixin):

    def __init__(self, columns, copy=True, with_mean=True, with_std=True):
        self.columns = columns
        self.copy = copy
        self.with_mean = with_mean
        self.with_std = with_std

    def fit(self, X, y=None):
        self.scaler = StandardScaler(copy= self.copy, with_mean=self.with_mean, with_std=self.with_std)
        self.scaler.fit(X[self.columns], y)
        self.mean_ = np.mean(X[self.columns])
        self.var_ = np.var(X[self.columns])
        return self

    def transform(self, X, y=None, copy=None):
        init_col_order = X.columns
        X_scaled = pd.DataFrame(self.scaler.transform(X[self.columns]), columns=self.columns)
        X_not_scaled = X.loc[:, ~X.columns.isin(self.columns)]
        return pd.concat([X_not_scaled, X_scaled], axis=1)[init_col_order]

1 answers ( 1 marked as helpful)
Instructor
Posted on:

22 May 2024

0

Hi Rosaline!

Thanks for reaching out!

For the purposes of teaching this course, we would sometimes like to keep certain topics simple. Nevertheless, you are right in your reasoning. Therefore, thank you for sharing this solution for the CustomScaler class!  

Hope this helps.

Best,
Martin

Submit an answer