In [1]:
# /!\ I'm using Python 3

import plotly
import numpy as np
import plotly.plotly as py
import plotly.graph_objs as go

import matplotlib.pyplot as plt
import scipy.io as sio
from scipy import stats
%matplotlib inline

plotly.offline.init_notebook_mode(connected=True)
from IPython.core.display import display, HTML, Markdown
# The polling here is to ensure that plotly.js has already been loaded before
# setting display alignment in order to avoid a race condition.
display(HTML(
    '<script>'
        'var waitForPlotly = setInterval( function() {'
            'if( typeof(window.Plotly) !== "undefined" ){'
                'MathJax.Hub.Config({ SVG: { font: "STIX-Web" }, displayAlign: "center" });'
                'MathJax.Hub.Queue(["setRenderer", MathJax.Hub, "SVG"]);'
                'clearInterval(waitForPlotly);'
            '}}, 250 );'
    '</script>'
))

# Colorscales
def colorscale_list(cmap, number_colors, return_rgb_only=False):
    cm = plt.get_cmap(cmap)
    colors = [np.array(cm(i/number_colors)) for i in range(1, number_colors+1)]
    rgb_colors_plotly = []
    rgb_colors_only = []
    for i, c in enumerate(colors):
        col = 'rgb{}'.format(tuple(255*c[:-1]))
        rgb_colors_only.append(col)
        rgb_colors_plotly.append([i/number_colors, col])
        rgb_colors_plotly.append([(i+1)/number_colors, col])
    return rgb_colors_only if return_rgb_only else rgb_colors_plotly

import scipy.integrate as integrate

import colorlover as cl

def formatted(f): 
    return format(f, '.2f').rstrip('0').rstrip('.')

1. Perceptron

In [2]:
data = {}
trace = {}
trace_handwritten = {}
ranges = {}
layout = {}
In [3]:
label = '2D'

ranges[label] = {}
trace[label] = {}
data[label] = {}
data[label]['X'] = np.array([[1.,2],[1,3],[3,4],[2,4],[4,0],[6,2],[2,-3],[6,-2]])
data[label]['Y'] = np.ones(8)
data[label]['Y'][:4] = 0

# Plotting the 2D-set

ranges[label]['x_1'] = [int(np.min(data[label]['X'][:,0])-1), int(np.max(data[label]['X'][:,0])+1)]
ranges[label]['x_2'] = [int(np.min(data[label]['X'][:,1])-2), int(np.max(data[label]['X'][:,1])+2)]

trace[label]['data'] = go.Scatter(
    x = data[label]['X'][:,0],
    y = data[label]['X'][:,1],
    mode = 'markers',
    marker = dict(
        size = 10,
        color = data[label]['Y'],
        colorbar = dict(
            title = 'Color',
            titleside = 'top',
            tickmode = 'array',
            tickvals = [0, 1],
            ticktext = [' Blue Set',' Red Set'],
            ticks = 'outside'
        ),
        showscale = True,
        line = dict(
            width = 2,
            color = 'rgb(0, 0, 0)'
        ),
        colorscale = [
            [0., 'rgb(69,117,180)'], [0.5, 'rgb(69,117,180)'],
            [0.5, 'rgb(215,48,39)'], [1, 'rgb(215,48,39)']
        ]
    ),
    showlegend = False
)

layout[label] = dict(
    title = '{} set'.format(label),
    xaxis = dict(
        title = '$x$',
        range = ranges[label]['x_1'],
        ticklen = 5,
        zeroline = False,
        gridwidth = 2,
        ),
    yaxis = dict(
        title = '$y$',
        range = ranges[label]['x_2'],
        zeroline=False,
        ticklen = 5,
        gridwidth = 2,
        ),
    legend = dict(
        orientation = 'h',
        y = -0.2
    )
)


range_values = np.linspace(ranges[label]['x_1'][0], ranges[label]['x_1'][1], 20)

trace_handwritten[label] = go.Scatter(
    x = range_values,
    y = range_values-1.5,
    mode = 'lines',
    line = dict(
        color = ('SeaGreen'),
        width = 4,
        dash = 'longdash'),
    name = 'Handwritten separating line'
)

fig = dict(data=[trace[label]['data'], trace_handwritten[label]], layout=layout[label])
plotly.offline.iplot(fig)
In [4]:
label = '3D'


ranges[label] = {}
trace[label] = {}
data[label] = {}
data[label]['X'] = np.array([[2.,1,2],[3,2,3],[4,2,4],[3,1,2],[1,4,-1],[2,3,0],[1,2,0],[0,1,0]])
data[label]['Y'] = np.ones(8)
data[label]['Y'][:4] = 0


# Plotting the 2D-set

trace[label]['data'] = go.Scatter3d(
    x = data[label]['X'][:,0],
    y = data[label]['X'][:,1],
    z = data[label]['X'][:,2],
    mode = 'markers',
    marker = dict(
        size = 7,
        color = data[label]['Y'],
        colorbar = dict(
            title = 'Color',
            titleside = 'top',
            tickmode = 'array',
            tickvals = [0, 1],
            ticktext = [' Blue Set',' Red Set'],
            ticks = 'outside'
        ),
        showscale = True,
        line = dict(
            width = 2,
            color = 'rgb(0, 0, 0)'
        ),
        colorscale = [
            [0., 'rgb(69,117,180)'], [0.5, 'rgb(69,117,180)'],
            [0.5, 'rgb(215,48,39)'], [1, 'rgb(215,48,39)']
        ]
    ),
    showlegend = False
)

ranges[label]['x_1'] = [int(np.min(data[label]['X'][:,0])-1), int(np.max(data[label]['X'][:,0])+1)]
ranges[label]['x_2'] = [int(np.min(data[label]['X'][:,1])-2), int(np.max(data[label]['X'][:,1])+2)]
ranges[label]['x_3'] = [int(np.min(data[label]['X'][:,2])-2), int(np.max(data[label]['X'][:,2])+2)]

layout[label] = dict(
    title = '{} set'.format(label)
)

x1_range_values = np.linspace(ranges[label]['x_1'][0], ranges[label]['x_1'][1], 100)
x2_range_values = np.linspace(ranges[label]['x_2'][0], ranges[label]['x_2'][1], 100)
    
x_1, x_2 = np.meshgrid(x1_range_values, x2_range_values)
    
trace_handwritten[label] = go.Surface(
    x = x_1,
    y = x_2,
    z = 0*x_1+1,
    name = 'Handwritten separating plane',
    surfacecolor = 0*x_1,
    cauto = False,
    colorscale = [[0., 'SeaGreen'], [1., 'SeaGreen']],
    opacity=0.7,
    showscale=False
)

fig = dict(data=[trace[label]['data'], trace_handwritten[label]], layout=layout[label])
plotly.offline.iplot(fig)
In [5]:
# Plotting the separating line
traces = []

arrows = []

v = np.array([4, -4])

traces.append(
    go.Scatter(
        x = range_values, 
        y = -v[0]*range_values/v[1],
        mode = 'lines',
        name = 'Separating line after applying the algorithm',
        line = dict(
            width = 2,
            color = 'Green',
            dash = 'solid'
        ),
        hoverlabel = dict(
            namelength = -1
        ),
        showlegend = True
    )
)

arrows.append(
    dict(
        ax=3,
        ay=-v[0]*3/v[1],
        axref='x',
        ayref='y',
        x=3+v[0]/(np.linalg.norm(v)),
        y=-v[0]*3/v[1]+v[1]/(np.linalg.norm(v)),
        xref='x',
        yref='y',
        showarrow=True,
        arrowhead=3,
        arrowsize=1,
        arrowwidth=2,
        arrowcolor='Purple',
        xshift=0,
        yshift=0
    )
)

    
layout_arrows = dict(
    title = '2D set',
    xaxis = dict(
        title = '$x$',
        ticklen = 5,
        zeroline = False,
        range=[0,8]
    ),
    yaxis = dict(
        title = '$y$',
        zeroline = False,
        range=[-3.5, 4.5],
        ticklen = 5
        ),
    legend = dict(
        orientation = 'h',
        y = -0.2
    ),
    annotations=arrows,
    height=900,
    width=900
)
    

plotly.offline.iplot(go.Figure(data=traces+[trace['2D']['data']], layout=layout_arrows))
In [6]:
# Plotting the separating plane

v = np.array([-1, 2, -3])

traces = []

arrows = []

label = '3D'
ranges[label]['x_1'] = [int(np.min(data[label]['X'][:,0])-1), int(np.max(data[label]['X'][:,0])+1)]
ranges[label]['x_2'] = [int(np.min(data[label]['X'][:,1])-2), int(np.max(data[label]['X'][:,1])+2)]
ranges[label]['x_3'] = [int(np.min(data[label]['X'][:,2])-2), int(np.max(data[label]['X'][:,2])+2)]

x1_range_values = np.linspace(ranges[label]['x_1'][0], ranges[label]['x_1'][1], 100)
x2_range_values = np.linspace(ranges[label]['x_2'][0], ranges[label]['x_2'][1], 100)


traces.append(
    go.Surface(
        x = x_1,
        y = x_2,
        z = (-v[0]*x_1-v[1]*x_2)/v[2],
        name = 'Separating plane after applying the algorithm',
        surfacecolor = 0*x_1,
        cauto = False,
        colorscale = [[0., 'Green'], [1., 'Green']],
        opacity = 0.7,
        showscale = False
    )
)
    
    
layout_arrows = dict(
    title = '3D set'
)
    

plotly.offline.iplot(go.Figure(data=traces+[trace['3D']['data']], layout=layout_arrows))
In [7]:
def perceptron_rule(X, Y):
    nb_trials, dimension = X.shape
    w = np.ones(X.shape[1])
    w_values = [np.copy(w)]

    while True:
        # is the readout vector still changing?
        # (to halt the loop, in case it isn't)
        still_changing = False
        
        for i in range(nb_trials):
            w += (Y[i]-int(w.dot(X[i])>=0))*X[i]
            
            if np.any(w_values[-1] != w):
                still_changing = True
            w_values.append(np.copy(w))

        if not still_changing:
            break
    
    # Returning all the readout weight vectors,
    # except those of the last step 
    # (throughout which the readout vector didn't change)
    return np.array(w_values[:-nb_trials])

perceptron_rule(data['2D']['X'], data['2D']['Y'])
Out[7]:
array([[ 1.,  1.],
       [ 0., -1.],
       [ 0., -1.],
       [ 0., -1.],
       [ 0., -1.],
       [ 0., -1.],
       [ 6.,  1.],
       [ 6.,  1.],
       [ 6.,  1.],
       [ 5., -1.],
       [ 4., -4.],
       [ 4., -4.],
       [ 4., -4.],
       [ 4., -4.],
       [ 4., -4.],
       [ 4., -4.],
       [ 4., -4.]])
In [8]:
legend_every = 5

values = perceptron_rule(data['2D']['X'], data['2D']['Y'])

#colors = cl.scales['{}'.format(len(values))]['seq']['Greens']
colors = colorscale_list('Greens', len(values)+3, return_rgb_only=True)


# Plotting the evolution
traces = []

arrows = []

for i, v in enumerate(values):
    traces.append(
        go.Scatter(
            x = range_values, 
            y = -v[0]*range_values/v[1],
            mode = 'lines',
            name = 'Separating line at iteration {}'.format(i+1),
            line = dict(
                width = 2,
                color = colors[i+2],
                dash = 'solid'
            ),
            hoverlabel = dict(
                namelength = -1
            ),
            showlegend = (i % legend_every == 0)
        )
    )
    
    arrows.append(
        dict(
            ax=.5,
            ay=-v[0]*.5/v[1],
            axref='x',
            ayref='y',
            x=.5+v[0]/(2*np.linalg.norm(v)),
            y=-v[0]*.5/v[1]+v[1]/(2*np.linalg.norm(v)),
            xref='x',
            yref='y',
            showarrow=True,
            arrowhead=3,
            arrowsize=1,
            arrowwidth=2,
            arrowcolor='Purple',
            xshift=0,
            yshift=0,
        )
    )

    
layout_arrows = dict(
    title = '2D set',
    xaxis = dict(
        title = '$x$',
        ticklen = 5,
        zeroline = False,
        range=[0,8]
    ),
    yaxis = dict(
        title = '$y$',
        zeroline = False,
        range=[-3.5, 4.5],
        ticklen = 5
        ),
    legend = dict(
        orientation = 'h',
        y = -0.2
    ),
    annotations=arrows,
    height=900,
    width=900
)
    

plotly.offline.iplot(go.Figure(data=traces+[trace['2D']['data']], layout=layout_arrows))
In [9]:
perceptron_rule(data['3D']['X'], data['3D']['Y'])
Out[9]:
array([[ 1.,  1.,  1.],
       [-1.,  0., -1.],
       [-1.,  0., -1.],
       [-1.,  0., -1.],
       [-1.,  0., -1.],
       [-1.,  0., -1.],
       [ 1.,  3., -1.],
       [ 1.,  3., -1.],
       [ 1.,  3., -1.],
       [-1.,  2., -3.],
       [-1.,  2., -3.],
       [-1.,  2., -3.],
       [-1.,  2., -3.],
       [-1.,  2., -3.],
       [-1.,  2., -3.],
       [-1.,  2., -3.],
       [-1.,  2., -3.]])
In [10]:
legend_every = 5

values = perceptron_rule(data['3D']['X'], data['3D']['Y'])

#colors = cl.scales['{}'.format(len(values))]['seq']['Greens']
colors = colorscale_list('Greens', len(values)+3, return_rgb_only=True)


# Plotting the evolution
traces = []

arrows = []

label = '3D'
ranges[label]['x_1'] = [int(np.min(data[label]['X'][:,0])-1), int(np.max(data[label]['X'][:,0])+1)]
ranges[label]['x_2'] = [int(np.min(data[label]['X'][:,1])-2), int(np.max(data[label]['X'][:,1])+2)]
ranges[label]['x_3'] = [int(np.min(data[label]['X'][:,2])-2), int(np.max(data[label]['X'][:,2])+2)]

x1_range_values = np.linspace(ranges[label]['x_1'][0], ranges[label]['x_1'][1], 100)
x2_range_values = np.linspace(ranges[label]['x_2'][0], ranges[label]['x_2'][1], 100)


for i, v in enumerate(values):
    traces.append(
        go.Surface(
            x = x_1,
            y = x_2,
            z = (-v[0]*x_1-v[1]*x_2)/v[2],
            name = 'Step {}'.format(i+1),
            surfacecolor = 0*x_1,
            cauto = False,
            colorscale = [[0., colors[i+2]], [1., colors[i+2]]],
            opacity = 0.5,
            showscale = False,
            showlegend = (i % legend_every == 0)
        )
    )
    
    
layout_arrows = dict(
    title = '3D set',
    height = 900,
    width = 900
)
    

plotly.offline.iplot(go.Figure(data=traces+[trace['3D']['data']], layout=layout_arrows))

2. Hopfield networks

In [11]:
N = 5
xi_ast = np.array([1., -1, -1, 1, -1])
eta_ast = np.array([1., 1, -1, -1, -1])

W = (np.outer(xi_ast, xi_ast) + np.outer(eta_ast, eta_ast))/N

def dynamics(state):
    return np.sign(W.dot(state))
In [12]:
fixed_point_reached = False
state = np.array([1., -1, 1, 1, 1])

table = '''
Step|State|
:--:|:--:|
0|{}
'''.format(state)

step = 1

while not fixed_point_reached:
    new_state = dynamics(state)
    
    if (new_state == state).all():
        fixed_point_reached = True
        
    table += "{}|{}\n".format(step, new_state)
    
    state = new_state
    step += 1

display(Markdown(table))
Step State
0 [ 1. -1. 1. 1. 1.]
1 [-1. -1. 1. 1. 1.]
2 [-1. -1. 1. 1. 1.]