【完全版】NumPyの使い方を徹底解説【機械学習】

機械学習をしたいけど、NumPyの使い方がよくわからないな…。



NumPy(ナムパイ)とは、高速計算処理を得意とするPythonのライブラリです。


機械学習をPythonで行う場合は、NumPyをよく使います。

本記事では、NumPyの基礎的な文法を徹底解説します。



ベクトルや行列の概念の説明から、基礎文法の図解まで、Python初心者でも挫折せずに学ぶことができます



是非ブックマークして、何度も見返すことをオススメします。

なぜ機械学習でNumPyを使うの?

なんで機械学習でNumPyを使うんだろう?



NumPyを使う理由は、大量のデータを計算するのに適しているからです。


機械学習はデータ量が多いほど精度が上がりやすいので、データを処理する速度は非常に大切なポイントです。


NumPyは機械学習に適したライブラリなのです。

なぜ計算が早いのか

NumPyはベクトル演算を使うことで、ループをせずに配列や行列の計算ができます。

だから計算が早いんだね



ベクトルや行列、配列は、後ほど解説します。

次元とは

NumPyの文法に入る前に、基本的な概念・用語について確認しておきましょう。

NumPyでは「次元」という言葉がよくでてきます。

一次元、二次元といった言葉だね

次元とは、空間の広がりを表します。

一次元というのは、軸が1本、つまり、点と直線のみで表現されます。
二次元は、軸が2本なので、を表します。
三次元は、軸が3本なので、立体を表します。






ベクトルと行列

ベクトルとは

NumPyでいうベクトルとは、数字や文字列が複数連なったものです

ベクトルは、配列の一種です。
列が1列なので、1次元配列です。



ベクトルの長さは、要素数です。

上記の例にあるベクトルAは、要素数が5なので、長さ=5です。

行列とは

行列とは、行と列からできた数字や文字列の集まりです。

行と列からなる行列は、二次元配列とも呼ばれます。



それぞれのデータを、要素と呼びます。



行列は、大文字のアルファベットを使って表現します。


上記の例では、行列Aと名付けられています。

縦と横、どっちが列か行か、わからなくなってきた…!

確かに紛らわしいよね。

列は縦方向、行は横方向だよ!
下の考え方が一番覚えやすいです。



行と列の覚え方




行列はどんなサイズも取ることができ、一般的にm×nの行列Aと表現します。

一方で、特定の要素は小文字で表現されます。(例:a22

例えば、aijは、i行j列にある要素を表現できます。

スカラー

1,2,3…のように、数字単体を表します。次元がありません。

0次元です!



配列とは(ndarray配列)

配列とは、複数の要素を入れておくための入れ物のイメージです。

NumPyで提供される配列は、ndarrayと呼ばれます。



配列は複数のデータ型の要素を格納できるのに対し、ndarray配列は一種類のデータ型しか格納できません。



ベクトルは一次元、行列は二次元ですが、ベクトルも行列もndarray配列の一種です。



リスト・タプル・ディクショナリとベクトルの違い

pythonで使う代表的なデータ型として、リストやタプル、ディクショナリ(辞書型)があるけど、ベクトルとどういった点が違うのかな



ベクトルと、リスト・タプル・ディクショナリとの違いは、数字・文字列などの複数のデータ型を1つのリストに格納できるかどうかです。


  • ベクトル:要素のデータ型は1種類のみ
  • リスト・タプル・ディクショナリ:複数のデータ型の要素を入れられる



リスト

リストとは、要素を並べたものです。

#リストの定義
list = [5,10,15,20]
list


>>実行結果
[5, 10, 15, 20]



ベクトルとの違いは、数字・文字列などの複数のデータ型を1つのリストに格納できるかどうかです。


#リストは複数のデータ型を格納できる
list2 = [1,"apple",4.5]
list2


>>実行結果
[1, 'apple', 4.5]





タプル

タプルも、リストと同様に要素を並べたものです。

定義する時に、リストは角括弧で囲むのに対し、タプルは丸括弧で囲みます。

#タプルの定義
tuple = (1,2,3)
tuple

>>実行結果
(1, 2, 3)




リストと異なり、タプルは一度定義すると、上書きや追加をすることができません。

#タプルは上書きできない
tuple[1] = 10

>>実行結果
TypeError: 'tuple' object does not support item assignment




ベクトルとタプルの違いは、リストと同様、複数のデータ型を入れられるかどうかです。


ディクショナリとベクトルの違い

ディクショナリ(辞書型)とは、keyとvalueをセットで格納できるデータ型です。

#辞書型を定義
dict = {"No.1":"apple", "No.2":"orange","No.3":"banana"}
dict


>>実行結果
{'No.1': 'apple', 'No.2': 'orange', 'No.3': 'banana'}



リストと同様に、複数の異なるデータ型を格納することができます。





NumPyの基本的な使い方

インポート

まずは、NumPyをインポートすることで、手元のPythonファイルでNumPyを使えるようにしましょう。

一般的に、NumPyはnpとしてインポートします。

#NumPyをimport
import numpy as np



ndarray配列の作り方

ベクトルの作り方

ndarray配列を作る時は、NumPyに含まれる関数arrayを使います。

事前に作ったリストをndarray配列に変換するイメージです。



ここでは、ベクトルを作成します。

#リストの作成(一次元)
data = [1,2,3,4]

#array関数でndarray配列にする
a = np.array(data)
a

>>実行結果
array([1, 2, 3, 4])



行列(マトリックス)の作り方

行列もndarray配列の一種です。


そのため、ベクトルを生成した時と同様、array関数を使います。

#1リストが1行になる
data2 = ([1,2,3,4],
         [5,6,7,8],
         [9,10,11,12])

#array関数で行列にする
b = np.array(data2)
b


>>実行結果
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])



初期化配列を作る【zeros関数】

全ての要素が0のベクトルや行列を作りたい場合は、zeros関数を使います。

0で初期化されているベクトルや行列がほしい時に使います。



#1次元配列(ベクトル)
zeros = np.zeros(10) 
zeros

>>実行結果
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])



#2次元配列はタプルで行数・列数をそれぞれ指定する
zeros2 = np.zeros((4,5))
zeros2

>>実行結果
array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]])



全ての要素が1の配列を作る【ones関数】

全ての要素が1のベクトルや行列を作るときは、onesを使いましょう。

#全ての要素が1のベクトルを作る
np.ones(4)


>>実行結果
array([1., 1., 1., 1.])




#全ての要素が1の行列を作る
np.ones((3,5))

>>実行結果
array([[1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.]])





全ての要素を指定した数でベクトルや行列を作る【full関数】

np.full(5,3)

>>実行結果
array([3, 3, 3, 3, 3])




対角線上の要素を1にした行列を作る【eye関数】

行列の対角線上の要素を1、他の要素を0にした行列を作る時は、eye関数を使います。

np.eye(4)

>>実行結果
array([[1., 0., 0., 0.],
       [0., 1., 0., 0.],
       [0., 0., 1., 0.],
       [0., 0., 0., 1.]])




等間隔の行列を作る【arange関数】

等間隔の要素が格納されたベクトルを作る時は、arange関数を使います。

#arange(終わりの数字)
np.arange(5)


>>実行結果
array([0, 1, 2, 3, 4])



#arange(始める数字, 終わりの数字)
np.arange(5,10)


>>実行結果
array([5, 6, 7, 8, 9])



#arange(始める数字, 終わりの数字, 間の数字)
np.arange(5,50,3)


>>実行結果
array([ 5,  8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47])




ベクトルを行列にしたい場合は、reshape関数を使います。

#行列にする
np.arange(5,50,3).reshape(5,3)

>>実行結果
array([[ 5,  8, 11],
       [14, 17, 20],
       [23, 26, 29],
       [32, 35, 38],
       [41, 44, 47]])



中身を調べる

配列の形状を調べる

各次元ごとの要素数を表示したい場合は、属性shapeをつかいます。

ndarray配列名.shapeで、ベクトルや行列のサイズを表示してくれます。

#ndarray配列の形状を調べる
a.shape

>>実行結果
(4,)



aは一次元配列です。

一次元配列は軸が列のみなので、4は要素数を表すことになりますね。


4×1の行列とも言えます。


shapeは、引数にndarray配列名を指定する方法でも使えます

np.shape(a)


行列の形状も調べることができます。



下記の例では、3×4の行列であることがわかりました。

#行列の形状もわかる
b.shape


>>実行結果
(3, 4)




次元を確認する

ndarray配列が何次元なのかを確認したい場合は、属性ndimを使います。


ndarray配列aは一次元なので、実行結果は1となります。

#次元を確認する
a.ndim

>>実行結果
1





行列bは二次元のため、実行結果は2になりました。

#行列は2次元
b.ndim

>>実行
2




引数にndarray配列を指定する方法でも、同様の結果が得られます。

#引数に指定する方法でも使える
np.ndim(a)





データ型を確認する

ndarray配列名.dtypeで、ndarray配列に格納されている要素のデータ型を確認できます。

#データ型の確認
a.dtype


>>実行結果
dtype('int64')




行列でも、同様にデータ型が確認できます。

b.dtype

>>実行結果
dtype('int64')



intの後に64という数字が入っていますが、これはビット数を表します。

ビット数とは、データのサイズで、数字が大きいほどデータも大きいことを表します。

ビット数が大きいと、計算の処理速度が遅くなります。




要素が文字列なら、unicode型になります。

data = ["apple", "banana", "orange"]
c = np.array(data)
c.dtype

>>実行結果
dtype('<U6')




要素が小数なら、float型になります。

#要素が小数なら、float型
data = [0.1,0.04,6.9]
d = np.array(data)



要素数を調べる

全ての要素数を確認するときは、属性sizeを使います。

#要素数の確認
a.size

>>実行結果
4




行列のときも同様に確認できます。

b.size


>>実行結果
12




統計量

平均

平均は、mean関数を使うことで簡単に算出できます。

np.mean(a)

>>実行結果
2.5


引数でaxis属性を指定することで、行ごと・列ごとの算出も可能です。

#行列の行ごとの平均を知りたい場合
np.mean(b,axis=1)


>>実行結果
array([ 2.5,  6.5, 10.5])


#行列の列ごとの平均を知りたい場合
np.mean(b, axis=0)

>>実行結果
array([5., 6., 7., 8.])



分散

分散は、var関数を使いましょう。

np.var(a)

>>実行結果
1.25

標準偏差

標準偏差の算出は、std関数を使います。

np.std(a)

>>実行結果
1.118033988749895



標準偏差や分散がどのような値なのか、何が違うのかについてはこちらの記事で解説しています。


ぜひご参照下さい。

標準偏差と分散の違いとは?

2022年6月23日




最大・最小

ndarray配列の要素の最大値・最小値を出す場合は、maxとmin関数を使います。

np.max(a)

>>実行結果
4



np.min(a)

>>実行結果
1





行列から抽出する


一次元配列にする

行列を一次元配列にする時は、ravel関数を使います。

ravel関数は、要素を1つずつ取り出したいときに使います。



np.ravel(b)

>array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])




行番号・列番号を指定して抽出する

ndarray配列名[行番号,列番号]と指定することで、指定した要素を取り出せます。

b[1,1]

>>実行結果
6



行番号・列番号は0から始まるので、注意しましょう。

b[0,3]


>>実行結果
4



ベクトルでも番号での指定が可能です。

a[2]

>>実行結果
3




最後の要素を指定したい場合は、-1で指定可能です。


a[-1]

>>実行結果
4





スライスで抽出する

スライスとは、複数要素を取得する場合に範囲選択することです。


スライスには、「:(コロン)」を使います。


#ベクトルの1番目〜2番目を抽出する
a[1:3]

>>実行結果
array([2, 3])


#0行目〜1行目、1列目〜2列目
b[0:2,1:3]

>>実行結果
array([[2, 3],
       [6, 7]])





「:(コロン)」は単体で使うと、全選択を意味します。

#行を全選択し、列は列番号で指定
b[:,2]

>>実行結果
array([ 3,  7, 11])


#行は行番号で指定し、列を全選択で指定
b[1,:]

>>実行結果
array([5, 6, 7, 8])



条件で抽出する

条件指定で配列や行列の要素を取得する場合は、比較演算子を使います。


b>4

>>実行結果
array([[False, False, False, False],
       [ True,  True,  True,  True],
       [ True,  True,  True,  True]])


比較演算子は、次の4種類が使えます。

比較演算子意味
配列 > xx よりも大きい要素を取得する
配列 < xx よりも小さい要素を取得する
配列 >= xx と等しいか大きい要素を取得する
配列 <= xx と等しいか小さい要素を取得する



行列を操作する

ベクトル同士の計算

ベクトル同士の計算について学習しましょう。

計算は通常の演算子を使います。

ベクトルの計算ってどうやるのかな?
イメージがつかないな〜。



ベクトル同士の計算は、横方向に算出します。

同じ場所にある要素を足したり、引いたりするんだね!


# 計算用の配列を作成
array1 = np.array([1,2,3,4,5,6])
array2 = np.array([2,4,6,8,10,12])


#和
array1 + array2


>>実行結果
array([ 3,  6,  9, 12, 15, 18])




和だけでなく、他の演算でも横方向に計算します

#差
array2 - array1


>>実行結果
array([1, 2, 3, 4, 5, 6])



#積
array1 * array2

>>実行結果
array([ 2,  8, 18, 32, 50, 72])



#商
array2 / array1


>>実行結果
array([2., 2., 2., 2., 2., 2.])




行列同士の計算

行列の演算も配列と同様に、同じ場所にある要素を足したり、引いたりします。



#行列を作成
matrix1 = np.array([[1,2,3,4,5,6],
                    [2,4,6,8,10,12],
                    [3,6,9,12,15,18]])
matrix2 = np.array([[4,8,12,16,20,24],
                    [5,10,15,20,25,30],
                    [6,12,18,24,30,36]])


#和
matrix1 + matrix2


>>実行結果
array([[ 5, 10, 15, 20, 25, 30],
       [ 7, 14, 21, 28, 35, 42],
       [ 9, 18, 27, 36, 45, 54]])


#差
matrix2 - matrix1


>>実行結果
array([[ 3,  6,  9, 12, 15, 18],
       [ 3,  6,  9, 12, 15, 18],
       [ 3,  6,  9, 12, 15, 18]])



#積
matrix1 * matrix2


>>実行結果
array([[  4,  16,  36,  64, 100, 144],
       [ 10,  40,  90, 160, 250, 360],
       [ 18,  72, 162, 288, 450, 648]])



#商
matrix2 / matrix1


>>実行結果
array([[4. , 4. , 4. , 4. , 4. , 4. ],
       [2.5, 2.5, 2.5, 2.5, 2.5, 2.5],
       [2. , 2. , 2. , 2. , 2. , 2. ]])













転置

転置とは、行と列を入れ替えることです。

転置のイメージ



#行と列を入れ替える
b.T


>>実行結果
array([[ 1,  5,  9],
       [ 2,  6, 10],
       [ 3,  7, 11],
       [ 4,  8, 12]])




ただし、ベクトル(一次元配列)は行と列がないため、Tでは転置できません。

#一次元配列は行と列がないため、Tでは転置できない
a.T


>>実行結果
array([1, 2, 3, 4])




行数と列数を指定して形を変える

reshape関数を使うと、行列の行数と列数を変更したり、ベクトルを行列に変更したりすることができます。



#3×4の行列を2×6に変更する
b.reshape(2,6)


>>実行結果
array([[ 1,  2,  3,  4,  5,  6],
       [ 7,  8,  9, 10, 11, 12]])


reshape関数を使うと、一次元配列も転置することができます。

もちろん、行列に変換することもできます。



#ベクトルを転置する。(縦1列にする)
a.reshape(4,1)

>>実行結果
array([[1],
       [2],
       [3],
       [4]])



#ベクトルaを2×2の行列に変える
a.reshape(2,2)


>>実行結果
array([[1, 2],
       [3, 4]])




ブロードキャスト

ブロードキャストとは、ndarray配列の大きさ・次元が違う場合、自動的に要素をコピーして大きさを揃える機能です。



例えば、ベクトル(一次元配列)と行列(二次元配列)や、スカラー(0次元配列)とベクトルの計算をする際などに効果的です。


#ブロードキャスト(行列と配列の和)
a + b


>>実行結果
array([[ 2,  4,  6,  8],
       [ 6,  8, 10, 12],
       [10, 12, 14, 16]])



#スカラー(0次元配列)と行列(2次元配列)
5 * b

>>実行結果
array([[ 5, 10, 15, 20],
       [25, 30, 35, 40],
       [45, 50, 55, 60]])



配列の結合・分割

縦方向にndarray配列を結合する時は、vstack関数を使います。

各行の要素数が同じでないと結合できないので、注意しましょう。

#aとbを縦方向に結合
np.vstack((a,b)) #引数はタプルにすること

>>実行結果
array([[ 1,  2,  3,  4],
       [ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])

ndarray配列を横方向に結合する時は、hstack関数を使います。


#array1とarray2の確認
array1

>>実行結果
array([1, 2, 3, 4, 5, 6])


array2

>>実行結果
array([ 2,  4,  6,  8, 10, 12])


#array1とarray2を横方向に結合
np.hstack((array1,array2))

>>実行結果
array([ 1,  2,  3,  4,  5,  6,  2,  4,  6,  8, 10, 12])



疑似乱数を生成する

疑似乱数を作る時はrandom関数を使います。


0~1の乱数

random.randで、0~1の乱数を生成できます。

引数には何を入れるのかな?


ベクトルの場合は、生成したい乱数の数(要素数)を入れます。

#ベクトル
np.random.rand(5)

>>実行結果
array([0.85572911, 0.41986047, 0.52022084, 0.60679373, 0.02879198])
where




行列の場合の引数は、(行,列)で指定します。

#行列
np.random.rand(4,6)


>>実行結果
array([[0.35599728, 0.14748427, 0.86172026, 0.92575276, 0.29228079,
        0.22964651],
       [0.34756348, 0.08573972, 0.59858781, 0.67060099, 0.00791902,
        0.02872533],
       [0.82821718, 0.75247201, 0.8961799 , 0.94816615, 0.48520699,
        0.15950374],
       [0.94662943, 0.81549464, 0.1551827 , 0.84437122, 0.20545317,
        0.96384743]])



指定した範囲の整数の乱数

指定した範囲にある整数をランダムに選んで、ベクトルや行列を作りたい場合は、random.randintを使います。


#引数の数字以内で整数を1つ選ぶ
np.random.randint(30)

>>実行結果
13



#範囲指定(10~30)
np.random.randint(10,30)

>>27



#複数の乱数を生成する(ベクトル)
np.random.randint(10,30,6)

>>実行結果(要素数=6)
array([18, 17, 20, 21, 24, 25])



#複数の乱数を生成する(行列)
np.random.randint(10,30,(6,3))


>>実行結果
array([[21, 27, 22],
       [16, 28, 11],
       [10, 28, 28],
       [19, 27, 10],
       [27, 10, 28],
       [28, 19, 12]])





最後に

pythonでデータ分析・データサイエンスをしたい初心者向けに、Pythonデータ分析徹底解説総まとめページを作成しました。


流れに沿って実装することで、データ分析の基礎が固められます。

【総集編】データ前処理をPythonで実装【機械学習入門】

2022年9月25日




また、専門の講師と一緒に挫折せずに学習したい方は、データサイエンススクールがおすすめです。

こちらもぜひ御覧ください。

【2023年最新版】データサイエンスが学べるおすすめスクール5選

2022年6月4日