TadaoYamaokaの開発日記

個人開発しているスマホアプリや将棋AIの開発ネタを中心に書いていきます。

ChatGPTでHacker Newsから人工知能に関連する人気記事を抽出する

人工知能に関するニュースは、最初に英語で発信されることが多い。
Hacker Newsは、人工知能を含む計算機科学に関するニュース記事を投稿するサイトとして英語圏で人気がある。

Hacker Newsはタイトルのみが並んだシンプルな見た目で、どれが人工知能に関連するホットな記事か見分けるのが難しい。
そこで、Hacker NewsのREST APIを使い、人気順に並べ替えて、人工知能に関連する記事かをChatGPTで判定するようにした。

結果は、Google Sheetsに出力するようにした。
一連の処理は、Google Apps Scriptで実装した。

Hacker News REST API

Hacker Newsの記事一覧は、REST APIで取得できる。
APIの仕様は、こちらにある。
GitHub - HackerNews/API: Documentation and Samples for the Official HN API

人気記事は、
https://hacker-news.firebaseio.com/v0/topstories.json
で、取得する。
最大500記事のID一覧が取得される。

各記事は、IDを元に、
https://hacker-news.firebaseio.com/v0/item/< id >.json
で取得する。
取得されるのは、「記事ID」、「スコア」、「日時」、「タイトル」、「URL」などである。

Hacker Newsから記事一覧を取得する処理

Google Apps Scriptで、Hacker Newsから記事一覧を取得してGoogle Sheetsに保存する処理は、こちらのコードを参考にした。
Hacker Newsを日本語訳してSlackに通知(Google Apps Script) · GitHub

スプレッドシートは、あらかじめ作成して、1行目に列名を記述しておく必要がある。

参考にしたコードになかったが、以下の処理を追加した。

タイトルをGoogle翻訳

スプレッドシートの関数でタイトルを翻訳するようにした。

=GOOGLETRANSLATE("<タイトル>", "en", "ja")
scoreの更新

1日以上経過した記事のscoreを更新するようにした。

score順にソート

処理の最後に、ソートする処理を追加した。
SpreadSheetsSQLには、ソートする機能はないが、privateのプロパティにアクセスして、ソートするようにした。

sheetObj.sheet_.sort(3, false);

ChatGPTで人工知能に関連する記事か判定する

REST APIで記事のタイトルが取得できるので、タイトルを元に人工知能に関連する記事か判定する。
記事のURLから記事の内容を取得して判定する方が多くの情報から判断できるが、課金が膨らみそうなため、使用する情報はタイトルのみとした。

Google Apps Scriptで、OpenAI APIを使用する処理は、こちらの記事を参考にした。
【忘備録】SlackチャンネルにChatGPTを組み込んでみた!【Google Apps Script】 | 情報学部生の気ままなブログ

人工知能に関連する記事か判定する方法

systemロールのcontentを「Answer Yes or No if the article is related to artificial intelligence(人工知能に関連する記事かをYesかNoで答えよ)」として、userロールのcontentに、記事のタイトルを設定して、YesかNoが返却されることを期待してリクエストする。

結果に、Yesが含まれているかを文字列検索して、含まれていれば人工知能に関連する記事と判断する。

なお、プロンプトを設計する際は、PlayGroundを使うと便利である。
https://platform.openai.com/playground

ソースコード

実装したソースコードは以下の通り。
スプレッドシートのIDと、OpenAI API Keyは、Apps Scriptのプロパティから取得するようにしている。
※コードにバグがあり想定外に課金される可能性も否定できないので、使用する際は自己責任でお願いします。

実行結果

実行結果のスプレッドシートの例を示す。
スプレッドシートにscore順に出力されて、related_ai列にTRUE/FALSEで人工知能に関連する記事かが出力されている。

まとめ

海外の人工知能に関連するニュースを効率的に確認できるように、Hacker Newsから人工知能に関連する人気記事を自動的に抽出する仕組みを実装した。
人工知能に関連する記事かの判定には、ChatGPT(OpenAI API)を活用した。

ChatGPT以前であれば、このような判定には教師データを準備してモデルを構築する必要があった。
大規模言語モデルを使うと、個別タスクごとのモデルの学習が不要になり、プロンプトの工夫のみで様々なタスクが可能になる。
モデルの学習やファインチューニングは、過去の技術になりつつあると思う。

ControlNetを「いらすとや」で学習する

先日試したControlNetの学習を「いらすとや」のデータセットで学習させてみた。

データセット

以前にStable Diffusionの追加学習を試したときに収集したいらすとやの22891枚の画像を使用した。
いらすとやの画像説明文に加えて、wd-v1-4-vit-taggerを使用して、確率が0.5以上のタグを付与した。

スケッチ画像は、データローダでOpenCV2のCannyを使用して動的に生成した。

ベースモデル

ベースモデルには、Stable Diffusion 1.5と、Waifu Diffusion 1.3の2パターンを使用した。

Stable Diffusionベースの結果

Stable Diffusion 1.5をベースモデルとして学習した結果を示す。

データセットにある画像

スケッチ

プロンプト:a cat
生成例

データセットにある画像のスケッチの場合、いらすとや風に着色できている。

データセットにない画像

スケッチ

プロンプト:a cat
生成例

書き込みが細かいスケッチの場合、違う雰囲気になる。
生成例の左上はそれなりに自然に着色できているが、それ以外は破綻している。
足の爪の線はいらすとやの特徴がでていそうである。

人物

スケッチ

プロンプト:a girl
生成例

口の描き方や、生成例の左下の目の描き方は少し特徴が表れているが、全体的に破綻が目立つ。
手のあたりの着色は完全に誤っている。これは、いらすとやに手の塗り方の例がないためと思われる。
データセットから離れた画像に対する着色は難しいようである。

損失

なお、14エポック学習した際の損失は以下の通りであった。

Waifu Diffusionベースの結果

Waifu Diffusion 1.3をベースモデルとして学習した結果を示す。

データセットにある画像

スケッチ

プロンプト:a cat
生成例

Stable Diffusionベースの場合と同様に、いらすとや風に着色できている。
生成例によっては頭と胴体がちぐはぐなところはある。

データセットにない画像

スケッチ

プロンプト:a cat
生成例

Stable Diffusionベースより破綻が少なくなっている。

人物

スケッチ

プロンプト:a girl
生成例

Stable Diffusionベースよりクオリティは上がっているように見える。
元がアニメ調のイラストなので、Waifu Diffusionの方がうまくいくようだ。

DeepBooruタグ

プロンプトをInterrogate DeepBooruで生成した場合も試してみた。

プロンプト:1girl, bangs, bare_shoulders, black_hair, blush, bookshelf, brown_eyes, brown_hair, curtains, frills, from_side, hair_ribbon, holding, long_hair, looking_at_viewer, red_ribbon, ribbon, sleeveless, smile, solo, two_side_up, upper_body

ところどころ破綻しているが、塗り方は上手くなっているように思える。

損失

なお、12エポック学習した際の損失は以下の通りであった。

まとめ

ControlNetをいらすとやのデータセットで学習させてみた。
結果、いらすとやのスケッチに対しては、いらすとや風に着色することができた。
いらすとや以外については、着色の特徴は表れているが、いらすとやの画風から離れるほど破綻が目立つようになった。

ベースにするモデルをStable Diffusionにした場合とWaifu Diffusionにした場合では、比較的Waifu Diffusionをベースにした方が質が高くなった。
これは、Waifu Diffusionがイラストを多く学習しており、いらすとやの画像により近い特性があるためと思われる。
ControlNetを学習する際は、元のモデルが着色したい画像に近い画像を生成できるモデルをベースにした方が良いと言える。

次は、イラストのデータセットでイラストの着色モデルを学習してみたい。

ControlNetの学習を試す

ControlNetは、Stable Diffusionの出力を、スケッチや深度、ポーズなどで制御する手法で、従来のテキストによる条件付けやImage2Imageでは難しかった制御が可能になる。

ControlNetを独自のデータセットで学習をしたいと考えており、まずは公式で用意されているチュートリアルを試した。

以下の内容は、公式のチュートリアルのままなので、手順は公式を参照した方が良い。

チュートリアル

公式のチュートリアルでは、色の付いた円を描いただけの画像を使って、スケッチに着色するControlNetモデルを学習する。


"prompt": "pale golden rod circle with old lace background"

同様の画像が5万セットある。
データセットHuggingfaceにある。

環境構築

NVIDIAのDockerコンテナを使用した。
docker run --gpus all --shm-size=32g -it nvcr.io/nvidia/pytorch:22.05-py3

environment.yamlに記載されたパッケージをインストールする。
バージョンの不整合を起こすパッケージを先にアンインストールした。

pip uninstall torch torchvision torchaudio torchtext Pillow
pip install torch==1.12.1+cu116 torchvision==0.13.1+cu116 torchaudio==0.12.1 --extra-index-url https://download.pytorch.org/whl/cu116
pip install torch==1.12.1 gradio==3.16.2 albumentations==1.3.0 opencv-contrib-python==4.3.0.36 imageio==2.9.0 imageio-ffmpeg==0.4.2 pytorch-lightning==1.5.0 omegaconf==2.1.1 test-tube streamlit==1.12.1 einops==0.3.0 transformers==4.19.2 webdataset==0.2.5 kornia==0.6 open_clip_torch==2.0.2 invisible-watermark streamlit-drawable-canvas==0.8.0 torchmetrics==0.6.0 timm==0.6.12 addict==2.4.0 yapf==0.32.0 prettytable==3.6.0 safetensors==0.2.7 basicsr==1.4.2 Pillow
pip uninstall tensorboard tb-nightly
pip install tensorboard

準備

Stable Diffusion 1.5のチェックポイントを元に初期チェックポイントを作成する。

python tool_add_control.py ./models/v1-5-pruned.ckpt ./models/control_sd15_ini.ckpt

4GPUで学習するため、pl.Trainerの引数をgpus=4に変更した。

trainer = pl.Trainer(gpus=4, precision=32, callbacks=[logger])

また、「if __name__ == '__main__':」がないと、データローダがエラーになるため、処理をmain関数に移動した。

訓練

訓練を開始する。

python tutorial_train.py

結果

訓練損失

2.4エポックほど学習した際の訓練損失は以下の通りとなった。

評価画像

200ステップごとに評価画像がimage_log/train/に生成される。
評価では、プロンプトとスケッチから画像を生成する。
訓練の過程で生成された画像は、以下のようになった。

訓練開始時

1エポック

2エポック

2.4エポック

訓練開始時は、Stable Diffusionの出力そのままになっている。
1エポック学習した時点で、ほぼ円を単色で塗った画像になっている。
2エポック学習した画像では、模様のようなものが出力されており、まだ十分に学習されていない。
2.4エポック学習した画像では、円と背景がほぼ単色で塗れているが、エッジがぼやけた個所が残っている。

学習時間

V100 4GPUで、バッチサイズ4で学習した場合、1エポック(3125step)に約1時間50分かかった。

まとめ

ControlNetの学習を公式のチュートリアルで試した。
円に色を塗るだけの単純なデータセットで、数エポックである程度学習できることが確認できた。
エッジがぼやけた個所が残ったため、どれくらいで鮮明になるか別途確認したい。

ControlNetの学習方法がわかったので、次は独自のデータセットで学習を試したい。

PaintsChainerをPyTorchで学習 その2

前回、PaintsChainerをPyTorchにポーティングして着色モデルの学習を行った。
その際、danbooru2017の512x512の画像をすべて使用したが、四コマ漫画のようなイラスト以外の画像も含んでいたため、学習の妨げになっていた可能性があるため、今回は、画像をフィルタをしてイラストに絞って学習した。
また、前回は、128x128の着色モデルの学習のみ試したが、512x512への超解像度モデルの学習も試した。

データセットのフィルタリング

danbooru2017の512x512の画像には、イラスト以外の4コマ漫画のような画像も含んでいる。
Stable Diffusionでは、CLIP aesthetic scoreで、画像の審美を採点してフィルタリングをしている。
Waifu Diffusionでは、danbooruのデータセットを、独自に構築したaestheticモデルでフィルタリングしている。
Waifu Diffusionと同じdanbooruのデータセットを使用しているため、Waifu Diffusionのaestheticモデルを使用した。

また、グレースケールは除外しているが、グレースケール以外の単色のイラストも含まれているため、画像のカラフルネスでもフィルタリングを行った。
カラフルネスの採点には、こちらのサイトのコードを使用した。
Computing image “colorfulness” with OpenCV and Python - PyImageSearch


Waifu Diffusionのaestheticモデルの採点0.1以上、カラフルネス10以上という条件でフィルタリングした結果、元のデータ数(288914)の約半分(138341)になった。

着色モデルの学習

フィルタリングしたデータセットで着色モデルを学習し直した。
フィルタリング前は、50エポック学習したので、倍の100エポックした。

100エポック学習した時点の損失は以下のようになった。

着色画像の例

スケッチ

前回のモデル

今回のモデル

エポックごとに着色の質が変わって安定しないが、最終エポックでは、淡い着色となった。
前回に比べると質が良くなったかは分からない。

超解像度モデルの学習

前回は超解像度モデルの学習は試さなかったが、今回は超解像度モデルの学習も行った。

13エポック学習した時点の損失は以下のようになった。

着色例

着色モデルの最終エポックが淡い着色になったため、超解像度モデルの結果も淡い着色になった。
顔と髪の着色は比較的自然な着色になっているが、手の色は白っぽくなってしまった(カラーヒントを与えることで半手動で改善はできるはずである)。

まとめ

danbooru2017データセットをカラフルなイラストにフィルタリングしてPyTorchにポーティングしたPaintsChainerの学習を試した。
また、超解像度モデルの学習も行った。
結果、淡い着色だが、部分的には比較的自然な着色ができるモデルが学習できた。

GANの学習は安定せず、エポックごとに着色の傾向が大きく変わる傾向があった。
ベストな着色のモデルを学習しようとした場合、複数回実験して、自然な着色ができた時点のモデルを選定する必要がある。

今回使用したデータセットは、アスペクト比が正方形でない場合、黒でパディングされているため学習に悪い影響を与えている可能性がある。
アスペクト比の影響を除くには、Novel AIで使われていたようなAspect Ratio Bucketingが有効と考える。
ただし、PaintsChainerのDiscriminatorは解像度に依存するモデルのため、出力層を全結合ではなくGlobal Average Poolingにするなど変更が必要になる。

イラストのデータセットの扱いに慣れてきたので、次は、拡散モデルの着色モデル の学習を試したい。

PaintsChainerをPyTorchで学習

Stable Diffusionが公開されてから、拡散モデルで自動着色したいと思っていて、自動着色についていろいろ調べていた。

最近、Style2Paints V5 Previewが発表されて、拡散モデルによる自動着色で高いクオリティの自動着色が実現できることが示された。

ControlNet

Style2Paints V5は、ControlNetという方法が使われており、つい先日、論文ソースが公開された。
線画の着色の学習済みモデルも公開されているが、アニメイラストの自動着色のモデルは、権利の関係で公開されていない。
また、公開されたモデルでは、元のイラストの線が少し書き換えられることがあり、生成画像の質は高いが着色用途には問題がある。
イラストの着色には、元の線を保持する特化したモデルが必要である。

従来の着色技術

拡散モデル以前は、GANによる手法が主流であったが、GANによる手法は以下のような問題があった。

  • 水彩画のようなにじみのある色になる
  • 色の鮮やかさが足りない
  • 色が線からはみ出す
  • 色の間違いがある
  • アーティファクトが表れる

PaintsChainerが最初期のモデルで、それ以降も改良手法が提案されている。

PaintsChainerの学習を試す

拡散モデルを試す前に、GANによる自動着色を試してみた。
PaintsChainer V1/V2は学習のソースコードも公開されており、試すことができる。
PaintsChainerはChainerで実装されているが、Chainerは既に開発が終了しているため、PyTorchにポーティングを行った。
GitHub - TadaoYamaoka/PaintsPyTorch: PaintsChainer training with PyTorch

PaintsChainerの学習

PaintsChainerの学習は、3段階に分かれている。

  1. カラー画像からスケッチ画像を予測するモデル(lnet)の学習
  2. GANによる128x128の画像の着色モデル
  3. UNetによる128x128の画像から512x512の画像への超解像度モデル
データセット

danbooru2017の512x512の画像を使用した。
グレースケールの画像も含まれるため、以下のような処理で事前に除外した。

    img = cv2.imread(path)
    b, g, r = cv2.split(img)
    if np.abs(b - g).mean() + np.abs(g - r).mean() + np.abs(r - b).mean() >= 100:
        files.append(path[len(dir):] + '\n')
スケッチ画像

スケッチ画像は、PaintsChainerでは、dilate(膨張)した画像と元画像の差分をとることで作成しているが、sketchKerasを使用して作成した。

縮小画像

lnetとGANモデルの学習には、128x128の画像が必要になるため、512x512画像をリサイズした画像を作成した。
その際、cv2.resizeのデフォルトパラメータで変換すると、スケッチの線が途切れるため、cv2.INTER_AREAを使用した。

lnetの学習

lnetは、GANのGeneratorが生成した画像をスケッチに変換して元のスケッチを再現できるかの損失関数のために使用される。
これがあることによって、生成画像に元のスケッチの線を残すことができる。
PaintsChainerでは、線の一致には強いペナルティが与えられている。

lnetは、以前は公式サイトで、学習済みモデルが配布されていたが、現在ダウンロードできなくなっているため、自分で学習した。
lnetは、学習用のコードがなかったため、自分で実装した。
PaintsPyTorch/train_lnet.py at main · TadaoYamaoka/PaintsPyTorch · GitHub

カラー画像とスケッチ画像のペアの平均絶対誤差(MAE)が最小になるように学習する。

GANによる着色モデル学習

128x128のカラー画像とスケッチ画像のペアから、GANにより着色モデルを学習する。
上記のlnetの箇所で説明した通り、通常のGANの損失に加えて、生成画像から元のスケッチが生成できるかも損失に加えられている。

PaintsChainerでは、訓練中の処理で画像のチャンネルを編集する処理があったが、実行が遅くなるためデータローダ側で処理するようにした。
PaintsPyTorch/train_128.py at main · TadaoYamaoka/PaintsPyTorch · GitHub

40エポックほど学習した時点の損失は以下のようになった。

着色画像の例

パーツの塗り分けは学習できているが、にじみが多く質は高くない。
これは比較的うまく塗れている例だが、書き込みが細かいとまったく着色ができていない。

生成例を確認していて気づいたが、元のデータセットには、四コマ漫画のようなイラスト以外の画像も含まれていたため、学習の妨げになっていそうである。

学習の途中で生成例を確認していると、色の間違いは多いがひとまず塗れていたものが、白っぽく塗るようになり、再び色が着くようになるという変化が見られて、GeneratorとDiscriminatorが競っている様子が観察できた。

超解像度モデル

超解像度モデルでは、512x512のスケッチ画像に、着色モデルで生成した128x128の画像を拡大して512x512にした画像をチャネル方向に連結したものを入力として、元のカラー画像を予測する。
GANは使用しておらず、単純なUNetのモデルになっている。

PaintsChainerでは、訓練中の処理で、画像の拡大を一旦CPUに転送してOpenCV2で拡大した後にGPUに戻す処理があったが、実行が遅くなるためTorchVisionを使用してGPU側で処理するようにした。
PaintsPyTorch/train_x2.py at main · TadaoYamaoka/PaintsPyTorch · GitHub

着色の質があまり良くない状態なので、超解像度モデルの学習はまだ試していない。

まとめ

GANによる自動着色を、PaintsChainerのソースをPyTorchにポーティングして試してみた。
PaintsChainerが元の線を残すために、通常のGANにない損失を加えていることなどがわかり、理解を深めることができた。
また、danbooruデータセットをそのまま使うと、イラスト以外の画像が含まれており、学習の妨げになりそうなことが分かった。
WaifuDiffusionでも行われているようにCLIP Aesthetic scoreによるフィルタリングは必要そうである。
データセットをクリーニングしたもので質がどう変わるか試してみたい。

続き
PaintsChainerをPyTorchで学習 その2 - TadaoYamaokaの開発日記

【Bing】Bingチャットにマインドマップを作らせる

小ネタです。
前回、ChatGPTにマインドマップを作らせてみたが、Bingチャットでも試してみた。

プロンプト:「AIの技術」に関するマインドマップを作って

回答:

ちゃんとツリーになって返ってきた。
前回ChatGPTで試した時は、箇条書きだったので、こっちの方が見やすい。

まとめ

Bingチャットでマインドマップを作らせてみたところ、ツリーにして回答が返ってきた。
前回ChatGPTで試した時は箇条書きだったので、より見やすい。
Bingチャットは検索とも統合されているので、最新情報も反映されるので実用になりそうである。

【ChatGPT】ChatGPTにマインドマップを作らせる

ChatGPTでマインドマップを作れるか試してみた。

プロンプト:「AIビジネスに関してマインドマップを作って」
回答:

はい、AIビジネスに関連するマインドマップを作成することができます。以下が一例です:

I. AI技術とその概要
A. 機械学習
B. 自然言語処理
C. 画像認識
D. ロボット技術
E. 深層学習

II. AIビジネスのセグメンテーション
A. ヘルスケア
B. 金融
C. マーケティング
D. ロボット製造
E. 自動運転

III. AIビジネスのメリット
A. コスト削減
B. 効率の向上
C. 顧客体験の向上
D. 新サービスの提供
E. 情報収集の効率化

IV. AIビジネスの課題
A. データのプライバシーとセキュリティ
B. AIアルゴリズムのバイアス
C. 技術力不足と人材育成
D. 法的制限
E. 技術の信頼性と安定性

V. AIビジネス戦略
A. 技術採用戦略
B. データ管理戦略
C. ビジネスプロセスの変革
D. パートナーシップと提携
E. 人材育成戦略

このマインドマップは、AI技術、ビジネスセグメンテーション、メリット、課題、戦略などに焦点を当てたものです。希望する情報が足りない場合は、教えてください。

図になっていないけど、箇条書きでちゃんとした内容が返っている。

さらに細分化ためするに、第一階層の項目に関してマインドマップを作らせてみた。

プロンプト:「AI技術とその概要に関してマインドマップを作って」
回答:

はい、AI技術とその概要に関連するマインドマップを作成することができます。以下が一例です:

I. 機械学習
A. 監督学習
1. 回帰分析
2. 分類
B. 非監督学習
1. クラスタリング
2. 次元削減
C. 強化学習

II. 自然言語処理
A. 文書分類
B. 意味解析
C. 言語生成
D. ディープラーニング

III. 画像認識
A. オブジェクト認識
B. 顔認識
C. 文字認識
D. 画像生成

IV. ロボット技術
A. ロボットアーム
B. 移動ロボット
C. 空間マッピング
D. 自律移動

V. 深層学習
A. Convolutional Neural Networks (ConvNets/CNN)
B. Recurrent Neural Networks (RNN)
C. Generative Adversarial Networks (GAN)
D. Autoencoders (AE)

このマインドマップは、機械学習、自然言語処理、画像認識、ロボット技術、深層学習などの主要なAI技術に焦点を当てたものです。希望する情報が足りない場合は、教えてください。

前の回答を受けて、さらに細分化されている。

これを続けていけば、詳細なマインドマップが出来上がりそうである。
欲を言えば図にして欲しい。

まとめ

ChatGPTでマインドマップを作ることができるか試してみた。
「〇〇に関してマインドマップを作って」というプロンプトで、2階層の箇条書きが返ってくることが分かった。
さらに細分化するには、「"第一階層の項目"に関してマインドマップを作って」とすればよい。
アイディアに詰まったときに使えそうである。