Generalized additive models with structured interactions
The following environments are required:
- Python 3.7 + (anaconda is preferable)
- tensorflow>=2.0.0
- tensorflow-lattice>=2.0.8
- numpy>=1.15.2
- pandas>=0.19.2
- matplotlib>=3.1.3
- scikit-learn>=0.23.0
pip install gaminetTo use it on GPU, conda install tensorflow==2.2, pip install tensorflow-lattice==2.0.8, conda install tensorflow-estimators==2.2
Import library
importosimportnumpyasnpimporttensorflowastffromsklearn.preprocessingimportMinMaxScalerfromsklearn.model_selectionimporttrain_test_splitfromgaminetimportGAMINetfromgaminet.utilsimportlocal_visualizefromgaminet.utilsimportglobal_visualize_densityfromgaminet.utilsimportfeature_importance_visualizefromgaminet.utilsimportplot_trajectoryfromgaminet.utilsimportplot_regularizationLoad data
defmetric_wrapper(metric, scaler):
defwrapper(label, pred):
returnmetric(label, pred, scaler=scaler)
returnwrapperdefrmse(label, pred, scaler):
pred=scaler.inverse_transform(pred.reshape([-1, 1]))
label=scaler.inverse_transform(label.reshape([-1, 1]))
returnnp.sqrt(np.mean((pred-label)**2))
defdata_generator1(datanum, dist="uniform", random_state=0):
nfeatures=100np.random.seed(random_state)
x=np.random.uniform(0, 1, [datanum, nfeatures])
x1, x2, x3, x4, x5, x6= [x[:, [i]] foriinrange(6)]
defcliff(x1, x2):
# x1: -20,20# x2: -10,5x1= (2*x1-1) *20x2= (2*x2-1) *7.5-2.5term1=-0.5*x1**2/100term2=-0.5* (x2+0.03*x1**2-3) **2y=10*np.exp(term1+term2)
returnyy= (8* (x1-0.5) **2+0.1*np.exp(-8*x2+4)
+3*np.sin(2*np.pi*x3*x4)
+cliff(x5, x6)).reshape([-1,1]) +1*np.random.normal(0, 1, [datanum, 1])
task_type="Regression"meta_info= {"X"+str(i+1):{'type':'continuous'} foriinrange(nfeatures)}
meta_info.update({'Y':{'type':'target'}}) fori, (key, item) inenumerate(meta_info.items()):
ifitem['type'] =='target':
sy=MinMaxScaler((0, 1))
y=sy.fit_transform(y)
meta_info[key]['scaler'] =syelse:
sx=MinMaxScaler((0, 1))
sx.fit([[0], [1]])
x[:,[i]] =sx.transform(x[:,[i]])
meta_info[key]['scaler'] =sxtrain_x, test_x, train_y, test_y=train_test_split(x, y, test_size=0.2, random_state=random_state)
returntrain_x, test_x, train_y, test_y, task_type, meta_info, metric_wrapper(rmse, sy)
train_x, test_x, train_y, test_y, task_type, meta_info, get_metric=data_generator1(10000, 0)Run GAMI-Net
## Note the current GAMINet API requires input features being normalized within 0 to 1.model=GAMINet(meta_info=meta_info, interact_num=20, interact_arch=[40] *5, subnet_arch=[40] *5, batch_size=200, task_type=task_type, activation_func=tf.nn.relu, main_effect_epochs=5000, interaction_epochs=5000, tuning_epochs=500, lr_bp=[0.0001, 0.0001, 0.0001], early_stop_thres=[50, 50, 50],
heredity=True, loss_threshold=0.01, reg_clarity=1,
mono_increasing_list=[], mono_decreasing_list=[], ## the indices list of featuresverbose=False, val_ratio=0.2, random_state=random_state)
model.fit(train_x, train_y)
val_x=train_x[model.val_idx, :]
val_y=train_y[model.val_idx, :]
tr_x=train_x[model.tr_idx, :]
tr_y=train_y[model.tr_idx, :]
pred_train=model.predict(tr_x)
pred_val=model.predict(val_x)
pred_test=model.predict(test_x)
gaminet_stat=np.hstack([np.round(get_metric(tr_y, pred_train),5), np.round(get_metric(val_y, pred_val),5),
np.round(get_metric(test_y, pred_test),5)])
print(gaminet_stat)Training Logs
simu_dir="./results/"ifnotos.path.exists(simu_dir):
os.makedirs(simu_dir)
data_dict_logs=model.summary_logs(save_dict=False)
plot_trajectory(data_dict_logs, folder=simu_dir, name="s1_traj_plot", log_scale=True, save_png=True)
plot_regularization(data_dict_logs, folder=simu_dir, name="s1_regu_plot", log_scale=True, save_png=True)Global Visualization
data_dict=model.global_explain(save_dict=False)
global_visualize_density(data_dict, save_png=True, folder=simu_dir, name='s1_global')Feature Importance
feature_importance_visualize(data_dict, save_png=True, folder=simu_dir, name='s1_feature')Local Visualization
data_dict_local=model.local_explain(train_x[:10], train_y[:10], save_dict=False)
local_visualize(data_dict_local[0], save_png=True, folder=simu_dir, name='s1_local')@article{yang2021gami,
title={GAMI-Net: An Explainable Neural Network based on Generalized Additive Models with Structured Interactions},
author={Yang, Zebin and Zhang, Aijun and Sudjianto, Agus},
journal={Pattern Recognition},
volume = {120},
pages = {108192},
year={2021}
}



