Пример #1
0
    num_epochs = 800
    for epoch in range(num_epochs):
        optimizer.zero_grad()
        outputs = model(x)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

    # Evaluation
    y_pred = model.predict(x_test).numpy()
    print("Accuracy: {0}".format(accuracy_score(y_test, y_pred)))

    # Select a data point whose prediction has to be explained
    x_orig = X_test[1, :]
    print("Prediction on x: {0}".format(
        model.predict(torch.from_numpy(np.array([x_orig])))))

    # Whitelist of features we can use/change when computing the counterfactual
    features_whitelist = [0, 2]  # Use the first and third feature only

    # Compute counterfactual
    print("\nCompute counterfactual ....")
    print(
        generate_counterfactual(model,
                                x_orig,
                                y_target=0,
                                features_whitelist=features_whitelist,
                                regularization="l1",
                                C=0.1,
                                optimizer="nelder-mead"))
Пример #2
0
def test_softmaxregression():
    # Neural network - Softmax regression
    class Model(torch.nn.Module, ModelWithLoss):
        def __init__(self, input_size, num_classes):
            super(Model, self).__init__()

            self.linear = torch.nn.Linear(input_size, num_classes)
            self.softmax = torch.nn.Softmax(dim=0)

        def forward(self, x):
            return self.linear(
                x)  # NOTE: Softmax is build into CrossEntropyLoss

        def predict_proba(self, x):
            return self.softmax(self.forward(x))

        def predict(self, x, dim=1):
            return torch.argmax(self.forward(x), dim=dim)

        def get_loss(self, y_target, pred=None):
            return NegLogLikelihoodCost(input_to_output=self.predict_proba,
                                        y_target=y_target)

    # Load data
    X, y = load_iris(return_X_y=True)
    X = X.astype(np.dtype(np.float32))

    X_train, X_test, y_train, y_test = train_test_split(X,
                                                        y,
                                                        test_size=0.33,
                                                        random_state=1)

    # numpy -> torch tensor
    x = torch.from_numpy(X_train)
    labels = torch.from_numpy(y_train)

    x_test = torch.from_numpy(X_test)
    y_test = torch.from_numpy(y_test)

    # Create and fit model
    model = Model(4, 3)

    learning_rate = 0.001
    momentum = 0.9
    criterion = torch.nn.CrossEntropyLoss()

    optimizer = torch.optim.SGD(model.parameters(),
                                lr=learning_rate,
                                momentum=momentum)

    num_epochs = 800
    for epoch in range(num_epochs):
        optimizer.zero_grad()
        outputs = model(x)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

    # Evaluation
    y_pred = model.predict(x_test).detach().numpy()
    assert accuracy_score(y_test, y_pred) >= 0.8

    # Select data point for explaining its prediction
    x_orig = X_test[1, :]
    assert model.predict(torch.from_numpy(np.array([x_orig
                                                    ]))).detach().numpy() == 1

    # Create weighted manhattan distance cost function
    md = np.median(X_train, axis=0)
    mad = np.median(np.abs(X_train - md), axis=0)
    regularization_mad = LMadCost(torch.from_numpy(x_orig),
                                  torch.from_numpy(mad))

    # Compute counterfactual
    features_whitelist = None

    optimizer = "bfgs"
    optimizer_args = {"max_iter": 1000, "args": {"lr": 0.9, "momentum": 0.9}}
    x_cf, y_cf, delta = generate_counterfactual(
        model,
        x_orig,
        y_target=0,
        features_whitelist=features_whitelist,
        regularization="l2",
        C=0.001,
        optimizer=optimizer,
        optimizer_args=optimizer_args,
        return_as_dict=False)
    assert y_cf == 0
    assert model.predict(torch.from_numpy(np.array(
        [x_cf], dtype=np.float32))).detach().numpy() == 0

    x_cf, y_cf, delta = generate_counterfactual(
        model,
        x_orig,
        y_target=0,
        features_whitelist=features_whitelist,
        regularization="l2",
        C=0.001,
        optimizer=MyOptimizer(),
        optimizer_args=optimizer_args,
        return_as_dict=False)
    assert y_cf == 0
    assert model.predict(torch.from_numpy(np.array(
        [x_cf], dtype=np.float32))).detach().numpy() == 0

    optimizer = "bfgs"
    optimizer_args = {"max_iter": 1000, "args": {"lr": 0.9, "momentum": 0.9}}
    x_cf, y_cf, delta = generate_counterfactual(
        model,
        x_orig,
        y_target=0,
        features_whitelist=features_whitelist,
        regularization=regularization_mad,
        C=0.001,
        optimizer=optimizer,
        optimizer_args=optimizer_args,
        return_as_dict=False)
    assert y_cf == 0
    assert model.predict(torch.from_numpy(np.array(
        [x_cf], dtype=np.float32))).detach().numpy() == 0

    optimizer = "nelder-mead"
    x_cf, y_cf, delta = generate_counterfactual(
        model,
        x_orig,
        y_target=0,
        features_whitelist=features_whitelist,
        regularization="l1",
        C=0.001,
        optimizer=optimizer,
        optimizer_args=optimizer_args,
        return_as_dict=False)
    assert y_cf == 0
    assert model.predict(torch.from_numpy(np.array(
        [x_cf], dtype=np.float32))).detach().numpy() == 0

    optimizer = torch.optim.SGD
    x_cf, y_cf, delta = generate_counterfactual(
        model,
        x_orig,
        y_target=0,
        features_whitelist=features_whitelist,
        regularization="l2",
        C=0.001,
        optimizer=optimizer,
        optimizer_args=optimizer_args,
        return_as_dict=False)
    assert y_cf == 0
    assert model.predict(torch.from_numpy(np.array(
        [x_cf], dtype=np.float32))).detach().numpy() == 0

    optimizer = "bfgs"
    optimizer_args = {"max_iter": 1000, "args": {"lr": 0.9, "momentum": 0.9}}
    x_cf, y_cf, delta = generate_counterfactual(
        model,
        x_orig,
        y_target=0,
        features_whitelist=features_whitelist,
        regularization=None,
        optimizer=optimizer,
        optimizer_args=optimizer_args,
        return_as_dict=False)
    assert y_cf == 0
    assert model.predict(torch.from_numpy(np.array(
        [x_cf], dtype=np.float32))).detach().numpy() == 0

    optimizer = torch.optim.SGD
    x_cf, y_cf, delta = generate_counterfactual(
        model,
        x_orig,
        y_target=0,
        features_whitelist=features_whitelist,
        regularization=None,
        optimizer=optimizer,
        optimizer_args=optimizer_args,
        return_as_dict=False)
    assert y_cf == 0
    assert model.predict(torch.from_numpy(np.array(
        [x_cf], dtype=np.float32))).detach().numpy() == 0

    features_whitelist = [0, 2]

    optimizer = "bfgs"
    optimizer_args = {"max_iter": 1000, "args": {"lr": 0.9, "momentum": 0.9}}
    x_cf, y_cf, delta = generate_counterfactual(
        model,
        x_orig,
        y_target=0,
        features_whitelist=features_whitelist,
        regularization="l1",
        C=0.001,
        optimizer=optimizer,
        optimizer_args=optimizer_args,
        return_as_dict=False)
    assert y_cf == 0
    assert model.predict(torch.from_numpy(np.array(
        [x_cf], dtype=np.float32))).detach().numpy() == 0
    assert all([
        True if i in features_whitelist else delta[i] == 0.
        for i in range(x_orig.shape[0])
    ])

    optimizer = "nelder-mead"
    x_cf, y_cf, delta = generate_counterfactual(
        model,
        x_orig,
        y_target=0,
        features_whitelist=features_whitelist,
        regularization="l2",
        C=0.001,
        optimizer=optimizer,
        optimizer_args=optimizer_args,
        return_as_dict=False)
    assert y_cf == 0
    assert model.predict(torch.from_numpy(np.array(
        [x_cf], dtype=np.float32))).detach().numpy() == 0
    assert all([
        True if i in features_whitelist else delta[i] == 0.
        for i in range(x_orig.shape[0])
    ])

    optimizer = torch.optim.SGD
    x_cf, y_cf, delta = generate_counterfactual(
        model,
        x_orig,
        y_target=0,
        features_whitelist=features_whitelist,
        regularization="l2",
        C=0.0001,
        optimizer=optimizer,
        optimizer_args=optimizer_args,
        return_as_dict=False)
    assert y_cf == 0
    assert model.predict(torch.from_numpy(np.array(
        [x_cf], dtype=np.float32))).detach().numpy() == 0
    assert all([
        True if i in features_whitelist else delta[i] == 0.
        for i in range(x_orig.shape[0])
    ])

    optimizer = "bfgs"
    x_cf, y_cf, delta = generate_counterfactual(
        model,
        x_orig,
        y_target=0,
        features_whitelist=features_whitelist,
        regularization=None,
        optimizer=optimizer,
        optimizer_args=optimizer_args,
        return_as_dict=False)
    assert y_cf == 0
    assert model.predict(torch.from_numpy(np.array(
        [x_cf], dtype=np.float32))).detach().numpy() == 0
    assert all([
        True if i in features_whitelist else delta[i] == 0.
        for i in range(x_orig.shape[0])
    ])

    optimizer = torch.optim.SGD
    x_cf, y_cf, delta = generate_counterfactual(
        model,
        x_orig,
        y_target=0,
        features_whitelist=features_whitelist,
        regularization=None,
        optimizer=optimizer,
        optimizer_args=optimizer_args,
        return_as_dict=False)
    assert y_cf == 0
    assert model.predict(torch.from_numpy(np.array(
        [x_cf], dtype=np.float32))).detach().numpy() == 0
    assert all([
        True if i in features_whitelist else delta[i] == 0.
        for i in range(x_orig.shape[0])
    ])
Пример #3
0
def test_linearregression():
    # Neural network - Linear regression
    class Model(torch.nn.Module, ModelWithLoss):
        def __init__(self, input_size):
            super(Model, self).__init__()

            self.linear = torch.nn.Linear(input_size, 1)
        
        def forward(self, x):
            return self.linear(x)
        
        def predict(self, x, dim=None): # Note: In contrast to classification, the parameter `dim` is not used!
            return self.forward(x)
        
        def get_loss(self, y_target, pred=None):
            return SquaredError(self.predict, y_target)

    # Load data
    X, y = load_boston(True)
    X = X.astype(np.dtype(np.float32))
    y = y.astype(np.dtype(np.float32))

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1)

    # numpy -> torch tensor
    x = torch.from_numpy(X_train)
    labels = torch.from_numpy(y_train.reshape(y_train.shape[0], -1))

    x_test = torch.from_numpy(X_test)
    y_test = torch.from_numpy(y_test)

    # Create and fit model
    model = Model(X_train.shape[1])

    learning_rate = 0.1
    criterion = torch.nn.MSELoss()

    optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate, weight_decay=0.01) 

    num_epochs = 3000
    for epoch in range(num_epochs):
        optimizer.zero_grad()
        outputs = model(x)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

    # Evaluation
    y_pred = model.predict(x_test).detach().numpy()
    assert r2_score(y_test, y_pred) >= 0.6

    # Select data point for explaining its prediction
    x_orig = X_test[1:4][1,:]
    y_orig_pred = model.predict(torch.from_numpy(np.array([x_orig], dtype=np.float32)))
    assert y_orig_pred >= 16. and y_orig_pred < 20.

    # Compute counterfactual
    features_whitelist = None
    y_target = 30.
    y_target_done = lambda z: np.abs(z - y_target) < 6.

    optimizer = "bfgs"
    optimizer_args = {"max_iter": 1000, "args": {"lr": 0.1}}
    x_cf, y_cf, delta = generate_counterfactual(model, x_orig, y_target=y_target, features_whitelist=features_whitelist, regularization="l2", C=10., optimizer=optimizer, optimizer_args=optimizer_args, return_as_dict=False, done=y_target_done)
    assert y_target_done(y_cf)
    assert y_target_done(model.predict(torch.from_numpy(np.array([x_cf], dtype=np.float32))))

    optimizer = "nelder-mead"
    x_cf, y_cf, delta = generate_counterfactual(model, x_orig, y_target=y_target, features_whitelist=features_whitelist, regularization="l2", C=8., optimizer=optimizer, optimizer_args=optimizer_args, return_as_dict=False, done=y_target_done)
    assert y_target_done(y_cf)
    assert y_target_done(model.predict(torch.from_numpy(np.array([x_cf], dtype=np.float32))))

    optimizer = torch.optim.Adam
    x_cf, y_cf, delta = generate_counterfactual(model, x_orig, y_target=y_target, features_whitelist=features_whitelist, regularization="l2", C=10., optimizer=optimizer, optimizer_args=optimizer_args, return_as_dict=False, done=y_target_done)
    assert y_target_done(y_cf)
    assert y_target_done(model.predict(torch.from_numpy(np.array([x_cf], dtype=np.float32))))

    features_whitelist = features_whitelist = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

    optimizer = "bfgs"
    optimizer_args = {"max_iter": 1000, "args": {"lr": 0.1}}
    x_cf, y_cf, delta = generate_counterfactual(model, x_orig, y_target=y_target, features_whitelist=features_whitelist, regularization="l2", C=10., optimizer=optimizer, optimizer_args=optimizer_args, return_as_dict=False, done=y_target_done)
    assert y_target_done(y_cf)
    assert y_target_done(model.predict(torch.from_numpy(np.array([x_cf], dtype=np.float32))))
    assert all([True if i in features_whitelist else delta[i] == 0. for i in range(x_orig.shape[0])])

    optimizer = "nelder-mead"
    x_cf, y_cf, delta = generate_counterfactual(model, x_orig, y_target=y_target, features_whitelist=features_whitelist, regularization="l2", C=6., optimizer=optimizer, optimizer_args=optimizer_args, return_as_dict=False, done=y_target_done)
    assert y_target_done(y_cf)
    assert y_target_done(model.predict(torch.from_numpy(np.array([x_cf], dtype=np.float32))))
    assert all([True if i in features_whitelist else delta[i] == 0. for i in range(x_orig.shape[0])])