What is it a NN does? This notebook is based on the excellent article: Neural Networks, Manifolds and Topology by Christopher Olah.
In [1]:
%config InlineBackend.figure_format='retina'
%matplotlib inline
# Silence warnings
import warnings
warnings.simplefilter(action="ignore", category=FutureWarning)
warnings.simplefilter(action="ignore", category=UserWarning)
warnings.simplefilter(action="ignore", category=RuntimeWarning)
import numpy as np
np.random.seed(123)
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = (8, 8)
plt.rcParams["font.size"] = 14
In [2]:
from ipywidgets import interact
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import train_test_split
In [3]:
# 1D data along the line, A=[−1/3,1/3], B=[−1,−2/3]∪[2/3,1]
X = np.linspace(-1, 1, 1800)
y = np.zeros_like(X)
y[(-1/3<X) & (X<1/3)] = 1
X = X.reshape(1800, 1)
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=900, random_state=2)
In [4]:
# add some scatter to spread points out, purely for display purposes
# the real data is only one dimensional
plt.scatter(X, np.random.normal(scale=0.5, size=1800), c=y, lw=0.)
plt.xlabel("Input feature")
plt.ylim([-3,3]);
In [5]:
mlp = MLPClassifier(hidden_layer_sizes=(2,), max_iter=400,
solver='sgd', verbose=0, random_state=1,
learning_rate_init=0.02, activation='tanh')
def compute_activations(mlp):
# fit it first to populate the various attributes ...
mlp.fit(X_train, y_train)
# re-implement the forward pass logic from within the MLP class
# so we can access the intermediate activations
hidden_layer_sizes = mlp.hidden_layer_sizes
hidden_layer_sizes = list(hidden_layer_sizes)
layer_units = [X_test.shape[1]] + hidden_layer_sizes + [mlp.n_outputs_]
activations = [X_test]
for i in range(mlp.n_layers_ - 1):
activations.append(np.empty((X.shape[0],
layer_units[i + 1])))
# forward pass
mlp._forward_pass(activations)
return activations
In [7]:
def plot_activations(activations):
np.random.seed(123)
hidden_layer = activations[-2]
y_pred = activations[-1]
fig, ax = plt.subplots(1, 3, figsize=(12,4))
# input
ax[0].scatter(X, np.random.normal(scale=0.5, size=1800), c=y, lw=0.)
ax[0].set_xlabel("Input feature")
ax[0].set_ylabel('Dummy')
ax[0].set_ylim([-3,3]);
# hidden layer
ax[1].scatter(hidden_layer[:,0], hidden_layer[:,1], c=y_test, lw=0)
ax[1].set_xlabel('neuron 1')
ax[1].set_ylabel('neuron 2')
#ax[1].set_xlim([-1, 1])
#ax[1].set_ylim([-1, 1])
# output layer
ax[2].scatter(activations[-1], np.random.normal(scale=0.5, size=900), c=y_test, lw=0)
ax[2].set_xlabel('network output')
ax[2].set_ylabel('dummy')
ax[2].set_xlim([0,1])
ax[2].set_ylim([-3,3]);
plt.tight_layout();
plt.show()
In [10]:
def run(iteration=1, activation='tanh'):
mlp.set_params(max_iter=iteration, activation=activation)
activations4 = compute_activations(mlp)
plot_activations(activations4)
interact(run, iteration=(1, 1500, 100), activation=['tanh', 'identity', 'relu']);
In [ ]: