scikit-fda使い方の備忘録

scikit-fdaに関する日本語ブログが少なかったのでメモ書きをまとめておきます。

scikit-fdaは、関数データ分析（Functional Data Analysis、略称：FDA）を行うためのPythonパッケージです。

### 関数データ分析
ここでいう関数データとは、離散的な波形データととらえていただいてよいです。
Tutorialでは、例えば以下のようなデータが解析されています。
・年齢によって増加していく身長のデータ
・食肉サンプルの赤外吸光スペクトル
・気候（温度）データ

これらの波形の形を解析し、代表例として
・分類（成長曲線 ⇒ 男or女？）
・予測（吸光スペクトル ⇒ 含有成分何g？）
などを行うのが関数データ分析です。

詳しい例は[Tutorial](https://fda.readthedocs.io/en/latest/auto_tutorial/index.html)ページを見てください。結構種類もあってわかりやすいです。

### scikit-fda使用時に気を付けること
まず、メインで使うデータ型として、
・FDataGrid型
・FDataBasis型
がありますので、それらの特徴を理解しておく必要があります。

#### [FDataGrid型](https://fda.readthedocs.io/en/latest/modules/autosummary/skfda.representation.grid.FDataGrid.html)
FDataGrid型は、決められたデータ間隔（Grid）に沿って離散的なデータを格納するクラスです。
手元の測定データ（Array型、DataFrame型）のデータを、このFDataGrid型に変換することで、
初めて関数データ分析の扉が開きます。


例えばFDataGrid型の宣言は以下のように行います。
ここでは、dfというデータフレーム型のデータをFDataGrid型に直しています。
事前に、dfの列名を測定点（0,10,20,30,　）などに直していたので、
それをgrid_pointsにしていますが、別で測定点を示すlistを用意していてもよいです。

```.py
grid_points = df.columns
data_matrix = df
X = skfda.FDataGrid(
    data_matrix=data_matrix.astype(np.float64),
    grid_points=grid_points.astype(np.float64),
    argument_names = ('Width Address',),
    coordinate_names = ('Diameter',)
)
```


#### [FDataBasis型](https://fda.readthedocs.io/en/latest/modules/autosummary/skfda.representation.basis.FDataBasis.html)
FDataBasis型は、離散的なデータを基底関数で分解し、その結果を表現するための型です。この型は、使用された基底関数の種類と、各基底関数に対する係数を保持します。

FDataGrid型が離散的だけれどもすべてのデータを保有しているのに対して、
FDataBasis型は連続関数として、基底表現であらわされており、各基底の係数しか保有しておりません。

FDataGrid型とFDataBasis型はお互い変換が可能です。

#### FDataGrid型 ⇒ FDataBasis型　への変換

表現したい基底を定義してから、FDataGrid型のXに対してto_basisをかけることでFDataBasis型に変換します。
```.py
F_basis = skfda.representation.basis.FourierBasis(n_basis=20)
# Fourie基底で当てはめ
X_basis = X.to_basis(F_basis)
```

逆にFDataBasis型にした関数データをFDataGrid型に変換することもできます。
連続した関数のデータを特定の感覚で抜き取るイメージですね。

これは公式ドキュメントからコード例を抜き出します。
以下は標準基底で定義されたFDataBasisを、抜き取り点（Grid）を決めてFDataGrid型に変換しているコード
```.py
from skfda.representation.basis import(
    FDataBasis,
    MonomialBasis,
)
fd = FDataBasis(
    coefficients=[[1, 1, 1], [1, 0, 1]],
    basis=MonomialBasis(domain_range=(0,5), n_basis=3),
)
fd.to_grid([0, 1, 2])
FDataGrid(
    array([[[ 1.],
            [ 3.],
            [ 7.]],
           [[ 1.],
            [ 2.],
            [ 5.]]]),
    grid_points=(array([ 0., 1., 2.]),),
    domain_range=((0.0, 5.0),),
    ...)
```

全体像としては、FDataGrid型とFDataBasis型の特徴や変換の仕方を理解することが非常に重要です。
大きな流れとしては、
1. 手持ちデータをFDataGrid型に変換
2. 基底を定義
2. FDataGrid型をFDataBasis型に変換
2. FPCAを行ったり微分をしたりで関数の形や特徴を捉える。
2. 特徴量エンジニアリングをしたりして、回帰にかける

特に公式ドキュメントがかなり充実しているので、
Tutorialは一読して、Exampleは気になるやつを読みましょう。
APIReferenceは、
<dl>
  <dt>Attributes</dt>
  <dd>そのクラスの属性（例えばfd.basisと書くと基底の種類を表示できる）</dd>
  <dt>Parameters</dt>
  <dd>そのクラスで定義できるパラメータ（例えば基底の種類や数など）</dd>
  <dt>Methods</dt>
  <dd>そのクラスに対して実行可能なメソッド</dd>
</dl>

の順で細かく書かれているので、参考にしてください。

以上、初めての技術ブログですのでまとまりありませんが、いつかの自分の参考になれば。


### 追記　関数主成分分析
関数主成分分析も同様に、FPCAクラスを宣言した後FDataBasis型に当てはめます。

```.py
fpca = skfda.preprocessing.dim_reduction.feature_extraction.FPCA(
n_components=2, # n_componentsは主成分の次数
)
fpca.fit(X)
```
当てはめてしまえば、以下のように寄与率や固有値を得ることができます。
```.py
# 主成分関数を描く
fpca.components_.plot()
# 寄与率
fpca.explained_variance_ratio_ 
# 固有値
fpca.singular_values_
# 主成分スコアを取り出す
sore = fpca.transform(basis_fd)
```