AIが作った画像か判断するAIを作りました
Why
ピクシブのお気持ち表明記事の「AI生成作品のフィルタリング機能」というのが気になり、機械学習で作ることが出来るのではと思いやってみることに
Step 1 素材を集める
割愛
Step 2 コードを書く
AutoGluon というAutoML(全自動で良い感じに機械学習してくれる奴)ツールを使ったので、パラメーターの調整や難しいコードは何も書いてません。
過去に使って良い感じになった奴を流用します。
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)
# 何時間も学習させたくないので緩めの設定で
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とかF-valueとか出してみる
# モデルロード
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)
#予想させる
result = predictor_loaded.predict(test)
# tfとか計算する@合ってるか知らんけど
tp=0
tn=0
tLen=0
fp=0
fn=0
fLen=0
for key, val in test['label'].iteritems():
if val == 0:
if val == result[key]:
tp+=1
else:
fn+=1
tLen+=1
else:
if val == result[key]:
tn+=1
else:
fp+=1
fLen+=1
print("TP:",tp/tLen)
print("FN:",fn/fLen)
print("FP:",fp/fLen)
print("TN:",tn/tLen)
print("Accuracy:",(tp+tn)/(tp+tn+fp+fn))
precision = (tp)/(tp+fp)
recall = tp/(tp+fn)
f1 = 2 * precision * recall / (precision + recall)
print("Precision:",precision)
print("Recall:",recall)
print("F-value:",f1)
結果
TP: 0.9808917197452229
FN: 0.025423728813559324
FP: 0.01694915254237288
TN: 0.7388535031847133
Accuracy: 0.9818181818181818
Precision: 0.9871794871794872
Recall: 0.9808917197452229
F-value: 0.9840255591054313
Step 4 Webサービス化
機械学習しているコードは自体はPythonですが、僕はGo言語が好きなのでサーバーはGoで書きます。
Web Page→Golang Echo Server→Fast API→AutoGluon って感じで遠回りしてますが作ります
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/
それで肝心な精度はどうなんですか?
テストデータでは一応95%の確立でAIが作った画像か見抜けるようになりました。
AIが作った画像をAIが作った画像と見抜ける確率は非常に高いですが、手書きで書いた絵をAIが描いた絵と見誤ることは多々ある感じです。(TFの値とか見ればそう@たぶん)
その原因は分かっていて、AIが生成する画像の学習データは満遍なく偏りなく集められているのですが、手書きで書かれた場合のパターンというか種類が多すぎて偏りが出てしまったのが原因です。
本職の人ならもっと出せるはず
機械学習知識0の自分でもまあまあの精度が出たので本職のプロがやればフィルタリングは簡単に出来ると思います。
知らんけど
コメント