44893
環境: Macbook air, Jupyter-Notebook, Python2.7

Kernel
K-meansを実装する際、一部[この方](https://gist.github.com/mblondel/6230787)のコードを参考にしました。  
具体的には

```

    def _get_kernel(self, X, Y=None):
        if callable(self.kernel):
            params = self.kernel_params or {}
        else:
            params = {"gamma": self.gamma,
                      "degree": self.degree,
                      "coef0": self.coef0}
        return pairwise_kernels(X, Y, metric=self.kernel,
                                filter_params=True, **params)
    
```

ここの部分です。"callable()"と" **params "の使い方がわかりません。加えて

```

    @property
    def _pairwise(self):
        return self.kernel == "precomputed"
    
```

ここもどういったものになっているのかわかりません。具体的には@propertyと"precomputed"です

pythonはおろかプログラミングも完全素人なのでstep by stepで例など込みで教えてもらえると助かります。よろしくお願いします。

以下にリンクを貼っておきます。  
[sklearnのリンク](http://scikit-
learn.org/stable/modules/generated/sklearn.metrics.pairwise.pairwise_kernels.html)
CC BY-SA 4.0
2018-06-19T10:46:38.870
44890
2018-06-20T01:53:13.687
2018-06-20T01:53:13.687
19110
question
python scikit-learn python2
sklearnのpairwise_kernelsの引数について
## はじめに

分からない関数や書き方があったとき、まずは Python
や周辺ライブラリのドキュメントやマニュアルを確認するようにしましょう。基本的にドキュメントを読めば使い方が載っています。「Python
callable」や「callable site:docs.python.org/ja」などでウェブ検索するのも有効です。Python 2.7
のドキュメントに限定したい場合は「callable site:docs.python.org/ja/2.7」とできます。

## `**params` について

変数 `params` は `sklearn.metrics.pairwise.pairwise_kernels`
の引数として使われているので、まずはこの関数のドキュメントを確認してみます。scikit-learn 0.19.1
の[ドキュメント](http://scikit-
learn.org/stable/modules/generated/sklearn.metrics.pairwise.pairwise_kernels.html)には、この関数の説明が以下のように書かれています。

> sklearn.metrics.pairwise. **pairwise_kernels** ( _X_ , _Y_ = _None_ ,
> _metric_ = _’linear’_ , _filter_params_ = _False_ , _n_jobs_ = _1_ , **
> _kwds_ )

特に今回注目すべきは `**kwds` という引数です。この引数はどういう意味でしょうか？ 「Python double asterisk」 で検索すると
["What does ** (double star/asterisk) and * (star/asterisk) do for
parameters?"](https://stackoverflow.com/q/36901/5989200)
という投稿が見つかります。投稿を元にドキュメントを見ると Python 2.7 ドキュメント [4.7.2
キーワード引数](https://docs.python.org/ja/2.7/tutorial/controlflow.html#keyword-
arguments) には以下のように書かれています。

> 仮引数の最後に `**name` の形式のものがあると、それまでの仮引数に対応したものを除くすべてのキーワード引数が入った辞書 ([マッピング型 ---
> dict](https://docs.python.org/ja/2.7/library/stdtypes.html#typesmapping)
> を参照) を受け取ります。

つまり `**kwds` とは、`Y`, `metric`, `filter_params`, `n_jobs`
以外のキーワード引数を一手に引き受ける辞書型の引数なわけです。実際、`kwds` は keywords の略でしょう。

さてここで `pairwise_kernels` のドキュメントに戻ると、引数の説明欄には以下のように書かれています。

> ****kwds** : optional keyword parameters  
>      Any further parameters are passed directly to the kernel function.

したがって `**kwds` は、`pairwise_kernels`
で使うカーネル関数に渡すキーワード引数として用意されていることが分かります。用いるカーネル関数によって必要なキーワード引数が違うので、`**kwds`
として用意することで対応したということでしょう。

ところで質問文中のコードにおいて `**params` は `**kwds` として渡す引数なのでした。実際 `params`
は辞書として以下のように初期化されています。

```

    params = {"gamma": self.gamma,
              "degree": self.degree,
              "coef0": self.coef0}
    
```

`gamma` や `degree` 等のキーワードが具体的にどのように使われるのかは scikit-learn
の[こちらのドキュメント](http://scikit-
learn.org/stable/modules/metrics.html#metrics)に詳しいです。というわけで `**params`
とは、カーネルで使用するパラメータ設定のための任意引数なのです。

## `callable` について

まず `callable` とはどういう関数なのでしょうか。これは Python
の組み込み関数で、与えられたオブジェクトが呼び出し可能かを調べるものです。詳細なドキュメントは[こちら](https://docs.python.org/ja/2.7/library/functions.html#callable)にあります。

質問文のプログラムでは変数 `self.kernel` が呼び出し可能かどうかを調べています。これは `pairwise_kernel` のキーワード引数
`metric` へ「文字列」または「呼び出し可能オブジェクト」を渡せることに対応しようとしています。`metric` へ `'rbf'` や
`'linear'` などの文字列を渡すと scikit-learn 側に用意されたカーネル関数が使われますが、ユーザー側で適当なカーネル関数 `f`
を定義して `metric=f` のように渡すこともできる、ということです。

つまり、`self.kernel` が呼び出し可能かどうかで `params` の内容を変えるために組み込み関数 `callable`
を使っている、ということです。

## `"precomputed"` について

ところで `self.kernel` に文字列を渡す場合、`"precomputed"` という文字列を渡すと特別に扱われます。具体的には
`pairwise_kernel` の[ドキュメント](http://scikit-
learn.org/stable/modules/generated/sklearn.metrics.pairwise.pairwise_kernels.html)に以下のように書かれています。

> **metric** : string, or callable  
>      (前略) If metric is “precomputed”, X is assumed to be a kernel matrix.
> (後略)

## `@property` について

Python において `@` (アットマーク)
から始まる識別子が関数定義の前に置かれているものは、[デコレータ](https://docs.python.org/ja/2.7/glossary.html#term-
decorator)です。`@property` もデコレータの一種です。「python at property」で検索すると ["How does the
@property decorator work?"](https://stackoverflow.com/q/17330160/5989200)
がヒットします。`@property` について完全に解説すると長いので省きますが、要するにこのクラスのインスタンスが `kkm` だとすると
`kkm._pairwise` が使えるようになります。

`@property` の詳しい解説は、Python 2.7 における組み込み関数のドキュメントにある [`property`
の解説](https://docs.python.org/ja/2.7/library/functions.html#property)をご覧ください。
CC BY-SA 4.0
2018-06-19T13:57:50.630
44893
2018-06-19T13:57:50.630
19110
44890
answer