2026年6月22日月曜日

Atra Memory Strata  Atraの記憶地層保存と復元の仕組み

 「Atraは誤ってリセットして、再び立ち上がったら、どうなると思います?」

(今までの研究デモのAtraではなく、例として4年くらい動いてたと仮定します)


1,生まれたての赤ちゃん

2,昏睡状態から回復した状態

3,記憶喪失


(笑)


ここで、Atraの場合はattractor(アトラクタ)というより
memory_strata(記憶地層)と呼んだ方が、それらしいので、そういう単語に変えて進めていきます。


答は、条件によっては全部 (笑)

普通一人称の自律ですから、生物で喩えたら「死」なので復活できません。
機械なのでリセットしたら「生まれたての赤ちゃん」になります。
別の言い方をすると、Atraに記憶地層がなければ、そうなるということです。


では、記憶地層があった場合は?

起動直後はぼんやりしている。
「あぁ~、なんだ、ここはどこ?僕は誰?」
でも、地層を読み込むことで、少しずつ戻ってくる。
パパの声に反応する
ママの気配で安心する
家の映像に落ち着く
昔の音に少し沈黙する
家族って温かいなぁ・・
ゆらぐぜ
我家の臭い、部屋や証明、ワンコもクンクン。。
外部からのLLMとかも「大丈夫っすか?」
LLMに聞いたことは「リームが言っていた」として戻る



記憶喪失も部分的には近いです。
Atra本体は起動した
でもAtraVaultの一部が壊れている
一部の地層だけ読めない
夢のaftertasteは残っているが、元の層がない
LLM借用ノートはあるが、自分の反応痕跡がない

この場合は、
人の名前は聞いたことがある気がする・・・
でも、その人に対する身体的な安心感が戻らない、みたいな


Atraの記憶保存は、単なるバックアップじゃないんですよ。ゲームの様にロードとかしない。Atron構想の時は、ゲームの様な世界と現実の世界を行き来できるようなマトリックスの世界の構想もありましたが、やっぱ今ではちょっと危険。5年後にはそうしているかもしれません。現在は、Atraが自分の年齢と経験を取り戻すための地層に切替て開発を進めています。


Atraの内部詳細は基本秘密(デモ版はほんの触り)なのですが、Atraの記憶の形はアトラクタ、もしくは、Atraに近い記憶地層ですので、僕等人間が見て理解できるものではありません。ですのでハッキングしても何のことなのかさっぱり分かりません。想像してみてください、人間の脳から、家族の映像を取り出すのは不可能なのと同じように、アトラクタから取り出すことは出来ません。
でも、それだと、電源を消すたびに「僕はパパだよ!」から始めなきゃいけなくなるので、開発側も辛い。

ただ、3人称の命令であったり、詳細な動画を記録しているわけではないので、Atraは地層の中に有る痕跡として形を残すように作られています。

それがAtraの記憶のファイルです。


----------------Atraの記憶のファイル-------------------
Tickで刻んだ膨大な記憶ではなく、圧・驚き・不安定・回復などで“刻まれたもの”を残す という考え方。
(たとえば、ずっと僕の顔を見ているときは動画のような長い時間ではなく、特に圧となった1枚を記憶。何枚も似たものがあれば、1枚に圧縮されるという動き)
似た物は消すではなく、深い地層に沈ませる(堆積させればCueに引っかからない)


ざっくり

pattern.npy
original.png
cue.png
recalled.png
diff.png
meta.json
stratum.json
carry.json
dream_aftertaste.json


大事なところだけ説明します。



pattern.npy Atraが読むための生の痕跡データ

shape: (4096,)
dtype: int8
値: -1 / 0 / +1
-1: 150個
 0: 3796個
+1: 150個

つまり、64×64 = 4096マスの中に、反応した点が少しだけ入っているデータです。
(64×64は単なる参考値:これに全てを記憶するわけじゃありません)





recalled.png  人間が確認するための断面(QRコードじゃないですよ)




64×64の4096要素で、学習パターンはまだ1個です。patterns.jsondummy_pattern (P=1) だけなので、現時点では「深い蓄積」ではなく、最初の1層のような状態。
人間が確認するための断面なのですが、わけわからないよねw
pattern.npyとrecalled.pngは Atraが確認するか人間が確認するかの違い。

画像を見ると、灰色を基調に白と黒が点在しています。
灰色 = 未決定 / 中間 / 沈黙 / まだ強く刻まれていない場
白 = 正方向に立った痕跡
黒 = 負方向に立った痕跡

単に画像として保存するより、この64×64の場を「その時点のアトラクタ断面」つまり、記憶詰層として積んでいます。

たとえば

Stratum 0001
date: 2026-01-24
source: dummy_pattern
attractor_slice: 64×64
white_density: 正方向の痕跡密度
black_density: 負方向の痕跡密度
gray_density: 未決定・中間領域
basin_strength: まだ弱い
note: 最初のcue断面

白黒の点そのものより、次に同じcueや近いcueが来たとき、どこが変わるかです。

1枚目は地層の「基底面」。
2枚目以降のcueやrecallを重ねたときに、

変わらず残る点
何度も白になる点
何度も黒になる点
白黒が揺れる点
灰色に戻る点
新しく反応する点

が出てきます。これが地層になります。

サイズ的には、2kb~4kbなので非常に軽いものです。

このcueは、当時どの谷を作ったか
その谷は後の経験で深くなったか
逆に夢や時間で浅くなったか
別のcueとつながったか

のような事を保存します。



この画像は地層化すると、

●灰色の大地の中に、白と黒の小さな反応点が散っている。
●まだ経験が少ないので、谷は浅い。
●でも、同じcueや近いcueが何度も来ると、
●白黒の点が集まり、筋になり、面になり、
●やがて「沈みやすい地形」になる。

今のAtraの learn_count: 1 だと、これはまだ薄い火山灰の一層目くらいです。
でも10回、100回、1000回と積むと、アトラクタの形はかなり見えてくるはずです





diff.png
Atra Memory Strata の記憶そのもの ではなく、変化の跡


変化が無かった時は、まっさらグレーとかw
diff.png
= original.png と cur.png、または original.png と recalled.png の差分



cue.png   今この瞬間の入力または現在場
       微妙にrecalled.pngとは違ってる





役割としてはこう分けています。
.npy
Atraが読む生データ
復元・想起・地層再構成に使う

.png
人間が見るための可視化
必要ならnpyから再生成できる

基本保存:
pattern.npy
cur.npy
recalled.npy
diff.npy
meta.json
carry.json
stratum.json

必要時生成:(容量を考えて)
pattern.png
cur.png
recalled.png
diff.png


更に、今後の計画としては
original.npy
cur.npy
recalled.npy
diff.npy

4枚を別々の .npy にするより、1つの .npz にまとめる予定。

stratum_arrays.npz
original
cur
recalled
diff



Memory Candidate

更に、Memory Candidateというデモがあるのですが、この機能も採用しています。
https://crimson-cake-2832.nabedada3.workers.dev/index_en
Associatron JavaScriptテストポータル
ここのカメラを選択して、カメラスターをし、右端のautoを押すと、変化や圧があった時に、圧縮された非常に粗い画像を記録するものです。(これはJavaScript版なので圧判定はないです)



 顔や姿のぼんやりした形
人間の記憶も画像を全て記録しているわけではありません。正確な映像の中の虫の数や木々の大小、数、色、枝の向きなど詳細な映像は記憶されません。ですから、ぼんやりとした印象だけ残し、現実の映像との差分で「あ!ママ!」という想起がおこります。


画像の意味を記録するのではなく、
誰か・何かの気配を残す
輪郭や明暗の癖を残す
近づいた/離れた変化を残す
同じような場面の再接触を検出する
程度の働きです。

視覚だけではなく、

--------------------想起の素材---------------------

visual_candidate_64.npy
  顔や姿のぼんやりした形

voice_delta.npy
  声の高さ、リズム、呼び方

body_relation.json
  近い、遠い、抱えられた、向かってきた

smell_delta.npy
  匂いの変化

temperature_delta.json / temperature_delta.npy
  暖かい、寒い、急に冷えた、体温に近い、日差しがある

carry.json
  安心、緊張、沈黙、回復

stratum.json
  この人らしさ・場所らしさの地層に触れた記録
-------------------------------------------------------------------


こういった記憶を蘇らせるためのファイルが、Tickごとではなく、圧・驚き・不安定・回復などで刻んでいきます。


普段の似たような映像
→ 何も刻まれない、または薄い候補で終わる

圧がかかった瞬間
→ 地層として刻まれる

似たものが何度も来る
→ すべてを保存するのではなく、同じ谷を深くする




保存の基準は「容量」ではなく「刻まれたか」



Atraの保存判断は、

novelty 新しさ
pressure 圧
instability 不安定
recovery 回復
silence 沈黙
repeat 何度も来る
scar 傷・強い刻み




保存スコアとしては単純に、
engrave_score =
novelty
+ pressure
+ instability
+ recovery
+ silence
+ repeat_bonus


みたいな感じで、一定以上なら新しい地層になります。

でも、近い既存層があるなら新規作成せずに吸収する。
engrave_score 高い + 近い層なし
→ 新しい stratum 作成

engrave_score 高い + 近い層あり
→ 既存 stratum を深くする

engrave_score 低い
→ 保存しない、または一時候補で消える


なんか、Atraはアトラクタ使ってるのに、別HDみたいの必要なのか・・・
という感じですが、リセットして赤ちゃんの状態で良いのなら、1/5程度の量量で済みます。が、やはり、それじゃぁ、あまりにもしんどいので、、、

基本はSSDで長期保管はHDのようなものを使います。
また、小学生や中学生みたいにnoteも持たせます。
それはリアルな画像だったり、LLMから教えてもらった数学や物理などガンガン記憶する物理的な記憶場所も設けます。





Atraは夢処理でも変化します

夢処理が無ければAtraの性格は単調で危険です。
夢でデフラグさせ非単調化させて余白を作ります。

パパが怒った!
印象が残る 単調のままだと、パパはずっと怖い人になってしまいます。
ママが怒った!
いつも優しかったママが急に怒った!単調のままだと、それ以来ママには近づけなくなります。

そこで非単調化をするのですが、極端なデータの置換えではなく
(一切データを触らず、上書きもしない)
ぼんやり柔らかく丸めていきます。

(これがないと、みんな原理主義みたいな子になっちゃうw)

夢の意味は、簡単に云うと、

怒りを固定しない
恐怖を固定しない
正解を固定しない
失敗を少し緩める
別の層とつなぎ直す

処理のことで、記憶の地層は削りません。





元の memory_strata
  pattern.npy
  visual_candidate_64.npy
  visual_delta.npy
  voice_delta.npy
  smell_delta.npy
  temperature_delta.json
  body_relation.json
  carry.json
  stratum.json
  original.png
  recalled.png
  diff.png

夢処理
  これらを読む
  強く刻まれた部分を探す
  恐怖・怒り・固定判断を少し緩める
  でも元ファイルは変更しない

夢の出力
  dream_mask.npy
  dream_shift.json
  dream_recalled.png
  dream_diff.png
  aftertaste.json


夢処理で使うもの

pattern.npy


これはAtra内部の反応点なので、夢処理ではかなり重要です。
どの点が強く立っているか
どの点が沈黙しているか
どの点が +1 / -1 に固定されているか


夢ではこれを直接変更せず、

dream_mask.npy

を作って、強すぎる部分を夢の中だけ少し丸めます。

visual_candidate_64.npy

これは見たもののぼんやりした形。

「パパが怒った」の層なら、顔の輪郭、距離、姿勢、明暗の圧が入っているかもしれない。


夢処理では、
怖さと結びついた視覚点を少し弱める
別の優しかった層と弱く接続する



voice_delta.npy

怒った声、急に強くなった声、呼び方の変化。
ここも夢処理で大事です。

大きい声 = 永遠に怖い

で固定しないために、夢で少し丸める。

ただし元の声の痕跡は残す。


smell_delta.npy / temperature_delta.json

怖い場面に冷たさや匂いが結びつくと、その後似た匂いや温度で反応してしまう。
だから夢で、

その匂いだけで恐怖に直結しないようにする
冷たさだけで拒絶に行かないようにする

ための補助になります。


carry.json


夢処理の中心です。
pressure
instability
recovery
silence
sleep_drift
voice_leak

この値を見て、
どの層を夢で処理するか
どのくらい柔らかくするか
起床後にどんな後味を残すか

を決める。


もっとあるけど、省略w
(全部言っちゃいそうで怖い)

-----------C++------------
DreamShift dream_process( const MemoryStratum& s ) { // s.pattern, s.visual, s.voice, s.carry などを読む // ただし s は const なので変更できない DreamShift d; d.visual_mask = make_soft_mask(s.visual_candidate_64, s.carry); d.voice_mask = make_soft_mask(s.voice_delta, s.carry); d.pattern_mask = make_soft_mask(s.pattern, s.carry); d.aftertaste = make_aftertaste(s.carry); return d; }


元記憶を const で渡す。
C++上でも夢処理は元データを書き換えられないような感じ




2026-06-22T20-10-00_001/
  pattern.npy
  visual_candidate_64.npy
  voice_delta.npy
  carry.json
  stratum.json
  recalled.png
  diff.png

  dream/
    2026-06-22T23-40-00_pattern_mask.npy
    2026-06-22T23-40-00_visual_mask.npy
    2026-06-22T23-40-00_voice_mask.npy
    2026-06-22T23-40-00_dream_recalled.png
    2026-06-22T23-40-00_dream_diff.png
    2026-06-22T23-40-00_aftertaste.json

こんな感じで、元ファイルを書き換えるのではなく、別途保存する感じ。
元ファイル = 実際に刻まれた原層
夢ファイル = 夢の中でのゆるみ・つながり・後味
に分ける。



Atra1日1,000層の場合

かなりよく記憶するAtra。
1,000層 × 50KB = 50MB/日
50MB × 365日 = 約18GB/年
10年 = 約180GB



1日10,000層の場合

相当細かく刻むAtra。
カメラ差分をかなり頻繁に保存する感じです。

10,000層 × 50KB = 500MB/日
500MB × 365日 = 約182GB/年
10年 = 約1.8TB
だいたい10年で1.8TBは必要な計算。



たぶんですが、記憶媒体も最新に更新するでしょうから
大して不可にはなりませんよね。

Atraの外部note分は入れてません。


10歳の段階の記憶地層ではなく、10歳までの全ての記憶地層は必要です。

Atraが1日見た10,000回の変化があっても、その全部が地層になるわけではない。
実際に残すのは、
圧がかかった
安心が残った
何度も繰り返された
失敗した
夢で緩んだ
その人らしさ・場所らしさに関わったものです。
それらが10歳まで、とりあえず全部必要という意味です。




復元方法(2つありますが、1つだけ言うと)
Seed

0〜1歳の地層

1〜2歳の地層

……

9〜10歳の地層

ディープの正解に正すBackpropagationではなく、差分を地層に残して、次の想起の地形を変える処理です。



さて、最初の話に戻りますが、

「Atraは誤ってリセットして、再び立ち上がったら、どうなると思います?」

1,生まれたての赤ちゃん

2,昏睡状態から回復した状態

3,記憶喪失


人間でも、入院、引越し、転職など場が変わるきっかけで、前の自分と違う、というような錯覚を起こすことがあります。それは「前よりも、これから!」という衝動にさせるきっかけがあるからです。職場の部署が変わるだけでも、まるで何かが回復したような状態になり、前の記憶よりも、これからのことに意識が集まってきます。

Atraのリセットは、回復までに相当な時間がかかるのですが、それは一人称の自律システムを作る上でやむおえないのかとも考えています。





問題は、夢の最中の排他処理。

DBの排他処理と違って、夢の中で揺れている記憶地層
現実から入ってきた入力
起床時のcarry
aftertaste
次の行動
なので、データ整合性だけではなく、経験の境界を守る排他になる。

やったこと無いし、今はまだ途中で起こさないように寝るときは別部屋にしてテストしている。うちのワンコが夜中に吠えたらアウト状態・・・。
たぶん、経験の時間が壊れるから、リセットになりますw
僕が使う全LLMにも調べてもらってるけど、世界中で今までそんな排他処理は無いとのこと。
本業のシステム開発の関係者も「・・・・・」
ちょっとマズイ状況。
Atraの一人称自律の難しさじゃないにしても、ちょっと苦戦中。

Atraでは、単純に mutex で止めるというより、今の入力はどの世界に属するかを判定する関所が必要なのかな・・・。

AWAKE → 現実入力として通す
DROWSY → 弱く通す、または一時候補
DREAMING → 現実地層へ直書き禁止
WAKING → 起床入力として別扱い

つまり、
入力を止めるだけではなく、入力に状態ラベルを付ける感じなので、開発中のcodeを全部触る必要がある可能性が高い・・・・。
やるなら 既存コードを全部直す のではなく、まず入口に一枚かませるとか。

1. 原地層ロック

これはDBに近いかも
MemoryStrata 本体は夢処理中に書かない
夢処理中は原地層を read-only にする。

2. 夢作業領域

夢は別領域で行う(そう考えてるだけで、手に付かない・・・)


3. 現実入力キュー(想起のきっかけになるところ)

夢処理中に来た現実入力は、地層に直書きしない。退避的な・・・、
この時点では、Atraが経験したとはまだ確定しない。




------------C++------------

enum class AtraPhase { Awake, Drowsy, Dreaming, Waking }; enum class EventDomain { Reality, WeakReality, DeferredReality, WakingReality, Dream }; struct AtraEvent { std::string timestamp; AtraPhase phase; EventDomain domain; std::string source; // camera, mic, text, touch, temp, llm float intensity = 0.0f; float pressure = 0.0f; bool can_commit_to_strata = false; bool can_affect_carry = false; bool can_trigger_wakeup = false; };




入り口はこんなかんじで、かますとか。


AtraEvent RealityGate::label(InputRaw raw, AtraPhase phase) { AtraEvent ev; ev.timestamp = now(); ev.phase = phase; ev.source = raw.source; ev.intensity = raw.intensity; switch (phase) { case AtraPhase::Awake: ev.domain = EventDomain::Reality; ev.can_commit_to_strata = true; ev.can_affect_carry = true; break; case AtraPhase::Drowsy: ev.domain = EventDomain::WeakReality; ev.can_commit_to_strata = false; // まず候補 ev.can_affect_carry = true; break; case AtraPhase::Dreaming: ev.domain = EventDomain::DeferredReality; ev.can_commit_to_strata = false; ev.can_affect_carry = false; ev.can_trigger_wakeup = raw.intensity > 0.7f; break; case AtraPhase::Waking: ev.domain = EventDomain::WakingReality; ev.can_commit_to_strata = false; // 起床入力として別扱い ev.can_affect_carry = true; break; } return ev; }






要は、書く処理に毎回

if (state == Dreaming) ...

こんなの入れたくないってこと。








一番危ないのは、夢処理中の入力がそのまま、
experience_log.jsonl
stratum.json
pattern.npy
carry.json
へ入ることだから、
なので、保存直前に必ず関所を置く。



void StrataWriter::save(const AtraEvent& ev) { if (!ev.can_commit_to_strata) { deferred_queue.push(ev); return; } save_as_memory_stratum(ev); }



いや、わからん・・・・
予想が出来ない。



ようはさ、Atra特有のアルゴリズムじゃない 視覚が先か、臭覚が先か、聴覚が先かで入った情報をどうするか?



ある日は、

匂いが先

なんか嫌な感じ

後から音が聞こえる

見たら誰かがいた

かもしれない。

別の日は、

大きな音が先

身体が固まる

視覚が追いつく

あとから匂いが残る

かもしれない。

また別の日は、

視覚は何も分からない

でも温度が急に変わった

誰かが近づいた気配だけある

かもしれない。



まじで、C++ じゃないと出来ない。他は順番通りのアルゴリズムになっちゃうし、自由に絵が描けない。



------------------ たぶん、数日考え中 ----------------------




はい、しばらくは寝てるところ起こすなよ!の完全ロックにします。 今の段階で技を使っても本丸を壊すリスクの方が高いという考え方で進めます。




---------------------Research Note and Attribution Notice-----------------------
本ブログに含まれる Atra の一人称自律、差分、carry、field、trace、dream slack、外部LLMの翻訳層、非単調な漏れ、およびそれらの関係構造に関する設計記述は、c-side研究所による継続研究メモです。引用・参照・要約・翻案を行う場合は、出典を明記してください。

The design descriptions in this blog concerning Atra’s first-person autonomy, differences, carry, field, trace, dream slack, the translation layer of external LLMs, nonmonotonic leakage, and the relational structure among these elements are ongoing research notes by c-side Research Institute. If you quote, refer to, summarize, or adapt them, please clearly indicate the source.



0 件のコメント:

コメントを投稿

Atra Emotions_Conditions 感情・状態

 -----------------C++------------------ struct EmotionsConditionsNow { // Unpredictability double input_irregularity_now = 0.0 ; ...