L
o
a
d
i
n
g
.
.
.

ホーム

お知らせ

製品・ソリューション

サービス

導入事例・パートナー

EXEM Academy・ブログ

会社情報

採用情報

2023.03.02

Time Series 機械学習のためのPython必須ライブラリ:Numpy 2

1編ではarrayの生成方法とタイプ確認、テンソル次元などを実習してみたら、2編ではarrayを直接適用して実習してみよう。 

2-4. numpy索引付け,スライシング,前置行列

2-4-1. 索引付け

インデックスはPythonリストと同じ概念で使用され、「、」(カンマを介して各次元のインデックスにアクセスできますそして、N darrayで目的の座標または特定のデータのみを選択するのに便利ですこのとき、インデックス付けをするときに0回からインデックスが始まることに注意し希望の軸を指定するにはaxisで選択できます索引付けの種類には「特定データのみ抽出」、「スライシング」、「ファンシー索引付け」、「ブール語索引付け」などがある

  • 索引付けとスライシング

「特定データのみ抽出」とは、文字通り所望の位置のインデックス値を指定して、その位置の値を受け取るものである1、2次元のインデックス作成の例で確認することができます

  • 1次元配列固有のデータ抽出とスライス

必要な特定のデータを抽出できます

In [1]:
arr = np.arange(10)

In [2]:
print(arr)
print(arr[2])

Out [3]:
[0 1 2 3 4 5 6 7 8 9]
2

図 2-4-1-1. 配列の作成と索引付け

スライスは、連続したインデックス上の配列を抽出する方法で範囲を指定することで一度に返すことができます。

In [4]:

print(arr[3:7])
print(arr[3:7:3])
print(arr[-1])

Out [5]:
[3 4 5 6]
[3 6]
9

図 2-4-1-2. スライス

  • 2次元索引付け

2次元からは視覚的に確認してみよう。 最初の結果は、0行目に4、5番目のインデックスの値を返します。理由は、ゼロからインデックスが始まるからです。 そして、スライスをするときに最初に始まる数字から終わる値の全値で区間をとるようになる(既存の繰り返し文の範囲を定めるようにn以上n未満と同じ意味である)。 2番目の結果は、4番目の行から最後まで、4番目の列から最後までのインデックスをすべて抽出するという意味です。 3番目の結果を見ると、コロンだけが書かれていることがわかりますが、すべてインポートするという意味であり、インデックス2番目の列の値を取得するために書かなければなりません(カンマを使用するため)。 最後の結果は、コロンを2回書いたことがわかりますが、既存のPythonイテレーションのようにステップを意味します。 数字「2」なので、偶数番目のインデックスだけを抽出することになる。

In [6]:

arr = np.arange(36).reshape(6,6)

In [7]:
print(arr)

Out [8]:
[[ 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 25 26 27 28 29]
 [30 31 32 33 34 35]]

그림 2-4-1-1. 슬라이싱

2-4-2. ブーリアン索引付け

ブールのインデックス付けは、配列の各要素の選択をブールのマスクを使用して指定する方法です。 条件に合ったデータを取得し、真か偽かを知らせる。

  • True、False 結果のみ戻り mask

比較演算子のみが少なくなったとき、条件によって合うものはTrue、他はFalseで成分が構成された配列を返す。 これをBoolean array、またはマスクという。

In [9]:
arr2 = np.random.randint(-10,10,[20])

In [10]:
print(arr2)
print(arr2 <= 0)

Out [11]:

[  6  -8  -2 -10  -4   7   3   5   4   0   1   6  -7  -6  -9   6   3   3
  -7   7]
[False  True  True  True  True False False False False  True False False
  True  True  True False False False  True False 

図 2-4-2-1. ブーリアン索引付け

  • ブールマスク true 要素に対応するインデックスのみ検索

上記では、マスクされた配列を返した結果を見たら、今回はマスクされた結果を配列に入れて希望の値だけを抽出してみることができる。 インデックス付けのように変数として宣言された配列に上記のような条件を同じように入れればよい。

In [12]:

arr2[arr2 < 0]

Out[13]:
array([ -8,  -2, -10,  -4,  -7,  -6,  -9,  -7])

他の演算子は既存のPython論理演算をそのまま使用すればよい。

2-4-3. ファンシーインデックス

ファンシー索引付けは、整数またはBoolean値を持つ別のNumpy配列に配列を索引付けすることを意味します。
ブール値を持つ配列を使用して直感的にインデックスを作成できます。

In [14]:

arr = np.arange(0,10,1)

In [15]:
print(arr[[1,3,4,5]])
print(arr[[False,False,False,False,True,False,False,False,False,False]])

Out [16]:
[1 3 4 5]
[4]

角かっこを2回使用せず、インデックスだけを抽出したいときはnp.where関数を利用すれば可能です。

In [17]:
print(np.where(arr[:6]))

Out [18]:
(array([1, 2, 3, 4, 5]),)

2-5. 転置行列と軸の変更

2-5-1. 転置行列(transpose)

前置行列は、行列計算、主に行列積を行うときによく使用されます。 このとき行列であるarrをarr.Tにするか、np.transpose(arr)と同じ結果である。

In [18]:
arr = np.arange(20).reshape(4,5)

In [19]:
print(arr)
print('------')
print(arr.T)

Out [20]:
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
------
[[ 0  5 10 15]
 [ 1  6 11 16]
 [ 2  7 12 17]
 [ 3  8 13 18]
 [ 4  9 14 19]]

  • 3次元転置行列

二次元行列のように、両方とも軸変更が可能である。 Np.transpose() の場合は直接軸を変更することができるが、T の場合は既存の行列サイズに合うように内積ができるように軸変更になるので、一番前の次元が後に行くことになる。

In [21]:

arr = np.arange(20).reshape(1,4,5)

In [22]:
print(arr)
print('-----')
print(arr.T)
print('-----')
print(np.transpose(arr))

Out [23]:

[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]
  [10 11 12 13 14]
  [15 16 17 18 19]]]
-----
[[[ 0]
  [ 5]
  [10]
  [15]]

 [[ 1]
  [ 6]
  [11]
  [16]]

 [[ 2]
  [ 7]
  [12]
  [17]]

 [[ 3]
  [ 8]
  [13]
  [18]]

 [[ 4]
  [ 9]
  [14]
  [19]]]
-----
[[[ 0]
  [ 5]
  [10]
  [15]]

 [[ 1]
  [ 6]
  [11]
  [16]]

 [[ 2]
  [ 7]
  [12]
  [17]]

 [[ 3]
  [ 8]
  [13]
  [18]]

 [[ 4]
  [ 9]
  [14]
  [19]]]

  • 転置行列軸の変更(swapaxes)

Transposeと大きく変わらないように使用が可能だ。 しかし、transposeの場合、中に引数なしで使用しても構いませんが、swapaxesは中に引数をディテールに書かなければならない違いがあります。

In [24]:
arr = np.arange(20).reshape(1,4,5)

In [25]:
print(arr)
print('-----')
print(np.swapaxes(arr, 0, 1))
print('-----')
print(np.transpose(arr, (1, 0, 2)))
print('-----')
print(np.transpose(arr, (1, 2, 0)))

Out [26]:

[[[ 0  1  2  3  4]
  [ 5  6  7  8  9]
  [10 11 12 13 14]
  [15 16 17 18 19]]]
-----
[[[ 0  1  2  3  4]]

 [[ 5  6  7  8  9]]

 [[10 11 12 13 14]]

 [[15 16 17 18 19]]]
-----
[[[ 0  1  2  3  4]]

 [[ 5  6  7  8  9]]

 [[10 11 12 13 14]]

 [[15 16 17 18 19]]]
-----
[[[ 0]
  [ 1]
  [ 2]
  [ 3]
  [ 4]]

 [[ 5]
  [ 6]
  [ 7]
  [ 8]
  [ 9]]

 [[10]
  [11]
  [12]
  [13]
  [14]]

 [[15]
  [16]
  [17]
  [18]
  [19]]]

2-6. 算術演算

Numpyは基本的に行列間の四則演算をサポートします。 したがって、同じ配列を計算すると、その位置にある値が計算されます。 代わりにshapeが同じ場合にのみ発生します。 この現象をelement-wise operationsという。 PythonリストタイプとNumpy配列と計算後の結果を確認してみましょう。

2-6-1. Pythonリストとnumpyの比較

Pythonリストの場合、加算時に項目をつなぐconcatenateを実行することになる。 そしてPythonリスト間の他の操作は許可しません。

In [27]:
list1 = [1,2,3,4]

In [28]:
print(list1 + list1)

Out [29]:
[1, 2, 3, 4, 1, 2, 3, 4]

In [30]:
arr1 = np.arange(4)

In [31]:
print(arr1 + arr1)

Out [32]:
[0 2 4 6]

このときスカラー因子を含む算術演算を行う場合、すべての元素にスカラー因子が適用され、追加的に乗算と除算は自然数のみ可能で元素コピーを意味する。

In [33]:

arr2 = arr1 + 1

In [34]:
print(arr2)
print(arr2 * arr2)
print(arr2 / arr2)

Out [35]:
[1 2 3 4]
[ 1  4  9 16]
[1. 1. 1. 1.]

Pythonリストの場合は算術演算をサポートしていないため、上記と同じ方法でエラーが発生しました。

In [36]:
print(list1 + 1)

Out [37]:
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-50-8dc4fc81bbff> in <module>
----> 1 print(list1 + 1)

TypeError: can only concatenate list (not "int") to list

今回の実習では、サイズの異なる配列間で演算が可能なものを見てみたが、これをブロードキャストという。

  • ブロードキャストの詳細条件

1.    メンバーが1つの配列は、任意の配列にブロードキャスティング可能ですが、メンバーが1つもない空の配列を除く)
         ex) 4×4 + 1

2.    1つの配列の次元が1の場合、ブロードキャスト可能
         ex) 4×4 + 1×4

3.    次元のペアに合わせてブロードキャスト(Broadcasting)可能
        ex) 3×1 + 1×3

図 2-6-1-1. ブロードキャスト

2-7. universal function(ユニバーサル関数)


ユニバーサル関数とは、汎用的な関数(ufunc)、つまりPythonとNumpyの違いはあるかもしれませんが、どちらも持っている関数を意味します。 しかし、Numpyにはベクトル化演算が可能ですが、ベクトル化演算とは繰り返し文をNumpy配列要素にそれぞれ適用するアイデアです。 そうなると、繰り返し文を使わなくても要素別演算が可能で、速いというメリットがある。 だから繰り返し文が見えたら、これをPythonの機能として使わずにベクトル化できるか悩むことをお勧めする.

  • 単項(1つの配列について) np.ufunc
Abs, fabs 各要素の絶対値
Ceil, Floor 各元素ごとに切り上げ、下げる
Modf 各要素の商と残りをそれぞれの配列として返す
Rint 各元素の小数点の丸め
Log, log10, log2, log1p ログ値をとる(自然ログ、ログ、ログ2、ログ(1+x)
Exp 各要素で指数関数を計算する
Sqrt 各元素ごとにルートをかぶせる.
Square 各要素ごとに2乗
Isnan 各要素が数値でないかどうか boolean として返される
Isinfinite 各元素が有限数であることを確認
Logical_not 各要素の論理否定値を計算する(== ~arr)
Sin, cos, tan 各関数の値の計算
Arcsin, arccos, arctan 逆三角関数の計算

  • 이항(2개의 배열에 대한) np.ufunc
Add(arr, arr), subtract(arr, arr), Multiply(arr, arr) 2つの配列で各要素を加算、減算、乗算
Divide(arr, arr), floor_divide(arr, arr), mod(arr, arr) 2つの配列で各要素を分割した値、商、残り
Power(arr or num, arr or num) 各要素の種類に応じた乗算
Maximum(arr, arr), fmax(arr, arr)
Minimum(arr, arr), fmin(arr, arr)
2つの配列で各要素を比較した後に大きな値を返す
2つの配列で各要素を比較した後に小さい値を返す
Greater(arr, arr), greater_equal(arr, arr), less(arr, arr) 各配列内の各要素間の比較演算の結果をbooleanとして返す
Copysign(arr, arr) 最初の配列の要素の記号を2番目の配列の要素記号に置き換える

 

2-8. 乱数生成

さまざまな種類の効果的な標本を抽出するために主に使用されます。 下の練習は、正規分布の形の乱数配列を生成します。 もちろん正規分布以外に様々な乱数生成が可能である。

In [38]:

samples = np.random.rand(100)

In [39]:
print(samples)

Out [40]:

[0.85523262 0.46078327 0.87611742 0.94701602 0.36346599 0.16641525
 0.71505748 0.41702892 0.35117872 0.24799137 0.16927744 0.03059451
 0.90605791 0.48085535 0.30943322 0.02627849 0.30579807 0.9516295
 0.42841414 0.66084711 0.55030129 0.14599804 0.84904265 0.42073973
 0.6835832  0.90772918 ... ]

しかし、乱数生成も完全ランダムではなく、乱数生成器のシード値によって決まる乱数を生成するため、「類似乱数」とも呼ばれる。 乱数ジェネレータのシード値はnp.random.seedに変更可能です。

In [41]:

print(np.random.rand(10))
np.random.seed(0)
print(np.random.rand(10))

Out [42]:
[0.79172504 0.52889492 0.56804456 0.92559664 0.07103606 0.0871293
 0.0202184  0.83261985 0.77815675 0.87001215]
[0.5488135  0.71518937 0.60276338 0.54488318 0.4236548  0.64589411
 0.43758721 0.891773   0.96366276 0.38344152]

  • Random 関数のクリーンアップ
Seed(num) 乱数ジェネレータのシード設定
Rand(num) 0~1の値の均等分布値を返す
Randn(num) ガウス分布から分布値を返す
Randint(num1, num2) 与えられた値の間の乱数の抽出


PHP Code Snippets Powered By : XYZScripts.com