[POSITIVE PROMPT]
日本アニメ風 3Dトゥーンキャラクター, セルシェード(Toon), アウトラインあり, ノイズなし, AO軽め,
日本式ライティング(キー+フィル+バック), ソフトなリムライト,
肌: 滑らか, 影弱め, 毛穴なし, ハイライト控えめ,
髪: 2段影のアニメ調, 低色数, つや控えめ,
女子高生, 6.5頭身, 大きい瞳, 滑らかな輪郭, 小鼻, 弱いリップ光,
正面, 全身, リラックスしたニュートラルポーズ, 手指の破綻なし(指5本・関節正常),
制服: ブレザー+リボン+プリーツスカート, ソックス, 上履き,
小物: シンプルな通学カバン(控えめ), 背景: 白または単色パステル,
カメラ: 35mm, 弱いDOF, 画面中央に全身が収まる, 破綻や法線崩れなし
[NEGATIVE PROMPT]
フォトリアル, ピクサー調, 海外CG風, PBR, 金属光沢, 強いスペキュラ, 肌の毛穴, シミ, 汚れ,
指の増減, 指欠け, 余分な手足, 関節破綻, 手の崩れ, 目の歪み, 顔の崩れ, 低解像, ぼけ, ノイズ, 粒状感,
過度なAO, 影が硬すぎ, 服のシワ過多(写実), テキスト, 透かし, ロゴ,
特定作品・特定キャラに似せる, 著作物の固有要素, 露出過多, 性的表現
[RECOMMENDED SETTINGS]
[CONFIG(数値を調整できるテンプレ:SD + LLM)]
※ {} の中だけ差し替えて使う(コピペ前提)
# ===========================
# 0) PRESET(1つ選ぶ)
# ===========================
PRESET = "{STABLE}" # {STABLE} / {BALANCED} / {VARIATION} / {CHAOS}
# ===========================
# A) SD(画像生成)PARAM
# ===========================
WIDTH = {768} # 例: 768 / 896 / 1024
HEIGHT = {1152} # 例: 1152 / 1344 / 1536
SAMPLER = "{DPM++ 2M Karras}" # "DPM++ 2M Karras" / "Euler a" / "DPM++ SDE Karras" / "UniPC"
STEPS = {26} # 目安: 20–36
CFG = {8.0} # 目安: 6.5–11.0
SEED = {123456} # 固定: 任意整数 / ランダム: -1
# img2img(使う場合のみ)
USE_IMG2IMG = "{OFF}" # {OFF} / {ON}
DENOISE = {0.00} # ON時のみ: 0.45–0.85
# Hires / Upscale(使う場合のみ)
USE_HIRES = "{OFF}" # {OFF} / {ON}
HIRES_SCALE = {0.00} # ON時のみ: 1.5–2.0
HIRES_STEPS = {0} # ON時のみ: 8–15
HIRES_DENOISE = {0.00} # ON時のみ: 0.25–0.40
# ネガティブ重み(環境対応時のみ)
NEG_WEIGHT = {1.0} # 目安: 0.8–1.2
# ===========================
# B) LLM(文章生成)PARAM(温度など)
# ===========================
TEMPERATURE = {0.9} # 目安: 0.7–1.6(崩れ狙いは 1.6+)
TOP_P = {0.95} # 目安: 0.85–0.98
TOP_K = {50} # 目安: 30–80(環境が対応する場合)
FREQUENCY_PENALTY = {0.2} # 目安: 0.0–0.6
PRESENCE_PENALTY = {0.1} # 目安: 0.0–0.6
MAX_TOKENS = {1200} # 目安: 600–2000
LLM_SEED = {123456} # 固定: 任意整数 / ランダム: -1
# ===========================
# 9) PRESETごとの推奨値(コピペして反映)
# ===========================
# {STABLE}(安定・破綻しにくい)
# SD: WIDTH=768, HEIGHT=1152, SAMPLER="DPM++ 2M Karras", STEPS=28, CFG=8.5, SEED=123456
# USE_IMG2IMG="OFF", DENOISE=0.00
# USE_HIRES="OFF", HIRES_SCALE=0.00, HIRES_STEPS=0, HIRES_DENOISE=0.00
# NEG_WEIGHT=1.1
# LLM: TEMPERATURE=0.7, TOP_P=0.92, TOP_K=40, FREQUENCY_PENALTY=0.3, PRESENCE_PENALTY=0.1, MAX_TOKENS=900, LLM_SEED=123456
# {BALANCED}(標準)
# SD: WIDTH=768, HEIGHT=1152, SAMPLER="DPM++ 2M Karras", STEPS=26, CFG=8.0, SEED=123456
# USE_IMG2IMG="OFF", DENOISE=0.00
# USE_HIRES="OFF", HIRES_SCALE=0.00, HIRES_STEPS=0, HIRES_DENOISE=0.00
# NEG_WEIGHT=1.0
# LLM: TEMPERATURE=0.9, TOP_P=0.95, TOP_K=50, FREQUENCY_PENALTY=0.2, PRESENCE_PENALTY=0.1, MAX_TOKENS=1200, LLM_SEED=123456
# {VARIATION}(揺らぎ・少し尖る)
# SD: WIDTH=768, HEIGHT=1152, SAMPLER="Euler a", STEPS=24, CFG=7.0, SEED=123456
# USE_IMG2IMG="OFF", DENOISE=0.00
# USE_HIRES="OFF", HIRES_SCALE=0.00, HIRES_STEPS=0, HIRES_DENOISE=0.00
# NEG_WEIGHT=0.9
# LLM: TEMPERATURE=1.2, TOP_P=0.92, TOP_K=40, FREQUENCY_PENALTY=0.2, PRESENCE_PENALTY=0.3, MAX_TOKENS=1400, LLM_SEED=123456
# {CHAOS}(崩れ狙い・破綻リスク高)
# SD: WIDTH=768, HEIGHT=1152, SAMPLER="DPM++ SDE Karras", STEPS=20, CFG=5.5, SEED=-1
# USE_IMG2IMG="OFF", DENOISE=0.00
# USE_HIRES="OFF", HIRES_SCALE=0.00, HIRES_STEPS=0, HIRES_DENOISE=0.00
# NEG_WEIGHT=0.8
# LLM: TEMPERATURE=1.6, TOP_P=0.88, TOP_K=30, FREQUENCY_PENALTY=0.1, PRESENCE_PENALTY=0.5, MAX_TOKENS=1600, LLM_SEED=-1
Temperature / TEMPERATURE(LLM)
確率分布 P(token | context) を「平坦化/尖鋭化」する係数。
プレーンテキストで書くと:
- 元の分布: p_i = softmax(z_i) = exp(z_i) / Σ_j exp(z_j)
- 温度T適用: p_i(T) = softmax(z_i / T) = exp(z_i / T) / Σ_j exp(z_j / T)
意味:
- T < 1 → 分布が尖る → 上位候補を選びやすい(安定)
- T > 1 → 分布が平坦 → 低確率候補も選ばれやすい(多様・破綻増)
Top-p / TOP_P(LLM)
温度でできた分布 p_i(T) を「上位から足し上げて p になるまで」に制限してサンプルする手法。
プレーンテキスト:
- 確率を降順に並べる: p_(1) ≥ p_(2) ≥ ...
- 最小の集合 S を作る: Σ_{i in S} p_(i) ≥ p_target
- S の中で再正規化してサンプル: p'i = p_i / Σ{j in S} p_j (i in S)
意味:
- p_target を下げる → 候補集合が小さくなる → “尖る/安定寄り”
- temperature 高め + top_p 低め → 候補を絞った上で揺らすので「尖った狂気」になりやすい
Top-k / TOP_K(LLM)
確率上位k個のみに候補を固定する(核サンプリングの“個数版”)。
プレーンテキスト:
- 上位k個の集合 K を取る
- K 内で再正規化: p'i = p_i / Σ{j in K} p_j (i in K)
- p' でサンプル
意味:
- k 小 → 候補が少ない → 安定
- k 大 → 候補が多い → 多様
Frequency penalty / FREQUENCY_PENALTY(LLM)
「同じトークンを繰り返したら、そのトークンのスコアを下げる」補正。実装はモデル/提供APIで差があるが、典型はログイット z_i を減点する形。
プレーンテキスト例(代表形):
- z_i' = z_i - α * count_i
ここで count_i はこれまでに出たトークンiの出現回数、α が frequency_penalty。
意味:
- α ↑ → 反復が減る
- ただし α を上げすぎると不自然な言い換えが増える
Presence penalty / PRESENCE_PENALTY(LLM)
「一度でも出たトークンを、再度出しにくくする」補正(回数ではなく出現有無)。
プレーンテキスト例:
- z_i' = z_i - β * I(count_i > 0)
I( ) は条件が真なら1、偽なら0。β が presence_penalty。
意味:
- β ↑ → “すでに出た語”が出にくくなり、新しい話題へ逸れやすい
Max tokens / MAX_TOKENS(LLM)
生成長の上限 N_max。単純に「N_maxトークン生成したら停止」。
プレーンテキスト:
- 出力長 N_out ≤ N_max
Seed / LLM_SEED(LLM)
乱数生成器の初期値。サンプリングは乱数 u ~ Uniform(0,1) を使うので、seed固定で u の列が固定され、同条件で再現しやすい。
プレーンテキスト:
- RNG(seed) → u_1, u_2, ...
WIDTH / HEIGHT(SD)
画像のピクセルサイズ。計算量は概ねピクセル数に比例する。
プレーンテキスト:
- pixels = WIDTH * HEIGHT
- 計算負荷 ~ O(pixels * STEPS)
Sampler / SAMPLER(SD)
拡散モデルの「逆拡散」数値解法(サンプラー)。
概念式(拡散過程)をプレーンテキストで:
- 前向き拡散: x_t = sqrt(alpha_t) * x_0 + sqrt(1 - alpha_t) * ε, ε ~ N(0, I)
逆過程は「ノイズ ε を予測して x_{t-1} を更新」を繰り返す。
サンプラー差は、この更新式(数値積分法・ノイズ注入方式・スケジューラ)にある。
Steps / STEPS(SD)
逆拡散の反復回数 N_steps。
プレーンテキスト:
- t = T, T-1, ..., 1 を N_steps 段に離散化して更新
意味:
- N_steps ↑ → 収束が進み、細部が整いやすい(ただし過剰だと“整いすぎ”になりやすい)
CFG Scale / CFG(SD)
Classifier-Free Guidance。条件付き予測と無条件予測を混ぜて「プロンプト方向」に強く引く。
プレーンテキスト(代表式):
- ε_guided = ε_uncond + s * (ε_cond - ε_uncond)
ここで s が CFG Scale。
意味:
- s ↑ → cond(プロンプト)方向の差分を強調 → 指示に忠実
- s ↓ → 自由度↑(ただし崩れやすい)
Seed / SEED(SD)
初期ノイズ x_T の生成を固定する。
プレーンテキスト:
- x_T ~ N(0, I) を RNG(seed) で生成
seed固定で構図・雰囲気が揃いやすい。
USE_IMG2IMG(SD)
初期状態を「純ノイズ」ではなく「元画像にノイズを載せたもの」にするモード。
概念式(Strengthの説明に直結):
- x_t = sqrt(alpha_t) * x_0 + sqrt(1 - alpha_t) * ε
ここで x_0 が元画像(潜在)。どの t から逆拡散を始めるかで変化量が決まる。
Denoising Strength / DENOISE(SD・img2img)
「どの時刻 t_start から逆拡散を始めるか」を決める係数(実装は線形対応が多い)。
プレーンテキスト(典型):
- t_start = round(DENOISE * T)
意味:
- DENOISE 小 → t_start 小 → ノイズ少 → 元画像を保持
- DENOISE 大 → t_start 大 → ノイズ多 → 別物に寄る
USE_HIRES / HIRES_*(SD)
2段階生成。低解像で一旦作ってから高解像で再生成(img2img的に再ノイズ→再復元)。
プレーンテキストの見方:
- 第1段: (W,H) で生成
- 第2段: (kW,kH) に拡大し、DENOISE_hires で再拡散→再復元
NEG_WEIGHT(SD)
ネガティブプロンプトの重み付け(対応UIのみ)。多くは「条件ベクトル」の合成係数として効く。
概念的には:
- cond = w_pos * cond_pos - w_neg * cond_neg
のような形で “避けたい方向” を押し返す。UIで実装差が大きく、非対応なら無視される。
PRESET(運用意図)
上の式のどの項を強くするかの組み合わせ最適化。
- STABLE:CFGやStepsを上げ、seed固定で分布の揺らぎを減らす(安定方向)
- VARIATION:CFGを下げたりEuler a等で更新を荒くし、揺らぎを増やす
- CHAOS:CFG↓、Steps↓、seed=-1、SDE系でノイズ注入が強い更新を選ぶ(破綻方向)
注意
SD側の「temperature / top_p / top_k」は通常のStable Diffusion実装には基本的に存在しない(LLMのサンプリング用)。SDで“揺らぎ”を作る主レバーは CFG、Steps、Sampler、Seed、Denoise(img2img)になる。
# Program Name: llm_sampling_params_demo_colab.py
# Creation Date: 20260124
# Purpose: Interactive simulation of LLM sampling params (Temperature/Top-p/Top-k/Penalties) + toy CFG (Colab-ready)
# ============================================================
# 0) Install (Colab) / インストール(Colab)
# ============================================================
try:
import sys, subprocess
def _pip(cmd: str):
subprocess.check_call([sys.executable, "-m", "pip", "-q", "install"] + cmd.split())
# ipywidgets + numba (version-pinned) / 版固定
_pip("ipywidgets==8.1.1 numba==0.59.1")
except Exception as e:
raise RuntimeError(f"pip install failed: {e}")
# Colab widget manager (needed in some runtimes) / Colabで必要な場合あり
try:
from google.colab import output as colab_output
colab_output.enable_custom_widget_manager()
except Exception:
pass
# ============================================================
# 1) Imports / インポート
# ============================================================
import numpy as np
import matplotlib.pyplot as plt
import datetime
from ipywidgets import (
FloatSlider, IntSlider, Dropdown, Checkbox, Button, HBox, VBox, Output, Label, Layout
)
from numba import njit
# ============================================================
# 2) PARAM_INIT(設定一元管理) / Centralized parameters
# ============================================================
PARAM_INIT = dict(
# Synthetic logits / 擬似ロジット
vocab_size=200, # pseudo vocab size / 擬似語彙数
sharpness=1.2, # ranking slope / ランク傾斜
base_noise=0.15, # logits noise / ロジット雑音
# LLM sampling / LLMサンプリング
temperature=0.9, # T
top_p=0.95, # nucleus p
top_k=50, # top-k
use_top_p=True,
use_top_k=False,
frequency_penalty=0.2, # alpha
presence_penalty=0.1, # beta
# Sampling simulation / サンプリングシミュレーション
sample_n=5000, # Monte Carlo samples
seed=123456, # -1 => random
# Display / 表示
plot_mode="Probabilities",
# SD-like toy (CFG) / SD風(玩具)
cfg_scale=8.0,
)
# ============================================================
# 3) Math core (vectorized + Numba) / 数学コア(ベクトル化+Numba)
# ============================================================
def _stable_softmax(x: np.ndarray) -> np.ndarray:
# Numerical stability / 数値安定化
x = x - np.max(x)
ex = np.exp(x)
s = np.sum(ex)
return ex / s
def softmax_with_temperature(logits: np.ndarray, T: float) -> np.ndarray:
"""
Inputs:
logits: shape (V,)
T: temperature (>0)
Outputs:
p: probabilities shape (V,)
Process:
p_i(T) = softmax(z_i / T)
"""
T = max(1e-6, float(T))
return _stable_softmax(logits / T)
def apply_penalties(logits: np.ndarray, counts: np.ndarray, freq_pen: float, pres_pen: float) -> np.ndarray:
"""
Inputs:
logits: z_i
counts: count_i
Outputs:
adjusted logits: z'_i
Process (typical):
z'_i = z_i - alpha*count_i - beta*I(count_i>0)
"""
z = logits.copy()
alpha = float(freq_pen)
beta = float(pres_pen)
if alpha != 0.0:
z = z - alpha * counts
if beta != 0.0:
z = z - beta * (counts > 0).astype(np.float64)
return z
def nucleus_mask(p: np.ndarray, top_p: float) -> np.ndarray:
# Smallest set S with cumulative prob >= top_p / 累積top_pまでの最小集合
tp = float(np.clip(top_p, 0.0, 1.0))
idx = np.argsort(p)[::-1]
cum = np.cumsum(p[idx])
cut = int(np.searchsorted(cum, tp, side="left"))
keep = idx[:max(1, cut + 1)]
m = np.zeros_like(p, dtype=bool)
m[keep] = True
return m
def topk_mask(p: np.ndarray, k: int) -> np.ndarray:
kk = int(max(1, k))
idx = np.argsort(p)[::-1][:kk]
m = np.zeros_like(p, dtype=bool)
m[idx] = True
return m
def renorm(p: np.ndarray, mask: np.ndarray) -> np.ndarray:
q = p.copy()
q[~mask] = 0.0
s = float(q.sum())
if s <= 0.0:
q[:] = 0.0
q[int(np.argmax(p))] = 1.0
return q
return q / s
@njit(cache=False)
def sample_categorical_numba(p: np.ndarray, n: int, seed: int) -> np.ndarray:
"""
Inputs:
p: probability vector (V,)
n: number of samples
seed: RNG seed
Outputs:
sampled indices (n,)
Process:
Inverse-CDF sampling with LCG RNG (reproducible).
"""
V = p.shape[0]
cdf = np.empty(V, dtype=np.float64)
s = 0.0
for i in range(V):
s += p[i]
cdf[i] = s
out = np.empty(n, dtype=np.int32)
# LCG
a = 1664525
c = 1013904223
m = 2**32
state = np.uint32(seed)
for t in range(n):
state = np.uint32((a * state + c) % m)
u = (state.astype(np.float64) + 1.0) / (m + 1.0) # (0,1)
lo = 0
hi = V - 1
while lo < hi:
mid = (lo + hi) // 2
if cdf[mid] >= u:
hi = mid
else:
lo = mid + 1
out[t] = lo
return out
def entropy_nats(p: np.ndarray) -> float:
q = p[p > 0]
return float(-(q * np.log(q)).sum())
# ============================================================
# 4) Synthetic logits / 擬似ロジット生成
# ============================================================
def make_synthetic_logits(V: int, sharpness: float, noise: float, seed: int) -> np.ndarray:
rng = np.random.default_rng(int(seed))
r = np.arange(V, dtype=np.float64)
base = -np.log1p(r) * float(sharpness) # decreasing curve
base = base - base.mean()
eps = rng.normal(0.0, float(noise), size=V)
return base + eps
# ============================================================
# 5) Toy CFG (SD-like) / CFG玩具モデル
# ============================================================
def cfg_guidance(eps_uncond: np.ndarray, eps_cond: np.ndarray, s: float) -> np.ndarray:
# eps_guided = eps_uncond + s*(eps_cond - eps_uncond)
return eps_uncond + float(s) * (eps_cond - eps_uncond)
# ============================================================
# 6) UI (入力→計算→出力) / UI
# ============================================================
out = Output()
slider_layout = Layout(width="360px")
# --- Synthetic logits controls / 擬似ロジット ---
w_vocab = IntSlider(value=PARAM_INIT["vocab_size"], min=50, max=2000, step=10, description="Vocab", layout=slider_layout)
w_sharp = FloatSlider(value=PARAM_INIT["sharpness"], min=0.2, max=3.0, step=0.05, description="Sharp", layout=slider_layout)
w_noise = FloatSlider(value=PARAM_INIT["base_noise"], min=0.0, max=1.0, step=0.02, description="Noise", layout=slider_layout)
# --- LLM sampling controls / LLMサンプリング ---
w_T = FloatSlider(value=PARAM_INIT["temperature"], min=0.2, max=2.5, step=0.05, description="Temp", layout=slider_layout)
w_top_p = FloatSlider(value=PARAM_INIT["top_p"], min=0.50, max=1.00, step=0.01, description="Top-p", layout=slider_layout)
w_top_k = IntSlider(value=PARAM_INIT["top_k"], min=1, max=500, step=1, description="Top-k", layout=slider_layout)
w_use_p = Checkbox(value=PARAM_INIT["use_top_p"], description="Use top-p")
w_use_k = Checkbox(value=PARAM_INIT["use_top_k"], description="Use top-k")
w_freq = FloatSlider(value=PARAM_INIT["frequency_penalty"], min=0.0, max=1.0, step=0.05, description="FreqPen", layout=slider_layout)
w_pres = FloatSlider(value=PARAM_INIT["presence_penalty"], min=0.0, max=1.0, step=0.05, description="PresPen", layout=slider_layout)
# --- Simulation controls / シミュレーション ---
w_n = IntSlider(value=PARAM_INIT["sample_n"], min=500, max=50000, step=500, description="Samples", layout=slider_layout)
w_seed = IntSlider(value=PARAM_INIT["seed"], min=-1, max=2_000_000_000, step=1, description="Seed", layout=slider_layout)
# --- SD-like toy / SD風玩具 ---
w_cfg = FloatSlider(value=PARAM_INIT["cfg_scale"], min=0.0, max=15.0, step=0.25, description="CFG", layout=slider_layout)
# --- Plot mode / 表示 ---
w_mode = Dropdown(
options=[
"Probabilities",
"Samples Histogram",
"Candidate Set Size",
"Toy CFG Effect",
"Penalty Demo (multi-step)"
],
value=PARAM_INIT["plot_mode"],
description="Plot",
layout=Layout(width="460px")
)
# --- Buttons / ボタン ---
btn_run = Button(description="Run / Update", button_style="primary")
btn_reset = Button(description="Reset")
btn_save_png = Button(description="Save PNG")
btn_save_pdf = Button(description="Save PDF")
def _current_seed() -> int:
# Seed=-1 => random / -1ならランダム
if int(w_seed.value) == -1:
return int(datetime.datetime.now().timestamp() * 1e6) % 2_000_000_000
return int(w_seed.value)
def _save_figure(path: str, as_pdf: bool):
if as_pdf:
plt.savefig(path, format="pdf")
else:
plt.savefig(path, format="png", dpi=220)
def compute_and_plot(savepath: str = None, save_pdf: bool = False):
with out:
out.clear_output(wait=True)
try:
seed = _current_seed()
V = int(w_vocab.value)
# 1) Synthetic logits / 擬似ロジット
z0 = make_synthetic_logits(V, w_sharp.value, w_noise.value, seed)
mode = w_mode.value
# ====================================================
# Mode A: single-step distribution + sampling / 単発
# ====================================================
if mode in ["Probabilities", "Samples Histogram", "Candidate Set Size"]:
counts = np.zeros(V, dtype=np.float64) # no history / 履歴なし
# penalties -> temperature / ペナルティ→温度
z = apply_penalties(z0, counts, w_freq.value, w_pres.value)
pT = softmax_with_temperature(z, w_T.value)
# top-p/top-k / top-p/top-k
mask = np.ones(V, dtype=bool)
if bool(w_use_p.value):
mask &= nucleus_mask(pT, w_top_p.value)
if bool(w_use_k.value):
mask &= topk_mask(pT, int(w_top_k.value))
p = renorm(pT, mask)
# sampling / サンプリング
n = int(w_n.value)
samp = sample_categorical_numba(p.astype(np.float64), n, seed)
# metrics / 指標
H = entropy_nats(p)
eff = int(mask.sum())
top1 = int(np.argmax(p))
top1p = float(p[top1])
# plot / 描画
plt.figure(figsize=(10, 5))
if mode == "Probabilities":
idx = np.argsort(p)[::-1][:40]
plt.bar(np.arange(idx.size), p[idx])
plt.xticks(np.arange(idx.size), idx, rotation=90)
plt.title("Top Probabilities (after Temperature + Constraints)")
plt.xlabel("Token index (sorted)")
plt.ylabel("Probability")
elif mode == "Samples Histogram":
c = np.bincount(samp, minlength=V)
idx = np.argsort(c)[::-1][:60]
plt.bar(np.arange(idx.size), c[idx] / c.sum())
plt.xticks(np.arange(idx.size), idx, rotation=90)
plt.title("Sample Frequency (Monte Carlo)")
plt.xlabel("Token index (sorted)")
plt.ylabel("Frequency")
elif mode == "Candidate Set Size":
nuc = nucleus_mask(pT, w_top_p.value)
km = topk_mask(pT, int(w_top_k.value))
comb = mask
sizes = [int(nuc.sum()), int(km.sum()), int(comb.sum())]
labels = ["Top-p set", "Top-k set", "Combined"]
plt.bar(labels, sizes)
plt.title("Candidate Set Size")
plt.xlabel("Constraint type")
plt.ylabel("Count")
plt.tight_layout()
if savepath:
_save_figure(savepath, save_pdf)
plt.show()
print("------------------------------------------------------------")
print("Key Stats")
print("------------------------------------------------------------")
print(f"Seed: {seed}")
print(f"Entropy H(p): {H:.3f} nats (lower => more peaked)")
print(f"Candidate set size: {eff} / {V}")
print(f"Top-1 token: {top1}, p={top1p:.4f}")
print("LLM Params:")
print(f" Temperature={w_T.value:.2f}")
print(f" Top-p={w_top_p.value:.2f} (use={w_use_p.value})")
print(f" Top-k={int(w_top_k.value)} (use={w_use_k.value})")
print(f" Frequency penalty={w_freq.value:.2f}, Presence penalty={w_pres.value:.2f}")
print(f" Samples={n}")
print("------------------------------------------------------------")
if savepath:
print(f"Saved: {savepath}")
# ====================================================
# Mode B: Toy CFG / CFG玩具
# ====================================================
elif mode == "Toy CFG Effect":
rng = np.random.default_rng(seed)
eps_un = rng.normal(0, 1, size=256)
eps_co = eps_un + rng.normal(0, 0.3, size=256) # correlated
eps_g = cfg_guidance(eps_un, eps_co, w_cfg.value)
n_un = float(np.linalg.norm(eps_un))
n_co = float(np.linalg.norm(eps_co))
n_g = float(np.linalg.norm(eps_g))
plt.figure(figsize=(10, 5))
plt.plot(eps_un[:80], label=f"eps_uncond (norm={n_un:.1f})")
plt.plot(eps_co[:80], label=f"eps_cond (norm={n_co:.1f})")
plt.plot(eps_g[:80], label=f"eps_guided (norm={n_g:.1f})")
plt.title("Toy CFG: eps_guided = eps_uncond + s*(eps_cond - eps_uncond)")
plt.xlabel("Index")
plt.ylabel("Value")
plt.legend()
plt.tight_layout()
if savepath:
_save_figure(savepath, save_pdf)
plt.show()
print("------------------------------------------------------------")
print("Toy CFG Stats")
print("------------------------------------------------------------")
print(f"Seed: {seed}")
print(f"CFG scale s: {w_cfg.value:.2f}")
print(f"norm(eps_uncond) = {n_un:.3f}")
print(f"norm(eps_cond) = {n_co:.3f}")
print(f"norm(eps_guided) = {n_g:.3f}")
print("------------------------------------------------------------")
if savepath:
print(f"Saved: {savepath}")
# ====================================================
# Mode C: Penalty demo (multi-step generation) / 反復生成でペナルティを見る
# ====================================================
elif mode == "Penalty Demo (multi-step)":
# This simulates "token-by-token" generation with penalties.
# ここで count_i が増える → logitsが抑制される様子を見る。
steps_gen = 80 # generation steps / 生成ステップ(固定)
counts = np.zeros(V, dtype=np.float64)
chosen = np.zeros(steps_gen, dtype=np.int32)
ent = np.zeros(steps_gen, dtype=np.float64)
top1p = np.zeros(steps_gen, dtype=np.float64)
seed_local = seed
for t in range(steps_gen):
z = apply_penalties(z0, counts, w_freq.value, w_pres.value)
pT = softmax_with_temperature(z, w_T.value)
mask = np.ones(V, dtype=bool)
if bool(w_use_p.value):
mask &= nucleus_mask(pT, w_top_p.value)
if bool(w_use_k.value):
mask &= topk_mask(pT, int(w_top_k.value))
p = renorm(pT, mask)
# sample one token / 1トークン生成
idx = sample_categorical_numba(p.astype(np.float64), 1, seed_local)[0]
seed_local = (seed_local + 1) % 2_000_000_000 # deterministic drift / 再現性のある変化
chosen[t] = idx
counts[idx] += 1.0
ent[t] = entropy_nats(p)
top1p[t] = float(np.max(p))
# Plot: entropy + top1 probability / エントロピーとtop1確率
plt.figure(figsize=(10, 5))
plt.plot(ent, label="Entropy H(p)")
plt.plot(top1p, label="Top-1 probability")
plt.title("Penalty Demo (multi-step): how distribution changes over time")
plt.xlabel("Generation step")
plt.ylabel("Value")
plt.legend()
plt.tight_layout()
if savepath:
_save_figure(savepath, save_pdf)
plt.show()
# Show most repeated tokens / よく出たトークン
c = np.bincount(chosen, minlength=V)
idx = np.argsort(c)[::-1][:15]
print("------------------------------------------------------------")
print("Penalty Demo Summary")
print("------------------------------------------------------------")
print(f"Seed: {seed}")
print(f"Gen steps: {steps_gen}")
print(f"Temperature={w_T.value:.2f}, Top-p(use={w_use_p.value})={w_top_p.value:.2f}, Top-k(use={w_use_k.value})={int(w_top_k.value)}")
print(f"Frequency penalty={w_freq.value:.2f}, Presence penalty={w_pres.value:.2f}")
print("Most frequent tokens (token_id: count):")
for k in idx:
if c[k] == 0:
break
print(f" {int(k)}: {int(c[k])}")
print("------------------------------------------------------------")
if savepath:
print(f"Saved: {savepath}")
else:
raise ValueError(f"Unknown mode: {mode}")
except Exception as e:
print(f"[ERROR] {e}")
def on_run(_):
compute_and_plot()
def on_reset(_):
# Reset all widgets / 初期化
w_vocab.value = PARAM_INIT["vocab_size"]
w_sharp.value = PARAM_INIT["sharpness"]
w_noise.value = PARAM_INIT["base_noise"]
w_T.value = PARAM_INIT["temperature"]
w_top_p.value = PARAM_INIT["top_p"]
w_top_k.value = PARAM_INIT["top_k"]
w_use_p.value = PARAM_INIT["use_top_p"]
w_use_k.value = PARAM_INIT["use_top_k"]
w_freq.value = PARAM_INIT["frequency_penalty"]
w_pres.value = PARAM_INIT["presence_penalty"]
w_n.value = PARAM_INIT["sample_n"]
w_seed.value = PARAM_INIT["seed"]
w_cfg.value = PARAM_INIT["cfg_scale"]
w_mode.value = PARAM_INIT["plot_mode"]
compute_and_plot()
def on_save_png(_):
ts = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
fname = f"sim_sampling_{w_mode.value.replace(' ','_')}_T{w_T.value:.2f}_p{w_top_p.value:.2f}_k{int(w_top_k.value)}_{ts}.png"
compute_and_plot(savepath=fname, save_pdf=False)
def on_save_pdf(_):
ts = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
fname = f"sim_sampling_{w_mode.value.replace(' ','_')}_T{w_T.value:.2f}_p{w_top_p.value:.2f}_k{int(w_top_k.value)}_{ts}.pdf"
compute_and_plot(savepath=fname, save_pdf=True)
btn_run.on_click(on_run)
btn_reset.on_click(on_reset)
btn_save_png.on_click(on_save_png)
btn_save_pdf.on_click(on_save_pdf)
ui_left = VBox([
Label("LLM Sampling Controls"),
w_T, w_top_p, HBox([w_use_p, w_use_k]),
w_top_k, w_freq, w_pres,
Label("Synthetic logits"),
w_vocab, w_sharp, w_noise,
], layout=Layout(width="520px"))
ui_right = VBox([
Label("Run & Output"),
w_mode,
w_n, w_seed,
Label("SD-like (toy)"),
w_cfg,
HBox([btn_run, btn_reset]),
HBox([btn_save_png, btn_save_pdf]),
], layout=Layout(width="520px"))
display(HBox([ui_left, ui_right]))
display(out)
# Initial run / 初回実行
compute_and_plot()