【初心者向け】Python講師が高速計算ライブラリNumpyの使い方を解説

Pythonライブラリの一つ、Numpyについて説明していきます。
機械学習を行う上で、高速の演算処理は必要不可欠です。

Numpyとは?

Numpyとは配列(リスト)計算を高速で行うためのライブラリです。

講師
講師
進導エイリ
進導エイリ

何か難しそうですね・・・
普通のリストを使っての計算ではダメなんですか?

もちろんリストをそのまま使って計算しても構いません。
ですが、Pythonの特徴の1つとしてループ処理の遅さがあります。
通常のリストを用いてループ処理で計算をさせようとすると、他のプログラミング言語の方が早かったりします。
Pythonの代名詞である機械学習等は高速かつ大容量の計算処理が求められます。
Numpyがあるのでこの高速計算処理が可能になっているのです。

講師
講師
進導エイリ
進導エイリ

なるほど・・・
ということは機械学習の基盤となるライブラリなのですね!

NumPyは、Pythonの科学計算のための基本的なライブラリです。
多次元配列を処理することができるなど、数学、論理、並べ替え、選択、などさまざまなルーチンを提供します。

NumPyパッケージの中核には、ndarrayオブジェクトがあります。
これにより、同種のデータ型のn次元配列がカプセル化され、パフォーマンスのためにコンパイルされたコードで多くの操作が実行されます。

NumPy配列と標準のPythonシーケンスの間には、いくつかの重要な違いがあります。

・NumPy配列は、Pythonリスト(動的に大きくなる可能性があります)とは異なり、作成時に固定サイズになります。ndarrayのサイズを変更すると、新しい配列が作成され、元の配列が削除されます。
・NumPy配列の要素はすべて同じデータ型である必要があるため、メモリ内で同じサイズになります。ただし、オブジェクトの配列を持つことができるため、さまざまなサイズの要素の配列が可能になります。
・NumPy配列は、多数のデータに対する高度な数学およびその他のタイプの操作を容易にします。通常、このような操作は、Pythonの組み込みシーケンスを使用する場合よりも効率的かつ少ないコードで実行されます。
・多くの科学的および数学的なPythonベースのパッケージがNumPy配列を使用しています。これらは通常Pythonシーケンス入力をサポートしますが、処理前にそのような入力をNumPy配列に変換し、多くの場合NumPy配列を出力します。つまり、科学的/数学的なPythonベースのソフトウェアの多く(おそらくほとんど)を効率的に使用するには、NumPy配列の使用方法も知っている必要があります。

Numpy公式doc

Numpyのはじめ方

install

pip install numpy

※Google Colaboratoryではインストール不要

import

通常はnpという識別名を使って「import as」でインポートします。

# npとしてnumpyをimport
import numpy as np

Numpy配列の作り方

Numpyの呼び出しは<mark>import numpy as np</mark>に統一しましょう。 from numpy import *とするとPythonの組み込み関数と名前空間が重なる可能性が高くなります。そのためスコープは分けておくべきです。

original_data = [9, 2, 3, 4, 10, 6, 7, 8, 1, 5]
data = np.array(original_data)

print(data)
print(type(data))  # データ型
print(data.dtype)  # numpy.arrayの中の各要素のデータ型
print('次元数:', data.ndim)
print('要素数:', data.size)
print('形状(各次元のサイズ):', data.shape)
# 実行結果
[ 9  2  3  4 10  6  7  8  1  5]
<class 'numpy.ndarray'>
int64
次元数: 1
要素数: 10
形状(各次元のサイズ): (10,)

2次元のデータ(リスト in リスト)

# 2次元のデータ(リストのリスト)
original_data = [
    [9, 2, 3, 4, 10, 6, 7, 8, 1, 5],
    [9, 2, 3, 4, 10, 6, 7, 8, 1, 5],
]
data = np.array(original_data)

print(data)
print(type(data))
print(data.dtype)
print('次元数:', data.ndim)
print('要素数:', data.size)
print('形状(各次元のサイズ):', data.shape)
[[ 9  2  3  4 10  6  7  8  1  5]
 [ 9  2  3  4 10  6  7  8  1  5]]
<class 'numpy.ndarray'>
int64
次元数: 2
要素数: 20
形状(各次元のサイズ): (2, 10)

要素が全て整数の場合

# 要素が全て整数の場合
data = np.array([9, 2, 3, 4, 10, 6, 7, 8, 1, 5])
print(data)
print(data.dtype)
[ 9  2  3  4 10  6  7  8  1  5]
int64

要素が整数と小数と文字列の場合

# 要素が整数と小数と文字列の場合
data = np.array([9, 2, 3, 4, 10, 6.5, 7, "8", 1, 5])
print(data)
print(data.dtype)
['9' '2' '3' '4' '10' '6.5' '7' '8' '1' '5']
<U32
進導エイリ
進導エイリ

他の要素が整数なのに、小数や文字列が混じっているだけで
全体の型が変わってしまうのですか?

そうなんです。
これは計算処理をスムーズに行うために、全体の型を統一して見てくれているためです。
イレギュラーを起こさない便利な機能ですが、扱う際には型を確認する習慣をつけましょう。

講師
講師

キャスト

astype(‘型’) を使うとキャストすることができます。

original_data = [9, 2, 3, 4, 10, 6, 7, 8, 1, 5]
data = np.array(original_data)

print(data)
print(data.dtype)

data = data.astype('float64')  # ここでキャスト

print(data)
print(data.dtype)
# 実行結果
[ 9  2  3  4 10  6  7  8  1  5]
int64
[ 9.  2.  3.  4. 10.  6.  7.  8.  1.  5.]
float64

計算

numpy配列では、算術計算の方法がリストと違います。 この場合、ベクトル演算を行います。
つまり、同サイズの配列の場合同位置の要素どうしで計算されます。

d1 = np.array([1, 2, 3, 4, 5])
d2 = np.array([6, 7, 8, 9, 10])

print('2倍にする:', d1 * 2)  # 各要素を2倍
print('足し算:', d1 + d2)  # 各要素同士を加算
print('掛け算:', d1 * d2)  # 各要素を乗算
print('累乗:', d1**2)  # 各要素を二乗
print('割り算:', d2 / d1)  # 各要素を除算
# 実行結果
2倍にする: [ 2  4  6  8 10]
足し算: [ 7  9 11 13 15]
掛け算: [ 6 14 24 36 50]
累乗: [ 1  4  9 16 25]
割り算: [6.         3.5        2.66666667 2.25       2.        ]
l1 = [1, 2, 3, 4, 5]
l2 = [6, 7, 8, 9, 10]
print(l1 + l2)
print(l1 * 2)
# 実行結果
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
進導エイリ
進導エイリ

見比べてみると確かに普通のリストの計算と違いますね!
これは凄いです!!

これがNumpyの魅力の一つです。
通常のリストでNumpyと同じ計算結果を算出するにはどうしても一手間かかってしまいます。
同位置で計算を行ってくれるので、ありがたいですね。

講師
講師

統計量

data = np.array([1, 2, 3, 4, 5])
print('最小値:', data.min())
print('最大値:', data.max())
print('合計値:', data.sum())
print('累積和:', data.cumsum())  # 順に加算
print('累積和の割合:', data.cumsum() / data.sum())  # 累積和の割合の例
print('中央値:', np.median(data))
print('標準偏差:', data.std())
print('分散:', data.var())
# 実行結果
最小値: 1
最大値: 5
合計値: 15
累積和: [ 1  3  6 10 15]
累積和の割合: [0.06666667 0.2        0.4        0.66666667 1.        ]
中央値: 3.0
標準偏差: 1.4142135623730951
分散: 2.0

単純計算だけでなく、上のような統計情報も取得することが出来ます。
中央値や標準偏差等聞き慣れない単語もありますが、詳しくは別の講義で説明しますね。
機械学習において統計は必ず扱う分野です。
統計に必要な情報を関数やメソッドを使用するだけで取得できる。
これもNumpyの強みですね。

講師
講師

行列

arange()

np.arangeは、連番や等差数列を生成する関数です。同様の関数としてlinspaceがありますが、指定できる要素が異なるのとarangeは1つだけ引数を設定するだけで手軽に数列を生成できる違いがあります。

numpy.arange([start, ]stop, [step, ]dtype = None)
np.arange(9)
# 実行結果
array([0, 1, 2, 3, 4, 5, 6, 7, 8])

reshape()

reshape()で行列データへ変換します。注意点として、行列数の積がデータ数と一致していなければなりません。

array = np.arange(9).reshape(3, 3)
array
# 実行結果
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
n = np.arange(9)
print(n)
n2 = n.reshape(3, 3)
print(n2)
n3 = n2.reshape(1, -1)
print(n3)

print(n.shape, n2.shape, n3.shape)
# 実行結果
[0 1 2 3 4 5 6 7 8]
[[0 1 2]
 [3 4 5]
 [6 7 8]]
[[0 1 2 3 4 5 6 7 8]]
(9,) (3, 3) (1, 9)

params

パラメータ名概要
startintまたはfloat(省略可能)初期値0 生成する等差数列の最初の項を設定します。これを指定しないと0から始まる等差数列が生成されます。
stop
intまたはfloat
生成する等差数列の終点を指定します。
step
intまたはfloat
(省略可能) 初期値1 生成される数列の1つ1つの項間における差を指定します。(公差)
dtype dtype
(省略可能)初期値None 生成される数列のデータ型を指定します。これを指定しないとstartやstopで入力したデータ型がそのまま適用されます。

要素の取り出し方

1次元データの取り出し方

# 元データ
data = np.arange(9)
print(data)

# リスト風の取り出し方
data[2]  # インデックス番号を指定
# 実行結果
[0 1 2 3 4 5 6 7 8]
2

2次元データの取り出し方

# 元データ
data = np.arange(9).reshape(3, 3)
print(data)

# 「5」を取る例

# 1. リスト風の取り出し方
print(data[1][2])  # インデックス番号を指定

# 2. 行列指定での取り出し方
print(data[1, 2])  # [行, 列]のインデックスで指定
# 実行結果
[[0 1 2]
 [3 4 5]
 [6 7 8]]
5
5

複数の値をスライス

# 元データ
data = np.arange(25).reshape(5, 5)
print(data)

# 2次元データのスライス
print(data[1:3, 0:2])  # カンマを境に、行・列で指定
# 実行結果
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]
 [20 21 22 23 24]]
[[ 5  6]
 [10 11]]
進導エイリ
進導エイリ

難しそうではありますが、
arangeやreshapeが便利そうなのは分かりました!
取り出し方は、これまでやってきたスライス等をしっかり理解しておく必要がありそうですね!

難しそうなことをしているように見えますが、実際はシンプルな取得をしています。
スライスによってどのようにどこの値を取得できているか、リストの扱い方を振り返りながら考えると良いですね。

講師
講師

Start Labでは、
未経験でも始められる入門コースから、DXや機械学習に特化したコースまで
スキルや目的に合わせて学習コースをお選びいただけます!
まずはお気軽にお問い合わせください✨