FFE now has a automatic optimization of the mu-parameters -> enables the fast comparison of LMS, NLMS and RLS and also good for very long filters (1000+ taps) which might be unstable else.
Minor changes here and there
This commit is contained in:
@@ -15,7 +15,7 @@ classdef FFE < handle
|
||||
e
|
||||
e_tr
|
||||
error
|
||||
debug_struct
|
||||
|
||||
|
||||
len_tr
|
||||
mu_tr
|
||||
@@ -31,6 +31,13 @@ classdef FFE < handle
|
||||
constellation % symbol constellation
|
||||
|
||||
decide %wether to return the (hard) decisions or the result after FFE (soft)
|
||||
|
||||
save_debug = 0;
|
||||
debug_struct
|
||||
|
||||
optmize_mus = 0;
|
||||
mu_optimization
|
||||
mu_optimization_iter = 0;
|
||||
end
|
||||
|
||||
methods
|
||||
@@ -51,6 +58,9 @@ classdef FFE < handle
|
||||
|
||||
options.decide = false;
|
||||
|
||||
options.save_debug = 0;
|
||||
options.optmize_mus = 0;
|
||||
|
||||
end
|
||||
|
||||
fn = fieldnames(options);
|
||||
@@ -75,6 +85,12 @@ classdef FFE < handle
|
||||
delta = 0.05;
|
||||
obj.P = (1/delta) * eye(obj.order);
|
||||
|
||||
if obj.optmize_mus
|
||||
obj.optimizeMus(X.signal,D.signal);
|
||||
obj.e = zeros(obj.order,1);
|
||||
obj.P = (1/delta) * eye(obj.order);
|
||||
end
|
||||
|
||||
% Training Mode
|
||||
training = 1;
|
||||
showviz = 0;
|
||||
@@ -131,7 +147,6 @@ classdef FFE < handle
|
||||
mask = ones(obj.order,1);
|
||||
maincursor_pos=ceil(length(obj.e)/2);
|
||||
always_ideal_decision = 0;
|
||||
save_debug = 0;
|
||||
grad =0;
|
||||
weight = 0;
|
||||
update = 0;
|
||||
@@ -205,21 +220,88 @@ classdef FFE < handle
|
||||
end
|
||||
|
||||
|
||||
if save_debug
|
||||
if obj.save_debug
|
||||
obj.debug_struct.error(epoch,symbol) = err(symbol) * err(symbol)'; % Instantaneous square error
|
||||
|
||||
if training
|
||||
obj.debug_struct.error_tr(epoch,symbol) = err(symbol) * err(symbol)'; % Instantaneous square error
|
||||
obj.debug_struct.update_tr(epoch,symbol) = update.'*update ./ rms(obj.e);
|
||||
else
|
||||
% if symbol == length(d)
|
||||
% M = numel(unique(d));
|
||||
% bits_ref = PAMmapper(M,0).demap(d);
|
||||
% bits_eq = PAMmapper(M,0).demap(d_hat);
|
||||
% [~,~,obj.debug_struct.ber(epoch)] = calc_ber(bits_eq,bits_ref);
|
||||
% end
|
||||
end
|
||||
obj.debug_struct.main_cursor(epoch,symbol) = abs(obj.e(maincursor_pos));
|
||||
obj.debug_struct.mu_nlms(epoch,symbol) = weight;
|
||||
obj.debug_struct.update_gradient(epoch,symbol) = grad.'*grad;
|
||||
obj.debug_struct.update(epoch,symbol) = update.'*update ./ rms(obj.e);
|
||||
|
||||
% obj.debug_struct.main_cursor(epoch,symbol) = abs(obj.e(maincursor_pos));
|
||||
% obj.debug_struct.mu_nlms(epoch,symbol) = weight;
|
||||
% obj.debug_struct.update_gradient(epoch,symbol) = grad.'*grad;
|
||||
% obj.debug_struct.update(epoch,symbol) = update.'*update ./ rms(obj.e);
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function optimizeMus(obj,x,d)
|
||||
switch obj.adaption_technique
|
||||
case adaption_method.lms
|
||||
mu_range = [1e-5, 1e-2];
|
||||
case adaption_method.nlms
|
||||
mu_range = [1e-3, 5e-1];
|
||||
case adaption_method.rls
|
||||
mu_range = [0.98, 0.99999];
|
||||
end
|
||||
|
||||
mu_tr_var = optimizableVariable("mu_tr",mu_range,"Transform","log");
|
||||
vars = mu_tr_var;
|
||||
if obj.dd_mode
|
||||
vars = [vars, optimizableVariable("mu_dd",mu_range,"Transform","log")];
|
||||
end
|
||||
obj.mu_optimization_iter = 0;
|
||||
obj.mu_optimization = bayesopt(@(p)obj.muObjective(p,x,d),vars, ...
|
||||
"MaxObjectiveEvaluations",10, ...
|
||||
"AcquisitionFunctionName","expected-improvement-plus", ...
|
||||
"IsObjectiveDeterministic",false, ...
|
||||
"Verbose",0, ...
|
||||
"PlotFcn",[]);
|
||||
obj.mu_tr = obj.mu_optimization.XAtMinObjective.mu_tr;
|
||||
if obj.dd_mode
|
||||
obj.mu_dd = obj.mu_optimization.XAtMinObjective.mu_dd;
|
||||
end
|
||||
fprintf("\nFFE mu opt done: mu_tr=%9.3e, mu_dd=%9.3e, metric=%9.3e\n", ...
|
||||
obj.mu_tr,obj.mu_dd,obj.mu_optimization.MinObjective);
|
||||
end
|
||||
|
||||
function objective = muObjective(obj,params,x,d)
|
||||
old_debug = obj.save_debug;
|
||||
obj.save_debug = 1;
|
||||
obj.e = zeros(obj.order,1);
|
||||
obj.P = (1/0.05) * eye(obj.order);
|
||||
obj.debug_struct = struct();
|
||||
obj.equalize(x,d,params.mu_tr,obj.epochs_tr,obj.len_tr,1,0);
|
||||
if obj.dd_mode
|
||||
obj.equalize(x,d,params.mu_dd,obj.epochs_dd,numel(x),0,0);
|
||||
objective = mean(obj.debug_struct.error(end,:),"omitnan");
|
||||
else
|
||||
objective = mean(obj.debug_struct.error_tr(end,:),"omitnan");
|
||||
end
|
||||
if ~isfinite(objective)
|
||||
objective = inf;
|
||||
end
|
||||
obj.mu_optimization_iter = obj.mu_optimization_iter + 1;
|
||||
if obj.dd_mode
|
||||
fprintf("\rFFE mu opt %02d: mu_tr=%9.3e, mu_dd=%9.3e, metric=%9.3e", ...
|
||||
obj.mu_optimization_iter,params.mu_tr,params.mu_dd,objective);
|
||||
else
|
||||
fprintf("\rFFE mu opt %02d: mu_tr=%9.3e, metric=%9.3e", ...
|
||||
obj.mu_optimization_iter,params.mu_tr,objective);
|
||||
end
|
||||
obj.save_debug = old_debug;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -54,7 +54,7 @@ classdef DBHandler < handle
|
||||
options.password, ... % Password (or getSecret)
|
||||
"Vendor", "MySQL", ...
|
||||
"Server", options.server, ...
|
||||
"PortNumber", 3306, ...
|
||||
"PortNumber", options.port, ...
|
||||
"JDBCDriverLocation", "C:\Users\Silas\Documents\mysql-connector-j-9.3.0\mysql-connector-j-9.3.0.jar");
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user