def test_percentile_tf_input_axis_not_none_keepdims_false(self): with self.subTest("two_dimensional"): t = tf.constant([[1, 3, 9], [2, 7, 5], [8, 4, 6]]) obj1 = fe.backend.percentile(t, percentiles=50, axis=0, keepdims=False) obj2 = tf.constant([2, 4, 6]) self.assertTrue(is_equal(obj1, obj2)) with self.subTest("single_axis"): obj1 = fe.backend.percentile(t, percentiles=50, axis=1, keepdims=False) obj2 = tf.constant([3, 5, 6]) self.assertTrue(is_equal(obj1, obj2)) with self.subTest("multi_axis"): obj1 = fe.backend.percentile(t, percentiles=50, axis=[0, 1], keepdims=False) obj2 = tf.constant(5) self.assertTrue(is_equal(obj1, obj2)) with self.subTest("multi_percentile"): obj1 = fe.backend.percentile(t, percentiles=[0, 50], axis=[0, 1], keepdims=False) obj2 = tf.constant([1, 5]) self.assertTrue(is_equal(obj1, obj2))
def test_on_batch_end(self): self.pbm_calibrator.y_true = [] self.pbm_calibrator.y_pred = [] batch1 = { 'y': np.array([0, 0, 1, 1]), 'y_pred': np.array([[1.0, 0.0], [1.0, 0.0], [0.0, 1.0], [0.0, 1.0]]) } self.pbm_calibrator.on_batch_end(data=Data(batch1)) with self.subTest('Check true values'): self.assertTrue( is_equal(self.pbm_calibrator.y_true, list(batch1['y']))) with self.subTest('Check pred values'): self.assertTrue( is_equal(self.pbm_calibrator.y_pred, list(batch1['y_pred']))) batch2 = { 'y': np.array([1, 1, 0, 0]), 'y_pred': np.array([[0.0, 1.0], [0.0, 1.0], [1.0, 0.0], [1.0, 0.0]]) } self.pbm_calibrator.on_batch_end(data=Data(batch2)) with self.subTest('Check true values (2 batches)'): self.assertTrue( is_equal(self.pbm_calibrator.y_true, list(batch1['y']) + list(batch2['y']))) with self.subTest('Check pred values (2 batches)'): self.assertTrue( is_equal(self.pbm_calibrator.y_pred, list(batch1['y_pred']) + list(batch2['y_pred'])))
def test_check_nan_torch_value(self): with self.subTest('Detect NaN values'): self.assertTrue( is_equal(check_nan(self.data_torch_nan), self.op_torch)) with self.subTest('Detect Inf values'): self.assertTrue( is_equal(check_nan(self.data_torch_inf), self.op_torch))
def test_pipeline_get_result_dict_batch_size_train_eval(self): pipeline = fe.Pipeline(train_data=self.sample_torch_dataset, eval_data=self.sample_torch_dataset, ops=NumpyOpAdd1(inputs="x", outputs="y"), batch_size={ "train": 2, "eval": 1 }) data_train = pipeline.get_results(mode="train", epoch=1) time.sleep( 2 ) # avoid DataLoader worker (pid #) is killed by signal: Aborted. data_eval = pipeline.get_results(mode="eval", epoch=1) time.sleep( 2 ) # avoid DataLoader worker (pid #) is killed by signal: Aborted. data_train["x"] = data_train["x"].numpy() data_train["y"] = data_train["y"].numpy() data_eval["x"] = data_eval["x"].numpy() data_eval["y"] = data_eval["y"].numpy() ans_train = { "x": np.array([[0], [1]], dtype=np.float32), "y": np.array([[1], [2]], dtype=np.float32) } ans_eval = { "x": np.array([[0]], dtype=np.float32), "y": np.array([[1]], dtype=np.float32) } self.assertTrue(is_equal(data_train, ans_train)) self.assertTrue(is_equal(data_eval, ans_eval))
def test_pipeline_get_loader_torch_dataset_with_batch_size(self): with self.subTest(shuffle=False): pipeline = fe.Pipeline(train_data=self.sample_torch_dataset, batch_size=2) loader = pipeline.get_loader(mode="train", shuffle=False) results = [] for idx, batch in enumerate(loader, start=1): results.append(batch) if idx == 2: break ans = [{ "x": torch.tensor([[0], [1]], dtype=torch.float32), "y": torch.tensor([[-99], [-98]], dtype=torch.float32) }, { "x": torch.tensor([[2], [3]], dtype=torch.float32), "y": torch.tensor([[-97], [-96]], dtype=torch.float32) }] self.assertTrue(is_equal(results, ans)) with self.subTest(shuffle=True): pipeline = fe.Pipeline(train_data=self.sample_torch_dataset, batch_size=2) loader = pipeline.get_loader(mode="train", shuffle=True) results = [] for idx, batch in enumerate(loader, start=1): results.append(batch) if idx == 2: break wrong_ans = [{ "x": torch.tensor([[0], [1]], dtype=torch.float32), "y": torch.tensor([[-99], [-98]], dtype=torch.float32) }, { "x": torch.tensor([[2], [3]], dtype=torch.float32), "y": torch.tensor([[-97], [-96]], dtype=torch.float32) }] self.assertFalse(is_equal(results, wrong_ans)) with self.subTest(shuffle=None): pipeline = fe.Pipeline(train_data=self.sample_torch_dataset, batch_size=2) loader = pipeline.get_loader(mode="train", shuffle=None) results = [] for idx, batch in enumerate(loader, start=1): results.append(batch) if idx == 2: break wrong_ans = [{ "x": torch.tensor([[0], [1]], dtype=torch.float32), "y": torch.tensor([[-99], [-98]], dtype=torch.float32) }, { "x": torch.tensor([[2], [3]], dtype=torch.float32), "y": torch.tensor([[-97], [-96]], dtype=torch.float32) }] self.assertFalse(is_equal(results, wrong_ans)) # if shuffle is None and has specify batch_size, it will shuffle
def test_input_multiple_keys(self): image = ReadMat(inputs='x', outputs=['a', 'label']) output = image.forward(data=self.mat_path, state={}) with self.subTest('Check data in mat'): self.assertTrue(is_equal(output[0], self.expected_mat_output)) with self.subTest('Check label in mat'): self.assertTrue(is_equal(output[1], np.array(['testcase'])))
def test_shared_variable_over_model_torch(self): def instantiate_system(): system = sample_system_object_torch() submodel = OneLayerTorchModel() model = fe.build(model_fn=lambda: TestModel(submodel), optimizer_fn='adam', model_name='torch') model2 = fe.build(model_fn=lambda: TestModel(submodel), optimizer_fn='adam', model_name='torch2') system.network = fe.Network(ops=[ ModelOp(model=model, inputs="x_out", outputs="y_pred"), ModelOp(model=model2, inputs="x_out", outputs="y_pred2"), ]) return system system = instantiate_system() # check if multi-gpu system if torch.cuda.device_count() > 1: model_0 = system.network.ops[0].model.module model_1 = system.network.ops[1].model.module else: model_0 = system.network.ops[0].model model_1 = system.network.ops[1].model # make some change new_weight = torch.tensor([[1, 1, 1]], dtype=torch.float32) model_0.submodel.fc1.weight.data = new_weight # save the state save_path = tempfile.mkdtemp() system.save_state(save_path) # reinstantiate system and load the state system = instantiate_system() shared_variable = model_0.submodel.fc1.weight system.load_state(save_path) with self.subTest("Check model varaible was re-loaded"): self.assertTrue( is_equal(new_weight, model_0.submodel.fc1.weight.data)) self.assertTrue( is_equal(new_weight, model_1.submodel.fc1.weight.data)) with self.subTest("Check model variable is still shared"): new_weight = torch.tensor([[2, 2, 2]], dtype=torch.float32) model_0.submodel.fc1.weight.data = new_weight self.assertTrue( is_equal(model_0.submodel.fc1.weight.data, model_1.submodel.fc1.weight.data)) with self.subTest( "Check that variable is still linked to outside code"): new_weight = torch.tensor([[3, 3, 3]], dtype=torch.float32) shared_variable.data = new_weight self.assertTrue( is_equal(new_weight, model_0.submodel.fc1.weight.data))
def test_qms(self): test_data = get_sample_tf_dataset() pipeline = fe.Pipeline(test_data=test_data) model = fe.build(model_fn=one_layer_tf_model, optimizer_fn="adam") network = fe.Network( ops=[ModelOp(model=model, inputs="x", outputs="y_pred")]) test_title = "Integration Test of QMSTest" temp_dir = tempfile.mkdtemp() json_output = os.path.join(temp_dir, "test.json") doc_output = os.path.join(temp_dir, "summary.docx") test_descriptions = [ "first result is greater than 0", "second result is greater than 0" ] traces = [ PassTrace(inputs="y_pred", mode="test"), QMSTest( test_descriptions=test_descriptions, test_criterias=[ lambda y_pred: y_pred[0][0][0] > 0, # 1*1 + 1*2 + 1*3 > 0 lambda y_pred: y_pred[0][1][0] > 0, # 1*1 + 2*2 + 3*(-3) > 0 ], test_title=test_title, json_output=json_output, doc_output=doc_output) ] estimator = fe.Estimator(pipeline=pipeline, network=network, epochs=1, traces=traces) with patch("fastestimator.trace.io.qms.json.dump") as fake_dump, \ patch("fastestimator.trace.io.qms._QMSDocx") as fake_qms: estimator.test() (json_summary, json_fp), _ = fake_dump.call_args with self.subTest("check json summary dict"): ans = { "title": test_title, "stories": [{ "description": test_descriptions[0], "passed": "True" }, { "description": test_descriptions[1], "passed": "False" }] } self.assertTrue(is_equal(json_summary, ans)) with self.subTest("check json summary stored path"): self.assertTrue(is_equal(json_fp.name, json_output)) with self.subTest("check call the _QMSDocx correctly"): ans = (1, 1) # (total_pass, total_fail) self.assertEqual(fake_qms.call_args[0], ans)
def test_multi_input(self): data = [self.img1_path, self.img2_path] image = ReadImage(inputs='x', outputs='x') output = image.forward(data=data, state={}) with self.subTest('Check first image in data'): self.assertTrue(is_equal(output[0], self.expected_image_output)) with self.subTest('Check second image in data'): self.assertTrue( is_equal(output[1], self.expected_second_image_output))
def test_is_equal_torch_tensor(self): obj1 = torch.Tensor([1.5, 0, -2.3]) obj2 = torch.Tensor([1.5, 0, -2.3]) self.assertTrue(is_equal(obj1, obj2)) obj2 = torch.Tensor([1.5, 0, -10]) self.assertFalse(is_equal(obj1, obj2)) obj2 = torch.Tensor([1.5, 0, -2.3, 100]) self.assertFalse(is_equal(obj1, obj2))
def test_is_equal_numpy_array(self): obj1 = np.array([1, 2.2, -3]) obj2 = np.array([1, 2.2, -3]) self.assertTrue(is_equal(obj1, obj2)) obj2 = np.array([1, 2.2, -3, 4.0]) self.assertFalse(is_equal(obj1, obj2)) obj2 = np.array([-1, 2.2, 3]) self.assertFalse(is_equal(obj1, obj2))
def test_permute_torch(self): t = torch.tensor([[[0, 1], [2, 3]], [[4, 5], [6, 7]], [[8, 9], [10, 11]]]) with self.subTest("permutation case 1"): obj1 = fe.backend.permute(t, [2, 0, 1]) obj2 = torch.tensor([[[0, 2], [4, 6], [8, 10]], [[1, 3], [5, 7], [9, 11]]]) self.assertTrue(is_equal(obj1, obj2)) with self.subTest("permutation case 2"): obj1 = fe.backend.permute(t, [0, 2, 1]) obj2 = torch.tensor([[[0, 2], [1, 3]], [[4, 6], [5, 7]], [[8, 10], [9, 11]]]) self.assertTrue(is_equal(obj1, obj2))
def test_shared_variable_over_model_tf(self): def instantiate_system(): system = sample_system_object() submodel = one_layer_tf_model() model = fe.build(model_fn=lambda: test_model(submodel), optimizer_fn='adam', model_name='tf') model2 = fe.build(model_fn=lambda: test_model(submodel), optimizer_fn='adam', model_name='tf2') system.network = fe.Network(ops=[ ModelOp(model=model, inputs="x_out", outputs="y_pred"), ModelOp(model=model2, inputs="x_out", outputs="y_pred2"), ]) return system system = instantiate_system() # make some change new_weight = [np.array([[1.0], [1.0], [1.0]])] system.network.ops[0].model.layers[1].set_weights(new_weight) # save the state save_path = tempfile.mkdtemp() system.save_state(save_path) # reinstantiate system and load the state system = instantiate_system() shared_variable = system.network.ops[0].model.layers[1] system.load_state(save_path) with self.subTest("Check model varaible was re-loaded"): self.assertTrue( is_equal(new_weight, system.network.ops[0].model.layers[1].get_weights())) self.assertTrue( is_equal(new_weight, system.network.ops[1].model.layers[1].get_weights())) with self.subTest("Check model variable is still shared"): new_weight = [np.array([[2.0], [2.0], [2.0]])] system.network.ops[0].model.layers[1].set_weights(new_weight) self.assertTrue( is_equal(system.network.ops[0].model.layers[1].get_weights(), system.network.ops[1].model.layers[1].get_weights())) with self.subTest( "Check that variable is still linked to outside code"): new_weight = [np.array([[3.0], [3.0], [3.0]])] shared_variable.set_weights(new_weight) self.assertTrue( is_equal(new_weight, system.network.ops[0].model.layers[1].get_weights()))
def test_permute_np(self): n = np.array([[[0, 1], [2, 3]], [[4, 5], [6, 7]], [[8, 9], [10, 11]]]) with self.subTest("permutation case 1"): obj1 = fe.backend.permute(n, [2, 0, 1]) obj2 = np.array([[[0, 2], [4, 6], [8, 10]], [[1, 3], [5, 7], [9, 11]]]) self.assertTrue(is_equal(obj1, obj2)) with self.subTest("permutation case 2"): obj1 = fe.backend.permute(n, [0, 2, 1]) obj2 = np.array([[[0, 2], [1, 3]], [[4, 6], [5, 7]], [[8, 10], [9, 11]]]) self.assertTrue(is_equal(obj1, obj2))
def test_gather_from_batch_tf_input(self): tensor = tf.constant([[0, 1], [2, 3], [4, 5]]) indice = tf.constant([1, 0, 1]) obj1 = fe.backend.gather_from_batch(tensor, indice) obj2 = tf.constant([1, 2, 5]) self.assertTrue(is_equal(obj1, obj2)) tensor = tf.constant([[[0, 1], [2, 3]], [[4, 5], [6, 7]], [[8, 9], [10, 11]]]) obj1 = fe.backend.gather_from_batch(tensor, indice) obj2 = tf.constant([[2, 3], [4, 5], [10, 11]]) self.assertTrue(is_equal(obj1, obj2))
def test_tf_input(self): model = fe.build(model_fn=one_layer_tf_model, optimizer_fn="adam") op = ModelOp(inputs='x', outputs='x', model=model) op.build(framework='tf', device=None) with self.subTest("Eager"): output = op.forward(data=self.tf_input_data, state=self.state) self.assertTrue(is_equal(output.numpy(), self.output)) forward_fn = tf.function(op.forward) with self.subTest("Static Call 1"): output = forward_fn(data=self.tf_input_data, state=self.state) self.assertTrue(is_equal(output.numpy(), self.output)) with self.subTest("Static Call 2"): output = forward_fn(data=self.tf_input_data, state=self.state) self.assertTrue(is_equal(output.numpy(), self.output))
def test_is_equal_set(self): obj1 = set() obj2 = set() self.assertTrue(is_equal(obj1, obj2)) obj1 = {1, 2, 3} obj2 = {1, 2, 3} self.assertTrue(is_equal(obj1, obj2)) obj2 = {1, 2, 4} self.assertFalse(is_equal(obj1, obj2)) obj2 = {1, 2, 3, 4} self.assertFalse(is_equal(obj1, obj2))
def test_is_equal_tuple(self): obj1 = tuple() obj2 = tuple() self.assertTrue(is_equal(obj1, obj2)) obj1 = (1, 2, 3) obj2 = (1, 2, 3) self.assertTrue(is_equal(obj1, obj2)) obj2 = (1, 2, 4) self.assertFalse(is_equal(obj1, obj2)) obj2 = (1, 2, 3, 4) self.assertFalse(is_equal(obj1, obj2))
def test_is_equal_list(self): obj1 = [] obj2 = [] self.assertTrue(is_equal(obj1, obj2)) obj1 = [1, 2, 3] obj2 = [1, 2, 3] self.assertTrue(is_equal(obj1, obj2)) obj2 = [1, 2, 4] self.assertFalse(is_equal(obj1, obj2)) obj2 = [1, 2, 3, 4] self.assertFalse(is_equal(obj1, obj2))
def test_is_equal_type_mixture(self): obj1 = [tf.constant([1, 2]), tf.constant([0.1, 0.2])] obj2 = [tf.constant([1, 2]), tf.constant([0.1, 0.2])] self.assertTrue(is_equal(obj1, obj2)) obj2 = [tf.constant([1, 2]), tf.constant([0.1, -0.2])] self.assertFalse(is_equal(obj1, obj2)) obj1 = {"1": np.array([-1, 2.5]), "2": {"3": torch.Tensor([1.5])}} obj2 = {"1": np.array([-1, 2.5]), "2": {"3": torch.Tensor([1.5])}} self.assertTrue(is_equal(obj1, obj2)) obj2 = {"1": [-1, 2.5], "2": {"3": torch.Tensor([1.5])}} self.assertFalse(is_equal(obj1, obj2))
def check_gradient(x): with tf.GradientTape(persistent=True) as tape: y = x * x with self.subTest("check gradient"): obj1 = fe.backend.get_gradient( target=y, sources=x, tape=tape) # [2.0, 4.0, 6.0] obj2 = tf.constant([2.0, 4.0, 6.0]) self.assertTrue(is_equal(obj1, obj2)) with self.subTest("check gradient of gradient"): obj1 = fe.backend.get_gradient(target=obj1, sources=x, tape=tape) # None self.assertTrue(is_equal(obj1, None))
def test_get_gradient_torch_tensor_higher_order_true(self): x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True) y = x * x with self.subTest("check gradient"): obj1 = fe.backend.get_gradient( target=y, sources=x, higher_order=True) # [2.0, 4.0, 6.0] obj2 = torch.tensor([2.0, 4.0, 6.0]) self.assertTrue(is_equal(obj1, obj2)) with self.subTest("check gradient of gradient"): obj1 = fe.backend.get_gradient(target=obj1, sources=x) # [2.0, 2.0, 2.0] obj2 = torch.tensor([2.0, 2.0, 2.0]) self.assertTrue(is_equal(obj1, obj2))
def test_is_equal_dict_mixture(self): obj1 = dict() obj2 = dict() self.assertTrue(is_equal(obj1, obj2)) obj1 = {"1": 1, "2": 0, "3": -1.5} obj2 = {"1": 1, "2": 0, "3": -1.5} self.assertTrue(is_equal(obj1, obj2)) obj2 = {"10": 1, "2": 0, "3": -1.5} self.assertFalse(is_equal(obj1, obj2)) obj2 = {"1": 1, "2": 0.5, "3": -1.5} self.assertFalse(is_equal(obj1, obj2))
def test_save_model_and_load_model_torch(self): m1 = fe.build(fe.architecture.pytorch.LeNet, optimizer_fn="adam") weight1 = get_model_weight_lenet_torch(m1) fe.backend.save_model(m1, save_dir="tmp", model_name="test") m2 = fe.build(fe.architecture.pytorch.LeNet, optimizer_fn="adam") weight2 = get_model_weight_lenet_torch(m2) self.assertFalse(is_equal(weight1, weight2)) fe.backend.load_model(m2, weights_path="tmp/test.pt") weight3 = get_model_weight_lenet_torch(m2) self.assertTrue(is_equal(weight1, weight3))
def test_get_gradient_tf_tensor_higher_order_false(self): x = tf.Variable([1.0, 2.0, 3.0]) with tf.GradientTape(persistent=True) as tape: y = x * x with self.subTest("check gradient"): obj1 = fe.backend.get_gradient(target=y, sources=x, tape=tape) # [2.0, 4.0, 6.0] obj2 = tf.constant([2.0, 4.0, 6.0]) self.assertTrue(is_equal(obj1, obj2)) with self.subTest("check gradient of gradient"): obj1 = fe.backend.get_gradient(target=obj1, sources=x, tape=tape) # None self.assertTrue(is_equal(obj1, None))
def test_pipeline_get_loader_torch_dataset_pad(self): """ [[1], => [[1, -1], [1]] [1, -1]] [[1, 1]] => [[1, 1], [-1, -1]] """ dataset = fe.dataset.NumpyDataset({ "x": [ np.ones((2, 1), dtype=np.float32), np.ones((1, 2), dtype=np.float32) ] }) pipeline = fe.Pipeline(train_data=dataset, pad_value=-1, batch_size=2) loader = pipeline.get_loader(mode="train", shuffle=False) for idx, batch in enumerate(loader, start=1): result = batch if idx == 1: break ans = { "x": torch.tensor([[[1, -1], [1, -1]], [[1, 1], [-1, -1]]], dtype=torch.float32) } self.assertTrue(is_equal(ans, result))
def test_tf_10class_16code(self): fromhadamard = UnHadamard(inputs='y', outputs='y', n_classes=10, code_length=16) fromhadamard.build('tf') output = fromhadamard.forward(data=[ tf.constant([[ -1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1. ], [ 1., -1., 1., -1., 1., -1., 1., -1., 1., -1., 1., -1., 1., -1., 1., -1. ], [ 1., -1., 1., -1., 1., -1., 1., -1., -1., 1., -1., 1., -1., 1., -1., 1. ], [ -1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1. ], [ -1., 1., 1., 1., -1., -1., -1., -1., 1., 1., 1., 1., -1., -1., -1., -1. ]]) ], state={})[0] output = np.argmax(output, axis=-1) self.assertTrue(is_equal(output, np.array([0, 1, 9, 0, 4])))
def test_tf_input(self): gradient = GradientOp(inputs='x', finals='x', outputs='y') with tf.GradientTape(persistent=True) as tape: x = self.tf_data * self.tf_data output = gradient.forward(data=[self.tf_data, x], state={'tape': tape}) self.assertTrue(is_equal(output, self.tf_output))
def test_network_transform_lenet_torch(self): model = fe.build( model_fn=LeNetTorch, optimizer_fn=lambda x: torch.optim.Adam(params=x, lr=1.0)) weight = get_torch_lenet_model_weight(model) network = fe.Network(ops=[ ModelOp(model=model, inputs="x", outputs="y_pred"), CrossEntropy(inputs=("y_pred", "y"), outputs="ce"), UpdateOp(model=model, loss_name="ce") ]) batch = { "x": np.ones((1, 1, 28, 28), dtype=np.float32), "y": np.array([[1]], dtype=np.float32) } batch = network.transform(data=batch, mode="train") with self.subTest("output y_pred check"): self.assertTrue("y_pred" in batch.keys()) self.assertIsNotNone(batch["y_pred"]) with self.subTest("output ce check"): self.assertTrue("ce" in batch.keys()) self.assertIsNotNone(batch["ce"]) with self.subTest("check whether model weight changed"): weight2 = get_torch_lenet_model_weight(model) self.assertFalse(is_equal(weight, weight2))
def test_network_transform_one_layer_model_torch(self): model = fe.build(model_fn=OneLayerTorchModel, optimizer_fn="adam") weight = get_torch_one_layer_model_weight(model) network = fe.Network(ops=[ ModelOp(model=model, inputs="x", outputs="y_pred"), MeanSquaredError(inputs=("y_pred", "y"), outputs="ce"), UpdateOp(model=model, loss_name="ce") ], pops=PlusOneNumpyOp(inputs="y_pred", outputs="y_pred_processed")) batch = { "x": np.array([[ 1, 1, 1, ]], dtype=np.float32), "y": np.array([[1]], dtype=np.float32) } batch = network.transform(data=batch, mode="train") with self.subTest("output y_pred check"): ans = np.array([[6]], dtype=np.float32) # 1*1 + 1*2 + 1*3 self.assertTrue(np.array_equal(batch["y_pred"].numpy(), ans)) with self.subTest("postprocessing y_pred check"): ans = np.array([[7]], dtype=np.float32) # 1*1 + 1*2 + 1*3 + 1 self.assertTrue(np.array_equal(batch["y_pred_processed"], ans)) with self.subTest("output ce check"): self.assertEqual(batch["ce"].numpy(), 25) # (6-1)^2 with self.subTest("check whether model weight changed"): weight2 = get_torch_one_layer_model_weight(model) self.assertFalse(is_equal(weight, weight2))