feat: modernize PSO and add convergence research

Migrate the package and examples to the tensor-native PyTorch implementation, add benchmark evidence, and add the guarded post-training convergence protocol with TensorBoard progress monitoring and hash-verified recovery.

Constraint: Preserve one-shot official-test sealing and auditable research artifacts

Rejected: Commit local .omc runs and downloaded datasets | multi-gigabyte runtime state is machine-local

Confidence: high

Scope-risk: broad

Not-tested: Production CUDA run on pieroot-server
This commit is contained in:
2026-09-07 22:03:25 +09:00
parent 9745bb7ad4
commit 813433000a
120 changed files with 198148 additions and 4745 deletions
+77 -64
View File
@@ -1,76 +1,89 @@
# %%
import os
import sys
import argparse
import torch
import torch.nn as nn
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import Sequential
from pso import optimizer
from pso import Optimizer
from cli import add_pso_args, build_optimizer_kwargs
def get_data():
x = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([[0], [1], [1], [0]])
x = torch.tensor([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]], dtype=torch.float32)
y = torch.tensor([[0.0], [1.0], [1.0], [0.0]], dtype=torch.float32)
return x, y
def make_model():
model = Sequential()
model.add(layers.Dense(2, activation="sigmoid", input_shape=(2,)))
model.add(layers.Dense(1, activation="sigmoid"))
return model
def make_model(seed: int = 101):
torch.manual_seed(seed)
return nn.Sequential(
nn.Linear(2, 4),
nn.Tanh(),
nn.Linear(4, 1),
)
# %%
model = make_model()
x_test, y_test = get_data()
def main():
parser = argparse.ArgumentParser(description="PSO XOR Benchmark Script")
add_pso_args(
parser,
defaults={
"method": "original",
"initialization": "model_noise",
"evaluation": "fixed_subset",
"convergence": "none",
"refinement": "adam",
"n_particles": 40,
"c0": None,
"c1": None,
"w_min": None,
"w_max": None,
"negative_swarm": 0.1,
"mutation_swarm": 0.03,
"particle_min": -5.0,
"particle_max": 5.0,
"velocity_limit_ratio": 0.1,
"boundary_strategy": "reflect",
"initial_position_noise": 1.0,
"seed": 101,
"epochs": 120,
"fitness_size": 4,
"renewal": "loss",
"output_dir": "output/xor",
"refinement_epochs": 100,
"refinement_lr": 0.03,
},
)
args = parser.parse_args()
x, y = get_data()
model = make_model(seed=args.seed)
loss = [
"mean_squared_error",
"mean_squared_logarithmic_error",
"binary_crossentropy",
"categorical_crossentropy",
"sparse_categorical_crossentropy",
"kullback_leibler_divergence",
"poisson",
"cosine_similarity",
"log_cosh",
"huber_loss",
"mean_absolute_error",
"mean_absolute_percentage_error",
]
fitness_size = args.fitness_size if args.evaluation == "fixed_subset" else None
refinement_epochs = args.refinement_epochs if args.refinement == "adam" else 0
pso_xor = optimizer(
model,
loss=loss[0],
n_particles=100,
c0=0.35,
c1=0.8,
w_min=0.6,
w_max=1.2,
negative_swarm=0.1,
mutation_swarm=0.2,
particle_min=-3,
particle_max=3,
)
best_score = pso_xor.fit(
x_test,
y_test,
epochs=200,
save_info=True,
log=2,
log_name="xor",
renewal="acc",
check_point=25,
)
kwargs = build_optimizer_kwargs(
args,
model=model,
loss=nn.BCEWithLogitsLoss(),
task="binary",
inertia_profile={"c0": 0.7, "c1": 0.9, "w_min": 0.3, "w_max": 0.8},
)
pso_xor = Optimizer(**kwargs)
print(f"Optimizer device: {pso_xor.device}")
print("Done!")
sys.exit(0)
# %%
best_score = pso_xor.fit(
x,
y,
epochs=args.epochs,
batch_size=args.batch_size,
fitness_size=fitness_size,
renewal=args.renewal,
output_dir=args.output_dir,
save_info=True,
refinement_epochs=refinement_epochs,
refinement_lr=args.refinement_lr,
)
print(f"Done! Best score: {best_score}")
if __name__ == "__main__":
main()