Пример #1
0
    def _execute(self, x):
        is_2d = x.ndim==2
        output_shape, input_shape = self._output_shape, self._input_shape
        filters = self.filters
        nfilters = filters.shape[0]

        # XXX depends on convolution
        y = numx.empty((x.shape[0], nfilters,
                        output_shape[0], output_shape[1]), dtype=self.dtype)
        for n_im, im in enumerate(x):
            if is_2d:
                im = im.reshape(input_shape)
            for n_flt, flt in enumerate(filters):
                if self.approach == 'fft':
                    y[n_im,n_flt,:,:] = signal.fftconvolve(im, flt, mode=self.mode)
                elif self.approach == 'linear':
                    y[n_im,n_flt,:,:] = signal.convolve2d(im, flt,
                                                          mode=self.mode,
                                                          boundary=self.boundary,
                                                          fillvalue=self.fillvalue)

        # reshape if necessary
        if self.output_2d:
            y.resize((y.shape[0], self.output_dim))

        return y
Пример #2
0
    def _execute(self, x):
        """Expansion of the data.

        :param x: The data to be expanded. Observations/samples must
            be along the first axis, variables along the second.
        :type x: numpy.ndarray

        :returns: The expansion of x with observations/samples along the
            first axis and corresponding function values (expansion)
            along the second axis.
        :rtype: numpy.ndarray
        """

        num_vars = x.shape[1]
        num_samples = x.shape[0]
        deg = self.degree

        _with0 = hasattr(self, "with0") and self.with0
        dim = self.expanded_dim(num_vars)
        dim += 1 if not self.with0 else 0
        result = np.empty(
            [num_samples, dim], dtype=self.dtype)

        if self.check:
            self.check_domain(x)

        result[:, 0] = 1.
        pos = 1

        if deg > 1:
            for cur_var in range(num_vars):
                # preset index for current variable
                pos, n, special = self.r_init(result, x, pos, cur_var)
                # single variable recursion
                while n <= deg:
                            # recursion step
                    result[:, pos] = self.recf(
                        result, x, special, n, cur_var, pos)
                    n += 1
                    pos += 1
        # in case input is unreasonable
        elif deg == 1:
            result[:, 0] = 1
            for i in range(num_vars):
                result[:, i+1] = x[:, i]
        elif self.with0:
            return np.ones((num_samples, num_vars))
        else:
            return None

        todoList = []
        for i in range(1, num_vars):
            todoList.append((i*deg, i, 1))
        # compute the rest of the "simplex" product
        while len(todoList) > 0:
            # pos = process(*todoList.pop(0), deg, pos, result, todoList)
            pos = process(*todoList.pop(0)+(deg, pos, result, todoList))
        return (result if _with0 else result[:, 1:])
Пример #3
0
    def time_derivative(self, x, dt=None, time_dep=True):
        """Compute the linear approximation of the time derivative

        :param x: The time series data.
        :type x: numpy.ndarray

        :param dt: Sequence of time increments between vectors. 

            Usage with only single chunk of data:
                *dt* should be of length *x.shape[0]-1* or a constant. When
                constant, the time increments are assumed to be constant. If
                *dt* is not supplied, a constant time increment of one is
                assumed. If a time sequence of length *x.shape[0]* is supplied
                the first element is disregarded and a warning is presented.

            Usage with multiple chunks of data with intended time dependence:
                *dt* should have length *x.shape[0]-1* in the first call and
                be of length *x.shape[0]* starting with the second call.
                Starting with the second call, the first element in each chunk
                will be considered the time difference between the last element
                of *x* in the previous chunk and the first element of *x* of the
                current chunk.
                The *time_dep* argument being *True* indicates this mode.

            Usage with multiple chunks without time dependence:
                The moments are computed as a weighted average of the moments
                of separate chunks, if *dt* continues to have length
                *x.shape[0]-1* after the first call. Time dependence between
                chunks is thus omitted and all algorithmic components regard
                only the time structure within chunks.
                The *time_dep* argument being *False* indicates this mode.
                As in the single chunk case it is possible to set *dt* to be a
                constant or omit it completely for constant or unit time
                increments within chunks respectively.

        :type dt: numpy.ndarray or numeric

        :param time_dep: Indicates whether time dependence between chunks can
            be considered. The argument is only relevant if multiple chunks
            of data are used. Time dependence between chunks is disregarded
            when data collection has been done time-independently and thus no
            reasonable time increment between the end of a chunk and
            beginning of the next can be specified.
        
        :type time_dep: bool

        :returns: Piecewise linear approximation of the time derivative.
        :rtype: numpy.ndarray
        """
        if dt is not None and type(dt) == numx.ndarray:
            # check for inconsistent arguments
            if time_dep and self.tchunk > 0 and x.shape[0] - 1 == len(dt):
                raise Exception(
                    'As time_dependence is specified, and it is not the first'
                    '\ncall argument dt should be of length x.shape[0].')
            if (not time_dep or self.tchunk == 0) and x.shape[0] == len(dt):
                warnings.warn(_INC_ARG_WARNING1, mdp.MDPWarning)
            if len(dt) != x.shape[0] and len(dt) != x.shape[0] - 1:
                raise Exception('Unexpected length of dt.')
        elif dt is not None and not dt > 0:
            raise Exception('Unexpected type or value of dt.')

        if dt is None:
            outlen = x.shape[
                0] if time_dep and self.tchunk > 0 else x.shape[0] - 1
        elif type(dt) == numx.ndarray:
            outlen = x.shape[0] - 1 if self.tchunk == 0 or dt.shape[
                0] != x.shape[0] else x.shape[0]
        elif dt > 0:
            outlen = x.shape[
                0] if self.tchunk > 0 and time_dep else x.shape[0] - 1
        out = numx.empty([outlen, x.shape[1]])

        if dt is not None and type(dt) == numx.ndarray:
            # Improvements can be made, by interpolating polynomials
            out[-x.shape[0]+1:, :] =\
                    (x[1:, :]-x[:-1, :]) / dt[-x.shape[0]+1:, None]
        elif dt is not None and dt > 0:
            out[-x.shape[0] + 1:, :] = (x[1:, :] - x[:-1, :]) / dt
        else:
            # trivial fallback
            out[-x.shape[0] + 1:, :] = x[1:, :] - x[:-1, :]

        if self.tchunk > 0 and time_dep:
            if dt is None:
                out[0, :] = x[0, :] - self.xlast
            elif type(dt) == numx.ndarray and dt.shape[0] == x.shape[0]:
                out[0, :] = numx.divide(x[0, :] - self.xlast, dt[0])
            elif dt > 0:
                out[0, :] = numx.divide(x[0, :] - self.xlast, dt)

        self.xlast = x[-1, :].copy()
        self.tchunk += 1

        return out