Beispiel #1
0
def ComputeMultiLevelSig(path, number_of_segment, deg_of_sig, s, sig='False'):
    """
    compute the signature and log-signature of segments of one path of dimension (n, d)
    """
    n_t = path.shape[0]
    n_Path = path.shape[1]
    t_vec = np.arange(1, n_t, int(n_t / number_of_segment))
    t_vec = np.append(t_vec, n_t)
    MultiLevelSig = np.empty
    MultiLevelLogSig = np.empty

    for i in range(1, number_of_segment + 1, 1):
        temp_path = path[t_vec[i - 1] - 1:t_vec[i], 0:2]
        if deg_of_sig == 1:
            temp = iisignature.sig(temp_path, 1)
        else:

            if sig == 'False':
                templog = iisignature.logsig(temp_path, s)
            else:
                templog = iisignature.sig(temp_path, deg_of_sig)

        tempStart = (temp_path[0, 1])
        # print(temp)
        if (i == 1):
            #MultiLevelSig = temp
            MultiLevelLogSig = templog
            MultiStart = np.array([tempStart])
        else:
            #MultiLevelSig = np.concatenate((MultiLevelSig,temp), axis = 0)
            MultiLevelLogSig = np.concatenate(
                (MultiLevelLogSig, templog), axis=0)
            MultiStart = np.append(MultiStart, [tempStart])
    return {'MultiLevelSig': MultiLevelSig, 'MultiLevelLogSig': MultiLevelLogSig, 'MultiStart': MultiStart}
Beispiel #2
0
    def testa(self):
        numpy.random.seed(775)
        d = 3
        m = 5
        pathLength = 5
        numberToDo = 2
        paths = numpy.random.uniform(size=(numberToDo,pathLength,d))
        sigs = numpy.vstack([iisignature.sig(i,m) for i in paths])
        scales = numpy.random.uniform(0.5,0.97,size=(numberToDo,d))
        scaledPaths = paths * scales[:,numpy.newaxis,:]
        scaledSigs = numpy.vstack([iisignature.sig(i,m) for i in scaledPaths])
        scaledSigsCalc = iisignature.sigscale(sigs,scales,m)
        self.assertEqual(scaledSigs.shape,scaledSigsCalc.shape)
        self.assertLess(diff(scaledSigs,scaledSigsCalc),0.0000001)

        bumpedScales = 1.001 * scales
        bumpedSigs = 1.001 * sigs
        base = numpy.sum(scaledSigsCalc)
        bump1 = numpy.sum(iisignature.sigscale(bumpedSigs,scales,m))
        bump2 = numpy.sum(iisignature.sigscale(sigs,bumpedScales,m))
        derivsOfSum = numpy.ones_like(scaledSigsCalc)
        calculated = iisignature.sigscalebackprop(derivsOfSum,sigs,scales,m)
        diff1 = (bump1 - base) - numpy.sum(calculated[0] * (bumpedSigs - sigs))
        diff2 = (bump2 - base) - numpy.sum(calculated[1] * (bumpedScales - scales))
        #print(calculated[1].shape,bumpedScales.shape,scales.shape)
        #print(calculated[1][0,0],bump2,base,bumpedScales[0,0],scales[0,0])
        #print (bump1,bump2,base,diff1,diff2)
        self.assertLess(numpy.abs(diff1),0.0000001)
        self.assertLess(numpy.abs(diff2),0.0000001)
def generate(M,
             N,
             h_x=0.8,
             h_y=0.8,
             scale=1.,
             signature=False,
             BM=False,
             dim_BM=2):

    if BM:
        X = brownian(M - 1, dim_BM, time=1.)
        Y = brownian(N - 1, dim_BM, time=1.)

    else:
        fbm_generator_X = FBM(M - 1, h_x)
        fbm_generator_Y = FBM(N - 1, h_y)

        x = scale * fbm_generator_X.fbm()
        y = scale * fbm_generator_Y.fbm()

        X = AddTime().fit_transform([x])[0]
        Y = AddTime().fit_transform([y])[0]

    if signature:
        X = iisignature.sig(X, 5, 2)
        Y = iisignature.sig(Y, 5, 2)

        X0 = np.zeros_like(X[0, :].reshape(1, -1))
        X0[0, 0] = 1.
        X = np.concatenate([X0, X])
        Y = np.concatenate([X0, Y])

    return X, Y
Beispiel #4
0
    def testcombining(self):
        dim = 2
        level = 2
        siglength = iisignature.siglength(dim,level)
        pathLength = 20
        halfPathLength=10
        numberToDo=4
        path = numpy.random.uniform(size=(numberToDo,pathLength,dim))
        sig = iisignature.sig(path,level)
        sig1 = iisignature.sig(path[:,:halfPathLength],level)
        sig2 = iisignature.sig(path[:,(halfPathLength-1):],level)
        combined = iisignature.sigcombine(sig1,sig2,dim,level)
        self.assertLess(diff(sig,combined),0.0001)

        extra = numpy.random.uniform(size=(siglength,))
        bumpedsig1 = 1.001 * sig1
        bumpedsig2 = 1.001 * sig2
        base = numpy.sum(iisignature.sigcombine(sig1,sig2,dim,level))
        bump1 = numpy.sum(iisignature.sigcombine(bumpedsig1,sig2,dim,level))
        bump2 = numpy.sum(iisignature.sigcombine(sig1,bumpedsig2,dim,level))
        derivsOfSum = numpy.ones((numberToDo,siglength))
        calculated = iisignature.sigcombinebackprop(derivsOfSum,sig1,sig2,dim,level)
        self.assertEqual(len(calculated), 2)
        diff1 = (bump1 - base) - numpy.sum(calculated[0] * (bumpedsig1 - sig1))
        diff2 = (bump2 - base) - numpy.sum(calculated[1] * (bumpedsig2 - sig2))
        #print ("\n",bump1,bump2,base,diff1,diff2)
        self.assertLess(numpy.abs(diff1),0.000001)
        self.assertLess(numpy.abs(diff2),0.00001)
Beispiel #5
0
 def testFewPoints(self):
     # check sanity of paths with less than 3 points
     path1=[[4.3,0.8]]
     path2=numpy.array([[1,2],[2,4]])
     m=4
     d=2
     s=iisignature.prepare(d,m,"cosx")
     s_a=iisignature.prepare(d,2,"cosx")
     length=iisignature.siglength(d,m)
     loglength=iisignature.logsiglength(d,m)
     loglength_a=iisignature.logsiglength(d,2)
     blankLogSig=numpy.zeros(loglength)
     blankLogSig_a=numpy.zeros(loglength_a)
     blankSig=numpy.zeros(length)
     self.assertLess(diff(iisignature.sig(path1,m),blankSig),0.000000001)
     self.assertTrue(numpy.array_equal(iisignature.sig(path1,m,2),numpy.zeros([0,length])))
     self.assertLess(diff(iisignature.logsig(path1,s,"C"),blankLogSig),0.000000001)
     self.assertLess(diff(iisignature.logsig(path1,s,"O"),blankLogSig),0.000000001)
     self.assertLess(diff(iisignature.logsig(path1,s,"S"),blankLogSig),0.000000001)
     self.assertLess(diff(iisignature.logsig(path1,s,"X"),blankSig),0.000000001)
     self.assertLess(diff(iisignature.logsig(path1,s_a,"A"),blankLogSig_a),0.000000001)
     blankLogSig[:d]=path2[1]-path2[0]
     blankLogSig_a[:d]=path2[1]-path2[0]
     blankSig[:d]=path2[1]-path2[0]
     self.assertLess(diff(iisignature.logsig(path2,s,"C"),blankLogSig),0.000001)
     self.assertLess(diff(iisignature.logsig(path2,s,"O"),blankLogSig),0.000001)
     self.assertLess(diff(iisignature.logsig(path2,s,"S"),blankLogSig),0.000001)
     self.assertLess(diff(iisignature.logsig(path2,s,"X"),blankSig),0.000001)
     self.assertLess(diff(iisignature.logsig(path2,s_a,"A"),blankLogSig_a),0.000001)
Beispiel #6
0
    def testa(self):
        numpy.random.seed(775)
        d = 3
        m = 5
        pathLength = 5
        numberToDo = 2
        paths = numpy.random.uniform(size=(numberToDo,pathLength,d))
        sigs = numpy.vstack([iisignature.sig(i,m) for i in paths])
        scales = numpy.random.uniform(0.5,0.97,size=(numberToDo,d))
        scaledPaths = paths * scales[:,numpy.newaxis,:]
        scaledSigs = numpy.vstack([iisignature.sig(i,m) for i in scaledPaths])
        scaledSigsCalc = iisignature.sigscale(sigs,scales,m)
        self.assertEqual(scaledSigs.shape,scaledSigsCalc.shape)
        self.assertLess(diff(scaledSigs,scaledSigsCalc),0.0000001)

        bumpedScales = 1.001 * scales
        bumpedSigs = 1.001 * sigs
        base = numpy.sum(scaledSigsCalc)
        bump1 = numpy.sum(iisignature.sigscale(bumpedSigs,scales,m))
        bump2 = numpy.sum(iisignature.sigscale(sigs,bumpedScales,m))
        derivsOfSum = numpy.ones_like(scaledSigsCalc)
        calculated = iisignature.sigscalebackprop(derivsOfSum,sigs,scales,m)
        diff1 = (bump1 - base) - numpy.sum(calculated[0] * (bumpedSigs - sigs))
        diff2 = (bump2 - base) - numpy.sum(calculated[1] * (bumpedScales - scales))
        #print(calculated[1].shape,bumpedScales.shape,scales.shape)
        #print(calculated[1][0,0],bump2,base,bumpedScales[0,0],scales[0,0])
        #print (bump1,bump2,base,diff1,diff2)
        self.assertLess(numpy.abs(diff1),0.0000001)
        self.assertLess(numpy.abs(diff2),0.0000001)
Beispiel #7
0
 def testFewPoints(self):
     # check sanity of paths with less than 3 points
     path1=[[4.3,0.8]]
     path2=numpy.array([[1,2],[2,4]])
     m=4
     d=2
     s=iisignature.prepare(d,m,"cosx")
     s_a=iisignature.prepare(d,2,"cosx")
     length=iisignature.siglength(d,m)
     loglength=iisignature.logsiglength(d,m)
     loglength_a=iisignature.logsiglength(d,2)
     blankLogSig=numpy.zeros(loglength)
     blankLogSig_a=numpy.zeros(loglength_a)
     blankSig=numpy.zeros(length)
     self.assertLess(diff(iisignature.sig(path1,m),blankSig),0.000000001)
     self.assertTrue(numpy.array_equal(iisignature.sig(path1,m,2),numpy.zeros([0,length])))
     self.assertLess(diff(iisignature.logsig(path1,s,"C"),blankLogSig),0.000000001)
     self.assertLess(diff(iisignature.logsig(path1,s,"O"),blankLogSig),0.000000001)
     self.assertLess(diff(iisignature.logsig(path1,s,"S"),blankLogSig),0.000000001)
     self.assertLess(diff(iisignature.logsig(path1,s,"X"),blankSig),0.000000001)
     self.assertLess(diff(iisignature.logsig(path1,s_a,"A"),blankLogSig_a),0.000000001)
     blankLogSig[:d]=path2[1]-path2[0]
     blankLogSig_a[:d]=path2[1]-path2[0]
     blankSig[:d]=path2[1]-path2[0]
     self.assertLess(diff(iisignature.logsig(path2,s,"C"),blankLogSig),0.000001)
     self.assertLess(diff(iisignature.logsig(path2,s,"O"),blankLogSig),0.000001)
     self.assertLess(diff(iisignature.logsig(path2,s,"S"),blankLogSig),0.000001)
     self.assertLess(diff(iisignature.logsig(path2,s,"X"),blankSig),0.000001)
     self.assertLess(diff(iisignature.logsig(path2,s_a,"A"),blankLogSig_a),0.000001)
 def transform(self, X, y=None):
     # get the lengths of all pathwise expected signatures
     lengths = [pwES.shape[0] for pwES in X]
     if len(list(set(lengths))) == 1:
         # if all pathwise expected signatures have the same length, the signatures can be computed in batch
         return iisignature.sig(X, self.order)
     else:
         return [iisignature.sig(item, self.order) for item in X]
def naive_sig_kernel(x, y, depth):
    sigx = iisignature.sig(x, depth, 2)
    sigy = iisignature.sig(y, depth, 2)
    k_true = np.ones((len(x), len(y)))
    for i, sx in enumerate(sigx):
        for j, sy in enumerate(sigy):
            k_true[i + 1, j + 1] = 1. + np.dot(sigx[i], sigy[j])
    return k_true
 def transform(self, X, y=None):
     # get the lengths of all time series (across items across bags)
     lengths = [item.shape[0] for bag in X for item in bag]
     if len(list(set(lengths))) == 1:
         # if all time series have the same length, the signatures can be computed in batch
         X = [iisignature.sig(bag, self.order) for bag in X]
     else:
         X = [np.array([iisignature.sig(item, self.order) for item in bag]) for bag in X]
     return [x.mean(0) for x in X]
Beispiel #11
0
 def testCumulative(self):
     m=3
     d=2
     length = 10
     path=numpy.random.uniform(size=(length,d))
     cumul = iisignature.sig(path,m,2)
     expected = numpy.array([iisignature.sig(path[:(i+1)],m) for i in range(1,length)])
     self.assertTrue(numpy.allclose(expected, cumul))
     path=numpy.random.uniform(size=(3,2,length,d))
     cumul = iisignature.sig(path,m,2)
     #expected = numpy.stack([iisignature.sig(path[:,:,:(i+1)],m) for i in range(1,length)],-2)
     expected = numpy.rollaxis(stack([iisignature.sig(path[:,:,:(i+1)],m) for i in range(1,length)]),0,3)
     self.assertTrue(numpy.allclose(expected, cumul))
Beispiel #12
0
 def testCumulative(self):
     m=3
     d=2
     length = 10
     path=numpy.random.uniform(size=(length,d))
     cumul = iisignature.sig(path,m,2)
     expected = numpy.array([iisignature.sig(path[:(i+1)],m) for i in range(1,length)])
     self.assertTrue(numpy.allclose(expected, cumul))
     path=numpy.random.uniform(size=(3,2,length,d))
     cumul = iisignature.sig(path,m,2)
     #expected = numpy.stack([iisignature.sig(path[:,:,:(i+1)],m) for i in range(1,length)],-2)
     expected = numpy.rollaxis(stack([iisignature.sig(path[:,:,:(i+1)],m) for i in range(1,length)]),0,3)
     self.assertTrue(numpy.allclose(expected, cumul))
Beispiel #13
0
    def testSig(self):
        #test that sigjacobian and sigbackprop compatible with sig
        numpy.random.seed(291)
        d = 3
        m = 5
        pathLength = 10
        path = numpy.random.uniform(size=(pathLength,d))
        path = numpy.cumsum(2 * (path - 0.5),0)#makes it more random-walk-ish, less like a scribble
        increment = 0.01 * numpy.random.uniform(size=(pathLength,d))
        base_sig = iisignature.sig(path,m)

        target = fdDeriv(lambda x:iisignature.sig(x,m),path,increment,2, nosum=True)
        
        gradient = iisignature.sigjacobian(path,m)
        calculated = numpy.tensordot(increment,gradient)

        diffs = numpy.max(numpy.abs(calculated - target))
        niceOnes = numpy.abs(calculated) > 1.e-4
        niceOnes2 = numpy.abs(calculated) < numpy.abs(base_sig)
        diffs1 = numpy.max(numpy.abs((calculated[niceOnes2] - target[niceOnes2]) / base_sig[niceOnes2]))
        diffs2 = numpy.max(numpy.abs(calculated[1 - niceOnes2] - target[1 - niceOnes2]))
        ratioDiffs = numpy.max(numpy.abs(calculated[niceOnes] / target[niceOnes] - 1))

        #numpy.set_printoptions(suppress=True,linewidth=os.popen('stty size',
        #'r').read().split()[1] #LINUX
        #numpy.set_printoptions(suppress=True,linewidth=150)
        #print ("")
        #print (path)
        #print
        #(numpy.vstack([range(len(base_sig)),base_sig,calculated,target,(calculated-target)/base_sig,calculated/target-1]).transpose())
        #print (diffs, ratioDiffs, diffs1, diffs2)
        #print(numpy.argmax(numpy.abs(calculated[niceOnes]/target[niceOnes]-1)),numpy.argmax(numpy.abs((calculated-target)/base_sig)))

        self.assertLess(diffs,0.00001)
        self.assertLess(ratioDiffs,0.01)
        self.assertLess(diffs1,0.001) 
        self.assertLess(diffs2,0.00001) 

        #compatibility between sigbackprop and sigjacobian is strong
        dFdSig = numpy.random.uniform(size=(iisignature.siglength(d,m),))
        backProp = iisignature.sigbackprop(dFdSig,path,m)
        manualCalcBackProp = numpy.dot(gradient,dFdSig)
        backDiffs = numpy.max(numpy.abs(backProp - manualCalcBackProp))
        if 0: # to investigate the compile logic problem I used this and
              # (d,m,pathLength)=(1,2,2)
            print("")
            print(dFdSig)
            print(path)
            print(backProp)
            print(manualCalcBackProp)
        self.assertLess(backDiffs,0.000001)
Beispiel #14
0
    def testSig(self):
        #test that sigjacobian and sigbackprop compatible with sig
        numpy.random.seed(291)
        d = 3
        m = 5
        pathLength = 10
        path = numpy.random.uniform(size=(pathLength,d))
        path = numpy.cumsum(2 * (path - 0.5),0)#makes it more random-walk-ish, less like a scribble
        increment = 0.01 * numpy.random.uniform(size=(pathLength,d))
        base_sig = iisignature.sig(path,m)

        target = fdDeriv(lambda x:iisignature.sig(x,m),path,increment,2, nosum=True)
        
        gradient = iisignature.sigjacobian(path,m)
        calculated = numpy.tensordot(increment,gradient)

        diffs = numpy.max(numpy.abs(calculated - target))
        niceOnes = numpy.abs(calculated) > 1.e-4
        niceOnes2 = numpy.abs(calculated) < numpy.abs(base_sig)
        diffs1 = numpy.max(numpy.abs((calculated[niceOnes2] - target[niceOnes2]) / base_sig[niceOnes2]))
        diffs2 = numpy.max(numpy.abs(calculated[1 - niceOnes2] - target[1 - niceOnes2]))
        ratioDiffs = numpy.max(numpy.abs(calculated[niceOnes] / target[niceOnes] - 1))

        #numpy.set_printoptions(suppress=True,linewidth=os.popen('stty size',
        #'r').read().split()[1] #LINUX
        #numpy.set_printoptions(suppress=True,linewidth=150)
        #print ("")
        #print (path)
        #print
        #(numpy.vstack([range(len(base_sig)),base_sig,calculated,target,(calculated-target)/base_sig,calculated/target-1]).transpose())
        #print (diffs, ratioDiffs, diffs1, diffs2)
        #print(numpy.argmax(numpy.abs(calculated[niceOnes]/target[niceOnes]-1)),numpy.argmax(numpy.abs((calculated-target)/base_sig)))

        self.assertLess(diffs,0.00001)
        self.assertLess(ratioDiffs,0.01)
        self.assertLess(diffs1,0.001) 
        self.assertLess(diffs2,0.00001) 

        #compatibility between sigbackprop and sigjacobian is strong
        dFdSig = numpy.random.uniform(size=(iisignature.siglength(d,m),))
        backProp = iisignature.sigbackprop(dFdSig,path,m)
        manualCalcBackProp = numpy.dot(gradient,dFdSig)
        backDiffs = numpy.max(numpy.abs(backProp - manualCalcBackProp))
        if 0: # to investigate the compile logic problem I used this and
              # (d,m,pathLength)=(1,2,2)
            print("")
            print(dFdSig)
            print(path)
            print(backProp)
            print(manualCalcBackProp)
        self.assertLess(backDiffs,0.000001)
Beispiel #15
0
 def testLevel1(self):
     m = 1
     d = 2
     path = numpy.random.uniform(size=(10, d))
     rightSig = path[-1, :] - path[0, :]
     s = iisignature.prepare(d, m, "cosx2")
     self.assertLess(diff(iisignature.sig(path, m), rightSig), 0.0000001)
     for type_ in ("C", "O", "S", "X", "A"):
         self.assertLess(diff(iisignature.logsig(path, s, type_), rightSig),
                         0.0000001, type_)
     self.assertLess(diff(rightSig, iisignature.logsigtosig(rightSig, s)),
                     0.000001)
     derivs = numpy.array([2.1, 3.2])
     pathderivs = numpy.zeros_like(path)
     pathderivs[-1] = derivs
     pathderivs[0] = -derivs
     self.assertLess(
         diff(iisignature.logsigbackprop(derivs, path, s), pathderivs),
         0.00001)
     self.assertLess(
         diff(iisignature.logsigbackprop(derivs, path, s, "X"), pathderivs),
         0.00001)
     self.assertLess(
         diff(iisignature.sigbackprop(derivs, path, m), pathderivs),
         0.00001)
def scale_path(x, M, a, level_sig):
    '''
        This function computes a single scaling factor \theta_x (path-dependent) and rescales the path x 
        , i.e. return x_new: t -> \theta_x*x_t, such that ||S_{<level_sig}(x_new)|| < M(1+1/a).
        
        Inputs:
            - x: an array (L,D) representing a path where L is the length and D is the state-space dimension
            - (int) level_sig: the truncation level to compute the norm of S_{<level_sig}(x)
            - (int) M: the first parameter used to define the maximum norm allowed 
            - (float) a: the second parameter used to define the maximum norm allowed 
        Outputs:
            - x_new: the rescaled path 
    '''
    D = x.shape[1]

    maxi = M * (1. + 1. / a)

    sig = iisignature.sig(x, level_sig)  # computes the signature of the path x

    norm_levels = get_norm_level_sig(
        sig, D, level_sig
    )  # gets the norm of each tensor in S(x) truncated at level level_sig

    norm = np.sum(
        norm_levels)  # gets the norm of S(x) truncated at level level_sig

    psi = psi_tilde(
        norm, M,
        a)  # computes an intermediary number which is used to find the scale

    theta_x = brentq(poly, 0, 10000,
                     args=(psi, norm_levels, level_sig))  # computes the scale

    return theta_x * x
def signature_of_path(path,upto_level):
    """Convenience method for calculating the signature of a path using iisignature.
    
    Parameters
    ----------
    path : numpy.array
       A (T,d) dimensional array, with `d` the dimnsion of the path and `T` the number of time-steps.
    upto_level: int
       Compute the signature up-to (and including) this level.

    Returns
    -------
    signature : A `LinearCombination` of `ConcatenationWord`s storing the signature as its coefficients.
    """
    import iisignature

    d = np.shape(path)[-1]

    s = iisignature.sig(path,upto_level,1)
    letters = range(1,d+1)    
    def signature_generator():
        yield (words.ConcatenationWord(), 1)
        for lev in range(1,upto_level+1):
            for word, val in zip( itertools.product(letters,repeat=lev), s[lev-1]):
                yield (words.ConcatenationWord(word), val)
    return lc.LinearCombination.from_generator( signature_generator() )
Beispiel #18
0
def get_sigX(X, k):
    """Returns a matrix containing signatures truncated at k of n samples
	given in the input tensor X.

	Parameters
	----------
	X: array, shape (n, npoints, d)
		A 3-dimensional array, containing the coordinates in R^d of n
		piecewise linear paths, each composed of n_points.

	k: int
		Truncation order of the signature

	Returns
	-------
	sigX: array, shape (n,p)
		A matrix containing in each row the signature truncated at k of a sample.
	"""
    if k == 0:
        return np.full((np.shape(X)[0], 1), 1)
    else:
        d = X.shape[2]
        sigX = np.zeros((np.shape(X)[0], isig.siglength(d, k) + 1))
        sigX[:, 0] = 1
        for i in range(np.shape(X)[0]):
            sigX[i, 1:] = isig.sig(X[i, :, :], k)
        return sigX
Beispiel #19
0
 def forward(ctx, path, depth):
     ctx.path = path.detach().cpu()
     ctx.depth = depth
     ctx.device = path.device
     ctx.dtype = path.dtype
     return torch.tensor(iisignature.sig(ctx.path, ctx.depth),
                         device=ctx.device,
                         dtype=ctx.dtype)
Beispiel #20
0
 def preprocess(self, X):
     """
     Preprocess training/testing data using signatures.
     """
     data = [sig(self.transform(x), self.level) for x in X]
     if self.scale:
         data = preprocessing.scale(data)
     return data
Beispiel #21
0
    def consistency(self, coropa, dim, level):
        #numpy.random.seed(21)
        s = iisignature.prepare(dim,level,"coshx" if coropa else "cosx")
        myinfo = {"level":level, "dimension":dim,
                  "methods": ("COSAX" if level <= 2 else "COSX"),
                  "basis":("Standard Hall" if coropa else "Lyndon")}
        self.assertEqual(iisignature.info(s),myinfo)
        path = numpy.random.uniform(size=(10,dim))
        basis = iisignature.basis(s)
        logsig = iisignature.logsig(path,s)
        sig = iisignature.sig(path,level)

        #check lengths
        self.assertEqual(len(basis),iisignature.logsiglength(dim,level))
        self.assertEqual((len(basis),),logsig.shape)
        self.assertEqual(sig.shape,(iisignature.siglength(dim,level),))

        #calculate a signature from logsig
        expanded_logsig = [numpy.zeros(dim ** m) for m in range(1,level + 1)]
        for coeff, expression in zip(logsig,basis):
            values, depth = valueOfBracket(expression,dim)
            expanded_logsig[depth - 1]+=values * coeff
        calculated_sig = numpy.concatenate(exponentiateTensor(expanded_logsig))
        self.assertLess(diff(sig,calculated_sig),0.00001)

        #calculate a log signature from sig
        fullLogSig = numpy.concatenate(logTensor(splitConcatenatedTensor(sig,dim,level)))
        fullLogSigLib = iisignature.logsig(path,s,"x")
        diff1 = numpy.max(numpy.abs(fullLogSigLib - fullLogSig))
        #print
        #(numpy.vstack([fullLogSig,fullLogSigLib,numpy.abs(fullLogSigLib-fullLogSig)]).transpose())
        self.assertLess(diff1,0.00001)

        basisMatrix = []
        zeros = [numpy.zeros(dim ** m) for m in range(1,level + 1)]
        for expression in basis:
            values, depth = valueOfBracket(expression, dim)
            temp = zeros[depth - 1]
            zeros[depth - 1] = values
            basisMatrix.append(numpy.concatenate(zeros))
            zeros[depth - 1] = temp
        calculatedLogSig = lstsq(numpy.transpose(basisMatrix),fullLogSig)[0]
        diff2 = numpy.max(numpy.abs(logsig - calculatedLogSig))
        self.assertLess(diff2,0.00001)

        #check consistency of methods
        slowLogSig = iisignature.logsig(path,s,"o")
        diffs = numpy.max(numpy.abs(slowLogSig - calculatedLogSig))
        self.assertLess(diffs,0.00001)

        sigLogSig = iisignature.logsig(path,s,"s")
        diffs = numpy.max(numpy.abs(sigLogSig - calculatedLogSig))
        self.assertLess(diffs,0.00001)

        if level < 3:
            areaLogSig = iisignature.logsig(path,s,"a")
            diffs = numpy.max(numpy.abs(areaLogSig - calculatedLogSig))
            self.assertLess(diffs,0.00001)
Beispiel #22
0
    def consistency(self, coropa, dim, level):
        #numpy.random.seed(21)
        s = iisignature.prepare(dim,level,"coshx" if coropa else "cosx")
        myinfo = {"level":level, "dimension":dim,
                  "methods": ("COSAX" if level <= 2 else "COSX"),
                  "basis":("Standard Hall" if coropa else "Lyndon")}
        self.assertEqual(iisignature.info(s),myinfo)
        path = numpy.random.uniform(size=(10,dim))
        basis = iisignature.basis(s)
        logsig = iisignature.logsig(path,s)
        sig = iisignature.sig(path,level)

        #check lengths
        self.assertEqual(len(basis),iisignature.logsiglength(dim,level))
        self.assertEqual((len(basis),),logsig.shape)
        self.assertEqual(sig.shape,(iisignature.siglength(dim,level),))

        #calculate a signature from logsig
        expanded_logsig = [numpy.zeros(dim ** m) for m in range(1,level + 1)]
        for coeff, expression in zip(logsig,basis):
            values, depth = valueOfBracket(expression,dim)
            expanded_logsig[depth - 1]+=values * coeff
        calculated_sig = numpy.concatenate(exponentiateTensor(expanded_logsig))
        self.assertLess(diff(sig,calculated_sig),0.00001)

        #calculate a log signature from sig
        fullLogSig = numpy.concatenate(logTensor(splitConcatenatedTensor(sig,dim,level)))
        fullLogSigLib = iisignature.logsig(path,s,"x")
        diff1 = numpy.max(numpy.abs(fullLogSigLib - fullLogSig))
        #print
        #(numpy.vstack([fullLogSig,fullLogSigLib,numpy.abs(fullLogSigLib-fullLogSig)]).transpose())
        self.assertLess(diff1,0.00001)

        basisMatrix = []
        zeros = [numpy.zeros(dim ** m) for m in range(1,level + 1)]
        for expression in basis:
            values, depth = valueOfBracket(expression, dim)
            temp = zeros[depth - 1]
            zeros[depth - 1] = values
            basisMatrix.append(numpy.concatenate(zeros))
            zeros[depth - 1] = temp
        calculatedLogSig = lstsq(numpy.transpose(basisMatrix),fullLogSig)[0]
        diff2 = numpy.max(numpy.abs(logsig - calculatedLogSig))
        self.assertLess(diff2,0.00001)

        #check consistency of methods
        slowLogSig = iisignature.logsig(path,s,"o")
        diffs = numpy.max(numpy.abs(slowLogSig - calculatedLogSig))
        self.assertLess(diffs,0.00001)

        sigLogSig = iisignature.logsig(path,s,"s")
        diffs = numpy.max(numpy.abs(sigLogSig - calculatedLogSig))
        self.assertLess(diffs,0.00001)

        if level < 3:
            areaLogSig = iisignature.logsig(path,s,"a")
            diffs = numpy.max(numpy.abs(areaLogSig - calculatedLogSig))
            self.assertLess(diffs,0.00001)
Beispiel #23
0
def signature(path, depth):
	"""return signature of a path up to level depth"""
	assert isinstance(depth, int), 'Argument of wrong type'
	assert depth > 1, 'depth must be > 1'
	width = path.shape[1]
	length = path.shape[0]
	if length <= 1:
		return np.array([0.]*(tosig.sigdim(width, depth)-1))
	return iisignature.sig(path, depth)
Beispiel #24
0
 def forward(ctx, path, depth):
     device = path.device
     # transpose because the PyTorch convention for convolutions is channels first. The iisignature expectation is
     # that channels are last.
     path = path.detach().cpu().numpy().transpose()  # sloooow CPU :(
     ctx.path = path
     ctx.depth = depth
     return torch.tensor(iisignature.sig(path, depth),
                         dtype=torch.float,
                         device=device)
def treeEsig(tree, truncation):
    """Function computing the (truncated) Expected Signature of a tree"""
    w, path = tree['value']
    path_dim = path.shape[1]
    forest = tree['forest']
    ES = iisignature.sig(path, truncation)
    if forest:
        ES_forest = sum([treeEsig(t, truncation) for t in forest])
        ES = iisignature.sigcombine(ES, ES_forest, path_dim, truncation)
    return w * ES
def _get_tree_reduced_steps(X, order=4, steps=4, tol=0.1):
    if len(X) < steps:
        return X

    dim = X.shape[1]

    for i in range(steps - 1, len(X)):
        new_path = X[i - steps + 1:i + 1]
        new_path2 = np.r_[X[i - steps + 1].reshape(-1, dim),
                          X[i].reshape(-1, dim)]

        new_path_sig = iisignature.sig(new_path, order)
        new_path2_sig = iisignature.sig(new_path2, order)

        norm = np.linalg.norm(new_path_sig - new_path2_sig)
        if norm < tol:
            return _get_tree_reduced_steps(np.r_[X[:i - steps + 2], X[i:]])

    return X
 def signature_matrix(self, market_info):  # compute the signature matrix
     X_ts = self.construct_multi_feature_time_series(self.trend)
     sig_m = []
     stream = []
     for i in range(X_ts.shape[0]):
         stream = list(enumerate(X_ts[i]))
         path = self.leadlag(stream)
         sig = iisignature.sig(path, 3)  # change the dimension of signature
         sig = sig.tolist()
         sig_m.append(sig)
     return sig_m
    def f(path):
        path = transform(path)
        if N == 0:
            sig = np.array([1.])
        elif N == 1:
            sig = np.array(
                [1., path[-1, 0] - path[0, 0], path[-1, 1] - path[0, 1]])
        else:
            sig = np.r_[1., iisignature.sig(path, N)]

        return sig.dot(l)
    def transform(self, X, y=None):
        pwES = []
        for bag in X:
            # get the lengths of all time series in the bag
            lengths = [item.shape[0] for item in bag]
            if len(list(set(lengths))) == 1:
                # if all time series have the same length, the (pathwise) signatures can be computed in batch
                pwES.append(iisignature.sig(bag, self.order, 2))
            else:
                error_message = 'All time series in a bag must have the same length'
                raise NameError(error_message)

        return [x.mean(0) for x in pwES]
def preprocess_data(x_train, x_test, flag=None):
    """Peforms model-dependent preprocessing."""
    if flag == 'neuralsig':
        # We don't need to backprop through the signature if we're just building a model on top
        # so we actually perform the signature here as a feature transformation, rather than in
        # the model.
        path_transform = AddTime()
        x_train = np.array([
            iisignature.sig(x, 4)
            for x in path_transform.fit_transform(x_train)
        ])
        x_test = np.array([
            iisignature.sig(x, 4) for x in path_transform.fit_transform(x_test)
        ])
    elif flag == 'lstm':
        # LSTM wants another dimension in one place...
        x_train = np.expand_dims(x_train, 2)
        x_test = np.expand_dims(x_test, 2)
    else:
        # ...everyone else wants the extra dimension in another
        x_train = np.expand_dims(x_train, 1)
        x_test = np.expand_dims(x_test, 1)
    return x_train, x_test
Beispiel #31
0
 def testLevel1(self):
     m=1
     d=2
     path=numpy.random.uniform(size=(10,d))
     rightSig = path[-1,:]-path[0,:]
     s=iisignature.prepare(d,m,"cosx")
     self.assertLess(diff(iisignature.sig(path,m),rightSig),0.0000001)
     for type_ in ("C","O","S","X","A"):
         self.assertLess(diff(iisignature.logsig(path,s,type_),rightSig),0.0000001,type_)
     derivs=numpy.array([2.1,3.2])
     pathderivs=numpy.zeros_like(path)
     pathderivs[-1]=derivs
     pathderivs[0]=-derivs
     self.assertLess(diff(iisignature.logsigbackprop(derivs,path,s),pathderivs),0.00001)
     self.assertLess(diff(iisignature.logsigbackprop(derivs,path,s,"X"),pathderivs),0.00001)
     self.assertLess(diff(iisignature.sigbackprop(derivs,path,m),pathderivs),0.00001)
Beispiel #32
0
    def testjoining(self):
        numberToDo = 1
        dim = 2
        level = 2
        siglength = iisignature.siglength(dim,level)
        for fixedPoint, inputDim, fixed in [(float('nan'),dim,False),(0.1,dim - 1,True)]:
            pathLength = 10
            def makePath():
                p = numpy.random.uniform(size=(pathLength,dim))
                if fixed:
                    p[:,-1] = fixedPoint * numpy.arange(pathLength)
                return p
            paths = [makePath() for i in range(numberToDo)]
            sig = numpy.vstack([iisignature.sig(path,level) for path in paths])

            joinee = numpy.zeros((numberToDo,siglength))
            for i in range(1,pathLength):
                displacements = [path[i:(i + 1),:] - path[(i - 1):i,:] for path in paths]
                displacement = numpy.vstack(displacements)
                if fixed:
                    displacement = displacement[:,:-1]
                joinee = iisignature.sigjoin(joinee,displacement,level,fixedPoint)
            self.assertLess(diff(sig,joinee),0.0001,"fullSig matches sig" + (" with fixed Dim" if fixed else ""))

            extra = numpy.random.uniform(size=(numberToDo,inputDim))
            bumpedExtra = 1.001 * extra
            bumpedJoinee = 1.001 * joinee
            base = numpy.sum(iisignature.sigjoin(joinee,extra,level,fixedPoint))
            bump1 = numpy.sum(iisignature.sigjoin(bumpedJoinee,extra,level,fixedPoint))
            bump2 = numpy.sum(iisignature.sigjoin(joinee,bumpedExtra,level,fixedPoint))
            derivsOfSum = numpy.ones((numberToDo,siglength))
            calculated = iisignature.sigjoinbackprop(derivsOfSum,joinee,extra,
                                                     level,fixedPoint)
            self.assertEqual(len(calculated),3 if fixed else 2)
            diff1 = (bump1 - base) - numpy.sum(calculated[0] * (bumpedJoinee - joinee))
            diff2 = (bump2 - base) - numpy.sum(calculated[1] * (bumpedExtra - extra))
            #print ("\n",bump1,bump2,base,diff1,diff2)
            self.assertLess(numpy.abs(diff1),0.000001,"diff1 as expected " + (" with fixed Dim" if fixed else ""))
            self.assertLess(numpy.abs(diff2),0.00001,"diff2 as expected " + (" with fixed Dim" if fixed else ""))
            if fixed:
                bumpedFixedPoint = fixedPoint * 1.01
                bump3 = numpy.sum(iisignature.sigjoin(joinee,extra, level, bumpedFixedPoint))
                diff3 = (bump3-base - numpy.sum(calculated[2] * (bumpedFixedPoint-fixedPoint)))
                #print("\n",bump3,base, fixedPoint, bumpedFixedPoint, calculated[2])
                self.assertLess(numpy.abs(diff3),0.00001, "diff3")
Beispiel #33
0
    def testjoining(self):
        numberToDo = 1
        dim = 2
        level = 2
        siglength = iisignature.siglength(dim,level)
        for fixedPoint, inputDim, fixed in [(float('nan'),dim,False),(0.1,dim - 1,True)]:
            pathLength = 10
            def makePath():
                p = numpy.random.uniform(size=(pathLength,dim))
                if fixed:
                    p[:,-1] = fixedPoint * numpy.arange(pathLength)
                return p
            paths = [makePath() for i in range(numberToDo)]
            sig = numpy.vstack([iisignature.sig(path,level) for path in paths])

            joinee = numpy.zeros((numberToDo,siglength))
            for i in range(1,pathLength):
                displacements = [path[i:(i + 1),:] - path[(i - 1):i,:] for path in paths]
                displacement = numpy.vstack(displacements)
                if fixed:
                    displacement = displacement[:,:-1]
                joinee = iisignature.sigjoin(joinee,displacement,level,fixedPoint)
            self.assertLess(diff(sig,joinee),0.0001,"fullSig matches sig" + (" with fixed Dim" if fixed else ""))

            extra = numpy.random.uniform(size=(numberToDo,inputDim))
            bumpedExtra = 1.001 * extra
            bumpedJoinee = 1.001 * joinee
            base = numpy.sum(iisignature.sigjoin(joinee,extra,level,fixedPoint))
            bump1 = numpy.sum(iisignature.sigjoin(bumpedJoinee,extra,level,fixedPoint))
            bump2 = numpy.sum(iisignature.sigjoin(joinee,bumpedExtra,level,fixedPoint))
            derivsOfSum = numpy.ones((numberToDo,siglength))
            calculated = iisignature.sigjoinbackprop(derivsOfSum,joinee,extra,
                                                     level,fixedPoint)
            self.assertEqual(len(calculated),3 if fixed else 2)
            diff1 = (bump1 - base) - numpy.sum(calculated[0] * (bumpedJoinee - joinee))
            diff2 = (bump2 - base) - numpy.sum(calculated[1] * (bumpedExtra - extra))
            #print ("\n",bump1,bump2,base,diff1,diff2)
            self.assertLess(numpy.abs(diff1),0.000001,"diff1 as expected " + (" with fixed Dim" if fixed else ""))
            self.assertLess(numpy.abs(diff2),0.00001,"diff2 as expected " + (" with fixed Dim" if fixed else ""))
            if fixed:
                bumpedFixedPoint = fixedPoint * 1.01
                bump3 = numpy.sum(iisignature.sigjoin(joinee,extra, level, bumpedFixedPoint))
                diff3 = (bump3-base - numpy.sum(calculated[2] * (bumpedFixedPoint-fixedPoint)))
                #print("\n",bump3,base, fixedPoint, bumpedFixedPoint, calculated[2])
                self.assertLess(numpy.abs(diff3),0.00001, "diff3")
    def path_to_dyadic_sig(self, file, dyadic_level):
        """Read one sample and output a vector containing a concatenation of
		signature coefficients. The path is divided into 2^dyadic_levelsubpaths 
		and a signature vector is computed on each subpath. All vectors
		obtained in this way are then concatenated.

		Parameters
		----------
		file: str
			- If data='quick_draw', it is the string containing the raw drawing
			coordinates.
			- If data='urban_sound' or 'motion_sense', it is the path to the
			sample file.

		dyadic_level: int
			It is the level of dyadic partitions considered. The path is divided
			into 2^dyadic_level subpaths and signatures are computed on each
			subpath.

		Returns
		-------
		sig: array, shape (p)
			A signature vector containing all signature coefficients. It is of
			shape p=2^dyadic_level*self.get_sig_dimension().
		"""
        path = self.data_to_path(file)
        n_points = np.shape(path)[0]
        n_subpaths = 2**dyadic_level
        window_size = n_points // n_subpaths

        if n_subpaths > n_points:
            path = np.vstack(
                (path, np.zeros((n_subpaths - n_points, np.shape(path)[1]))))
            window_size = 1
        siglength = self.get_sig_dimension()
        sig = np.zeros(n_subpaths * siglength)
        for i in range(n_subpaths):
            if i == n_subpaths - 1:
                subpath = path[i * window_size:, :]
            else:
                subpath = path[i * window_size:(i + 1) * window_size, :]
            sig[i * siglength:(i + 1) * siglength] = isig.sig(
                subpath, self.order)
        return (sig)
Beispiel #35
0
    def doL2S(self, coropa):
        numpy.random.seed(212)
        d = 3
        m = 6
        path = numpy.random.uniform(size=(12, d))
        sig = iisignature.sig(path, m)
        s = iisignature.prepare(d, m, "S2H" if coropa else "S2")
        self.assertTrue(iisignature.info(s)["logsigtosig_supported"])
        logsig = iisignature.logsig(path, s)
        sig_ = iisignature.logsigtosig(logsig, s)
        self.assertEqual(sig.shape, sig_.shape)
        self.assertTrue(numpy.allclose(sig, sig_))

        #Like the other iisig functions, we check that derivatives
        #of logsigtosig allow sum(logsigtosig) to be backproped correctly
        #This is a boring thing to calculate, because after the first level
        #each of the log signature elements is a lie bracket and so
        #contributes a net total of 0 to the signature
        derivsOfSum = numpy.ones((sig.shape[0], ), dtype="float64")
        bumpedLogSig = 1.01 * logsig
        calculated = iisignature.logsigtosigbackprop(derivsOfSum, logsig, s)
        #wantedbackprop = allSensitivities(logsig, lambda l: iisignature.logsigtosig(l,s).sum())
        manualChange = fdDeriv(lambda x: iisignature.logsigtosig(x, s), logsig,
                               bumpedLogSig - logsig, 6)
        calculatedChange = numpy.sum((bumpedLogSig - logsig) * calculated)
        self.assertLess(numpy.abs(manualChange - calculatedChange), 0.00001)
        #beyond the first level, all zero
        if m > 1:
            self.assertLess(numpy.max(numpy.abs(calculated[d:])), 0.00001)
        self.assertEqual(calculated.shape, logsig.shape)

        #Now for a better test, we backprop sum(random*logsigtosig)
        #specifically calculate the change in it caused by bump two ways
        random = numpy.random.uniform(size=sig.shape[0], )
        derivsOfSum = random
        calculated = iisignature.logsigtosigbackprop(derivsOfSum, logsig, s)
        manualChange = fdDeriv(
            lambda x: iisignature.logsigtosig(x, s) * random, logsig,
            bumpedLogSig - logsig, 4)
        calculatedChange = numpy.sum((bumpedLogSig - logsig) * calculated)
        self.assertLess(numpy.abs(manualChange - calculatedChange), 0.00001)
        self.assertEqual(calculated.shape, logsig.shape)
Beispiel #36
0
 def testa(self):
     numpy.random.seed(2141)
     d = 5
     m = 5
     pathLength = 4
     displacement = numpy.random.uniform(size=(d))
     sig,mults = sigOfSegment(displacement,m)
     path = [numpy.zeros(d),displacement]
     for x in range(pathLength):
         displacement1 = numpy.random.uniform(size=(d))
         path.append(path[-1] + displacement1)
         sig1, mults1 = sigOfSegment(displacement1, m)
         sig, mults2 = chen(sig,sig1)
         mults+=mults1 + mults2
     #print (path)
     path = numpy.vstack(path)
     isig = iisignature.sig(path,m,1)
     for i in range(m):
         self.assertLess(diff(isig[i],sig[i]),0.00001)
     self.assertEqual(mults,iisignature.sigmultcount(path,m))
Beispiel #37
0
 def testa(self):
     numpy.random.seed(2141)
     d = 5
     m = 5
     pathLength = 4
     displacement = numpy.random.uniform(size=(d))
     sig,mults = sigOfSegment(displacement,m)
     path = [numpy.zeros(d),displacement]
     for x in range(pathLength):
         displacement1 = numpy.random.uniform(size=(d))
         path.append(path[-1] + displacement1)
         sig1, mults1 = sigOfSegment(displacement1, m)
         sig, mults2 = chen(sig,sig1)
         mults+=mults1 + mults2
     #print (path)
     path = numpy.vstack(path)
     isig = iisignature.sig(path,m,1)
     for i in range(m):
         self.assertLess(diff(isig[i],sig[i]),0.00001)
     self.assertEqual(mults,iisignature.sigmultcount(path,m))
    def path_to_sig(self, file):
        """Read one sample and output its signature with the embedding selected
		by self.embedding.

		Parameters
		----------
		file: str
			- If data='quick_draw', it is the string containing the raw drawing
			coordinates.
			- If data='urban_sound' or 'motion_sense', it is the path to the
			sample file.

		Returns
		-------
		sig: array, shape (p)
			Array containing signature coefficients computed on the embedded
			path of the sample corresponding to file.
		"""
        path = self.data_to_path(file)
        sig = isig.sig(path, self.order)
        return (sig)
Beispiel #39
0
    def test_batch(self):
        numpy.random.seed(734)
        d=2
        m=2
        n=15
        paths = [numpy.random.uniform(-1,1,size=(6,d)) for i in range(n)]
        pathArray15=stack(paths)
        pathArray1315=numpy.reshape(pathArray15,(1,3,1,5,6,d))
        sigs = [iisignature.sig(i,m) for i in paths]
        sigArray=stack(sigs)
        sigArray15=iisignature.sig(pathArray15,m)
        sigArray1315=iisignature.sig(pathArray1315,m)
        siglength=iisignature.siglength(d,m)
        self.assertEqual(sigArray1315.shape,(1,3,1,5,siglength))
        self.assertTrue(numpy.allclose(sigArray1315.reshape(n,siglength),sigs))
        self.assertEqual(sigArray15.shape,(15,siglength))
        self.assertTrue(numpy.allclose(sigArray15,sigs))

        backsigs=[iisignature.sigbackprop(i,j,m) for i,j in zip(sigs,paths)]
        backsigArray = stack(backsigs)
        backsigs1315=iisignature.sigbackprop(sigArray1315,pathArray1315,m)
        self.assertEqual(backsigs1315.shape,(1,3,1,5,6,d))
        self.assertTrue(numpy.allclose(backsigs1315.reshape(n,6,2),backsigArray))

        data=[numpy.random.uniform(size=(d,)) for i in range(n)]
        dataArray1315=stack(data).reshape((1,3,1,5,d))
        joined=[iisignature.sigjoin(i,j,m) for i,j in zip(sigs,data)]
        joined1315=iisignature.sigjoin(sigArray1315,dataArray1315,m)
        self.assertEqual(joined1315.shape,(1,3,1,5,siglength))
        self.assertTrue(numpy.allclose(joined1315.reshape(n,-1),stack(joined)))
        backjoined=[iisignature.sigjoinbackprop(i,j,k,m) for i,j,k in zip(joined,sigs,data)]
        backjoinedArrays=[stack([i[j] for i in backjoined]) for j in range(2)]
        backjoined1315=iisignature.sigjoinbackprop(joined1315,sigArray1315,dataArray1315,m)
        self.assertEqual(backjoined1315[0].shape,sigArray1315.shape)
        self.assertEqual(backjoined1315[1].shape,dataArray1315.shape)
        self.assertTrue(numpy.allclose(backjoined1315[0].reshape(n,-1),backjoinedArrays[0]))
        self.assertTrue(numpy.allclose(backjoined1315[1].reshape(n,-1),backjoinedArrays[1]))

        scaled=[iisignature.sigscale(i,j,m) for i,j in zip(sigs,data)]
        scaled1315=iisignature.sigscale(sigArray1315,dataArray1315,m)
        self.assertEqual(scaled1315.shape,(1,3,1,5,siglength))
        self.assertTrue(numpy.allclose(scaled1315.reshape(n,-1),stack(scaled)))
        backscaled=[iisignature.sigscalebackprop(i,j,k,m) for i,j,k in zip(scaled,sigs,data)]
        backscaledArrays=[stack([i[j] for i in backscaled]) for j in range(2)]
        backscaled1315=iisignature.sigscalebackprop(scaled1315,sigArray1315,dataArray1315,m)
        self.assertEqual(backscaled1315[0].shape,sigArray1315.shape)
        self.assertEqual(backscaled1315[1].shape,dataArray1315.shape)
        self.assertTrue(numpy.allclose(backscaled1315[0].reshape(n,-1),backscaledArrays[0]))
        self.assertTrue(numpy.allclose(backscaled1315[1].reshape(n,-1),backscaledArrays[1]))

        s_s=(iisignature.prepare(d,m,"cosax"),iisignature.prepare(d,m,"cosahx"))
        for type in ("c","o","s","x","a","ch","oh","sh","ah"):
            s=s_s[1 if "h" in type else 0]
            logsigs = [iisignature.logsig(i,s,type) for i in paths]
            logsigArray=stack(logsigs)
            logsigArray1315=iisignature.logsig(pathArray1315,s,type)
            self.assertEqual(logsigArray1315.shape,(1,3,1,5,logsigs[0].shape[0]),type)
            self.assertTrue(numpy.allclose(logsigArray1315.reshape(n,-1),logsigArray),type)

            if type in ("s","x","sh"):
                backlogs = stack(iisignature.logsigbackprop(i,j,s,type) for i,j in zip(logsigs,paths))
                backlogs1315 = iisignature.logsigbackprop(logsigArray1315,pathArray1315,s,type)
                self.assertEqual(backlogs1315.shape,backsigs1315.shape)
                self.assertTrue(numpy.allclose(backlogs1315.reshape(n,6,d),backlogs),type)

        a=iisignature.rotinv2dprepare(m,"a")
        rots=stack([iisignature.rotinv2d(i,a) for i in paths])
        rots1315=iisignature.rotinv2d(pathArray1315,a)
        self.assertEqual(rots1315.shape,(1,3,1,5,rots.shape[1]))
        self.assertTrue(numpy.allclose(rots1315.reshape(n,-1),rots))
Beispiel #40
0
    def dotest(self,type):
        m = 8
        nPaths = 95
        nAngles = 348
        numpy.random.seed(775)
        s = iisignature.rotinv2dprepare(m,type)
        coeffs = iisignature.rotinv2dcoeffs(s)
        angles = numpy.random.uniform(0,math.pi * 2,size=nAngles + 1)
        angles[0] = 0
        rotationMatrices = [numpy.array([[math.cos(i),math.sin(i)],[-math.sin(i),math.cos(i)]]) for i in angles]
        paths = [numpy.random.uniform(-1,1,size=(32,2)) for i in range(nPaths)]
        samePathRotInvs = [iisignature.rotinv2d(numpy.dot(paths[0],mtx),s) for mtx in rotationMatrices]

        #check the length matches
        (length,) = samePathRotInvs[0].shape
        self.assertEqual(length,sum(i.shape[0] for i in coeffs))
        self.assertEqual(length,iisignature.rotinv2dlength(s))
        if type == "a":
            self.assertEqual(length,sumCentralBinomialCoefficient(m // 2))

        self.assertLess(length,nAngles)#sanity check on the test itself

        #check that the invariants are invariant
        if 0:
            print("\n",numpy.column_stack(samePathRotInvs[0:7]))
        for i in range(nAngles):
            if 0 and diff(samePathRotInvs[0],samePathRotInvs[1 + i]) > 0.01:
                print(i)
                print(samePathRotInvs[0] - samePathRotInvs[1 + i])
                print(diff(samePathRotInvs[0],samePathRotInvs[1 + i]))
            self.assertLess(diff(samePathRotInvs[0],samePathRotInvs[1 + i]),0.01)

        #check that the invariants match the coefficients
        if 1:
            sigLevel=iisignature.sig(paths[0],m)[iisignature.siglength(2,m-1):]
            lowerRotinvs = 0 if 2==m else iisignature.rotinv2dlength(iisignature.rotinv2dprepare(m-2,type))
            #print("\n",numpy.dot(coeffs[-1],sigLevel),"\n",samePathRotInvs[0][lowerRotinvs:])
            #print(numpy.dot(coeffs[-1],sigLevel)-samePathRotInvs[0][lowerRotinvs:])
            self.assertTrue(numpy.allclose(numpy.dot(coeffs[-1],sigLevel),samePathRotInvs[0][lowerRotinvs:],atol=0.000001))

        #check that we are not missing invariants
        if type == "a":
            #print("\nrotinvlength=",length,"
            #siglength=",iisignature.siglength(2,m))
            sigOffsets = []
            for path in paths:
                samePathSigs = [iisignature.sig(numpy.dot(path,mtx),m) for mtx in rotationMatrices[1:70]]
                samePathSigsOffsets = [i - samePathSigs[0] for i in samePathSigs[1:]]
                sigOffsets.extend(samePathSigsOffsets)
            #print(numpy.linalg.svd(numpy.row_stack(sigOffsets))[1])
            def split(a, dim, level):
                start = 0
                out = []
                for m in range(1,level + 1):
                    levelLength = dim ** m
                    out.append(a[:,start:(start + levelLength)])
                    start = start + levelLength
                assert(start == a.shape[1])
                return out
            allOffsets = numpy.row_stack(sigOffsets)
            #print (allOffsets.shape)
            splits = split(allOffsets,2,m)
            #print()
            rank_tolerance = 0.01 # this is hackish
            #print
                                             #([numpy.linalg.matrix_rank(i.astype("float64"),rank_tolerance)
                                                                              #for
                                                                              #i in splits])
                                                                              #print ([i.shape for i in splits])
                                                                              #print(numpy.linalg.svd(splits[-1])[1])

            #sanity check on the test
            self.assertLess(splits[-1].shape[1],splits[0].shape[0])
            totalUnspannedDimensions = sum(i.shape[1] - numpy.linalg.matrix_rank(i,rank_tolerance) for i in splits)
            self.assertEqual(totalUnspannedDimensions,length)

        if 0: #This doesn't work - the rank of the whole thing is less than
        #sigLength-totalUnspannedDimensions, which suggests that there are
        #inter-level dependencies,
        #even though the shuffle product dependencies aren't linear. 
        #I don't know why this is.
            sigLength = iisignature.siglength(2,m)
            numNonInvariant = numpy.linalg.matrix_rank(numpy.row_stack(sigOffsets))

            predictedNumberInvariant = sigLength - numNonInvariant
            print(sigLength,length,numNonInvariant)
            self.assertLess(sigLength,nAngles)
            self.assertEqual(predictedNumberInvariant,length)
Beispiel #41
0
from iisignature_theano import LogSig, Sig


#1: SETUP VARIABLES
dim=2
level=3
pathlength=4
timedim=False
useLogSig = True
s=iisignature.prepare(dim,level)

numpy.random.seed(51)
target = numpy.random.uniform(size=(pathlength,dim)).astype("float32")
#target = numpy.cumsum(2*(target-0.5),0)#makes it more random-walk-ish, less like a scribble

targetSig = iisignature.logsig(target,s) if useLogSig else iisignature.sig(target,level)
start = numpy.random.uniform(size=(pathlength,dim)).astype("float32")
start[0,:] = target[0,:]
learnable_mask = numpy.ones((pathlength,dim)).astype("float32")
learnable_mask[0,:]=0 #to stop the starting point being modified
if timedim:
    for i in six.moves.xrange(pathlength):
        target[i,0]=start[i,0]=i*0.2
        learnable_mask[i,0]=0
learning_rate_decay = 1.003
initial_learning_rate = 1.2
momentum = 0.95

#2: DEFINE THEANO STUFF

learning_rate = theano.shared(numpy.float32(initial_learning_rate),"learning_rate")
 def forward(self,X):
     result=iisignature.sig(X.numpy(), self.m)
     self.save_for_backward(X)
     return torch.FloatTensor(result)
 def perform(self,node,inputs_storage,outputs_storage):
     x=inputs_storage[0]
     m=inputs_storage[1]
     outputs_storage[0][0]=iisignature.sig(x,m)
Beispiel #44
0
#does not grow. Even a tiny memory leak becomes very visible e.g. in htop.

#add the parent directory, so we find our iisignature build if it was built --inplace
sys.path.append(os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
import iisignature

length = 20
dim=3
level=2
npaths=3
paths_ = np.random.uniform(size=(npaths,length,dim))
scale_ = np.random.uniform(size=(npaths,dim))
initialsigs_ = np.random.uniform(size=(npaths,iisignature.siglength(dim,level)))
p=iisignature.prepare(dim,level,"cosx")
while 0:
    iisignature.sig(paths[0],level)
for i in range(10**10):
    #copy major parts of the input data, in case we are leaking references to it
    paths=paths_[:]
    increment=scale=scale_[:]
    initialsigs=initialsigs_[:]
    iisignature.sigjoin(initialsigs,scale,level)
    iisignature.sigscale(initialsigs,scale,level)
    iisignature.sigjoinbackprop(initialsigs,initialsigs,scale,level)
    iisignature.sigscalebackprop(initialsigs,initialsigs,scale,level)
    iisignature.sig(paths[0,:,:],level)
    iisignature.sigbackprop(initialsigs[0,:],paths[0,:,:],level)
    #iisignature.sigjacobian(paths[0,:,:],level)
    #iisignature.prepare(dim,level,"cosx")#much slower than other functions
    iisignature.logsig(paths[0,:,:],p,"c")
    iisignature.logsig(paths[0,:,:],p,"o")
def _sigImp(x,m):
    return iisignature.sig(x,m)
def stream2sig(path, m):
    return np.hstack([1.0, iisignature.sig(path,m)])
Beispiel #47
0
total=[[(0,0)]]
for i in range(1,len(seq)):
    s={seq[i-1],seq[i]}
    if s in [{0,1},{2,3}]:
        raise RuntimeError("treelike")
for i in seq:
    offset=np.array([0,0])#change this to [2,0] to display petals separately
    startpoint=total[-1][-1]+offset
    if i in [0,1,2,3]:
        total.append(startpoint+petals[i])
    else:
        raise "whoops"

path=np.vstack(total)
print("Maximum absolute value of sig elements in each level:")
for i,j in enumerate(iisignature.sig(path,14,1)):
    print("level {:2}:".format(i+1),np.max(np.abs(j)))

if 0:
    import matplotlib.pyplot as plt
    import matplotlib as mpl
    #colors = np.arange(path.
    #plt.plot(path[:,0],path[:,1])
    plt.scatter(path[:,0],path[:,1],c=np.arange(path.shape[0]),
                norm=mpl.colors.Normalize(vmin=0,vmax=path.shape[0]))
    plt.show()




#A sort of Thue Morse chain of fig eights