AIが作った画像か判別するAIを4hで作ったらまあまあの精度出たのでWebサービスとして公開した件

### AIが作った画像か判断するAIを作りました
https://twitter.com/Azunyan1111_/status/1583073281090863104

##### Webサービスとして提供していましたが、飽きたのでクローズしました
※機械学習やったことない人が書いてます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110135/1624d9c2-c941-dd58-d2e1-2ce66517c911.png)

### Why
ピクシブのお気持ち表明記事の「AI生成作品のフィルタリング機能」というのが気になり、機械学習で作ることが出来るのではと思いやってみることに
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110135/1fc39523-62a9-8919-eaed-7067a8d06177.png)

## Step 1 素材を集める
割愛

## Step 2 コードを書く
AutoGluon というAutoML(全自動で良い感じに機械学習してくれる奴)ツールを使ったので、パラメーターの調整や難しいコードは何も書いてません。
過去に使って良い感じになった奴を流用します。

```main.py
from autogluon.vision import ImagePredictor, ImageDataset

if __name__ == "__main__":
    # \imagesの中にはAIが生成した画像フォルダとAIが作ってない画像フォルダを用意
	dataset = ImageDataset.from_folder(r'C:\Users\admin\ml\novel\images')
    # 学習用やテスト用のデータに分割
	train, val, test = dataset.random_split(val_size=0.1, test_size=0.1,random_state=1)
    
    # 何時間も学習させたくないので緩めの設定で
	hyperparameters = {'batch_size': 16, 'early_stop_patience': 15}
	time_limit = 60 * 60
	predictor = ImagePredictor()
	predictor.fit(train, time_limit=time_limit, presets='medium_quality_faster_train', hyperparameters=hyperparameters)
    # テストデータでどれくらい良かったか出力する
	test_acc = predictor.evaluate(test)
	print('Top-1 test acc: %.3f' % test_acc['top1'])

    # 結果を保存する
	filename = 'my.ag'
	predictor.save(filename)
```

## Step 3 完成!　したのでTFとか出してみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110135/73841543-7631-ce9d-dfc1-92ee744a8b6a.png)



```tfとかを出す非常に良くない即席で可読性と保守性が最悪な書いてはいけない悪いコード@合ってるか知らんけど.py
# モデルロード
filename = "my.ag"
predictor_loaded = ImagePredictor.load(filename)

#データセット読み込み分割
dataset = ImageDataset.from_folder(r'C:\Users\admin\ml\novel\images')
train, val, test = dataset.random_split(val_size=0.1, test_size=0.1,random_state=1)

#予想させる
result = predictor_loaded.predict(test)

# tfとか計算する@合ってるか知らんけど
tp=0
tn=0
fp=0
fn=0
for key, val in test['label'].iteritems():
    if val == 0:
        if val == result[key]:
            tp+=1
        else:
            fn+=1
    else:
        if val == result[key]:
            tn+=1
        else:
            fp+=1
print("TP:",tp)
print("FN:",fn)
print("FP:",fp)
print("TN:",tn)
print("Accuracy:",(tp+tn)/(tp+tn+fp+fn))
print(classification_report(test['label'], result))
```
結果@ random_stateを再生っていした結果です
ラベル0がAIなのでTPがAIをAIと判定
```
TP: 139
FN: 10
FP: 1
TN: 87
Accuracy: 0.9535864978902954
              precision    recall  f1-score   support

           0       0.99      0.93      0.96       149
           1       0.90      0.99      0.94        88

    accuracy                           0.95       237
   macro avg       0.94      0.96      0.95       237
weighted avg       0.96      0.95      0.95       237
```
## Step 4 Webサービス化

機械学習しているコードは自体はPythonですが、僕はGo言語が好きなのでサーバーはGoで書きます。
Web Page→Golang Echo Server→Fast API→AutoGluon って感じで遠回りしてますが作ります

```これは機械学習して結果を返すだけのサーバー.py
from autogluon.vision import ImagePredictor
from pathlib import Path

from fastapi import FastAPI

labels = sorted([dir.name for dir in Path(r'C:\Users\admin\ml\novel\images').iterdir() if dir.is_dir()])
print(labels)
filename = "my.ag"
predictor_loaded = ImagePredictor.load(filename)

app = FastAPI()


@app.get("/")
def read_root(file_name: str = ""):
	if file_name == "":
		return {"Error": "file name not found"}
	return check(file_name)


def check(file: str):
	result = predictor_loaded.predict_proba(file)
	label = labels[result.idxmax(axis=1)[0]]
	proba = result.max(axis=1)[0]
	print(f'結果: {label} (確信度={proba})')

	if label == 'AI':
		return {"IsAI": True, "Percent": proba}
	else:
		return {"IsAI": False, "Percent": proba}
```

後はGo + Echoで作ったサーバーからFastAPIで作った機械学習して結果を返すだけのサーバーにリクエストを投げて結果を返すだけ

## Step 5 世界に公開
クラウドだとGPUの値段で高額請求をされるので、メインPCをそのままポートを開けてクラウドフレア刺して公開です
https://ai.azunyan1111.com/

## それで肝心な精度はどうなんですか?
テストデータではAccuracyは95%くらいでAIが作った画像か見抜けるようになりました。
AIが作った画像をAIが作った画像と見抜ける確率は非常に高いですが、手書きで書かれた場合のパターンを宇野ク集められてないので手書きで書いた絵をAIが描いた絵と見誤ることは多々ある感じです。(TFの値とか見ればそう@たぶん)


## 本職の人ならもっと出せるはず
機械学習知識0の自分でもまあまあの精度が出たので本職のプロがやればフィルタリングは簡単に出来ると思います。
知らんけど