【機械学習】Cifar10の画像をCNNで分類【画像分析】

# KerasのCifar10の画像をモデルを作ってで画像分類する

## データのダウンロード
```python
#cifar10のデータダウンロード
from keras.datasets import cifar10
(X_train, Y_train), (X_test, Y_test) = cifar10.load_data()
```
### データの確認
```python
print(X_train[0], Y_train.shape)
print(X_train.shape, Y_train.shape)

import matplotlib.pyplot as plt
plt.title(Y_train[0])
plt.imshow(X_train[0])
plt.show()

[[[ 59  62  63]
  [ 43  46  45]
  [ 50  48  43]
  ...
  [158 132 108]
  [152 125 102]
  [148 124 103]]

 [[ 16  20  20]
  [  0   0   0]
  [ 18   8   0]
  ...
  [123  88  55]
  [119  83  50]
  [122  87  57]]

 [[ 25  24  21]
  [ 16   7   0]
  [ 49  27   8]
  ...
  [118  84  50]
  [120  84  50]
  [109  73  42]]

 ...

 [[208 170  96]
  [201 153  34]
  [198 161  26]
  ...
  [160 133  70]
  [ 56  31   7]
  [ 53  34  20]]

 [[180 139  96]
  [173 123  42]
  [186 144  30]
  ...
  [184 148  94]
  [ 97  62  34]
  [ 83  53  34]]

 [[177 144 116]
  [168 129  94]
  [179 142  87]
  ...
  [216 184 140]
  [151 118  84]
  [123  92  72]]] 

[[6]
 [9]
 [9]
 ...
 [9]
 [1]
 [1]]

(50000, 32, 32, 3) (50000, 1)
```
![c10 first image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/4426edc6-20a4-930f-28bc-2639020a59e0.png)
・上の3×3行列の集まりが画像を表している。
・各画像に対応する数字の行列が画像のタイトルを表す。

## 100個画像を取り出してどんな画像化を確認
```python
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(10,10))
#画像ごとにタイトルをつける
label = ["airplane", "automobile", "bird", "cat", "deer", "dog", "flog", "horse", "ship", "truck"]
for i in range(100):
  plt.subplot(10, 10, i+1)
  plt.subplots_adjust(wspace=0.4, hspace=0.6)
  plt.imshow(X_train[i])
  plt.title(label[Y_train[i][0]], fontsize = 7)
  plt.axis("off")
plt.show()
```
![c10 first image number 100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/cabdc4f3-c423-8ef5-69b1-a2ba5a40ca60.png)

## 各ラベルがトレーニングデータにどのくらい入ってるのか確認
```python
import seaborn as sns
ax = sns.countplot(x=Y_train.ravel())
plt.xlabel("Ravel", fontsize = 8)
plt.ylabel("Count", fontsize = 8)
plt.title('Count training data by rabel')
for p in ax.patches:
    ax.annotate((p.get_height()), (p.get_x()+0.3, p.get_height()+100))
plt.show()
```
![count x train ravel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/c28f30b3-6483-82f0-0bd2-acd5b9141fd6.png)


## 各ラベルごとに画像を20枚ずつ取り出して見てみる
```python
#画像データを正規化
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train = X_train/ 255
X_test = X_test/255

#各画像の平均画像を見てみる
import matplotlib.pyplot as plt
plt.figure(figsize=(1,8))
for j in range(10):
    xtrains = np.zeros(3072, dtype = float)
    for i in range(50000):
        if Y_train[i] == j:
            xtrains += np.ravel(X_train[i])

    xim = xtrains / 5000
    plt.subplot(10, 1, j+1)
    plt.xticks([])
    plt.yticks([])
    plt.imshow(xim.reshape(32,32,3))
plt.show()
```
![image 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/b2a2f342-7476-6f9a-cd63-3b1416734303.png)
![image 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/3e097e6e-43f0-46d4-b67a-46065b843ad2.png)
![image 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/80887181-cdf5-99d5-54e2-c54e2b2b9436.png)
![image 4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/af0dd2b0-5ed2-1ab3-64bb-346cdf078237.png)
![image 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/0ac615d8-8e3d-6071-8ae5-54218f15c157.png)
![image 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/4463cda9-8b22-2c71-d420-188e63dbd233.png)
![image 7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/61c1c302-dd6d-891c-c24e-bcabe9492f18.png)
![image 8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/945af5df-e78d-0b4e-30e0-46225d90227a.png)
![image 9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/d51a75ad-1310-15db-3a95-9f9b14b83626.png)
![image 10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/f90703fb-fdd2-d530-b8fd-e6d34999a109.png)

## 各ラベルごとに平均画像を見てみる
```python
import seaborn as sns
for t in  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]:
    fig = plt.figure(figsize=(10,2))
    h = 0
    k = 0
    plt.title(label[t], fontsize = 13)
    plt.xticks([])
    plt.yticks([])
    sns.despine(top=True, right=True, left=True, bottom=True)
    while h < 20:
        if Y_train[k] == t:
            fig.add_subplot(2, 10, h+1) 
            plt.xticks([])
            plt.yticks([])
            sns.despine(top=True, right=True, left=True, bottom=True)
            plt.imshow(X_train[k])
            k += 1
            h += 1
        else:
            k += 1
    plt.show()
```
![mean image by label.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/daa4ab07-211d-f99f-4870-9360a182fb61.png)
・上からラベル順に並んでいる。
・背景の色が特徴的で、一番目（airplane）や下二つ（ship、truck）は屋外を連想させる色をしている。

# CNNで分類
## モデルの作成
```python
#CNNモデルを作る
from keras.models import Sequential
from keras.layers import Dense, Flatten, Conv2D, MaxPooling2D, AvgPool2D
model = Sequential()
model.add(Conv2D(32, (5,5), activation = 'relu', padding = 'same', input_shape = (32,32,3)))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dense(32, activation = "relu"))

model.add(Conv2D(32, (5,5), activation = 'relu', padding = 'same'))
model.add(Dense(32, activation = "relu"))
model.add(AvgPool2D(pool_size=(2, 2)))

model.add(Conv2D(64, (5,5), activation = 'relu', padding = 'same'))
model.add(Dense(64, activation = "relu"))
model.add(AvgPool2D(pool_size=(2, 2)))

model.add(Conv2D(64, (4,4), activation = 'relu', padding = 'same'))
model.add(Dense(64, activation = "relu"))

model.add(Conv2D(10, (1,1), activation = 'relu', padding = 'same'))
model.add(Flatten())
model.add(Dense(10, activation = "softmax"))
```

## 学習実行
```python
from tensorflow import keras
from keras import optimizers
Y_train_oh = keras.utils.to_categorical(Y_train, 10)
Y_test_oh = keras.utils.to_categorical(Y_test, 10)
opt = keras.optimizers.RMSprop(lr=1e-5, rho=0.9, epsilon=1e-08, decay=0.0)
model.compile(optimizer = opt, loss = "categorical_crossentropy", metrics=["accuracy"])
history = model.fit(X_train, Y_train_oh, validation_split=0.25, epochs=100, verbose=1)
```

## ヒストリーの可視化
```python
fig = plt.figure(figsize=(8, 8))
#ヒストリーの可視化（正確差）
fig.add_subplot(1, 2, 1) 
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
plt.plot(label="Training accuracy")
plt.plot(label="Validation accuracy")
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='best')

#ヒストリーの可視化（損失）
fig.add_subplot(1, 2, 2) 
loss = history.history["loss"]
val_loss = history.history["val_loss"]
plt.plot(label="Training loss")
plt.plot(label="validation loss")
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='best')
plt.show()
```
![loss and accuracy e =100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/b3098cd1-5256-8dcd-14b3-b864187eda0a.png)
エポック＝100じゃ足りない

### エポック＝120
![loss and accuracy e =120.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/98fb865f-3b0b-7b92-315c-4fe26d00c4f8.png)


### エポック＝700
![loss and accuracy e =700.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658998/ab37fa64-cddb-ca4a-826f-e473c3020a03.png)
トレーニングの方はうまく機能してる。
テスト損失は一定量下がると上昇してしまう。
→勾配消失問題？？