「[[.NET 開発基盤部会 Wiki>http://dotnetdevelopmentinfrastructure.osscons.jp]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。 -[[戻る>Python]] > [[Pythonセカンド・ステップ]] --NumPy --[[Pandas]] --[[Matplotlib]] *目次 [#e017055b] #contents *概要 [#e25f43a7] 多次元配列における数値計算を効率的に行うことをサポートする数学関数ライブラリ -効率的な数値計算を行うための型付きの多次元配列のサポートをPythonに加える。 -多次元配列を操作するための大規模な高水準の数学関数ライブラリを提供する。 -NumPy自体はC言語で書かれているため、Pythonのリストと比べると高速な処理が可能。 *準備 [#k4a7dcd8] **インストール [#v3030c68] > pip install numpy **インポート [#fb5021f4] >>>import numpy as np *ファースト・ステップ [#sbc10627] **NumPyの配列 [#i84e9574] 1次元配列はベクトルとも言う。 ***生成 [#l1fc4a28] -array >>>np.array([1.0,2.0,3.0]) array([1., 2., 3.]) -arange >>>np.arange(10) array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) -ones(1埋め >>>np.ones(10) array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]) -zeros(0埋め >>>np.zeros(10) array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]) -ランダム --empty >>>np.empty(5) array([2.12199579e-314, 6.36598737e-314, 1.06099790e-313, 1.48539705e-313, 1.90979621e-313]) --random.randn(標準正規分布 >>>np.random.randn(10) array([ 1.33385073, -0.61769365, 1.41045502, -0.18429257, -0.00662791, -0.09483573, -2.26232104, 0.95660959, -1.02715574, -1.02119134]) -コピー >>>a=np.array([1.0,2.0,3.0]) --以下は参照渡し >>>b=a --コピーする場合は以下 >>>b=a.copy() ***確認 [#qef55406] >>>a=np.array([1.0,2.0,3.0]) -生 >>>a array([1., 2., 3.]) -print >>>print(a) [1. 2. 3.] -データ型 >>>type(a) <class 'numpy.ndarray'> -要素のデータ型 >>>a.dtype dtype('float64') -配列の次元 >>>np.ndim(a) 1 -次元の形状 >>>a.shape (3,) -次元の要素数 >>>a.shape[0] 3 ***算術計算 [#e5d33434] -四則演算~ 2つのNumPy配列を算術計算で処理する。 --同じ数の要素を持つ配列の要素ごとの計算 >>>x=np.array([1.0,2.0,3.0]) >>>y=np.array([2.0,4.0,6.0]) ---要素ごとの足し算 >>>x+y array([ 3., 6., 9.]) ---要素ごとの引き算 >>>x-y array([-1., -2., -3.]) ---要素ごとの掛け算 >>>x*y array([ 2., 8., 18.]) ---要素ごとの割り算 >>>x/y array([ 0.5, 0.5, 0.5]) --ブロード・キャストによる計算 >>>x/2.0 array([0.5, 1. , 1.5]) -その他の計算 >>>x=np.arange(10) >>>x array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) --平方根の計算 >>>np.sqrt(x) array([0. , 1. , 1.41421356, 1.73205081, 2. , 2.23606798, 2.44948974, 2.64575131, 2.82842712, 3. ]) --[[ネイピア数>DS:数学的基礎 - 微分・偏微分#adabdb73]](自然対数の底)e を底とする累乗 >>>np.exp(x) array([1.00000000e+00, 2.71828183e+00, 7.38905610e+00, 2.00855369e+01, 5.45981500e+01, 1.48413159e+02, 4.03428793e+02, 1.09663316e+03, 2.98095799e+03, 8.10308393e+03]) ***統計計算 [#yc1ceaad] 標準正規分布 >>>x=np.random.randn(10) -符号 >>>np.sign(x) array([ 1., 1., -1., -1., -1., -1., 1., 1., 1., 1.]) -平均~ (標準正規分布で要素数を増やすと0に近づく >>>x.mean() 0.02713878708811851 -標準偏差~ (標準正規分布で要素数を増やすと1に近づく >>>x.std() 1.2305510107988773 **NumPyのN次配列 [#y7024df9] ***行列 [#ka4b4dc8] 行列とは? -2次元配列は行列とも言う。 -行が、1つの添字で表される1つのべクトル -列は、ベクトルのn番目の要素をグループ化したもの。 列↓ ┌ ┐ 行│○ ○│ →│ │ │○ ○│ └ ┘ ***テンソル [#h768806a] テンソルとは? -ベクトルや行列を一般化したものをテンソルと呼ぶ。 -3次元以上の配列を、テンソル / 多次元配列と呼ぶ。 -任意の次元の配列 --3次元の配列は3階テンソル --4次元の配列は4階テンソル -特別な呼び方 --0階テンソルをスカラー --1階テンソルをベクトル --2階テンソルのことを行列 ***生成 [#t4e9d2b2] -通常 >>> a=np.array([[1,2],[3,4],[5,6]]) -型指定 >>> a=np.array([[1,2],[3,4],[5,6]],dtype=np.int32) -コピー >>>a=np.array([[1,2],[3,4],[5,6]]) --以下は参照渡し >>>b=a --コピーする場合は以下 >>>b=a.copy() ***確認 [#y77e03c9] -生 >>>a -print >>> print(a) [[1 2] [3 4] [5 6]] -データ型 >>>type(a) <class 'numpy.ndarray'> -行列要素のデータ型 >>>a.dtype dtype('int32') -行列の次元 >>>np.ndim(a) 2 -行列の形状(行数・列数 >>>a.shape (3, 2) -次元の要素数 >>>a.shape[0] 3 ***算術計算 [#u7ee288f] -四則演算~ 2つのNumPy行列を算術計算で処理する。 --要素ごとの足し算 ---行列の要素数が同じ >>>x=np.array([[1, 2], [3, 4]]) >>>y=np.array([[3, 0], [0, 6]]) >>>x+y array([[ 4, 2], [ 3, 10]]) ---行列の要素数が異なる~ (ブロード・キャスト) >>>x=np.array([[1, 2], [3, 4]]) >>>y=np.array([10,20]) >>>x+y array([[11, 22], [13, 24]]) --要素ごとの掛け算~ [[行列の積>#l3b1be5b]]&color(red){でないことに注意}; ---行列の要素数が同じ >>>x=np.array([[1, 2], [3, 4]]) >>>y=np.array([[3, 0], [0, 6]]) >>>x*y array([[ 3, 0], [ 0, 24]]) ---行列の要素数が異なる~ (ブロード・キャスト) >>>x=np.array([[1, 2], [3, 4]]) >>>y=np.array([10,20]) >>>x*y array([[10, 40], [30, 80]]) -その他の計算~ [[ベクトル>#e5d33434]]と同じ方法で計算できる。 ***統計計算 [#h5d3aa6f] -[[配列(ベクトル)の統計計算>#yc1ceaad]]と同じように計算できる。 -[[ベクトルを行列に変換>#p0ec3ace]]して計算してみると良い(結果が同じになる)。 *セカンド・ステップ [#m438f220] **要素へのアクセス [#hcfbe34e] -配列 >>> a=np.arange(10) >>> print(a) [0 1 2 3 4 5 6 7 8 9] -行列 >>> b=np.array([[51, 55], [14, 19], [0, 4]]) >>> print(b) [[51 55] [14 19] [ 0 4]] ***インデックス [#b73bb749] -配列 >>>a[1] 1 -行列 --N次配列にN個のインデックスを指定すると要素が取り出せる。 >>>b[0][1] 55 --N次配列にX個のインデックスを指定するとN-X次配列が取り出せる。 >>>b[0] array([51, 55]) ***抽出 [#e93817c2] -配列 --スライシング >>>a[3:7] --配列でインデックスを指定 >>>a[np.array([3,4,5,6])] --比較演算~ 比較の結果boolの配列が生成されて指定されている。 ---条件に合う値を抽出 >>>a[a==5] ---5より大きい値を抽出。 >>>a[a>5] -行列 --スライシング >>>b[0,1:2] array([55]) >>>b[1:2,0] array([14]) --配列でインデックスを指定 ---行インデックス >>>b[np.array([0,1])] array([[51, 55], [14, 19]]) ---行&列インデックス >>>b[np.array([0,1]),np.array([1])] array([55, 19]) --比較演算~ 比較の結果boolの配列とか行列などが生成されて指定されている。 ---15より大きい値を抽出。 >>>b[b>15] array([51, 55, 19]) ---列値が条件に合う行を抽出 >>>b[b[:,1]==19] array([[14, 19]]) **ベクトル編集 [#fc6526ef] ***置換 [#c3246bfb] -比較演算 --5より大きい値を調査。 >>>a>5 array([False, False, False, False, False, False, True, True, True, True]) --特定の値を変換 >>>a[a==5]=0 >>>a array([0, 1, 2, 3, 4, 0, 6, 7, 8, 9]) -型の置換 >>>b=np.array(b,dtype=np.int64) # 要素の型をint64に変換 ***要素の追加 [#u215b9e4] ... **行列編集 [#xed6f8b9] ***置換 [#o40025fe] -比較演算 --15より大きい値を調査。 >>>b>15 array([[ True, True], [False, True], [False, False]]) --特定の値を変換 >>>b[b==55]=99 array([[51, 99], [14, 19], [ 0, 4]]) -型の置換 >>>b=np.array(b,dtype=np.int64) # 要素の型をint64に変換 ***行追加 [#iad170b8] -vstack~ 2次元で言うと、垂直方向=行方向 2次元で言うと、垂直方向=行追加方向 np.vstack([a, a]) -concatenate~ 0次元目(行)方向に結合 0次元目(行追加)方向に結合 np.concatenate([a, a]) np.concatenate([a, a], 0) ***列追加 [#zae905bd] -hstack~ 2次元でいうと、水平方向=列方向にスタック 2次元でいうと、水平方向=列追加方向にスタック np.hstack([a, a]) -concatenate~ 1次元目(列)方向に結合 1次元目(列追加)方向に結合 np.concatenate([a, a], 1) ***行削除 [#ad3896b4] [[スライシング>#e93817c2]] ***列の削除 [#o586cdc0] [[スライシング>#e93817c2]] ***要素の追加 [#cc1480cb] stackで新規次元を追加してスタックする。 -新規次元を追加してスタック --ベクトル要素が新規次元で(行方向に)スタックして新規次元を追加 --ベクトル要素が新規次元で(行追加方向に)スタックして新規次元を追加 >>>np.stack([a.flatten(), a.flatten()]) >>>np.stack([a.flatten(), a.flatten()], 0) array([[51, 55, 14, 19, 0, 4], [51, 55, 14, 19, 0, 4]]) --行列の要素が新規次元でスタックして新規次元を追加 >>>np.stack([a, a]) >>>np.stack([a, a], 0) array([[[51, 55], [14, 19], [ 0, 4]], [[51, 55], [14, 19], [ 0, 4]]]) -既存の次元でスタックして次元を追加 --ベクトル要素が列の次元で(列方向に)スタックして新規次元を追加 --ベクトル要素が列の次元で(列追加方向に)スタックして新規次元を追加 >>>np.stack([a.flatten(), a.flatten()], 1) array([[51, 51], [55, 55], [14, 14], [19, 19], [ 0, 0], [ 4, 4]]) --行列の要素が行の次元でスタックして新規次元を追加 >>>np.stack([a, a], 1) array([[[51, 55], [51, 55]], [[14, 19], [14, 19]], [[ 0, 4], [ 0, 4]]]) --行列の要素が列の次元でスタックして新規次元を追加 >>>np.stack([a, a], 2) array([[[51, 51], [55, 55]], [[14, 14], [19, 19]], [[ 0, 0], [ 4, 4]]]) *サード・ステップ [#i77e421a] **型の変換 [#uf1d925a] ***要素の型の変換 [#f57ed9c0] 配列でも、行列でも。 >>> b=np.array(a,dtype=np.int32) ***LIST ⇔ NP型変換 [#a8ceeb5d] -LIST → NP~ コレについては、[[生成の所>#t4e9d2b2]]で既出(np.arrayを使う)。 -LIST ← NP~ ndarray.tolist()メソッドが使える。 np_arr.tolist() ***[[NP ⇔ DF型変換>Pandas#e3138f86]] [#y8098994] **配列・行列変換 [#m346600a] ***行列の配列化 [#f48e0091] (機械学習ライブラリ入力用) -平坦化 --flatten >>> b=a.flatten() >>> print(b) [51 55 14 19 0 4] --reshape >>>c.reshape(-1) -行ベクトル、列ベクトル --行ベクトル(横ベクトル)化 b=a[0,:] # 1行目、全列スライス --列ベクトル(縦ベクトル)化 b=a[:,0] # 1列目、全行スライス ***配列の行列化 [#r458dec2] (機械学習ライブラリ入力用) -1行n列化 --reshape >>>c=b.reshape(1, -1) --np.newaxis >>>c=b[np.newaxis, :] -n行1列化 --reshape >>>c=b.reshape(-1, 1) --np.newaxis >>>c=b[:, np.newaxis] **行列の変換 [#w2dc56a9] ***転置行列 [#w9e8a558] >>> a=np.array([[51, 55], [14, 19], [0, 4]]) >>> print(a) [[51 55] [14 19] [ 0 4]] -Tプロパティ >>>print(a.T) [[51 14 0] [55 19 4]] -transposeメソッド >>>print(a.transpose()) [[51 14 0] [55 19 4]] ***次元の入れ替え [#ud48adc4] 行(0)と列(1)が入れ替わる。~ [[転置>#w9e8a558]]と同じだが、2次元以上のn次元行列にも適用可能。 >>> a=np.array([[51, 55], [14, 19], [0, 4]]) >>> print(a) >>> a=a.transpose([1, 0]) >>> print(a) ***再構成 [#p0ec3ace] >>>a=np.arange(0, 12) -numpy.reshape >>>np.reshape(a,[4,3]) array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11]]) >>>np.reshape(a,[3,2,2]) array([[[ 0, 1], [ 2, 3]], [[ 4, 5], [ 6, 7]], [[ 8, 9], [10, 11]]]) -ndarray.reshape >>>a.reshape([4,3]) array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11]]) >>>a.reshape([3,2,2]) array([[[ 0, 1], [ 2, 3]], [[ 4, 5], [ 6, 7]], [[ 8, 9], [10, 11]]]) **One-Hotエンコーディング [#c1c53872] >>> a=np.array([[0,1,2,3,4,5,6,7,8,9]]) >>> print(a) [[0 1 2 3 4 5 6 7 8 9]] ***エンコーディング [#d3f97f04] -np_utils.to_categoricalを使う。 b = np_utils.to_categorical(a, num_classes=10).astype('i') -np.identityを使う。 b = np.identity(10)[a].astype('i') ***デコーディング [#u7f8449d] -np.argmaxを使う。 b.argmax(axis=1) -チェック print((b.argmax(axis=1) == a).all()) *4thステップ [#z6991a1b] **ベクトルの積算(ドット積 = 内積) [#mbd9806c] >>>a=np.array([1,2,3,4]) >>>b=np.array([10,20,30,40]) ***データの生成 [#ned27a0c] ベクトルを行列化する。 >>> a=a.reshape(1, -1) >>> b=b.reshape(1, -1).T # 転置行列に ***計算方法 [#k1b81e51] -演算子 >>>a@b -メソッド >>>np.dot(a,b) ***交換法則が成立 [#c1b7c987] 行列では、交換法則の不成立になるが、~ ベクトルの場合は成立する(ただし転置が必要)。 >>>a@b >>>b.T@a.T >>>np.dot(a,b) >>>np.dot(b.T,a.T) **行列の積算(ドット積 ≠ 内積) [#l3b1be5b] A行列 * B行列 =C行列 -A行列の列数とB行列の行数が一致ししている必要がある。 -計算後のC行列は、A行列の行数 * B行列の列数の行列になる。 ***2行2列の場合 [#j2dd9e74] ┌ ┐┌ ┐ ┌ ┐ │a1 b1││a2 b2│ │a1a2+b1c2 a1b2+b1d2│ │ ││ │ = │ │ │c1 d1││c2 d2│ │c1a2+d1c2 c1b2+d1d2│ └ ┘└ ┘ └ ┘ A行列 B行列 C行列 2行2列 2行2列 2行2列 ***x行y列の場合 [#n6d364a9] 計算後のC行列は、A行列の行数 * B行列の列数の行列になる。 -ベクトルと行列との計算では、~ ベクトルが行列形状に拡張され計算される。 ┌ ┐┌ ┐ ┌ ┐┌ ┐ ┌ ┐ │a1 b1││a2│ │a1 b1││a2 0│ │a1a2+b1b2│ │ ││ │ = │ ││ │ =│ │ │c1 d1││b2│ │c1 d1││b2 0│ │c1a2+d1b2│ └ ┘└ ┘ └ ┘└ ┘ └ ┘ A行列 B行列 C行列 2行2列 2行1列 2行1列 -A行列の列数とB行列の行数が一致ししている必要がある。 ┌ ┐┌ ┐ ┌ ┐ │a1 b1││a2 b2 c2 d2│ │a1a2+b1e2 a1b2+b1f2 a1c2+b1g2 a1d2+b1h2│ │ ││ │ │ │ │c1 d1││e2 f2 g2 h2│ = │c1a2+d1e2 c1b2+d1f2 c1c2+d1g2 c1d2+d1h2│ │ │└ ┘ │ │ │e1 f1│ │e1a2+f1e2 e1b2+f1f2 e1c2+f1g2 e1d2+f1h2│ └ ┘ └ ┘ A行列 B行列 C行列 3行2列 2行4列 3行4列 ***計算方法 [#ga79aea2] [[要素ごとの掛け算>#u7ee288f]]&color(red){でないことに注意}; -データ生成 >>>a=np.array([[1,2,3],[4,5,6]]) >>>b=np.array([[1,2],[3,4],[5,6]]) >>>c=np.array([[1,2],[3,4]]) >>>d=np.array([7,8]) >>>a array([[1, 2, 3], [4, 5, 6]]) >>>b array([[1, 2], [3, 4], [5, 6]]) >>>c array([[1, 2], [3, 4]]) >>>d array([7, 8]) -演算子~ @(ドット積)演算子を使用する。 >>>a@b array([[22, 28], [49, 64]]) >>>b@c array([[ 7, 10], [15, 22], [23, 34]]) >>>b@d array([23, 53, 83]) >>>a@c # A行列の列数とB行列の行数が一致しない。 Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 2 is different from 3) -メソッド~ dot(ドット積)メソッドを使用する。 >>>np.dot(a,b) array([[22, 28], [49, 64]]) >>>np.dot(b,c) array([[ 7, 10], [15, 22], [23, 34]]) >>>np.dot(b,d) array([23, 53, 83]) >>>np.dot(a,c) # A行列の列数とB行列の行数が一致しない。 Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: shapes (2,3) and (2,2) not aligned: 3 (dim 1) != 2 (dim 0) **信号処理 [#m63a8bdc] ***... [#s0d0a8e8] *参考 [#s7e8aee2] -NumPy - Wikipedia~ https://ja.wikipedia.org/wiki/NumPy -NumPy https://numpy.org/ --NumPy Reference — NumPy v1.22 Manual~ https://numpy.org/doc/stable/reference/ ---Universal functions (ufunc)~ https://numpy.org/doc/stable/reference/ufuncs.html -DxCommon/NumPyTraining.ipynb at develop · OpenTouryoProject/DxCommon · GitHub~ https://github.com/OpenTouryoProject/DxCommon/blob/develop/Notebook/Jupyter/path/NumPyTraining.ipynb