├── data └── hint.txt ├── Images ├── direct.png ├── model.png ├── completion.png └── ganstructure.png ├── README.md ├── BEGAN ├── complete.py ├── train.py └── model.py └── CNN └── cnn.py /data/hint.txt: -------------------------------------------------------------------------------- 1 | Please put dataset files with *.mat type here -------------------------------------------------------------------------------- /Images/direct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/safarisadegh/UL2DL/HEAD/Images/direct.png -------------------------------------------------------------------------------- /Images/model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/safarisadegh/UL2DL/HEAD/Images/model.png -------------------------------------------------------------------------------- /Images/completion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/safarisadegh/UL2DL/HEAD/Images/completion.png -------------------------------------------------------------------------------- /Images/ganstructure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/safarisadegh/UL2DL/HEAD/Images/ganstructure.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deep UL2DL 2 | ## Source code of: 3 | Deep UL2DL: Channel Knowledge Tranfer from Uplink to Downlink https://arxiv.org/abs/1812.07518 4 | 5 | Published version (IEEE Open Journal of Vehicular Technology): https://ieeexplore.ieee.org/document/8944056 6 | 7 | ## Abstract 8 | 9 | Knowledge of the channel state information (CSI) at the transmitter side is one of the primary sources of information that can be used for efficient allocation of wireless resources. Obtaining Down-Link (DL) CSI in FDD systems from Up-Link (UL) CSI is not as straightforward as TDD systems, and so usually users feedback the DL-CSI to the transmitter. To remove the need for feedback (and thus having less signaling overhead), several methods have been studied to estimate DL-CSI from UL-CSI. In this paper, we propose a scheme to infer DL-CSI by observing UL-CSI in which we use two recent deep neural network structures: a) Convolutional Neural network and b) Generative Adversarial Networks. The proposed deep network structures are first learning a latent model of the environment from the training data. Then, the resulted latent model is used to predict the DL-CSI from the UL-CSI. We have simulated the proposed scheme and evaluated its performance in a few network settings. 10 | 11 | ![UL to DL knowledge transfer procedure](Images/model.png?raw=true "UL to DL knowledge transfer procedure") 12 | 13 | 14 | ## Direct Approach 15 | 16 | ![Direct approach:](Images/direct.png?raw=true "Direct approach:") 17 | 18 | ## Generative Approach 19 | 20 | ![Generative Approach Training](Images/ganstructure.png?raw=true "Generative Approach Training") 21 | 22 | 23 | ![Generative Approach Image Completion](Images/completion.png?raw=true "Generative Approach Image Completion") 24 | 25 | ## Datasets 26 | To access datasets contact us: msadeq.safari@gmail.com 27 | 28 | ## Aknowledgement 29 | Thanks To https://github.com/JorgeCeja/began-tensorflow for BEGAN code 30 | -------------------------------------------------------------------------------- /BEGAN/complete.py: -------------------------------------------------------------------------------- 1 | # @Author: Mohammad Sadegh Safari By Thanks to : Brandon Amos 2 | 3 | import matplotlib.pyplot as plt 4 | from model import BEGAN 5 | import tensorflow as tf 6 | import numpy as np 7 | import math 8 | import os 9 | import scipy.io as sio 10 | 11 | 12 | def load_dataset(): 13 | hdict = sio.loadmat('../data/my_spec_ETU.mat') 14 | h = hdict['my_spec_ETU'] 15 | 16 | # if you use EVA dataset uncomment below lines and comment above lines 17 | 18 | # hdict = sio.loadmat('../data/My_perfect_H_12.mat') 19 | # h = hdict['My_perfect_H'] 20 | 21 | # uplink channel as input 22 | csi_ul = np.empty(shape=(5000, 72, 14, 2), dtype=np.float32) 23 | csi_ul[:, :, :, 0] = np.real(h[35000:, :, :]) 24 | csi_ul[:, :, :, 1] = np.imag(h[35000:, :, :]) 25 | print(np.mean(csi_ul)) 26 | print(np.max(csi_ul)) 27 | print(np.max(-csi_ul)) 28 | csi_ul = csi_ul/3.3 29 | return csi_ul 30 | 31 | 32 | def save_image(generated_images, name): 33 | out = 1.0j * np.squeeze(generated_images[:, :, :, 1]) 34 | out += np.squeeze(generated_images[:, :, :, 0]) 35 | 36 | if not os.path.isdir('images'): 37 | os.makedirs('images') 38 | 39 | sio.savemat('images/' + name + '.mat', {'h': out}) 40 | 41 | 42 | def train(model, epoch_count, batch_size, z_dim, star_learning_rate, beta1, beta2, real_images): 43 | input_real, input_z, lrate, k_t, decay = model.model_inputs(72, 14, 2, z_dim) 44 | 45 | d_loss, g_loss, d_real, d_fake, generated_images, generated_images_recon, input_image, input_image_recon = model.model_loss( 46 | input_real, input_z, 2, z_dim, k_t, decay) 47 | 48 | d_opt, g_opt, d_train_opt_on_d, d_train_opt_on_g = model.model_opt(d_loss, g_loss,d_real, d_fake, lrate, beta1, beta2) 49 | 50 | 51 | 52 | # added for completion 53 | lambda_val = 0.01 54 | mask = tf.placeholder(tf.float32, [None] + [72, 14, 2], name='mask') 55 | contextual_loss = tf.reduce_sum( 56 | tf.contrib.layers.flatten( 57 | tf.abs(tf.multiply(mask, generated_images) - tf.multiply(mask, input_image))), 1) 58 | mse = 2*tf.reduce_mean(tf.square(tf.multiply(1 - mask, generated_images) - tf.multiply(1 - mask, input_image))) 59 | 60 | perceptual_loss = g_loss 61 | complete_loss = contextual_loss + lambda_val * perceptual_loss 62 | grad_complete_loss = tf.gradients(complete_loss, input_z) 63 | 64 | config = {} 65 | config['maskType'] = 'csi' 66 | mask_ = np.ones([72, 14, 2]) 67 | mask_[36:, :, :] = 0 68 | mask_[:36, 7:, :] = 0 69 | 70 | batch_mask = np.resize(mask_, [batch_size, 72, 14, 2]) 71 | zhats = np.random.uniform(-1, 1, size=(batch_size, 64)) 72 | batch_images = load_dataset()[:batch_size, :, :, :] 73 | 74 | learning_rate = star_learning_rate 75 | iter = 0 76 | 77 | epoch_drop = 3 78 | 79 | lam = 1e-3 80 | gamma = .5 81 | k_curr = 0.0 82 | 83 | test_z = np.random.uniform(-1, 1, size=(batch_size, z_dim)) 84 | checkpoint_dir = 'checkpoint' 85 | saver = tf.train.Saver() 86 | 87 | # restore previous model if there is one 88 | ckpt = tf.train.get_checkpoint_state(checkpoint_dir) 89 | 90 | with tf.Session() as sess: 91 | sess.run(tf.global_variables_initializer()) 92 | if ckpt and ckpt.model_checkpoint_path: 93 | print("Restoring previous model...") 94 | try: 95 | saver.restore(sess, ckpt.model_checkpoint_path) 96 | print("Model restored") 97 | except: 98 | print("Could not restore model") 99 | pass 100 | 101 | vel = 0 102 | momentum = 0.9 103 | for i in range(2000): 104 | 105 | fd = { 106 | input_z: zhats, 107 | mask: batch_mask, 108 | input_real: batch_images, 109 | lrate: learning_rate, 110 | k_t: 0, 111 | decay: 0 112 | } 113 | run = [complete_loss, grad_complete_loss, generated_images] 114 | loss, g, G_imgs = sess.run(run, feed_dict=fd) 115 | 116 | if i % 20 is 0: 117 | print("loss in iteration: " + str(i) + " is: " + str(np.mean(loss))) 118 | print('contextual loss:', sum(sess.run(contextual_loss, feed_dict=fd)) / batch_size) 119 | print('perceptual loss:', sess.run(perceptual_loss, feed_dict=fd)) 120 | print('.mse: ', sess.run(mse, feed_dict=fd)) 121 | if i % 500 is 0: 122 | learning_rate = learning_rate / 2 123 | 124 | prev_vel = np.copy(vel) 125 | vel = momentum * vel - learning_rate * g[0] 126 | zhats += -momentum * prev_vel + (1 + momentum) * vel 127 | zhats = np.clip(zhats, -1, 1) 128 | 129 | if i % 500 == 499: 130 | 131 | created_images = G_imgs 132 | save_image(created_images, "created_images"+str(i)) 133 | 134 | masked_images = np.multiply(batch_images, batch_mask) 135 | 136 | inv_mask_ = 1 - mask_ 137 | 138 | inv_batch_mask = np.resize(inv_mask_, [batch_size] + [72, 14, 2]) 139 | inv_masked_images = np.multiply(G_imgs, inv_batch_mask) 140 | 141 | Recons_img = inv_masked_images + masked_images 142 | save_image(Recons_img, "completed_images"+str(i)) 143 | 144 | 145 | if __name__ == '__main__': 146 | 147 | batch_size = 1000 148 | z_dim = 64 # aka embedding 149 | learning_rate = 0.01 150 | beta1 = 0.5 151 | beta2 = 0.999 152 | epochs = 20 153 | 154 | model = BEGAN() 155 | 156 | with tf.Graph().as_default(): 157 | train(model, epochs, batch_size, z_dim, learning_rate, beta1, beta2, load_dataset()) 158 | -------------------------------------------------------------------------------- /BEGAN/train.py: -------------------------------------------------------------------------------- 1 | # @Author: Mohammad Sadegh Safari By Thanks to : @JorgeCeja 2 | 3 | from model import BEGAN 4 | import tensorflow as tf 5 | import numpy as np 6 | import math 7 | import os 8 | import scipy.io as sio 9 | 10 | 11 | def load_dataset(): 12 | hdict = sio.loadmat('../data/my_spec_ETU.mat') 13 | h = hdict['my_spec_ETU'] 14 | 15 | # if you use EVA dataset uncomment below lines and comment above lines 16 | 17 | # hdict = sio.loadmat('../data/My_perfect_H_12.mat') 18 | # h = hdict['My_perfect_H'] 19 | 20 | # load 35K of 72*14 frames as input of BEGAN 21 | csi_ul = np.empty(shape=(35000, 72, 14, 2), dtype=np.float32) 22 | csi_ul[:, :, :, 0] = np.real(h[:35000, :, :]) 23 | csi_ul[:, :, :, 1] = np.imag(h[:35000, :, :]) 24 | print(np.mean(csi_ul)) 25 | print(np.max(csi_ul)) 26 | print(np.max(-csi_ul)) 27 | # 3.3 is maximum value of real and imaginary parts 28 | csi_ul = csi_ul / 3.3 29 | return csi_ul 30 | 31 | 32 | def save_image(Test_result, epoch, batch_number): 33 | # generated_images 34 | tmp_image = Test_result[0] 35 | out = 1.0j * np.squeeze(tmp_image[:, :, :, 1]) 36 | out += np.squeeze(tmp_image[:, :, :, 0]) 37 | generated_images = out 38 | 39 | # reconstruction of generated_images 40 | tmp_image = Test_result[1] 41 | out = 1.0j * np.squeeze(tmp_image[:, :, :, 1]) 42 | out += np.squeeze(tmp_image[:, :, :, 0]) 43 | generated_images_recon = out 44 | 45 | # real image 46 | tmp_image = Test_result[2] 47 | out = 1.0j * np.squeeze(tmp_image[:, :, :, 1]) 48 | out += np.squeeze(tmp_image[:, :, :, 0]) 49 | Input_image = out 50 | 51 | # reconstruction of real image 52 | tmp_image = Test_result[3] 53 | out = 1.0j * np.squeeze(tmp_image[:, :, :, 1]) 54 | out += np.squeeze(tmp_image[:, :, :, 0]) 55 | Input_image_recon = out 56 | 57 | if not os.path.isdir('images'): 58 | os.makedirs('images') 59 | 60 | sio.savemat('images/Results_' + str(epoch + 1) + 61 | '_batch' + str(batch_number + 1) + '.mat', {'etu_generated_images': generated_images, 62 | 'etu_generated_images_recon': generated_images_recon, 63 | 'etu_Input_image': Input_image, 64 | 'etu_Input_image_recon': Input_image_recon}) 65 | 66 | 67 | def train(model, epoch_count, batch_size, z_dim, star_learning_rate, beta1, beta2, real_images): 68 | input_real, input_z, lrate, k_t, decay = model.model_inputs(72, 14, 2, z_dim) 69 | 70 | d_loss, g_loss, d_real, d_fake, generated_images, generated_images_recon, input_image, input_image_recon = model.model_loss( 71 | input_real, input_z, 2, z_dim, k_t, decay) 72 | 73 | d_opt, g_opt, d_train_opt_on_d, d_train_opt_on_g = model.model_opt(d_loss, g_loss, d_real, d_fake, lrate, beta1, 74 | beta2) 75 | 76 | losses = [] 77 | learning_rate = 0 78 | iter = 0 79 | 80 | epoch_drop = 3 81 | noise_decay=0.2 82 | 83 | lam = 1e-2 84 | gamma = .7 85 | k_curr = 0.0 86 | 87 | checkpoint_dir = 'checkpoint' 88 | saver = tf.train.Saver() 89 | 90 | if not os.path.isdir(checkpoint_dir): 91 | os.makedirs(checkpoint_dir) 92 | 93 | # restore previous model if there is one 94 | ckpt = tf.train.get_checkpoint_state(checkpoint_dir) 95 | 96 | config = tf.ConfigProto(log_device_placement=False, allow_soft_placement=True) 97 | config.gpu_options.allow_growth = True 98 | with tf.Session(config=config) as sess: 99 | sess.run(tf.global_variables_initializer()) 100 | if ckpt and ckpt.model_checkpoint_path: 101 | print("Restoring previous model...") 102 | try: 103 | saver.restore(sess, ckpt.model_checkpoint_path) 104 | print("Model restored") 105 | except: 106 | print("Could not restore model") 107 | pass 108 | 109 | for epoch_i in range(epoch_count): 110 | idxs = np.random.permutation(35000) 111 | 112 | learning_rate = star_learning_rate * \ 113 | math.pow(0.2, math.floor((epoch_i + 1) / epoch_drop)) 114 | 115 | for batch_i in range(35000 // batch_size): 116 | iter += 1 117 | idxs_i = idxs[batch_i * batch_size: (batch_i + 1) * batch_size] 118 | batch_images = np.array([ul for ul in real_images[idxs_i]]) 119 | 120 | batch_z = np.random.uniform(-1, 1, size=(batch_size, z_dim)) 121 | 122 | _, d_real_curr = sess.run([d_opt, d_real], feed_dict={ 123 | input_z: batch_z, input_real: batch_images, 124 | lrate: learning_rate, k_t: k_curr, decay: noise_decay / (epoch_i + 1)}) 125 | 126 | _, d_fake_curr, disc_loss = sess.run([g_opt, d_fake, d_loss], feed_dict={ 127 | input_z: batch_z, input_real: batch_images, 128 | lrate: learning_rate, k_t: k_curr, decay: noise_decay / (epoch_i + 1)}) 129 | 130 | k_curr = k_curr + lam * (gamma * d_real_curr - d_fake_curr) 131 | if k_curr < 0: 132 | _, d_fake_curr, disc_loss = sess.run([g_opt, d_fake, d_loss], feed_dict={ 133 | input_z: batch_z, input_real: batch_images, 134 | lrate: learning_rate, k_t: k_curr, decay: noise_decay /(epoch_i + 1)}) 135 | k_curr = 0.0 136 | 137 | # save convergence measure 138 | if batch_i % 100 == 0: 139 | measure = d_real_curr + \ 140 | np.abs(gamma * d_real_curr - d_fake_curr) 141 | losses.append(measure) 142 | 143 | print("nEpoch {}/{}...".format(epoch_i + 1, epoch_count), ' batch :', batch_i, 144 | ', Convergence measure: {:.4}'.format(measure), 145 | ', d_loss[{:.4}], g_loss[{:.4}], k[{:.4}]'.format(disc_loss, d_fake_curr, k_curr)) 146 | 147 | # save test and batch images 148 | if iter % 500 == 1: 149 | Test_result = sess.run([generated_images, generated_images_recon, input_image, input_image_recon], 150 | feed_dict={ 151 | input_z: batch_z, input_real: batch_images, decay: noise_decay / (epoch_i + 1)}) 152 | 153 | save_image(Test_result, epoch_i, batch_i) 154 | 155 | saver.save(sess, checkpoint_dir + '/saved_model.ckpt') 156 | 157 | print('Training steps: ', iter) 158 | 159 | 160 | if __name__ == '__main__': 161 | batch_size = 32 162 | z_dim = 64 # aka embedding 163 | learning_rate = 2e-5 164 | beta1 = 0.5 165 | beta2 = 0.999 166 | epochs = 20 167 | 168 | model = BEGAN() 169 | 170 | with tf.Graph().as_default(): 171 | train(model, epochs, batch_size, z_dim, learning_rate, beta1, beta2, load_dataset()) 172 | -------------------------------------------------------------------------------- /BEGAN/model.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | from tensorflow.python.ops import math_ops 3 | from tensorflow.python.framework import ops 4 | import numpy as np 5 | 6 | 7 | class BEGAN(object): 8 | def __init__(self, place_holder=''): 9 | self.place_holder = place_holder 10 | 11 | def gaussian_noise_layer(self, input_tensor, std=0.2): 12 | noise = tf.random_normal(shape=tf.shape(input_tensor), mean=0.0, stddev=std, dtype=tf.float32) 13 | 14 | return tf.reshape(input_tensor + noise, tf.shape(input_tensor)) 15 | 16 | def model_inputs(self, image_width, image_height, image_channels, z_dim): 17 | """ 18 | Create the model inputs/tensors 19 | """ 20 | inputs_real = tf.placeholder( 21 | tf.float32, (None, image_width, image_height, image_channels), name='input_real') 22 | inputs_z = tf.placeholder(tf.float32, (None, z_dim), name='input_z') 23 | learning_rate = tf.placeholder(tf.float32, [], name='learning_rate') 24 | k_t = tf.placeholder(tf.float32, name='k_t') 25 | decay = tf.placeholder(tf.float32, name='noise_decay') 26 | 27 | return inputs_real, inputs_z, learning_rate, k_t, decay 28 | 29 | # default aplha is 0.2, 0.01 works best for this example 30 | # Function from TensorFlow v1.4 for backwards compatability 31 | def leaky_relu(self, features, alpha=0.01, name=None): 32 | with ops.name_scope(name, "LeakyRelu", [features, alpha]): 33 | features = ops.convert_to_tensor(features, name="features") 34 | alpha = ops.convert_to_tensor(alpha, name="alpha") 35 | 36 | # return math_ops.maximum(alpha * features, features) 37 | return tf.nn.elu(features) 38 | 39 | def fully_connected(self, x, output_shape): 40 | # flatten and dense 41 | shape = x.get_shape().as_list() 42 | dim = np.prod(shape[1:]) 43 | 44 | x = tf.reshape(x, [-1, dim]) 45 | x = tf.layers.dense(x, output_shape, activation=tf.nn.sigmoid) 46 | 47 | return x 48 | 49 | def decoder(self, h, n, h_dim, w_dim, channel_dim): 50 | """ 51 | Reconstruction network 52 | """ 53 | # h = tf.layers.dense(h, h_dim * w_dim * n, activation=None, use_bias=False) 54 | h = tf.layers.dense(h, h_dim * w_dim * n, activation=None, name='df0') 55 | h = tf.reshape(h, (-1, h_dim, w_dim, n)) 56 | 57 | conv1 = tf.layers.conv2d( 58 | h, n, 3, padding="same", activation=self.leaky_relu, name='dc1') 59 | conv1 = tf.layers.conv2d( 60 | conv1, n, 3, padding="same", activation=self.leaky_relu, name='dc11') 61 | 62 | upsample1 = tf.image.resize_nearest_neighbor(conv1, size=(h_dim * 2, w_dim))+tf.image.resize_nearest_neighbor( 63 | h, size=(h_dim * 2, w_dim)) 64 | 65 | conv2 = tf.layers.conv2d( 66 | upsample1, n, 3, padding="same", activation=self.leaky_relu, name='dc2') 67 | conv2 = tf.layers.conv2d( 68 | conv2, n, 3, padding="same", activation=self.leaky_relu, name='dc22') 69 | 70 | upsample2 = tf.image.resize_nearest_neighbor(conv2, size=(h_dim * 4, w_dim * 2))+\ 71 | tf.image.resize_nearest_neighbor(h, size=(h_dim * 4, w_dim*2)) 72 | 73 | conv3 = tf.layers.conv2d( 74 | upsample2, n, 3, padding="same", activation=self.leaky_relu, name='dc3') 75 | conv3 = tf.layers.conv2d( 76 | conv3, n, 3, padding="same", activation=self.leaky_relu, name='dc32') 77 | 78 | conv4 = tf.layers.conv2d(conv3, channel_dim, 3, 79 | padding="same", activation=None, name='dc4') 80 | 81 | return conv4 82 | 83 | def encoder(self, images, n, z_dim, channel_dim): 84 | """ 85 | Feature extraction network 86 | """ 87 | conv1 = tf.layers.conv2d( 88 | images, n, 3, padding="same", activation=self.leaky_relu) 89 | 90 | conv2 = tf.layers.conv2d( 91 | conv1, n, 3, padding="same", activation=self.leaky_relu) 92 | conv2 = tf.layers.conv2d( 93 | conv2, n * 2, 3, padding="same", activation=self.leaky_relu) 94 | 95 | subsample1 = tf.layers.conv2d( 96 | conv2, n * 2, 3, strides=2, padding='same') 97 | 98 | conv3 = tf.layers.conv2d(subsample1, n * 2, 3, 99 | padding="same", activation=self.leaky_relu) 100 | conv3 = tf.layers.conv2d( 101 | conv3, n * 3, 3, padding="same", activation=self.leaky_relu) 102 | 103 | subsample2 = tf.layers.conv2d( 104 | conv3, n * 3, 3, strides=(2, 1), padding='same') 105 | 106 | conv4 = tf.layers.conv2d(subsample2, n * 3, 3, 107 | padding="same", activation=self.leaky_relu) 108 | conv4 = tf.layers.conv2d( 109 | conv4, n * 3, 3, padding="same", activation=self.leaky_relu) 110 | 111 | h = self.fully_connected(conv4, z_dim) 112 | 113 | return h 114 | 115 | def discriminator(self, images, z_dim, channel_dim, reuse=True): 116 | """ 117 | Create the discriminator network: The autoencoder 118 | """ 119 | # with tf.variable_scope('discriminator', reuse=reuse): 120 | with tf.variable_scope(tf.get_variable_scope(), reuse=tf.AUTO_REUSE): 121 | x = self.encoder(images, 64, z_dim, channel_dim) 122 | x = self.decoder(x, 64, 18, 7, channel_dim) 123 | 124 | return x 125 | 126 | def generator(self, z, channel_dim, is_train=True): 127 | """ 128 | Create the generator network: Only the encoder part 129 | """ 130 | # reuse = False if is_train else True 131 | # with tf.variable_scope('generator', reuse=reuse): 132 | x = self.decoder(z, 64, 18, 7, channel_dim) 133 | 134 | return x 135 | 136 | def model_loss(self, input_real, input_z, channel_dim, z_dim, k_t, decay): 137 | """ 138 | Get the loss for the discriminator and generator 139 | """ 140 | g_model_fake = self.generator(input_z, channel_dim, is_train=True) 141 | noisy_input_real = self.gaussian_noise_layer(input_real, decay) 142 | 143 | noisy_input_fake = self.gaussian_noise_layer(g_model_fake, decay) 144 | d_model_real = self.discriminator(noisy_input_real, z_dim, channel_dim) 145 | d_model_fake = self.discriminator( 146 | noisy_input_fake, z_dim, channel_dim, reuse=True) 147 | 148 | d_real = tf.sqrt(tf.reduce_mean(tf.square(noisy_input_real - d_model_real))) 149 | d_fake = tf.sqrt(tf.reduce_mean(tf.square(noisy_input_fake - d_model_fake))) 150 | 151 | d_loss = d_real - k_t * d_fake 152 | g_loss = d_fake 153 | 154 | return d_loss, g_loss, d_real, d_fake, g_model_fake, d_model_fake, input_real, d_model_real 155 | 156 | def model_opt(self, d_loss, g_loss, d_real, d_fake, learning_rate, beta1, beta2=0.999): 157 | """ 158 | Get optimization operations 159 | """ 160 | d_train_opt = tf.train.AdamOptimizer( 161 | learning_rate, beta1=beta1, beta2=beta2).minimize(d_loss) 162 | 163 | d_train_opt_on_d = tf.train.AdamOptimizer( 164 | learning_rate, beta1=beta1, beta2=beta2).minimize(d_real) 165 | 166 | d_train_opt_on_g = tf.train.AdamOptimizer( 167 | learning_rate, beta1=beta1, beta2=beta2).minimize(d_real - d_fake) 168 | 169 | g_train_opt = tf.train.AdamOptimizer( 170 | learning_rate, beta1=beta1, beta2=beta2).minimize(g_loss) 171 | 172 | return d_train_opt, g_train_opt, d_train_opt_on_d, d_train_opt_on_g 173 | -------------------------------------------------------------------------------- /CNN/cnn.py: -------------------------------------------------------------------------------- 1 | """@Author: Moahammad Sadegh Safari by thanks to @Parag K. Mital 2 | """ 3 | import tensorflow as tf 4 | import numpy as np 5 | import math 6 | import os 7 | import scipy.io as sio 8 | 9 | 10 | def autoencoder(input_shape=[None, 36, 7, 2], 11 | n_filters=[2, 8, 16, 32], 12 | filter_sizes=[3, 3, 3, 3]): 13 | """Build a deep neural net to predict DL CSI. 14 | 15 | Parameters 16 | ---------- 17 | input_shape : list, optional 18 | Description 19 | n_filters : list, optional 20 | Description 21 | filter_sizes : list, optional 22 | Description 23 | 24 | Returns 25 | ------- 26 | x : Tensor 27 | Input placeholder to the network 28 | y : Tensor 29 | Output reconstruction of the input 30 | cost : Tensor 31 | Overall cost to use for training 32 | 33 | 34 | """ 35 | 36 | # input to the network 37 | x = tf.placeholder(tf.float32, input_shape, name='x') 38 | Y = tf.placeholder(tf.float32, input_shape, name='Y') 39 | 40 | 41 | 42 | # %% 43 | # ensure 2-d is converted to square tensor. 44 | if len(x.get_shape()) == 2: 45 | x_dim = x.get_shape().as_list()[1] 46 | y_dim = x.get_shape().as_list()[2] 47 | x_tensor = tf.reshape( 48 | x, [-1, x_dim, y_dim, n_filters[0]]) 49 | elif len(x.get_shape()) == 4: 50 | x_tensor = x 51 | else: 52 | raise ValueError('Unsupported input dimensions') 53 | current_input = x_tensor 54 | 55 | # Build the network 56 | 57 | # first layer 58 | layer_i = 0 59 | n_output = n_filters[1] 60 | n_input = current_input.get_shape().as_list()[3] 61 | W = tf.Variable( 62 | tf.random_uniform(dtype=tf.float32, shape=[ 63 | filter_sizes[layer_i], 64 | filter_sizes[layer_i], 65 | n_input, n_output], 66 | minval=-1.0 / math.sqrt(n_input), 67 | maxval=1.0 / math.sqrt(n_input))) 68 | 69 | b = tf.Variable(tf.zeros(shape=[n_output], dtype=tf.float32)) 70 | 71 | # symmetric padding for first layer 72 | paddings = tf.constant([[0, 0], [1, 1], [1, 1], [0, 0]]) 73 | current_input = tf.pad(current_input, paddings, "SYMMETRIC") 74 | 75 | output = tf.nn.tanh( 76 | tf.add(tf.nn.conv2d( 77 | current_input, W, strides=[1, 1, 1, 1], padding='VALID'), b)) 78 | current_input = output 79 | 80 | for layer_i, n_output in enumerate(n_filters[2:]): 81 | n_input = current_input.get_shape().as_list()[3] 82 | W = tf.Variable( 83 | tf.random_uniform(dtype=tf.float32, shape=[ 84 | filter_sizes[layer_i+1], 85 | filter_sizes[layer_i+1], 86 | n_input, n_output], 87 | minval=-1.0 / math.sqrt(n_input), 88 | maxval=1.0 / math.sqrt(n_input))) 89 | b = tf.Variable(tf.zeros(shape=[n_output],dtype=tf.float32)) 90 | 91 | # symmetric padding for second layer 92 | paddings = tf.constant([[0, 0], [1, 1], [1, 1], [0, 0]]) 93 | current_input = tf.pad(current_input, paddings, "SYMMETRIC") 94 | output = tf.nn.tanh( 95 | tf.add(tf.nn.conv2d( 96 | current_input, W, strides=[1, 1, 1, 1], padding='VALID'), b)) 97 | current_input = output 98 | 99 | n_filters.reverse() 100 | 101 | for layer_i in range(2): 102 | W = tf.Variable( 103 | tf.random_uniform(dtype=tf.float32, shape=[ 104 | filter_sizes[layer_i], 105 | filter_sizes[layer_i], 106 | n_filters[layer_i], n_filters[layer_i + 1]], 107 | minval=-1.0 / math.sqrt(n_filters[layer_i]), 108 | maxval=1.0 / math.sqrt(n_filters[layer_i]))) 109 | b = tf.Variable(tf.zeros(shape=[n_filters[layer_i + 1]], dtype=tf.float32)) 110 | output = tf.nn.tanh(tf.add( 111 | tf.nn.conv2d( 112 | current_input, W, 113 | strides=[1, 1, 1, 1], padding='SAME'), b)) 114 | current_input = output 115 | 116 | layer_i = layer_i + 1 117 | W = tf.Variable( 118 | tf.random_uniform(dtype=tf.float32, shape=[ 119 | filter_sizes[layer_i], 120 | filter_sizes[layer_i], 121 | n_filters[layer_i], n_filters[layer_i + 1]], 122 | minval=-1.0 / math.sqrt(n_filters[layer_i]), 123 | maxval=1.0 / math.sqrt(n_filters[layer_i]))) 124 | b = tf.Variable(tf.zeros(shape=[n_filters[layer_i + 1]], dtype=tf.float32)) 125 | output = tf.add( 126 | tf.nn.conv2d( 127 | current_input, W, 128 | strides=[1, 1, 1, 1], padding='SAME'), b) 129 | 130 | # MSE cost function for prediction 131 | cost = tf.reduce_mean(tf.square(tf.subtract(output,Y))) 132 | 133 | # %% 134 | return {'x': x, 'Y': Y, 'cost': cost, 'Y_pred':output} 135 | 136 | 137 | # %% 138 | def train_csi(): 139 | """Test the convolutional network using csi samples.""" 140 | # %% 141 | # load CSI dataset with 40K samples 142 | hdict = sio.loadmat('../data/My_perfect_H_12.mat') 143 | h = hdict['My_perfect_H'] 144 | 145 | # uplink channel as input 146 | csi_ul = np.empty(shape=(35000, 36, 7, 2), dtype=np.float32) 147 | csi_ul_test = np.empty(shape=(4000, 36, 7, 2), dtype=np.float32) 148 | csi_ul_val = np.empty(shape=(1000, 36, 7, 2), dtype=np.float32) 149 | csi_ul[:, :, :, 0] = np.real(h[:35000, :36, :7]) 150 | csi_ul[:, :, :, 1] = np.imag(h[:35000, :36, :7]) 151 | csi_ul_val[:, :, :, 0] = np.real(h[35000:36000, :36, :7]) 152 | csi_ul_val[:, :, :, 1] = np.imag(h[35000:36000, :36, :7]) 153 | csi_ul_test[:, :, :, 0] = np.real(h[36000:, :36, :7]) 154 | csi_ul_test[:, :, :, 1] = np.imag(h[36000:, :36, :7]) 155 | mean_csi_ul = np.mean(csi_ul, axis=0) 156 | 157 | # downlink channel as output 158 | csi_dl = np.empty(shape=(35000, 36, 7, 2), dtype=np.float32) 159 | csi_dl_test = np.empty(shape=(4000, 36, 7, 2), dtype=np.float32) 160 | csi_dl_val = np.empty(shape=(1000, 36, 7, 2), dtype=np.float32) 161 | csi_dl[:, :, :, 0] = np.real(h[:35000, 36:, 7:]) 162 | csi_dl[:, :, :, 1] = np.imag(h[:35000, 36:, 7:]) 163 | csi_dl_val[:, :, :, 0] = np.real(h[35000:36000, 36:, 7:]) 164 | csi_dl_val[:, :, :, 1] = np.imag(h[35000:36000, 36:, 7:]) 165 | csi_dl_test[:, :, :, 0] = np.real(h[36000:, 36:, 7:]) 166 | csi_dl_test[:, :, :, 1] = np.imag(h[36000:, 36:, 7:]) 167 | mean_csi_dl = np.mean(csi_dl, axis=0) 168 | 169 | ae = autoencoder() 170 | 171 | val_input = np.array([ul - mean_csi_ul for ul in csi_ul_val]) 172 | val_output = np.array([dl - mean_csi_dl for dl in csi_dl_val]) 173 | csi_ul_test = np.array([ul - mean_csi_ul for ul in csi_ul_test]) 174 | csi_dl_test = np.array([dl - mean_csi_dl for dl in csi_dl_test]) 175 | 176 | # defining a placeholder for learning rate 177 | learning_rate = tf.placeholder(tf.float32, [], name='learning_rate') 178 | star_learning_rate = 0.001 179 | op = tf.train.AdamOptimizer(learning_rate) 180 | optimizer = op.minimize(ae['cost']) 181 | 182 | # %% 183 | # We create a session to use the graph 184 | config = tf.ConfigProto() 185 | config.gpu_options.allow_growth = True 186 | sess = tf.Session(config=config) 187 | sess.run(tf.global_variables_initializer()) 188 | saver = tf.train.Saver() 189 | 190 | batch_size = 32 191 | n_batch = 35000 // batch_size 192 | n_epochs = 100 193 | 194 | checkpoint_dir = 'checkpoint' 195 | if not os.path.isdir(checkpoint_dir): 196 | os.makedirs(checkpoint_dir) 197 | 198 | ckpt = tf.train.get_checkpoint_state(checkpoint_dir) 199 | if ckpt and ckpt.model_checkpoint_path: 200 | print("Restoring previous model...") 201 | try: 202 | saver.restore(sess, ckpt.model_checkpoint_path) 203 | print("Model restored") 204 | except: 205 | print("Could not restore model") 206 | pass 207 | 208 | for epoch_i in range(n_epochs): 209 | idxs = np.random.permutation(35000) 210 | for batch_i in range(n_batch): 211 | idxs_i = idxs[batch_i*batch_size: (batch_i+1)*batch_size] 212 | 213 | # normalize dl and ul csi's 214 | inputs = np.array([ul - mean_csi_ul for ul in csi_ul[idxs_i]]) 215 | labels = np.array([dl - mean_csi_dl for dl in csi_dl[idxs_i]]) 216 | sess.run(optimizer, feed_dict={ae['x']: inputs, ae['Y']: labels, learning_rate: star_learning_rate}) 217 | 218 | train_loss = sess.run(2*ae['cost'], feed_dict={ae['x']: inputs, ae['Y']: labels}) 219 | val_loss = sess.run(2*ae['cost'], feed_dict={ae['x']: val_input, ae['Y']: val_output}) 220 | 221 | print('epoch: ', epoch_i, ", train_loss: ", train_loss, ", val_loss: ", val_loss) 222 | if epoch_i % 5 == 1: 223 | saver.save(sess, checkpoint_dir + '/saved_model.ckpt') 224 | if epoch_i % 40 == 39: 225 | star_learning_rate = star_learning_rate/2 226 | 227 | print('and finally the loss is:{}'.format(2*sess.run(ae['cost'], 228 | feed_dict={ae['x']: csi_ul_test, ae['Y']: csi_dl_test}))) 229 | out_images = sess.run(ae['Y_pred'], feed_dict={ae['x']: csi_ul_test}) 230 | out_images = np.array([dl + mean_csi_dl for dl in out_images]) 231 | out = 1.0j*np.squeeze(out_images[:, :, :, 1]) 232 | out += np.squeeze(out_images[:, :, :, 0]) 233 | 234 | inp_images = np.array([ul + mean_csi_ul for ul in csi_ul_test]) 235 | inp = 1.0j*np.squeeze(inp_images[:, :, :, 1]) 236 | inp += np.squeeze(inp_images[:, :, :, 0]) 237 | 238 | ground_truth_images = np.array([dl + mean_csi_dl for dl in csi_dl_test]) 239 | ground_truth = 1.0j*np.squeeze(ground_truth_images[:, :, :, 1]) 240 | ground_truth += np.squeeze(ground_truth_images[:, :, :, 0]) 241 | 242 | if not os.path.isdir('images'): 243 | os.makedirs('images') 244 | sio.savemat('images/recon_images.mat', {'prediction': out, 'input': inp, 'ground_truth': ground_truth}) 245 | print(r'reconstructed images saved to images/recon_images.mat...') 246 | 247 | 248 | if __name__ == '__main__': 249 | train_csi() 250 | --------------------------------------------------------------------------------