# Path: DeepFried2/utils.py
# def tensors_for_ndarrays(datas, basename):
#     #if isinstance(datas, _np.ndarray):
#     try:
#         dtype, ndim = datas.dtype, datas.ndim
#     except AttributeError:
#         pass  # Not an array-like
#     else:
#         return make_tensor(dtype, ndim, basename)
# 
#     if isinstance(datas, (list, tuple)):
#         return [tensors_for_ndarrays(data, "{}_{}".format(basename, i)) for i, data in enumerate(datas)]
#     # Could potentially make it "any iterable" by removing above check.
#     # But would need to guarantee we never iterate over it twice, which is harder!
#     raise TypeError("I only understand lists or tuples of numpy arrays! (possibly nested)")
# 
# def flatten(what, types=(list, tuple), none_to_empty=False):
#     if what is None and none_to_empty:
#         return []
# 
#     if not isinstance(what, types):
#         return [what]
# 
#     # NOTE: I actually timed that this is faster than the comprehension,
#     #       even though it probably doesn't matter :)
#     # 350us vs 250us
#     ret = []
#     for sub in what:
#         ret += flatten(sub, types=types, none_to_empty=none_to_empty)
#     return ret


import DeepFried2 as df
from DeepFried2.utils import tensors_for_ndarrays, flatten
                # Need a very small eps to avoid 0/0 when all weights are 0!
                cost = cost / (1e-8 + df.T.mean(symb_weights))

        if with_penalties:
            for w, p in self.penalties:
                cost = cost + w*p.symb_forward()

        return cost

    def enable_weights(self):
        self.with_weights = True
        return self

    def enable_maskval(self, val):
        self.with_weights = val
        return self

    def enable_per_sample_cost(self):
        self._ret_per_sample = True
        return self

    def enable_nonzero_averaging(self):
        self._nonzero_averaging = True
        return self

    def forward(self, num_input, num_target, with_penalties=True, per_sample=False):
        # NOTE: using the GPU for such trivial computations as most costs
        # is actually somewhat slower (e.g. for RMSE: GPU 1.2ms vs. CPU 0.2ms).
        # So ideally, we'd like to compile a CPU-version here, but I don't know how!
        if (with_penalties, per_sample) not in self._fn_forward:

# Path: DeepFried2/utils.py
# def tensors_for_ndarrays(datas, basename):
#     #if isinstance(datas, _np.ndarray):
#     try:
#         dtype, ndim = datas.dtype, datas.ndim
#     except AttributeError:
#         pass  # Not an array-like
#     else:
#         return make_tensor(dtype, ndim, basename)
# 
#     if isinstance(datas, (list, tuple)):
#         return [tensors_for_ndarrays(data, "{}_{}".format(basename, i)) for i, data in enumerate(datas)]
#     # Could potentially make it "any iterable" by removing above check.
#     # But would need to guarantee we never iterate over it twice, which is harder!
#     raise TypeError("I only understand lists or tuples of numpy arrays! (possibly nested)")
# 
# def flatten(what, types=(list, tuple), none_to_empty=False):
#     if what is None and none_to_empty:
#         return []
# 
#     if not isinstance(what, types):
#         return [what]
# 
#     # NOTE: I actually timed that this is faster than the comprehension,
#     #       even though it probably doesn't matter :)
#     # 350us vs 250us
#     ret = []
#     for sub in what:
#         ret += flatten(sub, types=types, none_to_empty=none_to_empty)
#     return ret


# Path: DeepFried2/Criterion.py
import DeepFried2 as df
from DeepFried2.utils import tensors_for_ndarrays, flatten

                # Need a very small eps to avoid 0/0 when all weights are 0!
                cost = cost / (1e-8 + df.T.mean(symb_weights))

        if with_penalties:
            for w, p in self.penalties:
                cost = cost + w*p.symb_forward()

        return cost

    def enable_weights(self):
        self.with_weights = True
        return self

    def enable_maskval(self, val):
        self.with_weights = val
        return self

    def enable_per_sample_cost(self):
        self._ret_per_sample = True
        return self

    def enable_nonzero_averaging(self):
        self._nonzero_averaging = True
        return self

    def forward(self, num_input, num_target, with_penalties=True, per_sample=False):
        # NOTE: using the GPU for such trivial computations as most costs
        # is actually somewhat slower (e.g. for RMSE: GPU 1.2ms vs. CPU 0.2ms).
        # So ideally, we'd like to compile a CPU-version here, but I don't know how!
        if (with_penalties, per_sample) not in self._fn_forward:

            symb_in = tensors_for_ndarrays(num_input, 'Y')