mirror of
https://github.com/pytorch/pytorch.git
synced 2025-10-21 13:44:15 +08:00
* Fix gradient_check on in-place ops * Fix hsm_test * Fix SplitByLengthOp test * Fix input_device_options for gradient_checker * Fix hypothesis_test_util.py
556 lines
20 KiB
Python
556 lines
20 KiB
Python
# TODO(jiayq): as more and more tests are moving to hypothesis test, we
|
|
# can gradually remove this test script. DO NOT ADD MORE TESTS TO THIS
|
|
# FILE.
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import print_function
|
|
from __future__ import unicode_literals
|
|
import numpy as np
|
|
from caffe2.python import (
|
|
brew,
|
|
core,
|
|
device_checker,
|
|
gradient_checker,
|
|
model_helper,
|
|
test_util,
|
|
workspace,
|
|
)
|
|
from caffe2.python.gradient_checker import NetGradientChecker
|
|
from caffe2.python.net_builder import ops, NetBuilder
|
|
from caffe2.proto import caffe2_pb2
|
|
|
|
import unittest
|
|
|
|
|
|
if workspace.has_gpu_support and workspace.NumCudaDevices() > 0:
|
|
gpu_device_option = caffe2_pb2.DeviceOption()
|
|
gpu_device_option.device_type = caffe2_pb2.CUDA
|
|
cpu_device_option = caffe2_pb2.DeviceOption()
|
|
gpu_device_checker = device_checker.DeviceChecker(
|
|
0.01, [gpu_device_option]
|
|
)
|
|
device_checker = device_checker.DeviceChecker(
|
|
0.01, [gpu_device_option, cpu_device_option]
|
|
)
|
|
gpu_gradient_checkers = [
|
|
gradient_checker.GradientChecker(
|
|
0.005, 0.05, gpu_device_option, "gpu_checker_ws"
|
|
),
|
|
]
|
|
gradient_checkers = [
|
|
gradient_checker.GradientChecker(
|
|
0.005, 0.05, gpu_device_option, "gpu_checker_ws"
|
|
),
|
|
gradient_checker.GradientChecker(
|
|
0.01, 0.05, cpu_device_option, "cpu_checker_ws"
|
|
),
|
|
]
|
|
else:
|
|
cpu_device_option = caffe2_pb2.DeviceOption()
|
|
gpu_device_option = None
|
|
gpu_device_checker = device_checker.DeviceChecker(
|
|
0.01, []
|
|
)
|
|
device_checker = device_checker.DeviceChecker(0.01, [cpu_device_option])
|
|
|
|
gradient_checkers = [
|
|
gradient_checker.GradientChecker(
|
|
0.01, 0.05, cpu_device_option, "cpu_checker_ws"
|
|
)
|
|
]
|
|
gpu_gradient_checkers = []
|
|
|
|
|
|
class TestLRN(test_util.TestCase):
|
|
|
|
def setUp(self):
|
|
self.test_configs = [(6, 10), (3, 13), ]
|
|
|
|
def testLRN(self):
|
|
for input_size, depth in self.test_configs:
|
|
op = core.CreateOperator("LRN",
|
|
["X"],
|
|
["Y", "Y_scale"],
|
|
size=11,
|
|
alpha=0.001,
|
|
beta=0.5,
|
|
bias=2.0,
|
|
order="NHWC"
|
|
)
|
|
X = np.random.rand(2, input_size, input_size,
|
|
depth).astype(np.float32)
|
|
res = device_checker.CheckSimple(op, [X], [0])
|
|
self.assertTrue(res)
|
|
for checker in gradient_checkers:
|
|
res, grad, grad_estimated = checker.CheckSimple(op, [X], 0, [0])
|
|
self.assertTrue(res)
|
|
|
|
|
|
class TestFlatten(test_util.TestCase):
|
|
|
|
def testFlatten(self):
|
|
op = core.CreateOperator("Flatten", ["X"], ["Y"])
|
|
X = np.random.rand(2, 3, 4, 5).astype(np.float32)
|
|
res = device_checker.CheckSimple(op, [X], [0])
|
|
self.assertTrue(res)
|
|
for checker in gradient_checkers:
|
|
res, grad, grad_estimated = checker.CheckSimple(op, [X], 0, [0])
|
|
self.assertTrue(res)
|
|
|
|
|
|
class TestConcat(test_util.TestCase):
|
|
|
|
def setUp(self):
|
|
self.test_configs = [
|
|
# input_size, depth1, depth2, depth3, depth4
|
|
(3, 2, 3, 4, 5),
|
|
(4, 5, 4, 3, 2),
|
|
]
|
|
|
|
def testConcatNHWC(self):
|
|
for input_size, d1, d2, d3, d4 in self.test_configs:
|
|
op = core.CreateOperator("Concat",
|
|
["X1", "X2", "X3", "X4"],
|
|
["Y", "Y_dims"],
|
|
order="NHWC"
|
|
)
|
|
Xs = [
|
|
np.random.rand(2, input_size, input_size,
|
|
d1).astype(np.float32),
|
|
np.random.rand(2, input_size, input_size,
|
|
d2).astype(np.float32),
|
|
np.random.rand(2, input_size, input_size,
|
|
d3).astype(np.float32),
|
|
np.random.rand(2, input_size, input_size, d4).astype(np.float32)
|
|
]
|
|
for i in range(4):
|
|
res = device_checker.CheckSimple(op, Xs, [0])
|
|
self.assertTrue(res)
|
|
for checker in gradient_checkers:
|
|
res, grad, grad_estimated = checker.CheckSimple(op, Xs, i,
|
|
[0])
|
|
self.assertTrue(res)
|
|
|
|
def testConcatNCHW(self):
|
|
for input_size, d1, d2, d3, d4 in self.test_configs:
|
|
op = core.CreateOperator("Concat",
|
|
["X1", "X2", "X3", "X4"],
|
|
["Y", "Y_dims"],
|
|
order="NCHW"
|
|
)
|
|
Xs = [
|
|
np.random.rand(2, d1, input_size,
|
|
input_size).astype(np.float32),
|
|
np.random.rand(2, d2, input_size,
|
|
input_size).astype(np.float32),
|
|
np.random.rand(2, d3, input_size,
|
|
input_size).astype(np.float32),
|
|
np.random.rand(2, d4, input_size, input_size).astype(np.float32)
|
|
]
|
|
for i in range(4):
|
|
res = device_checker.CheckSimple(op, Xs, [0])
|
|
self.assertTrue(res)
|
|
for checker in gradient_checkers:
|
|
res, grad, grad_estimated = checker.CheckSimple(op, Xs, i,
|
|
[0])
|
|
self.assertTrue(res)
|
|
|
|
|
|
class TestRelu(test_util.TestCase):
|
|
|
|
def setUp(self):
|
|
self.test_configs = [
|
|
# input size
|
|
# (0, 1),
|
|
(1, 1),
|
|
(2, 1),
|
|
(1, 3, 3, 1),
|
|
(2, 3, 3, 1),
|
|
(1, 5, 5, 3),
|
|
(2, 5, 5, 3),
|
|
]
|
|
|
|
def testRelu(self):
|
|
for input_size in self.test_configs:
|
|
op = core.CreateOperator("Relu", ["X"], ["Y"])
|
|
X = np.random.rand(*input_size).astype(np.float32)
|
|
# go away from the origin point to avoid kink problems
|
|
X += 0.01 * np.sign(X)
|
|
X[X == 0] = 0.01
|
|
res = device_checker.CheckSimple(op, [X], [0])
|
|
self.assertTrue(res)
|
|
for checker in gradient_checkers:
|
|
res, grad, grad_estimated = checker.CheckSimple(op, [X], 0, [0])
|
|
self.assertTrue(res)
|
|
|
|
|
|
class TestTanh(test_util.TestCase):
|
|
|
|
def setUp(self):
|
|
self.test_configs = [
|
|
# (0, 1),
|
|
(1, 1),
|
|
(2, 1),
|
|
(1, 2, 3, 4),
|
|
]
|
|
|
|
def testTanh(self):
|
|
for input_size in self.test_configs:
|
|
op = core.CreateOperator("Tanh", ["X"], ["Y"])
|
|
X = np.random.rand(*input_size).astype(np.float32) - 0.5
|
|
res = device_checker.CheckSimple(op, [X], [0])
|
|
self.assertTrue(res)
|
|
for checker in gradient_checkers:
|
|
res, grad, grad_estimated = checker.CheckSimple(op, [X], 0, [0])
|
|
self.assertTrue(res)
|
|
|
|
|
|
class TestAbs(test_util.TestCase):
|
|
|
|
def setUp(self):
|
|
self.test_configs = [
|
|
(1, 1),
|
|
(2, 3),
|
|
(2, 3, 4),
|
|
(2, 3, 4, 5),
|
|
]
|
|
|
|
def testAbs(self):
|
|
for input_size in self.test_configs:
|
|
op = core.CreateOperator("Abs", ["X"], ["Y"])
|
|
X = np.random.rand(*input_size).astype(np.float32)
|
|
# go away from the origin point to avoid kink problems
|
|
X += 0.01 * np.sign(X)
|
|
X[X == 0] = 0.01
|
|
res = device_checker.CheckSimple(op, [X], [0])
|
|
self.assertTrue(res)
|
|
for checker in gradient_checkers:
|
|
res, grad, grad_estimated = checker.CheckSimple(op, [X], 0, [0])
|
|
self.assertTrue(res)
|
|
|
|
class TestExp(test_util.TestCase):
|
|
|
|
def setUp(self):
|
|
self.test_configs = [
|
|
# (0, 1),
|
|
(1, 1),
|
|
(2, 1),
|
|
(1, 2, 3, 4),
|
|
]
|
|
|
|
def testExp(self):
|
|
for input_size in self.test_configs:
|
|
op = core.CreateOperator("Exp", ["X"], ["Y"])
|
|
X = np.random.rand(*input_size).astype(np.float32) - 0.5
|
|
res = device_checker.CheckSimple(op, [X], [0])
|
|
self.assertTrue(res)
|
|
for checker in gradient_checkers:
|
|
res, grad, grad_estimated = checker.CheckSimple(op, [X], 0, [0])
|
|
self.assertTrue(res)
|
|
|
|
class TestCos(test_util.TestCase):
|
|
|
|
def setUp(self):
|
|
self.test_configs = [
|
|
(1, 1),
|
|
(2, 3),
|
|
(2, 3, 4),
|
|
(2, 3, 4, 5),
|
|
]
|
|
|
|
def testCos(self):
|
|
for input_size in self.test_configs:
|
|
op = core.CreateOperator("Cos", ["X"], ["Y"])
|
|
X = np.random.rand(*input_size).astype(np.float32) - 0.5
|
|
res = device_checker.CheckSimple(op, [X], [0])
|
|
self.assertTrue(res)
|
|
for checker in gradient_checkers:
|
|
res, grad, grad_estimated = checker.CheckSimple(op, [X], 0, [0])
|
|
self.assertTrue(res)
|
|
|
|
class TestSin(test_util.TestCase):
|
|
|
|
def setUp(self):
|
|
self.test_configs = [
|
|
(1, 1),
|
|
(2, 3),
|
|
(2, 3, 4),
|
|
(2, 3, 4, 5),
|
|
]
|
|
|
|
def testSin(self):
|
|
for input_size in self.test_configs:
|
|
op = core.CreateOperator("Sin", ["X"], ["Y"])
|
|
X = np.random.rand(*input_size).astype(np.float32) - 0.5
|
|
res = device_checker.CheckSimple(op, [X], [0])
|
|
self.assertTrue(res)
|
|
for checker in gradient_checkers:
|
|
res, grad, grad_estimated = checker.CheckSimple(op, [X], 0, [0])
|
|
self.assertTrue(res)
|
|
|
|
class TestSigmoid(test_util.TestCase):
|
|
|
|
def setUp(self):
|
|
self.test_configs = [
|
|
# (0, 1),
|
|
(1, 1),
|
|
(2, 1),
|
|
(1, 2, 3, 4),
|
|
]
|
|
|
|
def testSigmoid(self):
|
|
for input_size in self.test_configs:
|
|
op = core.CreateOperator("Sigmoid", ["X"], ["Y"])
|
|
X = np.random.rand(*input_size).astype(np.float32) - 0.5
|
|
res = device_checker.CheckSimple(op, [X], [0])
|
|
self.assertTrue(res)
|
|
for checker in gradient_checkers:
|
|
res, grad, grad_estimated = checker.CheckSimple(op, [X], 0, [0])
|
|
self.assertTrue(res)
|
|
|
|
|
|
class TestSum(test_util.TestCase):
|
|
|
|
def setUp(self):
|
|
self.test_configs = [
|
|
# ((0, 1), False),
|
|
((1, 2, 3, 4), True),
|
|
((1, 2, 3, 4), False)]
|
|
|
|
def testSum(self):
|
|
for (input_size, in_place) in self.test_configs:
|
|
op = core.CreateOperator("Sum", ["X1", "X2"],
|
|
["Y" if not in_place else "X1"])
|
|
X1 = np.random.rand(*input_size).astype(np.float32) - 0.5
|
|
X2 = np.random.rand(*input_size).astype(np.float32) - 0.5
|
|
res = device_checker.CheckSimple(op, [X1, X2], [0])
|
|
self.assertTrue(res)
|
|
for checker in gradient_checkers:
|
|
res, grad, grad_estimated = checker.CheckSimple(
|
|
op, [X1, X2], 0, [0])
|
|
self.assertTrue(res)
|
|
res, grad, grad_estimated = checker.CheckSimple(
|
|
op, [X1, X2], 1, [0])
|
|
self.assertTrue(res)
|
|
|
|
|
|
class TestMakeTwoClass(test_util.TestCase):
|
|
|
|
def setUp(self):
|
|
self.test_configs = [
|
|
# input size
|
|
# (0, 1),
|
|
(1,),
|
|
(7,),
|
|
(1, 3),
|
|
(2, 5),
|
|
]
|
|
|
|
def testMakeTwoClass(self):
|
|
for input_size in self.test_configs:
|
|
op = core.CreateOperator("MakeTwoClass", ["X"], ["Y"])
|
|
X = np.random.rand(*input_size).astype(np.float32)
|
|
# step a little to avoid gradient problems
|
|
X[X < 0.01] += 0.01
|
|
X[X > 0.99] -= 0.01
|
|
res = device_checker.CheckSimple(op, [X], [0])
|
|
self.assertTrue(res)
|
|
for checker in gradient_checkers:
|
|
res, grad, grad_estimated = checker.CheckSimple(op, [X], 0, [0])
|
|
self.assertTrue(res)
|
|
|
|
|
|
class TestNetGradientChecker(test_util.TestCase):
|
|
def test_net_gradient_checker(self):
|
|
model = model_helper.ModelHelper(name="test")
|
|
const = model.net.AddExternalInputs("const1", "const2")
|
|
fc = brew.fc(model, dim_in=3, dim_out=4, blob_in="X", blob_out="Y", axis=0)
|
|
dist = [model.net.SquaredL2Distance([fc, c]) for c in const]
|
|
losses = [model.net.AveragedLoss(d) for d in dist] # using two losses here
|
|
|
|
workspace.RunNetOnce(model.param_init_net)
|
|
NetGradientChecker.Check(
|
|
model.net,
|
|
outputs_with_grad=losses,
|
|
input_values={"X": np.array([1, 2, 3], dtype="float32"),
|
|
const[0]: np.array([1, 1, 1, 1], dtype="float32"),
|
|
const[1]: np.array([2, 2, 2, 2], dtype="float32")},
|
|
input_to_check="X",
|
|
)
|
|
|
|
def test_net_comparison(self):
|
|
# (a + b) * (c + d) == a * c + a * d + b * c + b * d
|
|
net1 = core.Net("net1")
|
|
a, b, c, d = net1.AddExternalInputs("a", "b", "c", "d")
|
|
a_b = net1.Sum([a, b], "a+b")
|
|
c_d = net1.Sum([c, d], "c+d")
|
|
x = net1.Mul([a_b, c_d], "x")
|
|
|
|
net2 = core.Net("net2")
|
|
ac = net2.Mul([a, c], "ac")
|
|
ad = net2.Mul([a, d], "ad")
|
|
bc = net2.Mul([b, c], "bc")
|
|
bd = net2.Mul([b, d], "bd")
|
|
y = net2.Sum([ac, ad, bc, bd], "y")
|
|
|
|
input_values = {blob: np.array([i], dtype=np.float32)
|
|
for i, blob in enumerate([a, b, c, d])}
|
|
|
|
NetGradientChecker.CompareNets(
|
|
[net1, net2], [[x], [y]], [0],
|
|
inputs_with_grads=[a, b, c, d],
|
|
input_values=input_values,
|
|
)
|
|
|
|
|
|
class TestIf(test_util.TestCase):
|
|
def testIf(self):
|
|
W_a_values = [2.0, 1.5]
|
|
B_a_values = [0.5]
|
|
W_b_values = [7.0, 3.5]
|
|
B_b_values = [1.5]
|
|
|
|
with NetBuilder(_use_control_ops=True) as init_nb:
|
|
W_a = ops.UniformFill([], "W_a", shape=[1, 2], min=-1., max=1.)
|
|
B_a = ops.ConstantFill([], "B_a", shape=[1], value=0.0)
|
|
W_b = ops.UniformFill([], "W_b", shape=[1, 2], min=-1., max=1.)
|
|
B_b = ops.ConstantFill([], "B_b", shape=[1], value=0.0)
|
|
|
|
W_gt_a = ops.GivenTensorFill(
|
|
[], "W_gt_a", shape=[1, 2], values=W_a_values)
|
|
B_gt_a = ops.GivenTensorFill([], "B_gt_a", shape=[1], values=B_a_values)
|
|
W_gt_b = ops.GivenTensorFill(
|
|
[], "W_gt_b", shape=[1, 2], values=W_b_values)
|
|
B_gt_b = ops.GivenTensorFill([], "B_gt_b", shape=[1], values=B_b_values)
|
|
|
|
params = [W_gt_a, B_gt_a, W_a, B_a, W_gt_b, B_gt_b, W_b, B_b]
|
|
|
|
with NetBuilder(_use_control_ops=True, initial_scope=params) as train_nb:
|
|
Y_pred = ops.ConstantFill([], "Y_pred", shape=[1], value=0.0)
|
|
Y_noise = ops.ConstantFill([], "Y_noise", shape=[1], value=0.0)
|
|
|
|
switch = ops.UniformFill(
|
|
[], "switch", shape=[1], min=-1., max=1., run_once=0)
|
|
zero = ops.ConstantFill([], "zero", shape=[1], value=0.0)
|
|
X = ops.GaussianFill(
|
|
[], "X", shape=[4096, 2], mean=0.0, std=1.0, run_once=0)
|
|
noise = ops.GaussianFill(
|
|
[], "noise", shape=[4096, 1], mean=0.0, std=1.0, run_once=0)
|
|
|
|
with ops.IfNet(ops.LT([switch, zero])):
|
|
Y_gt = ops.FC([X, W_gt_a, B_gt_a], "Y_gt")
|
|
ops.Add([Y_gt, noise], Y_noise)
|
|
ops.FC([X, W_a, B_a], Y_pred)
|
|
with ops.Else():
|
|
Y_gt = ops.FC([X, W_gt_b, B_gt_b], "Y_gt")
|
|
ops.Add([Y_gt, noise], Y_noise)
|
|
ops.FC([X, W_b, B_b], Y_pred)
|
|
|
|
dist = ops.SquaredL2Distance([Y_noise, Y_pred], "dist")
|
|
loss = dist.AveragedLoss([], ["loss"])
|
|
|
|
assert len(init_nb.get()) == 1, "Expected a single init net produced"
|
|
assert len(train_nb.get()) == 1, "Expected a single train net produced"
|
|
|
|
train_net = train_nb.get()[0]
|
|
gradient_map = train_net.AddGradientOperators([loss])
|
|
|
|
init_net = init_nb.get()[0]
|
|
ITER = init_net.ConstantFill(
|
|
[], "ITER", shape=[1], value=0, dtype=core.DataType.INT32)
|
|
train_net.Iter(ITER, ITER)
|
|
LR = train_net.LearningRate(ITER, "LR", base_lr=-0.1,
|
|
policy="step", stepsize=20, gamma=0.9)
|
|
ONE = init_net.ConstantFill([], "ONE", shape=[1], value=1.)
|
|
train_net.WeightedSum([W_a, ONE, gradient_map[W_a], LR], W_a)
|
|
train_net.WeightedSum([B_a, ONE, gradient_map[B_a], LR], B_a)
|
|
train_net.WeightedSum([W_b, ONE, gradient_map[W_b], LR], W_b)
|
|
train_net.WeightedSum([B_b, ONE, gradient_map[B_b], LR], B_b)
|
|
|
|
workspace.RunNetOnce(init_net)
|
|
workspace.CreateNet(train_net)
|
|
# print("Before training, W_a is: {}".format(workspace.FetchBlob("W_a")))
|
|
# print("Before training, B_a is: {}".format(workspace.FetchBlob("B_a")))
|
|
# print("Before training, W_b is: {}".format(workspace.FetchBlob("W_b")))
|
|
# print("Before training, B_b is: {}".format(workspace.FetchBlob("B_b")))
|
|
|
|
for _epoch in range(1000):
|
|
workspace.RunNet(train_net.Proto().name)
|
|
|
|
# print("After training, W_a is: {}".format(workspace.FetchBlob("W_a")))
|
|
# print("After training, B_a is: {}".format(workspace.FetchBlob("B_a")))
|
|
# print("After training, W_b is: {}".format(workspace.FetchBlob("W_b")))
|
|
# print("After training, B_b is: {}".format(workspace.FetchBlob("B_b")))
|
|
# print("Ground truth W_a is: {}".format(workspace.FetchBlob("W_gt_a")))
|
|
# print("Ground truth B_a is: {}".format(workspace.FetchBlob("B_gt_a")))
|
|
# print("Ground truth W_b is: {}".format(workspace.FetchBlob("W_gt_b")))
|
|
# print("Ground truth B_b is: {}".format(workspace.FetchBlob("B_gt_b")))
|
|
|
|
values_map = {
|
|
"W_a": W_a_values,
|
|
"B_a": B_a_values,
|
|
"W_b": W_b_values,
|
|
"B_b": B_b_values,
|
|
}
|
|
|
|
train_eps = 0.01
|
|
|
|
for blob_name, values in values_map.items():
|
|
trained_values = workspace.FetchBlob(blob_name)
|
|
if trained_values.ndim == 2:
|
|
self.assertEqual(trained_values.shape[0], 1)
|
|
trained_values = trained_values[0][:]
|
|
else:
|
|
self.assertEqual(trained_values.ndim, 1)
|
|
|
|
self.assertEqual(trained_values.size, len(values))
|
|
for idx in range(len(trained_values)):
|
|
self.assertTrue(abs(trained_values[idx] - values[idx]) < train_eps)
|
|
|
|
|
|
class TestWhile(test_util.TestCase):
|
|
@unittest.skip("Skip flaky test.")
|
|
def testWhile(self):
|
|
with NetBuilder(_use_control_ops=True) as nb:
|
|
ops.Copy(ops.Const(0), "i")
|
|
ops.Copy(ops.Const(1), "one")
|
|
ops.Copy(ops.Const(2), "two")
|
|
ops.Copy(ops.Const(2.0), "x")
|
|
ops.Copy(ops.Const(3.0), "y")
|
|
ops.Copy(ops.Const(2.0), "z")
|
|
# raises x to the power of 4 and y to the power of 2
|
|
# and z to the power of 3
|
|
with ops.WhileNet():
|
|
with ops.Condition():
|
|
ops.Add(["i", "one"], "i")
|
|
ops.LE(["i", "two"])
|
|
ops.Pow("x", "x", exponent=2.0)
|
|
with ops.IfNet(ops.LT(["i", "two"])):
|
|
ops.Pow("y", "y", exponent=2.0)
|
|
with ops.Else():
|
|
ops.Pow("z", "z", exponent=3.0)
|
|
|
|
ops.Add(["x", "y"], "x_plus_y")
|
|
ops.Add(["x_plus_y", "z"], "s")
|
|
|
|
assert len(nb.get()) == 1, "Expected a single net produced"
|
|
net = nb.get()[0]
|
|
|
|
net.AddGradientOperators(["s"])
|
|
workspace.RunNetOnce(net)
|
|
# (x^4)' = 4x^3
|
|
self.assertAlmostEqual(workspace.FetchBlob("x_grad"), 32)
|
|
self.assertAlmostEqual(workspace.FetchBlob("x"), 16)
|
|
# (y^2)' = 2y
|
|
self.assertAlmostEqual(workspace.FetchBlob("y_grad"), 6)
|
|
self.assertAlmostEqual(workspace.FetchBlob("y"), 9)
|
|
# (z^3)' = 3z^2
|
|
self.assertAlmostEqual(workspace.FetchBlob("z_grad"), 12)
|
|
self.assertAlmostEqual(workspace.FetchBlob("z"), 8)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
workspace.GlobalInit(["python"])
|
|
unittest.main()
|