Numpy完全基礎の全て

#Numpyの基本
『深層学習の教科書（翔泳社）』と、『機械学習のエッセンス（加藤公一著）』を元に自分用のNumpyの基本を制作しました。コードのほとんどは本から引用しております。
##Numpyって何？
Numpyとは、簡単に言えば「Pythonの計算を高速に行ってくれるもの」です！
「ナンパイ」または「ナムパイ」と呼ばれます。

「高速の行ってくれるもの」といいましたが、正確には『ライブラリ』と呼ばれるものです。
『ライブラリ』とは、『役に立つコードの塊』と思ったら良いです。

Numpyは他のライブラリの根底に関係する重要な役割を持っています。

##Numpyを使おう！
以下の様にする事で、numpyの準備が全て完了します

```
import numpy as np
```
as npというものはパッケージ名を「np」にしたよ、という意味です。

#Numpy１次元配列
##Numpyの関数
Numpyを用いることで、日常生活で使う数学の関数を使うことができるようになります。

以下はその例です。
###ユニバーサル関数
```
import numpy as np

np.exp(1) #eのべき乗
np.log(np.e) #自然対数
np.sin(np.pi) #正弦
np.sqrt(2) #平方根（ルート）
np.abs(-1) #絶対値
```
###統計関数
```
import numpy as np
arr = np.arrange(15).reshape(3, 5)

arr.mean(axis=0) #列ごとの平均
arr.sum(axis=1) #行の合計
arr.min() #arrの最小値
arr.argmax(axis=0) #それぞれの列の最大値のインデックス番号

```
##Numpyにおける配列
いつものPythonのようにNumpyにも配列が存在します。(**ndarray**といいます）
以下の様にして、配列を作成できます。
**np.array(リスト)**

```
np.array([0,1,2,3,4,5,6,7,8,9])
```
上記でも数字の配列を作成できますが、次のようにしても同様の意味になります。

```
np.arange(10)
```
##Numpy配列のスライス
次のようにして行います。
**arr[start:end] = 変更したい値**

```
abc = np.arange(10)
abc[0:5] = 0 #１個目から５個目までを0に変えています
print(abc) #出力結果「[0 0 0 0 0 5 6 7 8 9]」
```

##Numpy配列の注意
Numpy配列は代入先の値を変更すると、元の値も変更されてしまいます。それでは困るので以下のように、copy()メソッドを使います。
**コピーしたい配列.copy()**

```
import numpy as np

a = np.array([0,1,2,3,4,5,6,7])

#コピーします
b = a.copy()
#配列の要素を変えてみて、元の要素が変更されていないか確認します
b[0] = 7

print(a)
print(b)
```
##ブールインデックス参照
ブールインデックス参照とは、[]の中にTrueかFalseの配列を用いて要素を取り出す方法です。
以下の様にして、Trueに該当する箇所のNumpy配列を作成して返してくれます。

**arr[ndarrayの論理値の配列]**

```
arr = np.array([2, 4, 6, 7])
print(arr[np.array([True, True, True, False])])
```

##集合関数
集合関数は、１次元配列のみを対象とし、数学の集合演算を行う関数です。
###・重複を取り除きソートした結果を返す
**np.unique()**
###・少なくとも一方に存在する要素を取り出しソートする（和集合）
**np.union1d(x, y)**
###・共通する要素を取り出しソートする（積集合）
**np.intersect1d(x, y)**
###・共通する要素を取り除きソートする（差集合）
**np.setdiff1d(x, y)**
##乱数を扱う
乱数を扱うには基本的にnumpy.randint()を使いますが、次のように記述しておくと楽になります。

```
from numpy.random import randint
```
・０以上１未満の乱数を生成する
**np.random.rand()**
()の中に入れた整数の数だけ乱数が生成されます。

・ｘ以上ｙ未満の整数をz個生成する
**randint(x, y, z)**
さらに、zには(2,3)などの引数もいれることができ、それによって2×3の行列を生成できます。

```
import numpy as np
from numpy.random import randint

#arr1に０以上１０以内の整数の行列(5×2)を代入する
arr1 = randint(0, 11, (5,2))
print( arr1 )

#arr2に０以上１未満の乱数を３つ代入する
arr2 = np.random.rand(3)
print( arr2 )
```
#二次元配列
二次元行配列は行列に該当する。
**np.array([リスト,リスト])**
とすることで、二次元配列を作成することができる

##二次元配列の操作
・各次元ごとの要素数を返す
**ndarray配列.shape**

・指定した引数と同じ形の行列に変換する
**ndarray配列.reshape(a,b)**

```
import numpy as np
arr = np.array([[1,2,3,4],[5,6,7,8]])
print( arr )

#arrの形状を表示する
print( arr.shape )

#arrを４行２列の行列に変換する
print(arr.reshape(4,2))
```
##axisについて
二次元配列からはaxisという概念が重要になってきます。
**列**ごとに処理を行う:**axis=0**
**行**ごとに処理を行う:**axis=1**

```
#要素を足し合わせる
arr = np.array([[1,2,3],[4,5,6]])

print(arr.sum()) #要素をすべて足し合わせる
print(arr.sum(axis=0)) #列を足し合わせる
print(arr.sum(axis=1)) #行を足し合わせる
```
##ファンシーインデックス参照
ndarray配列から**ある特定の順序で行を抽出**する

```
arr = np.array([[1,2],[3,4],[5,6],[7,8]])
print(arr[[3,2,0]]) #インデックス番号で記述する

#出力結果
#[[7 8]
# [5 6]
# [1 2]]
```
##行列の転置
行と列を入れ替える（転置といいます）
**np.transpose(arr)**　もしくは
**arr.T**
で実行することができます。
##ソート
**argsort()メソッド**について
①要素の数字が大きい順に前から並べる
②インデックス番号を返す

```
arr = np.array([15,30,5])
arr.argsort()

#出力結果
#array([2, 0, 1])
```

#行列計算
###・二つの行列積を返す
**np.dot(a,b)関数**
###・ノルムを返す
**np.linalg.norm(変数（ベクトル）)関数**

```
import numpy as np

arr = np.arange(9).reshape(3,3)

#arrとarrの行列積を出力
print( np.dot(arr, arr) )

#vecを定義します
vec = arr.reshape(9)

#ノルムを出力する
print( np.linalg.norm(vec) )