Skip to content

Instantly share code, notes, and snippets.

@macrat
Created March 16, 2016 11:14
Show Gist options
  • Save macrat/884fd50e3168017e5ee4 to your computer and use it in GitHub Desktop.
Save macrat/884fd50e3168017e5ee4 to your computer and use it in GitHub Desktop.
pythonでSOM的なもの。一応sklearn互換っぽい。
from sklearn.base import BaseEstimator, TransformerMixin
import numpy
class SOM(BaseEstimator, TransformerMixin):
def __init__(self, mapsize, input_dim, ini=None, fin=1, coefficient=0.005, verbose=False):
self.input_dim = input_dim
self.mapsize = numpy.array(list(mapsize))
self.mapdim = len(self.mapsize)
self.idx = numpy.mgrid[[slice(x) for x in self.mapsize]].swapaxes(0, self.mapdim).swapaxes(0, 1)
if ini is None:
ini = max(1, self.mapsize.min() // 2)
self.ini = ini
self.fin = fin
self.coefficient = coefficient
self.verbose = verbose
self.initialize()
def initialize(self):
self.weight = numpy.random.rand(self.mapsize.prod(), self.input_dim).reshape(list(self.mapsize) + [self.input_dim])
def transform(self, X):
return numpy.array([
numpy.unravel_index(
numpy.sqrt((self.weight - x)**2).sum(axis=self.mapdim).argmin(),
self.mapsize
)[::-1]
for x in X
])
def fit_iteration(self, X, n_loop=2000):
for t in range(n_loop):
if self.verbose:
print('fitting SOM: {0}/{1}({2:.2%})'.format(t, n_loop, t/n_loop))
delta = (self.ini * (self.fin / self.ini) ** (t / n_loop)) ** 2
self.weight += sum((self.coefficient * numpy.exp(
-((self.idx - win)**2).sum(axis=self.mapdim) / delta
) * (x - self.weight).swapaxes(0, self.mapdim)).swapaxes(0, self.mapdim)
for x, win in zip(X, self.transform(X))
)
yield self
return self
def fit(self, X, n_loop=2000):
self.initialize()
for _ in self.fit_iteration(X, n_loop=n_loop):
pass
return self
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment