質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.92%

PCAのinverse_transformは何をしているのかが知りたい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 201

ttt_

score 5

pythonでPCAを学んでいますが、inverse_transform関数で何を行っているのかが分からず質問しました。

下記のようにinverse_transform関数を使うと、2次元に削減したデータが元の3次元に戻ります。

次元が同じだけでデータの値は元の数値と異なりますが、この関数では元のデータに戻す関数なのでしょうか。
仮に元ののデータを推測して戻しているのだとしたらどのように戻しているのでしょうか。
PCAのinspect.getsource関数で中を見てみましたが、分かりませんでした。

分かる方がいたら教えてください。
宜しくお願いします。

import numpy as np
from sklearn.decomposition import PCA

df = np.random.randn(6, 3)

pca = PCA(n_components=2)
pca.fit(df)
feature = pca.transform(df)
pca.inverse_transform(feature)
from sklearn.decomposition import PCA
import inspect
print(inspect.getsource(PCA)) 

追記
下記のコードで関数の中身が見れらしたが、self.whitenが何を指しているのかが分かりませんでした。
whiten : bool, optional (default False)
When True (False by default) the components_ vectors are multiplied
by the square root of n_samples and then divided by the singular values
to ensure uncorrelated outputs with unit component-wise variances.

import inspect
inspect.getsource(PCA.inverse_transform)
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

PCA.inverse_transform()の動作

PCA.transform()は主成分(分散の大きな軸)を見つけてそれを主軸とするような変換を行います。変換された値に対してPCA.inverse_transform()を行うと、元の変換される前の値を返します。

例として2次元平面上での理想的な楕円をPCA.transform()を行うとどうなるか、そしてさらに変換された値にPCA.inverse_transform()を行うとどうなるかを示します。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA


def make_ellipse(a, b, theta):
    rad = np.radians(theta)
    c = np.cos(rad)
    s = np.sin(rad)
    r = np.array([[c, -s], [s, c]])
    data = np.empty(shape=(360, 2))
    for deg in range(0, 360, 1):
        rad = np.radians(deg)
        pos = np.array([a * np.cos(rad), b * np.sin(rad)])
        data[deg, :] = r @ pos
    return data


def main():
    X0 = make_ellipse(1.0, 0.5, 30)
    pca = PCA(n_components=2)
    pca.fit(X0)
    X1 = pca.transform(X0)
    X2 = pca.inverse_transform(X1)
    X = np.array([X0, X1, X2])

    fig, ax = plt.subplots(1, 3, figsize=(12, 4), sharey=True)
    for i in range(3):
        ax[i].plot(X[i, :, 0], X[i, :, 1])
        ax[i].set_xlim(-1.5, 1.5)
        ax[i].set_ylim(-1.5, 1.5)
    ax[0].set_title("X0: Original")
    ax[1].set_title("X1: pca.transform(X0)")
    ax[2].set_title("X2: pca.inverse_transeform(X1)")
    plt.show()


if __name__ == "__main__":
    main()

PCA.inverse_transform()の実験

低次元から高次元へ戻る仕組み

簡単に言うと、N個のデータ、M個の特徴量に対してP次元のPCAを適用した場合

(N x P) = (N x M) (M x P)  # (変換後) = (変換前) (変換行列)

となっています。変換行列(M x P)を覚えておいて、inverse_transform()する際には

(N x M) = (N x P) (P x M)  # (変換前) = (変換後) (変換行列の転置行列)

を行っているだけです。

ソースコードの方を参照されているので詳しく説明します。入力データX0のデータ数をN, 特徴量の数をMとすると

X0.shape == (N, M)


です。これにPCAの要素数をPとすると、pca.transform()後のX1は

X1.shape == (N, P)


となります。このときPCAの内部ではfit()時に各々分散を計算して大きい順にP個保持しています。

explained_variance_.shape == (P, )  # 1次元配列


np.newaxisは次元を1つ追加しますので

explained_variance_[:, np.newaxis].shape == (P, 1)


と2次元配列になります。要素数P個は変わりません。

また主成分の係数components_

components_.shape == (P, M)


になっています。この2つを掛け算すると

(explained_variance_[:, np.newaxis] * components_).shape == (P, M)


となります。これはP個の分散の値をcomponents_の各行に掛け算しています。
np.sqrt()は次元を変えませんので、最終的に

np.dot(X, np.sqrt(self.explained_variance_[:, np.newaxis])


を計算することができます。Xは次元が減ったX1.shape == (N, P)のことですので、内積は(N, P) . (P, M) となり、演算結果の行列は(N, M)となります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/20 09:27

    大変詳しく説明してくださりありがとうございます。
    inverse_transform()についてよくわかりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る