『ゼロから作るDeep Learning』に入門を試みる

# はじめに

未経験から昨年の10月に機械学習に基づくプロダクトを扱う部署のエンジニアとして配属されまして、キャッチアップのための良書を探していたのですが、[『ゼロから作るDeep Learning』](https://www.amazon.co.jp/%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E4%BD%9C%E3%82%8BDeep-Learning-%E2%80%95Python%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%81%AE%E7%90%86%E8%AB%96%E3%81%A8%E5%AE%9F%E8%A3%85-%E6%96%8E%E8%97%A4-%E5%BA%B7%E6%AF%85/dp/4873117585)が良いらしいとのこと。
未だエンジニア文化には明るくない新参者ではありますが、ひとまずモチベの続く限り学習メモを残していこうと思います。
自分の前提知識は[CourseraのMachine Learning](https://www.coursera.org/learn/machine-learning)を一周した程度で、数学については大学受験以来になります。


## 環境

- macOS High Sierra 10.13.6

- Python 3.6.6 :: Anaconda custom (64-bit)

- 実行環境自体はJupyterNotebookです。

## C1：Numpy,Matplotlib概要

Pythonの環境設定、基本的な構文などはスキップ。
Numpy, Matplotlibについては復習を兼ねて写経します。
  
Numpyのインポート、四則演算です。基本的には全て要素ごとの演算が行われるらしい。
以前Numpyを使ったときは雰囲気でやってたので、この辺の基本からやってくれるのはありがたい。

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


x = np.array([1.0, 2.0, 3.0])
print(x)

# numpyの配列はndarray型で定義される
print(type(x))

# ndarrayどうしの計算
y = np.array([2.0, 4.0, 6.0])
print(x + y)
print(x - y)
# 要素ごと（element-wise）の計算を行う
print(x * y)
print(x / y)
```

実行結果。
```
[1. 2. 3.]
class 'numpy.ndarray'
[3. 6. 9.]
[-1. -2. -3.]
[ 2.  8. 18.]
[0.5 0.5 0.5]
```
x, yについて対応したインデックスの要素の演算が行われていることが確認できます。
  
次は行列（2次元配列）の計算です。

```python:c1.py
# ２次元配列(行列)
A = np.array([[1, 2], [3, 4]])
print(A)

# ndarrayの形状
print(A.shape)

# 配列内要素のデータ型
print(A.dtype, '\n')

# 行列どうしの計算
B = np.array([[3, 0], [0, 6]])
print(A + B)
print(A * B)
```

実行結果。
```
\[[1 2]
 [3 4]]
(2, 2)
int64

[[ 4  2]
 [ 3 10]]
[[ 3  0]
 [ 0 24]]
```
ndarray.shape, ndarray.dtypeでサイズ＆要素のデータ型がわかります。
また、行列も同様に要素ごとの計算が行われています。
  
Numpyでは基本的に演算対象のサイズが等しいことが求められるのですが、ブロードキャスト機能によってサイズが自動的に補正されます。

```python:c1.py
# ブロードキャスト
# numpyで形状の異なる配列どうしの計算を行うための機能

# 2*2サイズのAと同じ形状になるように、スカラー10が計算時に[[10, 10], [10, 10]]に変形される
A = np.array([[1, 2], [3, 4]])
print(A * 10)

# Aと、1*2サイズのCが同じ形状になるように、Cが計算時に[[5, 5], [5, 5]]に変形される
C = np.array([5, 5])
print(A * C)
```

実行結果。
```
[[10 20]
 [30 40]]
[[ 5 10]
 [15 20]]
```
コメントどおり、スカラー値と行列Cのサイズが、行列Aに合わせて補正されて計算されています。
ブロードキャストは名前しか知らなかったのですが、本書では図解の説明も入っていてありがたいです。
  
ndarray配列の要素へのアクセスは、通常のリストのインデックスでの参照と近い感覚だと思います。
条件を指定しての要素の抽出なども簡単にできます。

```python:c1.py
# 要素へのアクセス

# Pythonの通常のインデックス操作
X = np.array([[51, 55], [14, 19], [0, 4]])
print(X)
print(X[0])
print(X[0][1], '\n')

# Xをベクトルに変換し、複数の要素をインデックス指定によって抽出
X = X.flatten()
print(X)
print(X[np.array([0, 2, 4])], '\n')

# 条件を満たす要素のみを抽出
# ndarrayに比較演算子を使うとBool配列が返る
# これを利用してX > 15がTrueであるXの要素を抽出
print(X > 15)
print(X[X > 15])
```

実行結果。
```
[[51 55]
 [14 19]
 [ 0  4]]
[51 55]
55

[51 55 14 19  0  4]
[51 14  0]

[ True  True False  True False False]
[51 55 19]
```
2段落目のベクトルへの展開はndarray.flatten()メソッドで行います。
CourseraのOctaveでもそうでしたが、配列に比較演算子を使うとBoolの配列が返ってくるというのは少し慣れません…。  
  
次はMatplotlibのpyplotモジュールです。グラフの描画と画像の読み込み、表示が紹介されています。
まずはグラフから。

```python:c1.py
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline

# データ作成
x = np.arange(0, 6, 0.1) # 0~6まで0.1ステップで配列を生成
y = np.sin(x)

# グラフの描画
plt.plot(x, y)
plt.show()

# 2枚目
# cos関数の追加
y1 = np.sin(x)
y2 = np.cos(x)

# グラフの描画
plt.plot(x, y1, label='sin')
plt.plot(x, y2, linestyle = '--', label='cos')
plt.xlabel('x') # x軸のラベル
plt.ylabel('y') # y軸のラベル
plt.title('sin & cos') # グラフのタイトル
plt.legend()
plt.show()
```

実行結果。
![sin.png](https://qiita-image-store.s3.amazonaws.com/0/298190/ceed3ea5-50b6-467f-14e0-3ac095f8490e.png)
![sincos.png](https://qiita-image-store.s3.amazonaws.com/0/298190/f1034795-79d6-f9e4-045c-8d5c1935fa7e.png)

基本的には、Numpyの関数などでデータを用意し、それをpyplot.plotで描画、pyplot.show()で表示というフローのようです。
Matplotlibも写経しっぱなしになりがちなので、この程度はググらずかけるようになりたい。
  
画像の読み込みにはimageモジュールのimread(), imshow()を使います。

```python:c1.py
# 画像の表示
from matplotlib.image import imread
# 公式githubから落としたデータPATHを指定
img = imread('deep-learning-from-scratch-master/dataset/lena.png')
plt.imshow(img)
plt.show()
```

実行結果。
![rena.png](https://qiita-image-store.s3.amazonaws.com/0/298190/54225295-eca4-3f0a-336d-112e1ccff8e2.png)

この画像、MNISTなんかと同じで定番データらしいですね。これから飽きるほど見ることになるのでしょう。

## 終わりに

Markdownでこれだけ書いたのが初めてで死ぬほど肩が凝ってしまったので、一旦このへんで切らせていただこうと思います。
物足りないボリューム感になってしまいましたが、内容自体は非常に親切で読みやすくて順調に進んでいけると思うので、順次ここにアウトプットしていきたいと思います。
  
正直、こんだけ機械学習がバズった後に未経験からどの程度追いつけるかを考えてしまうと夜も眠れないくらいの焦燥があるのですが、牛歩でもいいから歩みを止めず頑張ろうと思います。
後々に、自分と同じような初心者の方の助けになれれば嬉しいです。