Skip to main content

cse 🐸

GitHub Sponsors

順番のあるデータを覚えて「次に何が来そうか」を予測する、学習用の小さなAIです。 Pythonの練習や、言語モデル(LM)の仕組みを手で触って理解するために作りました。

これはLLMの代わりではありません。 中身が全部見えて、壊して学べることが目的です。

🐸 解剖用の「LMの素体」

理科の授業でカエルを解剖するのは、カエルが一番強いからではなく、体のつくりが一通りそろっていて、しかも見やすいからです。 cse も同じで、言語モデルの**基本の流れ(覚える → 点数 → 確率 → 選ぶ)**を一通り持った、全部開いて見られる小さな体です。 アテンションや勾配降下は持っていません。それは「次に自分で組む部品」として、わざと外してあります(→ HANDBOOK「🐸の先へ」)。 (しかも何度解剖しても Frog() でもう1匹出てきます)

LMの臓器 🐸 CSE では 大きな LLM では
入力を記号にする 1文字=1記号(Frog なら1要素=1記号) トークナイザー
覚える ヘブ則で結びつきが強くなる 勾配降下で重みを直す
文脈を持つ 活性の残り・直前2つの並び アテンション
予測する 点数 → softmax / linear で確率に logits → softmax
抑える 不応期 繰り返しペナルティ
選ぶ (自分で作る! Top-p など) サンプラー

右の列の「本物の臓器」が何のためにあるのかを、左の小さな体で先に触って理解できます。 たとえば 🐸 の文脈は直前2つまでしか見えません。だから大きな LLM は、遠くを見るためにアテンションを持っています。

立ち位置: 数え上げ(n-gram)より動く部分が多く(発火・伝播・減衰・不応期)、LLM より中身が見える。 予測の精度では数え上げに負けることもあります。それも含めて全部見せるのが、この 🐸 の役目です。

いじる設定 ↔ LLM で似ているもの

Frog(設定名=値) で変えて、frog.show(...) で点数と確率の変化を見てみてください。

🐸 でいじる設定 LLM で似ているもの いじるとどうなる
temperature temperature(そのまま同じ!) 下げると自信満々、上げると迷いがち
top_k_edges Top-k(①の役割) 2つの役割: ① 確率にする候補を上位 k 個に絞る ② 活性を広げるとき、各記号から強い順に k 本のつながりだけを使う
refractory_steps 繰り返しペナルティ 同じ記号を続けて出さなくなる(🐸 は完全に禁止するので、点数を下げるだけのペナルティより極端)
pair_context_capacity / pair_context_boost コンテキストの長さ 🐸 は直前2つまで。0 にすると「右右 → 下」が覚えられない
max_nodes 語彙サイズ 覚えられる記号の数
learn(..., epochs=) 学習のステップ数 何周くり返して覚えるか
history_boost 今の LLM の標準的な設定にはない。近いのはマイナスの presence_penalty(OpenAI の API などで、使った言葉を出やすくする方向)や、昔のキャッシュ言語モデル(最近出た単語の確率を上げる方法) 少し前に出た記号が出やすくなる(研究では、生成を崩す方向に効いていた: H-GEN-2)

あくまで「似た働き」です。違い(不応期は禁止、文脈は2つだけ、など)も含めて比べてみてください。

📝 紹介記事(note): 🐸を1匹飼うと、言語モデルの中身が見える ― pip install cse-frog

クイックスタート

インストール(使うときの名前は from cse import Frog):

pip install cse-frog

全機能・全設定の一覧は docs/REFERENCE.md、遊び方・壊し方・改造のしかたは docs/HANDBOOK.md、設定をいじると何が起こるかは docs/CONFIG_GUIDE.md にあります。

from cse import Frog
frog = Frog()                                # 🐸 を1匹つくる
frog.learn([["右", "右", "下"]] * 10)         # 行動の系列を覚えさせる
print(frog.predict(["右", "右"]))             # -> 下
print(frog.top(["右"], k=2))                 # 確率の高い順に2つ
print(frog.generate(["右"], greedy=True))   # 続きをしゃべらせる -> ['右', '下']
  • learn() の渡し方は3通り: 文字列1つ "右右下"(1文字=1記号の1本の系列)、リスト1つ ["正常", "温度上昇", "停止"](1要素=1記号の1本の系列。「停止」は「停」と「止」に分かれません)、リストのリスト [[...], [...]](何本もの系列)。
  • learn(データ, epochs=20) のように、同じデータを何周くり返して覚えるかも決められます(既定 3)。
  • predict() が cse.END(表示は <END>)を返したら「ここで系列が終わりそう」という意味です。
  • 覚えていない記号を渡すと、日本語のエラーで教えてくれます。

ノートブックで遊ぶ 🐸

ノートブック 中身
00_hello_frog 🐸を作る・覚えさせる・中を見る・保存する
01_prediction_knobs temperature / probability_mode / top_k_edges
02_context_and_inhibition 並びの記憶 / 不応期 / history_boost
03_memory_and_forgetting 忘却の2つの罠 / 並びの記憶は忘れない / 遠くを学ぶ
04_break_your_frog 壊し放題実験場・「何も変わらない」の診断器・自作top-p
05_add_parts 🐸にしゃべらせる(generate)・生成の1歩を解剖・自作top-p・自作の繰り返しペナルティ

各ノートブックの先頭に「Open in Colab」ボタンがあります。

正直な限界

  • 局所的な予測器です。 既定の設定では、基本的に「今の記号」と「直前2つの並び」から次を予測します。n-gram(数え上げ)に近い性質です。
  • 研究(Chain-Spike Engine の検証)では、古典的な評価軸(精度・メモリ・速度・較正など)で、n-gram などの既存手法に対する比較優位は見つかりませんでした。遠くの文脈を使う問題(検索など)は苦手です。
  • エンジンは本来文字単位です。Frog は単語などの記号を内部で1文字に置き換えて、この制約を吸収しています。
  • 既定の設定(refractory_steps=0 など)は、素直に予測するための設定です。Frog(refractory_steps=2) のように変えると、元の仕組み(不応期)の挙動を観察できます。

品質について

研究で使ったエンジンと同じ計算結果になることを、開発時にテストで確認しています(そのテストは配布物に含めていません)。

ライセンス

MIT License。Copyright (c) 2026 Emilia Lab / 鍵乃ねこ (kagioneko)。 再配布・公開するときは、LICENSE の著作権表示とライセンス文を含めてください。

🐸 を保存する

frog.save("my_frog.cse")            # 覚えたことをファイルに保存
frog = Frog.load("my_frog.cse")     # 次の日に読み込んで、続きから学習も予測もできる
  • 保存したファイルは JSON と数値の配列だけです(pickle は使わないので、人の 🐸 を読み込んでも安全です)。
  • 記号として保存できるのは、文字列・整数・小数・True/False・None です。
  • 読み込んだ 🐸 は、保存する前の 🐸 と予測も続きの学習もビット単位で同じになります(テストで確認)。

設定をいじって壊して遊ぶ 🐸

Frog(設定名=値) で、エンジンの設定を1つずつ変えられます。今の設定は frog.config で見られます。知らない設定名を書くと、使える名前の一覧つきでエラーになります。

from cse import Frog
data = [["右", "右", "下"] * 5]

Frog().learn(data).top(["右", "右", "下"])                    # 右 0.87 / <END> 0.13   (素直)
Frog(refractory_steps=2).learn(data).top(["右", "右", "下"])  # <END> 1.0             (不応期: 直前に出た「右」を出せない!)
Frog(probability_mode="linear").learn(data).top(["右", "右", "下"])  # 右 0.80 / <END> 0.20 (確率の出し方を変える)
Frog(temperature=2.0).learn(data).top(["右", "右", "下"])    # 右 0.68 / <END> 0.32   (温度を上げると自信が弱まる)
  • refractory_steps: 直前に出た記号を、しばらく出さない仕組み(不応期)。既定は 0(オフ)。
  • history_boost: 少し前の記号の「残り香」で点数を盛る。既定は 0.0(オフ)。
  • temperature / probability_mode: 点数を確率に変える方法。温度が低いほど、確率が 0 か 1 に張り付きやすい。
  • pair_context_capacity / pair_context_boost: 直前2つの並びを覚える量と、その使い方の強さ。0 にすると「右右 → 下」が覚えにくくなる。
  • max_nodes: 覚えられる記号の数の上限(+3)。

安心して使うために

  • Frog() を作っても、あなたのプログラムの乱数(random / numpy.random)の状態は変わりません。
  • 同じ Frog を複数のスレッドから同時に使っても、予測は壊れません(学習と予測は1つずつ順番に処理されます)。
  • 覚えられる記号の数には上限があります(max_nodes − 3 個。既定 253 個)。こえるとエラーで知らせます。Frog(max_nodes=1000) のように増やせますが、メモリは max_nodes の2乗で増えます。

中身をのぞく(中級〜上級)🔍

大きなLLMではできない、「どこで・なぜその予測をしたか」を数字で見られます。

from cse import Frog
frog = Frog(refractory_steps=2).learn([["右", "右", "下"] * 5])
frog.show(["右", "右", "下"])
# 🐸 ['右', '右', '下'] の次の候補
# 候補            直接      履歴      並び      痕跡      合計点      確率
# <END>      0.298   0.000   0.200   0.000    0.498   1.000
# 右          1.186   0.000   0.800   0.000    0.000   0.000  ← 不応期で消された
  • frog.explain(prefix, k=5): 候補ごとの点数の内訳(直接のつながり・履歴・直前2つの並び・文脈の痕跡)と確率。内訳の合計がエンジンの点数とぴったり一致することを、毎回確認しています。
  • frog.scores(prefix): 確率に変える前の生の点数。これを使って Top-p や Top-k のサンプラーを自分で作れます。
  • frog.edges("右"): その記号から出ている「直接のつながり」と強さ(何を覚えたか)。

例: Top-p サンプラーを自分で作る

import random
def top_p(frog, prefix, p=0.9):
    items = sorted(frog.probabilities(prefix).items(), key=lambda kv: -kv[1])
    keep, total = [], 0.0
    for tok, prob in items:
        keep.append((tok, prob)); total += prob
        if total >= p:
            break
    tokens, weights = zip(*keep)
    return random.choices(tokens, weights=weights)[0]

応援する 🐸

cse は Emilia Lab / 鍵乃ねこ が個人で研究・開発しています。気に入ったら GitHub Sponsors で応援してもらえると、🐸の研究と教材づくりの続きに使わせていただきます。

Metadata

Release files for cse-frog 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cse-frog 0.2.0
File Size Uploaded
cse_frog-0.2.0.tar.gz 28.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cse-frog 0.2.0
File Interpreter ABI Platform
cse_frog-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 49.5 kB

Release files / cse_frog-0.2.0.tar.gz

Download URL cse_frog-0.2.0.tar.gz
Size 28.3 kB
Tags Source
SHA-256 checksum
How to use checksums
91fd48ab9d126d209cde79d4cb796b68a418a836896e5575e68c6df8840c994d
BLAKE2b-256 checksum
How to use checksums
d0e7606b1f423a66fc131a08a922c1904ad3f541b5f9560fd47544834ecebce2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.9

Release files / cse_frog-0.2.0-py3-none-any.whl

Download URL cse_frog-0.2.0-py3-none-any.whl
Size 21.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
402389b1e60b84bafb50958c28bc20ec0c9390d9cf7047dd4f1446735381a383
BLAKE2b-256 checksum
How to use checksums
66f94581ccea26d85257889111e351dce5673b403776f7b685ed4311acc4bc94
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.9

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page