Custom Meta Tags
2503 Hero Banner

AMD製品に関連する技術ブログ

Long Copy

初心者のためのPython & Numpy入門

2024-07-01

Long Copy_body

皆さん、こんにちは。Avnetエンジニアのノリさんです!

今回は初心者向けにPythonとNumpyを用いた行列計算の解説をしていきます。


Step0:環境要件


Step1: Python 3の基本

  • Pythonは主にPython 3とPython 2が利用されていますが、今回用いるものはPython 3です
  • Python 3はUbuntuにデフォルトで入っているので今回の環境ではインストール不要です
  • ターミナルからPython 3を起動できます
    • $ python3
  • 起動するとPython 3入力用コンソールが開きます
    • >>>
  • Pythonでは文字列を''や""で囲って表現します
    • 例:'abc', "abc"
  • Pythonではコメントを# で識別します
    • 例: # このようにしてコメントを書きます
  • Pythonは1行ずつ処理されます
    • 例:# なのでコメントが複数行にまたがる場合は
             # このように分けて書きます
  • print関数で数値や文字列の表示ができます
    • >>> print('a')
      a
    • >>> print(1)
      1
    • >>> print(1 + 1)
      2
  • 変数への代入は = を使って行います
    • >>> x = 1
    • >>> print(x)
      1
    • >>> x = 2
    • >>> print(x)
      2
  • 演算子と=を組み合わせて演算と同時に代入することもできます
    • >>> x = 1
    • >>> x += 2    # 足し算
    • >>> print(x)
      3
    • >>> x *= 3    # 掛け算
    • >>> print(x)
      9
    • >>> x -= 3    # 引き算
    • >>> print(x)
      6
    • >>> x /= 2    # 割り算(戻り値はfloat型になります)
    • >>> print(x)
      3.0
    • >>> x %= 2    # 割り算の余り
    • >>> print(x)
      1.0
    • >>> x //= 2    # 割り算の商
    • >>> print(x)
      0.0
    • >>> string = ''     # 空文字の代入
    • >>> string += 'abc'    # 文字列の連結
    • >>> print(string)
      abc
  • Pythonは動的型付け言語なので、数値を代入した後に文字列を代入することもできます
    • >>> x = 1
    • >>> print(x)
      1
    • >>> x = 'abc'
    • >>> print(x)
      abc
  • ただし、変数に代入されているデータの型と異なるデータを代入することは混乱を招くので推奨されません
  • Pythonでよく使われるデータ構造の一つにリスト(動的配列)があります
  • リストは要素を追加できるようにした配列で、数値や文字列を並べて扱うことができます
  • リストの作成は次のようにできます
    • >>> L = [1, 2, 3]
    • >>> print(L)
      [1, 2, 3]
  • リストの最大値、最小値はmax関数、min関数を用いて求めることができます
    • >>> print(max(L))
      3
    • >>> print(min(L))
      1
  • リストの総和はsum関数を用いて計算できます
    • >>> print(sum(L))
      6
  • リストのデータのアクセスには添字(インデックス)を使います、Pythonでは添字は0から始まります
    • >>> print(L[0])
      1
    • >>> print(L[1])
      2
    • >>> print(L[-1])    # 負の値を参照することもできます、-1で末尾を指します
      3
    • >>> print(L[-2])    # -2は末尾から2番目を指します、-nで末尾からn番目の値を参照できます
  • 文字列から文字を取得する場合もリスト同様に添字を使います
    • >>> a = 'xyz'
    • >>> print(a[0])
      x
  • リストの末尾に要素を追加するには、appendメソッドを使います
    • >>> L.append(4)
    • >>> print(L)
      [1, 2, 3, 4]
  • リストの任意の箇所に要素を追加するには、insertメソッドを使います
    • >>> L.insert(2, 5)   # 第一引数が挿入位置、第二引数が挿入する値です
    • >>> print(L)
      [1, 2, 5, 3, 4]
    • >>> L.insert(4, 6)
    • >>> print(L)
      [1, 2, 5, 3, 6, 4]
  • リストにおいて、末尾以外への要素の追加よりも末尾への要素の追加の方が高速です
  • 末尾への追加の方が高速な理由は、データを末尾から順に参照して追加を行うためです
  • リストを小さい順(昇順)に並べ替えるにはsortメソッドまたはsorted関数を用います
    • >>> S = sorted(L)
    • >>> print(S)
      [1, 2, 3, 4, 5, 6]
    • >>> print(L)    # sorted(L)ではLの中身は書き換わりません
      [1, 2, 5, 3, 6, 4]
    • >>> L.sort()
    • >>> print(L)    # L.sort()だとLの中身が書き換わります
      [1, 2, 3, 4, 5, 6]
  • 引数にreverse=Trueを追加すると大きい順(降順)に並び替えることもできます
    • >>> S = sorted(L, reverse=True)
    • >>> print(S)
      [6, 5, 4, 3, 2, 1]
    • >>> L.sort(reverse=True)
    • >>> print(L)
      [6, 5, 4, 3, 2, 1]
  • popメソッドでリストの要素を取り出すことができます
    • >>> p = L.pop()    # デフォルトだと末尾が取り出されます
    • >>> print(p)
      1
    • >>> print(L)
      [6, 5, 4, 3, 2]
    • >>> p = L.pop(2)    # 引数に取りだす位置を指定できます
    • >>> print(p)
      4
    • >>> print(L)
      [6, 5, 3, 2]
  • popもまた末尾を取り出す場合が最も高速です
  • rangeを使うことで連番のリストを作ることができます
    • >>> R = list(range(5))
    • >>> print(R)
      [0, 1, 2, 3, 4]
  • rangeはシーケンス型の一種であり、リストを直接生成するわけではありません
  • range型をlist型に変換するにはlistを用います、上の例だとlist(range(5))で型をrangeからlistにしています
  • rangeは初期値と刻み幅を設定することもできます
    • >>> print(list(range(1, 5)))
      [1, 2, 3, 4]
    • >>> print(list(range(1, 5, 2)))    # 5が範囲に含まれないことに注意してください
      [1, 3]
    • >>> print(list(range(1, 7, 2)))    # こちらも先程と同じで7は含まれません
      [1, 3, 5]
  • for文を使って繰り返しの処理を書くことができます(インデントが合っていないとエラーになるので注意)
    • >>> total = 0
    • >>> for i in range(1, 5):
      .   .   .    total += i     # インデントはタブまたは空白4つです
      .   .   .     # ここで一度改行します
    • >>> print(total)
      10
  • rangeだけでなくリストや文字列でもfor文の処理を書くことができます
    • >>> total = 0
    • >>> L = [1, 2, 3, 4]
    • >>> string1 = 'abcd'
    • >>> string2 = 'efgh'
    • >>> for i in L:
      .   .   .    total += i
      .   .   .
    • >>> print(total)
      10
    • >>> for i in string2:
      .   .   .    string1 += i
      .   .   .
    • >>> print(string1)
      abcdefgh
  • while文でも繰り返しの処理を書くことができます
    • >>> total = 0
    • >>> while total < 10:
      .   .   .    total += 1
      .   .   .
    • >>> print(total)
      10
  • if文やelif文、else文で条件分岐を書くことができます
    • >>> n = 0
    • >>> if  n > 0:
      .   .   .    print('positive')
      .   .   .elif  n < 0:
      .   .   .    print('negative')
      .   .   .else:
      .   .   .    print('zero')
      .   .   .
      zero
  • exit関数でプログラムを終了します
    • >>> exit()
  • テキストエディタで.pyファイルを作り、それを実行することもできます
  • ここでは、test.pyを作ってそれにPythonプログラムを書いて動かしてみます
  • 下記の内容をtest.pyに書きます
    # def 関数名(引数):
    #     処理
    #     return 戻り値
    # で関数を定義できます

    def add(a, b):
        x = a+b
        return x

    a, b = 1, 2    # このように複数の変数に対して代入を行うこともできます
    print(add(a, b))
     
  • 保存して下記のコマンドを実行すると結果が表示されます
    • $ python3 test.py
      3
  • ここでは扱いませんが、Pythonにはリスト以外にも辞書(連想配列)や
    集合などのデータ構造がデフォルトで用意されています


Step2: pipでのパッケージ管理

  • pipはPythonのパッケージ管理ツールです
  • Ubuntuではaptを使ってpipをインストールできます
  • 念のためaptパッケージをアップグレードしておきます
    • $ sudo apt update
    • $ sudo apt upgrade
  • pipをインストールします
    • $ sudo apt install pip-python3
  • pipでパッケージをインストールする場合は下記のようにします
    • $ python3 -m pip install パッケージ名
  • パッケージのバージョンを指定してインストールする場合は下記のようにします
    • $ python3 -m pip install パッケージ名
  • パッケージをアップグレードする場合は下記のどちらかを使うことでできます
    • $ python3 -m pip install -U パッケージ名
    • $ python3 -m pip install --upgrade パッケージ名
  • パッケージをアンインストールする場合は下記のようにします
    • $ python3 -m pip uninstall パッケージ名


Step3: Numpyの基本

  • 以降、初等的なベクトル・行列演算の知識を前提とします
  • NumpyはPythonの数値計算用ライブラリで、ベクトルや行列の演算を高速に行うことができます
  • Numpyをインストールします
    • python3 -m pip install numpy==1.26.1
  • それでは実際にNumpyを使ってみましょう
    • $ python3
    • >>> # importでモジュールの呼び出しができます
    • >>> # asでプログラム実行時のモジュールの名称を変更できます
    • >>> import numpy as np    # numpyの呼び出し、npへの名称の変更
    • >>> # numpyの演算にはnumpy用の配列を用います
    • >>> vec1 = np.array([1, 2, 3])    # np.array(リスト)でリストをnumpy用の配列に変換
    • >>> vec2 = np.array([4, 5, 6])
    • >>> print(vec1[0])    # 添字で要素を参照できます
      1
    • >>> print(vec1 + vec2)    # +で要素ごとの和を取ることができます
      [5 7 9]
    • >>> print(vec1 * vec2)    # 他の四則演算も同様にできます
      [ 4 10 18]
    • >>> print(3 * vec1)    # スカラー倍も計算できます
      [3 6 9]
    • >>> print(np.max(vec1))    # np.maxで最大値を計算できます
      3
    • >>> print(np.min(vec1))    # np.minで最小値を計算できます
      1
    • >>> print(np.sum(vec1))    # np.sumで総和を計算できます
      6
    • >>> print(np.mean(vec1))    # np.meanで平均値を計算できます
      2.0
    • >>> print(np.dot(vec1, vec2))    # np.dotで標準内積を計算できます
      32
    • >>> print(vec1 @ vec2)    # 後述する@演算子でも標準内積の計算ができます
      32
    • >>> Mat1 = np.array([[1, 1, 0], [0, 2, 2], [3, 0, 3]])    # 行列(2次元配列)の作成もできます
    • >>> Mat2 = np.array([[4, 4, 0], [0, 5, 5], [6, 0, 6]])
    • >>> print(Mat1[0][0])    # 添字で要素を参照できます
      1
    • >>> print(Mat1[0])    # 行列[行の指定]で行を取り出すことができる
      [1 1 0]
    • >>> print(Mat1[:, 0])    # 行列[:, 列の指定]で列を取り出すことができる
      [1 0 3]
    • >>> print(Mat1 + Mat2)    # 行列の和
      [[5 5 0]
       [0 7 7]
       [9 0 9]]
    • >>> print(Mat1 * Mat2)    # 行列の要素積(アダマール積)
      [[ 4   4   0]
       [ 0  10 10]
       [18   0 18]]
    • >>> print(3 * Mat1)    # スカラー倍も計算できます
      [[3 3 0]
       [0 6 6]
       [9 0 9]]
    • >>> print(Mat1 @ Mat2)    # @演算子で行列積を計算できます
      [[ 4   9   5]
       [12 10 22]
       [30 12 18]]
    • >>> print(Mat1 @ vec1)    # @は行列とベクトルの積も計算できます
      [ 3 10 12]
    • >>> print(np.sum(Mat1))    # np.sumで行列の要素の総和を求められます
      12
    • >>> print(np.mean(Mat1))    # np.meanで行列の要素の平均値を求められます
      1.3333333333333333
    • >>> print(np.transpose(Mat1))    # np.transposeで転置行列を求められます
      [[1 0 3]
       [1 2 0]
       [0 2 3]]
    • >>> print(np.linalg.det(Mat1))    # np.linalg.detで行列式を求められます
      12.0
    • >>> print(np.linalg.inv(Mat1))    # np.linalg.invで逆行列を求められます
      [[ 0.5        -0.25        0.16666667]
       [ 0.5         0.25       -0.16666667]
       [-0.5         0.25        0.16666667]]
    • >>> print(np.linalg.matrix_rank(Mat1))    # np.linalg.matrix_rankで行列のランクを求められます
      3
    • >>> I = np.identity(3)    # np.identityで単位行列を作ることができます
    • >>> print(I)
      [[1. 0. 0.]
       [0. 1. 0.]
       [0. 0. 1,]]
    • >>> O = np.zeros((3, 3))    # np.zerosで零行列を作ることができます
    • >>> print(O)
      [[0. 0. 0.]
       [0. 0. 0.]
       [0. 0. 0,]]
    • >>> O = np.zeros(3)    # 引数を単一の値にすると、零ベクトルになります
    • >>> print(O)
      [0. 0. 0.]
    • >>> X = np.ones((3, 3))    # np.onesで要素が全て1の行列を作ることができます
      >>> print(X)
      [[1. 1. 1.]
       [1. 1. 1.]
       [1. 1. 1,]]
    • >>> X = np.ones(3)    # 要素が全て1のベクトルも作ることができます
    • >>> print(X)
      [1. 1. 1,]
    • >>> print(np.linalg.eig(I))    # np.linalg.eigで固有値、固有ベクトルの計算ができます
      EigResult(eigenvalues=array([1. , 1. , 1.]), eigenvectors=array([[1. , 0. , 0.],
       [0. , 1. , 0.],
       [0. , 0. , 1,]]))


感想

今回は初心者向けにPythonとNumpyの解説をしました。
基礎からやることで改めて自分で学べたことも多かったので、個人的にも有用な体験ができました。
それではまたお会いしましょう!See you next time!