def num_hopfield_iter(self, X, max_iter=10 ** 5): """ Returns array consisting of the number of Hopfield iterations needed to converge elements in `X` to their memories. 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 max_iter : int, optional Maximal number if iterations to perform per element (default 10 ** 5) Returns ------- count : numpy array Number of iterations performed for each element in `X` """ count_arr = [] for x in X: count = 1 out = self(x) while not (x == out).all(): count += 1 out = x x = self(x) if count > max_iter: hdlog.warn("Exceeded maximum number of iterations (%d)" % max_iter) break count_arr.append(count) return count_arr
def num_hopfield_iter(self, X, max_iter=10**5): """ Returns array consisting of the number of Hopfield iterations needed to converge elements in `X` to their memories. 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 max_iter : int, optional Maximal number if iterations to perform per element (default 10 ** 5) Returns ------- count : numpy array Number of iterations performed for each element in `X` """ count_arr = [] for x in X: count = 1 out = self(x) while not (x == out).all(): count += 1 out = x x = self(x) if count > max_iter: hdlog.warn("Exceeded maximum number of iterations (%d)" % max_iter) break count_arr.append(count) return count_arr
def __call__(self, X, converge=True, max_iter=10 ** 5, clamped_nodes=None): """ Usage: network(X) returns the Hopfield dynamics update to patterns stored in rows of M x N matrix X. If `converge` is False then 1 update run through the neurons is performed, otherwise Hopfield dynamics are run on X until convergence or `max_iter` iterations of updates are reached. .. note: Set max_iter = Inf to always force convergence `clamped_nodes` is dictionary of those nodes not to update during the dynamics. 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 converge : bool, optional Flag whether to converge Hopfield dynamics. If False, just one step of dynamics is performed (default True) max_iter : int, optional Maximal number of iterations of dynamics (default 10 ** 5) clamped_nodes : Type, optional List of clamped nodes that are left untouched during dynamics update (default None) Returns ------- patterns : numpy array Converged patterns (memories) of Hopfield dynamics of input argument X """ if clamped_nodes is None: clamped_nodes = {} ndim = X.ndim # so that 1D vectors and arrays of vectors both work as X X = np.atleast_2d(X) out = np.zeros_like(X) niter = 0 if converge: while (niter == 0) or not (X == out).all(): if niter >= max_iter: hdlog.warn("Exceeded maximum number of iterations (%d)" % max_iter) break niter += 1 out = X X = self.hopfield_binary_dynamics( X, clamped_nodes=clamped_nodes, update=self._update) self._last_num_iter_for_convergence = niter else: self._last_num_iter_for_convergence = 1 X = self.hopfield_binary_dynamics(X, clamped_nodes=clamped_nodes, update=self._update) if ndim == 1: return X.ravel() else: return X
def read(self, file_name): """ Reads a Matlab file. Parameters ---------- file_name : str Name of file to read Returns ------- contents : dict (key: object) contents of file """ if not os.path.exists(file_name): hdlog.warn("File '{}' does not exist!".format(file_name)) return import scipy.io self.contents = scipy.io.loadmat(file_name, struct_as_record=True) return self.contents
def open(self, file_name): """ Opens a Matlab file of HDF format (version >= 7.3). Do not forget to close the file with :meth:`close` after reading its contents. Parameters ---------- file_name : str Name of file to read Returns ------- file : :class:`h5py.File` object Opened Matlab file """ if not os.path.exists(file_name): hdlog.warn("File '{}' does not exist!".format(file_name)) return import h5py self.file = h5py.File(file_name)
def converge_dynamics(self, X, converge = True, max_iter = 10 ** 5, clamped_nodes = None, record_iterations = False, record_energies = False): """ Computes the Hopfield dynamics update to patterns stored in rows of M x N matrix. If `converge` is False then 1 update run through the neurons is performed, otherwise Hopfield dynamics are run on X until convergence or `max_iter` iterations of updates are reached. .. note: Set max_iter = Inf to always force convergence `clamped_nodes` is dictionary of those nodes not to update during the dynamics. 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 converge : bool, optional Flag whether to converge Hopfield dynamics. If False, just one step of dynamics is performed (default True) max_iter : int, optional Maximal number of iterations of dynamics (default 10 ** 5) clamped_nodes : list, optional List of clamped nodes that are left untouched during dynamics update (default None) record_iterations : bool, optional If `True`, function records number of Hopfield dynamics update steps needed for converge of input to Hopfield memory for each input data vector and returns it as second return argument (default False) record_energies : bool, optional If `True`, function records difference in Ising energy for each update step needed for convergence of input to Hopfield memory for each input data vector and returns it as third return argument (default False) Returns ------- patterns : numpy array Converged patterns (memories) of Hopfield dynamics of input argument X iters : numpy array Number of dynamics iterations needed to converge to memory energies : numpy array Ising energy reduction upon convergence to memory """ if clamped_nodes is None: clamped_nodes = {} ndim = X.ndim # so that 1D vectors and arrays of vectors both work as X X = np.atleast_2d(X) out = np.zeros_like(X) niter = 0 if record_iterations: niters = np.zeros((X.shape[0],), dtype = np.int) if record_energies: energies = np.zeros((X.shape[0],), dtype = np.double) old_energies = self.energy(X) if converge: while (niter == 0) or not (X == out).all(): if niter >= max_iter: hdlog.warn("Exceeded maximum number of iterations (%d)" % max_iter) break niter += 1 out = X Xnew = self.hopfield_binary_dynamics( X, clamped_nodes=clamped_nodes, update=self._update) if record_iterations: niters += (Xnew != X).astype(np.int).max(axis = 1) if record_energies: new_energies = self.energy(Xnew) energies += (old_energies - new_energies) old_energies = new_energies X = Xnew self._last_num_iter_for_convergence = niter else: self._last_num_iter_for_convergence = 1 Xnew = self.hopfield_binary_dynamics(X, clamped_nodes=clamped_nodes, update=self._update) if record_iterations: niters += (Xnew != X).astype(np.int).max(axis = 1) if record_energies: new_energies = self.energy(Xnew) energies += (old_energies - new_energies) X = Xnew if ndim == 1: X = X.ravel() if record_iterations and record_energies: return X, niters, energies elif record_iterations: return X, niters elif record_energies: return X, energies else: return X
def converge_dynamics(self, X, converge=True, max_iter=10**5, clamped_nodes=None, record_iterations=False, record_energies=False): """ Computes the Hopfield dynamics update to patterns stored in rows of M x N matrix. If `converge` is False then 1 update run through the neurons is performed, otherwise Hopfield dynamics are run on X until convergence or `max_iter` iterations of updates are reached. .. note: Set max_iter = Inf to always force convergence `clamped_nodes` is dictionary of those nodes not to update during the dynamics. 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 converge : bool, optional Flag whether to converge Hopfield dynamics. If False, just one step of dynamics is performed (default True) max_iter : int, optional Maximal number of iterations of dynamics (default 10 ** 5) clamped_nodes : list, optional List of clamped nodes that are left untouched during dynamics update (default None) record_iterations : bool, optional If `True`, function records number of Hopfield dynamics update steps needed for converge of input to Hopfield memory for each input data vector and returns it as second return argument (default False) record_energies : bool, optional If `True`, function records difference in Ising energy for each update step needed for convergence of input to Hopfield memory for each input data vector and returns it as third return argument (default False) Returns ------- patterns : numpy array Converged patterns (memories) of Hopfield dynamics of input argument X iters : numpy array Number of dynamics iterations needed to converge to memory energies : numpy array Ising energy reduction upon convergence to memory """ if clamped_nodes is None: clamped_nodes = {} ndim = X.ndim # so that 1D vectors and arrays of vectors both work as X X = np.atleast_2d(X) out = np.zeros_like(X) niter = 0 if record_iterations: niters = np.zeros((X.shape[0], ), dtype=np.int) if record_energies: energies = np.zeros((X.shape[0], ), dtype=np.double) old_energies = self.energy(X) if converge: while (niter == 0) or not (X == out).all(): if niter >= max_iter: hdlog.warn("Exceeded maximum number of iterations (%d)" % max_iter) break niter += 1 out = X Xnew = self.hopfield_binary_dynamics( X, clamped_nodes=clamped_nodes, update=self._update) if record_iterations: niters += (Xnew != X).astype(np.int).max(axis=1) if record_energies: new_energies = self.energy(Xnew) energies += (old_energies - new_energies) old_energies = new_energies X = Xnew self._last_num_iter_for_convergence = niter else: self._last_num_iter_for_convergence = 1 Xnew = self.hopfield_binary_dynamics(X, clamped_nodes=clamped_nodes, update=self._update) if record_iterations: niters += (Xnew != X).astype(np.int).max(axis=1) if record_energies: new_energies = self.energy(Xnew) energies += (old_energies - new_energies) X = Xnew if ndim == 1: X = X.ravel() if record_iterations and record_energies: return X, niters, energies elif record_iterations: return X, niters elif record_energies: return X, energies else: return X
def __call__(self, X, converge=True, max_iter=10**5, clamped_nodes=None): """ Usage: network(X) returns the Hopfield dynamics update to patterns stored in rows of M x N matrix X. If `converge` is False then 1 update run through the neurons is performed, otherwise Hopfield dynamics are run on X until convergence or `max_iter` iterations of updates are reached. .. note: Set max_iter = Inf to always force convergence `clamped_nodes` is dictionary of those nodes not to update during the dynamics. 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 converge : bool, optional Flag whether to converge Hopfield dynamics. If False, just one step of dynamics is performed (default True) max_iter : int, optional Maximal number of iterations of dynamics (default 10 ** 5) clamped_nodes : Type, optional List of clamped nodes that are left untouched during dynamics update (default None) Returns ------- patterns : numpy array Converged patterns (memories) of Hopfield dynamics of input argument X """ if clamped_nodes is None: clamped_nodes = {} ndim = X.ndim # so that 1D vectors and arrays of vectors both work as X X = np.atleast_2d(X) out = np.zeros_like(X) niter = 0 if converge: while (niter == 0) or not (X == out).all(): if niter >= max_iter: hdlog.warn("Exceeded maximum number of iterations (%d)" % max_iter) break niter += 1 out = X X = self.hopfield_binary_dynamics(X, clamped_nodes=clamped_nodes, update=self._update) self._last_num_iter_for_convergence = niter else: self._last_num_iter_for_convergence = 1 X = self.hopfield_binary_dynamics(X, clamped_nodes=clamped_nodes, update=self._update) if ndim == 1: return X.ravel() else: return X