配列

Pythonの「配列」は,通常は「リスト」(list)を使う。数値計算にはNumPyの array を使う。いずれもインデックスは 0 から始まる。

リスト

3個の要素からなるリストを作ってみる:

a = [3, 5, 7]
for i in range(3):
    print(a[i])
3
5
7

範囲外の要素,例えば a[3] にアクセスすると,IndexError: list index out of range というエラーになる。

同じ要素のリストなら次のようにして作るのが簡単:

a = [5] * 10   # 5が10個
a
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5]

アペンドを繰り返して作ることもできる:

a = []
for i in range(3, 8, 2):  # 3から始まり8未満2ずつ増える
    a.append(i)
a
[3, 5, 7]

上と同じことは次のようにも書ける(リスト内包表記,list comprehension):

a = [i for i in range(3, 8, 2)]
a
[3, 5, 7]

リストの要素は同じ型でなくてもよい。[3, 5, 'seven'] のようなリストも可能である。

行列はリストのリストとして作れる:

a = [[2, 9, 4], [7, 5, 3], [6, 1, 8]]
a[1][2]
3

NumPy の array

ベクトル・行列などの数値計算をより高速に行うにはNumPyの array を使う。

import numpy as np

a = np.array([3, 5, 7])
a
array([3, 5, 7])
type(a)
numpy.ndarray
a.dtype
dtype('int64')

一つでも浮動小数点数にすると,全部が浮動小数点数になる。

a = np.array([3, 5, 7.])
a
array([3., 5., 7.])
a.dtype
dtype('float64')

データ型を指定することもできる:

a = np.array([3, 5, 7], dtype="int8")  # 8ビット整数型
a
array([3, 5, 7], dtype=int8)

0 に初期化された長さ n の配列を作るには np.zeros(n) とする。同様に,1 に初期化された長さ n の配列は np.ones(n) である。初期化の必要がなければ np.empty(n) とする。行列は,n のところを例えば (m, n) のように (行数, 列数) とする。同様に任意次元の配列が作れる。

a = np.ones((2, 3))
a
array([[1., 1., 1.],
       [1., 1., 1.]])

各要素にアクセスするには a[i, j] でも a[i][j] でも(通常は)同じ意味であるが a[i, j] のほうが倍ほど速い:

a = np.empty((1000, 1000))

%timeit a[123][456]
%timeit a[123, 456]

Intel Mac mini で a[123][456] は 204ns,a[123, 456] は 108ns であった。M1 Mac mini ではそれぞれ 109ns,58ns であった。

ab が array なら,例えば a + b は要素ごとの和になる。つまり,ベクトルや行列の演算はループしなくても高速にできる。

a = a + ba + b を計算してそれに a という名前を付ける(古い a はアクセスできなくなる)。一方で,a += bab をその場で加える。大きな array の計算はこの方がメモリを節約できるし,速い:

a = np.empty((1000, 1000))
b = np.empty((1000, 1000))

%%timeit
global a, b
a = a + b  # または a += b

M1 Mac mini で a = a + b は 724µs,a += b は 331µs であった。

ベクトル・行列の生成は他に np.arange()(arange = array range)も使える:

np.arange(6)
array([0, 1, 2, 3, 4, 5])
np.arange(6).reshape(2, 3)  # 2行3列にする
array([[0, 1, 2],
       [3, 4, 5]])

np.arange(3)array([0, 1, 2]) だが np.arange(3.) は浮動小数点の array([0., 1., 2.]) になる。

np.empty(n, dtype="int8") などのようにデータ型を指定することができる。

乱数のベクトルの生成は乱数を参照のこと。

PyTorch や Tensorflow のテンソル

PyTorch や Tensorflow などの機械学習ライブラリでは「テンソル」(tensor)というものを使う。これも要するに配列である。

PyTorch なら import torch して,np.array() の代わりに torch.tensor() を,np.ones() の代わりに torch.ones() を使うなどとすればよい。


Last modified: