魚を分類する画像分類AIの作成

# 目次
1.はじめに
2.データ収集
3.モデル作成
4.評価
5.アプリケーション
6.まとめ

# はじめに
　私は自社開発エンジニアをしておりますAI勉強中の27歳です。昨今、AIの発展が注目されておりますが、AIに関するスキルの修得は難易度が高いと感じておりました。そのような状況の中で、適切にスキルを身に着けるアプローチとして、AIプログラミングスクールの受講が考えられます。独学では思うように学習が進められなかったため、思い切ってAIプログラミングスクールAidemyを受講いたしました。本記事では、Aidemyで約2か月間学んだ内容を基に、成果物として画像分類AIを作成し、その内容をまとめました。
　作成するAIは、魚の画像を分類するAIです。作成したモデルは、flaskを用いたWebアプリケーションで利用できるように実装しました。
 
# データ収集
　データには、CIFAR-100の中にあるスーパークラス「fish」を使用しました(  CIFAR-100：https://www.cs.toronto.edu/~kriz/cifar.html )。このスーパークラスは「aquarium fish」,「flatfish」,「ray」,「shark」,「trout」の5つのクラスから構成されており、各クラスで訓練データが500枚、検証データが100枚あります。以下のような画像を使用します。
　観賞魚
 ![観賞魚.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654023/03b54b08-a670-a7a7-ad7f-7c5eef2f041c.png)
　カレイ
![カレイ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654023/2670f8bc-eb8c-ae7a-ad42-0032ab3b8089.png)
　エイ
![エイ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654023/de865838-cf51-cc6e-81bc-aaf24a139a43.png)
　サメ
![サメ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654023/13e9ab20-c466-a4a4-1a70-6f0ba7602a9f.png)
　マス
![マス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654023/62b66184-38d5-2112-c09f-16b6a5ab1996.png)

 
　以下のコードで、CIFAR-100の中からaquarium fish=1, flatfish=32, ray=67, shark=73, trout=91の魚画像を抽出して、順に0～4をラベル付けしました。

~~~python
(w_X_train, w_y_train), (w_X_test, w_y_test) = cifar100.load_data()
target = [1,32,67,73,91]
w_tr_mask = np.arange(0)
for n in w_y_train:
  w_tr_mask=np.append(w_tr_mask,np.isin(np.array(n) , target))

tr_mask =w_tr_mask.astype(np.bool)
X_train = w_X_train[tr_mask, :, :, :]
y_train = w_y_train[tr_mask,:]

w_te_mask = np.arange(0)
for n in w_y_test:
  w_te_mask=np.append(w_te_mask,np.isin(np.array(n) , target))
te_mask =w_te_mask.astype(np.bool)
X_test = w_X_test[te_mask, :, :, :]
y_test = w_y_test[te_mask,:]

y_train = np.where(y_train == 1, 0, y_train)
y_train = np.where(y_train == 32, 1, y_train)
y_train = np.where(y_train == 67, 2, y_train)
y_train = np.where(y_train == 73, 3, y_train)
y_train = np.where(y_train == 91, 4, y_train)

y_test = np.where(y_test == 1, 0, y_test)
y_test = np.where(y_test == 32, 1, y_test)
y_test = np.where(y_test == 67, 2, y_test)
y_test = np.where(y_test == 73, 3, y_test)
y_test = np.where(y_test == 91, 4, y_test)

y_train = to_categorical(y_train)
y_test = to_categorical(y_test)
~~~


# モデル設計
　以下のように、VGG16を用いて転移学習を行うモデルを設計しました。
~~~python
# モデルにvggを使います
input_tensor = Input(shape=(32, 32, 3))
vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)

# vggのoutputを受け取り、5クラス分類する層を定義
top_model = Sequential()
top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
top_model.add(Dense(256, activation='relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(5, activation='softmax'))

# vggとtop_modelを連結します
model = Model(inputs=vgg16.input, outputs=top_model(vgg16.output))

# vggの層の重みを変更不能にします
for layer in model.layers[:19]:
    layer.trainable = False

# コンパイルします
model.compile(loss='categorical_crossentropy',
              optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
              metrics=['accuracy'])

# 学習を行います
history = model.fit(X_train, y_train, batch_size=100, epochs=100, validation_data=(X_test, y_test))

~~~






# 評価
　以下のコードで正解率、学習時の正解率の推移を出力しました。正解率は0.632で、また正解率の推移について、epoch数80以降で0.6あたりで収束しました。

~~~python
# 精度の評価
scores = model.evaluate(X_test, y_test, verbose=1)
print('Test loss:', scores[0])
print('Test accuracy:', scores[1])

# 可視化
plt.plot(history.history['accuracy'], label='acc', ls='-', marker='o')
plt.plot(history.history['val_accuracy'], label='val_acc', ls='-', marker='x')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.suptitle('model1', fontsize=12)
plt.legend()
plt.show()
model.summary()
~~~

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654023/95a8a219-17f5-117f-79d9-6a42a29337e6.png)




# アプリケーション
　画像ファイルを選択して送信することで、画像がどのカテゴリーに分類されるかがわかります。実際に以下のエイの画像を選択して送信してみます。

![エイ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654023/9ef2d9bf-f4cc-f002-b1f8-b0be89eed51d.jpeg)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654023/c88e3885-b67c-0f19-7a44-f54f46e5a030.png)




　適切にエイと分類できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654023/464e4da2-f64b-9471-bd52-7a6f279e5102.png)




# まとめ
　アプリケーションを作成する中で、正解率の向上が難しかったです。バッチサイズやEpoch数を変更しても正解率が0.6より大きくならなかったです。今後の課題として、使用する画像データの特徴を考慮したデータ操作を行う等で性能を高めていくことが考えられました。

:::note info
このブログはAidemy Premiumのカリキュラムの一環で、受講修了条件を満たすために公開しています。
:::