def test_nested_basic_sanity(): """ Some trivially nested functions started throwing name errors, this test ensures we don't suffer from the same problems in the future. Just using single_pass(value=half) worked fine, the value() function was correctly replaced with the half() function, however single_pass(value=quarter) didn't work, it threw a NameError. """ data = np.array([1, 2, 3], dtype='float32') py_result = [half(x) for x in data] expected_half = [0.5, 1.0, 1.5] assert py_result == expected_half result_half = single_pass(data, value=half) assert np.allclose(expected_half, result_half) expected_quarter = [0.25, 0.5, 0.75] py_quarter = [quarter(x) for x in data] assert py_quarter == expected_quarter result = single_pass(data, value=quarter) assert np.allclose(expected_quarter, result)
def test_basic_sanity_local_nested_func(): """ If this test fails but the one above succeeds, then the insertion of func objects into the function copy's `globals` is broken. """ data = np.arange(10) * 2 assert data[0] == 0 assert data[1] == 2 assert data[-1] == 18 def square(x): return x * x assert square(2) == 4 result = single_pass(data, value=square) assert result[0] == 0 assert result[1] == 4 assert result[-1] == 324 assert square(2) == 4 assert square(3) == 9
def test_softplus_with_nan_and_inf(): data = np.array([np.nan, -np.inf, np.inf], dtype='float32') result = single_pass(data, value=softplus) assert np.isnan(result[0]) assert result[1] == 0. assert result[2] == np.inf
def test_math_tanh_function_supported(): data = np.arange(0.1, 1.0, 0.1, dtype='float32') result = single_pass(data, value=math.tanh) assert result[0] == approx(0.099668) assert result[1] == approx(0.19737533) assert result[2] == approx(0.29131263) assert sum(result) == approx(3.9521739)
def test_basic_sanity(): data = np.arange(-2, 2, dtype='float32') result = single_pass(data, value=logistic) assert result[0] == approx(0.11920292) assert result[1] == approx(0.26894143) assert result[2] == approx(0.5) assert result[3] == approx(0.7310586)
def test_math_sin_function_supported(): data = np.pi * np.array([0.25, 0.5, 0.75], dtype='float32') result = single_pass(data, value=math.sin) half_sqrt2 = math.sqrt(2) / 2 assert result[0] == approx(half_sqrt2) assert result[1] == approx(1.0) assert result[2] == approx(half_sqrt2) assert sum(result) == approx(2 * half_sqrt2 + 1)
def test_relu_basic_sanity(): data = np.arange(-2, 3, dtype='float32') result = single_pass(data, value=relu) assert result[0] == 0. assert result[1] == 0. assert result[2] == 0. assert result[3] == 1. assert result[4] == 2.
def test_softplus_basic_sanity(): data = np.array([-2, -1, 0, 1, 2], dtype='float32') result = single_pass(data, value=softplus) assert result[0] == approx(0.12692805) assert result[1] == approx(0.31326166) assert result[2] == approx(0.69314718) assert result[3] == approx(1.31326163) assert result[4] == approx(2.12692809)
def test_basic_sanity(): data = np.arange(10) assert data[0] == 0 assert data[1] == 1 assert data[-1] == 9 no_kwargs = single_pass(data) assert no_kwargs[0] == 0 assert no_kwargs[1] == 1 assert no_kwargs[-1] == 9 result = single_pass(data, value=twice) assert result[0] == 0 assert result[1] == 2 assert result[-1] == 18 assert result.sum() == 90 assert result.sum() == sum(twice(data))
def test_multi_column_support(): """ This still needs work - sum(x)/len(x) fails with a NameError, and the default return value is the same shape as input - ie, no reduction takes place. """ data = np.array(range(10), dtype='float').reshape((5, 2)) # Calculate mean with pure numpy calls... def mean(x): return np.sum(x) / x.size assert mean(data[0]) == 0.5 assert mean(data[4]) == 8.5 result = single_pass(data, value=mean) # TODO : update internals to be able to # reduce dimensions for reductions such as # mean assert result[0][0] == approx(0.5) assert result[1][0] == approx(2.5) assert result[2][0] == approx(4.5) assert result[3][0] == approx(6.5) assert result[4][0] == approx(8.5) # len(x) works fine... def mean_npy(x): return np.sum(x) / len(x) assert mean_npy(data[0]) == approx(0.5) assert mean_npy(data[1]) == approx(2.5) assert mean_npy(data[4]) == approx(8.5) result_npy = single_pass(data, value=mean_npy) assert result_npy[0][0] == approx(0.5) assert result_npy[4][0] == approx(8.5)
def test_transform_func_calls_second_func(): # Default iteration with no transforms data = np.array([1, 2, 3]) py_unit = [unit(x) for x in data] assert py_unit == data.tolist() default = single_pass(data) # The default behaviour should not # change the values in the data array expected = np.array([1, 2, 3]) assert np.allclose(expected, default) py_twice = [twice(x) for x in data] assert py_twice == (data * 2).tolist() # Now perform an iteration but change # the function for one that doubles. result = single_pass(data, value=twice) # Replacing the default function for one # that doubles the values. expected = np.array([2, 4, 6]) assert np.allclose(expected, result)
def test_multiple_transforms_top_level(): """ This tests for the 'free vars' issue - we had failures when the value= kwarg was decorated with @fs, but if you remove the decorator it's fine. """ data = np.array([1, 2, 3]) py_result = [multi(x) for x in data] assert py_result == [1, 64, 729] result = single_pass(data, value=multi) expected = np.array([1, 64, 729]) assert np.allclose(expected, result)
def test_nested_math_function_supported(): data = np.arange(10, dtype='float32') assert data[0] == approx(0.0) assert data[1] == approx(1.0) def calc(x): return 2 * math.log(x) assert calc(0.5) == approx(-1.38629436) # Assert ValueError for calling `log()` # on zero. # with raises(ValueError): # _ = single_pass(data, value=calc) result = single_pass(data[1:], value=calc) assert result[0] == approx(0.0) assert result[1] == approx(1.38629436) assert result[2] == approx(2.19722462) assert result.sum() == approx(25.603655)