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:
Silas Oettinghaus
2026-05-12 10:40:03 +02:00
parent 56b48095db
commit f883071dec
13 changed files with 524 additions and 65 deletions

View File

@@ -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

View File

@@ -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