OpenAIのtemperature：出力のばらつきを調整するパラメーターは一体なんで温度なんだ！？

# 概要
　OpenAIのAPIを使う際に出力の自由度を調整するためのパラメーターtemperatureは

**機械学習の世界から見ると，softmax関数におけるスケーリングファクター**であり，
**物理の世界から見ると，ボルツマン分布の温度**として考えることがで，
**統計の世界から見ると，確率分布の鋭さ**としてみることができるということが今回わかりました．

分野超えてディスカッションできるのは改めて大学のいいところだと感じた今日この頃でした．

そこで，OpenAIは物理的な世界から見た呼び方を採用しているようです．
機械学習の世界でも普通に温度とか言ったりすることもあるっぽいです．


# この記事で伝えたいこと
　OpenAIのtemperatureは出力の自由度を調整するためのパラメーターですが，なぜ，temperatureというのかわからずモヤモヤしていました．
　今回はこの**OpenAIのパラメーターのtemperatureがなぜtemperatureという理由**を記事にしてみたいと思います．

# そもそもsoftmaxとボルツマン分布
以下では，そもそもsoftmaxとボルツマン分布とは何か？softmax関数にける温度とは何かについて説明します．

## Softmax関数における温度とは
 Softmax関数をちょっといじると，温度orスケーリングファクターを定義できます．以下では実際に温度を定義してみます．
 そもそも，Softmax関数は通常は以下のように定義されます．

$$Softmax(x_i)=\frac{e^{x_i}}{\sum^n_{k=1}e^{x_k}}$$

これをちょっと工夫して式変形すると以下のようになります．

$$Softmax(x_i)=\frac{\frac{e^{x_i}}{T}}{\frac{\sum^n_{k=1}e^{x_k}}{T}}$$

**右辺の上下を$T$で割ることにします．これが，Temperatureと呼ばれるもの**です．

## ボルツマン分布とは
　ボルツマン分布は統計力学において物質状態の確率を表す分布のことです．
　まぁ，物理の中でも，ボルツマン分布はボルツマンマシンなどにも応用されていて，機械学習の世界とは馴染みが深いものなのかなと思います．

 ボルツマン分布は，特定の状態$i$が選ばれる確率$P(i)$が，その状態のエネルギー$ε_i$と絶対温度$T$に依存するということを表します．

　そんなボルツマン分布は$ε_i$は状態$i$のエネルギー，$k$はボルツマン定数，$T$は絶対温度（ケルビン単位），そして$\sum_j$は全可能な状態$j$にわたる和を意味し．以下のように表されます．

$$P(i) = \frac{ \exp(-\epsilon_i/(kT)) }{ \sum_{j} \exp(-\epsilon_j/(kT)) }$$

 ボルツマン分布自体，エネルギーが最小の状態に最も高い確率を割り当て，エネルギーが高くなると確率が指数的に減少します．

この分布の特徴的な点は，温度によって確率が変化することです。
- 温度が高くなると，高エネルギー状態の確率が増加し，
- 逆に温度が低くなると，低エネルギー状態の確率が増加します．


### ソフトマックス関数とボルツマン分布の関係
 ソフトマックス関数とボルツマン分布はそもそも形状が似ています．

|ソフトマックス関数|ボルツマン分布|
|:--:|:--:|
|$$Softmax(x_i)=\frac{e^{x_i}/T}{\sum^n_{k=1}e^{x_k}/T}$$|$$P(i) = \frac{ \exp(-\epsilon_i/(kT)) }{ \sum_{j} \exp(-\epsilon_j/(kT)) }$$|


そもそも両方とも，各要素が他の要素に対する相対的な重要性を表す確率分布を生成します．この性質は、機械学習の分類タスクや言語モデルなどで役立ち，色々応用されています．


# ソフトマックス関数における温度と出力の自由度の関係
　ソフトマックス関数の出力が温度（$T$）によって変化します．具体的にプログラムで確認して，そのれがChatGPTの出力にどんな影響があるのかということを見ていきます．

## 温度の変化によるソフトマックス関数の出力の変化
　実際のプログラムと出力は以下のようになります．
　3パターンの$T$で出力を試してみると以下のようにsoftmax関数の出力が変化していることがわかります．


```python
import numpy as np

def softmax(x:np.ndarray, temperature:float) -> list:
    e_x = np.exp(x / temperature - np.max(x / temperature))  # ネガティブ数とオーバーフローを防ぐために、xの最大値を引く
    print()
    # return (e_x / e_x.sum())
    return (e_x / e_x.sum()) * 100

# 使用例
scores = np.array([3.0, 1.0, 0.2])
temperatures = [0.3, 1.0, 1.7]

for t in temperatures:
  output = softmax(scores, t)
  print(f'temperature : {t}', ':', f'{output[0]:.2f}%, {output[1]:.2f}%, {output[2]:.2f}%')
```

**出力**


```bash
temperature : 0.3 : 99.86%, 0.13%, 0.01%
temperature : 1.0 : 83.60%, 11.31%, 5.08%
temperature : 1.7 : 66.62%, 20.54%, 12.83%
```

ここで，出力が温度によって変化することがわかりました．では，このような温度が変化することによってGPTからの出力がなぜ変化するのかということを次は見ていこうと思います．


## softmax関数の出力が変化することによってGPTの出力が変化する理由
　具体的にGPTをはじめとするLLMで考えたときに，

温度$T$が低い時は，モデルは最も確率の高い単語を選ぶことになり，予測が簡単な確定的なテキストを返すようになります．

逆に，温度$T$が高い時は，モデルはさまざまな可能性を探求して，結果として多様なテキストを返すようになります．

|温度|確率分布の様子|生成される単語|理由|
|:-:|:-:|:-:|:-:|
|低い|鋭い|確率的に妥当なもの|高スコアがより強調されて低スコアが抑制される|
|$T=1$|普通|普通|-|
|高い|フラット|創造的|スコアが均一化されて単語の出力確率分布はフラットになる|

要するに，


:::note
$T < 1$の時は，自由度が低くなり，固い文書を返す
$T=1$の時は，通常のSoftmax関数と同じ
$T > 1$の時は，自由度が高くなり，創造的な文書を返す
:::

ということ．

# 最後に
　ふとした雑談の中から，モヤモヤが解決して良い日でした．
　記事を書きながら知ったことなのですが，記事にされている方がすでにいました．
　下記も参考にどうぞ．

https://qiita.com/suzuki_sh/items/8e449d231bb2f09a510c#レベル3-なぜtemperatureというのかを調べる