# coding: utf-8
# pylint: disable = invalid-name, C0111
import gpboost as gpb
import numpy as np
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt
plt.style.use('ggplot')

#--------------------Cross validation for tree-boosting without GP or random effects----------------
print('Simulating data...')
# Simulate and create your dataset
def f1d(x):
    """Non-linear function for simulation"""
    return (1.7 * (1 / (1 + np.exp(-(x - 0.5) * 20)) + 0.75 * x))
x = np.linspace(0, 1, 200, endpoint=True)
plt.plot(x, f1d(x), linewidth=2, color="r")
plt.title("Mean function")
plt.show()
def sim_data(n):
    """Function that simulates data. Two covariates of which only one has an effect"""
    X = np.random.rand(n, 2)
    # mean function plus noise
    y = f1d(X[:, 0]) + np.random.normal(scale=0.1, size=n)
    return ([X, y])

# Simulate data
n = 1000
data = sim_data(2 * n)
# create dataset for gpb.train
data_train = gpb.Dataset(data[0][0:n, :], data[1][0:n])

# specify your configurations as a dict
params = {
    'objective': 'regression_l2',
    'metric': {'l2', 'l1'},
    'learning_rate': 0.1,
    'max_depth': 6,
    'min_data_in_leaf': 5,
    'verbose': 0
}

print('Starting cross-validation...')
# do cross-validation
cvbst = gpb.cv(params=params, train_set=data_train,
               num_boost_round=100, early_stopping_rounds=5,
               nfold=2, verbose_eval=True, show_stdv=False, seed=1)
print("Best number of iterations: " + str(np.argmin(cvbst['l2-mean'])))


# --------------------Combine tree-boosting and grouped random effects model----------------
print('Simulating data...')
# Simulate data
def f1d(x):
    """Non-linear function for simulation"""
    return (1.7 * (1 / (1 + np.exp(-(x - 0.5) * 20)) + 0.75 * x))
x = np.linspace(0, 1, 200, endpoint=True)
plt.figure("Mean function")
plt.plot(x, f1d(x), linewidth=2, color="r")
plt.title("Mean function")
plt.show()
n = 1000  # number of samples
np.random.seed(1)
X = np.random.rand(n, 2)
F = f1d(X[:, 0])
# Simulate grouped random effects
m = 25  # number of categories / levels for grouping variable
group = np.arange(n)  # grouping variable
for i in range(m):
    group[int(i * n / m):int((i + 1) * n / m)] = i
# incidence matrix relating grouped random effects to samples
Z1 = np.zeros((n, m))
for i in range(m):
    Z1[np.where(group == i), i] = 1
sigma2_1 = 1 ** 2  # random effect variance
sigma2 = 0.1 ** 2  # error variance
b1 = np.sqrt(sigma2_1) * np.random.normal(size=m)  # simulate random effects
eps = Z1.dot(b1)
xi = np.sqrt(sigma2) * np.random.normal(size=n)  # simulate error term
y = F + eps + xi  # observed data

# define GPModel
gp_model = gpb.GPModel(group_data=group)
gp_model.set_optim_params(params={"optimizer_cov": "fisher_scoring"})
# create dataset for gpb.train
data_train = gpb.Dataset(X, y)
# specify your configurations as a dict
params = {
    'objective': 'regression_l2',
    'learning_rate': 0.05,
    'max_depth': 6,
    'min_data_in_leaf': 5,
    'verbose': 0
}

print('Starting cross-validation...')
# do cross-validation
cvbst = gpb.cv(params=params, train_set=data_train,
               gp_model=gp_model, use_gp_model_for_validation=False,
               num_boost_round=100, early_stopping_rounds=5,
               nfold=2, verbose_eval=True, show_stdv=False, seed=1)
print("Best number of iterations: " + str(np.argmin(cvbst['l2-mean'])))

# Include random effect predictions for validation (observe the lower test error)
gp_model = gpb.GPModel(group_data=group)
print("Running cross validation for GPBoost model and use_gp_model_for_validation = TRUE")
cvbst = gpb.cv(params=params, train_set=data_train,
               gp_model=gp_model, use_gp_model_for_validation=True,
               num_boost_round=100, early_stopping_rounds=5,
               nfold=2, verbose_eval=True, show_stdv=Falsem, seed=1)
print("Best number of iterations: " + str(np.argmin(cvbst['l2-mean'])))
cvbst.best_iteration

[(7, 'matplotlib.pyplot.style.use', 'plt.style.use', (['"""ggplot"""'], {}), True, 'import matplotlib.pyplot as plt\n'), (15, 'numpy.linspace', 'np.linspace', (['(0)', '(1)', '(200)'], {'endpoint': '(True)'}), True, 'import numpy as np\n'), (17, 'matplotlib.pyplot.title', 'plt.title', (['"""Mean function"""'], {}), True, 'import matplotlib.pyplot as plt\n'), (18, 'matplotlib.pyplot.show', 'plt.show', ([], {}), True, 'import matplotlib.pyplot as plt\n'), (30, 'gpboost.Dataset', 'gpb.Dataset', (['data[0][0:n, :]', 'data[1][0:n]'], {}), True, 'import gpboost as gpb\n'), (44, 'gpboost.cv', 'gpb.cv', ([], {'params': 'params', 'train_set': 'data_train', 'num_boost_round': '(100)', 'early_stopping_rounds': '(5)', 'nfold': '(2)', 'verbose_eval': '(True)', 'show_stdv': '(False)', 'seed': '(1)'}), True, 'import gpboost as gpb\n'), (56, 'numpy.linspace', 'np.linspace', (['(0)', '(1)', '(200)'], {'endpoint': '(True)'}), True, 'import numpy as np\n'), (57, 'matplotlib.pyplot.figure', 'plt.figure', (['"""Mean function"""'], {}), True, 'import matplotlib.pyplot as plt\n'), (59, 'matplotlib.pyplot.title', 'plt.title', (['"""Mean function"""'], {}), True, 'import matplotlib.pyplot as plt\n'), (60, 'matplotlib.pyplot.show', 'plt.show', ([], {}), True, 'import matplotlib.pyplot as plt\n'), (62, 'numpy.random.seed', 'np.random.seed', (['(1)'], {}), True, 'import numpy as np\n'), (63, 'numpy.random.rand', 'np.random.rand', (['n', '(2)'], {}), True, 'import numpy as np\n'), (67, 'numpy.arange', 'np.arange', (['n'], {}), True, 'import numpy as np\n'), (71, 'numpy.zeros', 'np.zeros', (['(n, m)'], {}), True, 'import numpy as np\n'), (82, 'gpboost.GPModel', 'gpb.GPModel', ([], {'group_data': 'group'}), True, 'import gpboost as gpb\n'), (85, 'gpboost.Dataset', 'gpb.Dataset', (['X', 'y'], {}), True, 'import gpboost as gpb\n'), (97, 'gpboost.cv', 'gpb.cv', ([], {'params': 'params', 'train_set': 'data_train', 'gp_model': 'gp_model', 'use_gp_model_for_validation': '(False)', 'num_boost_round': '(100)', 'early_stopping_rounds': '(5)', 'nfold': '(2)', 'verbose_eval': '(True)', 'show_stdv': '(False)', 'seed': '(1)'}), True, 'import gpboost as gpb\n'), (104, 'gpboost.GPModel', 'gpb.GPModel', ([], {'group_data': 'group'}), True, 'import gpboost as gpb\n'), (106, 'gpboost.cv', 'gpb.cv', ([], {'params': 'params', 'train_set': 'data_train', 'gp_model': 'gp_model', 'use_gp_model_for_validation': '(True)', 'num_boost_round': '(100)', 'early_stopping_rounds': '(5)', 'nfold': '(2)', 'verbose_eval': '(True)', 'show_stdv': 'Falsem', 'seed': '(1)'}), True, 'import gpboost as gpb\n'), (21, 'numpy.random.rand', 'np.random.rand', (['n', '(2)'], {}), True, 'import numpy as np\n'), (76, 'numpy.sqrt', 'np.sqrt', (['sigma2_1'], {}), True, 'import numpy as np\n'), (76, 'numpy.random.normal', 'np.random.normal', ([], {'size': 'm'}), True, 'import numpy as np\n'), (78, 'numpy.sqrt', 'np.sqrt', (['sigma2'], {}), True, 'import numpy as np\n'), (78, 'numpy.random.normal', 'np.random.normal', ([], {'size': 'n'}), True, 'import numpy as np\n'), (23, 'numpy.random.normal', 'np.random.normal', ([], {'scale': '(0.1)', 'size': 'n'}), True, 'import numpy as np\n'), (47, 'numpy.argmin', 'np.argmin', (["cvbst['l2-mean']"], {}), True, 'import numpy as np\n'), (101, 'numpy.argmin', 'np.argmin', (["cvbst['l2-mean']"], {}), True, 'import numpy as np\n'), (110, 'numpy.argmin', 'np.argmin', (["cvbst['l2-mean']"], {}), True, 'import numpy as np\n'), (73, 'numpy.where', 'np.where', (['(group == i)'], {}), True, 'import numpy as np\n'), (14, 'numpy.exp', 'np.exp', (['(-(x - 0.5) * 20)'], {}), True, 'import numpy as np\n'), (55, 'numpy.exp', 'np.exp', (['(-(x - 0.5) * 20)'], {}), True, 'import numpy as np\n')]