「ゼロから作るDeep Learning」自習メモ（その６の２）Kaggleの猫と犬のデータセット

「ゼロから作るDeep Learning」(斎藤 康毅　著　オライリー・ジャパン刊)を読んでいる時に、参照したサイト等をメモしていきます。 [その６](https://qiita.com/slow_learner/items/5589a95081d30f82fbbd)←　→[その６の３](https://qiita.com/slow_learner/items/3b7d3b8f4c7821a2b617)　→ [その７](https://qiita.com/slow_learner/items/efbe24999562c3630c93)

お仕着せのMNISTデータセットを読み込んで、学習させるというのを２通りやってみましたが、MNISTデータセットではない画像集をMNISTの形式に変換して学習させる、というのもやってみようかと思います。

元データは、Kaggleの猫と犬のデータセット。下記サイトからダウンロードできます。
https://www.microsoft.com/en-us/download/details.aspx?id=54765

けっこう大きなファイルで、ダウンロードにも解凍にも時間がかかります。

##ダウンロードした画像データの内容を調べて見る

ダウンロードしたファイルの中身
![p6-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686010/d9c0f5f3-0c4d-c8e3-ecce-d9e89411d254.jpeg)

フォルダ　PetImages　の下にあるフォルダ Cat と Dog に、画像が入っています。
![p6-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686010/8640f2a8-6eed-c3c4-da13-001ab7b8da6e.jpeg)
 
画像はカラーで、大きさはそれぞれ違っています。
0.jpg から 12499.jpg とファイル名が連番になっていますので、犬、猫それぞれ 12500枚 ずつの画像があるということになります。


##画像情報を配列に格納する

MNISTデータセットと同じようにするためには、
カラーをグレースケールにする
同じ大きさにそろえる
といった加工をしてから配列に格納しなければなりません。

まずは、画像データを１枚確認してみます。

```python
import os.path
import matplotlib.pyplot as plt
from matplotlib.image import imread

dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset/Cat'
imgData = imread(dataset_dir + '/0.jpg') 
plt.imshow(imgData)
plt.show()
```
![p6-4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686010/718b442c-97fd-3744-eb8e-099ee4fddb37.jpeg)

この画像をNumPy配列に格納してみます。

```python
import numpy as np 
img = np.array(imgData)
print(img.ndim)
print(img.shape)
```
結果は
3
(375, 500, 3)
(高さ, 幅, 色)の３次元の配列として格納されているようです。

で、色が　０は赤、１が緑、２が青　ということらしいので、
確認してみます。
配列img と同じ形の配列imgRを０で初期化して、
imgの赤のデータだけをimgRに格納して表示してみます。

```python
imgR = np.zeros_like(img)
imgR[:, :, 0] = img[:, :, 0]
plt.imshow(imgR)
plt.show()
```
![p6-5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686010/15e74730-a439-3e4a-f263-7bbf20d5f25a.jpeg)
確かに赤いですね。

同様に緑と青も確認。

```python
imgG = np.zeros_like(img)
imgG[:, :, 1] = img[:, :, 1]
plt.imshow(imgG)
plt.show()
```
![p6-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686010/3388fae4-a33f-6faf-cc9c-43bcbdde9d7a.jpeg)

```python
imgB = np.zeros_like(img)
imgB[:, :, 2] = img[:, :, 2]
plt.imshow(imgB)
plt.show()
```
![p6-7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686010/23a52a95-5470-5be2-24ef-16c65715427c.jpeg)

念のため、RGBに分けた配列を集計して表示してみます。

```python
imgRGB = np.zeros_like(img)
imgRGB = imgR + imgG + imgB
plt.imshow(imgRGB)
plt.show()
```
![p6-8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686010/0d23b021-5b98-d2dc-ce77-d3f985775e93.jpeg)

ちゃんと元の画像に戻りました。

##グレースケールにしてみる

ライブラリPillowを使って、グレースケールに変換してみます。

```python
from PIL import Image
imgGray = np.array(Image.open(dataset_dir + '/0.jpg').convert('L'))
print(imgGray.ndim)
print(imgGray.shape)
plt.imshow(imgGray,cmap=plt.cm.gray)
plt.show()
```
![p6-9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686010/52d019ae-0e28-96d1-f8ac-39914dadf38d.jpeg)
２次元の配列として格納されています。

上のほうで、ＲＧＢに分けて画像を処理してましたが、もしかしてＲＧＢに同じ数値を入れればグレーになるのでは？　と考えて、こんなことしてみました。

```python
img=Image.open(dataset_dir + '/0.jpg')
imgN = np.array(img)
img0 = np.zeros_like(imgN)
img0[:,:,0]=imgN[:,:,0]
img0[:,:,1]=imgN[:,:,0]
img0[:,:,2]=imgN[:,:,0]
plt.imshow(img0)
plt.show()
```
![c6-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686010/a50a51b2-792a-b81a-687f-f7e67eea8c7e.jpeg)

グレーになりましたが、赤色部分だけなので、ちょっと感じが違います。

```python
img=Image.open(dataset_dir + '/0.jpg')
imgN = np.array(img)
w, h, c =imgN.shape
imgX=np.zeros((w,h))
imgX[:,:]=imgN[:,:,0]//3 + imgN[:,:,1]//3 + imgN[:,:,2]//3
plt.imshow(imgX,cmap=plt.cm.gray)
plt.show()
```
![c6-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686010/f569bc58-b1be-d3e5-cb6e-73793088ed21.jpeg)

なんかそれっぽくなりました。



##リサイズしてみる
Pillowのresizeメソッドで256×256にしてみます。

```python
import numpy as np 
import matplotlib.pyplot as plt
from matplotlib.image import imread
from PIL import Image

img=Image.open(dataset_dir + '/0.jpg').convert('L').resize((256, 256))
imgResize = np.array(img)
print(imgResize.ndim)
print(imgResize.shape)
plt.imshow(imgResize,cmap=plt.cm.gray)
plt.show()
```
![p6-10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686010/ccfef7fb-9782-6130-58f3-3d0ce479f16f.jpeg)

指定した大きさになりましたが、縦横の比率が変わってしまいました。画質も不鮮明に。

ためしにMNISTと同じ２８×２８の大きさにしてみると
![p6-11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686010/f4f2fb15-33fe-bc44-9b60-ab8053698595.jpeg)
何の画像なのか、まったくわからなくなりました。


これとは反対に、元の画像のサイズが小さいものもあって、5534.jpgは　３６×６０　です。
![p6-12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686010/0a53fe0d-dac8-fa2d-14e1-ad3340cfbb60.jpeg)

これを２５６×２５６にリサイズすると、こうなります。
![p6-13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686010/e2970c6c-d7dc-1a56-e46b-99960551bea7.jpeg)

pillow を使わないで画像をリサイズ等する方法は [その19の２](https://qiita.com/slow_learner/items/b705e5cf89a271b9f8d1)

##配列 dataset に画像データを格納する 

猫１２５００枚のうち、最初の５００枚をテストデータとし、残り１２０００枚を訓練データにします。犬も同様。
データは１００×１００のグレースケールに変換して、datasetに格納します。縦横の比率や画像の鮮明さが変わるのは無視します。
ラベルは、０：猫、１：犬　ということにして、datasetに格納するときに付加します。

フォルダ内の.jpgファイルを反復処理するために、次のようなプログラムを組んでみました。犬と猫はフォルダ別に分かれているので、フォルダ別に処理しています。
学習の際に与えるデータは犬猫がランダムに混在している必要はないはずだし、ミニバッチ処理ではランダムに抽出するので、これで問題はないと思います。

```python
# 学習用データ編集

import os
import glob
from PIL import Image
import numpy as np 

dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset'
catfiles = glob.glob(dataset_dir + '/Cat/*.jpg')
dogfiles = glob.glob(dataset_dir + '/Dog/*.jpg')

tsl = []
tsi = []
trl = []
tri = []
tst_count = 0
trn_count = 0

count = 0
for f in catfiles:
    lblA = 0
    img = Image.open(f).convert('L').resize((100, 100))
    imgA = np.array(img)
    imgA = imgA.flatten()
    imgA = imgA.tolist()

    if count < 500:
        tsl.append(lblA)
        tsi.append(imgA)
        tst_count += 1
    else:
        trl.append(lblA)
        tri.append(imgA)
        trn_count += 1
    count += 1
・
・
・
```

が、EXIFデータが壊れていると思われる、というメッセージが出て中断します。

>
C:\Users\021133\AppData\Local\Continuum\anaconda3\lib\site-packages\PIL\TiffImagePlugin.py:747: UserWarning: Possibly corrupt EXIF data.  Expecting to read 80000 bytes but only got 0. Skipping tag 64640
  " Skipping tag %s" % (size, len(data), tag))
C:\Users\021133\AppData\Local\Continuum\anaconda3\lib\site-packages\PIL\TiffImagePlugin.py:747: UserWarning: Possibly corrupt EXIF data.  Expecting to read 65536 bytes but only got 0. Skipping tag 3
  " Skipping tag %s" % (size, len(data), tag))
C:\Users\021133\AppData\Local\Continuum\anaconda3\lib\site-packages\PIL\TiffImagePlugin.py:747: UserWarning: Possibly corrupt EXIF data.  Expecting to read 404094976 bytes but only got 0. Skipping tag 5
  " Skipping tag %s" % (size, len(data), tag))
C:\Users\021133\AppData\Local\Continuum\anaconda3\lib\site-packages\PIL\TiffImagePlugin.py:747: UserWarning: Possibly corrupt EXIF data.  Expecting to read 404619264 bytes but only got 0. Skipping tag 5
  " Skipping tag %s" % (size, len(data), tag))
C:\Users\021133\AppData\Local\Continuum\anaconda3\lib\site-packages\PIL\TiffImagePlugin.py:747: UserWarning: Possibly corrupt EXIF data.  Expecting to read 131072 bytes but only got 0. Skipping tag 3
  " Skipping tag %s" % (size, len(data), tag))
・・・
OverflowError: Python int too large to convert to C ssize_t

調べて見ると、ファイル読み込みの繰り返し処理では、次のような順番でファイルを処理していました。この順番で826番目のファイル 1074.jpg でエラーが発生しています。

>
C:\Users\021133/dataset/Cat\0.jpg
C:\Users\021133/dataset/Cat\1.jpg
C:\Users\021133/dataset/Cat\10.jpg
C:\Users\021133/dataset/Cat\100.jpg
C:\Users\021133/dataset/Cat\1000.jpg
C:\Users\021133/dataset/Cat\10000.jpg
C:\Users\021133/dataset/Cat\10001.jpg
C:\Users\021133/dataset/Cat\10002.jpg
C:\Users\021133/dataset/Cat\10003.jpg
C:\Users\021133/dataset/Cat\10004.jpg
C:\Users\021133/dataset/Cat\10005.jpg
C:\Users\021133/dataset/Cat\10006.jpg
C:\Users\021133/dataset/Cat\10007.jpg
C:\Users\021133/dataset/Cat\10008.jpg
C:\Users\021133/dataset/Cat\10009.jpg
C:\Users\021133/dataset/Cat\1001.jpg
C:\Users\021133/dataset/Cat\10010.jpg

問題の写真とそのプロパティはこれ。
![p6-14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686010/ad0462e5-e8f3-6845-0b60-53cab9227a1d.jpeg)
何が悪いのかよくわかりません。
しかたないので、エラーはエラーとして例外処理にして、その後の処理を継続できるようにしました。

```python
# 学習用データ編集

import os
import glob
from PIL import Image
import numpy as np 

dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset'
catfiles = glob.glob(dataset_dir + '/Cat/*.jpg')
dogfiles = glob.glob(dataset_dir + '/Dog/*.jpg')

tsl = []
tsi = []
trl = []
tri = []
tst_count = 0
trn_count = 0

count = 0
for f in catfiles:
    try:
        lblA = 0
        img = Image.open(f).convert('L').resize((100, 100))
        imgA = np.array(img)
        imgA = imgA.flatten()
        imgA = imgA.tolist()
    except:
        print(str(count)+":"+f+" error")

    if count < 500:
        tsl.append(lblA)
        tsi.append(imgA)
        tst_count += 1
    else:
        trl.append(lblA)
        tri.append(imgA)
        trn_count += 1
    count += 1

count = 0
for f in dogfiles:
    try:
        lblA = 1
        img = Image.open(f).convert('L').resize((100, 100))
        imgA = np.array(img)
        imgA = imgA.flatten()
        imgA = imgA.tolist()
    except:
        print(str(count)+":"+f+" error")

    if count < 500:
        tsl.append(lblA)
        tsi.append(imgA)
        tst_count += 1
    else:
        trl.append(lblA)
        tri.append(imgA)
        trn_count += 1
    count += 1

dataset = {}
dataset['test_label']  = np.array(tsl, dtype=np.uint8)
dataset['test_img']    = np.array(tsi, dtype=np.uint8)
dataset['train_label'] = np.array(trl, dtype=np.uint8)
dataset['train_img']   = np.array(tri, dtype=np.uint8)    
```
結局、猫で３件、犬で３件異常データがありました。

>825:C:\Users\021133/dataset/Cat\1074.jpg error
7088:C:\Users\021133/dataset/Cat\5127.jpg error
8790:C:\Users\021133/dataset/Cat\666.jpg error
1895:C:\Users\021133/dataset/Dog\11702.jpg error
10601:C:\Users\021133/dataset/Dog\829.jpg error
10686:C:\Users\021133/dataset/Dog\8366.jpg error

異常があった画像のところには、直前に格納した画像と同じものが格納されてしまっていますが、まあ、実害はないだろうから、このまま進めていく事にします。

この処理では画像サイズを100×100と、比較的大きめにしているので、メモリエラーになったりします。

>
MemoryError                               Traceback (most recent call last)
<ipython-input-1-34cc7a9989f0> in <module>()
     65 dataset['test_img']    = np.array(tsi, dtype=np.uint8)
     66 dataset['train_label'] = np.array(trl, dtype=np.uint8)
---> 67 dataset['train_img']   = np.array(tri, dtype=np.uint8)
MemoryError: 

こうなると、同時に立ち上がっているプログラムをとめたり、再起動して使用していたメモリを開放したり、画像サイズを変えたり、処理件数を減らしたりと、いろいろやらないといけなくなります。

結局、猫と犬を別々に処理して、最終結果を連結することにしました。
まず、猫の処理をして、結果をpickleで退避

```python
# 学習用データ編集

import os
import glob
from PIL import Image
import numpy as np 

dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset'
catfiles = glob.glob(dataset_dir + '/Cat/*.jpg')
dogfiles = glob.glob(dataset_dir + '/Dog/*.jpg')

tsl = []
tsi = []
trl = []
tri = []
tst_count = 0
trn_count = 0

count = 0
for f in catfiles:
    try:
        lblA = 0
        img = Image.open(f).convert('L').resize((100, 100))
        imgA = np.array(img)
        imgA = imgA.flatten()
        imgA = imgA.tolist()
    except:
        print(str(count)+":"+f+" error")

    if count < 500:
        tsl.append(lblA)
        tsi.append(imgA)
        tst_count += 1
    else:
        trl.append(lblA)
        tri.append(imgA)
        trn_count += 1
    count += 1

cat = {}
cat['test_label']  = np.array(tsl, dtype=np.uint8)
cat['test_img']    = np.array(tsi, dtype=np.uint8)
catlabel = np.array(trl, dtype=np.uint8)
catimg   = np.array(tri, dtype=np.uint8)

import pickle
dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset'

save_file = dataset_dir + '/tempcat.pkl'    
with open(save_file, 'wb') as f:
    pickle.dump(cat, f, -1) 
    
save_file = dataset_dir + '/tempcatL.pkl'    
with open(save_file, 'wb') as f:
    pickle.dump(catlabel, f, -1) 

    save_file = dataset_dir + '/tempcatI.pkl'    
with open(save_file, 'wb') as f:
    pickle.dump(catimg, f, -1) 
```
次に、途中経過をクリアしてから、犬の処理

```python
import gc
del tsl
del tsi
del trl
del tri
del cat
del catlabel
del catimg
gc.collect()

# 学習用データ編集

import os
import glob
from PIL import Image
import numpy as np 

dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset'
catfiles = glob.glob(dataset_dir + '/Cat/*.jpg')
dogfiles = glob.glob(dataset_dir + '/Dog/*.jpg')

tsl = []
tsi = []
trl = []
tri = []
tst_count = 0
trn_count = 0

count = 0
for f in dogfiles:
    try:
        lblA = 1
        img = Image.open(f).convert('L').resize((100, 100))
        imgA = np.array(img)
        imgA = imgA.flatten()
        imgA = imgA.tolist()
    except:
        print(str(count)+":"+f+" error")

    if count < 500:
        tsl.append(lblA)
        tsi.append(imgA)
        tst_count += 1
    else:
        trl.append(lblA)
        tri.append(imgA)
        trn_count += 1
    count += 1

dog = {}
dog['test_label']  = np.array(tsl, dtype=np.uint8)
dog['test_img']    = np.array(tsi, dtype=np.uint8)
doglabel = np.array(trl, dtype=np.uint8)
dogimg   = np.array(tri, dtype=np.uint8)

import pickle
dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset'
save_file = dataset_dir + '/tempdog.pkl'    
with open(save_file, 'wb') as f:
    pickle.dump(dog, f, -1) 
    
save_file = dataset_dir + '/tempdogL.pkl'    
with open(save_file, 'wb') as f:
    pickle.dump(doglabel, f, -1) 
save_file = dataset_dir + '/tempdogI.pkl'    
with open(save_file, 'wb') as f:
    pickle.dump(dogimg, f, -1) 
```

いったん終わらせてメモリをクリアしてから、退避した結果を読み込んで、連結します。
テスト用データの連結。

```python
import os.path
import pickle
import numpy as np 
dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset'
mnist_file = dataset_dir + '/tempcat.pkl'
with open(mnist_file, 'rb') as f:
    cat = pickle.load(f)

mnist_file = dataset_dir + '/tempdog.pkl'
with open(mnist_file, 'rb') as f:
    dog = pickle.load(f)

dataset = {}
dataset['test_label']  = np.append(cat['test_label'],dog['test_label'], axis=0)
dataset['test_img']    = np.append(cat['test_img'],dog['test_img'], axis=0)

import pickle
dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset'
save_file = dataset_dir + '/catdogmnist.pkl'    #拡張子は.pkl

with open(save_file, 'wb') as f:
    pickle.dump(dataset, f, -1) 
```

訓練用データの連結。データが大きいため、ラベルと画像を別々にしている。

```python
import os.path
import pickle
import numpy as np 
dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset'

mnist_file = dataset_dir + '/tempcatL.pkl'
with open(mnist_file, 'rb') as f:
    cat = pickle.load(f)

mnist_file = dataset_dir + '/tempdogL.pkl'
with open(mnist_file, 'rb') as f:
    dog = pickle.load(f)

catdog   = np.append(cat,dog, axis=0)
save_file = dataset_dir + '/catdogL.pkl' 
with open(save_file, 'wb') as f:
    pickle.dump(catdog, f, -1) 

mnist_file = dataset_dir + '/tempcatI.pkl'
with open(mnist_file, 'rb') as f:
    cat = pickle.load(f)

mnist_file = dataset_dir + '/tempdogI.pkl'
with open(mnist_file, 'rb') as f:
    dog = pickle.load(f)

catdog   = np.append(cat,dog, axis=0)
save_file = dataset_dir + '/catdogI.pkI' 
with open(save_file, 'wb') as f:
    pickle.dump(catdog, f, -1) 
```

##学習させてみる

```python
# 2層ニューラルネットワークのクラス
import numpy as np
from common.functions import *

class TwoLayerNet:
    def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):
        # 重みの初期化
        self.params = {}
        self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)
        self.params['b1'] = np.zeros(hidden_size)
        self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)
        self.params['b2'] = np.zeros(output_size)
        
    def predict(self, x):
        W1, W2 = self.params['W1'], self.params['W2']
        b1, b2 = self.params['b1'], self.params['b2']
        a1 = np.dot(x, W1) + b1
        z1 = sigmoid(a1)
        a2 = np.dot(z1, W2) + b2
        y = softmax(a2)
        return y

    # x:入力データ、　t:教師データ
    def loss(self, x, t):
        y = self.predict(x)
        return cross_entropy_error(y, t)
    
    def accuracy(self, x, t):
        y = self.predict(x)
        y = np.argmax(y, axis=1)
        t = np.argmax(t, axis=1)
        accuracy = np.sum(y == t) / float(x.shape[0])
        return accuracy
    
    def gradient(self, x, t):
        W1, W2 = self.params['W1'], self.params['W2']
        b1, b2 = self.params['b1'], self.params['b2']
        grads = {}
        batch_num = x.shape[0]
        
        # forward
        a1 = np.dot(x, W1) + b1
        z1 = sigmoid(a1)
        a2 = np.dot(z1, W2) + b2
        y = softmax(a2)
        
        # backward
        dy = (y - t) / batch_num
        grads['W2'] = np.dot(z1.T, dy)
        grads['b2'] = np.sum(dy, axis=0)
        
        dz1 = np.dot(dy, W2.T)
        da1 = sigmoid_grad(a1) * dz1
        grads['W1'] = np.dot(x.T, da1)
        grads['b1'] = np.sum(da1, axis=0)

        return grads

# 4.5.2 ミニバッチ学習の実装

import sys, os
import pickle
import numpy as np
from common.functions import *

def to_one_hot(label):
    t = np.zeros((label.size, 2))
    for i in range(label.size):
        t[i][label[i]] = 1
    return t

dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset'

mnist_file = dataset_dir + '/catdogI.pkl'
with open(mnist_file, 'rb') as f:
    catdogImg = pickle.load(f)
x_train = catdogImg.astype(np.float16)
x_train /= 255
catdogImg = []

mnist_file = dataset_dir + '/catdogL.pkl'
with open(mnist_file, 'rb') as f:
    catdogLabel = pickle.load(f)
t_train = to_one_hot(catdogLabel)
    
# ハイパーパラメータ
iters_num = 10000
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.1

train_loss_list = []

network = TwoLayerNet(input_size=10000, hidden_size=50, output_size=2)
for i in range(iters_num):
    # ミニバッチの取得
    batch_mask = np.random.choice(train_size, batch_size)
    x_batch = x_train[batch_mask]
    t_batch = t_train[batch_mask]
    
    # 勾配の計算
    grad = network.gradient(x_batch, t_batch) # 誤差逆伝播法 速い
    
    # パラメータの更新
    for key in ('W1', 'b1', 'W2', 'b2'):
        network.params[key] -= learning_rate * grad[key]

    #学習経過の記録
    loss = network.loss(x_batch, t_batch)
    train_loss_list.append(loss)

# networkオブジェクトを、pickleで保存する。保存したオブジェクトは、推論処理で使う
import pickle
save_file = dataset_dir + '/catdogkekka_weight.pkl'    #拡張子は.pkl
with open(save_file, 'wb') as f:
    pickle.dump(network, f, -1)    
```
これは、訓練データの読み込み部分以外は、これまで使ってきたプログラムと同じです。

##学習したニューロネットで推論させてみる

```python
import numpy as np
from common.functions import *

class TwoLayerNet:
    def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):
        # 重みの初期化
        self.params = {}
    def predict(self, x):
        W1, W2 = self.params['W1'], self.params['W2']
        b1, b2 = self.params['b1'], self.params['b2']
        
        a1 = np.dot(x, W1) + b1
        z1 = sigmoid(a1)
        a2 = np.dot(z1, W2) + b2
        y = softmax(a2)
        
        return y


import sys, os
import pickle

def normalize(key):
    dataset[key] = dataset[key].astype(np.float32)
    dataset[key] /= 255
    return dataset[key]

def to_one_hot(label):
    T = np.zeros((label.size, 10))
    for i in range(label.size):
        T[i][label[i]] = 1
    return T

dataset_dir = os.path.dirname(os.path.abspath('__file__'))+'/dataset'
mnist_file = dataset_dir + '/catdogmnist.pkl'
with open(mnist_file, 'rb') as f:
    dataset = pickle.load(f)
x = normalize('test_img')
t = dataset['test_label']

#network = TwoLayerNet(input_size=10000, hidden_size=50, output_size=10)
weight_file = dataset_dir + '/catdogkekka_weight.pkl'
with open(weight_file, 'rb') as f:
    network = pickle.load(f)

accuracy_cnt = 0
for i in range(len(x)):
    y = network.predict(x[i])
    p= np.argmax(y) 
    if p == t[i]:
        accuracy_cnt += 1

print("Accuracy:" + str(float(accuracy_cnt) / len(x))) 
```
これも、これまで使ったプログラムと同じものです。
結果は
>Accuracy:0.615

となっており、あてずっぽうより少しマシ、というレベル。

```python
ccnt = np.zeros(2, dtype=np.int)
ecnt = np.zeros((2, 2), dtype=np.int)
for i in range(len(x)):
    y = network.predict(x[i])
    c = t[i]
    p= np.argmax(y) 
    if p == c:
        ccnt[c] += 1
    else:
        ecnt[p, c] += 1
        
print(ccnt)
print(ecnt)
```
>[195 420]
[[  0  80]
 [305   0]]

1000件中725件を「犬」と判定している。うち420件が正解で、正解率58%。
275件を「猫」と判定し、195件正解で、正解率70%。
判定が犬に偏っています。

ところが、もう一度学習をし直すと、今度は猫に偏りました。
この形式のデータでは、犬か猫かの特長を明確につかめていないのかもしれません。


##参考にしたサイト

今回は、画像データの処理について学習しました。

[オリジナルの画像からデータセットを作成する方法](https://intellectual-curiosity.tokyo/2019/07/02/%E3%82%AA%E3%83%AA%E3%82%B8%E3%83%8A%E3%83%AB%E3%81%AE%E7%94%BB%E5%83%8F%E3%81%8B%E3%82%89%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BB%E3%83%83%E3%83%88%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B%E6%96%B9/)
[画像処理その3 ~NumPy配列~](https://qiita.com/kikuchiTakuya/items/298d83efd82dedd4adda)
[Pythonの画像処理ライブラリPillow(PIL)の使い方](https://note.nkmk.me/python-pillow-basic/)
[Pillowで画像を一括リサイズ（拡大・縮小）](https://note.nkmk.me/python-pillow-image-resize/)
[PIL/Pillow チートシート](https://qiita.com/pashango2/items/145d858eff3c505c100a)
[matplotlibのcmap(colormap)パラメータの一覧](https://beiznotes.org/matplot-cmap-list/)

また、pythonの list　と numpy.ndarray の違いがよくわかっていなかったことを思い知らされました。

[Pythonのリストと配列とnumpy.ndarrayの違いと使い分け](https://note.nkmk.me/python-list-array-numpy-ndarray/)

deep learning では、メモリを大量消費することもわかりました。

[pythonでメモリ不足になったときにすること](https://www.haya-programming.com/entry/2017/02/09/190512)


 [その６](https://qiita.com/slow_learner/items/5589a95081d30f82fbbd)←　→[その６の３](https://qiita.com/slow_learner/items/3b7d3b8f4c7821a2b617)　→ [その７](https://qiita.com/slow_learner/items/efbe24999562c3630c93)

[読めない用語集](https://qiita.com/slow_learner/items/03eb3367119e98b5a22c)