cognithread-ssm / src_train.py
gamer729's picture
Upload src_train.py
449e8f6 verified
Raw History Blame Contribute Delete
3.66 kB
###############################################################################
# TRAINING: PILE dataset (streaming) with wave-scalar computing
###############################################################################
import optax
def load_pile_streaming(batch_size, seq_len, seed=42):
from datasets import load_dataset
ds = load_dataset("monology/pile-uncopyrighted", streaming=True, split="train")
def tokenize(example):
text = example.get("text", "")
if not text: text = ""
tokens = list(text.encode('utf-8'))[:seq_len]
tokens = tokens + [0] * (seq_len - len(tokens))
return {"input_ids": tokens}
ds = ds.map(tokenize)
ds = ds.shuffle(seed=seed, buffer_size=1000)
return ds
def create_batches(ds, batch_size, seq_len, d_model, n_batches=50):
batches = []
it = iter(ds)
for _ in range(n_batches):
batch = []
for _ in range(batch_size):
try:
example = next(it)
ids = example.get("input_ids", [0]*seq_len)
if len(ids) < seq_len: ids = ids + [0]*(seq_len-len(ids))
batch.append(ids[:seq_len])
except StopIteration: batch.append([0]*seq_len)
ids_arr = np.array(batch, dtype=np.float32)
x = ids_arr / 256.0
x = np.tile(x[..., None], (1,1,d_model//seq_len+1))[:,:,:d_model]
x = x * (0.5 + 0.5*np.random.randn(batch_size,seq_len,d_model)*0.1)
batches.append(jnp.array(x.astype(np.float32)))
return batches
def train_model(model, d_model, n_steps=30, lr=1e-4):
"""Train CogniThread model on PILE data with wave-scalar computing."""
print(f" Training on PILE (streaming) for {n_steps} steps...")
try:
ds = load_pile_streaming(batch_size=2, seq_len=8)
batches = create_batches(ds, batch_size=2, seq_len=8, d_model=d_model, n_batches=n_steps)
print(f" Loaded {len(batches)} batches from PILE")
except Exception as e:
print(f" PILE loading failed ({e}), using synthetic data")
key = jax.random.key(0)
batches = [jax.random.normal(jax.random.fold_in(key, i), (2, 8, d_model))
for i in range(n_steps)]
# Use gradient clipping to prevent NaN from exploding SSM dynamics
tx = optax.chain(
optax.clip_by_global_norm(1.0),
optax.adam(lr),
)
opt = nn.ModelAndOptimizer(model, tx, wrt=nn.Param)
@nn.jit
def train_step(opt, x, step_key):
def loss_fn(model):
y_final, var_y, w_f, mu = model(x, key=step_key)
# Use L2 loss on output (autoencoder-style)
# Replace inf/nan with large but finite value
y_sq = jnp.sum(y_final ** 2)
y_sq = jnp.where(jnp.isfinite(y_sq), y_sq, jnp.array(1e6))
var_loss = jnp.mean(var_y) * 0.01
ent_loss = -jnp.mean(mu * jnp.log(mu + 1e-8)) * 0.001
return jnp.mean(y_sq) + var_loss + ent_loss
loss, grads = nn.value_and_grad(loss_fn)(opt.model)
# Replace NaN gradients with zeros
grads = jax.tree.map(lambda g: jnp.where(jnp.isfinite(g), g, jnp.zeros_like(g)), grads)
opt.update(grads)
return jnp.where(jnp.isfinite(loss), loss, jnp.array(1e6))
losses = []
for step, x_batch in enumerate(batches):
step_key = jax.random.key(step)
loss = train_step(opt, x_batch, step_key)
losses.append(float(loss))
if step % 10 == 0 or step == n_steps - 1:
print(f" Step {step+1}/{n_steps}: loss={float(loss):.4f}")
print(f" Training complete. Final loss: {losses[-1]:.4f}")
return opt.model, losses