def remove_hidden_node(self, n): if self.w_res_type in ['tetragonal', 'hexagonal', 'triangular']: nodes = list(self.G.nodes) self.G.remove_node(nodes[n]) A = nx.to_numpy_matrix(self.G) self.hidden_nodes = len(A) w_res = torch.FloatTensor(A) cur_sr = _spectral_radius(w_res) self.org_spectral_radius = cur_sr if cur_sr != 0: w_res *= self.spectral_radius / cur_sr self.w_in = torch.cat([self.w_in[0:n], self.w_in[n + 1:]]) self.w_res = w_res self.w_out = torch.cat([self.w_out[0:n], self.w_out[n + 1:]]) elif self.w_res_type is None: self.w_in = np.delete(self.w_in, n) self.w_out = np.delete(self.w_out, n) self.w_res = np.delete(self.w_res, n, axis=1) self.w_res = np.delete(self.w_res, n, axis=0) self.hidden_nodes = len(self.w_in) else: raise ESNException( f'Cannot remove hidden node for w_res_type={self.w_res_type}')
def make_edge_undirected(self, edge): if self.w_res_type in ['tetragonal', 'hexagonal', 'triangular']: u, v = edge[0], edge[1] self.G.add_edge(v, u) A = nx.to_numpy_matrix(self.G) self.hidden_nodes = len(A) self.w_res = torch.FloatTensor(A) cur_sr = _spectral_radius(self.w_res) self.org_spectral_radius = cur_sr if cur_sr != 0: self.w_res *= self.spectral_radius / cur_sr else: raise ESNException( f'Cannot remove edge for w_res_type={self.w_res_type}')
def set_G(self, G): if self.w_res_type in ['tetragonal', 'hexagonal', 'triangular']: A = nx.to_numpy_matrix(G) self.hidden_nodes = len(A) self.G = G self.w_res = torch.FloatTensor(A) cur_sr = _spectral_radius(self.w_res) if cur_sr != 0: self.w_res *= self.spectral_radius / cur_sr else: # print('[WARN]: Original spectral radius was 0') pass self.w_in = torch.ones(self.hidden_nodes) self.w_in *= self.input_scaling self.w_out = torch.zeros(self.hidden_nodes) else: raise ESNException( f'Cannot set G for w_res_type={self.w_res_type}')
def __init__(self, hidden_nodes=200, spectral_radius=0.9, washout=200, w_in_density=1.0, w_res_density=1.0, input_scaling=1.0, w_in_distrib=Distribution.uniform, w_res_distrib=Distribution.uniform, readout='rr', w_ridge=0.00, w_res_type=None, grow_neigh=0, **kwargs): super().__init__() self.hidden_nodes = hidden_nodes self.spectral_radius = spectral_radius self.f = torch.tanh self.w_in_density = w_in_density self.w_res_density = w_res_density self.washout = washout self.input_scaling = input_scaling self.w_in_distrib = w_in_distrib self.w_res_distrib = w_res_distrib self.readout = readout self.w_ridge = w_ridge self.rr = Ridge(alpha=w_ridge, solver='svd') self.w_res_type = w_res_type self.grow_neigh = grow_neigh if self.w_res_type == 'waxman': G = matrix.waxman(n=self.hidden_nodes, alpha=1.0, beta=1.0, connectivity='global', **kwargs) self.G = G A = nx.to_numpy_matrix(G) w_res = torch.FloatTensor(A) cur_sr = _spectral_radius(w_res) self.org_w_res = w_res.clone() self.org_spectral_radius = cur_sr if self.spectral_radius is None: self.spectral_radius = self.org_spectral_radius if cur_sr != 0: w_res *= self.spectral_radius / cur_sr elif self.w_res_type in [ 'tetragonal', 'hexagonal', 'triangular', 'rectangular' ]: sqrt = np.sqrt(self.hidden_nodes) if sqrt - int(sqrt) != 0: raise ValueError( "Non square number of nodes given for lattice") self.sign_frac = None if 'sign_frac' in kwargs: self.sign_frac = kwargs['sign_frac'] del kwargs['sign_frac'] self.dir_frac = None if 'dir_frac' in kwargs: self.dir_frac = kwargs['dir_frac'] del kwargs['dir_frac'] if self.w_res_type == 'tetragonal': G = matrix.tetragonal([int(sqrt), int(sqrt)], **kwargs) elif self.w_res_type == 'hexagonal': G = matrix.hexagonal( int(sqrt) // 2, int(np.ceil(sqrt / 2) * 2), **kwargs) elif self.w_res_type == 'triangular': G = matrix.triangular(int(sqrt) + 3, int(sqrt) + 3, **kwargs) elif self.w_res_type == 'rectangular': G = matrix.rectangular(int(sqrt), int(sqrt), **kwargs) self.G = G if self.grow_neigh > 0: matrix.grow_neighborhoods(self.G, l=grow_neigh, **kwargs) if self.sign_frac is not None: matrix.make_weights_negative(self.G, self.sign_frac) if self.dir_frac is not None: self.G = matrix.make_graph_directed(self.G, self.dir_frac) A = nx.to_numpy_matrix(self.G) self.hidden_nodes = len(A) w_res = torch.FloatTensor(A) cur_sr = _spectral_radius(w_res) self.org_spectral_radius = cur_sr if cur_sr != 0: w_res *= self.spectral_radius / cur_sr else: if self.w_res_distrib == Distribution.gaussian: w_res = torch.empty(self.hidden_nodes, hidden_nodes).normal_(mean=0.0, std=1.0) elif self.w_res_distrib == Distribution.uniform: w_res = torch.rand(self.hidden_nodes, self.hidden_nodes) - 0.5 elif self.w_res_distrib == Distribution.fixed: w_res = torch.ones(self.hidden_nodes, self.hidden_nodes) w_res[torch.rand(self.hidden_nodes, self.hidden_nodes) > self.w_res_density] = 0.0 if _spectral_radius(w_res) != 0: w_res *= self.spectral_radius / _spectral_radius(w_res) if self.w_in_distrib == Distribution.gaussian: w_in = torch.empty(self.hidden_nodes).normal_(mean=0.0, std=1.0) elif self.w_in_distrib == Distribution.uniform: w_in = torch.rand(self.hidden_nodes) - 0.5 elif self.w_in_distrib == Distribution.fixed: w_in = torch.ones(self.hidden_nodes) w_in[torch.rand(self.hidden_nodes) > self.w_in_density] = 0.0 w_in *= self.input_scaling w_out = torch.zeros(self.hidden_nodes) self.register_buffer('w_res', w_res) self.register_buffer('w_in', w_in) self.register_buffer('w_out', w_out)
def scale_spectral_radius(self, new_sr): cur_sr = _spectral_radius(self.w_res) if cur_sr != 0: self.w_res *= new_sr / cur_sr
def __init__(self, hidden_nodes=200, spectral_radius=0.9, washout=200, w_in_density=1.0, w_out_density=1.0, w_res_density=1.0, input_scaling=1.0, w_in_distrib=Distribution.uniform, w_res_distrib=Distribution.uniform, awgn_train_std=0.0, awgn_test_std=0.0, adc_quantization=None, readout='pinv', w_ridge=0.00): super(ESN, self).__init__() self.hidden_nodes = hidden_nodes self.spectral_radius = spectral_radius self.f = torch.tanh self.w_in_density = w_in_density self.w_out_density = w_out_density self.w_res_density = w_res_density self.washout = washout self.input_scaling = input_scaling self.w_in_distrib = w_in_distrib self.w_res_distrib = w_res_distrib self.awgn_train_std = awgn_train_std self.awgn_test_std = awgn_test_std self.adc_quantization = adc_quantization self.readout = readout self.rr = Ridge(alpha=w_ridge) # We can't just mask w_out with the density, as the masked out nodes # must be hidden during training as well. mask_size = int(self.hidden_nodes * self.w_out_density) self.w_out_mask = np.random.choice(self.hidden_nodes, mask_size, replace=False) self.w_out_mask = torch.from_numpy(self.w_out_mask) self.output_dim = self.w_out_mask.shape[0] if self.w_res_distrib == Distribution.gaussian: w_res = torch.empty(self.hidden_nodes, hidden_nodes).normal_(mean=0.0, std=1.0) elif self.w_res_distrib == Distribution.uniform: w_res = torch.rand(self.hidden_nodes, self.hidden_nodes) - 0.5 elif self.w_res_distrib == Distribution.fixed: w_res = torch.ones(self.hidden_nodes, self.hidden_nodes) w_res[torch.rand(self.hidden_nodes, self.hidden_nodes) > self.w_res_density] = 0.0 w_res *= self.spectral_radius / _spectral_radius(w_res) if self.w_in_distrib == Distribution.gaussian: w_in = torch.empty(self.hidden_nodes).normal_(mean=0.0, std=1.0) elif self.w_in_distrib == Distribution.uniform: w_in = torch.rand(self.hidden_nodes) - 0.5 elif self.w_in_distrib == Distribution.fixed: w_in = torch.ones(self.hidden_nodes) w_in[torch.rand(self.hidden_nodes) > self.w_in_density] = 0.0 w_in *= self.input_scaling w_out = torch.ones(self.hidden_nodes) self.register_buffer('w_res', w_res) self.register_buffer('w_in', w_in) self.register_buffer('w_out', w_out)