def learn_from_spikes(self, spikes=None, window_size=1, trials=None, remove_zeros=True, disp=False): """ Trains network over spikes contained in instance of :class:`.Spikes` class. Parameters ---------- spikes : :class:`.Spikes`, optional Instance of Spikes class (default None) window_size : int, optional Window size to use (default 1) trials : Type, optional Description (default None) remove_zeros : bool, optional Flag whether to remove windows in which all entries are 0 (default True) disp : bool, optional Display scipy L-BFGS-B output (default False) Returns ------- Nothing """ spikes = spikes or self.spikes trials = trials or range(spikes.T) self.window_size = window_size self.network = HopfieldNetMPF(spikes.N * self.window_size) X = spikes.to_windowed(window_size=self.window_size, trials=trials, reshape=True) self.learn_from_binary(X, remove_zeros=remove_zeros, disp=disp)
def learn_from_binary(self, X, remove_zeros=False, disp=False): """ Trains on M x N matrix X of M N-length binary vects Parameters ---------- X : numpy array (M, N)-dim array of binary input patterns of length N, where N is the number of nodes in the network remove_zeros : bool, optional Flag whether to remove vectors from X in which all entries are 0 (default True) disp : bool, optional Display scipy L-BFGS-B output (default False) Returns ------- Nothing """ self.network = HopfieldNetMPF(len(X[0])) if remove_zeros: X_ = X[X.mean(axis=1) != 0., :] # remove all zeros hdlog.info( "Learning %d %d-bit (nonzero) binary patterns, sparsity %.04f..." % (X_.shape[0], X_.shape[1], X_.mean())) else: X_ = X hdlog.info( "Learning %d %d-bit binary patterns, sparsity %.04f..." % (X_.shape[0], X_.shape[1], X_.mean())) self.network.learn_all(X_, disp=disp)
def test_learning(self): # OPR learning (Hopfield original rule) np.random.seed(42) N = 300 M = N / (4 * np.log(N)) # theoretical max for OPR [McEliece et al, 87] t = now() OPR = HopfieldNet(N) data = (np.random.random((M, N)) < .5).astype('int') OPR.learn_all(data) recall = (data == OPR.hopfield_binary_dynamics(data)).all(1).mean() # recall = (data == OPR.hopfield_binary_dynamics(data, model='OPR')).all(1).mean() # recall = OPR.exact_recalled(data, model='OPR') hdlog.info("OPR Performance (%d/%d): %1.2f in %1.2f s" % (M, N, 100 * recall, now() - t)) self.assertTrue(recall > .8) M = 50 OPR = HopfieldNet(N) data = (np.random.random((M, N)) < .5).astype('int') OPR.learn_all(data) recall = (data == OPR.hopfield_binary_dynamics(data)).all(1).mean() # recall = (data == OPR.hopfield_binary_dynamics(data, model='OPR')).all(1).mean() # recall = OPR.exact_recalled(data) hdlog.info("OPR Performance (%d/%d): %1.2f in %1.2f s" % (M, N, 100 * recall, now() - t)) self.assertTrue(recall < .5) MPF = HopfieldNetMPF(N) MPF.learn_all(data) recall = MPF.exact_recalled(data) hdlog.info("MPF Performance (%d/%d): %1.2f in %1.2f s" % (M, N, 100 * recall, now() - t)) self.assertEqual(recall, 1) # store 90 memories in 64-bit neurons N = 64 M = 90 t = now() MPF = HopfieldNetMPF(N) data = (np.random.random((M, N)) < .5).astype('int') MPF.learn_all(data) recall = MPF.exact_recalled(data) hdlog.info("MPF Performance (%d/%d): %1.2f in %1.2f s" % (M, N, 100 * recall, now() - t)) self.assertEqual(recall, 1) OPR = HopfieldNet(N) OPR.learn_all(data) recall = (data == OPR.hopfield_binary_dynamics(data)).all(1).mean() # recall = OPR.exact_recalled(data) hdlog.info("OPR Performance (%d/%d): %1.2f in %1.2f s" % (M, N, 100 * recall, now() - t)) self.assertTrue(recall < .01)
def learn_from_spikes_rot(self, spikes=None, window_size=1, trials=None, remove_zeros=True, disp=False): """ Trains network over spikes contained in instance of :class:`.Spikes` class, removes windows that are identical modulo a rotation along the first axis. Parameters ---------- spikes : :class:`.Spikes`, optional Instance of Spikes class (default None) window_size : int, optional Window size to use (default 1) trials : Type, optional Description (default None) remove_zeros : bool, optional Flag whether to remove windows in which all entries are 0 (default True) disp : bool, optional Display scipy L-BFGS-B output (default False) Returns ------- Nothing """ spikes = spikes or self.spikes trials = trials or range(spikes.T) self.window_size = window_size self.network = HopfieldNetMPF(spikes.N * self.window_size) c = Counter(save_sequence=True) c.chomp_spikes(spikes, window_size=self.window_size, rotate=(spikes.N, self.window_size)) X = np.array([Counter.pattern_for_key(c.patterns[m]) for m in c.sequence]) self.learn_from_binary(X, remove_zeros=remove_zeros, disp=disp)
def learn_from_binary(self, X, remove_zeros=False, disp=False): """ Trains on M x N matrix X of M N-length binary vects Parameters ---------- X : numpy array (M, N)-dim array of binary input patterns of length N, where N is the number of nodes in the network remove_zeros : bool, optional Flag whether to remove vectors from X in which all entries are 0 (default True) disp : bool, optional Display scipy L-BFGS-B output (default False) Returns ------- Nothing """ self.network = HopfieldNetMPF(len(X[0])) if remove_zeros: X_ = X[X.mean(axis=1) != 0., :] # remove all zeros hdlog.info("Learning %d %d-bit (nonzero) binary patterns, sparsity %.04f..." % ( X_.shape[0], X_.shape[1], X_.mean())) else: X_ = X hdlog.info("Learning %d %d-bit binary patterns, sparsity %.04f..." % (X_.shape[0], X_.shape[1], X_.mean())) self.network.learn_all(X_, disp=disp)
def __init__(self, spikes=None, network=None, network_file=None, window_size=1, params=None): object.__init__(self) Restoreable.__init__(self) self._window_size = window_size if spikes is not None: self._spikes = spikes self._network = HopfieldNetMPF(self._spikes.N * self._window_size) if network is not None: self._network = network if network_file is not None and network is None: self._network = HopfieldNet.load(network_file) if params is not None: self._params = params else: self._params = {'Mode': 'default'}
def learn_from_spikes_rot(self, spikes=None, window_size=1, trials=None, remove_zeros=True, disp=False): """ Trains network over spikes contained in instance of :class:`.Spikes` class, removes windows that are identical modulo a rotation along the first axis. Parameters ---------- spikes : :class:`.Spikes`, optional Instance of Spikes class (default None) window_size : int, optional Window size to use (default 1) trials : Type, optional Description (default None) remove_zeros : bool, optional Flag whether to remove windows in which all entries are 0 (default True) disp : bool, optional Display scipy L-BFGS-B output (default False) Returns ------- Nothing """ spikes = spikes or self.spikes trials = trials or range(spikes.T) self.window_size = window_size self.network = HopfieldNetMPF(spikes.N * self.window_size) c = Counter(save_sequence=True) c.chomp_spikes(spikes, window_size=self.window_size, rotate=(spikes.N, self.window_size)) X = np.array( [Counter.pattern_for_key(c.patterns[m]) for m in c.sequence]) self.learn_from_binary(X, remove_zeros=remove_zeros, disp=disp)
def test_basic(self): MPF = HopfieldNetMPF(N=3) MPF._J = np.array([[0, -1, 1], [-1, 0, 2], [1, 2, 0]]) x = np.array([0, 1, 0]) y = MPF(x, converge=False) self.assertEqual(np.linalg.norm(y - np.array([0, 0, 0])), 0.) x = np.array([1, 0, 0]) y = MPF(x, converge=False) self.assertEqual(np.linalg.norm(y - np.array([0, 0, 0])), 0.) x = np.array([1, 1, 0]) y = MPF(x, converge=False) self.assertEqual(np.linalg.norm(y - np.array([0, 0, 0])), 0.) x = np.array([0, 0, 1]) y = MPF(x, converge=False) self.assertEqual(np.linalg.norm(y - np.array([1, 1, 1])), 0.) x = np.array([1, 0, 1]) y = MPF(x, converge=False) self.assertEqual(np.linalg.norm(y - np.array([1, 1, 1])), 0.) x = np.array([1, 1, 1]) y = MPF(x, converge=False) self.assertEqual(np.linalg.norm(y - np.array([0, 1, 1])), 0.) x = np.array([0, 1, 1]) y = MPF(x, converge=False) self.assertEqual(np.linalg.norm(y - np.array([0, 1, 1])), 0.) self.assertEqual(MPF.energy(np.array([1, 1, 0])), 1) self.assertEqual(MPF.energy(np.array([0, 0, 0])), 0) self.assertEqual(MPF.energy(np.array([1, 0, 0])), 0) self.assertEqual(MPF.energy(np.array([0, 1, 0])), 0) self.assertEqual(MPF.energy(np.array([0, 0, 1])), 0) self.assertEqual(MPF.energy(np.array([1, 0, 1])), -1) self.assertEqual(MPF.energy(np.array([1, 1, 1])), -2) self.assertEqual(MPF.energy(np.array([0, 1, 1])), -2)
class Learner(Restoreable, object): """ Takes spikes and learns a network on windowed patterns. Parameters ---------- spikes : :class:`.Spikes`, optional Spikes class instance to use (default None) network : :class:`.HopfieldNet`, optional HopfieldNetwork class instance to use (default None) network_file : str, optional File name of Hopfield network to load (default None) window_size : int, optional Size of window in bins (default 1) params : dict, optional Dictionary of optional parameters (default None) Returns ------- learner : :class:`.Learner` Instance of class :class:`.Learner` """ _SAVE_ATTRIBUTES_V1 = ['_spikes_file', '_window_size', '_params'] _SAVE_VERSION = 1 _SAVE_TYPE = 'Learner' _INTERNAL_OBJECTS = zip([HopfieldNet], ['_network'], ['network']) def __init__(self, spikes=None, network=None, network_file=None, window_size=1, params=None): object.__init__(self) Restoreable.__init__(self) self._window_size = window_size if spikes is not None: self._spikes = spikes self._network = HopfieldNetMPF(self._spikes.N * self._window_size) if network is not None: self._network = network if network_file is not None and network is None: self._network = HopfieldNet.load(network_file) if params is not None: self._params = params else: self._params = {'Mode': 'default'} @property def network(self): """ Getter for hopfield network of this learner. Returns ------- network : :class:`.HopfieldNet` Network of this learner """ return self._network @network.setter def network(self, value): """ Setter for setting the network of this learner. Parameters ---------- value : :class:`.HopfieldNet` HopfieldNet network to set Returns ------- Nothing """ self._network = value @property def params(self): """ Getter for parameters of learner. Returns ------- parameters : dict Parameters of learner """ return self._params @params.setter def params(self, value): """ Setter for parameters of learner. Parameters ---------- value : dict New dictionary to assign Returns ------- Nothing """ self._params = value @property def window_size(self): """ Getter for window size. Returns ------- value : int Value of window size """ return self._window_size @window_size.setter def window_size(self, value): """ Setter for window size. Parameters ---------- value : int Value of window size to set Returns ------- Nothing """ self._window_size = value @property def spikes(self): """ Setter for spikes. Returns ------- value : :class:`.Spikes` Instance of :class:`.Spikes` class """ return self._spikes @spikes.setter def spikes(self, value): """ Setter for spikes. Parameters ---------- value : :class:`.Spikes` Instance of :class:`.Spikes` class to assign Returns ------- Nothing """ self._spikes = value @property def spikes_file(self): """ Getter for spikes file. Returns ------- file : str File name of spikes file """ return self._spikes_file @spikes_file.setter def spikes_file(self, value): """ Setter for spikes file. Parameters ---------- value : str Value of spikes file to set Returns ------- Nothing """ self._spikes_file = value def learn_from_binary(self, X, remove_zeros=False, disp=False): """ Trains on M x N matrix X of M N-length binary vects Parameters ---------- X : numpy array (M, N)-dim array of binary input patterns of length N, where N is the number of nodes in the network remove_zeros : bool, optional Flag whether to remove vectors from X in which all entries are 0 (default True) disp : bool, optional Display scipy L-BFGS-B output (default False) Returns ------- Nothing """ self.network = HopfieldNetMPF(len(X[0])) if remove_zeros: X_ = X[X.mean(axis=1) != 0., :] # remove all zeros hdlog.info("Learning %d %d-bit (nonzero) binary patterns, sparsity %.04f..." % ( X_.shape[0], X_.shape[1], X_.mean())) else: X_ = X hdlog.info("Learning %d %d-bit binary patterns, sparsity %.04f..." % (X_.shape[0], X_.shape[1], X_.mean())) self.network.learn_all(X_, disp=disp) def learn_from_spikes(self, spikes=None, window_size=1, trials=None, remove_zeros=True, disp=False): """ Trains network over spikes contained in instance of :class:`.Spikes` class. Parameters ---------- spikes : :class:`.Spikes`, optional Instance of Spikes class (default None) window_size : int, optional Window size to use (default 1) trials : Type, optional Description (default None) remove_zeros : bool, optional Flag whether to remove windows in which all entries are 0 (default True) disp : bool, optional Display scipy L-BFGS-B output (default False) Returns ------- Nothing """ spikes = spikes or self.spikes trials = trials or range(spikes.T) self.window_size = window_size self.network = HopfieldNetMPF(spikes.N * self.window_size) X = spikes.to_windowed(window_size=self.window_size, trials=trials, reshape=True) self.learn_from_binary(X, remove_zeros=remove_zeros, disp=disp) def learn_from_spikes_rot(self, spikes=None, window_size=1, trials=None, remove_zeros=True, disp=False): """ Trains network over spikes contained in instance of :class:`.Spikes` class, removes windows that are identical modulo a rotation along the first axis. Parameters ---------- spikes : :class:`.Spikes`, optional Instance of Spikes class (default None) window_size : int, optional Window size to use (default 1) trials : Type, optional Description (default None) remove_zeros : bool, optional Flag whether to remove windows in which all entries are 0 (default True) disp : bool, optional Display scipy L-BFGS-B output (default False) Returns ------- Nothing """ spikes = spikes or self.spikes trials = trials or range(spikes.T) self.window_size = window_size self.network = HopfieldNetMPF(spikes.N * self.window_size) c = Counter(save_sequence=True) c.chomp_spikes(spikes, window_size=self.window_size, rotate=(spikes.N, self.window_size)) X = np.array([Counter.pattern_for_key(c.patterns[m]) for m in c.sequence]) self.learn_from_binary(X, remove_zeros=remove_zeros, disp=disp) def save(self, folder_name='learner'): """ Saves Learner to file. Also saves the contained instance of :class:`.HopfieldNet`. Parameters ---------- folder_name : str, optional Folder name name to save Learner to (default 'learner') Returns ------- Nothing """ super(Learner, self)._save( 'learner.npz', self._SAVE_ATTRIBUTES_V1, self._SAVE_VERSION, has_internal=True, folder_name=folder_name, internal_objects=self._INTERNAL_OBJECTS) @classmethod def load(cls, folder_name='learner', load_extra=False): """ Loads Learner from file. .. note: This is a class method, i.e. loading should be done like this: learner = Learner.load('folder_name') Parameters ---------- folder_name : str, optional Folder name name to load Learner from (default 'learner') load_extra : bool, optional Flag whether to load extra file contents, if any (default False) Returns ------- learner : :class:`.Learner` Instance of :class:`.Learner` if loaded, `None` upon error """ return super(Learner, cls)._load('learner.npz', has_internal=True, folder_name=folder_name, internal_objects=cls._INTERNAL_OBJECTS, load_extra=load_extra) def _load_v1(self, contents, load_extra=False): # internal function to load v1 file format hdlog.debug('Loading Learner, format version 1') return Restoreable._load_attributes(self, contents, self._SAVE_ATTRIBUTES_V1) # representation def __repr__(self): return '<Learner: on network with {n} nodes>'.format(n=self.network.N if self.network.N is not None else 0)
class Learner(Restoreable, object): """ Takes spikes and learns a network on windowed patterns. Parameters ---------- spikes : :class:`.Spikes`, optional Spikes class instance to use (default None) network : :class:`.HopfieldNet`, optional HopfieldNetwork class instance to use (default None) network_file : str, optional File name of Hopfield network to load (default None) window_size : int, optional Size of window in bins (default 1) params : dict, optional Dictionary of optional parameters (default None) Returns ------- learner : :class:`.Learner` Instance of class :class:`.Learner` """ _SAVE_ATTRIBUTES_V1 = ['_spikes_file', '_window_size', '_params'] _SAVE_VERSION = 1 _SAVE_TYPE = 'Learner' _INTERNAL_OBJECTS = zip([HopfieldNet], ['_network'], ['network']) def __init__(self, spikes=None, network=None, network_file=None, window_size=1, params=None): object.__init__(self) Restoreable.__init__(self) self._window_size = window_size if spikes is not None: self._spikes = spikes self._network = HopfieldNetMPF(self._spikes.N * self._window_size) if network is not None: self._network = network if network_file is not None and network is None: self._network = HopfieldNet.load(network_file) if params is not None: self._params = params else: self._params = {'Mode': 'default'} @property def network(self): """ Getter for hopfield network of this learner. Returns ------- network : :class:`.HopfieldNet` Network of this learner """ return self._network @network.setter def network(self, value): """ Setter for setting the network of this learner. Parameters ---------- value : :class:`.HopfieldNet` HopfieldNet network to set Returns ------- Nothing """ self._network = value @property def params(self): """ Getter for parameters of learner. Returns ------- parameters : dict Parameters of learner """ return self._params @params.setter def params(self, value): """ Setter for parameters of learner. Parameters ---------- value : dict New dictionary to assign Returns ------- Nothing """ self._params = value @property def window_size(self): """ Getter for window size. Returns ------- value : int Value of window size """ return self._window_size @window_size.setter def window_size(self, value): """ Setter for window size. Parameters ---------- value : int Value of window size to set Returns ------- Nothing """ self._window_size = value @property def spikes(self): """ Setter for spikes. Returns ------- value : :class:`.Spikes` Instance of :class:`.Spikes` class """ return self._spikes @spikes.setter def spikes(self, value): """ Setter for spikes. Parameters ---------- value : :class:`.Spikes` Instance of :class:`.Spikes` class to assign Returns ------- Nothing """ self._spikes = value @property def spikes_file(self): """ Getter for spikes file. Returns ------- file : str File name of spikes file """ return self._spikes_file @spikes_file.setter def spikes_file(self, value): """ Setter for spikes file. Parameters ---------- value : str Value of spikes file to set Returns ------- Nothing """ self._spikes_file = value def learn_from_binary(self, X, remove_zeros=False, disp=False): """ Trains on M x N matrix X of M N-length binary vects Parameters ---------- X : numpy array (M, N)-dim array of binary input patterns of length N, where N is the number of nodes in the network remove_zeros : bool, optional Flag whether to remove vectors from X in which all entries are 0 (default True) disp : bool, optional Display scipy L-BFGS-B output (default False) Returns ------- Nothing """ self.network = HopfieldNetMPF(len(X[0])) if remove_zeros: X_ = X[X.mean(axis=1) != 0., :] # remove all zeros hdlog.info( "Learning %d %d-bit (nonzero) binary patterns, sparsity %.04f..." % (X_.shape[0], X_.shape[1], X_.mean())) else: X_ = X hdlog.info( "Learning %d %d-bit binary patterns, sparsity %.04f..." % (X_.shape[0], X_.shape[1], X_.mean())) self.network.learn_all(X_, disp=disp) def learn_from_spikes(self, spikes=None, window_size=1, trials=None, remove_zeros=True, disp=False): """ Trains network over spikes contained in instance of :class:`.Spikes` class. Parameters ---------- spikes : :class:`.Spikes`, optional Instance of Spikes class (default None) window_size : int, optional Window size to use (default 1) trials : Type, optional Description (default None) remove_zeros : bool, optional Flag whether to remove windows in which all entries are 0 (default True) disp : bool, optional Display scipy L-BFGS-B output (default False) Returns ------- Nothing """ spikes = spikes or self.spikes trials = trials or range(spikes.T) self.window_size = window_size self.network = HopfieldNetMPF(spikes.N * self.window_size) X = spikes.to_windowed(window_size=self.window_size, trials=trials, reshape=True) self.learn_from_binary(X, remove_zeros=remove_zeros, disp=disp) def learn_from_spikes_rot(self, spikes=None, window_size=1, trials=None, remove_zeros=True, disp=False): """ Trains network over spikes contained in instance of :class:`.Spikes` class, removes windows that are identical modulo a rotation along the first axis. Parameters ---------- spikes : :class:`.Spikes`, optional Instance of Spikes class (default None) window_size : int, optional Window size to use (default 1) trials : Type, optional Description (default None) remove_zeros : bool, optional Flag whether to remove windows in which all entries are 0 (default True) disp : bool, optional Display scipy L-BFGS-B output (default False) Returns ------- Nothing """ spikes = spikes or self.spikes trials = trials or range(spikes.T) self.window_size = window_size self.network = HopfieldNetMPF(spikes.N * self.window_size) c = Counter(save_sequence=True) c.chomp_spikes(spikes, window_size=self.window_size, rotate=(spikes.N, self.window_size)) X = np.array( [Counter.pattern_for_key(c.patterns[m]) for m in c.sequence]) self.learn_from_binary(X, remove_zeros=remove_zeros, disp=disp) def save(self, folder_name='learner'): """ Saves Learner to file. Also saves the contained instance of :class:`.HopfieldNet`. Parameters ---------- folder_name : str, optional Folder name name to save Learner to (default 'learner') Returns ------- Nothing """ super(Learner, self)._save('learner.npz', self._SAVE_ATTRIBUTES_V1, self._SAVE_VERSION, has_internal=True, folder_name=folder_name, internal_objects=self._INTERNAL_OBJECTS) @classmethod def load(cls, folder_name='learner', load_extra=False): """ Loads Learner from file. .. note: This is a class method, i.e. loading should be done like this: learner = Learner.load('folder_name') Parameters ---------- folder_name : str, optional Folder name name to load Learner from (default 'learner') load_extra : bool, optional Flag whether to load extra file contents, if any (default False) Returns ------- learner : :class:`.Learner` Instance of :class:`.Learner` if loaded, `None` upon error """ return super(Learner, cls)._load('learner.npz', has_internal=True, folder_name=folder_name, internal_objects=cls._INTERNAL_OBJECTS, load_extra=load_extra) def _load_v1(self, contents, load_extra=False): # internal function to load v1 file format hdlog.debug('Loading Learner, format version 1') return Restoreable._load_attributes(self, contents, self._SAVE_ATTRIBUTES_V1) # representation def __repr__(self): return '<Learner: on network with {n} nodes>'.format( n=self.network.N if self.network.N is not None else 0)