【python】Numpyメモ

# 機械学習に入門したてのNumpyメモである

参考資料

- [NumpyとScipy](https://www.eidos.ic.i.u-tokyo.ac.jp/~tau/lecture/computational_physics/slide/numpy.pdf)

## numpyのimportと使い方

タイプ数も少なく混同のリスクが少ない以下がおすすめ

```python:numpy.py
import numpy as np
np.array([2, 0, 2, 0])
```

## numpyの基本は`array`、多次元のarrayも書ける

```python:numpy.py
import numpy as np
x = np.array([[2, 0, 2, 0],[2, 0, 2, 1]])
```

## arrayの演算

[numpy.dot関数 = ベクトルの内積や行列の積を求める](https://deepage.net/features/numpy-dot.html)

`array`は任意の次元のデータの集まりを表す、汎用的なデータで、`行列`専用というわけではない

```python:numpy_array.py
import numpy as np
x = np.array([2, 0, 2, 0])
y = np.array([2, 0, 2, 1])
print(x + y)
print(x * y)
print(x.dot(y))

=> [4, 0, 4, 1] #要素ごと
=> [4, 0, 4, 0] #要素ごと（注意)
=> 8            #内積

#行列×ベクトル
import numpy as np
A = np.array([[1, 2, 3],[4, 5, 6]])
x = np.array([7, 8, 9])
print(A.dot(x))
=> [ 50, 122]

#行列×行列
import numpy as np
A = np.array([[1, 2, 3],[4, 5, 6]])
B = np.array([[1, 2], [3, 4], [5, 6]])
print(A.dot(B))

=>[[22 28]
  [49 64]]
```

## matrixの演算

`matrixは行列を表すクラス`
`array`と`matrix`は異なるので注意 

[np.matrixクラスの特性](https://www.sejuku.net/blog/71829)

```python:numpy_matrux.py
import numpy as np
A = np.matrix([[1, 2, 3],[4, 5, 6]])
B = np.matrix([[1, 2], [3, 4], [5, 6]])
print(A.dot(B)) #numpy.dot関数の結果はarrayと一緒　内積を計算

=> [[22 28]
    [49 64]]

import numpy as np
A = np.matrix([[1, 2, 3],[4, 5, 6]])
B = np.matrix([[1, 2], [3, 4], [5, 6]])
print(A * B) #matrixでは演算子"*"で内積を計算

=> [[22 28]
    [49 64]]

import numpy as np
A = np.array([[1, 2, 3],[4, 5, 6]])
B = np.array([[1, 2], [3, 4], [5, 6]])
print(A * B) #要素ごとの計算をしようとするが行列の形状が一致していないためエラーとなる

=> ValueError: operands could not be broadcast together with shapes (2,3) (3,2)
```


## arrayのいろいろな作り方

```python:numpy.array.py
import numpy as np

#等差数列(等差指定)
np.arrange(2, 3, 0.2)
=> array([ 2. ,  2.2,  2.4,  2.6,  2,8])

#等差数列(点数を指定)
np.linspace(2, 3, 6)
=> array([ 2. , 2.2, 2.4, 2.6, 2.8, 3. ])

#zoreを並べる
np.zeros((3, 2))
=> array([[0., 0.],
          [0., 0.],
          [0., 0.]])

#oneを並べる
np.ones((2, 3))
=> array([[1., 1.],
          [1., 1.],
          [1., 1.]])

#手法
#0で形を作り、各要素に値を代入
import numpy as np

def make_diag(n):
  A = np.zeros((n, n))
  for i in range(n):
    A[i, i] = i + 1
  return A

print(make_diag(4))

=> [[1. 0. 0. 0.]
    [0. 2. 0. 0.]
    [0. 0. 3. 0.]
    [0. 0. 0. 4.]]

#要素の並びはそのままにして、形を変えるreshape
import numpy as np

A = np.arange(0, 15, 1)
print("Aの中身:\n{}".format(A))
B = A.reshape(3, 5)
print("Bの中身:\n{}".format(B))
C = B.reshape(5, 3)
print("Cの中身:\n{}".format(C))

=>Aの中身:
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14]
Bの中身:
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
Cの中身:
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]
 [12 13 14]]

#乱数の利用random
import numpy as np

np.random.random((3, 3))
=>array([[0.96781535, 0.64650387, 0.05718226],
         [0.78586557, 0.4422813 , 0.92825971],
         [0.94403786, 0.90600626, 0.85543603]])

#各成分を関数で指定
import numpy as np

def f(i, j):
  return i + j

A = np.fromfunction(f, (3, 3))
print(A)

=>[[0. 1. 2.]
   [1. 2. 3.]
   [2. 3. 4.]]
```

## 要素・行・列の取り出し

```python:numpy.py
import numpy as np

A = np.arange(0, 15, 1)
print("A=>\n{}".format(A))
B = A.reshape(3, 5)
print("B=>\n{}".format(B))

print("B[1:2]=>\n{}".format(B[1:2]))
print("B[1:3, 2:3]=>\n{}".format(B[1:3, 2:4]))
print("B[1:3, :]=>\n{}".format(B[1:3, :]))
print("B[:, 2:4]=>\n{}".format(B[:, 2:4]))
print("B[:, 2]=>\n{}".format(B[:, 2]))
print("B[:, :]=>\n{}".format(B[:,:])

A=>
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14]
B=>
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
B[1:2]=>
[[5 6 7 8 9]]
B[1:3, 2:3]=>
[[ 7  8]
 [12 13]]
B[1:3, :]=>
[[ 5  6  7  8  9]
 [10 11 12 13 14]]
B[:, 2:4]=>
[[ 2  3]
 [ 7  8]
 [12 13]]
B[:, 2]=>
[ 2  7 12]
B[:, :]=>
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
```

## Universal関数

`numpy`はsin, cosなど、mathモジュールが提供する関数と同名の関数を提供する
それらはarrayに対して`arrayの全要素に適用`という動作をする

```python:universal.py
import numpy as np
import math

r = np.linspace(0, 0.5 * math.pi, 6)
print(r)

sin_r = np.sin(r)
print(sin_r)

cos_r = np.cos(r)
print(cos_r)

print("mathの提供する関数をnumpyに使用するとTypeErrorになる")
print(math.sin(r)

[0.         0.31415927 0.62831853 0.9424778  1.25663706 1.57079633]
[0.         0.30901699 0.58778525 0.80901699 0.95105652 1.        ]
[1.00000000e+00 9.51056516e-01 8.09016994e-01 5.87785252e-01
 3.09016994e-01 6.12323400e-17]
mathの提供する関数を使用するとTypeErrorになる
Traceback (most recent call last):
  File "test_conda.py", line 14, in <module>
    print(math.sin(r))
TypeError: only size-1 arrays can be converted to Python scalars
```