def __init__(self, labels, mode=None): """Initializes an object of type '_LabelNormalizer'. """ if mode is None: mode = "id" if mode == "id": # don't do anything. self.normalize = self._id self.revert = self._id return self._mode = mode self._labels = set(labels) self._mapping = {} self._inverse = {} if mode == "dual": if len(self._labels) > 2: msg = "In dual mode only two labels can be given" raise mdp.NodeException(msg) t_label_norm = list(zip(self._labels, [1, -1])) self._set_label_dicts(t_label_norm) elif mode == "multi": # enumerate from zero to len t_label_norm = list(zip(self._labels, count())) self._set_label_dicts(t_label_norm) else: msg = "Remapping mode not known" raise mdp.NodeException(msg)
def init_eigen_vectors(self, init_eigen_vectors=None): """Set initial eigen vectors (principal components). :param init_eigen_vectors: The vectors to set as initial principal components. :type init_eigen_vectors: numpy.ndarray """ """Set initial eigen vectors (principal components)""" self._init_v = init_eigen_vectors if self._input_dim is None: self._input_dim = self._init_v.shape[0] else: assert ( self.input_dim == self._init_v.shape[0]), mdp.NodeException( 'Dimension mismatch. init_eigen_vectors shape[0] must be' '%d, given %d' % (self.input_dim, self._init_v.shape[0])) if self._output_dim is None: self._output_dim = self._init_v.shape[1] else: assert ( self.output_dim == self._init_v.shape[1]), mdp.NodeException( 'Dimension mismatch. init_eigen_vectors shape[1] must be' '%d, given %d' % (self.output_dim, self._init_v.shape[1])) if self.v is None: self._v = self._init_v.copy() self.d = mdp.numx.sum( self._v**2, axis=0)**0.5 # identical with np.linalg.norm(self._v, axis=0) # Using this for backward numpy (versions below 1.8) compatibility. self.v = old_div(self._v, self.d)
def init_eigen_vectors(self, init_eigen_vectors=None): """Set initial eigen vectors (minor components). :param init_eigen_vectors: The inital eigenvectors which are set before the online routine starts. :type init_eigen_vectors: numpy.ndarray """ self._init_v = init_eigen_vectors if self._input_dim is None: self._input_dim = self._init_v.shape[0] else: assert ( self.input_dim == self._init_v.shape[0]), mdp.NodeException( 'Dimension mismatch. init_eigen_vectors ' 'shape[0] must be' '%d, given %d' % (self.input_dim, self._init_v.shape[0])) if self._output_dim is None: self._output_dim = self._init_v.shape[1] else: assert ( self.output_dim == self._init_v.shape[1]), mdp.NodeException( 'Dimension mismatch. init_eigen_vectors' ' shape[1] must be' '%d, given %d' % (self.output_dim, self._init_v.shape[1])) if self.v is None: self.v = self._init_v.copy() self.d = mdp.numx.sum( self.v**2, axis=0)**0.5 # identical with np.linalg.norm(self.v, axis=0)
def _xy_to_layersxy(self, xy, xyname): """ if scalar: convert scalar to a list of 2tuple for all layers if tuple: check if 2tuple and convert to a list of 2tuples for all layers if list: check if the list has n_layers elements and each element is a 2tuple """ if mdp.numx.isscalar(xy) or (xy is None): xy = [(xy, xy)] * self.n_layers elif isinstance(xy, tuple): xy = [xy] * self.n_layers if not isinstance(xy, list): err_str = ("'%s' must be a list of 2-tuples" ", and not %s" % (xyname, type(xy))) raise mdp.NodeException(err_str) if not (len(xy) == self.n_layers): raise mdp.NodeException("%d '%s' elements needed, " "%d given." % (self.n_layers, xyname, len(xy))) # check that all elements are 2-tuples for i, tup in enumerate(xy): if not (len(tup) == 2): err = ("Element number %d in the '%s'" " list is not a 2tuple." % (i, xyname)) raise mdp.NodeException(err) return xy
def __init__(self, action_lims, dstr_fn=None, input_dim=None, dtype=None, numx_rng=None): """ action_lims - Lower and upper bounds for all action dimensions. Eg. [(min1, min2, ...,), (max1, max2, ...,)] dstr_fn - A funtion that returns a real number given the min bound and max bound. Eg. dstr_fn(action_lims[0], action_lims[1], shape) -> array, where mini <= array_elem_i < maxi. """ super(ContinuousExplorerNode, self).__init__(input_dim=input_dim, output_dim=None, dtype=dtype, numx_rng=numx_rng) if len(action_lims) != 2: raise mdp.NodeException( "'action_lims' has %d elements given, required 2 " "[(lower1, lower2, ...,), (upper1, upper2, ...,)]" % (len(action_lims))) if mdp.numx.isscalar(action_lims[0]): action_lims = [tuple((lim, )) for lim in action_lims] if len(action_lims[0]) != len(action_lims[1]): raise mdp.NodeException( "Length of lower_bounds ('action_lims[0]=%d') does not match the length " "of the upper_bounds ('action_lims[1]=%d)." % (len(action_lims[0]), len(action_lims[1]))) self.action_lims = mdp.numx.asarray(action_lims) self._dstr_fn = dstr_fn self._action = None self._output_dim = len(action_lims[0])
def _check_output(self, y): # check output rank if not y.ndim == 2: error_str = "y has rank %d, should be 2" % (y.ndim) raise mdp.NodeException(error_str) if y.shape[1] == 0 or y.shape[1] > self.output_dim: error_str = ("y has dimension %d" ", should be 0<y<=%d" % (y.shape[1], self.output_dim)) raise mdp.NodeException(error_str)
def __init__(self, input_dim=None, output_dim=None, dtype='int', connectivity=2, expected_p=0.5, input_connectivity=None, n_runs_after_perturb=1, should_perturb=True, heterogenous=False, input_connections=None, connections=None, rules=None): if input_connectivity > output_dim: raise mdp.NodeException( 'Cannot connect more input than available nodes') super(RBNNode, self).__init__(input_dim=input_dim, output_dim=output_dim, dtype=dtype) self.connectivity = connectivity self.n_nodes = output_dim self.expected_p = expected_p self.n_runs_after_perturb = n_runs_after_perturb self.should_perturb = should_perturb self.heterogenous = heterogenous # Initialize state and connections self.state = create_empty_state(self.n_nodes) if input_connections is not None: self.input_connectivity = len(input_connections) self.input_connections = input_connections elif input_connectivity is not None: self.input_connectivity = input_connectivity self.input_connections =\ numpy.random.choice(range(self.n_nodes), self.input_connectivity, replace=False) else: raise mdp.NodeException( 'Gotta have either connections of connectivity') if connections is not None: self.connections = connections else: self.connections = generate_connections(self.n_nodes, self.connectivity, self.heterogenous) if rules is not None: self.rules = rules else: self.rules = generate_rules(self.n_nodes, self.connectivity, self.expected_p)
def _stop_training(self, debug=False): """Stop the training phase. Keyword arguments: debug=True if stop_training fails because of singular cov matrices, the singular matrices itselves are stored in self.cov_mtx and self.dcov_mtx to be examined. """ # request the covariance matrix and clean up self.cov_mtx, avg, self.tlen = self._cov_mtx.fix() del self._cov_mtx # this is a bit counterintuitive, as it reshapes the average vector to # be a matrix. in this way, however, we spare the reshape # operation every time that 'execute' is called. self.avg = avg.reshape(1, avg.shape[0]) # range for the eigenvalues rng = self._adjust_output_dim() # if we have more variables then observations we are bound to fail here # suggest to use the NIPALSNode instead. if debug and self.tlen < self.input_dim: wrn = ('The number of observations (%d) ' 'is larger than the number of input variables ' '(%d). You may want to use ' 'the NIPALSNode instead.' % (self.tlen, self.input_dim)) _warnings.warn(wrn, mdp.MDPWarning) # total variance can be computed at this point: # note that vartot == d.sum() vartot = numx.diag(self.cov_mtx).sum() ## compute and sort the eigenvalues # compute the eigenvectors of the covariance matrix (inplace) # (eigenvalues sorted in ascending order) try: d, v = self._symeig(self.cov_mtx, range=rng, overwrite=(not debug)) # if reduce=False and svd=False. we should check for # negative eigenvalues and fail if not (self.reduce or self.svd or (self.desired_variance is not None)): if d.min() < 0: raise mdp.NodeException( "Got negative eigenvalues: %s.\n" "You may either set output_dim to be smaller, " "or set reduce=True and/or svd=True" % str(d)) except SymeigException, exception: err = str(exception) + ("\nCovariance matrix may be singular." "Try setting svd=True.") raise mdp.NodeException(err)
def set_x_range(self, x_range): """Sets the range for x axis.""" if x_range is None: return if (not isinstance(x_range, tuple)) and (not isinstance(x_range, list)): raise mdp.NodeException( "x_range must be a tuple or a list and not %s." % str(type(x_range))) if len(x_range) != 2: raise mdp.NodeException( "x_range must contain 2 elements, given %s." % len(x_range)) self._x_range = x_range
def set_train_features(self, features, labels): if issubclass(self._class, sgClassifier.LinearMachine): self._instance.set_features(features) elif issubclass(self._class, sgClassifier.KernelMachine): try: self.kernel.init(features, features) except AttributeError: msg = "You must assign a kernel before training." raise mdp.NodeException(msg) #self.svm.set_kernel(self.kernel) else: msg = "Sorry, SHOGUN classifiers of this type are not yet implemented" raise mdp.NodeException(msg) self._instance.set_labels(labels)
def _set_kernel(self, kernel): """Set the kernel in the current classifier instance""" try: self._instance.set_kernel(kernel) except AttributeError: msg = "Error setting kernel. The classifier might not support kernels." raise mdp.NodeException(msg)
def _get_kernel(self): """Retrieve the currently set kernel from the classifier instance.""" try: return self._instance.get_kernel() except AttributeError: msg = "Error retrieving kernel. The classifier might not support kernels." raise mdp.NodeException(msg)
def __init__(self, nodes, dtype=None): """Setup the layer with the given list of nodes. The input dimensions for the nodes must all be equal, the output dimensions can differ (but must be set as well for simplicity reasons). Keyword arguments: nodes -- List of the nodes to be used. """ self.nodes = nodes # check node properties and get the dtype dtype = self._check_props(dtype) # check that the input dimensions are all the same input_dim = self.nodes[0].input_dim for node in self.nodes: if not node.input_dim == input_dim: err = "The nodes have different input dimensions." raise mdp.NodeException(err) output_dim = self._get_output_dim_from_nodes() # set layer state nodes_is_training = [node.is_training() for node in nodes] if mdp.numx.any(nodes_is_training): self._is_trainable = True self._training = True else: self._is_trainable = False self._training = False # intentionally use MRO above Layer, not SameInputLayer super(Layer, self).__init__(input_dim=input_dim, output_dim=output_dim, dtype=dtype)
def __init__(self, use_buffer=False, x_range=None, y_range=None, interval=1, timeout=0, window_title=None, window_size_xy=(640, 480), input_dim=None, output_dim=None, dtype=None): """ user_buffer: If the data arrives sample by sample (like in an OnlineFlow), use_buffer can be set to store samples in a circular buffer. At each time-step the buffer contents are displayed. x_range: Denotes the range of x-axis values to be shown. When the use_buffer is set, this also denotes the size of the buffer. y_range: y-axis range interval: Number of execute calls after which the plots are updated. 1 - Plots are updated after each execute call 10 - Plots are updated after every 10th execute call -1 - Automatically optimize the interval such that the plot updates do not slow the flow's execution time. timeout: Sets a minimum of timeout msecs for each plot update. Default is 0. window_title: Window title window_size: XY size tuple of the window """ super(PG2DNode, self).__init__(input_dim, output_dim, dtype) self.use_buffer = use_buffer self._x_range = x_range self._y_range = y_range self._interval = 1 if interval == -1 else interval self._given_interval = interval self._timeout = timeout self._window_title = window_title self._window_size_xy = window_size_xy if use_buffer: if x_range is None: raise mdp.NodeException("Provide x_range to init buffer size.") self._buffer = mdp.nodes.NumxBufferNode(buffer_size=x_range[1]) self._flow_time = 0 self._tlen = 0 # child process that is set upon execution self._viewer = None # queue to communicate data between the main and the child process self.new_data = Queue(1) # all these variables are set in the child process self._win = None # pyqtgraph window self._layout = None # pyqtgraph plots layout self._plot_items = None # pyqtgraph plot items self._plot_objects = None # pyqtgraph plot objects (graphics objects)
def _init_random_sampling_net(self): if not hasattr(self, '_default_net'): raise mdp.NodeException("'_init_random_sampling_net' must be called after '_init_default_net'") if self.field_channels_xy[0] == (-1, -1): sb = mdp.hinet.RandomChannelSwitchboard(self.in_channels_xy, self.in_channels_xy, in_channel_dim=self.in_channel_dim, out_channels=1, field_dstr=self.field_dstr) else: sb = mdp.hinet.RandomChannelSwitchboard(self.in_channels_xy, self.field_channels_xy[0], in_channel_dim=self.in_channel_dim, out_channels=self.n_training_fields[0], field_dstr=self.field_dstr) cl = mdp.hinet.CloneLayer(self._default_net[0].flow[1].node, n_nodes=sb.output_channels) node = mdp.hinet.FlowNode(mdp.Flow([sb, cl])) layers = [node] for i in xrange(1, self.n_layers): if self.field_channels_xy[i] == (-1, -1): sb = mdp.hinet.RandomChannelSwitchboard(self._default_net[i - 1].flow[0].out_channels_xy, self._default_net[i - 1].flow[0].out_channels_xy, in_channel_dim=self._default_net[i - 1].flow[1].node.output_dim, out_channels=1, field_dstr=self.field_dstr) else: sb = mdp.hinet.RandomChannelSwitchboard(self._default_net[i - 1].flow[0].out_channels_xy, self.field_channels_xy[i], in_channel_dim=self._default_net[i - 1].flow[1].node.output_dim, out_channels=self.n_training_fields[i], field_dstr=self.field_dstr) cl = mdp.hinet.CloneLayer(self._default_net[i].flow[1].node, n_nodes=sb.output_channels) node = mdp.hinet.FlowNode(mdp.Flow([sb, cl])) layers.append(node) return layers
def _inverse(self, y, n=None): """Project data from the output to the input space using the first 'n' components. If 'n' is not set, use all available components. :param y: Data to be projected to the input space. :type y: numpy.ndarray :param n: Number of first principle components. :type n: int :return: The projected data :rtype: numpy.ndarray """ if n is None: n = y.shape[1] if n > self.output_dim: error_str = ("y has dimension %d," " should be at most %d" % (n, self.output_dim)) raise mdp.NodeException(error_str) v = self.get_recmatrix() if n is not None: return mult(y, v[:n, :]) + self.avg return mult(y, v) + self.avg
def _inverse(self, y, n=None): """Project 'y' to the input space using the first 'n' components. :param y: Vectors from the output space. :type y: numpy.ndarray :param n: The number of components to use for projection to the input space. If 'n' is not set, use all available components. :type n: int :return: The projected vectors. :rtype: numpy.ndarray :raises mdp.NodeException: If the valid dimension is exceeded. """ if n is None: n = y.shape[1] if n > self.output_dim: error_str = ("y has dimension %d," " should be at most %d" % (n, self.output_dim)) raise mdp.NodeException(error_str) v = self.get_recmatrix() if n is not None: return mult(y, v[:n, :]) return mult(y, v)
def _x_to_layersx(self, x, xname): """ if scalar: convert scalar to a list of scalars for all layers if tuple: convert tuple to a list of tuples for all layers if list: check if the list has n_layers elements. """ if mdp.numx.isscalar(x) or isinstance(x, tuple) or (x is None): x = [x] * self.n_layers if not isinstance(x, list): err_str = ("'%s' must be a list" ", and not %s" % (xname, type(x))) raise mdp.NodeException(err_str) if not (len(x) == self.n_layers): raise mdp.NodeException("%d '%s' needed, " "%d given." % (self.n_layers, xname, len(x))) return x
def _stop_training(self): """ Trains and creates the model. """ # reset variables self.problems = [] self.models = [] self.labels = [] self._dosim = numpy.zeros(self._output_dim, dtype='int') # finally generate the models for n in range(self._output_dim): # get labels (min,max) self.labels.append((self.Y[:, n].max(), self.Y[:, n].min())) if self.labels[n][0] == self.labels[n][1]: # apport simulation if there is only one label self._dosim[n] = 1 self.problems.append(None) self.models.append(None) continue # construct problems self.problems.append(svm.svm_problem(self.Y[:, n], self.X)) # generate models self.models.append(svm.svm_model(self.problems[n], self.parameters)) # check if there are only 2 classes if self.models[n].get_nr_class() > 2: raise mdp.NodeException( "Only binary classification possible with libsvm for now !" ) # reset data for training self.reset_model()
def _set_label_dicts(self, t_label_norm): self._mapping = dict(t_label_norm) self._inverse = dict((norm, label) for label, norm in t_label_norm) # check that neither original nor normalised labels have occured more than once if not (len(self._mapping) == len(t_label_norm) == len(self._inverse)): msg = "Error in label normalisation." raise mdp.NodeException(msg)
def _label(self, x): if isinstance(x, (list, tuple, numx.ndarray)): y = [0] * len(x) p_labs, p_acc, p_vals = libsvmutil.svm_predict( y, x.tolist(), self.model) return numx.array(p_labs) else: msg = "Data must be a sequence of vectors" raise mdp.NodeException(msg)
def _execute(self, x): phi_ = self._split_x(x)[1] if self.output_mode == 'action': return self.get_action(phi_) elif self.output_mode == 'value': return self.get_value(phi_) else: raise mdp.NodeException( "Unrecognized 'output_mode'. Accepted values: 'action' and " "'value', given %s." % str(self.output_mode))
def _execute(self, x): phi_ = self._split_x(x)[1] if self.output_mode == 'action': return self.get_action(phi_) elif self.output_mode == 'value': return self.get_value(phi_) # qvals = mdp.numx.asarray([self.get_qvalue(phi_[i]) for i in xrange(len(phi_))]) # return qvals else: raise mdp.NodeException( "Unrecognized 'output_mode'. Accepted values: 'action' and " "'value', given %s." % str(self.output_mode))
def _set_kernel(self, kernel): """Set the kernel in the current classifier instance. :param kernel: The kernel to set. :raises mdp.NodeException: If the kernel could not be set due to an AttributeError. """ try: self._instance.set_kernel(kernel) except AttributeError: msg = "Error setting kernel. The classifier might not support kernels." raise mdp.NodeException(msg)
def _pre_execution_checks(self, x): """Make sure that output_dim is set and then perform nromal checks.""" if self.output_dim is None: # first make sure that the output_dim is set for all nodes for node in self.nodes: node._pre_execution_checks(x) self.output_dim = self._get_output_dim_from_nodes() if self.output_dim is None: err = "output_dim must be set at this point for all nodes" raise mdp.NodeException(err) # intentionally use MRO above Layer, not SameInputLayer super(Layer, self)._pre_execution_checks(x)
def dstr_fn(self, fn): if fn is None: return else: if not callable(fn): raise mdp.NodeException( "Given dstr_fn is not callable. It must of a function that returns an action array." ) # check if the samples returned are within the specified bounds. a = fn(self.action_lims[0], self.action_lims[1], (10, self.output_dim)) for i in xrange(self.output_dim): if (a[:, i].min() < self.action_lims[0][i]) or ( a[:, i].min() >= self.action_lims[1][i]): raise mdp.NodeException( "Out of bounds error. Given dstr_fn returns an action %d outside a specified" "bounds (%d, %d) " % (a[:, i].min(), self.action_lims[0][i], self.action_lims[1][i])) # if no exceptions raised self._dstr_fn = fn
def _init_RBF(self, centers, sizes): # initialize the centers of the RBFs centers = numx.array(centers, self.dtype) # define input/output dim self.set_input_dim(centers.shape[1]) self.set_output_dim(centers.shape[0]) # multiply sizes if necessary sizes = numx.array(sizes, self.dtype) if sizes.ndim == 0 or sizes.ndim == 2: sizes = numx.array([sizes] * self._output_dim) else: # check number of sizes correct if sizes.shape[0] != self._output_dim: msg = "There must be as many RBF sizes as centers" raise mdp.NodeException(msg) if numx.isscalar(sizes[0]): # isotropic RBFs self._isotropic = True else: # anisotropic RBFs self._isotropic = False # check size if (sizes.shape[1] != self._input_dim or sizes.shape[2] != self._input_dim): msg = ("Dimensionality of size matrices should be the same " + "as input dimensionality (%d != %d)" % (sizes.shape[1], self._input_dim)) raise mdp.NodeException(msg) # compute inverse covariance matrix for i in range(sizes.shape[0]): sizes[i, :, :] = mdp.utils.inv(sizes[i, :, :]) self._centers = centers self._sizes = sizes
def init_eigen_vectors(self, init_eigen_vectors=None): """Set initial eigen vectors (minor components)""" self._init_v = init_eigen_vectors if self._input_dim is None: self._input_dim = self._init_v.shape[0] else: assert (self.input_dim == self._init_v.shape[0]), mdp.NodeException( 'Dimension mismatch. init_eigen_vectors ' 'shape[0] must be' '%d, given %d' % (self.input_dim, self._init_v.shape[0])) if self._output_dim is None: self._output_dim = self._init_v.shape[1] else: assert (self.output_dim == self._init_v.shape[1]), mdp.NodeException( 'Dimension mismatch. init_eigen_vectors' ' shape[1] must be' '%d, given %d' % (self.output_dim, self._init_v.shape[1])) if self.v is None: self.v = self._init_v.copy() self.d = mdp.numx.sum(self.v ** 2, axis=0) ** 0.5 # identical with np.linalg.norm(self.v, axis=0)
def _inverse(self, y, n=None): """Project 'y' to the input space using the first 'n' components. If 'n' is not set, use all available components.""" if n is None: n = y.shape[1] if n > self.output_dim: error_str = ("y has dimension %d," " should be at most %d" % (n, self.output_dim)) raise mdp.NodeException(error_str) v = self.get_recmatrix() if n is not None: return mult(y, v[:n, :]) + self.avg return mult(y, v) + self.avg
def __init__(self, input_dim=None, output_dim=None, dtype='float64'): """ Initializes and constructs a random reservoir. input_dim -- nr. of features (f1,f2,...) * individual classifiers coded: (f1,f2,f3,...,f1,f2,f3,...) output_dim -- nr. of features (averaged over all classifiers) """ super(VoteAverageNode, self).__init__(input_dim, output_dim, dtype) # calculate number of individual voters if input_dim % output_dim != 0: raise mdp.NodeException( "input_dim must be a multiple of output_dim !") self.voters = input_dim / output_dim