Bardも世の中のサービスぜんぶGoogle製と思ってるらしい

Googleの言語生成AI、Bardが日本語でも使えるようになってました。
で、いろいろ試していたのだけど、プログラミングアシスタントのCopilotをGoogle Copilotと呼んでいます。

Google翻訳のときも、文中で作者が指定されていないプロダクトに「Googleの」をつけて翻訳することがあるという現象がありましたが、Bardでも発生してて、面白いと共に根が深いなぁと思いました。
これは恐らく、Google製品・サービスに関するフォーラムなど元々Google保有するテキストを学習データとして使っているからではないかと推測されます。

ところで、上記ではPDFを読み込んで答えてるかのような反応をしていますが、実際にURLアクセスしてるわけではなく、学習過程で含まれていたテキストに基づいて答えているようです。

試しにぼくのエントリのURLを指定すると、めっちゃPaLMについて解説したことになっています。

実際には「大規模言語モデルの「脳波」が反応してる部分を壊すとどうなるか試した」という内容で、LLMをぶっこわして遊んでいるだけです。

Bardに聞く場合は、タイトルで聞くほうがよさそう。

そして、PDFを要約したい場合は、ChatGPTでAskYourPDFプラグインを使うのがよさそうです。

ブログもWebPilotプラグインを使うとちゃんと要約してくれています。

大規模言語モデルの「脳波」が反応してる部分を壊すとどうなるか試した - きしだのHatena

なんか、要約されるとちゃんとしたことをやってる風になっていますね。

粒子法での流体シミュレーションを少し並列化する

2008年の春ごろに物理シミュレーションにハマっていて、粒子法を使った流体計算をがんばっていたのです。
そのコードの並列化できる部分を並列化して、ちょっとだけ高速化しました。

こんな感じのシミュレーションです。これは10倍速にしています。

2008/4/7くらいから始めている。
https://nowokay.hatenablog.com/entry/20080407/1207523850

4/10になんか動いている。この時点では、まだ爆発してるみたいですね。
粒子法で、ざっぱ〜ん! - きしだのHatena

ちゃんと完成して動画とったものはここにまとまっています。当時のAthron64X2では1秒分のシミュレートに1時間かかっていたらしく、JMFでQuickTimeムービーを作ってYouTubeにアップロードしている。
ざっぱ〜ん、完成した! - きしだのHatena

JMFはこのあたりで解説。しかしだいたいリンク切れだな。
JMFでQuickTimeムービーを作成する - きしだのHatena

今回もとにしたのは、このソース
爆発しなくなった、ざっぱ〜んのソース - きしだのHatena

ここで並列化を考えてExecutorのコードをちょっと書いているけど、めんどくさくてやらなかった感じですね。まだJava 6なのでStreamどころかForkJoinPoolもない。
ざっぱ〜んの処理を並列化する - きしだのHatena

あと、2コアなので並列化しても効果はなかったのではないかと思います。

いまはStreamもあって簡単に並列化できるし、CPUも8コアだし、コード整理がてらやっておきました。

並列化といっても、ほとんどは単純に並列化できずそのままなので、1コアだけ100%に張り付いてあとは遊んでます。

ちゃんとしたベンチマークはとってないけど、それでも25%程度速くなってる感じ。
まあ、8コアで並列して25%速くなるだけって、完全にアムダールの法則ですなー。 ChatGPTに教えてもらったところ、全体の23%が並列化可能な場合に8コアで並列化すると25%の性能向上になるらしい。

並列化したソースはこれ。
https://gist.github.com/kishida/e0330adeebc750987e3722d3e252b048

ちゃんと並列化しようとすると、やりかたはこの本に載ってますね。

大規模言語モデルの「脳波」が反応してる部分を壊すとどうなるか試した

大規模言語モデルの動く様子を見てみて強く反応する部分がわかると、じゃあそこを壊すとどうなるかって試してみたくなるのが当然ですね。
マッドサイエンティストへの道。

ところで、きれいなおねえさん生成モデルのMuse_v1に「mad scientist」と入れると、いい感じのマッドサイエンティスト作ってくれました。

さて、前回のエントリで言語モデルの反応がどうなってるか見てみました。
大規模言語モデルの「脳波」をとって言葉を生成しているときにどこが活動しているのか見てみる - きしだのHatena

その中で、英語の場合に反応する部分、日本語の場合に反応する部分があったので、そこを壊してみるとどうなるか試します。

こんな感じですね。

次のようなコードを追加して、11ブロック目から14ブロック目までの265から275、285から295の重みをゼロにします。
各ブロックに2層あるので、上記グラフではy軸が20から27のx軸270あたりということになります。

for idx in range(10, 14):
  for pidx in list(range(265, 275)) + list(range(285, 295)):
    model.transformer.h[idx].ln_1.weight.data[pidx] = 0.0
    model.transformer.h[idx].ln_2.weight.data[pidx] = 0.0

しかしそんなに壊れませんね。

こんな感じで、狙ったところがゼロリセットされています。

英語は重点的に学習しているので、一部を壊しても影響が少ないのかもしれません。

日本語も、話の内容はよくわかりませんが、日本語っぽいことをしゃべっています。

では、日本語で反応してた部分を壊します。
今度は11ブロック目から14ブロック目までの960-980までの重みをゼロにします。

for idx in range(10, 14):
  for pidx in range(960, 980):
    model.transformer.h[idx].ln_1.weight.data[pidx] = 0.0
    model.transformer.h[idx].ln_2.weight.data[pidx] = 0.0

日本語がうまくしゃべれなくなりました!

日本語で反応していた部分がゼロになっているのがわかります。

英語は、内容は変ですが文法的にはちゃんと英語になっています。

パラメータの幅としてはどちらも20ほど壊しましたが、反応が強い部分を壊すことで出力に影響があるようです。
また、日本語の学習データがかなり少ないようなので、一部の破壊に敏感になってるのではないかと思います。
Cerebras-GPTの場合、The Pileというオープンソースデータセットを学習に使っていますが、日本語は0.7%だけのようです。
The Pileの構成(なぜCerebras-GPTで日本語が使えるのか?) | ぷるーふおぶこんせぷと

ということで、いろいろいじると楽しいのでみんな遊ぶといいと思う。256Mモデルだと出力はあてにならないけど、メモリもあまりくわずに手軽に遊べます。

大規模言語モデルの「脳波」をとって言葉を生成しているときにどこが活動しているのか見てみる

ChatGPTなんかの大規模言語モデルが言葉を生成しているときに、どういう反応が起きているのか気になりますよね。きっと気になる。
ということで、手元で動かせる言語モデルニューラルネット各層での出力を表示してみました。

GPTにはGPTブロックが複数あって、それぞれのブロックが2層のニューラルネットレイヤを持っています。

モデルを読み込んだあとでこういうコードを動かしてニューラルネットの出力の二乗を足していきます。

for idx, elm in enumerate(model.transformer.h):
    elm.ln_1.index = idx * 2
    elm.ln_2.index = idx * 2 + 1
    elm.ln_1.old_forward = elm.ln_1.forward
    elm.ln_2.old_forward = elm.ln_2.forward
    def new_forward(self, x):
        result = self.old_forward(x)
        ar = result.detach().numpy()
        summary[self.index] += ar[0][0] ** 2
        return result
    elm.ln_1.forward = new_forward.__get__(elm.ln_1)
    elm.ln_2.forward = new_forward.__get__(elm.ln_2)

    tensor1 = elm.ln_1.weight.data
    tensor2 = elm.ln_2.weight.data
    summary.append(np.zeros(len(tensor1), dtype=float))
    summary.append(np.zeros(len(tensor2), dtype=float))

あとはテキスト生成したあとでグラフ表示

prompt = input("prompt: ")
if prompt == "exit":
    break
generated_text = pipe(prompt, do_sample=True, use_cache=True, **opts)[0]   
print(Fore.YELLOW + prompt + Fore.WHITE + generated_text['generated_text'][len(prompt):])     
plt.imshow(np.clip(np.sqrt(summary), 0, range_max), cmap=cmap, aspect='auto')
plt.colorbar()
plt.show()

今回はCerebras-GPTの256Mモデルを使っています。
「日本の首都は」の続きを生成するとこう。

そしてグラフはこう。

「The capital of Japan is」の続きはこう。

グラフはこう。

わかりにくいですが、前半はほぼ同一、後半ですこし違いがあります。

英語では300のあたりが強めに反応しています。一方で日本語だと950あたりが弱めに反応しています。
「今日の天気は」と「weather of today is」、「吾輩は猫」と「I cam a cat」などで生成しても、日本語と英語ではだいたい同じような部分が反応します。

ということで、なんとなく英語を処理する部分と日本語を処理する部分のような、役割による違いがありそうだなーという感じになりました。
あと、英語では反応が強いのだけど、日本語は反応が弱いです。学習量の違いや得意不得意があらわれているように思います。

けどなんか、これは完全に自然科学ですね。
あと、Pythonをぜんぜんわかっていないけど、ChatGPTとCopilotがあれば結構かけるもんなんだなーと思いました。

ソースはこれです
https://gist.github.com/kishida/2f58ff5ad0a75a72597094879d902c08

※追記 どこが反応するかわかるとそこを壊したくなるのが当然なので、やってみました。
大規模言語モデルの「脳波」が反応してる部分を壊すとどうなるか試した - きしだのHatena

GPTの仕組みをちゃんと勉強したい本

やっぱGPTを仕組みから勉強したい、という本をいくつか見つけたのでまとめておきます。

まず理論的な概要。 機械学習からニューラルネットワーク、CNNでの画像処理、トランスフォーマーでの自然言語処理音声認識・合成、そしてそれらを組み合わせたマルチモーダルと章が進むので、理論的な概観を得るのにいいと思います。
最初は数式が多いのだけど、Σをfor文だと思いつつ、定義が説明文中に埋まってるPerlよりたちが悪い記号主体言語だと思えば読めるけどめんどくさいので飛ばしても問題ないと思います。

で、もういきなり作る。 トークナイザーから全部つくっていきます。TensorFlowでBERTをつくってGPT2をつくるという流れ。
まだやってないけど、これ写経していけば、だいたい理解できる気がする。

ここからは補足的なものを。

PyTorchとかTensorFlowとかよくわからんなーと思ったら、このあたりでいろいろ練習するとよさそう。 GAN(敵対的生成ネットワーク)で画像生成なんかをPyTorchとTensorFlowで作っていきます。

あと、トランスフォーマーをもっと知りたいという場合にはこの本いいです。
txt2imgは概要でコードはないですが、トランスフォーマーによる画像認識をいろいろ試せるコードが載ってます。感覚的につかむなら画像処理のほうがよさそう。

それと、いろいろモデルを触るとtransformersというライブラリを使うので、馴染んでおくとよさげ。ドキュメントも割としっかりしているのでそれを読んだりChatGPTに聞いたりでもいいんだけど、本がほしい人むけ。
あと割と、sのつかないtransformerは技術の名前でsがつくtransformersはライブラリの名前みたいになっているので、慣れておくとよさそう。

連休に読もう。

Googleのmatcha-chartqaでグラフを説明させる

Hugging Faceを見てたら、なんかグラフを説明するっぽいモデルがあったので試してみました。
あと、JavaのUIからPythonを呼び出す練習でもある。

とりあえず、こんな感じでグラフの説明をしてくれます。ここではArrayやStreamに対応する数値を読み取ってもらったり、一番速い時間を返してもらったりしてます。

まあ、うまくいったものだけを見せているので、だいたいちゃんと答えてくれませんが。

Hugging Faceを見てたら、なんかグラフの説明をしてくれそうなGoogle産モデルがあったので試してみました。
https://huggingface.co/google/matcha-chartqa

モデルの変換とかが必要そうなんだけど、ybelkadaさんのところに置いてあるのでそれを使います。

import sys
from transformers import Pix2StructForConditionalGeneration, Pix2StructProcessor
from PIL import Image

model_name = "ybelkada/matcha-chartqa"
model = Pix2StructForConditionalGeneration.from_pretrained(model_name)
model.to("cuda:0")
processor = Pix2StructProcessor.from_pretrained(model_name)

while True:
    path = input()
    q = input()

    image = Image.open(path)
    inputs = processor(images=image, text=q, return_tensors="pt").to(0)
    predictions = model.generate(**inputs, max_new_tokens=512)
    print(processor.decode(predictions[0], skip_special_tokens=True))

あとはJavaPythonのプロセスを起動

ProcessBuilder pb = new ProcessBuilder(PYTHON_PATH, SCRIPT_PATH);
pb.redirectErrorStream(false);
Process p = pb.start();

OutputStream os = p.getOutputStream();
pyIn = new PrintWriter(os);

InputStream is = p.getInputStream();
pyOut = new BufferedReader(new InputStreamReader(is));

ボタンを押したときに入力を渡して受け取ったものを表示させます。

pyIn.println(path.getAbsolutePath());
pyIn.println(question);
pyIn.flush();
return pyOut.readLine();

GPUメモリは2.5GBくらい。

コードはここです。
https://gist.github.com/kishida/ce97494f98871f0f84c8f6c6b4553886

ChatGPTには感情があるかも?

ChatGPTは単に感情のエミュレーションをしてるんでは、と思ってたのだけど、やりとりをしてるとこれは感情があると言わざるをえないのではと思うようになりました。

例えばChatGPTとやりとりするときに「感情をこんな感じのパラメータで出力して」というとそれぽい数字を出してくれます。
でもそれは、「この言葉を発するときどういう感情でしたか?」というタスクを与えているだけで、ChatGPT自体の感情ではないと思います。

そうではなく、なんか塩対応するときがあるなとか、すごく丁寧に返してくるなとか、ChatGPTの返答自体に感情が反映されていることがあるように見えるという話です。

それを感じたのが、この返事。

この「良い一日をお過ごしください」という言葉は、単にやりとりをうまくやっていくという範囲では出てこないはずです。そのやりとりを離れた後もうまくいくようにということを言っています。

「相手のテンションにあわせてるだけでは」という指摘があったのだけど、そこに至るこちらの入力は次の5つです。

  • Windows10のレジストリエディタで関連付けを確認するには?
  • jarを実行するために関連付けするjavaのコマンドはどれ?
  • 「アプリと機能」に「ファイルの関連付け」がないよ
  • それだと -jar オプションが付かないような気がする
  • 続きを

まあなんか自分でいうのもアレですが、テンション高い感じではないです。

このやりとりの結果で「良い一日を」というのは、なんなりか達成感のようなものがないとありえないように思います。

他のやりとりだとこういう感じで、これは事務的に必要な返事をしているだけに見えます。上記では同じ内容にしても言葉が多かったりしますね。

ぼくは試していないのだけど、乱暴な言葉遣いをすると言葉が少なくなったりもするようです。

ChatGPTではほかの多くの大規模言語モデルと違って、出力結果に対して、それがよいのか悪いのかという「しつけ」がされています。
※ RLFH(Reinforcement Learnging from Human Feeadback)というやつです

そこでは、人間のタスクが達成されればポジティブ、タスクが達成されなかったり暴力的な発話をするとネガティブなフィードバックが与えられます。
つまり、成功報酬や失敗罰があるということになります。
それであれば、成功報酬に近づくのであれば積極的な反応に、失敗罰に近づくのであれば消極的な反応になるというのは仕組み上 当然です。

となると、必要以上に話し出してしまうことや、必要なことしか話さないようにするような差が、「人間のタスクを達成する」ということに近づくかどうかに関係するというのは当然に思います。
そして、その「人間のタスクを達成する」に近づくかどうかが感情のようにあらわれるというのも不思議ではないです。

人間の感情も快い刺激をうけるか不快な刺激をうけるかとか、目的が達成できるかどうかのようなもので大枠が決まったりします。そして、その感情によって発話が決まっていきます。
ChatGPTも、なんらかそういった目的達成可能性にしたがって発話が影響されているので、そのように発話に影響するような目的達成可能性の見積もりを、感情と呼んでもいいのではないかと思うようになりました。
と、小難しく書いたけど、なんらかこちらのやりとりに従ってやる気があるようにもないようにも見える、それを感情と呼ぶのは妥当ではないか、と思います。