Пример #1
0
    def calculateTransientTime(self, inputs, outputs, epsilon, proximityLength = None):
        # inputs: input of reserovoir
        # outputs: output of reservoir
        # epsilon: given constant
        # proximity length: number of steps for which all states have to be epsilon close to declare convergance
        # initializes two initial states as far as possible from each other in [-1,1] regime and tests when they converge-> this is transient time

        length = inputs.shape[0] if inputs is not None else outputs.shape[0]
        if proximityLength is None:
            proximityLength = int(length * 0.1)
            if proximityLength < 3:
                proximityLength = 3

        initial_x = B.empty((2, self.n_reservoir, 1))
        initial_x[0] = - B.ones((self.n_reservoir, 1))
        initial_x[1] = B.ones((self.n_reservoir, 1))

        countedConsecutiveSteps = 0
        length = inputs.shape[0] if inputs is not None else outputs.shape[0]
        for t in range(length):
            if B.max(B.ptp(initial_x, axis=0)) < epsilon:
                if countedConsecutiveSteps >= proximityLength:
                    return t - proximityLength
                else:
                    countedConsecutiveSteps += 1
            else:
                countedConsecutiveSteps = 0

            u = inputs[t].reshape(-1, 1) if inputs is not None else None
            o = outputs[t].reshape(-1, 1) if outputs is not None else None
            for i in range(initial_x.shape[0]):
                self.update(u, o, initial_x[i])

        #transient time could not be determined
        raise ValueError("Transient time could not be determined - maybe the proximityLength is too big.")       
Пример #2
0
        def getEquilibriumState(inputs, outputs, epsilon = 1e-3):
            # inputs: input of reserovoir
            # outputs: output of reservoir
            # epsilon: given constant
            # returns the equilibrium state when esn is fed with the first state of input
            x = B.empty((2, self.n_reservoir, 1))
            while not B.max(B.ptp(x, axis=0)) < epsilon:
                x[0] = x[1]
                u = inputs[0].reshape(-1, 1) if inputs is not None else None
                o = outputs[0].reshape(-1, 1) if outputs is not None else None
                self.update(u, o, x[1])

            return x[1]
Пример #3
0
def calculate_esn_mi_input_scaling(input_data, output_data):
    if len(input_data) != len(output_data):
        raise ValueError(
            "input_data and output_data do not have the same length -  {0} vs. {1}"
            .format(len(input_data), len(output_data)))

    # Scott's rule to calculate nbins
    std_output = B.std(output_data)
    nbins = int(
        B.ceil(2.0 / (3.5 * std_output / B.power(len(input_data), 1.0 / 3.0))))

    mi = B.zeros(input_data.shape[1])
    for i in range(len(mi)):
        mi[i] = calculate_mutualinformation(input_data[:, i], output_data,
                                            nbins)
    scaling = mi / B.max(mi)

    return scaling
Пример #4
0
    def reduceTransientTime(self, inputs, outputs, initialTransientTime, epsilon = 1e-3, proximityLength = 50):
        # inputs: input of reserovoir
        # outputs: output of reservoir
        # epsilon: given constant
        # proximity length: number of steps for which all states have to be epsilon close to declare convergance
        # initialTransientTime: transient time with calculateTransientTime() method estimated
        # finds initial state with lower transient time and sets internal state to this state
        # returns the new transient time by calculating the convergence time of initial states found with SWD and Equilibrium method
 
        def getEquilibriumState(inputs, outputs, epsilon = 1e-3):
            # inputs: input of reserovoir
            # outputs: output of reservoir
            # epsilon: given constant
            # returns the equilibrium state when esn is fed with the first state of input
            x = B.empty((2, self.n_reservoir, 1))
            while not B.max(B.ptp(x, axis=0)) < epsilon:
                x[0] = x[1]
                u = inputs[0].reshape(-1, 1) if inputs is not None else None
                o = outputs[0].reshape(-1, 1) if outputs is not None else None
                self.update(u, o, x[1])

            return x[1]

        def getStateAtGivenPoint(inputs, outputs, targetTime):
            # inputs: input of reserovoir
            # outputs: output of reservoir
            # targetTime: time at which the state is wanted
            # propagates the inputs/outputs till given point in time and returns the state of the reservoir at this point
            x = B.zeros((self.n_reservoir, 1))

            length = inputs.shape[0] if inputs is not None else outputs.shape[0]
            length = min(length, targetTime)
            for t in range(length):
                u = inputs[t].reshape(-1, 1) if inputs is not None else None
                o = outputs[t].reshape(-1, 1) if outputs is not None else None
                self.update(u, o, x)
        
            return x

        length = inputs.shape[0] if inputs is not None else outputs.shape[0]
        if proximityLength is None:
            proximityLength = int(length * 0.1)
            if proximityLength < 3:
                proximityLength = 3
     
        x = B.empty((2, self.n_reservoir, 1))
        equilibriumState = getEquilibriumState(inputs, outputs)
     
        if inputs is None:
            swdPoint, _ = hp.SWD(outputs, int(initialTransientTime*0.8))
        else:
            swdPoint, _ = hp.SWD(inputs, int(initialTransientTime * 0.8))
        
        swdState = getStateAtGivenPoint(inputs, outputs, swdPoint)
        
        x[0] = equilibriumState
        x[1] = swdState
        
        transientTime = 0

        countedConsecutiveSteps = 0
        for t in range(length):
            if B.max(B.ptp(x, axis=0)) < epsilon:
                countedConsecutiveSteps += 1
                if countedConsecutiveSteps > proximityLength:
                    transientTime = t - proximityLength
                    break
            else:
                countedConsecutiveSteps = 0

            u = inputs[t].reshape(-1, 1) if inputs is not None else None
            o = outputs[t].reshape(-1, 1) if outputs is not None else None
            for i in range(x.shape[0]):
                self.update(u, o, x[i])

        self._x = x[0]
        return transientTime
Пример #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(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
Пример #6
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