Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanhgm committed Sep 30, 2021
0 parents commit 8583591
Show file tree
Hide file tree
Showing 83 changed files with 8,290 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
### Build files ###
/target/

### IntelliJ IDEA ###
.idea
*.iws
*.ipr
/EBM-Java-UI.iml

### Generated CSS files ###
/src/main/webapp/css/*
!/src/main/webapp/css/fonts/
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2021 Stefan Hegselmann

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
75 changes: 75 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# EBM-Java-UI

A web-based user interface to visualize and inspect [Explainable Boosting Machines (EBM)](https://github.com/interpretml/interpret). It also allows to remove risk functions in a validation step and use the resulting model for predictions: However, the prediction module was not tested sufficiently yet. This software was used in two research projects to present learned risk functions to practitioners and we wanted to make the code accessible to other researchers.

1. [An Evaluation of the Doctor-Interpretability of Generalized Additive Models with Interactions](http://proceedings.mlr.press/v126/hegselmann20a.html)
2. (Reference follows)

![gif of EBM-Java-UI](ebmjavaui.gif)

## Run Project

This setup was tested for Ubuntu 20.04. It uses an example project build from `example/EBM-Java-UI.war`.
* Install Java 13: `sudo apt-get install openjdk-13-jdk`.
* Install Tomcat 9: `sudo apt-get install tomcat9 tomcat9-admin tomcat9-user`.
* Install PostgreSQL: `sudo apt-get install postgresql`.
* Configure a user for PostgreSQL called "postgres": Login with `sudo -u postgres psql` and set password
according to the `datasource.password` field in `src/main/webapp/config/config.properties` with
`ALTER USER postgres WITH PASSWORD '<db.password>';`. Use password `s27P5hXhHKGoYzIO` to run the example build.
* Create a new database called "ebmjavaui-db": `create database "ebmjavaui-db";`. Verify whether it was created with `\l` (
exit with `q`).
* Connect to the ebmjavaui-db database: `\c ebmjavaui-db`. Afterwards run "createDB.sql" with `\i createDB.sql` to
create the necessary schemes and exit with `\q`.
* Configure your user as tomcat admin: `sudo nano /etc/tomcat9/tomcat-users.xml` and add an entry for a new user, e.g. `<user username="user" password="add-your-pw" roles="admin-gui, manager-gui"/>`
* Start tomcat: `systemctl start tomcat9`. It can be stopped using `systemctl stop tomcat9`.
* To deploy the project visit `http://localhost:8080/manager` and login with the admin user created previously. At "WAR file to deploy" select the example build (`example/EBM-Java-UI.war`) and press deploy.
* Go to http://localhost:8080/EBM-Java-UI to check if it works.

## Run Example

* Install requirements of visualization_database.py: `pip install -r scripts/requirements.txt`.
* Parse a dataset like in the example [Notebook](https://nbviewer.jupyter.org/github/interpretml/interpret/blob/master/benchmarks/EBM%20Classification%20Comparison.ipynb) of [InterpretML](https://github.com/interpretml/interpret).
* Train an EBM with the Data. [Example](https://interpret.ml/docs/getting-started.html#train-a-glassbox-model).
* Call `store_ebm_model()` of visualization_database.py with the EBM Model, a timestamp and the password of the ebmjavaui-db database as parameters.
* The EBM should now be stored in the database and can be inspected and validated using EBM-Java-UI.
* An Example can be seen in `example/example.py`. It can be run after adjusting the password according to the ebmjavaui-db database and installing requirements with `pip install -r example/requirements.txt`.

Example Code:
```
# Load dataset.
dataset = load_heart_data()
X_train, X_test, y_train, y_test = train_test_split(
dataset['full']['X'], dataset['full']['y'], test_size=0.2)
# Train EBM model.
ebm = ExplainableBoostingClassifier(random_state=seed)
ebm.fit(X_train, y_train)
# Load trained EBM model into EBM-Java-UI and inspect it via http://localhost:8080/EBM-Java-UI/.
timestamp = datetime.now().strftime("%Y-%m-%d_%H:%M:%S")
store_ebm_model(ebm, timestamp, "<db-password>")]()
```

## Setup Environment to Compile Project
This setup is valid for the IntelliJ IDE. Please adapt, if necessary. Steps 1-5 from [Run Project](#run-project) are required.
* Install IntelliJ, open it and clone the project: https://github.com/stefanhgm/EBM-Java-UI.git
* Set project SDK to opendjdk-13:`File -> Project Structure -> Project -> Project SDK`(set project SDK to 13)
* Add the PostgreSQL datasource to IntelliJ: `View -> Tool Windows -> Database` and
add a Data Source PostgreSQL with the according DB login information (you can now run createDB.sql from within
IntelliJ by right-clicking on it -> "Run")
* Add tomcat to IntelliJ: `File -> Settings -> Build, Execution, Deployment -> Application Server -> Add Tomcat Server` (
default Home: `/usr/share/tomcat9`, Base: `/var/lib/tomcat9`)
* Add a run configuration to build the project locally and deploy it automatically: `Add Configuration/Edit
Configuration (upper right corner next to the build button) -> "Plus" -> Tomcat Server -> local`. Choose the previously
configured tomcat server as application server. In the box "Before launch:..." delete all entries and add a single one
for `Run Maven Goal` with `clean install` as Command Line. Set URL to "http://localhost:8080/". In the tab Deployment
add the artifact ebm-java-ui:war and set application context to `/`)
* Add another tomcat configuration "Tomcat install" by repeating the above step and just use the maven goal "install"
only. This should lead to faster build when clean is not necessary.
* These configurations ought to work, however, certain problems with permission occurred in the described setup. The best
way to fix them should be to change ownership of all tomcat directories to the group tomcat and add the local user to
this group. This did not work out and one workaround seems to be setting rights to 777 for tomcat directories in order to
make them accessible for IntelliJ: `sudo chmod 777 -R /var/lib/tomcat9`, `sudo chmod 777 -R /etc/tomcat9`
* Edit the shutdown port of tomcat: `nano /var/lib/tomcat9/conf/server.xml` and edit the server line for shutdown like this `<Server port="8079" shutdown="SHUTDOWN"\>`
* Please notice that tomcat started from IntelliJ and manually from the command line via `systemctl start tomcat9` can interfere. Stop one of them to start the other (either by hitting stop in IntelliJ or by `systemctl stop tomcat9`)
* Set custom password in `src/main/webapp/config/config.properties` (and set database password accordingly)
41 changes: 41 additions & 0 deletions createDB.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
DROP SCHEMA EBMJAVAUI cascade;
CREATE SCHEMA EBMJAVAUI;

-- modeldata
CREATE TABLE EBMJAVAUI.PREDICTION_MODEL
(
ID BIGSERIAL NOT NULL,
MODEL_IDENTIFIER TEXT,
VALIDATED BOOL,
INTERCEPT DOUBLE PRECISION,
MAX_ABS_RISK_1D DOUBLE PRECISION,
MAX_ABS_RISK_2D DOUBLE PRECISION,
MODEL_COMMENT TEXT,
PRIMARY KEY (ID)
);
CREATE TABLE EBMJAVAUI.COMPONENT
(
ID BIGSERIAL NOT NULL,
PREDICTION_MODEL_ID BIGINT,
INDEX INTEGER,
FEATURE_NAME TEXT,
FEATURE_GROUP TEXT,
FEATURE_NAMES TEXT,
FEATURE_IMPORTANCE FLOAT,
ADDITIVE_TERMS TEXT,
TERM_STANDARD_DEVIATION TEXT,
FEATURE_TYPES TEXT,
COL_BIN_COUNT TEXT,
COL_BIN_EDGES TEXT,
COL_MAPPING TEXT,
COL_MAX_ TEXT,
COL_MIN_ TEXT,
PRIMARY KEY (ID)
);


-- modeldata constraints
ALTER TABLE EBMJAVAUI.COMPONENT
ADD CONSTRAINT FK_COMPONENT_PREDICTION_MODEL_ID FOREIGN KEY (PREDICTION_MODEL_ID) REFERENCES EBMJAVAUI.PREDICTION_MODEL (ID);

ALTER ROLE POSTGRES SET SEARCH_PATH TO EBMJAVAUI;
Binary file added ebmjavaui.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/EBM-Java-UI.war
Binary file not shown.
3 changes: 3 additions & 0 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Example

Contains project build ready to deploy in a tomcat instance. Careful it might not be based on the newest version of the repository. For an up-to-date version please build it yourself.
37 changes: 37 additions & 0 deletions example/example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import pandas as pd
from datetime import datetime
from interpret.glassbox import ExplainableBoostingClassifier
from sklearn.model_selection import train_test_split

from scripts.visualization_database import store_ebm_model

seed = 1

def load_heart_data():
# https://www.kaggle.com/ronitf/heart-disease-uci
df = pd.read_csv(r'heart.csv')
train_cols = df.columns[0:-1]
label = df.columns[-1]
X_df = df[train_cols]
y_df = df[label]
dataset = {
'problem': 'classification',
'full': {
'X': X_df,
'y': y_df,
},
}
return dataset

# Load dataset.
dataset = load_heart_data()
X_train, X_test, y_train, y_test = train_test_split(
dataset['full']['X'], dataset['full']['y'], test_size=0.20, random_state=seed)

# Train EBM model.
ebm = ExplainableBoostingClassifier(random_state=seed)
ebm.fit(X_train, y_train)

# Load trained EBM model into EBM-Java-UI and inspect it via http://localhost:8080/EBM-Java-UI/.
timestamp = datetime.now().strftime("%Y-%m-%d_%H:%M:%S")
store_ebm_model(ebm, timestamp, "<db-password>")
Loading

0 comments on commit 8583591

Please # to comment.