2014年2月11日火曜日

行列の対角化とは何か?

はじめてのパターン認識」の観測データの無相関化の節を読んでいて、行列の対角化ってなんだっけ?という、そもそものところでつまづいたので(※1)、行列の対角化について、ここで少し整理しようと思う。

今回は純粋に線形代数学の話題に終始して、本来のデータの無相関化については、また後日書く予定。

■対角化を理解するまでの道筋

すこし長くなるので、「行列の対角化とは何か?」を理解するための道筋を整理すると
  1. 固有値と固有ベクトルの意味を理解する。
  2. 固有ベクトルを並べた変換行列の性質を理解する。
  3. 対角化操作を理解する。
になると思う。というわけでこの道筋に従って話しを進めようと思う。
なお、ここでは話しの分かりやすさを優先するので、数学的な一般性(※2)はひとまずおいておいて、わかりやすいシチュエーションの話だけをしていきたいと思います。一般的な状況でのより詳しいことはここ(PDF)を参照すると良いです。(上記、1、2の話題について、非常にわかりやすく整理&説明されています。)


■固有値と固有ベクトルの意味を理解する。

▼固有値と固有ベクトルの定義

まずは、固有値、固有ベクトルを定義をしておくと以下のとおり。
任意の正方行列 \(A\) について, \(A \mathbf{v} = \lambda \mathbf{v}\)を満たす \(\lambda \) を\(A \) の固有値といい、\(\mathbf{v} \) を\(A \) の固有ベクトルという.
n次の正方行列にはn個の固有値とそれに対応した固有ベクトルを持つ(※3)。

▼固有値と固有ベクトルの意味

上記の定義だけだといまいちなので、これらが図形的に何を意味しているのかを少し説明しておく。
一般にベクトル\(\mathbf{v} \) に行列\(A \)を作用させるということは、ベクトルを線形変換しそのベクトルの「方向」と「長さ」を変更する操作にあたる。

たとえば、
行列\(A=\left(
\begin{array}{cc}
3 & 1 \\
2 & 4 \\
\end{array}
\right)\)
をベクトル \(\mathbf{v} = (5, 1)^T\) (下図:青)に作用させた場合、作用後のベクトルは\(A\mathbf{v} = (16, 14)^T\)(下図:赤)になる。行列を作用させることによって方向と長さが変更されたことがもわかる。



今回は2次元行列を考えているので、2次元の\(\mathbb{R}^2\)空間でのベクトルは(2つ特別なベクトルを除いて)どんなベクトルも上の例と同じように方向が変更される。

その2つの特殊なベクトルが固有ベクトルであるわけだ。

固有ベクトルの定義を見直すとわかるとおり、固有ベクトルに行列\(A \)を作用させても、元のベクトルの定数倍(固有値倍)にしかならない。つまり「方向が変更されない」のである。

実際の例を見てみよう。行列\(A \)の固有値は、\(\lambda_1 = 5\), \(\lambda_1 = 2\)の2つであり、それに対応する固有ベクトルは、\(\mathbf{u}_1 = (1, 2)^T\), \(\mathbf{u}_2 = (1, -1)^T\)である(※4)。例えばそのうちの1つの固有ベクトル\((1,2)^T\)に行列\(A \)を作用させると\((5,10)^T=5(1,2)^T\)であり元のベクトルの固有値(定数)倍で方向は変わらないのである。下図はそれを図示したもので、青が行列\(A \)作用前、赤が作用後のベクトルとなっている。わざわざ図示するまでもないけれど、方向に変化がないことがわかる。



\(\mathbf{x} = a_1 \mathbf{u}_1 +  a_2 \mathbf{u}_2\)
というように、固有ベクトルを線形結合することで、2次元\(\mathbb{R}^2\)空間の任意のベクトル\(\mathbf{x}\)が表現できることに注意すると、任意のベクトルに行列\(A \)を作用させるということは、
\(A\mathbf{x} = a_1 A \mathbf{u}_1 +  a_2 A \mathbf{u}_2 = a_1 \lambda_1 \mathbf{u}_1 +  a_2 \lambda_2 \mathbf{u}_2\)
であり、それぞれの固有ベクトル方向に固有値倍ずつ伸縮結果に他ならない。

■固有ベクトルを並べた変換行列の性質を理解する

行列Aに、一次独立なn個の固有ベクトルが存在し、それを並べた
\(P=(\mathbf{u}_1, \cdot\cdot\cdot , \mathbf{u}_n)\)
を考える。
このとき、基底ベクトル \(\mathbf{e}_i  (i = 1, 2, ..., n )\)に\(P\)を作用させると、
\(P\mathbf{e}_i = \mathbf{u}_i\)
と固有ベクトルに変換されることがわかる。
結果、任意のベクトル
\(\mathbf{x} = \sum_{i=1}^n a_n \mathbf{e}_i\)
に\(P\)を作用させると
\(P\mathbf{x} = P \sum_{i=1}^n a_n \mathbf{e}_i = \sum_{i=1}^n a_n P\mathbf{e}_i  = \sum_{i=1}^n a_n \mathbf{u}_i \)
と変換される。

先述の具体的な行列を例に見ていく。
固有値ベクトルを並べた変換行列\(P = (\mathbf{u}_1,\mathbf{u}_2)\)を考える。この行列を基底ベクトル、
\(\mathbf{e}_1 = (1, 0)^T\),\(\mathbf{e}_2 = (0, 1)^T\)
に作用させると、
\(P\mathbf{e}_1 = (1, 2)^T = \mathbf{u}_1\), \(P\mathbf{e}_2 = (1, -1)^T = \mathbf{u}_2\)
となり、基底を固有空間に移す行列になっていることがわかる。
例えば、
\(\mathbf{x} = (5, 1)^T = 5\mathbf{e}_1+ \mathbf{e}_2 \)
に\(P\)を作用させると、
\(P\mathbf{x} = 5\mathbf{u}_1+\mathbf{u}_2\)
となる。


■対角化操作

上記のように、変換行列を書けることで、任意のベクトルを基底\(\mathbf{e}_i  (i = 1, 2, ..., n )\)での表現から、行列Aの固有ベクトルの固有空間の表現に変換される。
このような変換後、行列Aを作用させると\(\mathbf{u}_i\)は向きが変わらず、長さが \(\lambda_i\)倍になるだけ。
\[AP\mathbf{x} = A \sum_{i=1}^n a_n \mathbf{u}_i = \sum_{i=1}^n \lambda_i a_i \mathbf{u}_i \]
これにさらに\(P^{-1}\)を作用させると\(\mathbf{u}_i\)は元の\(\mathbf{e}_i\)に戻り、
\[P^{-1}AP\mathbf{x} = \sum_{i=1}^n \lambda_i a_i P^{-1}\mathbf{u}_i = \sum_{i=1}^n \lambda_i a_i \mathbf{e}_i \ = D\mathbf{x}\]
ここで、
\[
  D = \left(
    \begin{array}{cccc}
      \lambda_1 & 0         & \cdots & 0 \\
      0         & \lambda_1 & \cdots & 0 \\
      \vdots    & \vdots    & \ddots & 0 \\
      0         & 0         & \cdots & \lambda_n
    \end{array}
  \right)
\]

となり、\(P^{-1}AP\)が対角化行列となるわけである。


(追伸)
ここで使った図はpython&matplotlibを使って描いた。そのソースはここを参照のこと。

  • (※1)昔は、嫌というほど線形代数学を勉強したのに、情けない話だ・・・
  • (※2)固有値が重解になる場合はどうなんだ、とかそんな話。
  • (※3)固有値が重解を持つ場合などは、一見 n個よりも少ない固有値しかないようにみえることもあるが・・・。また、回転行列は実数の固有値はないが、複素数まで考えるとちゃんと固有値を持つ。
  • (※4)求め方はやはりここ(PDF)が参考になる。
  • (※5)つまり、2つの固有ベクトルが2次元\(\mathbb{R}^2\)空間の基底であるということ。

2014年2月4日火曜日

rpy2をインストールする。

IPython NotebookからRを利用するためには、Rmagicという機能拡張を使えばいいとのことなのだけど、これがrpy2というライブラリを使うため、これをインストールしなくてはならない。
折角なので、今回行ったインストール手順をまとめておく。

■インストール

▼前提

Windows7で、pythonとRはインストールされているものとする。

▼RのPATHを設定しておく。

これをしないと・・・
  • インストールの時に「Error: Tried to guess R's HOME but no R command in the PATH.」と、Rが見つからないよ!と怒られます。
  • pythonでモジュールをimportする際に、「RuntimeError: R_HOME not defined.」とか、「RuntimeError: R_USER not defined.」とか怒られます。
スタート>「コンピューター」を右クリック>プロパティ>左パネルの「システムの詳細設定」>環境変数 を開きます。その画面で次の3つを設定。

  • ユーザー環境変数のPATHを編集し、R.exeのあるbinフォルダをセミコロンで区切って末尾に追記します。つまり「;C:\Program Files\R\R-2.15.3\bin」(←僕の環境の場合)を末尾に追加する。
  • システム環境変数で、以下のPATHを追加。
    • 変数名「R_HOME」、変数値「C:\Program Files\R\R-2.15.3」(←僕の環境の場合)
    • 変数名「R_USER」、変数値「xxxx」(xxxxはWindowsのログイン名)

▼pipでインストール

上記で環境変数を指定した後、コマンドプロンプト(*1)を開き
$pip install rpy2
と打つ。簡単!


▼pipでエラーが出る場合・・・

環境によっては、pipでインストールしようとしたら、
"C:\PROGRA~1\R\R-215~1.3\bin\R" CMD config --ldflags
Invalid substring


みたいなエラーが出る場合がある(*2)。
この場合は、このページの環境に合わせたバイナリ(僕の環境の場合はrpy2 2.3.9.win32 py2.7.exe)をダウンロードし、あとはダブルクリックでインストールすればよい模様(参考)。

▼確認

コマンドプロンプトなりでpythonを起動して
import rpy2.robjects as robjects
を打って、エラーとかでないと、とりあえずインストール成功!

■Rmagic

rpy2をインストールしたら、IPython NotebookでRmagicを使ってRのコマンドが使えるようになる。
使い方はココが分かりやすい。


(*1)Windows標準のコマンドプロントでもいいし、scipyスタックのanacondaを使ってる場合、「anaconda command prompt」でもいい。ただしどちらの場合も、環境変数の更新を行った場合には、プロンプトを開きなおさないと環境変数の設定変更が反映されないことに注意!(これでだいぶハマッた)

(*2) 僕の職場のPCへのインストールはこれでハマる (+_+)。

2014年2月2日日曜日

科学計算用のscipyスタック(anaconda)

科学計算用(というより統計や機械学習系)のpython環境をwindowsにつくろうとして、いろいろ調べていると、scipyスタック(*1) として「anaconda」というものが存在することを知った

このanaconda、かなり便利でこれ1つインストールするだけで、主なところで、
  • python 2.7.5
  • theano 0.5.0 L
  • numpy 1.7.1
  • scipy 0.13.0
  • pip 1.4.1
  • matplotlib 1.3.1
  • pandas 0.12.0
とかが一緒にインストールされる。(全パッケージ情報はここ参照)

■インストール方法(Windows)

インストール方法は全くもって簡単で、ここからwindows用インストーラーをダウンロード。ダウンロードしたインストーラーをダブルクリックで起動するだけ。

インストール中は、基本的に画面に従ってデフォルト設定で「次へ」を押していけばいいが、一点だけ注意が必要で、英語で「自分のみにインストールするか?(推奨)、それともシステム全体にインストールするか?」と聞かれる箇所がある。この時デフォルトの設定では「システム全体にインストール」側にチェックが入っているので、推奨の「自分のみにインストール」をしたければ、チェックを付替えてから「次へ」でインストールを進める。

■動作確認

インストールが終わったら、「スタートボタン>全てのプログラム」に「Anaconda」の項目がある。
例えば、「Annaconda Command Prompt」を選択し、コンソールから
$python -V
と入力してバージョン情報が表示されれば、ひとまずインストールは成功。

また、anaconda本体は、「自分のみにインストール」を選択してインストールした場合、
「C:\Users\[XXX]\Anaconda」
以下にインストールされている。(ここで[XXX]はあなたのユーザーネーム)

これだけ簡単にインストールできるとなると、pythonでのデータ分析とかの敷居がどんどん低くなっていくなーと感じる。

■パッケージをアップデート

Anacondaで使われているパッケージは若干古いバージョンのものも含まれるので、使うパッケージは最新版にアップデートしておいた方がよい。Anacondaは独自のパッケージ管理ツール「conda」で管理されるので、例えばpandasを最新版にアップデートしたい場合は、
「Annaconda Command Prompt」を起動し、コンソールから
$conda update pandas
を実行すればOK。依存するパッケージも自動でアップデートしてくれる。
また、condaで管理していないパッケージについては、従来どおりpipでアップデートも可能。