Esempio n. 1
0
    def update(self, inputData, outputData=None, x=None):
        if x is None:
            x = self._x

        if self._WFeedback is None:
            #reshape the data
            u = inputData.reshape(self.n_input, 1)

            #update the states
            transmission = self.calculateLinearNetworkTransmissions(u, x)
            x *= (1.0-self._leakingRate)
            x += self._leakingRate * self._activation(transmission + (B.rand()-0.5)*self._noiseLevel)
        
            return u, x

        else:
            #the input is allowed to be "empty" (size=0)
            if self.n_input != 0:
                #reshape the data
                u = inputData.reshape(self.n_input, 1)
                outputData = outputData.reshape(self.n_output, 1)

                #update the states
                transmission = self.calculateLinearNetworkTransmissions(u, x)
                x *= (1.0-self._leakingRate)
                x += self._leakingRate*self._activation(transmission +
                     B.dot(self._WFeedback, B.vstack((B.array(self._outputBias), outputData))) + (B.rand()-0.5)*self._noiseLevel)

                return u, x
            else:
                #reshape the data
                outputData = outputData.reshape(self.n_output, 1)
                #update the states
                transmission = B.dot(self._W, x)
                x *= (1.0-self._leakingRate)
                x += self._leakingRate*self._activation(transmission + B.dot(self._WFeedback, B.vstack((B.array(self._outputBias), outputData))) +
                     (B.rand()-0.5)*self._noiseLevel)

                return np.empty((0, 1)), x
Esempio n. 2
0
    def create_random_rotation_matrix(self):
        h = B.randint(low=0, high=self.n_reservoir)
        k = B.randint(low=0, high=self.n_reservoir)

        phi = B.rand(1) * 2 * np.pi

        Q = B.identity(self.n_reservoir)
        Q[h, h] = B.cos(phi)
        Q[k, k] = B.cos(phi)

        Q[h, k] = -B.sin(phi)
        Q[k, h] = B.sin(phi)

        return Q
Esempio n. 3
0
    def _createInputMatrix(self):
        #random weight matrix for the input from -0.5 to 0.5
        self._WInput = B.rand(self.n_reservoir, 1 + self.n_input)-0.5

        #scale the inputDensity to prevent saturated reservoir nodes
        if (self.inputDensity != 1.0):
            #make the input matrix as dense as requested
            input_topology = (np.ones_like(self._WInput) == 1.0)
            nb_non_zero_input = int(self.inputDensity * self.n_input)
            for n in range(self.n_reservoir):
                input_topology[n][rnd.permutation(np.arange(1+self.n_input))[:nb_non_zero_input]] = False

            self._WInput[input_topology] = 0.0

        self._WInput = self._WInput * self._expandedInputScaling
Esempio n. 4
0
    def _createReservoir(self, weightGeneration, feedback=False, verbose=False):
        #naive generation of the matrix W by using random weights
        if weightGeneration == 'naive':
            #random weight matrix from -0.5 to 0.5
            self._W = B.array(rnd.rand(self.n_reservoir, self.n_reservoir) - 0.5)

            #set sparseness% to zero
            mask = rnd.rand(self.n_reservoir, self.n_reservoir) > self._reservoirDensity
            self._W[mask] = 0.0

            _W_eigenvalues = B.abs(B.eigenval(self._W)[0])
            self._W *= self._spectralRadius / B.max(_W_eigenvalues)

        #generation using the SORM technique (see http://ftp.math.uni-rostock.de/pub/preprint/2012/pre12_01.pdf)
        elif weightGeneration == "SORM":
            self._W = B.identity(self.n_reservoir)

            number_nonzero_elements = self._reservoirDensity * self.n_reservoir * self.n_reservoir
            i = 0

            while np.count_nonzero(self._W) < number_nonzero_elements:
                i += 1
                Q = self.create_random_rotation_matrix()
                self._W = Q.dot(self._W)
            
            self._W *= self._spectralRadius

        #generation using the proposed method of Yildiz
        elif weightGeneration == 'advanced':
            #two create W we must follow some steps:
            #at first, create a W = |W|
            #make it sparse
            #then scale its spectral radius to rho(W) = 1 (according to Yildiz with x(n+1) = (1-a)*x(n)+a*f(...))
            #then change randomly the signs of the matrix

            #random weight matrix from 0 to 0.5

            self._W = B.array(rnd.rand(self.n_reservoir, self.n_reservoir) / 2)

            #set sparseness% to zero
            mask = B.rand(self.n_reservoir, self.n_reservoir) > self._reservoirDensity
            self._W[mask] = 0.0

            from scipy.sparse.linalg.eigen.arpack.arpack import ArpackNoConvergence
            #just calculate the largest EV - hopefully this is the right code to do so...
            try:
                #this is just a good approximation, so this code might fail
                _W_eigenvalue = B.max(np.abs(sp.sparse.linalg.eigs(self._W, k=1)[0]))
            except ArpackNoConvergence:
                #this is the safe fall back method to calculate the EV
                _W_eigenvalue = B.max(B.abs(sp.linalg.eigvals(self._W)))
            #_W_eigenvalue = B.max(B.abs(np.linalg.eig(self._W)[0]))

            self._W *= self._spectralRadius / _W_eigenvalue

            if verbose:
                M = self._leakingRate*self._W + (1 - self._leakingRate)*np.identity(n=self._W.shape[0])
                M_eigenvalue = B.max(B.abs(B.eigenval(M)[0]))#np.max(np.abs(sp.sparse.linalg.eigs(M, k=1)[0]))
                print("eff. spectral radius: {0}".format(M_eigenvalue))

            #change random signs
            random_signs = B.power(-1, rnd.random_integers(self.n_reservoir, self.n_reservoir))

            self._W = B.multiply(self._W, random_signs)
        elif weightGeneration == 'custom':
            pass
        else:
            raise ValueError("The weightGeneration property must be one of the following values: naive, advanced, SORM, custom")

        #check of the user is really using one of the internal methods, or wants to create W by his own
        if (weightGeneration != 'custom'):
            self._createInputMatrix()

        #create the optional feedback matrix
        if feedback:
            self._WFeedback = B.rand(self.n_reservoir, 1 + self.n_output) - 0.5
            self._WFeedback *= self._feedbackScaling
        else:
            self._WFeedback = None
Esempio n. 5
0
    def _createReservoir(self,
                         weightGeneration,
                         feedback=False,
                         verbose=False):
        # naive generation of the matrix W by using random weights
        if weightGeneration == "naive":
            # random weight matrix from -0.5 to 0.5
            self._W = B.array(B.rand(self.n_reservoir, self.n_reservoir) - 0.5)

            # set sparseness% to zero
            mask = B.rand(self.n_reservoir,
                          self.n_reservoir) > self._reservoirDensity
            self._W[mask] = 0.0

            _W_eigenvalues = B.abs(B.eigenval(self._W)[0])
            self._W *= self._spectralRadius / B.max(_W_eigenvalues)

        # generation using the SORM technique (see http://ftp.math.uni-rostock.de/pub/preprint/2012/pre12_01.pdf)
        elif weightGeneration == "SORM":
            self._W = B.identity(self.n_reservoir)

            number_nonzero_elements = (self._reservoirDensity *
                                       self.n_reservoir * self.n_reservoir)
            i = 0

            while B.count_nonzero(self._W) < number_nonzero_elements:
                i += 1
                Q = self.create_random_rotation_matrix()
                self._W = Q.dot(self._W)

            self._W *= self._spectralRadius

        # generation using the proposed method of Yildiz
        elif weightGeneration == "advanced":
            # two create W we must follow some steps:
            # at first, create a W = |W|
            # make it sparse
            # then scale its spectral radius to rho(W) = 1 (according to Yildiz with x(n+1) = (1-a)*x(n)+a*f(...))
            # then change randomly the signs of the matrix

            # random weight matrix from 0 to 0.5

            self._W = B.array(B.rand(self.n_reservoir, self.n_reservoir) / 2)

            # set sparseness% to zero
            mask = B.rand(self.n_reservoir,
                          self.n_reservoir) > self._reservoirDensity
            self._W[mask] = 0.0

            _W_eigenvalue = B.max(B.abs(B.eigvals(self._W)))

            self._W *= self._spectralRadius / _W_eigenvalue

            if verbose:
                M = self._leakingRate * self._W + (
                    1 - self._leakingRate) * B.identity(n=self._W.shape[0])
                M_eigenvalue = B.max(B.abs(B.eigenval(M)[0]))
                print("eff. spectral radius: {0}".format(M_eigenvalue))

            # change random signs
            random_signs = B.power(-1, B.randint(1, 3, (self.n_reservoir, )))

            self._W = B.multiply(self._W, random_signs)
        elif weightGeneration == "custom":
            pass
        else:
            raise ValueError(
                "The weightGeneration property must be one of the following values: naive, advanced, SORM, custom"
            )

        # check of the user is really using one of the internal methods, or wants to create W by his own
        if weightGeneration != "custom":
            self._createInputMatrix()

        # create the optional feedback matrix
        if feedback:
            self._WFeedback = B.rand(self.n_reservoir, 1 + self.n_output) - 0.5
            self._WFeedback *= self._feedbackScaling
        else:
            self._WFeedback = None