37529
自作クラスのオブジェクト作成時の挙動と、自身のオブジェクトを表す `self` の挙動に関して、  
以下の２つの不明点があり解決出来ません。  
解決方法を教えて頂きたいですm(__)m

## 1\. **１つ目の不明点（自作クラスのオブジェクト生成時の挙動）**

`scikit-learn` ライブラリの推定器 estimator の基本クラス
`sklearn.base.BaseEstimator`,`sklearn.base.ClassifierMixin` を多重継承した、  
自作クラス `class EnsembleLearningClassifier( BaseEstimator, ClassifierMixin ):`
を生成する際に、以下のような記述をすると、コンパイルエラーが出てしまう。  
エラー内容は、 **TypeError: 'module' object is not callable**

```

    import EnsembleLearningClassifier
    
    ensemble_clf1 = EnsembleLearningClassifier( 
                        classifiers = [ pipe1, pipe2, pipe3 ],
                        class_labels = [ "Logistic Regression", "Decision Tree", "k-NN" ]
                    )
    
```

以下のようにすると、コンパイルエラーにならない。

```

    import EnsembleLearningClassifier
    
    ensemble_clf1 = EnsembleLearningClassifier.EnsembleLearningClassifier( 
                        classifiers = [ pipe1, pipe2, pipe3 ],
                        class_labels = [ "Logistic Regression", "Decision Tree", "k-NN" ]
                    )
    
```

## 2\. **２つ目の不明点（自身のオブジェクトを表す`self` の挙動）**

自作クラス `EnsembleLearningClassifier` のオブジェクト作成後、自身のオブジェクトを表す `self` の 属性値が
`classifiers=None` になってしまう。  
以下、オブジェクトの生成コード

```

    ensemble_clf1 = EnsembleLearningClassifier.EnsembleLearningClassifier( 
                        classifiers = [ pipe1, pipe2, pipe3 ],
                        class_labels = [ "Logistic Regression", "Decision Tree", "k-NN" ]
                    )
    
```

以下、 `EnsembleLearningClassifier` 自作クラスのオブジェクト `ensemble_clf1` での、print
関数`ensemble_clf1.print("ensemble_clf1")`の実行結果。  
オブジェクト生成時に、コンストラクタの引数を `classifiers = [ pipe1, pipe2, pipe3
]`と設定したにも関わらず、自身のオブジェクトを表す `self` の 属性値が `classifiers=None` になってしまう。  
これを `classifiers=[ pipe1, pipe2, pipe3 ]`となるように修正したい。

```

    -------------------------------------------------------------------
    ensemble_clf1
    
    [Attributes]
    __classifiers :
     Pipeline(steps=[('sc', StandardScaler(copy=True, with_mean=True, with_std=True)), ('clf', LogisticRegression(C=0.001, class_weight=None, dual=False, fit_intercept=True,
          intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,
          penalty='l2', random_state=0, solver='liblinear', tol=0.0001,
          verbose=0, warm_start=False))])
     Pipeline(steps=[('sc', StandardScaler(copy=True, with_mean=True, with_std=True)), ('clf', DecisionTreeClassifier(class_weight=None, 
    
    criterion='entropy', max_depth=3,
                max_features=None, max_leaf_nodes=None,
                min_impurity_split=1e-07, min_samples_leaf=1,
                min_samples_split=2, min_weight_fraction_leaf=0.0,
                presort=False, random_state=0, splitter='best'))])
         Pipeline(steps=[('sc', StandardScaler(copy=True, with_mean=True, with_std=True)), ('clf', KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
               metric_params=None, n_jobs=1, n_neighbors=3, p=2,
               weights='uniform'))])
    __n_classifier :  3
    __class_labels :  ['Logistic Regression', 'Decision Tree', 'k-NN']
    __weights :  None
    __vote_method :  majority_vote
    
    [self]
     EnsembleLearningClassifier(class_labels=None, classifiers=None, vote=None,
                  weights=None)
    -------------------------------------------------------------------
    
```

**デバッグ画面：**  
`all_clf[3]` の値が `EnsembleLearningClassifier(class_labels=None,
classifiers=None, vote=None,weights=None)`となってしまう。  
オブジェクト生成時に、コンストラクタの引数を `classifiers = [ pipe1, pipe2, pipe3
]`と設定したにも関わらず、自身のオブジェクトを表す `self` の 属性値が `classifiers=None` になってしまう。  
これを `classifiers=[ pipe1, pipe2, pipe3 ]`となるように修正したい。

[![デバッグ画面](https://i.stack.imgur.com/qN02F.png)](https://i.stack.imgur.com/qN02F.png)

> **< 実装中のコード>**
>
> 以下のリンク先（GitHub）の `main2.py`,`EnsembleLearningClassifier.py`ファイル  
>
> <https://github.com/Yagami360/MachineLearning_Samples_Python/tree/master/EnsembleLearning_scikit-
> learn>

<参考URL>

> scikit-learn ライブラリ
>

>> 開発者向け情報 :  
>  <http://scikit-learn.org/stable/developers/contributing.html#rolling-your-
> own-estimator>  
>  `sklearn.base` モジュールの API Reference  
>  `sklearn.base` :  
>  <http://scikit-learn.org/stable/modules/classes.html#module-sklearn.base>  
>  `sklearn.base.BaseEstimator` :  
>  <http://scikit-
> learn.org/stable/modules/generated/sklearn.base.BaseEstimator.html#sklearn.base.BaseEstimator>
CC BY-SA 3.0
2017-08-27T14:20:48.827
37528
2017-08-27T16:10:43.013
2017-08-27T15:24:39.537
20266
20266
question
python 機械学習 scikit-learn
scikit-learn ライブラリを継承した自作クラスのオブジェクト生成時にエラー : TypeError: 'module' object is not callable が発生してしまう。又、自身のオブジェクトを表す self が 意図に反して None となってしまう。
**1\. について**  
Pythonでは`import
<モジュール名>`とすると、`<モジュール名>.<モジュール内で定義された名前>`という形でアクセスできるようになります。もし一番目のコードのようにモジュール名を省略したいのであれば、`from
<モジュール名> import <モジュール内で定義された名前>`と書く必要があります。

**2.について**  
こちらは動かしてみたわけでもないので自信が無いですが、

[挙げられたドキュメント](http://scikit-
learn.org/stable/modules/generated/sklearn.base.BaseEstimator.html#sklearn.base.BaseEstimator)の以下の記述

> Notes
>
> All estimators should specify all the parameters that can be set at the
> class level in their **init** as explicit keyword arguments (no *args or
> **kwargs).

及び[BaseEstimatorのソース](https://github.com/scikit-learn/scikit-
learn/blob/ef5cb84a/sklearn/base.py#L175)を見る限り

```

    EnsembleLearningClassifier(class_labels=None, classifiers=None, vote=None, weights=None)
    
```

という内容は`__init__`の引数と同名の属性を探し出して値として表示しているようなので、
**引数と同じ名前の属性を定義する、具体的には`__init__`中に`self.classifiers =
classifiers`といった記述を行う必要がある**のだと思います。  
(BaseEstimatorのコード中には`value = getattr(self, key,
None)`という記述があり、属性が存在しない場合に`None`になるので、今回の事例にも合致します)
CC BY-SA 3.0
2017-08-27T16:10:43.013
37529
2017-08-27T16:10:43.013
13199
37528
answer