Parameter Grids¶
Parameter grids!
This lets you do basic grid expansion and grid arithmetic.
g = Grid([
('a', [1, 2]),
('b', [1, 2]),
], name='train')
# append two configurations
g = g + LiteralGrid([{'a': 5, 'b': 5}, {'a': 10, 'b': 10}])
# create a bigger grid from the product of another grid
g = g * Grid([
('c', [5, 6])
], name='dataset')
assert list(g) == [
{'a': 1, 'b': 1, 'c': 5},
{'a': 1, 'b': 1, 'c': 6},
{'a': 1, 'b': 2, 'c': 5},
{'a': 1, 'b': 2, 'c': 6},
{'a': 2, 'b': 1, 'c': 5},
{'a': 2, 'b': 1, 'c': 6},
{'a': 2, 'b': 2, 'c': 5},
{'a': 2, 'b': 2, 'c': 6},
{'a': 5, 'b': 5, 'c': 5},
{'a': 5, 'b': 5, 'c': 6},
{'a': 10, 'b': 10, 'c': 5},
{'a': 10, 'b': 10, 'c': 6},
]
- class slurmjobs.grid.Grid(_Grid__grid, name=None, **constants)[source]¶
A parameter grid! To get all combinations from the grid, just do
list(Grid(...)).- Parameters
grid (list, dict) –
The parameter grid. Should be either a dict or a list of key values, where the values are a list of values to use in the grid. Examples of valid inputs:
# simple grid Grid([ ('a', [1, 2]), ('b', [1, 2]) ]) Grid({ 'a': [1, 2], 'b': [1, 2] }) # paired parameters Grid([ ('a', [1, 2]), (('b', 'c'), ([1, 2], [1, 2])) ]) Grid([ ('a', [1, 2]), [{'b': 1, 'c': 1}, {'b': 2, 'c': 2}], ]) # any of these are valid grid specs g = slurmjobs.Grid([ # basic ('a', [1, 2]), # paired (('b', 'c'), ([1, 1, 2, 2], [1, 2, 1, 2])), # literal list of dicts [{'d': i} for i in [1, 2]], # dict generator ({'e': i} for i in [1, 2]), # function lambda: [{'f': i} for i in [1, 2]], # function that returns a generator lambda: ({'g': i} for i in [1, 2]), # basic generator ('h', (x for x in [1, 2])), # basic function ('i', lambda: [x for x in [1, 2]]), ]) keys = 'abcdefghi' assert list(g) == [ dict(zip(keys, vals)) for vals in itertools.product(*([ [1, 2] ]*len(keys))) ]
name (str) – The name of this grid. Can be used to search for the parameters from this grid.
**constants – Extra parameters to add to the grid that don’t vary. These will not be included in the job_id name.
Just a heads up, there is nothing stopping you from passing an infinite generator, meaning that you can make some fancy sampling grid generators, but
slurmjobswill take that and not know when to stop. If you want to use an infinite generator, just wrap it initertools.islicewhich will let you provide a limit.Obviously,
slurmjobsdoesn’t operate anywhere near the memory scale where you’d need to even use generators in the first place, but I figured why limit the implementation if it can be used for other things too.
- class slurmjobs.grid.LiteralGrid(_LiteralGrid__grid, name=None, **constants)[source]¶
A parameter grid, specified as a flattened list. This doesn’t do any grid expansion, it lets you specify the grid as you want.
- Parameters
grid (list, dict) – The parameter list. Should be a list of dicts, each corresponding to a parameter config.
name (str) – The name of this grid. Can be used to search for the parameters from this grid.
g = LiteralGrid([ {'a': 1, 'b': 1}, {'a': 1, 'b': 2}, {'a': 2, 'b': 2}, ]) assert list(g) == [ {'a': 1, 'b': 1}, {'a': 1, 'b': 2}, {'a': 2, 'b': 2}, ]
Grid Operations¶
- class slurmjobs.grid.GridCombo(*grids, name=None)[source]¶
This handles the multiplication of two grids (combinations). It will create a grid as a product of all provided grids.
You can create this doing
grid_a * grid_b. The only reason to use this directly is if you want to give it a name or if you want to make a grid product of 3 or more grids.a = Grid(('a', [1, 2]), ('b', [1, 2])) b = Grid(('c', [1, 2])) # functionally equivalent c = a * b c = GridCombo(a, b, name='my-a-b-combo-grid') c_items = [ dict(da, **db) for da, db in itertools.product(a, b) ]
- class slurmjobs.grid.GridChain(*grids, name=None)[source]¶
This handles the addition of two grids (one after the other).
You can create this doing
grid_a + grid_b. The only reason to use this directly is if you want to give it a name.a = Grid(('a', [1, 2]), ('b', [1, 2])) b = Grid(('c', [1, 2])) # functionally equivalent c = a + b c = GridChain(a, b, name='my-a-then-b-grid') c_items = list(a) + list(b)
- class slurmjobs.grid.GridOmission(grid, omission, name=None)[source]¶
This handles the subtraction of two grids (combinations). It will yield only dicts from
grid_athat don’t appear ingrid_b.You can create this doing
grid_a - grid_b. The only reason to use this directly is if you want to give it a name.a = Grid(('a', [1, 2]), ('b', [1, 2])) b = Grid(('a', [2]), ('b', [1])) # functionally equivalent c = a - b c = GridOmission(a, b, name='my-a-minus-b-grid') omit = list(b) c_items = [da for da in a if da not in omit]
Extending Grids¶
- class slurmjobs.grid.BaseGrid(name=None, ignore_job_id_keys=None, **constants)[source]¶
The base class for all grids. Use this if you want to extend another grid.
You just need to implement:
__iter__: This should yield all items generated by the grid__len__: This should tell you the number of items in the grid. If you cannot determine the length of a grid, then raise a TypeError (as the other grids do).__repr__: A nice string representation of the grid