In [1]:
%load_ext autoreload
%autoreload 2
%matplotlib inline
In [2]:
import random
import numpy as np
import matplotlib.pyplot as plt
from sklearn.externals import joblib
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import classification_report, roc_curve, auc
from sklearn.model_selection import RandomizedSearchCV, train_test_split
from game.utils import get_database_cursor
from game.constants import DIM, CLFILE
In [3]:
import warnings
warnings.filterwarnings('ignore')
In [4]:
with get_database_cursor() as cur:
# Fetch data from the database and preprocess it:
# 1. Average the 'winning' value over the equal 'state's
# 2. Retrieve 'state' and 'winning' values from the averaged
# ones such that the 'winning' value becomes equal to 0 if
# it's less than 0.5, and equal to 1 otherwise.
cur.execute("""
SELECT
state,
CASE WHEN winning < 0.5 THEN 0 ELSE 1 END AS winning
FROM (
SELECT
state,
SUM(winning) / COUNT(winning) AS winning
FROM states
GROUP BY state
);
""")
rows = cur.fetchall()
if rows is None:
raise TypeError('no training data found')
X and target y vectors:
In [5]:
n = len(rows)
X = np.zeros((n, 2 * DIM * DIM))
y = np.zeros(n)
for i, row in enumerate(rows):
state_str, winning = row
X[i, :] = np.fromstring(state_str, dtype=int)
y[i] = int(winning)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
In [6]:
pos_n = int(y.sum())
print('positives:', pos_n)
print('negatives:', len(y) - pos_n)
In [7]:
N_ARCH = 1000
N_LAYERS_MIN = 1
N_LAYERS_MAX = 2
N_NEURONS_MIN = 100
N_NEURONS_MAX = 500
hidden_layer_sizes = []
for i in range(N_ARCH):
n_layers = random.randint(N_LAYERS_MIN, N_LAYERS_MAX)
random_size = []
for layer in range(n_layers):
n_neurons = random.randint(N_NEURONS_MIN, N_NEURONS_MAX)
random_size.append(n_neurons)
hidden_layer_sizes.append(tuple(random_size))
In [8]:
# Number of random search iterations:
N_ITER = 100
clf = MLPClassifier(early_stopping=True)
params = {
'hidden_layer_sizes': hidden_layer_sizes,
'alpha': np.linspace(0.001, 0.05, num=100),
'activation': ('logistic', 'tanh', 'relu')
}
rs = RandomizedSearchCV(estimator=clf, param_distributions=params,
n_jobs=2, n_iter=N_ITER, cv=5, scoring='f1', verbose=1)
rs.fit(X_train, y_train)
clf = rs.best_estimator_
# Save the best classifier model:
joblib.dump(clf, CLFILE);
In [9]:
print('Best score:', rs.best_score_)
print('Best NN parameters found:', rs.best_params_)
In [10]:
print(classification_report(y_test, clf.predict(X_test)))
In [11]:
y_score = clf.predict_proba(X_test)[:, 1]
fpr, tpr, _ = roc_curve(y_test, y_score)
roc_auc = auc(fpr, tpr)
plt.figure()
plt.plot(fpr, tpr, label='ROC curve (area = {:.2f})'.format(roc_auc))
plt.plot([0, 1], [0, 1], 'k--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.0])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic')
plt.legend(loc="lower right")
plt.show()