ディープラーニングを実装から学ぶ（１）はじめに


ディープラーニングの勉強を開始したが、大学レベルの数学知識が必要のため、ついていけなかった人も多いのではないでしょうか。
まずは、理論抜きで実装から入って仕組みを理解できないかと考えています。

# はじめに
機械学習は、**黒魔術**とも言われています。なぜか分からないが結果が出ると。
「それなら理論はわからなくても、まずは、実践してみましょう。」ということで、実装から開始したいと思います。実装により何か得られればと考えています。

# MNISTの確認
機械学習の実験用データとして[MNIST](http://yann.lecun.com/exdb/mnist/)が一般的に利用されているようです。０～９までの手書きの数字の画像です。当面、このデータを利用しますので、まずこのデータの読み込みからはじめましょう。
ホームページより、データをダウンロードします。データは、学習用の画像 60,000枚とテスト用の画像 10,000枚を含んでいます。

- train-images-idx3-ubyte.gz: 学習用画像
- train-labels-idx1-ubyte.gz: 学習用正解ラベル
- t10k-images-idx3-ubyte.gz: テスト用画像
- t10k-labels-idx1-ubyte.gz: テスト用正解ラベル

実装には、Pythonを利用います。私は、[Anaconda](https://www.anaconda.com/download/)を利用しています。多次元配列や数値関数をサポートするnumpyも含まれています。今後、numpyを多用することになります。実行には、ブラウザ上からPythonを実行できるJupyter Notebookを利用します。こちらもAnacondaに含まれています。

## 画像データの読み込み
ファイルの先頭に件数、縦横のピクセル数などの情報が格納されているようです。形式の詳細は、MNISTのページを参照してください。ビッグエンディアンで格納されているので変換しています。
ファイルは、"c:\mnist\"フォルダに格納されているとします。

```python

import gzip
import numpy as np

mnist_path = 'c:\\mnist\\'

with gzip.open(mnist_path + 'train-images-idx3-ubyte.gz', 'rb') as f:
    buffer = f.read()
size = np.frombuffer(buffer, np.dtype('>i4'), 1, offset=4)
rows = np.frombuffer(buffer, np.dtype('>i4'), 1, offset=8)
columns = np.frombuffer(buffer, np.dtype('>i4'), 1, offset=12)
data = np.frombuffer(buffer, np.uint8, offset=16)
print(size[0])
print(rows[0])
print(columns[0])
```
```
60000
28
28
```
60,000画像、28×28ピクセルであることが確認できます。

次に画像データを確認してみましょう。データを6000:28:28の配列に変換します。1枚目のデータを表示します。

```python

data = np.reshape(data, (60000,28,28))  # 60000:28:28の配列に変換
print(data[0]) # 1枚目の画像データ表示
```
```
[[  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   3  18  18  18 126 136 175  26 166 255 247 127   0   0   0   0]
 [  0   0   0   0   0   0   0   0  30  36  94 154 170 253 253 253 253 253 225 172 253 242 195  64   0   0   0   0]
 [  0   0   0   0   0   0   0  49 238 253 253 253 253 253 253 253 253 251  93  82  82  56  39   0   0   0   0   0]
 [  0   0   0   0   0   0   0  18 219 253 253 253 253 253 198 182 247 241   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0  80 156 107 253 253 205  11   0  43 154   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0  14   1 154 253  90   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0 139 253 190   2   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0  11 190 253  70   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0  35 241 225 160 108   1   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0  81 240 253 253 119  25   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0  45 186 253 253 150  27   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0  16  93 252 253 187   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0 249 253 249  64   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0  46 130 183 253 253 207   2   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0  39 148 229 253 253 253 250 182   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0  24 114 221 253 253 253 253 201  78   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0  23  66 213 253 253 253 253 198  81   2   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0  18 171 219 253 253 253 253 195  80   9   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0  55 172 226 253 253 253 253 244 133  11   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0 136 253 253 253 212 135 132  16   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0]]
```
0～255のグレースケールで画像が格納されています。

matplotlibを利用し、実際に画像を表示してみましょう。

```python

import matplotlib.pyplot as plt
plt.imshow(data[0], 'gray')
plt.show()
```

![5.png](https://qiita-image-store.s3.amazonaws.com/0/212365/8d3a2654-17dc-f07e-a726-90dbe160b750.png)

5のような画像が表示されました。
## 正解ラベルの読み込み
では、正解を見てみましょう。60,000画像分の正解データがあります。

```python

with gzip.open(mnist_path + 'train-labels-idx1-ubyte.gz', 'rb') as f:
    buffer = f.read()
size = np.frombuffer(buffer, np.dtype('>i4'), 1, offset=4)
data = np.frombuffer(buffer, np.uint8, offset=8)
print(size[0])
```
```
60000
```
1枚目の正解は？

```python

print(data[0])
```
```
5
```
やはり、正解は5でした。
NMISTは、欧米人の書いたデータなのか、日本の数字の書き方とは微妙に異なっているようです。

今後の学習で利用しやすいように、0～9を表す10個の配列とし、正解を1、不正解を0としてデータを格納します。

```python

t = np.zeros((data.size, 10))
for i in range(data.size):
    t[i, data[i]] = 1
print(t[0])
```
```
[ 0.  0.  0.  0.  0.  1.  0.  0.  0.  0.]
```

# MNISTデータの準備
画像データは、表示用に28×28に変換しましたが、学習データとしては、1画像、784個のデータとみなします。また、データは実数型に変換します。
最後に、MNISTデータの読み込み部分を関数化

```python

def load_mnist( mnist_path ) :
    return _load_image(mnist_path + 'train-images-idx3-ubyte.gz'), \
           _load_label(mnist_path + 'train-labels-idx1-ubyte.gz'), \
           _load_image(mnist_path + 't10k-images-idx3-ubyte.gz'), \
           _load_label(mnist_path + 't10k-labels-idx1-ubyte.gz')
def _load_image( image_path ) :
    # 画像データの読み込み
    with gzip.open(image_path, 'rb') as f:
        buffer = f.read()
    size = np.frombuffer(buffer, np.dtype('>i4'), 1, offset=4)
    rows = np.frombuffer(buffer, np.dtype('>i4'), 1, offset=8)
    columns = np.frombuffer(buffer, np.dtype('>i4'), 1, offset=12)
    data = np.frombuffer(buffer, np.uint8, offset=16)
    image = np.reshape(data, (size[0], rows[0]*columns[0]))
    image = image.astype(np.float32)
    return image
def _load_label( label_path ) :
    # 正解データ読み込み
    with gzip.open(label_path, 'rb') as f:
        buffer = f.read()
    size = np.frombuffer(buffer, np.dtype('>i4'), 1, offset=4)
    data = np.frombuffer(buffer, np.uint8, offset=8)
    label = np.zeros((size[0], 10))
    for i in range(size[0]):
        label[i, data[i]] = 1
    return label
```

これで、ディープラーニングを行うためのデータの準備ができました。