Skip to content

Instantly share code, notes, and snippets.

@ottokart
Created December 12, 2016 13:58
Show Gist options
  • Save ottokart/7335eccc688370fe6ee6937346150e1b to your computer and use it in GitHub Desktop.
Save ottokart/7335eccc688370fe6ee6937346150e1b to your computer and use it in GitHub Desktop.
Simple Self-Organizing Map
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(1)
# Replace X with your own data if you wish
##########################################
N = 300 # num samples
NOISE_LEVEL = 100 # between 0 and 255
COLORS = np.array([[255,0,0], [0,255,0], [0,0,255]], dtype=np.float32)
X = COLORS[np.random.choice(len(COLORS), N)] # dataset of random colors
X = np.clip(X + np.random.uniform(-NOISE_LEVEL, NOISE_LEVEL, size=(N, 3)), 0, 255)
X /= X.max()
##########################################
ROWS = 10
COLS = 15
NUM_NODES = ROWS*COLS
TMAX = 30 # Max number of iterations
R0 = max(ROWS, COLS) / 2. # Initial neighbourhood radius
L0 = 0.1 # Initial learning rate
neighbourhood_func = lambda w1, w2, t: np.exp(-((w1[0] - w2[0])**2 + (w1[1] - w2[1])**2) / (2. * decay_func(R0, t)**2))
decay_func = lambda x0, t: x0 * np.exp(-2 * x0 * t / TMAX)
index_to_coords = lambda i: (int(i / COLS), i % COLS)
coords_to_index = lambda x, y: x * COLS + y
W = np.random.uniform(0, 1, size=(NUM_NODES, 3)) # randomize weights
for t in range(TMAX):
for x in X:
i = np.argmin(np.sum((x - W)**2, axis=1)) # find the node with the smallest distance from x
x_i, y_i = index_to_coords(i)
r = int(decay_func(R0, t))
for x_j in range(max(x_i - r, 0), min(x_i + r + 1, ROWS)):
for y_j in range(max(y_i - r, 0), min(y_i + r + 1, COLS)): # update the nodes in the neighborhood of the winner by pulling them closer to the input vector
j = coords_to_index(x_j, y_j)
W[j] += decay_func(L0, t) * neighbourhood_func([x_i, y_i], [x_j, y_j], t) * (x - W[j])
plt.imshow(W.reshape(ROWS,COLS,3), interpolation='none')
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment