Bases: NumpyOp
Perform a NumpyOp with a given probability.
Note that Sometimes should not be used to wrap an op whose output key(s) do not already exist in the data
dictionary. This would result in a problem when future ops / traces attempt to reference the output key, but
Sometimes declined to generate it. If you want to create a default value for a new key, simply use a LambdaOp before
invoking the Sometimes.
Parameters:
Name |
Type |
Description |
Default |
numpy_op |
NumpyOp
|
The operator to be performed. |
required
|
prob |
float
|
The probability of execution, which should be in the range: [0-1). |
0.5
|
Source code in fastestimator\fastestimator\op\numpyop\meta\sometimes.py
| @traceable()
class Sometimes(NumpyOp):
"""Perform a NumpyOp with a given probability.
Note that Sometimes should not be used to wrap an op whose output key(s) do not already exist in the data
dictionary. This would result in a problem when future ops / traces attempt to reference the output key, but
Sometimes declined to generate it. If you want to create a default value for a new key, simply use a LambdaOp before
invoking the Sometimes.
Args:
numpy_op: The operator to be performed.
prob: The probability of execution, which should be in the range: [0-1).
"""
def __init__(self, numpy_op: NumpyOp, prob: float = 0.5) -> None:
# We're going to try to collect any missing output keys from the data dictionary so that they don't get
# overridden when Sometimes chooses not to execute.
inps = set(numpy_op.inputs)
outs = set(numpy_op.outputs)
self.extra_inputs = list(outs - inps) # Used by traceability
self.inp_idx = len(numpy_op.inputs)
super().__init__(inputs=numpy_op.inputs + self.extra_inputs, outputs=numpy_op.outputs, mode=numpy_op.mode)
# Note that in_list and out_list will always be true
self.op = numpy_op
self.prob = prob
def __getstate__(self) -> Dict[str, Dict[Any, Any]]:
return {'op': self.op.__getstate__() if hasattr(self.op, '__getstate__') else {}}
def forward(self, data: List[np.ndarray], state: Dict[str, Any]) -> List[np.ndarray]:
"""Execute the wrapped operator a certain fraction of the time.
Args:
data: The information to be passed to the wrapped operator.
state: Information about the current execution context, for example {"mode": "train"}.
Returns:
The original `data`, or the `data` after running it through the wrapped operator.
"""
if self.prob > np.random.uniform():
data = data[:self.inp_idx] # Cut off the unnecessary inputs
if not self.op.in_list:
data = data[0]
data = self.op.forward(data, state)
if not self.op.out_list:
data = [data]
else:
data = [data[self.inputs.index(out)] for out in self.outputs]
return data
|
Execute the wrapped operator a certain fraction of the time.
Parameters:
Name |
Type |
Description |
Default |
data |
List[np.ndarray]
|
The information to be passed to the wrapped operator. |
required
|
state |
Dict[str, Any]
|
Information about the current execution context, for example {"mode": "train"}. |
required
|
Returns:
Type |
Description |
List[np.ndarray]
|
The original data , or the data after running it through the wrapped operator. |
Source code in fastestimator\fastestimator\op\numpyop\meta\sometimes.py
| def forward(self, data: List[np.ndarray], state: Dict[str, Any]) -> List[np.ndarray]:
"""Execute the wrapped operator a certain fraction of the time.
Args:
data: The information to be passed to the wrapped operator.
state: Information about the current execution context, for example {"mode": "train"}.
Returns:
The original `data`, or the `data` after running it through the wrapped operator.
"""
if self.prob > np.random.uniform():
data = data[:self.inp_idx] # Cut off the unnecessary inputs
if not self.op.in_list:
data = data[0]
data = self.op.forward(data, state)
if not self.op.out_list:
data = [data]
else:
data = [data[self.inputs.index(out)] for out in self.outputs]
return data
|