모든 실험은 신성하다
모든 실험은 훌륭함
만약 실험이 낭비되면 신이 매우 화를 낼 것
Sacred는 실험을 구성, 기록 복제하는 도구
기능
메인 메커니즘
@ex.config
데코레이터 함수를 사용해 쉽게 설정 가능from numpy.random import permutation
from sklearn import svm, datasets
from sacred import Experiment
ex = Experiment('iris_rbf_svm', interactive=True)
# jupyter notebook일 경우 interactive=True, python 스크립트라면 없어도 됨
@ex.config
def cfg():
C = 1.0
gamma = 0.7
# ex.automain은 python 스크립트일 때 사용
@ex.main
def run(C, gamma):
iris = datasets.load_iris()
per = permutation(iris.target.size)
iris.data = iris.data[per]
iris.target = iris.target[per]
clf = svm.SVC(C, 'rbf', gamma=gamma)
clf.fit(iris.data[:90],
iris.target[:90])
return clf.score(iris.data[90:],
iris.target[90:])
ex.run()
WARNING - iris_rbf_svm - No observers have been added to this run INFO - iris_rbf_svm - Running command 'run' INFO - iris_rbf_svm - Started INFO - iris_rbf_svm - Result: 0.9833333333333333 INFO - iris_rbf_svm - Completed after 0:00:00
<sacred.run.Run at 0x11f5970f0>
from sacred import Experiment
ex = Experiment('my_experiment', interactive=True)
@ex.config
def my_config():
foo = 42
bar = 'baz'
@ex.capture
def some_function(a, foo, bar=10):
print(a, foo, bar)
@ex.main
def my_main():
some_function(1, 2, 3) # 1 2 3
some_function(1) # 1 42 'baz'
some_function(1, bar=12) # 1 42 12
some_function() # TypeError: missing value for 'a'
ex.run()
WARNING - my_experiment - No observers have been added to this run INFO - my_experiment - Running command 'my_main' INFO - my_experiment - Started ERROR - my_experiment - Failed after 0:00:00!
1 2 3 1 42 baz 1 42 12
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-14-106ea74a54b1> in <module>() ----> 1 ex.run() /usr/local/lib/python3.6/site-packages/sacred/experiment.py in run(self, command_name, config_updates, named_configs, meta_info, options) 207 run = self._create_run(command_name, config_updates, named_configs, 208 meta_info, options) --> 209 run() 210 return run 211 /usr/local/lib/python3.6/site-packages/sacred/run.py in __call__(self, *args) 219 self._start_heartbeat() 220 self._execute_pre_run_hooks() --> 221 self.result = self.main_function(*args) 222 self._execute_post_run_hooks() 223 if self.result is not None: /usr/local/lib/python3.6/site-packages/sacred/config/captured_function.py in captured_function(wrapped, instance, args, kwargs) 44 start_time = time.time() 45 # =================== run actual function ================================= ---> 46 result = wrapped(*args, **kwargs) 47 # ========================================================================= 48 if wrapped.logger is not None: <ipython-input-13-b76dd844dd54> in my_main() 16 some_function(1) # 1 42 'baz' 17 some_function(1, bar=12) # 1 42 12 ---> 18 some_function() # TypeError: missing value for 'a' /usr/local/lib/python3.6/site-packages/sacred/config/captured_function.py in captured_function(wrapped, instance, args, kwargs) 39 bound = (instance is not None) 40 args, kwargs = wrapped.signature.construct_arguments(args, kwargs, options, ---> 41 bound) 42 if wrapped.logger is not None: 43 wrapped.logger.debug("Started") /usr/local/lib/python3.6/site-packages/sacred/config/signature.py in construct_arguments(self, args, kwargs, options, bound) 100 args, kwargs = self._fill_in_options(args, kwargs, options, bound) 101 --> 102 self._assert_no_missing_args(args, kwargs, bound) 103 return args, kwargs 104 /usr/local/lib/python3.6/site-packages/sacred/config/signature.py in _assert_no_missing_args(self, args, kwargs, bound) 158 if missing_args: 159 raise TypeError("{} is missing value(s) for {}".format( --> 160 self.name, missing_args)) TypeError: some_function is missing value(s) for ['a']
from sacred.observers import MongoObserver
ex.observers.append(MongoObserver.create())
from pymongo import MongoClient
import urllib.parse
username = urllib.parse.quote_plus('user')
password = urllib.parse.quote_plus('password')
from sacred.observers import MongoObserver
ex.observers.append(MongoObserver.create(
url='mongodb://user:password@example.com/the_database?authMechanism=SCRAM-SHA-1',
db_name='MY_DB'))
from sacred.observers import FileStorageObserver
ex = Experiment('iris_rbf_svm', interactive=True)
# jupyter notebook일 경우 interactive=True, python 스크립트라면 없어도 됨
@ex.config
def cfg():
C = 1.0
gamma = 0.7
# ex.automain은 python 스크립트일 때 사용
@ex.main
def run(C, gamma):
iris = datasets.load_iris()
per = permutation(iris.target.size)
iris.data = iris.data[per]
iris.target = iris.target[per]
clf = svm.SVC(C, 'rbf', gamma=gamma)
clf.fit(iris.data[:90],
iris.target[:90])
return clf.score(iris.data[90:],
iris.target[90:])
ex.observers.append(FileStorageObserver.create('my_runs'))
ex.run()
INFO - iris_rbf_svm - Running command 'run' INFO - iris_rbf_svm - Started run with ID "1" INFO - iris_rbf_svm - Result: 0.95 INFO - iris_rbf_svm - Completed after 0:00:00
<sacred.run.Run at 0x11f5ce5f8>
_log
사용@ex.capture
def some_function(_log):
_log.warning('My warning message!')
#!/usr/bin/env python
# coding=utf-8
""" An example showcasing the logging system of Sacred."""
from __future__ import division, print_function, unicode_literals
import logging
from sacred import Experiment
ex = Experiment('log_example', interactive=True)
# set up a custom logger
logger = logging.getLogger('mylogger')
logger.handlers = []
ch = logging.StreamHandler()
formatter = logging.Formatter('[%(levelname).1s] %(name)s >> "%(message)s"')
ch.setFormatter(formatter)
logger.addHandler(ch)
logger.setLevel('INFO')
# attach it to the experiment
ex.logger = logger
@ex.config
def cfg():
number = 2
got_gizmo = False
@ex.capture
def transmogrify(got_gizmo, number, _log):
if got_gizmo:
_log.debug("Got gizmo. Performing transmogrification...")
return number * 42
else:
_log.warning("No gizmo. Can't transmogrify!")
return 0
@ex.main
def main(number, _log):
_log.info('Attempting to transmogrify %d...', number)
result = transmogrify()
_log.info('Transmogrification complete: %d', result)
return result
ex.run()
[W] mylogger.log_example >> "No observers have been added to this run" WARNING - mylogger.log_example - No observers have been added to this run [I] mylogger.log_example >> "Running command 'main'" INFO - mylogger.log_example - Running command 'main' [I] mylogger.log_example >> "Started" INFO - mylogger.log_example - Started [I] mylogger.main >> "Attempting to transmogrify 2..." INFO - mylogger.main - Attempting to transmogrify 2... [W] mylogger.transmogrify >> "No gizmo. Can't transmogrify!" WARNING - mylogger.transmogrify - No gizmo. Can't transmogrify! [I] mylogger.main >> "Transmogrification complete: 0" INFO - mylogger.main - Transmogrification complete: 0 [I] mylogger.log_example >> "Result: 0" INFO - mylogger.log_example - Result: 0 [I] mylogger.log_example >> "Completed after 0:00:00" INFO - mylogger.log_example - Completed after 0:00:00
<sacred.run.Run at 0x102c54908>
from __future__ import division, print_function, unicode_literals
from sacred import Experiment
ex = Experiment('hello_config', interactive=True)
@ex.named_config
def rude():
"""A rude named config"""
recipient = "bastard"
message = "Fuck off you {}!".format(recipient)
@ex.config
def cfg():
recipient = "world"
message = "Hello {}!".format(recipient)
@ex.main
def main(message):
print(__name__)
print(message)
ex.run()
WARNING - hello_config - No observers have been added to this run INFO - hello_config - Running command 'main' INFO - hello_config - Started INFO - hello_config - Completed after 0:00:00
__main__ Hello world!
<sacred.run.Run at 0x11f8a6400>
from __future__ import division, print_function, unicode_literals
from sacred import Experiment, Ingredient
# ============== Ingredient 0: settings =================
s = Ingredient("settings")
@s.config
def cfg1():
verbose = True
# ============== Ingredient 1: dataset.paths =================
data_paths = Ingredient("dataset.paths", ingredients=[s])
@data_paths.config
def cfg2(settings):
v = not settings['verbose']
base = '/home/sacred/'
# ============== Ingredient 2: dataset =======================
data = Ingredient("dataset", ingredients=[data_paths, s])
@data.config
def cfg3(paths):
basepath = paths['base'] + 'datasets/'
filename = "foo.hdf5"
@data.capture
def foo(basepath, filename, paths, settings):
print(paths)
print(settings)
return basepath + filename
# ============== Experiment ==============================
ex = Experiment('modular_example', ingredients=[data, data_paths])
@ex.config
def cfg(dataset):
a = 10
b = 17
c = a + b
out_base = dataset['paths']['base'] + 'outputs/'
out_filename = dataset['filename'].replace('.hdf5', '.out')
@ex.automain
def main(a, b, c, out_base, out_filename, dataset):
print('a =', a)
print('b =', b)
print('c =', c)
print('out_base =', out_base, out_filename)
# print("dataset", dataset)
# print("dataset.paths", dataset['paths'])
print("foo()", foo())