SIGMA-SE Math & Tech Library

SIGMA-SE Math & Tech Library


数学と情報技術をテーマに、書籍や教材だけではつかみにくい考え方を具体例とともに簡潔にわかりやすく伝える解説サイトです。
技術の歴史や背景、関連知識の整理、学習のための覚書や要約記事も掲載しています。

Python - NumPy:ndarrayの基本操作と配列計算の使い方

概要

NumPyのndarrayを使い、Pythonで配列を効率よく扱うための基本操作を整理する。

Python標準のリストでも複数の値は扱えるが、数値計算や機械学習では、配列同士の演算、条件抽出、行列計算をまとめて実行できるndarrayの理解が重要になる。
ここでは、配列の作成、次元や形状の確認、要素アクセス、ブロードキャスト、条件指定による抽出を、対話モードの実行例で確認する。

この記事の構成

実施内容

NumPyの環境準備

NumPyは、高速な数値演算をはじめ、科学技術計算で広く利用されるPythonの外部ライブラリ。 同じデータ型の値を連続的に扱うndarrayと、Cなどで実装されたベクトル化処理を利用することで、Pythonのループを要素ごとに実行する場合より効率よく数値計算できる。

  • NumPyインストール
    使用するPython環境を明確にするため、次のようにPython経由でpipを実行。
    $ python -m pip install numpy
    
    インストール後はpython -c "import numpy as np; print(np.__version__)"で、読み込まれたNumPyのバージョンを確認できる。

NumPyの使用方法

  • 配列の定義と型の確認
    np.array()へPythonのリストなどを渡すと、numpy.ndarray型の配列を生成できる。
    変数名にlistを使うとPython組み込みのlistを上書きしてしまうため、ここではvaluesとする。

    $ python
     >>> import numpy as np
     >>> values = np.array([0.5, 1.5, 2.5, 3.5, 4.5, 5.5])
     >>> print(values)
     [0.5 1.5 2.5 3.5 4.5 5.5]
     >>> type(values)
     <class 'numpy.ndarray'>
     >>>
    
  • 一次元配列同士の四則演算
    形状が同じ配列同士、または後述するブロードキャストが可能な形状同士では、それぞれの要素を対応させて四則演算できる。

    $ python
     >>> import numpy as np
     >>> list_a = np.array([1.0, 2.0, 3.0])
     >>> list_b = np.array([2.0, 2.5, 3.0])
     >>> list_a + list_b    # 加算
     array([3. , 4.5, 6. ])
     >>> list_a - list_b    # 減算
     array([-1. , -0.5,  0. ])
     >>> list_a * list_b    # 乗算
     array([2., 5., 9.])
     >>> list_a / list_b    # 除算
     array([0.5, 0.8, 1. ])
     >>>
    
  • 多次元配列(行列)の四則演算
    一次元配列と同様に、形状が同じ多次元配列では対応する要素ごとに四則演算を行う。

    $ python
     >>> import numpy as np
     >>> matrix_a = np.array([[1, 2], [3, 4]])
     >>> matrix_b = np.array([[5, 10], [15, 20]])
     >>> matrix_a + matrix_b    # 加算
     array([[ 6, 12],
             [18, 24]])
     >>> matrix_a - matrix_b    # 減算
     array([[ -4,  -8],
             [-12, -16]])
     >>> matrix_a * matrix_b    # 乗算
     array([[ 5, 20],
             [45, 80]])
     >>> matrix_a / matrix_b    # 除算
     array([[0.2, 0.2],
             [0.2, 0.2]])
     >>>
    

    *は行列積ではなく要素ごとの乗算である。線形代数の行列積には@またはnp.matmul()を使う。

    >>> matrix_a @ matrix_b
    array([[ 35,  50],
           [ 75, 110]])
    
    • 形状とデータ型の確認
      shapeで各軸の要素数、ndimで次元数、dtypeで要素のデータ型を確認できる。
      二次元配列のshape(行数, 列数)の順となる。
      $ python
       >>> import numpy as np
       >>> matrix_a = np.array([[1, 2], [3, 4]])
       >>> print(matrix_a)
       [[1 2]
         [3 4]]
       >>> matrix_a.shape    # 形状の確認
       (2, 2)
       >>> matrix_a.ndim     # 次元数の確認
       2
       >>> matrix_a.dtype    # データ型の確認
       dtype('int64')
      >>>
      

      dtypeの表示はOSやPython、NumPyの環境によって異なる場合があるため、特定の整数幅を必要とする処理ではdtype=np.int64のように明示する。

  • ブロードキャスト
    NumPyでは、末尾の次元から比較し、各次元の大きさが等しいか、どちらかが1であればブロードキャストできる。
    単に要素数が近いだけでは演算できない。下記3つは、互換性のある形状の例である。

    • 一次元配列とスカラ値(単一の数値)
      一次元配列とスカラ値「2」との四則演算。
      $ python
       >>> import numpy as np
       >>> list_a = np.array([1.0, 2.0, 3.0])
       >>> list_a + 2    # 加算
       array([3., 4., 5.])
       >>> list_a - 2    # 減算
       array([-1.,  0.,  1.])
       >>> list_a * 2    # 乗算
       array([2., 4., 6.])
       >>> list_a / 2    # 除算
       array([0.5, 1. , 1.5])
       >>>
      
    • 多次元配列とスカラ値
      多次元配列とスカラ値「16」との四則演算。
      $ python
       >>> import numpy as np
       >>> matrix_a + 16    # 加算
       array([[17, 18],
               [19, 20]])
       >>> matrix_a - 16    # 減算
       array([[-15, -14],
               [-13, -12]])
       >>> matrix_a * 16    # 乗算
       array([[16, 32],
               [48, 64]])
       >>> matrix_a / 16    # 除算
       array([[0.0625, 0.125 ],
               [0.1875, 0.25  ]])
       >>>
      
    • 多次元配列と一次元配列
      多次元配列と一次元配列との四則演算。
      $ python
       >>> import numpy as np
       >>> matrix_a = np.array([[1, 2], [4, 8], [16, 32]])
       >>> matrix_b = np.array([2, 4])
       >>> matrix_a + matrix_b    # 加算
       array([[ 3,  6],
               [ 6, 12],
               [18, 36]])
       >>> matrix_a - matrix_b    # 減算
       array([[-1, -2],
               [ 2,  4],
               [14, 28]])
       >>> matrix_a * matrix_b    # 乗算
       array([[  2,   8],
               [  8,  32],
               [ 32, 128]])
       >>> matrix_a / matrix_b    # 除算
       array([[0.5, 0.5],
               [2. , 2. ],
               [8. , 8. ]])
       >>>
      
  • 各要素の取得

    • インデックスで要素を指定
      Pythonのリストと同様にNumPyでもインデックスは0から始まり、下記要領でアクセスできる。
      多次元配列ではmatrix_c[0, 1]のように各軸をカンマで指定する書き方もできる。
      $ python
       >>> import numpy as np
       >>> matrix_c = np.array([[1, 5], [10, 15], [20, 25]])
       >>> print(matrix_c)
       [[ 1  5]
         [10 15]
         [20 25]]
       >>> matrix_c[0]    # 行 1
       array([1, 5])
       >>> matrix_c[1]    # 行 2
       array([10, 15])
       >>> matrix_c[2]    # 行 3
       array([20, 25])
       >>> matrix_c[0][0]    # 行 1 、列 1
       1
       >>> matrix_c[0][1]    # 行 1 、列 2
       5
       >>> matrix_c[1][0]    # 行 2 、列 1
       10
       >>> matrix_c[1][1]    # 行 2 、列 2
       15
       >>> matrix_c[2][0]    # 行 3 、列 1
       20
       >>> matrix_c[2][1]    # 行 3 、列 2
       25
       >>>
      
    • 配列で要素を指定
      インデックスだけでなく一次元配列に対して、配列で要素を指定することもできる。
      $ python
        >>> import numpy as np
        >>> matrix_d = np.array([1, 5, 10, 15, 20, 25])
        >>> print(matrix_d)
        [ 1  5 10 15 20 25]
        >>> matrix_d[np.array([1, 3, 5])]    # インデックス 1, 3, 5 (2、4、6個目)を指定
        array([ 5, 15, 25])
        >>> matrix_d[1:4]    # インデックス1以上4未満をスライス
        array([ 5, 10, 15])
        >>>
      
    • 任意の条件で要素を指定
      $ python
        >>> import numpy as np
        >>> matrix_e = np.array([1, 5, 2, 10, 3, 15, 4, 20, 5, 25])
        >>> matrix_e > 4    # 一次元配列に対して直接比較する
        array([False, True, False, True, False, True, False,  True, True, True])
        >>> matrix_e[matrix_e > 4]    # 上記の結果がTrueの要素のみ抽出する
        array([ 5, 10, 15, 20,  5, 25])
        >>>
        >>> matrix_e[matrix_e == 5]   # 5のみ抽出する
        array([5, 5])
        >>>
       

まとめ

  • NumPyのndarrayは、Pythonのリストとは異なる、数値計算に適した多次元配列。
  • shape、ndim、dtypeで配列の構造を確認できる。2次元配列のshapeは(行, 列)の順で、1次元配列は列ベクトルとは異なる。
  • 配列演算や、比較結果のTrue/False配列を使った条件抽出は、数値処理や機械学習の前処理の基本となる。

参考文献

この記事を共有
Xで共有 Facebookで共有 LINEで共有



Copyright SIGMA-SE All Rights Reserved.
s-hama@sigma-se.jp