utcsilab / score-based-channels

Source code for paper "MIMO Channel Estimation using Score-Based Generative Models", published in IEEE Transactions on Wireless Communications.
Other
63 stars 23 forks source link

About getting the received signal val_Y in test_score.py #6

Closed STARainZ closed 9 months ago

STARainZ commented 9 months ago

Hello,

Thanks for the excellent work! I have a question about the way you generate val_Y in the following code:

https://github.com/utcsilab/score-based-channels/blob/199792eb8eeb6ce2eb1e7e6215d1798ec4ea07f7/test_score.py#L120-L122

I'm wondering whether it should be np.sqrt(local_noise/2) in L122 instead since localnoise is the variance of complex-valued noise. Should the standard deviation of the real and imaginary parts be $\sigma{\text{pilot}}/\sqrt{2}$, as shown in test_ml.py:

https://github.com/utcsilab/score-based-channels/blob/199792eb8eeb6ce2eb1e7e6215d1798ec4ea07f7/test_ml.py#L125-L129

Thank you.

mariusarvinte commented 9 months ago

Thank you for noticing this very subtle aspect - while it seems incorrect at a first look, there is an undocumented behavior of the PyTorch torch.randn and torch.randn_like functions that makes this correct.

Whenever these functions are used with complex data types they will sample from the unit power complex Gaussian distribution with real and imaginary powers 1/2 and standard deviations 1/sqrt(2) each.

This can be verified by running the following basic snippet:

import torch
import numpy as np

desired_power = 4.2

y_cplx_native = np.sqrt(desired_power) * torch.randn(1000, 1000, dtype=torch.complex64)
print('Complex signal power using native complex: ', torch.var(y_cplx_native))
print('Real part signal power using native complex: ', torch.var(torch.real(y_cplx_native)))
print('Imag part signal power using native complex: ', torch.var(torch.imag(y_cplx_native)))

y_cplx_from_reals = np.sqrt(desired_power) * 1/np.sqrt(2) * (torch.randn(1000, 1000, dtype=torch.float32) + 1j * torch.randn(1000, 1000, dtype=torch.float32))
print('Complex signal power using manual complex: ', torch.var(y_cplx_from_reals ))
print('Real part signal power using manual complex: ', torch.var(torch.real(y_cplx_from_reals)))
print('Imag part signal power using manual complex: ', torch.var(torch.imag(y_cplx_from_reals)))

Should give correct results in both cases, such as:

Complex signal power using native complex:  tensor(4.2006)
Real part signal power using native complex:  tensor(2.1028)
Imag part signal power using native complex:  tensor(2.0978)

Complex signal power using manual complex:  tensor(4.2078)
Real part signal power using manual complex:  tensor(2.1055)
Imag part signal power using manual complex:  tensor(2.1023)

This can also be verified for torch.randn_like - whenever a torch.complex variable is used as input, it will correctly sample from the unit power complex Gaussian. We used the native complex sampling in test_score.py and the "manual" construction in test_ml.py, so the definitions should be consistent.

It took us a while to realize this ourselves through trial and error. Let us know if you have any more questions.

STARainZ commented 9 months ago

Thanks for the reply! I have checked and found that torch.randn_like samples from a complex Gaussian distribution with variance 1 when the input is complex-valued. Therefore, the code is correct.

jtamir commented 9 months ago

Marius, can you add a comment in the code there? Great attention to detail !

Jon www.jtsense.com


From: Xingyu Zhou @.> Sent: Thursday, January 25, 2024 12:09:02 AM To: utcsilab/score-based-channels @.> Cc: Subscribed @.***> Subject: Re: [utcsilab/score-based-channels] About getting the received signal val_Y in test_score.py (Issue #6)

Thanks for the reply! I have checked and found that torch.randn_like samples from a complex Gaussian distribution with variance 1 when the input is complex-valued. Therefore, the code is correct.

— Reply to this email directly, view it on GitHubhttps://github.com/utcsilab/score-based-channels/issues/6#issuecomment-1909416643, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ACCQC23UFTT7WYCELRDINV3YQHZH5AVCNFSM6AAAAABCDZOKV2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMBZGQYTMNRUGM. You are receiving this because you are subscribed to this thread.Message ID: @.***>

mariusarvinte commented 9 months ago

Thanks, added.

Also raised the issue on pytorch: https://github.com/pytorch/pytorch/issues/118269. A like there wouldn't hurt for visibility.