Good day all,
I’m very sorry for constantly asking question. I’m actually a student and trying to learn how to use pytorch very well for my research in deep learning & signal processing. I have tried all possible ways to make the tensors’ dimensions compatible but couldn’t.
import os
import torch
from torch.autograd import Variable
import numpy as np
SNR_dB_min = 8
SNR_dB_max = 13
rho = 0.55
seed = 2
N = 60
K = 30
batch_size = 5000
Random_Channel = 'True'
dtype = torch.FloatTensor
def vec_multiplication(W, b):
#A = torch.mm(W, b.unsqueeze(2))
#C = A.unsqueeze(-1)
A = np.dot(W, np.expand_dims(b, 2)).astype(np.float32)
C = np.squeeze(A, axis = -1)
C = torch.from_numpy(C)
return C
class Modulator(object):
def __init__(self, mod_type, K):
# Create constellation
self.mod_type = mod_type
self.K = K
# Set modulation type
if (mod_type not in ['BPSK', '4PAM']):
raise(Exception('Modulator: Unknown modulation format'))
if (self.mod_type == 'BPSK'):
self.constellation = np.array([-1.0, 1.0])
self.constellation = (torch.from_numpy(self.constellation)).type(dtype)
elif (self.mod_type == '4PAM'):
self.constellation = np.array([-3.0, -1.0, 1.0, 3.0])
self.constellation = (torch.from_numpy(self.constellation)).type(dtype)
self.constellation_size = self.constellation.shape[0]
# Normalize constellation to unit power and convert to tensor
self.constellation /= torch.sqrt(torch.mean(torch.abs(self.constellation)**2))
#self.constellation = torch.Variable(self.constellation, requires_grad = False)
return
def random_indices(self, batch_size):
'''Generate random constellation symbol indices'''
indices = torch.FloatTensor(batch_size, self.K).uniform_(0, self.constellation_size).int()
return indices
def modulate(self, indices):
'''Map indices to constellation symbols'''
x = self.constellation[indices.long()]
return x
def gen_toeplitz_channel(self, N, rho):
'''Generate a random channel matrix with Toeplitz Gramian H'H
as done in the original paper
'''
HtH = np.zeros([self.K, self.K])
for i in range(self.K):
for j in range(self.K):
HtH[i,j] = rho ** np.abs(i-j)
T = np.random.normal(size=[N,N])
V, D, V = np.linalg.svd(HtH)
U = np.linalg.svd(np.dot(T,np.transpose(T)))
H = np.dot(np.dot(U[0][:,0:self.K],np.diagflat(np.sqrt(D))),V)
H = torch.from_numpy(H)
return H
def channel(self, x, N, snr_db_min, snr_db_max, rho, random_channel=False):
'''Simulate transmission over a random or static channel with SNRs draw uniformly
from the range [snr_db_min, snr_db_max]
'''
# Derive parameters from inputs
batch_size = x.shape[0]
# Channel matrices
if random_channel:
H = np.random.normal(0.0,1/np.sqrt(N), [batch_size, N, self.K]).astype(np.float32)
H = torch.from_numpy(H)
else:
H = (self.gen_toeplitz_channel(N, rho)).unsqueeze(0)
H = H.repeat([batch_size, 1, 1])
# Random noise
snr_db = torch.FloatTensor(batch_size, 1).uniform_(SNR_dB_min, SNR_dB_max).type(dtype)
w = torch.randn([batch_size, N]).type(dtype)
w = torch.mul(w, torch.pow(10.0, -snr_db/20.0))
# Channel output
y = vec_multiplication(H, x) + w
#y = torch.mm(torch.squeeze(H,-1), x) + w
return y, H
def demodulate(self, y):
'''Find closest constellation symbols in Tensor'''
shape = y.shape
y = y.reshape([-1, 1])
constellation = self.constellation.reshape([1, self.constellation_size])
indices = torch.argmin((torch.abs(y - constellation)), 1).type(dtype)
indices = indices.reshape(shape).long()
return indices
# Generate random transmit signals
mod = Modulator('BPSK', K)
indices = mod.random_indices(batch_size)
x = mod.modulate(indices)
# Send x through the channel
y, H = mod.channel(x, N, SNR_dB_min, SNR_dB_max, rho, random_channel='Random_Channel')
def zf(y, H):
'''Zero-Forcing Detector
Inputs:
y: Tensor of shape [batch_size, N]
H: Tensor of shape [batch_size, N, K]
mod: Instance of the modulator class
Outputs:
indices: Tensor of shape [batch_size, K]
'''
# Projected channel output
Hty = vec_multiplication(torch.transpose(H, 0, 2, 1), y)
#Hty = torch.mm(torch.transpose(H, 0, 2, 1), y)
# Gramian of transposed channel matrix
HtH = torch.mm(H, H.t())
# Inverse Gramian
HtHinv = torch.inverse(HtH)
# ZF Detector
x = vec_multiplication(HtHinv, Hty)
#x = torch.mm(HtHinv, Hty)
return x
When the code is run, it returns the following error:
Traceback (most recent call last):
File "/Users/Abdullahi/Desktop/DETNET_INCOMPLETE/signal_modulation.py", line 120, in <module>
y, H = mod.channel(x, N, SNR_dB_min, SNR_dB_max, rho, random_channel='Random_Channel')
File "/Users/Abdullahi/Desktop/DETNET_INCOMPLETE/signal_modulation.py", line 100, in channel
y = vec_multiplication(H, x) + w
RuntimeError: The size of tensor a (5000) must match the size of tensor b (60) at non-singleton dimension 2
Thank you very much.