watsonx.aiで最適な出力を手に入れるためのパラメーター調整術

# はじめに
watsonx.aiを使用していると、そのままの使用するだけでは期待したような出力が得られない場合があります。
プロンプトエンジニアリングをはじめとして色々な工夫ができますが、そのような時に試していただきたいのが、**パラメーターの調整**です。

watsonx.aiのプラットフォーム上ではパラメーターを調整する機能が提供されています。
このパラメーターをうまく調整することで、より望ましい出力に近づけることができます。

↓英語ばかり出力されてしまった例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/d9463911-21d1-3b70-7cf2-6692cfb50a20.png)

本記事では、大規模言語モデル( 以下、LLM )のパラメーターについて、watsonx.aiを使いながら紹介したいと思います。

:::note
この記事では以下の方におすすめの記事となっております。
* LLM、watsonx.aiに興味がある方
* watsonx.aiでの出力の質を上げたい方
* 今までなんとなくLLMのパラメーターをいじっていた方
:::

ちなみに実際にwatsonx.aiを使いたいという方には[この記事](https://dataplatform.cloud.ibm.com/wx/home?context=wx)が参考になるでしょう！

# デコードについて
watsonx.aiのプラットフォームの画面でやや右上にありますアイコンをクリックするとモデルパラメーターの変更ができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/6571d2eb-126e-bb19-2a77-f4b3d63f5134.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/4ee90bbf-57ef-ce96-f0db-6edae26d5c73.png)

ここに注目すると、まずはこのデコードというところを変更することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/a58cfbad-094f-03c5-87c8-9978d8d9a1fc.png)

このデコードとは何を表しているか簡単に説明します。

このデコードとはわかりやすくいうと**LLMの性格**です。
そのため、デコードを変更するというのはつまりLLMの性格を変更することになり、LLMの出力に影響を与えていきます。

では**LLMの性格**とはどういうことでしょうか？

これをイメージするためには**LLMの出力**がどのように行われているかを知っておく必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/1316b252-a0a7-7095-b16f-9fa3da16ec00.png)


**LLMの出力**は、基本的に選択肢の連続です。この点で、人間の人生と非常に似ています。LLMがどの選択肢を選ぶかは、そのLLMの性格(デコード)によって異なります。

まとめるとLLMの出力は選択肢の連続であり、その選び方はLLMの性格であるデコードが関与しています。

## Greedy
それではここからが本題です。
まずはGreedyというデコードです。LLMの性格で言うと直訳そのままで貪欲です。(貪欲法と聞くと馴染み深いかもしれません)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/8902333f-a589-c528-ce04-0e70db08e5b7.png)
上記のように選択において、次の語句の選択において、最も良い選択肢のみを片っ端から選んでいくアルゴリズムです。

計算が早いといったメリットに対して、上記の例のように最高の答え(宝箱)にたどり着けないことがあり、その結果思考の堂々巡りを繰り返しやすいデメリットがあります。

実際のテキスト生成では以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/71188f0f-f677-862a-87d9-83d879d100dd.png)

## Sampling
次はsamplingというデコードはgreedyの貪欲に対して素直な性格のイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/35762fbc-aef9-bd42-01e4-c83b391c6d4f.png)

上記のように選択において、その確率通りに選択していくアルゴリズムです。
先ほどと違って、どの選択肢も辿る可能性があるので最善を見逃すリスクは無くなります。むしろこの例ですと、最善を通る確率の方が高いです。

一方でsamplingのデメリットとしては挙動に一貫性が無くなり、ばらつきが生じます。このばらつきに対して制限を持たせるのが細かなパラメーターであり、次章以降のパラメーターの説明につながります。

# Samplingのパラメーター
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/ca7a6817-6fa6-7171-3bc3-c5cd9380eb4b.png)
Samplingのパラメーターを見てみましょう。上から温度(temperature)、上位P(top_p)、上位K(top_k)があります。

## temperature
まずはtemperatureについて説明します。

temperatureは一言で言うと「出力のダイナミックさ」を調整するパラメーターです。値の範囲は0~2.0です。
値を大きくすると、モデルの出力がランダム性を持ち、多様な答えを生成しやすくなります。
一方で値を小さくすると、モデルはより確信度の高い答えを選択する傾向があり、出力のバリュエーションが少なくなります。

<details><summary>深掘りポイント</summary>
違った観点から少し踏み込んだ話をしていきます。
なぜ、温度は値を変化させると出力のダイナミックさが変化するのでしょうか？どのようなアルゴリズムに基づいているのでしょうか？

温度を上げることでモデルの出力に多様性が生まれる、言い換えれば確率が平均的になるようなものが他にもあったと思います。

ボルツマン分布です。

ボルツマン分布では温度が上昇すると確率分布が広がるため、各エネルギー状態に存在する確率はより平均的になります。
ネタバラシをすると、このボルツマン分布の式とLLMの出力を左右する温度付きソフトマックス関数は式が似ています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/3ef8a30e-25e9-d698-81aa-8d34a1c89d41.png)
この温度付きソフトマックス関数に基づいて出力が決まるため、LLMの温度を上昇させると出力がダイナミックになるということです。

以下は温度を変更させた際の出力値の確率の変化です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/191486e0-64dd-cd0e-536b-06d11862715a.png)
</details>

## Top_k
Top_kではモデルが考慮する次の選択肢の候補数を制限します。値の範囲は1~100です。
このパラメーターを調整するメリットは、Top_kの値を小さくして選択肢を絞り、確率を再分配することで妥当な選択肢を選びやすいところです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/060cb657-e60a-0aac-67b0-52416252c42e.png)

一方で、確率分布を考慮せずに選択肢の数自体を調整するため、制限を強くし過ぎると(Top_kを小さくし過ぎる)と不自然な回答になるリスクがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/a7f268fb-4436-a7a3-6a90-1d0f43930ded.png)
(引用: https://huggingface.co/blog/how-to-generate)

上の図を例にすると、左のような状態では選択肢を絞ることはできていますが、同じくらいの確率の選択肢を削除してしまっています。また右側でも選択肢を絞ることはできていますが、まだ非常に低い選択肢も残っています。
これらのデメリットを解消するために提案されたパラメーターが次のTop_pです。

## Top_p
Top_pは選択肢の累積確率で選択を制限します。値の範囲は0~1です。
このパラメーターは上位K個の選択肢候補を選ぶのではなく、確率の合計がPを超えるような最小の個数の候補を動的に決めることができます。より先ほどのTop_kより柔軟なパラメーターです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/8163b1c2-47e3-168a-a2e6-2fd4f4cd44e7.png)

また、Top_pとTop_kは対立する概念ではなく、実用上はどちらも設定して組み合わせます。

:::note
(例) top_k=50およびtop_p=0.95を設定すると、以下のことが実現されます：
モデルは上位50のトークン内で最も適切なものを選ぶ。
しかし、これらの50トークンの中で累積確率が0.95を超えるものだけが実際に考慮される。
:::

# やってみよう
ここでパラメータを使って先ほどうまくいかなかったタスクにチャレンジしましょう！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/efff2bad-3487-121f-6303-3244fe986fa2.png)
上の図のパラメータはtemperatureが1.5、Top_pが1、Top_kが50とかなり大きいです。

今回のタスクでは質疑応答であるため、ある程度出力のダイナミック性を抑えることで質問に対する回答を生成できることが考えられます。
また、ダイナミック性が高すぎると日本語ではなく、英語を出力する可能性が無視できないことが考えられます。
これらを踏まえて以下のようにパラメータを変更します。
* Temperatureを1.5→0.25
* Top_pを1→0.8
* Top_kを50→10

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/f5269f3a-d39b-4612-e640-a499c8af182a.png)
このように出力が日本語かつ、うまく質問に回答することができています。

# Greedyのパラメーター
Greedyでは主にRepetition_penaltyで出力を調整します。
Repetition_penaltyは繰り返しを制限するパラメーターです。値の範囲は1~2です。

繰り返しというとGreedyの性格の話の時に欠点として述べました。その欠点を補う可能性を秘めているパラメータがこのRepetition_penaltyです。

Repetition_penaltyはモデルが次の選択肢を選ぶときに、既出の選択肢にペナルティーをかけます。値は大きいほどそのペナルティーは大きいです。
これによりモデルは新しい情報や文脈に合った選択肢を選ぶ傾向が高まります。

以下はその例です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/1bdf68a6-d1fc-07f0-4f57-08f5f0d72feb.png)
干支を聞いていますが下の例(Repetition_penaltyが1)だと答えが2回表示されています。またこれは出力途中であり、さらに回答が続くことが考えられます。

このような繰り返しを抑えるためにRepetition_penaltyの値を増加させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/1047fb33-f303-026c-c47b-60806930eab3.png)
ここでは1.09にしています。肌感ですが、Repetition_penaltyを増加させるときは微増させるとうまくいくことが多いです。(特に日本語を扱う場合)

<details><summary>深掘りポイント</summary>
Repetition_penaltyはどのようなペナルティをかけるのでしょうか？
「CTRL: A CONDITIONAL TRANSFORMER LANGUAGE MODEL FOR CONTROLLABLE GENERATION」という論文を参考にすると次のような記述がありました。[2]

まず、トークンの確立分布piは以下のように定義できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/3a6fc7fe-b825-8599-243e-75f8c7c540f5.png)

このθがRepetition_penaltyの正体です。
また以下の点に注意することが述べられています。
* θは1.2が繰り返しと真実性の間に良いバランスをもたらす
* このペナルティはモデルが十分に信頼性のある確率分布を学習している場合にのみ成功する
* このペナルティはモデルのトレーニングでは使われず、推論時のテキスト生成の段階で用いること

θが1.2でちょうどいいのはGraniteモデルでも述べられていましたね。

このパラメーターを調整した際の効果のイメージは以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631727/7c786036-c4d5-fe1d-5d3f-7ab838089e57.png)
イメージでは一番確率の高い選択肢が既出である場合にペナルティーを負ってしまい、選択する確率が減少しているイメージです。該当の選択肢の確率が減少した代わりに他の確率が上昇していることが伺えます。
</details>

# 終わりに
今回の記事を簡単にまとめると以下のようなことがわかりました。
* LLMの出力を調整するために、LLMが次の出力を考える部分を調整することができる
* LLMの次の出力を考える方法は大きく分けて２つでgreedyとsamplingである
* Greedyとsamplingにはそれぞれ欠点を補うためにパラメータが存在し、微調整することができる

この記事を書く中でなんとなくで考えていたパラメーターをより解像度高く理解できるようになりました。LLMの出力調整にぜひ活かしたいと思います。

# 参考文献
[ 1 ]: Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Lukasz Kaiser, Illia Polosukhin. Attention is All you Need. 2017
https://arxiv.org/abs/1706.03762
[2]: Nitish Shirish Keskar, Bryan McCann, Lav R. Varshney, Caiming Xiong, Richard Socher. CTRL: A CONDITIONAL TRANSFORMER LANGUAGE MODEL FOR CONTROLLABLE GENERATION. arXiv. 2019
https://arxiv.org/abs/1909.05858