def test_decoding_results(): viterbi_net_performance = [] threshold_performance = [] classic_performance = [] SNRs = np.linspace(.1, 10, 10) seed_generator = 0 data_gen = None for SNR in SNRs: """ Generated Testing Data using the same channel as was used for training the mixture model and the nn """ number_symbols = 500 channel = np.zeros((1, 4)) channel[0, [0, 1, 2, 3]] = 1, 0.1, 0.1, 0.2 data_gen = training_data_generator( symbol_stream_shape=(1, number_symbols), SNR=SNR, plot=True, channel=channel) data_gen.random_symbol_stream() data_gen.send_through_channel() """ Load in Trained Neural Network and verify that it is acceptable performance """ device = torch.device("cpu") num_inputs_for_nn = 1 x, y = data_gen.get_labeled_data(inputs=num_inputs_for_nn) y = np.argmax( y, axis=1 ) # Fix for how the pytorch Cross Entropy expects class labels to be shown x = torch.Tensor(x) y = torch.Tensor(y) train_size = int(.6 * number_symbols) x_train = x[0:train_size, :] x_test = x[train_size::, :] y_train = y[0:train_size] y_test = y[train_size::] """ Setup NN and optimizer """ m = data_gen.alphabet.size channel_length = data_gen.CIR_matrix.shape[1] N, D_in, H1, H2, D_out = number_symbols, 1, 100, 50, np.power( m, channel_length) net = models.ViterbiNet(D_in, H1, H2, D_out) optimizer = optim.Adam(net.parameters(), lr=1e-2) """ Train NN """ # criterion = nn.CrossEntropyLoss() criterion = nn.NLLLoss() train_cost_over_epoch = [] test_cost_over_epoch = [] # If training is perfect, then NN should be able to perfectly predict the class to which a test set belongs and thus the loss (KL Divergence) should be zero for t in range(500): output = net(x_train) loss = criterion(output, y_train.long()) train_cost_over_epoch.append(loss) net.zero_grad() print(loss) loss.backward() optimizer.step() test_cost_over_epoch.append(criterion(net(x_test), y_test.long())) # Test NN x, y = data_gen.get_labeled_data(inputs=num_inputs_for_nn) y = np.argmax( y, axis=1 ) # Fix for how the pytorch Cross Entropy expects class labels to be shown x = torch.Tensor(x) y = torch.Tensor(y) # criterion = nn.NLLLoss() criterion = nn.CrossEntropyLoss() cost = criterion(net(x), y.long()) threshold = 1e-2 # assert cost < threshold """ Train Mixture Model """ mixture_model_training_data = data_gen.channel_output.flatten() num_sources = pow(data_gen.alphabet.size, data_gen.CIR_matrix.shape[1]) mm = em_gausian(num_sources, mixture_model_training_data, 20, save=True, model=True) mm = mm.get_probability # mm = 1 """ After sending through channel, symbol detection should be performed using something like a matched filter. Create new set of test data. """ data_gen = training_data_generator( symbol_stream_shape=(1, number_symbols), SNR=SNR, plot=True, channel=channel) data_gen.random_symbol_stream() data_gen.send_through_channel() # !! Make sure channel output gets flipped here!! metric = NeuralNetworkMixtureModelMetric( net, mm, data_gen.channel_output, input_length=num_inputs_for_nn ) # This is a function to be used in the viterbi detected_nn = viterbi_setup_with_nodes(data_gen.alphabet, data_gen.channel_output, data_gen.CIR_matrix.shape[1], metric.metric) ser_nn = symbol_error_rate_channel_compensated( detected_nn, data_gen.symbol_stream_matrix, channel_length) """ Compare to Classical Viterbi with full CSI """ metric = GaussianChannelMetric( channel, data_gen.channel_output ) # This is a function to be used in the viterbi detected_classic = viterbi_setup_with_nodes( data_gen.alphabet, data_gen.channel_output, data_gen.CIR_matrix.shape[1], metric.metric) ser_classic = symbol_error_rate_channel_compensated( detected_classic, data_gen.symbol_stream_matrix, channel_length) """ Analyze SER performance """ viterbi_net_performance.append(ser_nn) classic_performance.append(ser_classic) path = "Output/SER.pickle" pickle_out = open(path, "wb") pickle.dump([classic_performance, viterbi_net_performance], pickle_out) pickle_out.close() plt.figure(1) plt.plot(SNRs, viterbi_net_performance, label='viterbi net') plt.plot(SNRs, classic_performance, label='standard viterbi') plt.title(str(data_gen.get_info_for_plot()), fontdict={'fontsize': 10}) plt.xlabel("SNR") plt.ylabel("SER") plt.legend(loc='upper left') path = "Output/SER_curves.png" plt.savefig(path, format="png") time_path = "Output/SER_" + net.name + str(num_inputs_for_nn) + str( number_symbols) + " symbols " + str(time.time()) + "curves.png" plt.savefig(time_path, format="png") assert True
def test_full_integration(): viterbi_net_performance = [] linear_mmse_performance = [] classic_performance = [] SNRs_dB = np.linspace(20, 20, 2) # SNRs_dB = np.linspace(6, 10,3) SNRs = np.power(10, SNRs_dB/10) seed_generator = 0 data_gen = None channel = None number_symbols = 5000 channel = np.zeros((1, 5)) # channel[0, [0, 1, 2, 3, 4]] = 0.227, 0.460, 0.688, 0.460, 0.227 channel[0, [0, 1, 2, 3, 4]] = 0.9, 0.7, 0.3, 0.5, 0.1 # Method used in ViterbiNet Paper # channel[0, :] = np.random.randn(channel.size) # channel = np.zeros((1, 5)) # channel[0, [0, 1, 2, 3, 4]] = 1, 0, .2, .2, .4 # channel[0, [0, 1, 2, 3]] = .8, 0, .02, .4 # channel[0, [0, 1, 2, 3, 4]] = 1, .7, .3, .1, .4 # channel[0, [0, 1, 2, 3, 4]] = 1, .4, .7, .1, .3 # channel = np.zeros((1, 3)) # channel[0, [0]] = 1 for SNR in SNRs: """ Generated Testing Data using the same channel as was used for training the mixture model and the nn """ data_gen = CommunicationDataGenerator(symbol_stream_shape=(1, number_symbols), SNR=SNR, plot=True, channel=channel) data_gen.random_symbol_stream() data_gen.send_through_channel() # plt.scatter(data_gen.channel_output.flatten(),data_gen.channel_output.flatten()) # plt.show() """ Load in Trained Neural Network and verify that it is acceptable performance """ device = torch.device("cpu") x, y = data_gen.get_labeled_data() y = np.argmax(y, axis=1) # Fix for how the pytorch Cross Entropy expects class labels to be shown x = torch.Tensor(x) y = torch.Tensor(y) train_size = int(.6 * number_symbols) x_train = x[0:train_size, :] x_test = x[train_size::, :] y_train = y[0:train_size] y_test = y[train_size::] """ Setup NN and optimizer """ m = data_gen.alphabet.size channel_length = data_gen.CIR_matrix.shape[1] # channel_length = channel_length-2 output_layer_size = np.power(m, channel_length) num_states = output_layer_size N, D_in, H1, H2, D_out = number_symbols, 1, 100, 50, output_layer_size net = models.ViterbiNet(D_in, H1, H2, D_out) optimizer = optim.Adam(net.parameters(), lr=1e-2) """ Train NN """ # This loss function looks at only the true class and takes the NLL of that. criterion = nn.NLLLoss() train_cost_over_epoch = [] test_cost_over_epoch = [] batch_size = 1000 # If training is perfect, then NN should be able to perfectly predict the class to which a test set belongs and thus the loss (KL Divergence) should be zero epochs = 900 for t in range(epochs): batch_indices = np.random.randint(len(y_train), size=(1, batch_size)) x_batch = x_train[(batch_indices)] y_batch = y_train[(batch_indices)] # Add "dropout to prevent overfitting data" net.zero_grad() output = net(x_batch) loss = criterion(output, y_batch.long()) loss.backward() optimizer.step() test_batch_indices = np.random.randint(len(y_test), size=(1, batch_size)) x_batch_test = x_test[(test_batch_indices)] y_batch_test = y_test[(test_batch_indices)] # Setup Accuracy test # detached_ouput = output. max_state_train = np.argmax(output.detach().numpy(), axis=1) max_state_test = np.argmax(net(x_batch_test).detach().numpy(), axis=1) train_cost_over_epoch.append(np.sum(np.not_equal(max_state_train, y_batch.detach().numpy()))/y_batch.size()) test_cost_over_epoch.append(np.sum(np.not_equal(max_state_test, y_batch_test.detach().numpy()))/y_batch_test.size()) # test_cost_over_epoch.append(criterion(net(x_batch_test), y_batch_test.long())) """ Train Mixture Model """ mm_train_size = 1000 mixture_model_training_data = data_gen.channel_output.flatten()[0:mm_train_size] num_sources = num_states mm = em_gausian(num_sources, mixture_model_training_data, 10, save=True, model=True) mm = mm.get_probability """ User training data to train MMSE equalizer to then use on the test data """ mmse_equalizer = LinearMMSE() mmse_equalizer.train_equalizer(data_gen.symbol_stream_matrix, data_gen.channel_output, data_gen.symbol_stream_matrix, channel.size) """ Create new set of test data. """ ser_nn = [] ser_classic = [] ser_lmmse = [] for reps in range(5): del data_gen data_gen = CommunicationDataGenerator(symbol_stream_shape=(1, 2000), SNR=SNR, plot=True, channel=channel) data_gen.random_symbol_stream() data_gen.send_through_channel() """ Evaluate Neural Net Performance """ # metric = NeuralNetworkMixtureModelMetric(net, mm, data_gen.channel_output) metric = NeuralNetworkMixtureModelMetric(net, mm, np.flip(data_gen.channel_output)) detected_nn = viterbi_setup_with_nodes(data_gen.alphabet, data_gen.channel_output, data_gen.CIR_matrix.shape[1], metric.metric) ser_nn = symbol_error_rate_channel_compensated_NN(detected_nn, data_gen.symbol_stream_matrix, channel_length) """ Compare to Classical Viterbi with full CSI """ metric = GaussianChannelMetric(channel, np.flip(data_gen.channel_output)) # This is a function to be used in the viterbi detected_classic = viterbi_setup_with_nodes(data_gen.alphabet, data_gen.channel_output, data_gen.CIR_matrix.shape[1], metric.metric) ser_classic = symbol_error_rate(detected_classic, data_gen.symbol_stream_matrix, channel_length) """ Evaluate performance with linear MMSE """ ser_lmmse.append(mmse_equalizer.test_equalizer(data_gen.symbol_stream_matrix, data_gen.channel_output)) ser_nn = np.average(ser_nn) ser_classic = np.average(ser_classic) ser_lmmse = np.average(ser_lmmse) """ Analyze SER performance """ linear_mmse_performance.append(ser_lmmse) viterbi_net_performance.append(ser_nn) classic_performance.append(ser_classic) path = "Output/SER.pickle" pickle_out = open(path, "wb") pickle.dump([classic_performance, linear_mmse_performance, viterbi_net_performance], pickle_out) pickle_out.close() figure, dictionary = plot_symbol_error_rates(SNRs_dB, [classic_performance, linear_mmse_performance, viterbi_net_performance], data_gen.get_info_for_plot()) time_path = "Output/SER_"+f"{time.time()}"+"curves.png" figure.savefig(time_path, format="png") text_path = "Output/SER_"+f"{time.time()}"+"curves.csv" pd.DataFrame.from_dict(dictionary).to_csv(text_path) figure.savefig(time_path, format="png") #Plots for NN training information plt.figure(2) plt.plot(test_cost_over_epoch, label='Test Error') plt.plot(train_cost_over_epoch, label='Train Error') plt.title(str(data_gen.get_info_for_plot()), fontdict={'fontsize': 10}) plt.xlabel("Epoch") plt.ylabel("Error") plt.legend(loc='upper right') path = f"Output/Neural_Network{time.time()}_Convergence.png" plt.savefig(path, format="png")
def test_nn_channel_reduced(): viterbi_net_performance = [] linear_mmse_performance = [] classic_performance = [] SNRs_dB = np.linspace(15, 15, 1) # SNRs_dB = np.linspace(6, 10,3) SNRs = np.power(10, SNRs_dB / 10) seed_generator = 0 data_gen = None channel = None number_symbols = 5000 channel = np.zeros((1, 5)) # channel[0, [0, 1, 2, 3, 4]] = 0.227, 0.460, 0.688, 0.460, 0.227 # Method used in ViterbiNet Paper channel[0, :] = np.random.randn(channel.size) # channel = np.zeros((1, 5)) # channel[0, [0, 1, 2, 3, 4]] = 1, 0, .2, .2, .4 # channel[0, [0, 1, 2, 3]] = .8, 0, .02, .4 # channel[0, [0, 1, 2, 3, 4]] = 1, .7, .3, .1, .4 # channel[0, [0, 1, 2, 3, 4]] = 1, .4, .7, .1, .3 # channel = np.zeros((1, 3)) # channel[0, [0]] = 1 """ Generated Testing Data using the same channel as was used for training the mixture model and the nn """ data_gen = training_data_generator(symbol_stream_shape=(1, number_symbols), SNR=SNRs, plot=True, channel=channel) data_gen.random_symbol_stream() data_gen.send_through_channel() # plt.scatter(data_gen.channel_output.flatten(),data_gen.channel_output.flatten()) # plt.show() """ Load in Trained Neural Network and verify that it is acceptable performance """ device = torch.device("cpu") reduced_state = 32 x, y = data_gen.get_labeled_data_reduced_state(reduced_state) # x, y = data_gen.get_labeled_data() y = np.argmax( y, axis=1 ) # Fix for how the pytorch Cross Entropy expects class labels to be shown x = torch.Tensor(x) y = torch.Tensor(y) train_size = int(.6 * number_symbols) x_train = x[0:train_size, :] x_test = x[train_size::, :] y_train = y[0:train_size] y_test = y[train_size::] """ Setup NN and optimizer """ m = data_gen.alphabet.size channel_length = data_gen.CIR_matrix.shape[1] output_layer_size = np.power(m, channel_length) output_layer_size = reduced_state N, D_in, H1, H2, D_out = number_symbols, 1, 100, 50, output_layer_size # N, D_in, H1, H2, H3, D_out = number_symbols, 1, 20, 20, 20, output_layer_size net = models.ViterbiNet(D_in, H1, H2, D_out) # net = models.viterbiNet(D_in, H1, H2, D_out, dropout_probability) # net = models.deeper_viterbiNet(D_in, H1, H2, H3, D_out, dropout_probability) # N, D_in, H1, H2, H3, D_out = number_symbols, num_inputs_for_nn, 20, 10, 10, np.power(m, channel_length) # net = models.deeper_viterbiNet(D_in, H1, H2, H3, D_out) optimizer = optim.Adam(net.parameters(), lr=1e-2) # optimizer = optim.SGD(net.parameters(), lr=1e-1) """ Train NN """ # This loss function looks at only the true class and takes the NLL of that. criterion = nn.NLLLoss() train_cost_over_epoch = [] test_cost_over_epoch = [] batch_size = 1000 # If training is perfect, then NN should be able to perfectly predict the class to which a test set belongs and thus the loss (KL Divergence) should be zero epochs = 900 for t in range(epochs): batch_indices = np.random.randint(len(y_train), size=(1, batch_size)) x_batch = x_train[(batch_indices)] y_batch = y_train[(batch_indices)] # Add "dropout to prevent overfitting data" net.zero_grad() output = net(x_batch) loss = criterion(output, y_batch.long()) loss.backward() optimizer.step() test_batch_indices = np.random.randint(len(y_test), size=(1, batch_size)) x_batch_test = x_test[(test_batch_indices)] y_batch_test = y_test[(test_batch_indices)] # Setup Accuracy test # detached_ouput = output. max_state_train = np.argmax(output.detach().numpy(), axis=1) check = np.not_equal(max_state_train, y_batch.detach().numpy()) max_state_test = np.argmax(net(x_batch_test).detach().numpy(), axis=1) train_cost_over_epoch.append( np.sum(np.not_equal(max_state_train, y_batch.detach().numpy())) / y_batch.size()) test_cost_over_epoch.append( np.sum(np.not_equal(max_state_test, y_batch_test.detach().numpy())) / y_batch_test.size()) # test_cost_over_epoch.append(criterion(net(x_batch_test), y_batch_test.long())) #Plots for NN training information plt.figure(2) plt.plot(test_cost_over_epoch, label='Test Error') plt.plot(train_cost_over_epoch, label='Train Error') plt.title(str(data_gen.get_info_for_plot()), fontdict={'fontsize': 10}) plt.xlabel("Epoch") plt.ylabel("Error") plt.legend(loc='upper right') path = f"Output/Neural_Network{time.time()}_Convergence.png" plt.savefig(path, format="png")
def test_auto_encoder(): """ Generated Testing Data using the same channel as was used for training the mixture model and the nn """ number_symbols = 5000 sources = 32 x = np.random.randint(sources, size=(number_symbols, 1)) y = x.flatten() x = x + np.random.standard_normal((number_symbols, 1)) * 1 # plt.scatter(x, x) # plt.show() x = torch.Tensor(x) y = torch.Tensor(y) train_size = int(.6 * number_symbols) x_train = x[0:train_size] x_test = x[train_size::] y_train = y[0:train_size] y_test = y[train_size::] """ Setup NN and optimizer """ N, D_in, H1, H2, D_out = number_symbols, 1, 100, 50, sources net = models.ViterbiNet(D_in, H1, H2, D_out) # N, D_in, H1, H2, H3, D_out = number_symbols, 1, 50, 50, 50, sources # net = models.deeper_viterbiNet(D_in, H1, H2, H3, D_out, dropout_probability) optimizer = optim.Adam(net.parameters(), lr=1e-2) # optimizer = optim.SGD(net.parameters(), lr=1e-1) """ Train NN """ criterion = nn.NLLLoss() # criterion = nn.CrossEntropyLoss() train_cost_over_epoch = [] test_cost_over_epoch = [] accuracy = [] batch_size = 1000 # If training is perfect, then NN should be able to perfectly predict the class to which a test set belongs and thus the loss (KL Divergence) should be zero for t in range(900): batch_indices = np.random.randint(len(y_train), size=(1, batch_size)) x_batch = x_train[(batch_indices)] y_batch = y_train[(batch_indices)] output = net(x_batch) loss = criterion(output, y_batch.long()) train_cost_over_epoch.append(loss) net.zero_grad() # print(loss) loss.backward() optimizer.step() test_batch_indices = np.random.randint(len(y_test), size=(1, batch_size)) x_batch_test = x_test[(test_batch_indices)] y_batch_test = y_test[(test_batch_indices)] # check = np.argmax(net(x_batch_test)) # accuracy.append(np.sum(np.equal(net(x_batch_test), y_batch_test))) test_cost_over_epoch.append( criterion(net(x_batch_test), y_batch_test.long())) x = np.random.randint(sources, size=(100000, 1)) y = x.flatten() x = torch.Tensor(x) check = net(x).detach().numpy() output = np.argmax(net(x).detach().numpy(), axis=1) test = np.not_equal(y, output) error = np.sum(np.not_equal(y, output)) print(f"number of errors: {error/100000}") #Plots for NN training information # plt.figure(1) # plt.plot(accuracy, label='Test Error') plt.figure(2) plt.plot(test_cost_over_epoch, label='Test Error') plt.plot(train_cost_over_epoch, label='Train Error') plt.xlabel("Epoch") plt.ylabel("Error") plt.legend(loc='upper left') plt.show() assert True
def test_reduced_full_final(): viterbi_net_performance = [] viterbi_net_reduced_performance = [] linear_mmse_performance = [] classic_performance = [] SNRs_dB = np.linspace(0, 15, 15) SNRs = np.power(10, SNRs_dB / 10) seed_generator = 0 data_gen = None channel = None quantization_level = None quantization_level = 0 noise_levels = None # noise_levels = 2 number_symbols = 5000 channel = np.zeros((1, 5)) # channel[0, [0, 1, 2, 3, 4]] = 0.227, 0.460, 0.688, 0.460, 0.227 # channel[0, [0, 1, 2, 3, 4]] = 0.9, 0.7, 0.3, 0.5, 0.1 # Channel to use for redundancy testing # Method used in ViterbiNet Paper # channel[0, :] = np.random.randn(channel.size) # channel = np.zeros((1, 5)) channel[0, [0, 1, 2, 3, 4]] = .9, 0, .0, .4, .7 # channel = np.zeros((1, 3)) # channel[0, [0, 1, 2]] = .9, .8, .7 # channel = np.zeros((1, 3)) # channel[0, [0]] = 1 for SNR in SNRs: """ Generated Testing Data using the same channel as was used for training the mixture model and the nn """ data_gen = CommunicationDataGenerator( symbol_stream_shape=(1, number_symbols), SNR=SNR, plot=True, channel=channel) data_gen.random_symbol_stream() data_gen.send_through_channel(quantization_level, noise_levels=noise_levels) # plt.scatter(data_gen.channel_output.flatten(),data_gen.channel_output.flatten()) # plt.show() """ Setup Reduced ViterbiNet training data. """ reduced_state = 8 x_reduced, y_reduced, states_reduced, states_original, totals = data_gen.get_labeled_data_reduced_state( reduced_state) y_reduced = np.argmax( y_reduced, axis=1 ) # Fix for how the pytorch Cross Entropy expects class labels to be shown x_reduced = torch.Tensor(x_reduced) y_reduced = torch.Tensor(y_reduced) train_size = int(.6 * number_symbols) x_train_reduced = x_reduced[0:train_size, :] x_test_reduced = x_reduced[train_size::, :] y_train_reduced = y_reduced[0:train_size] y_test_reduced = y_reduced[train_size::] """ Setup Standard ViterbiNet training data. """ x, y = data_gen.get_labeled_data() y = np.argmax( y, axis=1 ) # Fix for how the pytorch Cross Entropy expects class labels to be shown x = torch.Tensor(x) y = torch.Tensor(y) train_size = int(.6 * number_symbols) x_train = x[0:train_size, :] x_test = x[train_size::, :] y_train = y[0:train_size] y_test = y[train_size::] """ Setup reduced NN and optimizer """ m = data_gen.alphabet.size channel_length = data_gen.CIR_matrix.shape[1] output_layer_size = reduced_state N, D_in, H1, H2, D_out = number_symbols, 1, 100, 50, output_layer_size net_reduced = models.ViterbiNet(D_in, H1, H2, D_out) optimizer_reduced = optim.Adam(net_reduced.parameters(), lr=1e-2) criterion_reduced = nn.NLLLoss() batch_size = 1000 train_cost_over_epoch_reduced = [] test_cost_over_epoch_reduced = [] # If training is perfect, then NN should be able to perfectly predict the class to which a test set belongs and thus the loss (KL Divergence) should be zero epochs = 50 for t in range(epochs): batch_indices = np.random.randint(len(y_train), size=(1, batch_size)) x_batch_reduced = x_train_reduced[(batch_indices)] y_batch_reduced = y_train_reduced[(batch_indices)] # Add "dropout to prevent overfitting data" net_reduced.zero_grad() output_reduced = net_reduced(x_batch_reduced) loss_reduced = criterion_reduced(output_reduced, y_batch_reduced.long()) loss_reduced.backward() optimizer_reduced.step() test_batch_indices = np.random.randint(len(y_test), size=(1, batch_size)) x_batch_test_reduced = x_test_reduced[(test_batch_indices)] y_batch_test_reduced = y_test_reduced[(test_batch_indices)] # Setup Accuracy test max_state_train_reduced = np.argmax( output_reduced.detach().numpy(), axis=1) max_state_test_reduced = np.argmax( net_reduced(x_batch_test_reduced).detach().numpy(), axis=1) train_cost_over_epoch_reduced.append( np.sum( np.not_equal(max_state_train_reduced, y_batch_reduced.detach().numpy())) / y_batch_reduced.size()) test_cost_over_epoch_reduced.append( np.sum( np.not_equal(max_state_test_reduced, y_batch_test_reduced.detach().numpy())) / y_batch_test_reduced.size()) """ Setup standard NN and optimizer """ m = data_gen.alphabet.size channel_length = data_gen.CIR_matrix.shape[1] # channel_length = channel_length-2 output_layer_size = np.power(m, channel_length) num_states = output_layer_size N, D_in, H1, H2, D_out = number_symbols, 1, 100, 50, output_layer_size net = models.ViterbiNet(D_in, H1, H2, D_out) optimizer = optim.Adam(net.parameters(), lr=1e-2) """ Train NN """ # This loss function looks at only the true class and takes the NLL of that. criterion = nn.NLLLoss() train_cost_over_epoch = [] test_cost_over_epoch = [] epochs = 500 for t in range(epochs): batch_indices = np.random.randint(len(y_train), size=(1, batch_size)) x_batch = x_train[(batch_indices)] y_batch = y_train[(batch_indices)] # Add "dropout to prevent overfitting data" net.zero_grad() net_reduced.zero_grad() output = net(x_batch) loss = criterion(output, y_batch.long()) loss.backward() optimizer.step() test_batch_indices = np.random.randint(len(y_test), size=(1, batch_size)) x_batch_test = x_test[(test_batch_indices)] y_batch_test = y_test[(test_batch_indices)] # Setup Accuracy test max_state_train = np.argmax(output.detach().numpy(), axis=1) max_state_test = np.argmax(net(x_batch_test).detach().numpy(), axis=1) train_cost_over_epoch.append( np.sum(np.not_equal(max_state_train, y_batch.detach().numpy())) / y_batch.size()) test_cost_over_epoch.append( np.sum( np.not_equal(max_state_test, y_batch_test.detach().numpy())) / y_batch_test.size()) """ Train Mixture Model """ mixture_model_training_data = data_gen.channel_output.flatten( )[0:train_size] num_sources = reduced_state mm = em_gausian(num_sources, mixture_model_training_data, 10, save=True, model=True) mm = mm.get_probability """ Train Reduced Mixture Model """ mixture_model_training_data_reduced = data_gen.channel_output.flatten( )[0:train_size] num_sources = reduced_state mm_reduced = em_gausian(num_sources, mixture_model_training_data_reduced, 10, save=True, model=True) mm_reduced = mm_reduced.get_probability """ User training data to train MMSE equalizer to then use on the test data """ mmse_equalizer = LinearMMSE() mmse_equalizer.train_equalizer(data_gen.symbol_stream_matrix, data_gen.channel_output, data_gen.symbol_stream_matrix, channel.size) """ Create new set of test data. """ ser_nn = [] ser_nn_reduced = [] ser_classic = [] ser_lmmse = [] for reps in range(1): del data_gen data_gen = CommunicationDataGenerator(symbol_stream_shape=(1, 10000), SNR=SNR, plot=True, channel=channel) data_gen.random_symbol_stream() data_gen.send_through_channel(quantization_level, noise_levels=noise_levels) """ Evaluate Reduced Neural Net Performance """ metric = NeuralNetworkMixtureModelMetric( net_reduced, mm_reduced, np.flip(data_gen.channel_output)) detected_nn = viterbi_setup_with_nodes( data_gen.alphabet, data_gen.channel_output, data_gen.CIR_matrix.shape[1], metric.metric, reduced_length=reduced_state, reduced=True) symbol_probabilities = get_symbol_probabilities( totals, states_original, data_gen.alphabet) survivor_state_path = get_symbols_from_probabilities( detected_nn, symbol_probabilities, data_gen.alphabet) ser_nn_reduced = symbol_error_rate_channel_compensated_NN_reduced( survivor_state_path, data_gen.symbol_stream_matrix, channel_length) """ Evaluate Neural Net Performance """ metric = NeuralNetworkMixtureModelMetric( net, mm, np.flip(data_gen.channel_output)) detected_nn = viterbi_setup_with_nodes( data_gen.alphabet, data_gen.channel_output, data_gen.CIR_matrix.shape[1], metric.metric) ser_nn = symbol_error_rate_channel_compensated_NN( detected_nn, data_gen.symbol_stream_matrix, channel_length) """ Compare to Classical Viterbi with full CSI """ metric = GaussianChannelMetric( channel, np.flip(data_gen.channel_output), quantization_level ) # This is a function to be used in the viterbi detected_classic = viterbi_setup_with_nodes( data_gen.alphabet, data_gen.channel_output, data_gen.CIR_matrix.shape[1], metric.metric) ser_classic = symbol_error_rate(detected_classic, data_gen.symbol_stream_matrix, channel_length) """ Evaluate LMMSE """ ser_lmmse.append( mmse_equalizer.test_equalizer(data_gen.symbol_stream_matrix, data_gen.channel_output)) ser_nn = np.average(ser_nn) ser_nn_reduced = np.average(ser_nn_reduced) ser_classic = np.average(ser_classic) ser_lmmse = np.average(ser_lmmse) """ Analyze SER performance """ linear_mmse_performance.append(ser_lmmse) viterbi_net_performance.append(ser_nn) classic_performance.append(ser_classic) viterbi_net_reduced_performance.append(ser_nn_reduced) figure, dictionary = plot_quantized_symbol_error_rates_nn_compare( SNRs_dB, [ classic_performance, linear_mmse_performance, viterbi_net_performance, viterbi_net_reduced_performance ], data_gen.get_info_for_plot()) time_path = "Output/SER_" + f"{time.time()}" + "curves.png" figure.savefig(time_path, format="png") text_path = "Output/SER_" + f"{time.time()}" + "curves.csv" pd.DataFrame.from_dict(dictionary).to_csv(text_path) figure.savefig(time_path, format="png")
def test_nn_validation(): viterbi_net_performance = [] threshold_performance = [] classic_performance = [] SNRs_dB = 2 SNRs = np.power(10, SNRs_dB/10) seed_generator = 0 data_gen = None """ Generated Testing Data using the same channel as was used for training the mixture model and the nn """ number_symbols = 2000 channel = np.zeros((1, 3)) channel[0, [0, 1, 2]] = 1, 0.1, 0.1 data_gen = training_data_generator(symbol_stream_shape=(1, number_symbols), SNR=SNRs, plot=True, channel=channel) data_gen.random_symbol_stream() data_gen.send_through_channel() """ Load in Trained Neural Network and verify that it is acceptable performance """ device = torch.device("cpu") num_inputs_for_nn = 1 x, y = data_gen.get_labeled_data(inputs=num_inputs_for_nn) y = np.argmax(y, axis=1) # Fix for how the pytorch Cross Entropy expects class labels to be shown x = torch.Tensor(x) y = torch.Tensor(y) train_size = int(.6 * number_symbols) x_train = x[0:train_size, :] x_test = x[train_size::, :] y_train = y[0:train_size] y_test = y[train_size::] """ Setup NN and optimizer """ m = data_gen.alphabet.size channel_length = data_gen.CIR_matrix.shape[1] N, D_in, H1, H2, D_out = number_symbols, 1, 100, 50, np.power(m, channel_length) net = models.ViterbiNet(D_in, H1, H2, D_out) # N, D_in, H1, H2, H3, D_out = number_symbols, num_inputs_for_nn, 20, 10, 10, np.power(m, channel_length) # net = models.deeper_viterbiNet(D_in, H1, H2, H3, D_out) # optimizer = optim.Adam(net.parameters(), lr=1e-4) optimizer = optim.SGD(net.parameters(), lr=1e-2) """ Train NN """ # criterion = nn.NLLLoss() criterion = nn.CrossEntropyLoss() train_cost_over_epoch = [] test_cost_over_epoch = [] batch_size = 500 # If training is perfect, then NN should be able to perfectly predict the class to which a test set belongs and thus the loss (KL Divergence) should be zero for t in range(1000): batch_indices = np.random.randint(len(y_train), size=(1, batch_size)) x_batch = x_train[(batch_indices)] y_batch = y_train[(batch_indices)] output = net(x_batch) loss = criterion(output, y_batch.long()) train_cost_over_epoch.append(loss) net.zero_grad() print(loss) loss.backward() optimizer.step() test_batch_indices = np.random.randint(len(y_test), size=(1, batch_size)) x_batch_test = x_test[(test_batch_indices)] y_batch_test = y_test[(test_batch_indices)] test_cost_over_epoch.append(criterion(net(x_batch_test), y_batch_test.long())) #Plots for NN training information plt.figure(2) plt.plot(test_cost_over_epoch, label='Test Error') plt.plot(train_cost_over_epoch, label='Train Error') plt.title(str(data_gen.get_info_for_plot()), fontdict={'fontsize': 10}) plt.xlabel("Epoch") plt.ylabel("Error") plt.legend(loc='upper left') plt.show() assert True
def test_results_nerual_net(): """ Train and save the neural network :return: """ """ Choose platform """ device = torch.device("cpu") # device = torch.device('cuda') # Uncomment this to run on GPU """ Setup Training Data """ number_symbols = 5000 channel = np.zeros((1, 4)) channel[0, [0, 1, 2, 3]] = 1, 0.6, 0.3, 0.2 data_gen = training_data_generator(symbol_stream_shape=(1, number_symbols), SNR=4, plot=True, channel=channel) # data_gen.setup_channel(shape=None) data_gen.random_symbol_stream() data_gen.send_through_channel() """ After sending through channel, symbol detection should be performed using something like a matched filter """ num_inputs_for_training_data = 1 x, y = data_gen.get_labeled_data(inputs=num_inputs_for_training_data) y = np.argmax( y, axis=1 ) # Fix for how the pytorch Cross Entropy expects class labels to be shown x = torch.Tensor(x) y = torch.Tensor(y) train_size = int(.6 * number_symbols) x_train = x[0:train_size, :] x_test = x[train_size::, :] y_train = y[0:train_size] y_test = y[train_size::] """ Setup NN and optimizer """ m = data_gen.alphabet.size channel_length = data_gen.CIR_matrix.shape[1] # N is batch size; D_in is input dimension; # H is hidden dimension; D_out is output dimension. N, D_in, H1, H2, D_out = number_symbols, num_inputs_for_training_data, 100, 50, np.power( m, channel_length) net = models.ViterbiNet(D_in, H1, H2, D_out) #TODO use better optimizer optimizer = optim.SGD(net.parameters(), lr=1e-2) optimizer = optim.Adam(net.parameters(), lr=1e-2) """ Train NN """ criterion = nn.CrossEntropyLoss() # criterion = nn.NLLLoss() train_cost_over_epoch = [] test_cost_over_epoch = [] # If training is perfect, then NN should be able to perfectly predict the class to which a test set belongs and thus the loss (KL Divergence) should be zero for t in range(400): output = net(x_train) loss = criterion(output, y_train.long()) train_cost_over_epoch.append(loss) net.zero_grad() print(loss) loss.backward() optimizer.step() test_cost_over_epoch.append(criterion(net(x_test), y_test.long())) path = "Output/nn.pt" torch.save(net, path) """ Test NN """ plt.figure() plt.plot(test_cost_over_epoch, label='Test Error') plt.plot(train_cost_over_epoch, label='Train Error') plt.title(str(data_gen.get_info_for_plot()), fontdict={'fontsize': 10}) plt.xlabel("Epoch") plt.ylabel("Error") plt.legend(loc='upper left') path = "Output/Neural_Network_Convergence.png" path = "Output/NN_ERROR" + str(number_symbols) + " symbols " \ + str(num_inputs_for_training_data) + " inputs " + str(time.time())+"curves.png" plt.savefig(path, format="png") plt.show() assert True
def test_nano_data_nerual_net(): viterbi_net_performance = [] """ Generated Testing Data using the same channel as was used for training the mixture model and the nn """ # Load data from path train_path = 'mc_data/5_cm_train.csv' test_path = 'mc_data/5_cm_test.csv' true_path = 'mc_data/input_string.csv' # train_path = 'mc_data/20_cm_train.csv' # test_path = 'mc_data/20_cm_test.csv' test_input_sequence = 'mc_data/input_string.csv' test_input_sequence = np.loadtxt(test_input_sequence, delimiter=",") true_input_string = np.loadtxt(true_path, delimiter=",") # For now just making a channel that represents some estimated memory length of the true channel SNRs_dB = np.linspace(5, 5, 1) # SNRs_dB = np.linspace(6, 10,3) SNRs = np.power(10, SNRs_dB / 10) channel = np.zeros((1, 8)) channel[0, [0]] = 1 train_time, train_measurement = load_file(train_path) test_time, test_measurement = load_file(test_path) # plt.plot(test_measurement) # plt.show() pulse_shape = get_pulse(train_time, train_measurement) # Train with a random symbol stream generated from the training set pulse number_symbols = 10000 data_gen = CommunicationDataGenerator(SNR=SNRs, symbol_stream_shape=(1, number_symbols), constellation="onOffKey", channel=channel) data_gen.random_symbol_stream() # 5 is true perdiod symbol_period = 5 data_gen.modulate_sampled_pulse(pulse_shape, symbol_period) data_gen.filter_sample_modulated_pulse(pulse_shape, symbol_period) # Test for making sure alignment is correct # ser = symbol_error_rate_mc_data(data_gen.symbol_stream_matrix.flatten(), data_gen.channel_output.flatten(), channel.size) """ Load in Trained Neural Network and verify that it is acceptable performance """ reduced_state = 4 # x, y, states_reduced, states_original, totals = data_gen.get_labeled_data_reduced_state(reduced_state) x, y = data_gen.get_labeled_data() y = np.argmax( y, axis=1 ) # Fix for how the pytorch Cross Entropy expects class labels to be shown x = torch.Tensor(x) y = torch.Tensor(y) train_size = int(.6 * number_symbols) x_train = x[0:train_size, :] x_test = x[train_size::, :] y_train = y[0:train_size] y_test = y[train_size::] """ Setup NN and optimizer """ channel_length = data_gen.CIR_matrix.shape[1] # test_length = channel_length-1 output_layer_size = reduced_state output_layer_size = np.power(data_gen.alphabet.size, channel_length) N, D_in, H1, H2, D_out = number_symbols, 1, 100, 50, output_layer_size net = models.ViterbiNet(D_in, H1, H2, D_out) optimizer = optim.Adam(net.parameters(), lr=1e-2) """ Train NN """ criterion = nn.NLLLoss() # criterion = nn.CrossEntropyLoss() train_cost_over_epoch = [] test_cost_over_epoch = [] batch_size = 1000 # If training is perfect, then NN should be able to perfectly predict the class to which a test set belongs and thus the loss (KL Divergence) should be zero epochs = 900 for t in range(epochs): batch_indices = np.random.randint(len(y_train), size=(1, batch_size)) x_batch = x_train[(batch_indices)] y_batch = y_train[(batch_indices)] # Add "dropout to prevent overfitting data" output = net(x_batch) loss = criterion(output, y_batch.long()) net.zero_grad() loss.backward() optimizer.step() test_batch_indices = np.random.randint(len(y_test), size=(1, batch_size)) x_batch_test = x_test[(test_batch_indices)] y_batch_test = y_test[(test_batch_indices)] max_state_train = np.argmax(output.detach().numpy(), axis=1) max_state_test = np.argmax(net(x_batch_test).detach().numpy(), axis=1) train_cost_over_epoch.append( np.sum(np.not_equal(max_state_train, y_batch.detach().numpy())) / y_batch.size()) test_cost_over_epoch.append( np.sum(np.not_equal(max_state_test, y_batch_test.detach().numpy())) / y_batch_test.size()) """ Train Mixture Model """ # num_sources = pow(data_gen.alphabet.size, data_gen.CIR_matrix.shape[1]) num_sources = reduced_state mixture_model_training_data = data_gen.channel_output.flatten( )[0:train_size] mm = em_gausian(num_sources, mixture_model_training_data, 10, save=True, model=True) mm = mm.get_probability """ Create new set of test data. """ # For comparing generated data to the true test data # del data_gen # number_symbols = 2000 # data_gen = CommunicationDataGenerator(SNR=SNRs, symbol_stream_shape=(1, number_symbols), constellation="onOffKey", channel= channel) # data_gen.random_symbol_stream() # data_gen.modulate_sampled_pulse(pulse_shape, symbol_period) # data_gen.filter_sample_modulated_pulse(pulse_shape, symbol_period) # generated_output = data_gen.channel_output del data_gen data_gen = CommunicationDataGenerator(SNR=SNRs, symbol_stream_shape=(1, number_symbols), constellation="onOffKey", channel=channel) data_gen.random_symbol_stream(true_input_string) data_gen.provide_transmitted_matrix(test_measurement) data_gen.filter_sample_modulated_pulse(pulse_shape, symbol_period) # # plt.scatter(data_gen.channel_output, data_gen.channel_output) # plt.scatter(generated_output, generated_output) # plt.show() """ Use Test Data """ """ Evaluate Neural Net Performance """ # metric = NeuralNetworkMixtureModelMetric(net, mm, data_gen.channel_output) metric = NeuralNetworkMixtureModelMetric(net, mm, np.flip(data_gen.channel_output)) # detected_nn = viterbi_setup_with_nodes(data_gen.alphabet, data_gen.channel_output, data_gen.CIR_matrix.shape[1], # metric.metric, reduced_length=reduced_state, reduced=True) detected_nn = viterbi_setup_with_nodes(data_gen.alphabet, data_gen.channel_output, data_gen.CIR_matrix.shape[1], metric.metric) # symbol_probabilities = get_symbol_probabilities(totals, states_original, data_gen.alphabet) # detected_nn = get_symbols_from_probabilities(detected_nn, symbol_probabilities, data_gen.alphabet) ser_nn = symbol_error_rate_mc_data(detected_nn, data_gen.symbol_stream_matrix, channel_length) # ser_nn = symbol_error_rate_channel_compensated_NN(detected_nn, data_gen.symbol_stream_matrix, channel_length) viterbi_net_performance.append(ser_nn) print(viterbi_net_performance) path = "Output/SER.pickle" pickle_out = open(path, "wb") pickle.dump([viterbi_net_performance], pickle_out) pickle_out.close() # figure, dictionary = plot_symbol_error_rates(SNRs_dB, [classic_performance, linear_mmse_performance, viterbi_net_performance], data_gen.get_info_for_plot()) # time_path = "Output/SER_"+f"{time.time()}"+"curves.png" # figure.savefig(time_path, format="png") # text_path = "Output/SER_"+f"{time.time()}"+"curves.csv" # pd.DataFrame.from_dict(dictionary).to_csv(text_path) # figure.savefig(time_path, format="png") # #Plots for NN training information plt.figure(2) plt.plot(test_cost_over_epoch, label='Test Error') plt.plot(train_cost_over_epoch, label='Train Error') plt.title(str(data_gen.get_info_for_plot()), fontdict={'fontsize': 10}) plt.xlabel("Epoch") plt.ylabel("Error") plt.legend(loc='upper right') path = f"Output/Neural_Network{time.time()}_Convergence.png" plt.savefig(path, format="png")