SAI-SHIKI | 自然言語処理AIに特化したコンサルティングと開発 https://www.sai-shiki.com Thu, 01 Jun 2023 00:51:36 +0000 ja hourly 1 https://wordpress.org/?v=7.0.2 https://www.sai-shiki.com/wp-content/uploads/2023/05/cropped-SAI-SHIKI_A1-32x32.png SAI-SHIKI | 自然言語処理AIに特化したコンサルティングと開発 https://www.sai-shiki.com 32 32 ChatGPTで品質の高い文章を作成するには何が必要?ビジネスにおける具体例とともに解説します https://www.sai-shiki.com/well-designed-text-generation-ai/ Sat, 25 Feb 2023 00:00:00 +0000 https://www.sai-shiki.com/?p=1714 今回は2023年になってから数多くのお問い合わせを頂いている、文章生成AIの構築に関わるお話をいたします。 扱う題材は、“キャリア採用(転職活動)における自己PR生成” としました。例えばこれを転...

The post ChatGPTで品質の高い文章を作成するには何が必要?ビジネスにおける具体例とともに解説します first appeared on SAI-SHIKI | 自然言語処理AIに特化したコンサルティングと開発.

]]>
今回は2023年になってから数多くのお問い合わせを頂いている、
文章生成AIの構築に関わるお話をいたします。

扱う題材は、“キャリア採用(転職活動)における自己PR生成” としました。
例えばこれを転職系の事業として扱う場合、転職したいと思っている人材側のスキルセットを入力することで、自動で自己PR文章を作成するというサービスになることが想定されます。

上記テーマで、文章生成AIでビジネスを行う場合にどのようなアプローチが必要になるのかイメージを掴んでいただければ幸いです。
特に後半では、将来的にどのような要因によって品質の差が生まれるのかについても述べています。
また、以下の用語紹介を見ていただければわかりますが、AIについて詳しくないよという方向けのチュートリアル記事でもあります。

【用語紹介】
・プロンプト:AIに”こういう文章を作ってください”とお願いする指示文章
・GPT:   文章生成に特化したAI、日本語だけでなく他言語やプログラムのコードなどを出力することもできるがこの記事では日本語を出力
・ChatGPT: 最近流行りの賢いGPT、この記事の範囲ではGPT=ChatGPTと思っていただいても差し支えないです


プロンプトデザイン(プロンプティング)とは

最初のプロンプト

まず、以下の例から始めていきたいと思います。
GPTを使用して文章を生成する場合には、プロンプトと呼ばれる指示をAIに与える必要があります。
以下の例では、1つ目が我々が用意したプロンプトで、2つ目が生成された自己PR文章になります。
(生成された自己PR文章は長文なため、読みやすさのために一部省略します。)

あなたはIT企業で働きたいプログラマーです。以下に自己PRを作成してください
私の強みは、問題解決能力やコーディングスキルにあります。また、協調性やコミュニケーション能力も高いです。これらのスキルを活かし、チームでの開発やコミュニケーションを円滑に行うことができます。

私は常に新しい技術やトレンドに興味を持ち、自己学習に励んでいます。また、プロジェクトにおいても、積極的に新しい技術を導入し、より高度なソリューションを提供できるように努めています。

さらに、私はユーザーのニーズに合わせた柔軟なソリューションを提供することに強い関心を持っています。ユーザーフレンドリーなアプリケーションやシステムの開発を通じて、ユーザー体験を向上させることを目指しています。

自己RPではそれなりに十分アピールはできていますし、誰でも使えるようなフレーズで応用性もありそうです。
その一方で、なんとまぁ、ありがちな感じで物足りなさを感じますね。
採用されるために興味を持ってもらえるかどうかで言えば、あまり質が良いものとは言えません。

質を上げるためには、どうすればいいでしょうか?
今回はペルソナをより詳細化するアプローチを採用してみたいと思います。
つまりは、もっと詳細にどのような人物なのかプロンプトで指示したいと思います。
また、転職先で希望する職種についても合わせて情報を与えてみましょう。

改善したプロンプト

あなたはIT企業で働きたいプログラマーです。新しい職場ではReactを使用してフロントエンドの開発をしたいと思っています。また、あなたはPythonを使用したプロダクトを3年間開発してきた経験があります。以下に自己PRを作成してください
私は、常に新しい技術に興味を持ち、最新のWeb開発技術にも精通していることを重視しています。フロントエンドの開発については、Reactを中心に学習を進めています。Reactは、コンポーネント指向のアプローチや仮想DOMを使用することで、スピーディーで動的なWebアプリケーションの開発を可能にしてくれます。私は、Reactを使用して、よりモダンで効率的なWebアプリケーションを開発するために献身的に学習しています。

また、Pythonを使用したプロダクト開発にも経験があります。Pythonに関する深い知識と経験を持っていることで、フロントエンドからバックエンドまでの技術についても熟知しており、フルスタックでの開発が可能です。Pythonを使用して、Webアプリケーションの開発やAPIの設計・実装などを行ってきました。

追加のペルソナとして、プロンプトではPythonの使用歴を3年と設定しました。
これによってバックエンドの経験があることを生かして、フルスタックな開発ができることをアピールしていますね。

一つ目に生成した自己PRと比べてグッと人物像の解像度が上がりましたし、キャリア採用により適した形になってきました。

次は試しに、バックグラウンドが異なるペルソナで自己PRを生成してみましょう。
例えば以下のように半導体設計者からフロントエンジニアへ思い切って転身したいケースを取り上げて見ましょう。

あなたはIT企業で働きたいプログラマーです。新しい職場ではReactを使用してフロントエンドの開発をしたいと思っています。また、あなたは半導体設計を10年間行ってきました。以下に自己PRを作成してください
私の半導体設計の経験は、技術的な問題に対する解決策の見つけ方や、細かいディテールに注意を払うことができる能力を身につけました。これらのスキルは、プログラミングにも非常に役立つと考えています。例えば、Reactのようなフロントエンド開発では、細かいディテールに注意を払う必要があります。また、半導体設計のような複雑なシステムを扱う経験は、プログラムの設計やアーキテクチャの理解にも役立ちます。

私は、フロントエンドの開発においてReactを使用することで、スピーディーで効率的なWebアプリケーションの構築が可能になると考えています。これにより、ユーザーエクスペリエンスの向上やビジネス上のメリットを提供することができます。

うーん…頑張って作った感があり、やはりどこか無理を感じさせる文章になっています。細かいディテールへの注意力を強調されてもなかなか響かなく、やはりキャリアにギャップがありすぎて転職は難しいのでしょうか?

さて、ここで魔法のコトバを一つ紹介します。

“ステップバイステップ” です!

もっと改善したプロンプト

以下が使用例となります。

あなたはIT企業で働きたいプログラマーです。新しい職場ではReactを使用してフロントエンドの開発をしたいと思っています。また、あなたは半導体設計を10年間行ってきました。この経験を活かしながらステップバイステップにメリットを挙げながら、以下に自己PRを作成してください
Reactは、現代のWebアプリケーションに欠かせない人気のあるJavaScriptフレームワークです。Reactを使うことで、高品質で使いやすいWebアプリケーションを開発できます。私はこのフレームワークを熟知し、熟練したReact開発者としてのスキルを磨くことを目指しています。

また、私は半導体設計の経験をフロントエンド開発に生かせると考えています。私は、論理回路設計の概念を理解しているため、Webアプリケーションの設計においても、データのフローと処理の最適化に重点を置くことができます。これにより、Webアプリケーションのパフォーマンスを最適化し、高速かつスムーズなユーザーエクスペリエンスを提供することができます。


2段落目が面白く、「論理回路設計の概念を理解しているためWebアプリのパフォーマンスを最適化し、スムーズなUXを提供することができる」という記載が出てきました。

ここで注目していただきたいのが、我々が行ったことはプロンプトに“ステップバイステップにメリットを挙げながら”という記述を追加しただけです。
たった一言この表現をいれるだけで、非常に説得力のある自己PR文章が生成できるようになりました。

このようにプロンプトを改善することで生成される文章の品質を向上させる手法を、
プロンプトデザイン(通称 プロンプティング) と呼びます。
上記のように指示の方法をちょっと変更するだけで生成される文章が改善される上に、プロンプトは私達が使用する自然言語(日本語)で柔軟に指示できるため、あらゆる可能性を秘めています。

過去に流行った自然言語処理AIと比較してみましょう、例えばBERTなどが挙げられます。
こういった事前学習モデルでは最適化させたいドメインごとに1.データを沢山用意して、2.GPU(行列計算ユニット)を用意して、3. ファインチューニング(モデルの追加学習)を行うことで品質を高めてきました。
一方で、最近流行りのChatGPTなどでは1.プロンプトデザイン、だけで最適化が十分なケースが出てきます。
特に数十万円以上するGPUが必要ないことはお財布に優しい上に過去のAI開発のノウハウはあまり必要がないため、多数の人があれやこれやと試してその知見を共有しあっていることがChatGPTが話題になっている要因の一つであるといえます。

以上がプロンプトデザインについてのご紹介でした。
プロンプトデザインを作り込んでいくことで、文章生成AIの品質を高められることが伝わったかと思います。
読者の皆様におかれましてはご満足いただけましたでしょうか?

 

 

… 満足してしまいましたか?


実は先程作成した自己PR文章、まだまだ改善できる可能性があります!

ファインチューニング(プロンプトチューニング)

我々が先程作成した自己PRですが、本当に好印象なのでしょうか?我々素人が勝手に判断してそんな気がしているだけではないでしょうか?
また、社風や業界によって好まれやすい自己PRは変わらないと、本当に断言できるのでしょうか?
特に、製造業などの多人数が関わり合うため保守的・協調的であることが求められやすい業界と、ベンチャー企業のように強い主体性が求められる企業では、必要とされる人材の傾向がガラッと変わることが想定されます。

残念ながらこの場で該当するデータを保持していないため上記の仮説を検証することは叶いませんが、例えば特定の企業に対して複数の自己PR文章を活用したときの書類審査の合否結果を教師データとして扱うことで、企業ごとにウケの良い自己PRを作成する、ということが可能になるかもしれません。

上記のケースでは従来のAI開発で行ってきたようなファインチューニングが必要になります。
このファインチューニングでは”Xという企業”に対して”{突破, 不採用}”の情報を埋め込んだプロンプトを与えたときに、”その自己PR文章”が生成されるように学習を行います。(実際には先述した例のスキルセットや経歴などの情報も合わせて入力する必要があります。
これによって”Xという企業”で”突破”というプロンプトを与えたときに、その企業に対してウケのいい”自己PR文章”が生成できるという理屈になります。

また上記に加えて、企業Xという表現を特定の法人名で表すだけでなく、業界や法人規模、所在地、IT企業であれば技術スタックなどの変数に落とし込むことによっても、より柔軟に学習していくことができそうです。

上記で示したようにファインチューニングを行うことで、プロンプトデザインよりも品質の高い文章生成AIが構築できる可能性がでてきます。
また、特にプロンプトデザインで実現できる範囲では、最初のうちは先行者利益があるかもしれませんが、時間が経つとコモディティ化しやすい(レッドオーシャンになりやすい)面があります
従って、事業化を目指す企業においては、競争に晒されやすい領域であることを理解しつつ、どのように差別化を図っていくのかが求められます

とはいえ、まだまだ開拓されたばかりの領域ですので、まずは自社事業での応用可能性について見定めていければ十分でしょう。

さいごに

本稿では転職活用における自己PR文章の生成について取り上げ、品質の高い文章生成AIについて必要なアプローチをご紹介いたしました。
特に、効果的なアプローチとして順番に、

  1. ファインチューニング
  2. 情報の多いプロンプト
  3. 情報の少ないプロンプト

という関係があることを示しました。
また、長期に渡って本当に品質の良い文章生成AIを構築するためには、以下の2要素が必要であることを述べました。

  1. 関連分野の意義のあるデータを集める
  2. 1.のデータを活用してファインチューニングを行う


特にファインチューニングについては従来のAI開発のような学習処理を行う必要があり、専門性の高いスキルとノウハウが問われます。

自然言語処理を専門とするSAI-SHIKIでは、文章生成AIについても開発を承っております。
また、自然言語処理に関する総合的なコンサルティングも提供してございますので、自社事業の課題と解決策がまだピンときていない段階からご相談いただくことができます。
自社の事業でうまく文章生成AIを活用できないか模索している方は、以下の「お問い合わせ」からご相談のご予約をいただければ幸いです(弊社のご紹介資料の請求もこちらから行っていただけます)。

The post ChatGPTで品質の高い文章を作成するには何が必要?ビジネスにおける具体例とともに解説します first appeared on SAI-SHIKI | 自然言語処理AIに特化したコンサルティングと開発.

]]>
医療分野に特化した大規模学習済みモデルGatorTronの使い方(準備編) https://www.sai-shiki.com/gatortron/ Sun, 22 Jan 2023 04:30:00 +0000 https://www.sai-shiki.com/?p=1070 こんにちは、代表の藤倉です。本記事では医療分野に特化したLLM(大規模言語モデル)GatorTronの導入について解説していきます。日本語資料は当然として英語資料も少ないのはキツかった。執筆時の現在だとGatorTron...

The post 医療分野に特化した大規模学習済みモデルGatorTronの使い方(準備編) first appeared on SAI-SHIKI | 自然言語処理AIに特化したコンサルティングと開発.

]]>
こんにちは、代表の藤倉です。
本記事では医療分野に特化したLLM(大規模言語モデル)GatorTronの導入について解説していきます。
日本語資料は当然として英語資料も少ないのはキツかった。
執筆時の現在だとGatorTronのモデルが置いてあるだけで公式のチュートリアルは一切ありません。
この記事があることで多少は救われる人がいると思うので、落とし穴の回避策も含めて本記事にまとめていきたいと思います。


事前準備

方針

GatorTronは同じくNVIDIAが提供しているフレームワーク(NeMo)用の.nemo形式とPyTrochモデルのチェックアウト(.pt)形式の2つで公開されています。

まずはNeMo版についてですが、肝心のNeMo上で読み込みができずGithub上に報告があがってはいますが、1ヶ月以上もcloseしない状況です(https://github.com/NVIDIA/NeMo/issues/5654)。
認知度の高いOSSだと上記のような状況自体はなんら珍しいものではないですが、それに対してユーザ側でなんとかしようというトライアンドエラーに関する記事がほとんどなく、コミュニティがまだ小さい印象を受けました。
というかNeMoに関するユーザの記事もめちゃくちゃ少ないのでトライアンドエラーの難易度が高い。

従って、本記事ではGatorTronのNeMo版の使用は避け、PyTorchで扱えるようにしています。
※ちなみにNeMo Megatronのエンタープライズ版なるものがあるようで、こちらであれば公式のNVIDIAからサポートを受けながら開発できるものだと思われます(https://docs.nvidia.com/deeplearning/nemo/user-guide/docs/en/stable/nlp/nemo_megatron/intro.html)。


また、GatorTronは厳密にはMegatronというLLMが前身にあり、それを医療分野にファインチューニングしたものとなります(https://huggingface.co/nvidia/megatron-bert-cased-345m)。
後述しますが、実際のGatorTronのファイル名もMegatronになっているため、ここで混乱しないように意識しておくことが大事です。

GatorTronのダウンロード

以下のNVIDIAのページからモデルをダウンロードします。

https://catalog.ngc.nvidia.com/orgs/nvidia/teams/clara/models/gatortron_og

右上のDownloadのボタンをクリックしWGETを選択します。
するとクリップボードにwgetを使ったスクリプトがコピーされますので、導入したいマシンのコンソール上に貼り付けてダウンロードを実行します。

データ容量が5GBとなかなか重たいです、早速ですがコーヒーでも淹れて待ちましょう。
待ってる間に50杯は飲めると思います。

ダウンロード前のコンテンツリストかダウンロード後に中身を見ればわかりますが、GatorTronというモデル名ではなくMegatronBERTというモデル名でチェックポイントが入っています。

その他の準備も合わせて並行して進めてしまいましょう。

Megatronを使えるようにする

次にMegatronを使用できるようにセッティングしていきます。

基本的にはこちらの案内(https://huggingface.co/nvidia/megatron-bert-cased-345m)に従ってMegatronを使用できるようにします。

まずは環境変数を設定していきます。

export MYDIR=$HOME

公式の例では$HOMEを指定していますが、$HOMEは基本的に汚したくないためtmpディレクトリなどを作成してそこに設定すると良いと思います。

次にmegatronをダウンロードしていきます。

mkdir -p $MYDIR/nvidia/megatron-bert-cased-345m
wget --content-disposition https://api.ngc.nvidia.com/v2/models/nvidia/megatron_bert_345m/versions/v0.1_cased/zip -O $MYDIR/nvidia/megatron-bert-cased-345m/checkpoint.zip
python3 $MYDIR/transformers/src/transformers/models/megatron_bert/convert_megatron_bert_checkpoint.py $MYDIR/nvidia/megatron-bert-cased-345m/checkpoint.zip

上記の2行目でダウンロードを行い、3行目で圧縮ファイルからファイルの作成を行っています。
ここまでのステップが完了すると、config.jsonpytorch_model.binが生成されています。


GatorTronを構築する

GatorTronにはPyTorchのチェックアウト(MegatronBERT.pt)のみがあり、Megatronにはconfig.jsonとmegatronのバイナリ(pytorch_model.bin)があります。
つまり、モデルアーキテクチャとしてはMegatronを読み込み、重みパラメータはMegatronBERT.ptを指定します。
これを表現しようとすると以下のコードになります。

import os
import torch

gatortron_path = '/workspace/model/gatortron/MegatronBERT.pt'
state_dict = torch.load(gatortron_path)["model"]

megatron_dir = '/workspace/gatortron/nvidia/megatron-bert-cased-345m' # docker上のpathにする
model = MegatronBertModel.from_pretrained(megatron_dir, state_dict=state_dict)
model

上記の図のようにモデルアーキテクチャが表示されたら読み込み成功です。

筆者の場合はDocker上にJupyterNotebookを展開しているため、gatortron_pathはDocker内でのpathになります。
Dockerを使わない方はダウンロードしてきたmegatron-bert-cased-345mのpathをそのまま指定すると良いでしょう。
Dockerを使う方場合はCOPYで移しておくかdocker run時にボリュームのマウンティングを行う必要があります。

導入については以上となります、お疲れさまでした

使い方についてはまた次の記事で紹介したいと思います。
最後にいつもので締めさせていただきます。

サイシキでは医療分野のような専門性の高い分野における強いAIの開発にも対応してございます。
自然言語処理について開発やサポートが必要になりましたら弊社までご相談いただければ幸いです。
資料請求も以下からお問い合わせいただけます。

お問い合わせ: https://www.sai-shiki.com/contact/
メールアドレス: office@sai-shiki.com

The post 医療分野に特化した大規模学習済みモデルGatorTronの使い方(準備編) first appeared on SAI-SHIKI | 自然言語処理AIに特化したコンサルティングと開発.

]]>
OpenAIのモデルとgpt_index(llama_index)を使ってビジネスに関する質問応答botを構築 https://www.sai-shiki.com/openai%e3%81%ae%e3%83%a2%e3%83%87%e3%83%ab%e3%81%a8gpt_index%e3%82%92%e4%bd%bf%e3%81%a3%e3%81%a6%e3%83%93%e3%82%b8%e3%83%8d%e3%82%b9%e3%81%ab%e9%96%a2%e3%81%99%e3%82%8b%e8%b3%aa%e5%95%8f%e5%bf%9c/ Sun, 15 Jan 2023 01:56:57 +0000 https://www.sai-shiki.com/?p=742 サイシキ代表の藤倉です久々になってしまいましたが、弊社でも優先的に取り組んでいきたい事例が出てきましたので、簡単な内容ではありますが記事にまとめていきたいと思います。 ご存知のようにOpenAIがChatGPTを公開して...

The post OpenAIのモデルとgpt_index(llama_index)を使ってビジネスに関する質問応答botを構築 first appeared on SAI-SHIKI | 自然言語処理AIに特化したコンサルティングと開発.

]]>

サイシキ代表の藤倉です
久々になってしまいましたが、弊社でも優先的に取り組んでいきたい事例が出てきましたので、簡単な内容ではありますが記事にまとめていきたいと思います。

ご存知のようにOpenAIがChatGPTを公開してから、(いくらか問題は残るものの)その発言の人間らしさや情報構築の精度の高さに皆が驚かされている昨今です。
今回ご紹介するOpenAIが提供するdavinci-003はそのChatGPTの前身とも言われているモデルで、このモデルから得られるembeddingでQAを行うbotを作成したいと思います。
残念ながらChatGPTは執筆時の現在はAPIが公開されていないためdavinci-003を使用していきますが、十分に賢いものになっています。

この記事では、ほぼ公式のチュートリアルを手元のデータで再現したものになりますが、その方法についてご紹介して、最後に簡単な考察とビジネスシーンへの展望について記載します。
(チュートリアルに関してはN番煎じの内容にはなりますが、弊社が提携している早大の研究室の新規学生の方に向けた資料の一部として活用するため、こちらにも記載を残してみたいと思います)

用語紹介(ふんわりめ)
・ChatGPT:強化学習を使用してGPTをより会話に適した形に調整したモデル
・GPT Index(この記事でコードないしはリポジトリを指す場合はgpt_index):LLMなどで作成されたembeddingを使いやすくするツール
・LLM(Large Language Model):大量のパラメータを持つモデルで大規模データを学習したモデル。この記事の文脈ではdavinci-003やChatGPTが該当
bot:対話ができるシステム。従来のQAでは回答は対象内の文字スパンだけを返していたが、davinci-003では応答文章の自動生成ができるためこのように呼称


事前準備

※執筆時現在は無料期間の設定がありますが、有料の操作が含まれるためご注意ください

OpenAIのSecretKeyを取得する

※無償化サービスが終わったタイミングでクレジットカードの登録が必要になる可能性がありますが、執筆時にはカード情報の登録も必要ありませんでした

まずは次のリンク先からOpenAIのアカウントを作成してログインを行ってください。
https://beta.openai.com/signup/

その後右上からView API Keysをクリックし、左手側のAPI Keysを開きます。
Create New Secret Keyをクリックすると、無作為なパスワードが表示されますので、これをコピーして控えておきます。
※一度この表示を消すと2度と表示されないため、紛失した場合は新規のSecretKeyの発行が必要になります

gpt_indexの準備

以下のリンク先がgpt_indexのリポジトリとなります。
https://github.com/jerryjliu/gpt_index

インストールはpipで以下のように指定します。
pip install gpt-index

ちなみに私の場合はDockerを使用して環境を閉じ込めているので以下のようにバージョンを固定しています(0.2.3は執筆時の最新版)。
RUN python3.8 -m pip install gpt-index==0.2.3

余談ですが今後もライブラリの大幅なアップデート(仕様変更)が見込まれますので、ビジネス用途の場合は再現性は確保したほうが得策だと思われます。

デモデータの準備とコーディング

社内のSandbox環境のJupyterNotebookを使用しているため、後述のスクショはセルごとの結果が表示されます。
もちろん通常のPython(.py)で試していただいても同様の結果になります。

使用するデータ

弊社のトップページの文章で試してみました。
https://www.sai-shiki.com/

すべては掲載しませんが上記のようなページの文章部分をコピペして、手作業で以下のようにexample.txtとしてまとめました(33行ほど)。

依存ライブラリのimport〜対象の抽出まで

import os
from gpt_index import GPTSimpleVectorIndex, SimpleDirectoryReader

os.environ["OPENAI_API_KEY"] = "ここにOpenAIのSecretKeyを記載"

data_dir = "../../dataset/sandbox/gpt_index/" # 実際に.txtをおいているディレクトリを指定
documents = SimpleDirectoryReader(data_dir).load_data()

※上記例ではわかりやすさのためにコード上にSecretKeyを記載していますが、この状態のままgitで管理やGithubへのアップロードなどはしないように注意してください。

筆者の環境はDockerですので、docker run時に--env-file ./.env.txtのオプションを追加しています。
.env.txtの中身は以下のようになっています。

OPENAI_API_KEY=<SECRET KEY>

あとは.env.txtを.gitignoreに記載して管理しないようにしましょう。

SimpleDirectoryReader(data_dir).load_data()で指定したディレクトリ以下にあるファイルを探索し、次に行うindex作成の対象とします。

インデックスの作成

index = GPTSimpleVectorIndex(documents)

いくつか方法はありますが、今回は一番シンプルなGPTSimpleVectorIndex()を使用します。
内部でOpenAIのAPIを呼び出すため、この処理から課金対象となります(執筆時は筆者環境では無料範囲内でした)。

筆者はまだ試せていませんが、Pineconeなどのベクトルデータベースなどを使用すると本番環境などで扱いやすそうですね。
ひとまずは以下のようにローカルストレージに作成したindexを保存します。

 index.save_to_disk(data_dir + 'index.json')

次回からは以下のようにindexをそのままロードするだけです。
同じデータを何度も計算する必要がないため、地球とお財布に優しいですね。

index = GPTSimpleVectorIndex.load_from_disk(data_dir+'index.json')

ここまでの作業で下準備となるindexの作成が完了しました。
さて、ここでindexという変数に埋め込み表現が含まれているため、この文脈に対してquery(質問)を実際に投げて行きたいと思います。

デモ結果

Q:会社名は?
A:会社名は不明です。

Q:どんなサービスを手掛けていますか?
A:当社では、自然言語処理AIからWebシステム制作まで一貫してサポートを行っています。プロジェクトの策定、AIシステムの開発・運用、Webシステムの開発・運用、文書を精査するAI、チャットボット、検索システム、コンサルティング、データ分析、Webシステムなどを手掛けています。

Q:どんなサポートがありますか?
A:当社では、自然言語処理AIからWebシステム制作まで一貫してサポートを提供しています。プロジェクトの策定、AIシステムの開発・運用、Webシステムの開発・運用、文書を精査するAI、チャットボット、検索システム、コンサルティング、データ分析、Webシステムなどをサポートしています。

考察

最初の会社名を問う質問についてですが、会社情報に関しては私がうっかりexmaple.txtに含めていませんでした。
その一方で、しっかりと見つからなかった旨を報告できている点はかなり賢いです。

2, 3点目の質問について、内容が適切なだけではなく構築された文章までしっかりとしています。davinci-003の内部で要約に親しい処理が発生し、必要な情報が残っているものと思われます。

webのリソースを使用してLLMの学習を行っている関係か、今回のようなWebコンテンツ(もしくは類するもの)に対してはかなり良い結果が出せるのかもしれません。

今後の展望

読者の皆様の気になる点は以下になるでしょうか。

  • ビジネスでどのように使えそうか
  • 既存ビジネスへの転用(ファインチューニング)

ビジネスでどのように使えそうか

例えば今回は企業情報について抽出を行いましたが、これをそのまま拡張する場合はより賢いスクレイピングを行うことができます。

例えば、筆者は学生の頃にファッション業界で複数の契約先企業のアパレルグッズに関する情報をスクレイピングする業務を行ったことがありますが、HTML要素で指定しなくとも自然言語でqueryを出すだけで簡単に、そして柔軟に情報を抽出することができるようになりそうです。

昔)クラス名がpriceとdiscount-priceの要素を引っ張ってきて、priceが打ち消されている場合はdiscount priceを優先して取得して…よしA社終わった!B社は…あれdiscount-priceじゃなくてsales-priceか…企業毎にスクリプト分けておかないとなぁ…

上記の例が今ではqueryで「今の値段は?」と聞くだけです。企業毎にスクリプトを分ける必要もありません。

情報をスクレイピングして自社DBに保管して情報を売りにするサービスやお問い合わせ対応などのQAに関するサービスは状況が一転しそうですね。

新規ビジネスへの活用については本当にアイデア次第でいくらでも可能性があるものと思います。
このあたりについては別記事にまとめたいと思います。

既存ビジネスへの転用(ファインチューニング)

業界ごとに特有の問題そして表現方法があるため、従来のAI開発では基盤モデルに対してファインチューニングを行ってその上で専用のソリューションを提供することが一般的でした。
(実際に弊社では法曹系と医療系のパートナー企業様がおりますが、効果的なアプローチが全く異なっています)

davinci-003についてOpenAIのサービス上にはファインチューニングについて記載があり、こちらを利用すると従来のように業界特有の表現に最適化していくことができるかもしれません。
https://openai.com/api/pricing/#faq-fine-tuning-pricing-calculation

またファインチューニング以外のアプローチですが、単純にindexにその業界に関連するテキスト(例えば法律なら判例、医療ならカルテなど)を含めるだけでも精度が向上する可能性があります。
上記はまだ仮説に過ぎないため実際に着手して数値で確認していきたいところです。

さいごに

本記事ではOpenAIの提供するdavinci-003とQAなどのベクトル操作と管理を簡単にしてくれるgpt_indexを使用してQAボットの作成を行いました。
弊社では新手法や旧来手法を問わず、pros/consを提示しながら課題に応じて最適なサービスをご提案してございます。
自然言語処理についてサポートが必要になりましたら弊社までご相談いただければ幸いです。

お問い合わせ: https://www.sai-shiki.com/contact/
メールアドレス: office@sai-shiki.com

The post OpenAIのモデルとgpt_index(llama_index)を使ってビジネスに関する質問応答botを構築 first appeared on SAI-SHIKI | 自然言語処理AIに特化したコンサルティングと開発.

]]>
教師ラベルの間違えを効率的に修正する魔法の方法Confident Learningとその実装cleanlab https://www.sai-shiki.com/confident-learning/ Fri, 27 Nov 2020 04:55:00 +0000 https://www.sai-shiki.com/?p=389 注目すべき理由 教師ラベルには間違えがよく含まれる 教師ラベルが間違っていると、どんな賢いアルゴリズムを用いても精度を挙げることが困難となります。間違った教師ラベルが振られてしまうことは以下の理由からよくあります。 知識...

The post 教師ラベルの間違えを効率的に修正する魔法の方法Confident Learningとその実装cleanlab first appeared on SAI-SHIKI | 自然言語処理AIに特化したコンサルティングと開発.

]]>
注目すべき理由

教師ラベルには間違えがよく含まれる

教師ラベルが間違っていると、どんな賢いアルゴリズムを用いても精度を挙げることが困難となります。
間違った教師ラベルが振られてしまうことは以下の理由からよくあります。

  1. 知識不足、単純な繰り返し作業によるヒューマンエラー
  2. 昔は検知の対象ではなかったが、新規クラスとして対応しなければいけない

原理上、人の手が加わる限りは1.から逃れることはかなり困難です。
裏を返せば教師ラベルの品質が保証しきれる範囲では学習データが足りていないことがほとんどです。
この場合は、そもそもルールベースで十分なタスクか、精度が上がりきっていないケースに当てはまります。

2.についても、ユーザの要望による機能追加等でサービスのユーザが増えるほどに顕在化してくる問題です。

50万円〜300万円ほどのプロジェクト費用が浮くかも!?

今までであれば数千〜数十万件のすべてのデータを再確認しながらラベルを修正する必要がありますが、こちらのConfident Learningでは優先度をつけながら簡単に修正すべき候補が見つけられます。
一般的に、過去データに対するクラスの修正だけで2週間〜数ヶ月かかるものが数日まで削減できるため、プロジェクト予算を先述した価格まで低減することができます。
大きくなっているプロジェクトほど恩恵が大きくなりますが、AIの使用感は多数のユーザに使われてから段々と明確になるため、この手法にはAI開発のプロジェクトに対して大きな影響力があると言えます

デモンストレーション

公式で配布されているデモに手を加えたものを以下に掲載していきます( https://github.com/cgnorthcutt/cleanlab/blob/master/examples/iris_simple_example.ipynb )。
最初に必要なライブラリを読み込みます。

import numpy as np
from sklearn.model_selection import train_test_split
from sklearn import datasets
from sklearn.metrics import accuracy_score
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_predict
from cleanlab.classification import LearningWithNoisyLabels
from cleanlab.noise_generation import generate_noisy_labels
from cleanlab.util import value_counts
from cleanlab.latent_algebra import compute_inv_noise_matrix
from cleanlab.pruning import get_noise_indices

模擬データの準備

皆さん大好きIrisデータセットをベースに準備していきます。

seed = 2
clf = LogisticRegression(solver='lbfgs', multi_class='auto', max_iter=1000)
rp = LearningWithNoisyLabels(clf=clf, seed=seed)
np.random.seed(seed=seed)

iris = datasets.load_iris()
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

try:
    get_ipython().run_line_magic('matplotlib', 'inline')
    from matplotlib import pyplot as plt

    _ = plt.figure(figsize=(12, 8))
    color_list = plt.cm.tab10(np.linspace(0, 1, 6))
    _ = plt.scatter(X_train[:, 1], X_train[:, 3],
                    color=[color_list[z] for z in y_train], s=50)
    ax = plt.gca()
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    _ = ax.get_xaxis().set_ticks([])
    _ = ax.get_yaxis().set_ticks([])
    _ = plt.title("Iris dataset (feature 3 vs feature 1)", fontsize=30)
except Exception as e:
    print(e)
    print("Plotting is only supported in an iPython interface.")

上記を実行すると、以下のような図が表示されます。
今回はIrisデータセットの1,3番目の特徴量を使用します。

次にラベル情報にノイズを加えます。
こちらはあくまでも模擬データの準備なので、本番データでは必要ありません。

noise_matrix = np.array([
    [0.5, 0.0, 0.0],
    [0.5, 1.0, 0.5],
    [0.0, 0.0, 0.5],
])

py = value_counts(y_train)
s = generate_noisy_labels(y_train, noise_matrix)

try:
    get_ipython().run_line_magic('matplotlib', 'inline')
    from matplotlib import pyplot as plt

    _ = plt.figure(figsize=(15, 8))
    color_list = plt.cm.tab10(np.linspace(0, 1, 6))
    for k in range(len(np.unique(y_train))):
        X_k = X_train[y_train == k]  # data for class k
        _ = plt.scatter(
            X_k[:, 1],
            X_k[:, 3],
            color=[color_list[noisy_label] for noisy_label in s[y_train == k]],
            s=200,
            marker=r"${a}$".format(a=str(k)),
            linewidth=1,
        )
    _ = plt.scatter(
        x=X_train[s != y_train][:, 1],
        y=X_train[s != y_train][:, 3],
        color=[color_list[z] for z in s],
        s=400,
        facecolors='none',
        edgecolors='black',
        linewidth=2,
        alpha=0.5,
    )
    ax = plt.gca()
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    _ = ax.get_xaxis().set_ticks([])
    _ = ax.get_yaxis().set_ticks([])
    _ = plt.title("Iris dataset (features 3 and 1). Label errors circled.",
                  fontsize=30)
except Exception as e:
    print(e)
    print("Plotting is only supported in an iPython interface.")

上記を実行すると以下の図が表示されます。

先に作成した図と比較すると一目瞭然ですが、○でくくられたデータポイントはノイズ情報によってクラスが変わりました。
ここまでで、ラベル情報が間違っているかもしれないデータセットの準備ができました。

怪しいデータの検知

clf = LogisticRegression(solver='lbfgs', multi_class='auto', max_iter=1000)
psx = cross_val_predict(clf,X_train,y_train,method='predict_proba')
noise_targets = get_noise_indices(s=s, psx=psx,sorted_index_method='normalized_margin')
changed = np.where(s != y_train)[0]

今回はロジスティック回帰を用いましたが、モデル自体はなんでもokです。
ポイントは cross_val_predict で交差検定することで、各クラスの予測確率を計算することです。

def diff(changes, noise_targets):
    match_acc, failed_acc = [], []
    for gt in changed:
        if gt in set(noise_targets):
            match_acc.append(gt)
        else:
            failed_acc.append(gt)
    return match_acc, failed_acc

match_acc, failed_acc = diff(changed, noise_targets)
print("検知できたケース")
print(match_acc)
print("実際には誤ったラベルだが、検知できなかったケース")
print(failed_acc

怪しいデータから順番に出力されるため、本番データではこの情報を元に教師ラベルの修正を行うと効率的になります。

ここまでで、検知できたケースとできなかったケースのそれぞれのデータを特定することができました。
上記のデータポイントを改めて図で表示します。

mask_match = np.zeros(len(X_train), dtype=bool)
mask_failed = np.zeros(len(X_train), dtype=bool)
mask_match[match_acc] = 1
mask_failed[failed_acc] = 1

try:
    get_ipython().run_line_magic('matplotlib', 'inline')
    from matplotlib import pyplot as plt

    _ = plt.figure(figsize=(15, 8))
    color_list = plt.cm.tab10(np.linspace(0, 1, 6))
    for k in range(len(np.unique(y_train))):
        X_k = X_train[y_train == k]  # data for class k
        _ = plt.scatter(
            X_k[:, 1],
            X_k[:, 3],
            color=[color_list[noisy_label] for noisy_label in s[y_train == k]],
            s=200,
            marker=r"${a}$".format(a=str(k)),
            linewidth=1,
        )
    _ = plt.scatter(
        x=X_train[s != y_train][:, 1],
        y=X_train[s != y_train][:, 3],
        color=[color_list[z] for z in s],
        s=400,
        facecolors='none',
        edgecolors='black',
        linewidth=2,
        alpha=0.5,
    )
    # Success
    _ = plt.scatter(
        x=X_train[mask_match][:, 1],
        y=X_train[mask_match][:, 3],
        color=[color_list[z] for z in s],
        s=400,
        facecolors='#1ABC9C',
        #edgecolors='black',
        linewidth=2,
        alpha=0.1,
    )
    # Failed
    _ = plt.scatter(
        x=X_train[mask_failed][:, 1],
        y=X_train[mask_failed][:, 3],
        color=[color_list[z] for z in s],
        s=400,
        facecolors='#E67E22',
        #edgecolors='black',
        linewidth=2,
        alpha=0.1,
    )
    ax = plt.gca()
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    _ = ax.get_xaxis().set_ticks([])
    _ = ax.get_yaxis().set_ticks([])
except Exception as e:
    print(e)
    print("Plotting is only supported in an iPython interface.")

ちょっと見にくいですが、○の中が青い色のものがラベル間違えの検出に成功したもの、赤いものは検出に失敗したものになります。
最後に数値的にどれだけ精度が上がるのか見ていきます。

ラベル間違いの検知によって、どれだけ精度が上がるのか?

clf = LogisticRegression(solver='lbfgs', multi_class='auto', max_iter=1000)
rp = LearningWithNoisyLabels(clf=clf, seed=seed)

print('WITHOUT confident learning,', end=" ")
clf = LogisticRegression(solver='lbfgs', multi_class='auto', max_iter=1000)
_ = clf.fit(X_train, s)
pred = clf.predict(X_test)
print("Iris dataset test accuracy:", round(accuracy_score(pred, y_test), 2))

print("\nNow we show improvement using cleanlab to characterize the noise")
print("and learn on the data that is (with high confidence) labeled correctly.")
print()
print('WITH confident learning (noise matrix given),', end=" ")
_ = rp.fit(X_train, s, noise_matrix=noise_matrix)
pred = rp.predict(X_test)
print("Iris dataset test accuracy:", round(accuracy_score(pred, y_test), 2))

print('WITH confident learning (noise / inverse noise matrix given),', end=" ")
inv = compute_inv_noise_matrix(py, noise_matrix)
_ = rp.fit(X_train, s, noise_matrix=noise_matrix, inverse_noise_matrix=inv)
pred = rp.predict(X_test)
print("Iris dataset test accuracy:", round(accuracy_score(pred, y_test), 2))

print('WITH confident learning noise not given,', end=" ")
clf = LogisticRegression(solver='lbfgs', multi_class='auto', max_iter=1000)
rp = LearningWithNoisyLabels(clf=clf, seed=seed)
_ = rp.fit(X_train, s)
pred = rp.predict(X_test)
print("Iris dataset test accuracy:", round(accuracy_score(pred, y_test), 2))

LearningWithNoisyLabelsを使用すると、モデルフィッティングの段階で自動でラベルの間違え検知を行った上で学習を行います。

正解ラベルにノイズの乗ったデータセットでは、普通にモデルフィッティングした場合は精度が0.60となりました。
いくつかハンパーパラメータを使用しましたが、Confident Learningによる手法を活用すると、それぞれ0.83, 0.83, 0.77とベースラインに比較すると十分に高い精度で正解ラベルを予測することができるようになりました。

まとめ

最後にConfident Learning(cleanlab)を使用するにあたって要点を掲載します。
・教師ラベルが間違っているデータセットで大幅に精度が向上
・交差検定が必要

交差検定が必要なため、ディープなモデルとは実のところ相性があまりよくありません。
大規模モデルの場合、モデルを蒸留する等のいくつかのトリックが必要になるかもしれません。
ちなみに、弊社で取り扱った案件では交差検定で予測確率を算出するまでに4日ほどかかりました。
しかしながら、弊社の取り扱っているタスクで精度が0.91ほどで頭打ちになっていたものが0.95まで上昇させることができたため、新規に機械学習モデルを提案するよりも優先度が高い手法であることは間違いないと言えます。

SAI-SHIKIでは、最新の手法をキャッチアップすることで円滑にAIプロジェクトを進める体制が整っています。
データ分析やAI開発のご相談がございましたら、以下からお問い合わせください。
https://www.sai-shiki.com/contact/

【参考】
[cleanlab](https://github.com/cgnorthcutt/cleanlab)
[Confident Learning: Estimating Uncertainty in Dataset Labels](https://arxiv.org/abs/1911.00068)

The post 教師ラベルの間違えを効率的に修正する魔法の方法Confident Learningとその実装cleanlab first appeared on SAI-SHIKI | 自然言語処理AIに特化したコンサルティングと開発.

]]>