こんにちは! プログラマーのakiraです。
PythonではリストやNumPyを使用して、行列の計算を行うことができます。
「Pythonの行列ってなんだろう?」
「機械学習で行列ってどういう時に使うんだろう?」
と疑問に思ったことはないでしょうか?
そんな方に向けて、本記事では以下の内容で解説していきます!
【基礎】行列とは
【実践】行列計算をしてみよう!
【応用】機会学習で行列を使用する例
Pythonで行列計算を行うと、基本的な計算から複雑なものまで簡単に行うことができます!
是非参考にしてください!
本記事を読む前に、Pythonがどんなプログラミング言語なのかをおさらいしておきたい人は次の記事を参考にしてください。
→ Pythonとは?特徴やできること、活用例をわかりやすく簡単に解説
なお、その他のPythonの記事についてはこちらにまとめています。
行列とは
行列とはその名前の通り、横(行)と縦(列)方向の並びのからなる以下のような2次元のデータです。
行列計算は、学生の時に学びましたよね?
難しくありませんでしたか?
もし学生時代に行列計算が苦手だった方も、計算自体は単純なものですので、Pythonのプログラミングと一緒に行列計算もマスターしちゃいましょう!
Pythonで行列を扱う方法は大まかに分けて
・ リストの要素としてリストを使用する
・ NumPyを使用する
の方法があります。
次項からそれぞれの行列の扱い方について詳しく見ていきましょう!
Pythonでの行列の作成方法
リストで行列を作成する!
それではPythonのリストを使用して行列を作成してみましょう!
以下のように、Pythonのリストの要素としてさらにリストを追加すると行列(2次元配列)として作成することができます。
list_arr1 = [[1, 2], [3, 4]] print('行列1: {}'.format(list_arr1))
実行結果
行列1: [[1, 2], [3, 4]]
また行列計算でよく使用する転置は以下のようにして行うことができます。
list_arr2 = [[1, 2], [3, 4]] print('転置: {}'.format(list(zip(*list_arr2))))
実行結果
転置: [(1, 3), (2, 4)]
それでは試しに行列1と行列2を作成して、行列の積を計算してみましょう!
行列1と行列2(転置)をfor文でループして計算することにより、行列の計算結果を取得しています!
list_arr1 = [[1, 2], [3, 4]] list_arr2 = [[1, 2], [3, 4]] result = [] for k, v in list_arr1: tmp = [] for kk, vv in zip(*list_arr2): tmp.append(k * kk + v * vv) result.append(tmp) print(result)
実行結果
[[7, 10], [15, 22]]
NumPyを使用して行列を作成する!
今度は、Pythonの学術計算ライブラリであるNumPyを使用して行列計算をしてみましょう!
NumPyはNumPy配列(ndarrayと呼ばれている)を使用し、少ないコード量で様々な数値計算が簡単に行えるようになっています。
またNumPyはとても高速であるため、大量のデータを扱う場合など、Pythonを使いこなすには必須のライブラリでもあります。
それでは、NumPyを使用した行列の作成方法を見ていきましょう!
np.array()でNumPy配列(ndarray)を生成します。
import numpy as np np_arr1 = np.array([[1, 2], [3, 4]]) print(np_arr1)
実行結果
[[1 2] [3 4]]
NumPyの転置は.Tようにして簡単にできます!
import numpy as np np_arr = np.array([[1, 2], [3, 4]]) print(np_arr.T)
実行結果
[[1 3] [2 4]]
先程と同様に行列の積を計算してみましょう!
NumPyでは以下のように計算することができます!
import numpy as np np_arr = np.array([[1, 2], [3, 4]]) result = np.dot(np_arr, np_arr) print(result)
実行結果
[[ 7 10] [15 22]]
行列をリストで扱う方法と比べるとNumPyを使用した方法は、とても簡単に計算できることがわかって頂けたかと思います!
次項以降では、このNumPyを使用した行列計算の方法について様々な計算を試してきましょう!
NumPyの計算についてより詳しく知りたい方はこちらの記事でも紹介していますので参考にしてみてください。
行列操作の基本を学習しよう!
ここではNumPyを使用する上で必要となる基本的な使い方について確認しておきましょう!
行列の次元ごとの要素数(形状)を確認しよう!
行列を扱うのに「行の要素がいくつあるのか」「列の要素がいくつあるのか」など、行列がどんな形をしているのか調べたい時がありますよね!
行列の要素数を取得するには、以下のサンプルコードのようにshapeを使用します!
それぞれarr1は2×2、arr2は2×4の行列であることがわかります。
import numpy as np arr1 = np.array([[1, 2], [3, 4]]) arr2 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]]) print(arr1.shape) print(arr2.shape)
実行結果
(2, 2) (2, 4)
行列のサイズを確認しよう!
行列の要素の数は、sizeを使用することで確認することができます。
import numpy as np arr1 = np.array([[1, 2], [3, 4]]) arr2 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]]) print(arr1.size) print(arr2.size)
実行結果
4 8
NumPyのsizeについてより詳しく知りたい方は、こちらの記事でも紹介されています!
行列を指定した形に変換しよう!
行列の形状を変更したい場合は、reshapeで変更することができます。
arr1は2×2から1×4へ、arr2は2×4から4×2へ変換しています!
import numpy as np arr1 = np.array([[1, 2], [3, 4]]) arr2 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]]) print(arr1.reshape(1, 4)) print(arr2.reshape(4, 2))
実行結果
[[1 2 3 4]] [[1 2] [3 4] [5 6] [7 8]]
行列を転置(行と列の入れ替え)をしてみよう!
行列の転置(行と列を入れ替える)は、Tまたはtranspose()ですることができます!
以下サンプルコードでそれぞれの実行結果を出力しています。
import numpy as np arr1 = np.array([[1, 2], [3, 4]]) arr2 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]]) print("転置T") print(arr1.T) print(arr2.T) print("転置transpose()") print(arr1.transpose()) print(arr2.transpose())
実行結果
転置T [[1 3] [2 4]] [[1 5] [2 6] [3 7] [4 8]] 転置transpose() [[1 3] [2 4]] [[1 5] [2 6] [3 7] [4 8]]
実行結果から、行と列が入れ替わっているのがわかりますか?
転置によって、arr1、arr2に定義した行列を入れ替えることができるのです!
行列計算をしてみよう!
それでは行列の計算方法について詳しく見ていきましょう!
行列の足し算、引き算をやってみよう!
行列の足し算、引き算は、通常の計算方法と変わりません。
行列の各要素を足したり、引いた結果を求めることができます。
以下、それぞれのサンプルコードについて見ていきましょう!
・ 足し算
import numpy as np arr1 = np.arange(1, 5).reshape((2, 2)) arr2 = np.arange(5, 9).reshape((2, 2)) print('arr1') print(arr1) print('arr2') print(arr2) result = arr1 + arr2 print("足し算 結果") print(result)
実行結果
arr1 [[1 2] [3 4]] arr2 [[5 6] [7 8]] 足し算 結果 [[ 6 8] [10 12]]
・ 引き算
import numpy as np arr1 = np.arange(1, 5).reshape((2, 2)) arr2 = np.arange(5, 9).reshape((2, 2)) print('arr1') print(arr1) print('arr2') print(arr2) result = arr2 - arr1 print("引き算 結果") print(result)
実行結果
arr1 [[1 2] [3 4]] arr2 [[5 6] [7 8]] 引き算 結果 [[4 4] [4 4]]
arr1、arr2のそれぞれの要素同士で足し算、引き算が行われているのがわかったかと思います!
行列の掛け算(積)をやってみよう!
行列の掛け算には、各要素同士を単純に掛けたものと、行列の積を求める場合と2パターンあります。
それぞれのやり方と違いについて確認していきましょう!
・ 各要素の掛け算
それぞれの行列を「*」を使って掛け算を行っています。
各行列の要素同士で掛け算が行われていることが実行結果からわかります!
import numpy as np arr1 = np.arange(1, 5).reshape((2, 2)) arr2 = np.arange(5, 9).reshape((2, 2)) print('arr1') print(arr1) print('arr2') print(arr2) result = arr1 * arr2 print("掛け算 結果") print(result)
実行結果
arr1 [[1 2] [3 4]] arr2 [[5 6] [7 8]] 掛け算 結果 [[ 5 12] [21 32]]
・ 行列の積
こちらはnp.dot()を使用して計算をしています。
実行結果には、行列の積の計算結果が確認できるかと思います。
高校の数学などで習った計算方法ですね!
import numpy as np arr1 = np.arange(1, 5).reshape((2, 2)) arr2 = np.arange(5, 9).reshape((2, 2)) print('arr1') print(arr1) print('arr2') print(arr2) result = np.dot(arr1, arr2) print("掛け算 結果") print(result)
実行結果
arr1 [[1 2] [3 4]] arr2 [[5 6] [7 8]] 掛け算 結果 [[19 22] [43 50]]
行列の割り算をやってみよう!
行列の割り算は各要素を割った結果になりますので、通常の割り算とほとんど変わりません!
サンプルコードを見ていきましょう!
import numpy as np arr1 = np.full((2, 2), 10) arr2 = np.full((2, 2), 2) print('arr1') print(arr1) print('arr2') print(arr2) result = arr1 // arr2 print("割り算 結果") print(result)
実行結果
arr1 [[10 10] [10 10]] arr2 [[2 2] [2 2]] 割り算 結果 [[5 5] [5 5]]
各要素を割った結果が正しく求められていますね!
NumPyの計算方法について詳しく知りたい方はこちらの記事でも紹介していますので参考にしてみてください!
画像データをNumPy行列で扱ってみよう!
何で画像データを行列で扱うのか?
ここまでNumPyを使用して行列の使い方について学習してきましたが
・ そもそも行列って何に使うの?
・ Pythonの機械学習でNumPy行列(配列)を扱うと聞いたけど、どういうこと?
と疑問の方もいるかと思いますので、画像データ処理を一例として紹介していきます。
まず何で画像データをNumPy配列で扱うのかについて説明します。
画像データを読み込んでNumPy配列として扱うことによって、NumPyの機能で様々な処理を行うことができるようになるのです!
またPythonのNumPyデータとして画像を保持できるため、プログラミングでの処理で大変扱いやすくなるのです!
次項で画像をNumPy配列に変換してみましょう!
実際に画像データをNumPy配列に変換してみよう!
それでは行列操作のまとめてとして、画像データをNumPy配列に変換してみましょう!
画像の読み込みは、pillowを使用しています!
Image.open()を使用することで簡単に画像を読み込むことができます!
また今回は読み込む画像として、本記事の序文で使用した行列の画像を使用しています。
サンプルコードでは、画像を読み込んだ後に画像をリサイズし、NumPyの配列(3次元の配列)に変換しています。
その後、変換した画像配列をリストに10回詰めて、ファイルとして保存しています。
pillowについて詳しく学習したい方はこちらの記事に記載されています。
import numpy as np from PIL import Image X = [] image_size = 50 image_path = './matrix.png' image = Image.open(image_path) image = image.resize((image_size, image_size)) image = np.asarray(image) for _ in range(10): X.append(image) np.save('save.npy', X)
リサイズされた10枚の画像が「save.npy」の1ファイルに保存されていますのでかなりポータブルになったと思います!
それでは今度は、「save.npy」を読み込んで、画像として出力してみましょう!
np.load()でファイルを読み込み、for文でリストの要素をループして1画像ずつ処理をしています!
先程作成した10枚のリサイズされた画像がカレントディレクトリに作成されるかと思います!
import numpy as np from PIL import Image save_path = './save.npy' for k, np_img in enumerate(np.load(save_path)): image = Image.fromarray(np_img) image.save('./change{}.png'.format(k))
まとめ
いかがでしたでしょうか。
今回は、Pythonの行列について学習しました。
NumPyでの行列の操作は、複雑な計算処理や機械学習などでも使用されていてPythonを扱う上ではとても重要なものとなりますので、しっかりとマスターしていきましょう!