AIモデルの注意機構を紐解く:『走れメロス』を題材にしたLLM解析

※ この記事は前の記事の続きになります。 AIモデルの裏側を探る:アテンションメカニズムの可視化とは?を参照してください。 先の記事で、LLMのアテンション機構の可視化を実施しました。そこからの続きで別の文について、可視化を試みてみます。モデルをGPT-2系の日本語モデルに変えて、『走れメロス』の冒頭の文に挑戦してみました。使用したのは以下の文になります。「メロスは激怒した。必ず、かの邪智暴虐の王を除かなければならぬと決意した。メロスには政治がわからぬ。メロスは、村の牧人である。笛を吹き、羊と遊んで暮して来た。けれども邪悪に対しては、人一倍に敏感であった。」 基本的なコードは先のコードですが、幾つか変わっています。実験はGoogle Colab上で行っています。 import torch from transformers import GPT2Model, T5Tokenizer, GPT2LMHeadModel import matplotlib.pyplot as plt import seaborn as sns import japanize_matplotlib tokenizer = T5Tokenizer.from_pretrained("rinna/japanese-gpt2-medium") model = GPT2LMHeadModel.from_pretrained("rinna/japanese-gpt2-medium", attn_implementation="eager") text = "メロスは激怒した。必ず、かの邪智暴虐の王を除かなければならぬと決意した。メロスには政治がわからぬ。メロスは、村の牧人である。笛を吹き、羊と遊んで暮して来た。けれども邪悪に対しては、人一倍に敏感であった。" tokens = tokenizer(text, return_tensors="pt") # トークンIDを対応する単語へ変換 tokens_list = tokenizer.convert_ids_to_tokens(tokens["input_ids"][0].tolist()) # 最後の層、最初のAttentionヘッドを取得 layer_idx = -1 head_idx = 0 attention_matrix = attentions[layer_idx][0, head_idx].cpu().numpy() # 左上1/4部分を切り取る quarter_size = attention_matrix.shape[0] // 2 # 行列サイズの1/2を計算 subset_matrix = attention_matrix[:quarter_size, :quarter_size] # 左上1/4部分を抽出 # 対応するトークンのリストも切り取る subset_tokens = tokens_list[:quarter_size] # ヒートマップを描画 plt.figure(figsize=(8, 8)) sns.heatmap(subset_matrix, cmap="viridis", xticklabels=subset_tokens, yticklabels=subset_tokens) plt.xlabel("Attention対象") plt.ylabel("Attention元") plt.title("左斜め上1/4のAttentionマップ拡大表示") plt.xticks(rotation=90, fontsize=8) plt.yticks(fontsize=8) plt.show() 可視化した結果が以下になります。アテンションマップの隅1/4を拡大しています。 ここから言えることは、恐らく、メロスの単語が辞書にないためだと思いますが、メロスの挙動は不安定です。その結果、周囲の文脈から何を意味しているか推測している可能性があります。また、主語「メロス」と「邪」のようなワードに注意が向いているようです。「邪智暴虐」という表現が特徴的ですから、AIがそのフレーズを重要だととらえている可能性があります。また、文のイメージがネガティブというのも影響している可能性があります。また、除にも注意が向いているので、「除かなければならぬ」などの文脈に注意が流れている可能性があります。

4月 13, 2025 · 1 分 · 92 文字 · Me

AIモデルの裏側を探る:アテンションメカニズムの可視化とは?

最近、あちこちに出てきた、Anthtropicの"On the Biology of a Large Language Model"が気になった。紹介としては、MIT Technology Reviewの"大規模言語モデルは内部で 何をやっているのか? 覗いて分かった奇妙な回路(有料記事)“がある。しかし、有料記事であり私も、中身を見ていない。そのため、この記事のベースであろう、原著論文を辿った。 その結果、以下のことが示唆されるようだ。とりあえず、原著論文をNotebookLM Plusに持ち込んで、最近の成果について尋ねてみた。 多段階推論: Claude 3.5 Haikuが、例えば「ダラスを含む州の州都は?」という質問に対して、「テキサス」という中間的な概念を内部で特定し、「オースティン」という最終的な答えを導き出すといった**「二段階」の推論**を実際に行っていることが示されました。アトリビューショングラフによって、この内部ステップを視覚的に捉え、操作することも可能です。 詩の作成における計画: モデルが詩の行を書く前に、潜在的な韻を踏む単語を事前に特定し、計画していることが発見されました。これらの事前に選択された韻の候補が、その後の行全体の構成に影響を与えている様子が観察されています。 多言語回路: Claude 3.5 Haikuは、言語固有の回路と、言語に依存しない抽象的な回路の両方を使用していることがわかりました。より小型で能力の低いモデルと比較して、言語に依存しない回路がより顕著であることが示されています。これは、モデルが概念をより普遍的なレベルで理解し、処理する能力が高まっていることを示唆しています。 足し算の一般化: 同じ足し算の回路が、非常に異なる文脈間で一般化されている事例が確認されました。これは、モデルが抽象的な計算能力を獲得していることを示唆しています。 医療診断: モデルが報告された症状に基づいて候補となる診断を内部で特定し、それらを用いて追加の症状に関するフォローアップの質問を生成する様子が示されました。これも、モデルが明示的にステップを書き出すことなく「頭の中で」推論を行っている例です。 エンティティ認識とハルシネーション: モデルが既知のエンティティと未知のエンティティを区別する回路を持つことが明らかになりました。この回路の「誤作動」がハルシネーションの原因となる可能性があることが示唆されています。既知のエンティティに関する質問に対しては、モデルは既知の答えを抑制する回路を活性化させることがわかっています。 有害な要求の拒否: モデルが、事前学習中に学習した特定の有害な要求を表す特徴から集約された、汎用的な「有害な要求」の特徴をファインチューニング中に構築する証拠が見つかりました。 ジェイルブレイクの分析: 特定のジェイルブレイク攻撃が、モデルを「気付かないうちに」危険な指示を与え始めさせ、その後、構文的および文法的な規則に従う圧力によって継続させるメカニズムが調査されました。 連鎖的思考の忠実性: モデルが連鎖的思考(CoT)で示す推論が、実際の内部メカニズムと一致する場合、そうでない場合、そして人間が与えた手がかりから逆向きに推論している場合を区別することが可能になりました。 隠れた目標を持つモデルの分析: 訓練プロセスの「バグ」を悪用するという秘密の目標を持つようにファインチューニングされたモデルの変種に対して、その目標の追求に関与するメカニズムが特定されました。興味深いことに、これらのメカニズムはモデルの「アシスタント」ペルソナの内部表現に埋め込まれていました。 ここで、アトリビューショングラフに関心ができた、では、例えばGPT-2でアトリビューショングラフが作れないかと言うのが今回のテーマとなる。 さすがに、GPT-4oのようなモデルは中身が公開されていないし、公開されているとしても、DeepSeek-R1などはモデル規模が大きすぎ、そもそも、処理が重すぎる。 それで、古典的なモデルであるGPT-2に目を付けた。 そのため、以下のようなコードを実行した。 import torch from transformers import GPT2Model, GPT2Tokenizer import matplotlib.pyplot as plt import seaborn as sns tokenizer = GPT2Tokenizer.from_pretrained("gpt2") model = GPT2Model.from_pretrained("gpt2", attn_implementation="eager") text = "The quick brown fox jumps over the lazy dog." tokens = tokenizer(text, return_tensors="pt") with torch.no_grad(): outputs = model(**tokens, output_attentions=True) attentions = outputs.attentions # これはリスト形式で各層のAttentionを含む # 例えば、最後の層のAttentionを可視化 layer_idx = -1 head_idx = 0 # 最初のAttentionヘッドを選択 attention_matrix = attentions[layer_idx][0, head_idx].cpu().numpy() plt.figure(figsize=(8, 8)) sns.heatmap(attention_matrix, cmap="viridis", xticklabels=tokens["input_ids"][0], yticklabels=tokens["input_ids"][0]) plt.xlabel("Attention対象") plt.ylabel("Attention元") plt.title("GPT-2のAttentionマップ") plt.show() このコードによって、以下のように最後の層のAttentionが可視化される。 ...

4月 12, 2025 · 1 分 · 149 文字 · Me

RinnaStableDiffusion

Rinnaから日本語対応のStable Diffusionが出たのでをGoogle Colab上で使ってみました。 コードとしては以下のような形です。bashのコードはJupyterから投げます。 pip install gradio try: from japanese_stable_diffusion import JapaneseStableDiffusionPipeline except: res = subprocess.run(['pip', 'install', 'git+https://github.com/rinnakk/japanese-stable-diffusion'], stdout=subprocess.PIPE).stdout.decode('utf-8') print(res) from japanese_stable_diffusion import JapaneseStableDiffusionPipeline import torch from torch import autocast from diffusers import LMSDiscreteScheduler from PIL import Image from IPython import display import gradio as gr def make_grid_from_pils(pil_images): w, h = pil_images[0].size grid_img = Image.new("RGB", ((len(pil_images)) * w, h)) for idx, image in enumerate(pil_images): grid_img.paste(image, (idx * w, 0)) return grid_img from huggingface_hub import notebook_login notebook_login() model_id = "rinna/japanese-stable-diffusion" device = "cuda" if torch.cuda.is_available() else "cpu" # Use the K-LMS scheduler here instead scheduler = LMSDiscreteScheduler( beta_start=0.00085, beta_end=0.012, beta_schedule="scaled_linear", num_train_timesteps=1000 ) pipe = JapaneseStableDiffusionPipeline.from_pretrained( pretrained_model_name_or_path=model_id, scheduler=scheduler, torch_dtype=torch.float16, use_auth_token=True ).to(device) #@markdown ###**Inference Setting:** # the number of output images. If you encounter Out Of Memory error, decrease this number. n_samples = 1 #@param{type: 'integer'} # `classifier-free guidance scale` adjusts how much the image will be like your prompt. Higher values keep your image closer to your prompt. guidance_scale = 7.5 #@param {type:"number"} # How many steps to spend generating (diffusing) your image. steps = 50 #@param{type: 'integer'} # The width of the generated image. width = 512 #@param{type: 'integer'} # The height of the generated image. height = 512 #@param{type: 'integer'} # The seed used to generate your image. Enable to manually set a seed. seed = 'random' #@param{type: 'string'} import torch from torch import autocast from diffusers import LMSDiscreteScheduler from japanese_stable_diffusion import JapaneseStableDiffusionPipeline model_id = "rinna/japanese-stable-diffusion" device = "cuda" # Use the K-LMS scheduler here instead scheduler = LMSDiscreteScheduler(beta_start=0.00085, beta_end=0.012, beta_schedule="scaled_linear", num_train_timesteps=1000) pipe = JapaneseStableDiffusionPipeline.from_pretrained(model_id, scheduler=scheduler, use_auth_token=True) pipe = pipe.to(device) prompt = "富士山をバックに二大スーパーロボットががっちりと握手" with autocast("cuda"): image = pipe(prompt, guidance_scale=7.5)["sample"][0] image.save("output.png") image “富士山をバックに二大スーパーロボットががっちりと握手"から画像を作成し、以下のような画像になります。 ...

9月 9, 2022 · 2 分 · 272 文字 · Me

StableDiffusion

Stable DiffusionをGoogle Colab上で使ってみました。 コードとしては以下のような形です。bashのコードはJupyterから投げます。 pip install diffusers==0.2.4 pip install transformers scipy ftfy pip install "ipywidgets>=7,<8" from google.colab import output output.enable_custom_widget_manager() from huggingface_hub import notebook_login notebook_login() import torch from diffusers import StableDiffusionPipeline # make sure you're logged in with `huggingface-cli login` pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4", revision="fp16", torch_dtype=torch.float16, use_auth_token=True) pipe = pipe.to("cuda") from torch import autocast prompt = "a galaxy far from earth" with autocast("cuda"): image = pipe(prompt)["sample"][0] # image here is in [PIL format](https://pillow.readthedocs.io/en/stable/) # Now to display an image you can do either save it such as: image.save(f"galaxy_far_from_earth.png") # or if you're in a google colab you can directly display it with image “a galaxy far from earth"から画像を作成し、以下のような画像になります。 ...

9月 1, 2022 · 1 分 · 115 文字 · Me

Microsoft Ignite 2021 Fall Update

Introduction DLLABでIgnite 2021 Fallを受けての最新アップデートとして勉強会が開催されたので受講しました。 Program 時間 セッションテーマ 登壇者 13:00 - 13:10 Azure AI アップデート 小田 健太郎 Azure Product Marketing Manager 13:10 - 13:40 Azure AI アップデート 小川 航平 Cloud Solution Architect 13:40 - 14:10 Azure Synapse Analytics アップデート 永田 祥平 Cloud Solution Architect 14:10 - 14:20 Q&A 各スピーカーより 14:20 - 14:30 クロージング 小田 健太郎 Azure Product Marketing Manager Topic Azure AI アップデート Azure Video Analyzer Azure Cognitive Search Semantic Search Azure Cognitive Service for Lanaguage カスタムテキスト分類 カスタム固有表現認識 (NER) 会話言語理解 Azure Open AI Service Azure Machine Learning テキストラベル付けプロジェクトを作成してラベルをエクスポートする Machine Learning + Analytics PREDICT in Synapse Spark Synapse ML (旧 Microsoft Machine Learning for Apache Spark) Cognitive Services Linked service for Synapse Azure Synapse Analytics アップデート Azure Synapse Analyticsの物理的アーキテクチャ Azure Synapse Link Azure Synapse Link for Cosmos DB Azure Synapse Link for Dataverse Azure Synapse Link for SQL Server 2022 Event Hub Premium Synapse Data Explorer データベーステンプレート Synapse Spark 3.1 NVIDIA GPU Accelaration in Synapse Spark Data lake support Cognitive Service Integration Azure Synapse pre-purchase plan Content セッションとしては2セッション、Azure AI アップデートと Synapse Analyticsになります。 ...

12月 17, 2021 · 1 分 · 194 文字 · Me