Teachable Machineで気軽にAIを体験

## はじめに
気軽にAIの学習やタスク(分類とか予測)を体験してみたいが、高価なAI用の機材が必要なのではないか？と思われるかもしれませんが、**無料で、画像、音声、ポーズを認識する機械学習モデルを簡単に作成できる**、[Teachable Machine](https://teachablemachine.withgoogle.com/)というサービスが存在します。
この記事では、Teachable Machineを利用して実際に画像分類を実施してみます。

上記の機械学習はAIの一分野であり、Teachable Machineでは機械学習の手法の1つであるディープラーニング(深層学習)が利用されています。
![AI00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/c8acb678-7cc2-46cf-632f-239bc3cab26f.png)

## 何をしたい？できる？
- **簡単に分類する為のモデル(判断ルール)を作成したい**
- **分類したい画像を使って、機械学習モデル学習の体験**
- **作った機械学習モデルで、画像を分類できるかの体験**

## 用意するもの
- **PC**　(Webカメラ付きのノートPCだと簡単に体験できます)
- **Webブラウザ**　(Chromeだとエラー無く進めると思います)
- **分類したいもの**　(野菜、ジュース、文房具、ぬいぐるみ等、用意できそうなもの)


## 機械学習モデルの学習と推論までの簡単な流れ
学習から分類を行うまでの流れとしては、以下のような流れになります。

**1. 分類に使う画像を用意**(各画像は正解がついている[犬の画像には、犬というラベル])
   学習では使わないけれども、類似している画像があるとモデルを試す時に利用することができます。
**2. 用意した画像を使って学習**(判断ルールの作成)
**3. 学習の結果、作成されたモデル(判断ルール)を使って分類を試す** 

![AI01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/c544fb56-d187-f528-22b0-f65ab230e5a9.png)

## Teachable Machineの操作手順
**この例では、3種類の分類を実施します。**

#### 1. [Teachable Machine](https://teachablemachine.withgoogle.com/)へアクセス
[使ってみる]をクリックします。
![AI02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/6043a59a-f241-cd79-e64b-d535bea36e2f.png)

#### 2. [画像プロジェクト]をクリック
![AI03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/b48374ac-1147-84d4-6e76-3cfece4c9ab8.png)

#### 3. [標準の画像モデル]をクリック
![AI04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/4418c64c-9782-a1f5-e2dc-c004d895afe4.png)

#### 4. [ウェブカメラ]をクリック
操作PC上に既に画像を用意しているのであれば、[アップロード]から画像を追加も可能です。
この例では、上手く学習できるように100枚位の画像を用意したいので、ここではウェブカメラを利用して画像を追加します。
![AI05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/c636d694-f892-478b-ece9-d00929be9d1f.png)

#### 4. 色々な方向から[長押しして録画]をクリックしながら撮影
![AI06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/cdcd0cb6-4fa7-a1ea-8725-0fae895bb820.png)

#### 5. 鉛筆マークをクリックし、撮影画像の分類(正解)を入力
![AI07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/6471b2d5-4af4-6a89-ecb0-f6d07d6c77f0.png)


#### 6. 別の画像を撮影する為、Class2で同じ操作を繰り返す
![AI08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/f1d95cbc-588a-90f2-d1cb-3b5cd744ee22.png)
![AI09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/3902f217-3d1b-086b-a790-a855bf73df82.png)

#### 7. 3種類目の画像を撮影する為、[クラスを追加]をクリックしてから同じ操作を繰り返す

![AI10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/abfa1a80-fd2a-9b88-1569-f5527f4c6da4.png)

![AI11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/77412763-137d-56fe-0311-270e363d8209.png)

#### 8. [モデルをトレーニングする]をクリックして学習開始

![AI12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/bcfcf51d-a381-f0e0-7eba-98a93c498520.png)

#### 9. プレビューでは学習で利用していないものを使って分類
**学習に利用していないが、似ているものを使って分類結果を試してみます。**
以下画像にあるように、恐竜くん**パペットのポーズを学習時の分類に合わせる事で、結果が変わってくる**のが確認できます。
**全く関係ない画像では、正解ではないけれども、3つの分類で一番近いものが回答**されます。
わからないものは、不明と言って欲しいところですが、分布外データの検知といった手法が必要となってきますので、ここでは割愛します。
![AI16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/f75b13d3-08a3-8833-65fa-7c2d252437ca.png)

## モデルのエクスポートを試す

作成したモデルをTeachable Machineのクラウド上にアップロードして、API経由で分類を試す事ができます。
ここでは、以下のようなサービス構成で画像分類を試すイメージになります。
(例ではWebサーバは用意してないので、置き換えてイメージして下さい)
![AI18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/799e08d9-22cf-1210-cb98-88714d59e89b.png)


#### 1. プレビュー部分にある[モデルをエクスポートする]をクリック
出力形式を選択する画面が出てくるので、 TensorFlow.js の「アップロード(共有可能なリンク)」を選択し、「モデルをアップロード」をクリックします。

![AI17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/bb864dfb-8da2-b6ef-622b-d2195e8113ac.png)

#### 2. モデルのアップロード

出力形式を選択する画面が出てくるので、TensorFlow.js の「アップロード(共有可能なリンク)」を選択し、「モデルをアップロード」をクリックします。
![AI19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/cfea8838-8f42-251d-e3c8-192f4d1b4faf.png)

#### 3. 生成されたコードのコピー
コードを使用するスニペット」のJavascript のコードをコピーし、Webサイトのbody タグ内などに貼り付ける事で利用できるようになります。

**簡易的に試す場合は、index.html ファイルを作り、 「コードを使用するスニペット」のJavascript のコードをコピーしてbody タグ内に貼り付けてからブラウザで読み込むことがで試すことができます。**

![AI20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/e257c5ea-eb5e-7f5f-f2fc-8617cb301beb.png)

```html:
//ファイル名はindex.htmlとして作成します
<!doctype html>
<html lang="en">
<head>
</head>
<body>
// ここにコピーしたコードを貼り付けます
</body>
</html>
```

#### 4. ブラウザでindex.html を開いて、[start]をクリック
カメラの使用を許可すると、画像分類を試すことができます。

![AI21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/270ca5d5-272c-c15c-1321-78cb28b144ab.png)
![AI22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/39a138bc-17dd-023b-6c92-53d67ab09b4a.png)
![AI23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/c60bbc79-cf9a-a0cd-daa9-f1aa326f0e76.png)


## モデルのダウンロードを試す

**作成したモデルをダウンロードして、Python環境で分類を試す事ができます。**
**例ではPython環境を簡単に利用する為に、[Google Collaboratory](https://colab.research.google.com/?hl=ja)を使って、全てクラウド上で試します。**
[Google Collaboratory](https://colab.research.google.com/?hl=ja)はgoogleアカウント作成を行うことで利用可能です。
(例ではWebサーバは用意してないので、置き換えてイメージして下さい)

![AI24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/1706e5c3-f980-8443-d73b-a3d752a1c1cd.png)
[Google Collaboratory](https://colab.research.google.com/?hl=ja)についての詳細は以下が参考になります。
https://atmarkit.itmedia.co.jp/ait/subtop/features/di/deeplearningenv_index.html

#### 1. モデルのダウンロード

出力形式を選択する画面で、TensorFlowの「Keras」を選択し、「モデルをダウンロード」をクリックします。
![AI25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/d5b65cfa-725d-0c72-1148-43c013927674.png)

#### 2. ダウンロードしたモデルをGoogle Collaboratoryへアップロード
Google Collaboratory上で[ファイル]を選択し、[ノードブックを新規作成]を選択します。
![AI27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/654aeedd-0a21-7b3b-43f6-f5080ba9afcd.png)
新規タブで**画面左側にあるフォルダアイコンをクリック**して、表示された部分にTeachable Machineから**ダウンロードしたファイルをドラッグ&ドロップでアップロード**します。
![AI28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/c3b388d6-0f56-65b5-3c27-5b222c6c533f.png)

#### 3. 分類したいファイルのアップロード
分類したいファイルをドラッグ&ドロップでアップロードします。
アップロードしたファイルは、以下のコードをGoogle Collaboratoryのセルに記載して実行([Shift+Enter]もしくはセル左側の矢印をクリック)する事で確認できます。
**ファイル名は実際にアップロードしたものに合わせて変更が必要です。**
```python:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

img = mpimg.imread("ファイル名を記載")
imgplot = plt.imshow(img)
```
![AI29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/a6e26933-1028-47c5-39c4-8bc0d4fafab2.png)

#### 4. Teachable Machineのコードコピーと修正
Teachable Machineのモデルをダウンロードした画面で、コードをコピーし、Google Collaboratoryのセルに貼り付けます。
2022/10月時点では以下の項目の修正が必要となります。
**・セルに張り付けたコードの分類ファイル名部分を実際にアップロードしたものに合わせて変更**
**・アップロードしたモデル名の"M"が小文字なので、コードのモデル名も小文字に変更**
**・アップロードした画像のサイズ変更部分のコードが古いので書き換え**
![AI30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/49d84b40-95b9-f6ab-9cb6-f4673ce27a1d.png)
![AI31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/b310400b-cd3a-3942-c3e5-1b13fcd58b23.png)
![AI32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/308158aa-1dfb-d2e4-1dda-da6c5f0cf770.png)
以下の部分をコピペして置き換えて頂ければと思います。
```python:
#resize the image to a 224x224 with the same strategy as in TM2:
#resizing the image to be at least 224x224 and then cropping from the center
size = (224, 224)

#image = ImageOps.fit(image, size, Image.Resampling.LANCZOS)

image = image.resize((size),resample=Image.BICUBIC)
```
#### 5. 分類の実行
Google Collaboratoryに貼り付けて修正したコードを実行([Shift+Enter]もしくはセル左側の矢印をクリック)すると、分類結果が表示されます。
後は、ファイル名を変更して、繰り返して分類を試すことができます。
![AI33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/9874f9e8-feaa-28ae-b5b3-467965d99989.png)



## (余談)画像を加工してどうなるかを試す
参考までに、色とポーズのどちらの影響が強いかを見る為に、同じ画像の色を変化して分類結果がどうなるか試してみます。
![AI36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1268577/e26d7dfe-e6b2-c4cc-97e2-80fbebb4ad7c.png)

OpenCVの関数imread()の画像読み込みは色の順番がBGRとの事なので、それを利用して画像を変換させて、変換後のファイル名を指定しての分類を実施した結果となります。
```python:
import matplotlib.pyplot as plt
import cv2
#ファイルの読み込み
img2 = cv2.imread("変更前のファイル名")
#ファイルの保存
plt.imsave('変換後のファイル名', img2)
```