예제 #1
0
def test_operation_and_placeholder_gradients():
    a_array = np.ones([10, 5])
    b_array = np.ones([5, 10])
    a_sp = sp.Variable(a_array)
    b_sp = sp.Variable(b_array)

    a = sp.Placeholder()
    b = sp.Placeholder()
    y = sp.Lazy(sp.matmul)(a, b)

    a.assign_value(a_sp)
    b.assign_value(b_sp)
    result = y.run()

    grads = sp.get_gradients(result)
    sp_results = [result.array, grads[a_sp], grads[b_sp]]

    def func(a, b):
        return np.matmul(a, b)

    y_np = func(a_array, b_array)
    args = [a_array, b_array]
    num_grads = numgrads(func, args, n=1, delta=1)
    num_results = [y_np, num_grads[0], num_grads[1]]

    for spval, numval in zip(sp_results, num_results):
        error = rmse(spval, numval)
        assert error < EPS, f"rmse = {error}"
예제 #2
0
def test_conv2d_result():
    "Check that rd.conv2d gets the same results as tf.conv2d."
    images, kernels = generate_images_and_kernels([3, 55, 66, 5], [13, 22, 5, 7])

    for stride in range(1, 11, 3):
        for padding in ["SAME", "VALID"]:
            strides = [stride, stride]
            result_sp = sp.conv2d(
                sp.Variable(images), sp.Variable(kernels), padding=padding, strides=strides,
            )
            result_tf = tf.nn.conv2d(images, kernels, padding=padding, strides=strides)
            result_mean_error = np.mean(np.abs(result_sp.array - result_tf))
            assert result_mean_error < EPS, f"Mean error = {result_mean_error}"
예제 #3
0
def test_sgd_step():
    a = sp.Variable(np.random.random([3, 5]))
    b = sp.Variable(np.random.random([5, 3]))
    y_true = sp.Variable(np.ones([3, 3]))

    losses = []
    for _ in range(100):
        y_pred = sp.matmul(a, b)
        loss = sp.sum(sp.square(y_true - y_pred))
        losses.append(loss.array)
        
        gradients = sp.get_gradients(loss)
        sp.sgd_step([a, b], gradients)
    
    assert np.all(np.diff(losses) < 0), 'Not converging.'
예제 #4
0
def test_operation_and_placeholder_result():
    a_array = np.ones([10, 5])
    b_array = np.ones([5, 10])

    a = sp.Placeholder()
    b = sp.Placeholder()
    c = sp.Lazy(sp.matmul)(a, b)
    d = sp.Lazy(sp.mul)(c, sp.Variable(np.array(5)))

    a.assign_value(sp.Variable(a_array))
    b.assign_value(sp.Variable(b_array))

    result = d.run()  # runs the graph

    assert np.all(result.array - np.matmul(a_array, b_array) * 5) == 0, "invalid result"
예제 #5
0
def test_learnable_and_get_learnables():
    """Test that sp.get_learnables correctly obtains 
    sp.Variables that have been flagged by sp.learnable().
    """
    param_1 = sp.learnable(sp.Variable(np.array(5)))
    param_2 = sp.learnable(sp.Variable(np.array(10)))

    a = sp.Placeholder()
    b = sp.Placeholder()
    y = sp.Lazy(sp.matmul)(a, b)
    y = sp.Lazy(sp.mul)(y, param_1)
    y = sp.Lazy(sp.add)(y, param_2)

    params = sp.get_learnables(y)

    assert params == [param_1, param_2], "Did not get params."
예제 #6
0
def test_maxpool2d():
    np.random.seed(0)
    images = np.random.random([4, 12, 14, 3])
    images_sp = sp.Variable(images)
    images_tf = tf.Variable(images)

    for stride in range(1, 11, 3):
        strides = [stride, stride]
        for padding in ["SAME", "VALID"]:
            strides = [stride, stride]

            result_sp = sp.maxpool2d(images_sp, 2, 2, padding, strides)

            gradients_sp = sp.get_gradients(result_sp)
            grad_images_sp = gradients_sp[images_sp]

            with tf.GradientTape() as tape:
                result_tf = tf.nn.max_pool2d(images_tf, [1, 2, 2, 1], strides, padding)

            grad_images_tf = tape.gradient(result_tf, [images_tf])[0]

            # Compare results:
            results_error = rmse(result_sp.array, result_tf)
            assert results_error < EPS, f"Results error = {results_error}"

            # Compare gradients:
            imgrad_error = np.mean(np.abs(grad_images_sp - grad_images_tf))
            assert imgrad_error < EPS, f"Gradient error = {imgrad_error}"
예제 #7
0
def compare_results(args, sp_func, np_func, delta=1, eps=EPS):
    """Compares:
    - SmallPebble function output against NumPy function output.
    - SmallPebble gradient against numerical gradient.

    Notes: 
    `delta` can be 1 for linear functions,
    but should otherwise be a very small number.

    `eps` may need to be adjusted, in the case of
    inaccurate numerical approximations.
    """
    # Compute SmallPebble results
    args_sp = [sp.Variable(a) for a in args]
    y_sp = sp_func(*args_sp)
    grads_sp = sp.get_gradients(y_sp)
    grads_sp = [grads_sp[var] for var in args_sp]

    # Compute numerical results
    y_np = np_func(*args)
    grads_np = numgrads(np_func, args, n=1, delta=delta)

    # Compare output values
    error = rmse(y_sp.array, y_np)
    if error > eps:
        raise NumericalError("function output rmse:", error)

    # Compare gradient values
    for i, (spval, npval) in enumerate(zip(grads_sp, grads_np)):
        if error > eps:
            raise NumericalError(f"arg[{i}] gradient rmse:", error)
예제 #8
0
def test_conv2d_grads():
    "Compare TensorFlow derivatives with SmallPebble."
    images, kernels = generate_images_and_kernels([5, 16, 12, 2], [2, 4, 2, 3])

    images_sp = sp.Variable(images)
    kernels_sp = sp.Variable(kernels)
    images_tf = tf.Variable(images)
    kernels_tf = tf.Variable(kernels)

    for stride in range(1, 11, 3):
        strides = [stride, stride]
        for padding in ["SAME", "VALID"]:
            print("\n\n")
            print(stride)
            print(padding)

            # Calculate convolution and gradients with revdiff:
            result_sp = sp.conv2d(images_sp,
                                  kernels_sp,
                                  padding=padding,
                                  strides=strides)

            gradients_sp = sp.get_gradients(result_sp)
            grad_images_sp = gradients_sp[images_sp]
            grad_kernels_sp = gradients_sp[kernels_sp]

            # Calculate convolution and gradients with tensorflow:
            with tf.GradientTape() as tape:
                result_tf = tf.nn.conv2d(images_tf,
                                         kernels_tf,
                                         padding=padding,
                                         strides=strides)
            grad_images_tf, grad_kernels_tf = tape.gradient(
                result_tf, [images_tf, kernels_tf])

            # Compare the gradients:
            imgrad_error = np.mean(np.abs(grad_images_sp - grad_images_tf))
            assert imgrad_error < EPS, f"Image gradient error = {imgrad_error}"

            kerngrad_error = np.mean(np.abs(grad_kernels_sp - grad_kernels_tf))
            assert kerngrad_error < EPS, f"Kernel gradient error = {kerngrad_error}"