def test_df_input(): """Test the operation of the PGNN with labeled input dataframes.""" PhysicsGuidedNeuralNetwork.seed(0) model = PhysicsGuidedNeuralNetwork(p_fun=p_fun_pythag, hidden_layers=HIDDEN_LAYERS, loss_weights=(0.0, 1.0), n_features=2, n_labels=1) x_df = pd.DataFrame(X, columns=('a', 'b')) y_df = pd.DataFrame(Y_NOISE, columns=('c', )) p_df = pd.DataFrame(P, columns=('a', 'b')) model.fit(x_df, y_df, p_df, n_batch=1, n_epoch=2) assert model.feature_names == ['a', 'b'] assert model.output_names == ['c'] x_df_bad = pd.DataFrame(X, columns=('x1', 'x2')) y_df_bad = pd.DataFrame(Y_NOISE, columns=('y', )) try: model.fit(x_df_bad, y_df_bad, p_df, n_batch=1, n_epoch=2) except AssertionError as e: assert "Cannot work with input x columns: ['x1', 'x2']" in str(e) try: model.fit(x_df, y_df_bad, p_df, n_batch=1, n_epoch=2) except AssertionError as e: assert "Cannot work with input y columns: ['y']" in str(e)
def test_save_load(): """Test the save/load operations of PGNN""" PhysicsGuidedNeuralNetwork.seed(0) model = PhysicsGuidedNeuralNetwork(p_fun=p_fun_pythag, hidden_layers=HIDDEN_LAYERS, loss_weights=(0.0, 1.0), n_features=2, n_labels=1, feature_names=['a', 'b'], output_names=['c']) model.fit(X, Y_NOISE, P, n_batch=4, n_epoch=20) y_pred = model.predict(X) with tempfile.TemporaryDirectory() as td: fpath = os.path.join(td, 'tempfile.pkl') model.save(fpath) loaded = PhysicsGuidedNeuralNetwork.load(fpath) assert len(model.layers) == len(loaded.layers) for layer0, layer1 in zip(model.layers, loaded.layers): for i in range(len(layer0.weights)): assert layer0.weights[i].shape == layer1.weights[i].shape assert np.allclose(layer0.weights[i], layer1.weights[i]) y_pred_loaded = loaded.predict(X) assert np.allclose(y_pred, y_pred_loaded) assert loaded.feature_names == ['a', 'b'] assert loaded.output_names == ['c'] assert isinstance(model._optimizer, Adam) assert isinstance(loaded._optimizer, Adam) assert model._optimizer.get_config() == loaded._optimizer.get_config()
def test_phygnn_model(): """Test the operation of the PGNN with weighting pfun.""" PhysicsGuidedNeuralNetwork.seed(0) model = PhygnnModel.build_trained(p_fun_pythag, FEATURES, LABELS, P, normalize=False, hidden_layers=HIDDEN_LAYERS, loss_weights=(0.0, 1.0), n_batch=4, n_epoch=20) test_mae = np.mean(np.abs(model.predict(X, table=False) - Y)) loss = 0.019 assert len(model.layers) == 6 assert len(model.weights) == 6 assert len(model.history) == 20 assert isinstance(model.layers[0], InputLayer) assert isinstance(model.layers[1], Dense) assert isinstance(model.layers[2], Activation) assert isinstance(model.layers[3], Dense) assert isinstance(model.layers[4], Activation) assert isinstance(model.layers[5], Dense) assert model.history.validation_loss.values[-1] < loss assert test_mae < loss
def test_OHE(): """ Test one-hot encoding """ ohe_features = FEATURES.copy() categories = list('def') ohe_features['categorical'] = np.random.choice(categories, len(FEATURES)) one_hot_categories = {'categorical': categories} x = ohe_features.values PhysicsGuidedNeuralNetwork.seed(0) model = PhygnnModel.build_trained(p_fun_pythag, ohe_features, LABELS, P, one_hot_categories=one_hot_categories, hidden_layers=HIDDEN_LAYERS, loss_weights=(0.0, 1.0), n_batch=4, n_epoch=20) assert all(np.isin(categories, model.feature_names)) assert not any(np.isin(categories, model.input_feature_names)) assert 'categorical' not in model.feature_names assert 'categorical' in model.input_feature_names out = model.predict(x) assert 'c' in out
def test_bad_pfun(): """Test the preflight check with a non-differentiable p_fun""" PhysicsGuidedNeuralNetwork.seed(0) model = PhysicsGuidedNeuralNetwork(p_fun=p_fun_bad, hidden_layers=HIDDEN_LAYERS, loss_weights=(0.0, 1.0), n_features=2, n_labels=1) with pytest.raises(RuntimeError) as e: model.fit(X, Y_NOISE, P, n_batch=4, n_epoch=20) assert 'not differentiable' in str(e.value)
def test_classification(): """Test the phygnn model as a classifier without the pfun""" PhysicsGuidedNeuralNetwork.seed(0) model = PhysicsGuidedNeuralNetwork(p_fun=None, hidden_layers=hidden_layers, output_layer=output_layer, loss_weights=(1.0, 0.0), metric='binary_crossentropy', learning_rate=0.05, n_features=2, n_labels=1) model.fit(features, labels, features, n_batch=1, n_epoch=50) y_pred = model.predict(features) accuracy = 100 * (np.round(y_pred) == labels.values).sum() / len(labels) assert accuracy > 0.99
def test_normalize(): """Test the operation of the PGNN with weighting pfun.""" PhysicsGuidedNeuralNetwork.seed(0) model = PhygnnModel.build_trained(p_fun_pythag, FEATURES, LABELS, P, normalize=False, hidden_layers=HIDDEN_LAYERS, loss_weights=(0.0, 1.0), n_batch=4, n_epoch=20) test_mae = np.mean(np.abs(model.predict(X, table=False) - Y)) loss = 0.015 assert model.history.validation_loss.values[-1] < loss assert test_mae < loss
def test_nn(): """Test the basic NN operation of the PGNN without weighting pfun.""" PhysicsGuidedNeuralNetwork.seed(0) model = PhysicsGuidedNeuralNetwork(p_fun=p_fun_pythag, hidden_layers=HIDDEN_LAYERS, loss_weights=(1.0, 0.0), n_features=2, n_labels=1, feature_names=['a', 'b'], output_names=['c']) model.fit(X, Y_NOISE, P, n_batch=4, n_epoch=20) test_mae = np.mean(np.abs(model.predict(X) - Y)) assert len(model.layers) == 6 assert len(model.weights) == 6 assert len(model.history) == 20 assert model.history.validation_loss.values[-1] < 0.15 assert test_mae < 0.15
def test_nn(): """Test the basic NN operation of the PGNN without weighting pfun.""" PhysicsGuidedNeuralNetwork.seed(0) model = PhygnnModel.build_trained(p_fun_pythag, features, labels, P, hidden_layers=HIDDEN_LAYERS, loss_weights=(1.0, 0.0), n_batch=4, n_epoch=20) test_mae = np.mean(np.abs(model.predict(X, table=False) - Y)) loss = 0.15 assert len(model.layers) == 6 assert len(model.weights) == 6 assert len(model.history) == 20 assert model.history.validation_loss.values[-1] < loss assert test_mae < loss
def test_save_load(): """Test the save/load operations of PGNN""" PhysicsGuidedNeuralNetwork.seed(0) model = PhysicsGuidedNeuralNetwork(p_fun=p_fun_pythag, hidden_layers=HIDDEN_LAYERS, loss_weights=(0.0, 1.0), n_features=2, n_labels=1, feature_names=['a', 'b'], output_names=['c']) model.fit(X, Y_NOISE, P, n_batch=4, n_epoch=20) y_pred = model.predict(X) model.save(FPATH) loaded = PhysicsGuidedNeuralNetwork.load(FPATH) y_pred_loaded = loaded.predict(X) assert np.allclose(y_pred, y_pred_loaded) assert loaded.feature_names == ['a', 'b'] assert loaded.output_names == ['c'] os.remove(FPATH)
def test_save_load(): """Test the save/load operations of PhygnnModel""" PhysicsGuidedNeuralNetwork.seed(0) model = PhygnnModel.build_trained(p_fun_pythag, FEATURES, LABELS, P, normalize=False, hidden_layers=HIDDEN_LAYERS, loss_weights=(0.0, 1.0), n_batch=4, n_epoch=20, save_path=FPATH) y_pred = model[X] loaded = PhygnnModel.load(FPATH) y_pred_loaded = loaded[X] np.allclose(y_pred.values, y_pred_loaded.values) assert loaded.feature_names == ['a', 'b'] assert loaded.label_names == ['c'] shutil.rmtree(os.path.dirname(FPATH))
def test_dummy_p_fun(): """Test the phygnn model with dummy pfun that is just MAE""" PhysicsGuidedNeuralNetwork.seed(0) model_0 = PhysicsGuidedNeuralNetwork(p_fun=p_fun_dummy, hidden_layers=HIDDEN_LAYERS, loss_weights=(0.5, 0.5), n_features=2, n_labels=1) model_0.fit(X, Y_NOISE, P, n_batch=4, n_epoch=20) PhysicsGuidedNeuralNetwork.seed(0) model_1 = PhysicsGuidedNeuralNetwork(p_fun=p_fun_dummy, hidden_layers=HIDDEN_LAYERS, loss_weights=(1.0, 0.0), metric='mae', n_features=2, n_labels=1) model_1.fit(X, Y_NOISE, P, n_batch=4, n_epoch=20) assert np.allclose(model_0.history.training_loss.values.astype(float), model_1.history.training_loss.values.astype(float))
def test_phygnn(): """Test the operation of the PGNN with weighting pfun.""" PhysicsGuidedNeuralNetwork.seed(0) model = PhysicsGuidedNeuralNetwork(p_fun=p_fun_pythag, hidden_layers=HIDDEN_LAYERS, loss_weights=(0.0, 1.0), n_features=2, n_labels=1) model.fit(X, Y_NOISE, P, n_batch=4, n_epoch=20) test_mae = np.mean(np.abs(model.predict(X) - Y)) assert len(model.layers) == 6 assert len(model.weights) == 6 assert len(model.history) == 20 assert isinstance(model.layers[0], InputLayer) assert isinstance(model.layers[1], Dense) assert isinstance(model.layers[2], Activation) assert isinstance(model.layers[3], Dense) assert isinstance(model.layers[4], Activation) assert isinstance(model.layers[5], Dense) assert model.history.validation_loss.values[-1] < 0.015 assert test_mae < 0.015
def test_kernel_regularization(): """Test the kernel regularization of phygnn.""" base = PhysicsGuidedNeuralNetwork(p_fun=p_fun_pythag, hidden_layers=HIDDEN_LAYERS, loss_weights=(1.0, 0.0), n_features=2, n_labels=1) model_l1 = PhysicsGuidedNeuralNetwork(p_fun=p_fun_pythag, hidden_layers=HIDDEN_LAYERS, loss_weights=(1.0, 0.0), n_features=2, n_labels=1, kernel_reg_rate=0.01, kernel_reg_power=1) model_l2 = PhysicsGuidedNeuralNetwork(p_fun=p_fun_pythag, hidden_layers=HIDDEN_LAYERS, loss_weights=(1.0, 0.0), n_features=2, n_labels=1, kernel_reg_rate=0.01, kernel_reg_power=2) base.seed(0) base.fit(X, Y_NOISE, P, n_batch=1, n_epoch=20) model_l1.seed(0) model_l1.fit(X, Y_NOISE, P, n_batch=1, n_epoch=20) model_l2.seed(0) model_l2.fit(X, Y_NOISE, P, n_batch=1, n_epoch=20) assert base.kernel_reg_term > model_l1.kernel_reg_term assert model_l1.kernel_reg_term > model_l2.kernel_reg_term assert np.abs(base.kernel_reg_term - 498) < 5 assert np.abs(model_l1.kernel_reg_term - 84) < 5 assert np.abs(model_l2.kernel_reg_term - 17) < 5
def test_bad_categories(): """ Test OHE checks """ one_hot_categories = {'categorical': list('abc')} feature_names = FEATURES.columns.tolist() + ['categorical'] label_names = 'c' with pytest.raises(RuntimeError): PhygnnModel.build(p_fun_pythag, feature_names, label_names, one_hot_categories=one_hot_categories, hidden_layers=HIDDEN_LAYERS, loss_weights=(0.0, 1.0)) one_hot_categories = {'categorical': list('cdf')} feature_names = FEATURES.columns.tolist() + ['categorical'] label_names = 'c' with pytest.raises(RuntimeError): PhygnnModel.build(p_fun_pythag, feature_names, label_names, one_hot_categories=one_hot_categories, hidden_layers=HIDDEN_LAYERS, loss_weights=(0.0, 1.0)) one_hot_categories = {'categorical': list('def')} feature_names = FEATURES.columns.tolist() + ['categories'] label_names = 'c' with pytest.raises(RuntimeError): PhygnnModel.build(p_fun_pythag, feature_names, label_names, one_hot_categories=one_hot_categories, hidden_layers=HIDDEN_LAYERS, loss_weights=(0.0, 1.0)) one_hot_categories = {'cat1': list('def'), 'cat2': list('fgh')} feature_names = FEATURES.columns.tolist() + ['cat1', 'cat2'] label_names = 'c' with pytest.raises(RuntimeError): PhygnnModel.build(p_fun_pythag, feature_names, label_names, one_hot_categories=one_hot_categories, hidden_layers=HIDDEN_LAYERS, loss_weights=(0.0, 1.0)) ohe_features = FEATURES.copy() categories = list('def') ohe_features['categorical'] = np.random.choice(categories, len(FEATURES)) one_hot_categories = {'categorical': categories} x = ohe_features.values[:, 1:] PhysicsGuidedNeuralNetwork.seed(0) model = PhygnnModel.build_trained(p_fun_pythag, ohe_features, LABELS, P, one_hot_categories=one_hot_categories, hidden_layers=HIDDEN_LAYERS, loss_weights=(0.0, 1.0), n_batch=4, n_epoch=20) with pytest.raises(RuntimeError): model.predict(x)
def test_dropouts(): """Test the dropout rate kwargs for adding dropout layers.""" hidden_layers_1 = [{ 'units': 64 }, { 'activation': 'relu' }, { 'units': 64, 'activation': 'relu', 'name': 'relu2' }] hidden_layers_2 = [{ 'units': 64 }, { 'activation': 'relu' }, { 'dropout': 0.1 }, { 'units': 64, 'activation': 'relu', 'name': 'relu2', 'dropout': 0.1 }] PhysicsGuidedNeuralNetwork.seed() model_1 = PhysicsGuidedNeuralNetwork(p_fun=p_fun_pythag, hidden_layers=hidden_layers_1, loss_weights=(0.0, 1.0), n_features=2, n_labels=1) PhysicsGuidedNeuralNetwork.seed() model_2 = PhysicsGuidedNeuralNetwork(p_fun=p_fun_pythag, hidden_layers=hidden_layers_2, loss_weights=(0.0, 1.0), n_features=2, n_labels=1) assert len(model_1.layers) == 6 assert len(model_2.layers) == 8, "dropout layers did not get added!" assert isinstance(model_2.layers[0], InputLayer) assert isinstance(model_2.layers[1], Dense) assert isinstance(model_2.layers[2], Activation) assert isinstance(model_2.layers[3], Dropout) assert isinstance(model_2.layers[4], Dense) assert isinstance(model_2.layers[5], Activation) assert isinstance(model_2.layers[6], Dropout) PhysicsGuidedNeuralNetwork.seed() model_1.fit(X, Y_NOISE, P, n_batch=4, n_epoch=20) PhysicsGuidedNeuralNetwork.seed() model_2.fit(X, Y_NOISE, P, n_batch=4, n_epoch=20) y_pred_1 = model_1.predict(X) y_pred_2 = model_2.predict(X) # make sure dropouts dont predict the same as non-dropout diff = np.abs(y_pred_1 - y_pred_2) assert not np.allclose(y_pred_1, y_pred_2) assert np.max(diff) > 0.1 with tempfile.TemporaryDirectory() as td: fpath = os.path.join(td, 'tempfile.pkl') model_2.save(fpath) loaded = PhysicsGuidedNeuralNetwork.load(fpath) y_pred_loaded = loaded.predict(X) assert np.allclose(y_pred_2, y_pred_loaded) assert len(model_2.layers) == len(loaded.layers)