ここでは、pythonプログラミングの基本である、Numpyと行列について解説します。まずは、Google Colaboratoryの使い方 を参考に、プログラミングの環境に移動しましょう。ローカルに環境を構築している方は、そちらでもokです。
Numpyとは
様々な計算を行うためのライブラリ(便利な関数が詰まったパックのようなもの)の1つにnumpyがあります。ここでは、numpyの使用方法について簡単に解説します。
行列とは
Numpyでは行列の扱いを主体的に行います。これを理解するために、まずは行と列の概念を説明します。はじめに以下の表をみてください。
0行0列目 | 0行1列目 | 0行2列目 |
1行0列目 | 1行1列目 | 1行2列目 |
2行0列目 | 2行1列目 | 2行2列目 |
3行0列目 | 3行1列目 | 3行2列目 |
行数が4、列数が3ですから、4行3列の行列と表現します。これだけ聞くとすんなり理解できると思いますが、初学者が自分で行列を考えるとき、上から下に増えていく方、左から右に増えていく方、どちらが行でどちらが列なのかわからなくなることが多いようです。これに同意する方は、横書きのノートを思い浮かべてください。横書きのノートでは、通常、上から下に文字を書いていくと思います。このとき、文章の進みを行と呼ぶでしょうか?それとも列と呼ぶでしょうか?
おそらく、多くの人は横書きのノートについて、上から下に進むたび、1行、2行…と読んでいくと思います。行列も同様に、上から下にいくごとに行数が増えていきます。そうすると、左から右に増えていくものを列と呼ぶことを受け入れることができると思います。
続いて、行列の開始地点について説明します。ノートの場合は1行2行と呼びますが、一般的なプログラミング言語では0を開始地点とします(これは、以前説明したリストでも同様でした)。そのため、上に示した行列の左上が0行0列目となるわけです。0が開始地点になるので、4行3列の行列には、3行目・2列目までしかないことになります。行列のサイズが4行3列だからといって、4行目と3列目があるとは思わないようにしましょう。
すべての要素が0である行列の定義
それでは、numpyを利用して行列を定義していく方法を説明します。はじめに、numpyを利用できるようにするため、以下のコードを記載し、実行してみましょう。
import numpy as np
何も起こりませんが、これには重要な意味があります。それは、numpyのライブラリにある関数を、npという略語で使用可能とするというものです(npの部分は自由に決めることができますが、慣例としてnpが利用されます)。少しわかりにくいので、次のコードを実行してみましょう。
a = np.zeros([2, 3])
print(a)
ディスプレイ上に、2行3列の行列が表示されたと思います。また、個々の要素はすべて0となります。np.zerosは行列を定義する関数の1つで、引数として指定したサイズ、すべての要素を0とした行列を作ることができます。
すべての要素が1である行列の定義
0ではなく1で埋めた行列も定義することができます。これは下記のように記載します。zeros関数ではなく、ones関数を利用します。
b = np.ones([2, 3])
print(b)
任意の要素・サイズの行列の定義
以下のように記載することで、自分の好きな行列を作ることができます。
c = np.array([ [1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
print(c)
- 0行目: 1, 2, 3
- 1行目: 4, 5, 6
- 2行目: 7, 8, 9
- 3行目: 10, 11, 12
となる行列が定義されたことがわかると思います。
次元数・サイズの確認方法
numpyで定義した変数において、その次元数とサイズを確認するために、以下の関数を利用します(次元数の説明は後述します)。
- 次元数の確認: np.ndim
- サイズの確認: np.shape
この役割を確認するために、以下のコードを実行してみてください。
b = np.ones([2, 3])
dim_b = np.ndim(b)
size_b = np.shape(b)
print("変数bの次元数は", dim_b, "で、サイズは", size_b, "です。")
すると、
- 変数bの次元数は 2 で、サイズは (2, 3) です。
と表示されます。np.shapeにより、行列bのサイズが2行3列として調べられていることが確認できます。np.ndim関数で出てくる次元数2という結果は並びの数を意味しており、変数bが行と列の2つの並びを有していることを表しています。
このように書くと、2つの並び以外にもあるのかと疑問に思うと思います。この答えはYesであり、例えば下記のように記述すると、1つの並び、すなわち1次元の変数が定義されます。
e = np.ones([3])
dim_e = np.ndim(e)
size_e = np.shape(e)
print(e)
print("変数eの次元数は", dim_e, "で、サイズは", size_e, "です。")
これを実行すると、変数eは1が3つ並んだものであることがわかります。さらに、
- 変数eの次元数は 1 で、サイズは (3,) です。
と出力されます。変数eは、行列のような2つの並びを有しておらず、並びの数は1つのみです。したがって、np.ndim関数で得られる数値は1、すなわち1次元となります。また、1が3つ並んでいますので、サイズは3となります。次元数が1の変数は、行列とは呼ばず、ベクトルと呼ぶことが多いようです。
また、行列やベクトルをいちいち分けて呼ぶのは面倒なので、配列と表現することもあります。次元数を明白にしたい場合は、1次元配列、2次元配列などと表現します。少し複雑になってきたので、下記の通り整理しておきます。
- 1つの並びを有する変数 = 1次元配列 = ベクトル(np.ndimで調べると、次元数が1となるもの。サイズは不問)
- 2つの並びを有する変数 = 2次元配列 = 行列(np.ndimで調べると、次元数が2となるもの。サイズは不問)
他にも3次元以上の配列(テンソル)もありますが、初学者が触れても混乱するだけですので、解説記事では1, 2次元配列のみを扱うことにします。
ある規則に基づいたベクトル(1次元配列)の定義
以下は、2から10まで、3刻みで増えていく1次元配列を作るコードです。引数として、開始地点、終了地点、刻み幅を順番に入れることで機能します。
d = np.arange(2, 11, 3)
print(d)
これを実行すると、2, 5, 8と表示されます。3ずつ増えていることがわかると思います。なお、終了地点そのものは対象とならず、11よりも1つ前の数字である10までが考慮する対象となります。今回は8の次が11であるものの、11は考慮されませんので、11は含まれません。なお、arange関数は行と列の成分を持ちませんので、注意してください。試しに色々な数字を入れてみると、理解が早まると思います。
なお、np.arange関数は、1次元配列しか作ることができません。
配列の次元の変更
np.reshape関数を利用することで、1次元の配列を2次元に変換することができます。例えば、以下のコードを見てください。
a = np.array([1, 1, 1, 2, 2, 2])
変数aは、サイズが6の1次元配列となります。これを、
- 0行目: 1, 1, 1
- 1行目: 2, 2, 2
- → 次元数2、2行3列の行列(2次元配列)
にしてみたいと思います。これを実現するには、下記のように記載します。
a = np.array([1, 1, 1, 2, 2, 2])
b = np.reshape(a, [2, 3])
print(b)
これを実行すると、2行3列の行列に変換されたことを確認できます。ポイントとなるのがnp.reshape関数であり、これは第一引数に設定した変数aを、第二引数で設定したサイズ(今回は、[2, 3]が第二引数の値です)に変換する機能があります。これにより、
- 1, 1, 1, 2, 2, 2 の前半3つを0行目、後半3つを1行目
とする行列が出来上がります。注意が必要なのは、変換前の要素数と変換後の要素数が適合していなければならないという点です。変数aの要素数は6で、変数bの要素数もまた、2行3列の変換を指定していますので6となります。したがって、変換することが可能となります。
この観点から、意図的にエラーを出すコードは以下となります。
a = np.array([1, 1, 1, 2, 2, 2, 3, 3])
b = np.reshape(a, [2, 3])
print(b)
変数aの要素数が8個です。これでは、2行3列の行列に収めることができません。したがって、このコードはエラー終了します。np.reshape関数はとてもよく利用する関数なので、いくつか自分で動かしてみることをお勧めします。
おわりに
本記事ではnumpyの第一ステップとして、行列、ベクトル、配列について説明しました。この中で、np.zeros, np.ones, np.array, np.shape, np.reshape, np.ndimといった関数を新たに説明しました。少し量が多いので、自分で色々と試してみてから、次に進むとスムーズかもしれません。少し大変ですが頑張っていきましょう。
[…] ベーシック09 Numpy: 配列、ベクトル、行列、次元数、サイズ […]