Closed STARainZ closed 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.
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.
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: @.***>
Thanks, added.
Also raised the issue on pytorch: https://github.com/pytorch/pytorch/issues/118269. A like there wouldn't hurt for visibility.
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.