SGW icon indicating copy to clipboard operation
SGW copied to clipboard

fails with different number of samples in source and target

Open bionicles opened this issue 5 years ago • 4 comments

Dear Tituoan,

thanks for making this -- I'm adding FGW to make sliced FGW

for whatever reason, this fails right now:

s_samples, t_samples = 100, 200
n_projections = 5
dimensionality = 8
Xs=np.random.rand(s_samples, dimensionality)
Xt=np.random.rand(t_samples, dimensionality)
P=np.random.randn(dimensionality, n_projections)
%%time
sgw_cpu(Xs,Xt,P=P)


---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<timed eval> in <module>

~/hax/SGW/lib/sgw_numpy.py in sgw_cpu(xs, xt, nproj, tolog, P)
     66         log['gw_1d_details']=log_gw1d
     67     else:
---> 68         d=gromov_1d(xsp,xtp,tolog=False)
     69 
     70     if tolog:

~/hax/SGW/lib/sgw_numpy.py in gromov_1d(xs, xt, tolog, fast)
    170         xt_asc=np.sort(xt,axis=0)
    171         xt_desc=np.sort(xt,axis=0)[::-1]
--> 172         l1=_cost(xs2,xt_asc,tolog=tolog)
    173         l2=_cost(xs2,xt_desc,tolog=tolog)
    174     toreturn=np.mean(np.minimum(l1,l2))

~/hax/SGW/lib/sgw_numpy.py in _cost(xsp, xtp, tolog)
    109         Y4=np.sum(xt**4)
    110 
--> 111         xxyy_=np.sum((xs**2)*(xt**2))
    112         xxy_=np.sum((xs**2)*(xt))
    113         xyy_=np.sum((xs)*(xt**2))

ValueError: operands could not be broadcast together with shapes (100,) (200,) 
xs=torch.from_numpy(Xs).to(torch.float32).to('cuda')
xt=torch.from_numpy(Xt).to(torch.float32).to('cuda')
device = 'cuda'
%%time
sgw_gpu(xs,xt,device,P=torch.from_numpy(P).to(torch.float32))


----------------------------------------
xs origi dim : torch.Size([100, 8])
xt origi dim : torch.Size([200, 8])
dim_p : 8
dim_d : 8
random_projection_dim :  8
projector dimension :  torch.Size([2, 5])
xs2 dim : torch.Size([100, 8])
xt2 dim : torch.Size([200, 8])
xs_tmp dim : torch.Size([100, 8])
xt_tmp dim : torch.Size([200, 8])
----------------------------------------
size mismatch, m1: [100 x 8], m2: [2 x 5] at /opt/conda/conda-bld/pytorch_1587428266983/work/aten/src/THC/generic/THCTensorMathBlas.cu:283
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
~/hax/SGW/lib/sgw_pytorch.py in sink_(xs, xt, device, nproj, P)
    242     try:
--> 243 
    244         xsp = torch.matmul(xs2, p.to(device))

RuntimeError: size mismatch, m1: [100 x 8], m2: [2 x 5] at /opt/conda/conda-bld/pytorch_1587428266983/work/aten/src/THC/generic/THCTensorMathBlas.cu:283

During handling of the above exception, another exception occurred:

BadShapeError                             Traceback (most recent call last)
<timed eval> in <module>

~/hax/SGW/lib/sgw_pytorch.py in sgw_gpu(xs, xt, device, nproj, tolog, P)
     61         xsp, xtp = sink_(xs, xt, device, nproj, P)
     62         ed = time.time()
---> 63         log['time_sink_'] = ed-st
     64     else:
     65         xsp, xtp = sink_(xs, xt, device, nproj, P)

~/hax/SGW/lib/sgw_pytorch.py in sink_(xs, xt, device, nproj, P)
    257         print('xt_tmp dim :', xt2.shape)
    258         print('----------------------------------------')
--> 259         print(error)
    260         raise BadShapeError
    261 

BadShapeError: 

bionicles avatar May 24 '20 19:05 bionicles

Dear Bion,

Indeed this is a problem but the main reason is that GW1D is not defined for distributions with not the same number of atoms yet. The reason is that there is not theoretical guaranties that we recover de GW distance in this case with our procedure when m is different from n (see original paper). We are working to prove this/or to find a way to recover a solution that is not so far.

In short we are planning to make some heuristic so as to compute gw1D for distributions that do not share the same number of samples.

Best regards

Titouan

Le dim. 24 mai 2020 à 21:56, bion howard [email protected] a écrit :

Dear Tituoan,

thanks for making this -- I am adapting it to include your cool FGW distance to make SFGW

for whatever reason, this fails right now:

s_samples, t_samples = 100, 200 n_projections = 5 dimensionality = 8 Xs=np.random.rand(s_samples, dimensionality) Xt=np.random.rand(t_samples, dimensionality) projections=np.random.randn(dimensionality, n_projections)

%%time sgw_cpu(Xs,Xt,P=projections)


ValueError Traceback (most recent call last) in

~/hax/SGW/lib/sgw_numpy.py in sgw_cpu(xs, xt, nproj, tolog, P) 66 log['gw_1d_details']=log_gw1d 67 else: ---> 68 d=gromov_1d(xsp,xtp,tolog=False) 69 70 if tolog:

~/hax/SGW/lib/sgw_numpy.py in gromov_1d(xs, xt, tolog, fast) 170 xt_asc=np.sort(xt,axis=0) 171 xt_desc=np.sort(xt,axis=0)[::-1] --> 172 l1=_cost(xs2,xt_asc,tolog=tolog) 173 l2=_cost(xs2,xt_desc,tolog=tolog) 174 toreturn=np.mean(np.minimum(l1,l2))

~/hax/SGW/lib/sgw_numpy.py in cost(xsp, xtp, tolog) 109 Y4=np.sum(xt**4) 110 --> 111 xxyy=np.sum((xs2)*(xt2)) 112 xxy_=np.sum((xs2)(xt)) 113 xyy_=np.sum((xs)(xt2))

ValueError: operands could not be broadcast together with shapes (100,) (200,)

xs=torch.from_numpy(Xs).to(torch.float32).to('cuda') xt=torch.from_numpy(Xt).to(torch.float32).to('cuda') print(xt.is_cuda)

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

device = 'cuda'

%%time sgw_gpu(xs,xt,device,P=torch.from_numpy(P).to(torch.float32))


xs origi dim : torch.Size([100, 8]) xt origi dim : torch.Size([200, 8]) dim_p : 8 dim_d : 8 random_projection_dim : 8 projector dimension : torch.Size([2, 5]) xs2 dim : torch.Size([100, 8]) xt2 dim : torch.Size([200, 8]) xs_tmp dim : torch.Size([100, 8]) xt_tmp dim : torch.Size([200, 8])

size mismatch, m1: [100 x 8], m2: [2 x 5] at /opt/conda/conda-bld/pytorch_1587428266983/work/aten/src/THC/generic/THCTensorMathBlas.cu:283

RuntimeError Traceback (most recent call last) ~/hax/SGW/lib/sgw_pytorch.py in sink_(xs, xt, device, nproj, P) 242 try: --> 243 244 xsp = torch.matmul(xs2, p.to(device))

RuntimeError: size mismatch, m1: [100 x 8], m2: [2 x 5] at /opt/conda/conda-bld/pytorch_1587428266983/work/aten/src/THC/generic/THCTensorMathBlas.cu:283

During handling of the above exception, another exception occurred:

BadShapeError Traceback (most recent call last) in

~/hax/SGW/lib/sgw_pytorch.py in sgw_gpu(xs, xt, device, nproj, tolog, P) 61 xsp, xtp = sink_(xs, xt, device, nproj, P) 62 ed = time.time() ---> 63 log['time_sink_'] = ed-st 64 else: 65 xsp, xtp = sink_(xs, xt, device, nproj, P)

~/hax/SGW/lib/sgw_pytorch.py in sink_(xs, xt, device, nproj, P) 257 print('xt_tmp dim :', xt2.shape) 258 print('----------------------------------------') --> 259 print(error) 260 raise BadShapeError 261

BadShapeError:

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/tvayer/SGW/issues/3, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEDBMDIH7DBDUMLSMIPO4W3RTF3YTANCNFSM4NJAWA4Q .

tvayer avatar May 24 '20 20:05 tvayer

Is the problem we require diagonal or anti-diagonal assignment which only works when n=m?

bionicles avatar May 24 '20 20:05 bionicles

https://dl.acm.org/doi/pdf/10.1145/3306346.3323021 this seems relevant, a different way to assign the atoms

code in c++, alas! https://github.com/nbonneel/spot/blob/master/UnbalancedSliced.cpp

bionicles avatar May 24 '20 20:05 bionicles

Yes exactly it is beacause the assignement problem. And yes this paper introduce some works to circumvent this limitation for the sliced wasserstein distance! however it remains to be proved for the gromov-wasserstein distance..

tvayer avatar May 25 '20 08:05 tvayer