Search code examples
pythonfftnormalizationcomplex-numbers

Normalize vectors in the complex space : mean=0 and std-dev=1/sqrt(n)


I have a Vector Or bunch of vectors (stored in 2D array, by rows)

The vectors are generated as :

MEAN=0, STD-DEV=1/SQRT(vec_len)

and before or after operations have to be normalized in the same form

I want to normalize them in the complex space. Here is the wrapper of a function:

@staticmethod
def fft_normalize(x, dim=DEF_DIM):
    cx = rfft(x, dim=dim)
    ....
    rv = irfft(cx_proj, dim=dim)
    return rv

help me fill the dots.

Here is the real-value normalization that I use.

@staticmethod 
def normalize(a, dim=DEF_DIM): 
    norm=torch.linalg.norm(a,dim=dim)
    # if torch.eq(norm,0) : return torch.divide(a,st.MIN)
    if dim is not None : norm = norm.unsqueeze(dim)
    return torch.divide(a,norm)

In [70]: st.normalize(x + 3)
Out[70]: 
([[0.05, 0.04, 0.05,  ..., 0.04, 0.04, 0.04],
 [0.04, 0.04, 0.05,  ..., 0.05, 0.04, 0.05],
 [0.05, 0.04, 0.05,  ..., 0.04, 0.05, 0.04]])

In [71]: st.normalize(x + 5)
Out[71]: 
([[0.05, 0.04, 0.05,  ..., 0.04, 0.04, 0.04],
 [0.04, 0.04, 0.05,  ..., 0.05, 0.04, 0.04],
 [0.05, 0.04, 0.04,  ..., 0.04, 0.05, 0.04]])


In [73]: st.normalize(x + 5).len()
Out[73]: ([1.00, 1.00, 1.00])

In [74]: st.normalize(x + 3).len()
Out[74]: ([1., 1., 1.])

In [75]: st.normalize(x).len()
Out[75]: ([1.00, 1.00, 1.00])

#bad, need normalization
In [76]: (x + 3).len()
Out[76]: ([67.13, 67.13, 67.13])


@staticmethod
def len(a,dim=DEF_DIM): return torch.linalg.norm(a,dim=dim) 

I did not want to post this so not to influence possible better solution.. So here is one my attempts .. parts I borrowed from what I found.

This only works for 1D vectors ;(

@staticmethod
def fft_normalize(x, dim=DEF_DIM):# Normalize a vector x in complex domain.
    c = rfft(x,dim=dim)
    ri = torch.vstack([c.real, c.imag])
    norm = torch.abs(c)
    print(norm.shape, ri.shape)
    # norm = torch.linalg.norm(ri, dim=dim)
    # if dim is not None : norm = norm.unsqueeze(dim)

    if torch.any(torch.eq(norm,0)): norm[torch.eq(norm,0)] = st.MIN #!fixme
    ri= torch.divide(ri,norm) #2D fails here
    c_proj = ri[0,:] + 1j * ri[1,:]
    rv = irfft(c_proj, dim=dim)

    return rv

adapted the solution of Thibault Cimic ... seems to work for 1D vectors, but not for 2D

@staticmethod
def fft_normalize(x, dim=DEF_DIM, dot_dim=None):# Normalize a vector x in complex domain.
    c = rfftn(x,dim=dim)
    c_conj = torch.conj(c)
    if dot_dim is None : dot_dim = st.dot_dims(c, c_conj)
    c_norm = torch.sqrt(torch.tensordot(c, c_conj, dims=dot_dim))
    c_proj = torch.divide(c, c_norm)
    rv = irfftn(c_proj, dim=dim)
    return rv       

Solution

  • I'm guessing you want to normalize with the norm associated to the natural complex inner product. So is that what you're trying to do :

    def fft_normalize(x, dim=DEF_DIM):# Normalize a vector x in complex domain.
        c = rfft(x,dim=dim)
        c_norm = math.sqrt(c.dot(numpy.conjugate(c)))
        c_proj = c/c_norm
        rv = irfft(c_proj, dim=dim)
       return rv