From 02293389a1d7ddfa8eeb4b7caa1c89e97409c3bd Mon Sep 17 00:00:00 2001 From: Sooyoung Cheong <64125280+c-sooyoung@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:05:59 +0900 Subject: [PATCH] made sobo and randombo more consistent --- bo/random.py | 78 ++++++++++++++++------------------------------------ bo/sobo.py | 3 +- config.yaml | 4 +-- job.sub | 4 +-- main.py | 17 +++++------- 5 files changed, 36 insertions(+), 70 deletions(-) diff --git a/bo/random.py b/bo/random.py index dfa020f..55cb930 100644 --- a/bo/random.py +++ b/bo/random.py @@ -9,71 +9,44 @@ class RandomBOEngine(BOEngine): def __init__(self, config): super().__init__(config) - bo_params = [ - key for key, spec in config["bo"]["params"].items() if spec is not None - ] + self.params = [key for key, spec in config["bo"]["params"].items() if spec is not None] + self.param_types = {key: config["bo"]["params"][key].get("type", "float") for key in self.params} + self.integer_indices = [i for i, param in enumerate(self.params) if self.param_types[param] == 'int'] + self.bounds = np.empty((2, len(self.params))) - bo_param_types = { - key: config["bo"]["params"][key].get("type", "float") for key in bo_params - } - - integer_params = [ - key for key in bo_params if bo_param_types[key] == "int" - ] - - integer_indices = [ - bo_params.index(key) for key in integer_params - ] - - bounds = np.empty((2, len(bo_params))) - - for i, param in enumerate(bo_params): + for i, param in enumerate(self.params): center = config["ptycho"]["params"][param] radius = config["bo"]["params"][param]["radius"] - bounds[0, i] = center - radius - bounds[1, i] = center + radius + self.bounds[0, i] = center - radius + self.bounds[1, i] = center + radius - state = { - "method": "random", - "acquisition": "", - "params": bo_params, - "param_types": bo_param_types, - "integer_params": integer_params, - "integer_indices": integer_indices, - "bounds": bounds, # shape: (2, BOparam) - "train_x": np.empty((0, len(bo_params))), # shape: (BOiter, BOparam) - "train_y": np.empty((0,)), # shape: (BOiter,) - "train_info": [] # shape: (BOiter,) - } + self.train_x = np.empty((0, len(self.params))) # shape: (BOiter, BOparam) + self.train_y = np.empty((0,)) # shape: (BOiter,) train_x_path = config["bo"].get("train_x") train_y_path = config["bo"].get("train_y") - if train_x_path is not None and train_y_path is not None: if os.path.exists(train_x_path) and os.path.exists(train_y_path): train_x = np.load(train_x_path) train_y = np.load(train_y_path) assert train_x.ndim == 2, "loaded train_x must be 2D" - assert train_x.shape[1] == len(bo_params), "loaded train_x shape(1) does not match number of variable parameters" + assert train_x.shape[1] == len(self.params), "loaded train_x shape(1) does not match number of variable parameters" assert train_y.ndim == 1, "loaded train_y must be 1D" assert train_y.shape[0] == train_x.shape[0], "loaded train_x and train_y shape(0) have unequal iterations" - state["train_x"] = train_x - state["train_y"] = train_y - - self.state = state - + self.train_x = train_x + self.train_y = train_y + def ask(self): config = self.config - state = self.state next_config = copy.deepcopy(config) - for param in state['params']: + for param in self.params: radius = config['bo']['params'][param]['radius'] center = config['ptycho']['params'][param] modulation = radius * (np.random.rand() - 0.5) * 2 next_value = center + modulation - if state['param_types'][param] == 'int': + if self.param_types[param] == 'int': next_value = round(next_value) next_config['ptycho']['params'][param] = next_value @@ -82,31 +55,28 @@ class RandomBOEngine(BOEngine): def tell(self, job_config, y_value): config = self.config - state = self.state x_value = [] - for param in state['params']: + for param in self.params: x_value.append(job_config['ptycho']['params'][param]) - state['train_x'] = np.vstack([ - state['train_x'], + self.train_x = np.vstack([ + self.train_x, np.array(x_value).reshape(1, -1) ]) - state['train_y'] = np.concatenate([ - state['train_y'], + self.train_y = np.concatenate([ + self.train_y, np.array([y_value]) ]) - state['train_info'].append(state['method']) - train_x_path = config['bo'].get('train_x') train_y_path = config['bo'].get('train_y') if train_x_path is not None and train_y_path is not None: - np.save(train_x_path, state['train_x']) - np.save(train_y_path, state['train_y']) + np.save(train_x_path, self.train_x) + np.save(train_y_path, self.train_y) else: result_dir = config['io']['result_dir'] - np.save(os.path.join(result_dir, 'train_x.npy'), state['train_x']) - np.save(os.path.join(result_dir, 'train_y.npy'), state['train_y']) + np.save(os.path.join(result_dir, 'train_x.npy'), self.train_x) + np.save(os.path.join(result_dir, 'train_y.npy'), self.train_y) diff --git a/bo/sobo.py b/bo/sobo.py index 42adb9b..788e3b2 100644 --- a/bo/sobo.py +++ b/bo/sobo.py @@ -38,7 +38,6 @@ class SingleObjectiveBOEngine(BOEngine): train_x_path = config["bo"].get("train_x") train_y_path = config["bo"].get("train_y") - if train_x_path is not None and train_y_path is not None: if os.path.exists(train_x_path) and os.path.exists(train_y_path): train_x = np.load(train_x_path) @@ -168,7 +167,7 @@ class SingleObjectiveBOEngine(BOEngine): ]) - train_x_path = config['bo'].get('train_x') + train_x_path = config['bo'].get('tain_x') train_y_path = config['bo'].get('train_y') if train_x_path is not None and train_y_path is not None: np.save(train_x_path, self.train_x) diff --git a/config.yaml b/config.yaml index 6c6e7b1..ea1a241 100644 --- a/config.yaml +++ b/config.yaml @@ -1,7 +1,7 @@ io: input_data_path: '/home/swim/Si_project/data/Si2V1_1.mat' - result_dir: '/home/swim/Si_project/wrapper/results/260721' - verbosity: 1 + result_dir: '/home/swim/bo-ptycho/results/260730' + verbosity: 0 ptycho: engine: 'fold_slice' diff --git a/job.sub b/job.sub index a87950a..3ab02ab 100644 --- a/job.sub +++ b/job.sub @@ -1,5 +1,5 @@ #!/bin/bash -#SBATCH --job-name=jobname +#SBATCH --job-name=Si2V1 #SBATCH --nodes=1 #SBATCH --ntasks=1 #SBATCH --cpus-per-task=1 @@ -7,7 +7,7 @@ #SBATCH --time=100:00:00 #SBATCH --output=/home/swim/slurm-logs/job_%j.log -echo "JOBNAME" +echo "Si_2V_1" pwd hostname date diff --git a/main.py b/main.py index c5bac1e..d262838 100644 --- a/main.py +++ b/main.py @@ -16,30 +16,27 @@ def main(config_yaml): os.makedirs(result_dir, exist_ok=True) shutil.copy(config_yaml, os.path.join(result_dir, os.path.basename(config_yaml))) + # RANDOM BO SAMPLING PREPARATIONS; 20 SAMPLES randombo = bo.RandomBOEngine(config) - - for j in range(10): + for j in range(20): + print(f"RANDOM sampling iteration {j+1}") job_config = randombo.ask() ptycho_engine = ptycho.FoldSlicePtychoEngine(job_config) ptycho_engine.run() y_value = -np.log(ptycho_engine.metric()) randombo.tell(job_config, y_value) - print('[random] TRAIN_X\n', randombo.state['train_x']) - print('[random] TRAIN_Y\n', randombo.state['train_y']) + # MAIN SINGLE OBJECTIVE BAYESIAN OPTIMIZATION sobo = bo.SingleObjectiveBOEngine(config) - sobo.train_x = randombo.state['train_x'] - sobo.train_y = randombo.state['train_y'] - + sobo.train_x = randombo.train_x + sobo.train_y = randombo.train_y for j in range(config['bo']['max_iterations']): + print(f"SOBO sampling iteration {j+1}") job_config = sobo.ask() ptycho_engine = ptycho.FoldSlicePtychoEngine(job_config) ptycho_engine.run(header=f"[BO {j:03d}] ") y_value = -np.log(ptycho_engine.metric()) sobo.tell(job_config, y_value) - print('[sobo] TRAIN_X\n', sobo.train_x) - print('[sobo] TRAIN_Y\n', sobo.train_y) - if __name__ == "__main__": if len(sys.argv) != 2: