Commit 1d89e362 authored by PLian's avatar PLian
Browse files

Upgraded to python3.7 and removed Spearmint

parent ae90c5b4
"""Executor classes are responsible for running tasks that are provided by an Optimizer."""
from local import LocalExecutor # noqa
from slurm import SrunExecutor # noqa
from .local import LocalExecutor # noqa
from .slurm import SrunExecutor # noqa
......@@ -76,7 +76,7 @@ class BaseExecutor(object):
def start_trace(self):
"""Write out the header line of the trace.txt TSV file."""
trace_path = os.path.join(self.logdir, 'trace.txt')
trace_file = open(trace_path, 'w', buffering=False)
trace_file = open(trace_path, 'w')
trace_file.write("Index\tStatus\t")
......@@ -93,8 +93,8 @@ class BaseExecutor(object):
def write_trace(self, summary_dict):
"""Write a single line to the trace file, summarizing a task."""
print 'Start to writing trace ...'
print summary_dict
print('Start to writing trace ...')
print(summary_dict)
try:
self._write_trace(summary_dict)
......@@ -114,7 +114,7 @@ class BaseExecutor(object):
summary_dict["_status"]
)
for arg in summary_dict["_cmd"].values():
for arg in list(summary_dict["_cmd"].values()):
summary_line += "%s\t" % str(arg['value'])
summary_line += "%d\t%s\t%s\t%s" % (
......@@ -132,7 +132,7 @@ class BaseExecutor(object):
summary_line = summary_line + "\n"
trace_path = os.path.join(self.logdir, 'trace.txt')
trace_file = open(trace_path, 'a', buffering=False)
trace_file = open(trace_path, 'a')
trace_file.write(summary_line)
trace_file.close()
......@@ -175,7 +175,7 @@ class BaseExecutor(object):
}
if ret_code != 0:
logger.warn(" - Task %s had a non-zero exit code, may have failed" % ret_code)
logger.warning(" - Task %s had a non-zero exit code, may have failed" % ret_code)
summary_dict["_status"] = "ERROR"
if "summary" in self.params.vals:
......
......@@ -4,7 +4,7 @@ import logging
import multiprocessing
from subprocess import call
from base import BaseExecutor
from .base import BaseExecutor
logger = logging.getLogger(__name__)
......@@ -23,7 +23,7 @@ class LocalExecutor(BaseExecutor):
cpus = multiprocessing.cpu_count()
logger.info(" - %d CPUs available on this machine" % cpus)
cpus_per_task = params.vals['cpus_per_task']
self.conc_tasks = (cpus / cpus_per_task)
self.conc_tasks = int(cpus // cpus_per_task)
if self.conc_tasks < 1:
raise ValueError("Cannot run any tasks - cpus_per_task (%d) is larger than CPUs on this machine."
......
......@@ -5,7 +5,7 @@ import os
import re
from subprocess import call
from base import BaseExecutor
from .base import BaseExecutor
logger = logging.getLogger(__name__)
......
"""Optimizer classes implement an algorithm exploring parameter ranges."""
from basic import GridSearchOptimizer
from sp import SpearmintOptimizer
from harmonica import HarmonicaOptimizer
from .basic import GridSearchOptimizer
# from sp import SpearmintOptimizer
from .harmonica import HarmonicaOptimizer
def get_optimizer(params, executor):
......@@ -13,8 +13,8 @@ def get_optimizer(params, executor):
if optimizer == "gridsearch":
return GridSearchOptimizer(params, executor)
if optimizer == "spearmint":
return SpearmintOptimizer(params, executor)
# if optimizer == "spearmint":
# return SpearmintOptimizer(params, executor)
if optimizer == "harmonica":
return HarmonicaOptimizer(params, executor)
......
......@@ -2,7 +2,7 @@
import logging
from base import BaseOptimizer
from .base import BaseOptimizer
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
......
......@@ -2,7 +2,7 @@
import logging
from base import BaseOptimizer
from .base import BaseOptimizer
logger = logging.getLogger(__name__)
......
......@@ -5,7 +5,7 @@ import time
import traceback
import os
from base import BaseOptimizer
from .base import BaseOptimizer
from spearmint.chooser.GPEIOptChooser import GPEIOptChooser
from spearmint.ExperimentGrid import ExperimentGrid, load_experiment, Job
......
......@@ -87,8 +87,7 @@ class ParamFile(object):
(rc, err) = anyconfig.validate(params, schema)
if err:
message = "Parameter file invalid: " + \
err.splitlines()[0]
message = "Parameter file invalid: " + err.splitlines()[0]
raise ParamFileException(message)
logging.info("Parameter file is valid")
......@@ -103,13 +102,13 @@ class ParamFile(object):
"""
modules_ok = True
if 'modules' in params.keys():
if 'modules' in list(params.keys()):
for mod_name in params['modules']:
cmd = [MODULECMD, 'sh', 'show', mod_name]
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
if "Unable to locate" in output:
if "Unable to locate" in str(output):
logging.error('Module %s was not found.' % mod_name)
modules_ok = False
else:
......@@ -137,7 +136,7 @@ class ParamFile(object):
for problem in linter.run(f, conf):
logging.warn(Format.standard(problem, file))
logging.warning(Format.standard(problem, ''))
if err == 0 and problem.level == 'error':
err = 1
......@@ -149,8 +148,7 @@ class ParamFile(object):
def load(self):
"""Read in metadata from the astrocyte_pkg.yml to populate vals dict."""
if self.loaded:
raise ParamFileException(
"Parameter information was already loaded.")
raise ParamFileException("Parameter information was already loaded.")
self.validate()
metadata = anyconfig.load(self.param_file)
......@@ -158,8 +156,7 @@ class ParamFile(object):
if "summary" in self.vals:
self.__check_summary_regexes()
self.__check_score()
if "optimizer" not in self.vals or self.vals[
"optimizer"] == "gridsearch":
if "optimizer" not in self.vals or self.vals["optimizer"] == "gridsearch":
self.__compute_param_ranges()
self.commands = self.__compute_commands()
self.loaded = True
......@@ -172,31 +169,22 @@ class ParamFile(object):
compiled_re = re.compile(summary['regex'])
if compiled_re.groups != 1:
raise (TypeError(
"Regular expression for summary %s must contain exactly 1 matching group."
% summary['id']))
raise TypeError
logging.info('- Summary %s using regex %s' %
(summary['id'], summary['regex']))
except re.error:
raise (re.error("Regular expression for summary %s is invalid"
% summary['id']))
raise re
def __check_score(self):
if "score" in self.vals:
for summary in self.vals['summary']:
if summary['id'] == self.vals['score']:
logging.info(
" - Using '%s' as score to minimize" % summary['id'])
logging.info(" - Using '%s' as score to minimize" % summary['id'])
return
raise ValueError("Specified score '%s' is not a defined summary" %
self.vals['score'])
raise ValueError("Specified score '%s' is not a defined summary" % self.vals['score'])
#
# Set the default score to Accuracy
# TODO: need a better way to obtain the input score!
......@@ -341,7 +329,7 @@ class ParamFile(object):
"""
cmd_str = self.vals['command'] + ' '
for arg in arg_combn.values():
for arg in list(arg_combn.values()):
# In substitution mode we replace a placeholder in the command string
if arg['substitution'] is not None:
cmd_str = cmd_str.replace(arg['substitution'], arg['value'])
......
......@@ -115,9 +115,7 @@
"items":{
"type":"object",
"oneOf":[
{
"$ref":"#/definitions/summary_parameter"
}
{ "$ref":"#/definitions/summary_parameter"}
]
}
},
......@@ -136,9 +134,7 @@
"title":"Software Modules",
"description":"A list of environment module names that should be loaded to run this job.",
"name":"modules",
"items":{
"type":"string"
}
"items":{ "type":"string"}
},
"parameters":{
"type":"array",
......@@ -151,134 +147,59 @@
"items":{
"type":"object",
"oneOf":[
{
"$ref":"#/definitions/int_range"
},
{
"$ref":"#/definitions/real_range"
},
{
"$ref":"#/definitions/choice"
}
{ "$ref":"#/definitions/int_range" },
{ "$ref":"#/definitions/real_range" },
{ "$ref":"#/definitions/choice" }
]
}
}
},
"required":[
"command",
"partition",
"nodes",
"cpus_per_task",
"time_limit",
"parameters"
],
"required":["command", "partition", "nodes", "cpus_per_task", "time_limit", "parameters"],
"definitions":{
"int_range":{
"type":"object",
"properties":{
"id":{
"type":"string"
},
"type":{
"enum":[
"int_range"
]
},
"flag":{
"type":"string"
},
"optional":{
"type":"boolean"
},
"min":{
"type":"integer"
},
"max":{
"type":"integer"
},
"step":{
"type":"integer"
},
"scale":{
"type":"integer"
},
"description":{
"type":"string"
},
"substitution":{
"type":"string"
}
"id":{ "type":"string" },
"type":{ "enum":["int_range"]},
"flag":{ "type":"string" },
"optional":{ "type":"boolean" },
"min":{ "type":"integer" },
"max":{ "type":"integer" },
"step":{ "type":"integer" },
"scale":{ "type":"integer" },
"description":{ "type":"string" },
"substitution":{ "type":"string" }
},
"required":[
"id",
"type",
"min",
"max"
],
"required":["id", "type", "min", "max"],
"additionalProperties":false
},
"real_range":{
"type":"object",
"properties":{
"id":{
"type":"string"
},
"type":{
"enum":[
"real_range"
]
},
"flag":{
"type":"string"
},
"optional":{
"type":"boolean"
},
"min":{
"type":["number", "string"]
},
"max":{
"type":["number", "string"]
},
"step":{
"type":["number", "string"]
},
"scale":{
"type":["number", "string"]
},
"description":{
"type":"string"
},
"substitution":{
"type":"string"
}
"id":{ "type":"string" },
"type":{ "enum":["real_range"]},
"flag":{ "type":"string" },
"optional":{ "type":"boolean" },
"min":{ "type":["number", "string"]},
"max":{ "type":["number", "string"]},
"step":{ "type":["number", "string"]},
"scale":{"type":["number", "string"]},
"description":{ "type":"string" },
"substitution":{ "type":"string" }
},
"required":[
"id",
"type",
"min",
"max"
],
"required":["id", "type", "min", "max"],
"additionalProperties":false
},
"choice":{
"type":"object",
"properties":{
"id":{
"type":"string"
},
"type":{
"enum":[
"choice"
]
},
"flag":{
"type":"string"
},
"optional":{
"type":"boolean"
},
"id":{ "type":"string" },
"type":{ "enum":["choice"]},
"flag":{ "type":"string" },
"optional":{ "type":"boolean" },
"values":{
"type":"array",
"items":{
......@@ -286,35 +207,20 @@
"additionalItems":false
}
},
"description":{
"type":"string"
},
"substitution":{
"type":"string"
}
"description":{ "type":"string"},
"substitution":{ "type":"string"}
},
"required":[
"id",
"type",
"values"
],
"required":["id", "type", "values"],
"additionalProperties":false
},
"summary_parameter":{
"type":"object",
"properties":{
"id":{
"type":"string"
},
"regex":{
"type":"string"
}
"id":{ "type":"string" },
"regex":{ "type":"string" }
},
"required":[
"id",
"regex"
],
"required":["id", "regex"],
"additionalProperties":false
}
}
......
......@@ -2,7 +2,7 @@
set -ef -o pipefail
# This script installs a new python 2.7 and then sets up a virtualenv for
# This script installs a new python 3.7 and then sets up a virtualenv for
# astrocyte dependencies.
# Where am I?
......@@ -22,7 +22,7 @@ VENV_DIR="$DIR/../../venv"
# Check if conda is available
if ! conda -V > /dev/null 2>&1; then
module load python/2.7.x-anaconda
module load python/3.7.x-anaconda
fi
VENV_EXISTS=0
......@@ -39,7 +39,7 @@ fi
if [ "$VENV_EXISTS" = "0" ]; then
# Create venv with conda
echo "Creating virtual env"
conda create -y -q --prefix $VENV_DIR python=2.7
conda create -y -q --prefix $VENV_DIR python=3.7
# Activate the virtual env
echo "Activating virtual env"
......
......@@ -8,7 +8,9 @@ yamllint
pathos
# Needed by spearmint
numpy==1.10.04
scipy==0.16.1
protobuf==2.6.1
weave==0.17.0
#numpy==1.10.04
#scipy==0.16.1
#protobuf==2.6.1
#weave==0.17.0
#pymongo==3.10.1
......@@ -32,10 +32,10 @@ setup(
'pyyaml',
'yamllint',
'pathos',
'numpy==1.10.04',
'scipy==0.16.1',
'protobuf==2.6.1',
'weave==0.17.0',
#'numpy==1.10.04',
#'scipy==0.16.1',
#'protobuf==2.6.1',
#'weave==0.17.0',
],
scripts=['bin/param_runner'],
setup_requires=['pytest-runner'],
......
##
# Copyright (C) 2012 Jasper Snoek, Hugo Larochelle and Ryan P. Adams
#
# This code is written for research and educational purposes only to
# supplement the paper entitled
# "Practical Bayesian Optimization of Machine Learning Algorithms"
# by Snoek, Larochelle and Adams
# Advances in Neural Information Processing Systems, 2012
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import sys
import tempfile
import cPickle
import logging
import numpy as np
import numpy.random as npr
from spearmint_pb2 import *
from Locker import *
from sobol_lib import *
from helpers import *
CANDIDATE_STATE = 0
SUBMITTED_STATE = 1
RUNNING_STATE = 2
COMPLETE_STATE = 3
BROKEN_STATE = -1
EXPERIMENT_GRID_FILE = 'expt-grid.pkl'
logger = logging.getLogger(__name__)
class ExperimentGrid:
@staticmethod
def job_running(expt_dir, id):
expt_grid = ExperimentGrid(expt_dir)
expt_grid.set_running(id)
@staticmethod
def job_complete(expt_dir, id, value, duration):
# log("setting job %d complete" % id)
expt_grid = ExperimentGrid(expt_dir)
expt_grid.set_complete(id, value, duration)
# log("set...")
@staticmethod
def job_broken(expt_dir, id):
expt_grid = ExperimentGrid(expt_dir)
expt_grid.set_broken(id)
def __init__(self, expt_dir, variables=None, grid_size=None, grid_seed=1):
self.expt_dir = expt_dir
self.jobs_pkl = os.path.join(expt_dir, EXPERIMENT_GRID_FILE)
self.locker = Locker()
# Only one process at a time is allowed to have access to the grid.
self.locker.lock_wait(self.jobs_pkl)
# Set up the grid for the first time if it doesn't exist.
if variables is not None and not os.path.exists(self.jobs_pkl):
self.seed = grid_seed
self.vmap = GridMap(variables, grid_size)
self.grid = self._hypercube_grid(self.vmap.card(), grid_size)
self.status = np.zeros(grid_size, dtype=int) + CANDIDATE_STATE
self.values = np.zeros(grid_size) + np.nan
self.durs = np.zeros(grid_size) + np.nan
self.proc_ids = np.zeros(grid_size, dtype=int)
self._save_jobs()
# Or load in the grid from the pickled file.
else:
self._load_jobs()
def __del__(self):
self._save_jobs()
if self.locker.unlock(self.jobs_pkl):
pass
else:
raise Exception("Could not release lock on job grid.\n")