MPI analysis, work on DC tracking
This commit is contained in:
@@ -33,6 +33,7 @@ classdef FFE < handle
|
||||
epochs_dd
|
||||
dd_len_fraction
|
||||
mu_dc
|
||||
adaptive_dc_enabled
|
||||
e_dc
|
||||
|
||||
P % covariance matrix of rls
|
||||
@@ -48,6 +49,8 @@ classdef FFE < handle
|
||||
mu_optimization
|
||||
mu_optimization_iter = 0;
|
||||
mu_optimization_len
|
||||
plot_mu_optimization = 0;
|
||||
mu_optimization_fignum = 3010;
|
||||
end
|
||||
|
||||
methods
|
||||
@@ -67,12 +70,15 @@ classdef FFE < handle
|
||||
options.epochs_dd = 5;
|
||||
options.dd_len_fraction = 1;
|
||||
options.mu_dc = 0;
|
||||
options.adaptive_dc_enabled = false;
|
||||
|
||||
options.decide = false;
|
||||
|
||||
options.save_debug = 0;
|
||||
options.optmize_mus = 0;
|
||||
options.mu_optimization_len = 2^15;
|
||||
options.plot_mu_optimization = 0;
|
||||
options.mu_optimization_fignum = 3010;
|
||||
|
||||
end
|
||||
|
||||
@@ -175,12 +181,40 @@ classdef FFE < handle
|
||||
epochs = 1;
|
||||
end
|
||||
|
||||
P_err = 0;
|
||||
alpha = 0.98;
|
||||
err_prev = 0;
|
||||
gamma_dc = 1e-6;
|
||||
mu_min = 1e-6;
|
||||
mu_max = 3e-1;
|
||||
|
||||
debug_enabled = obj.save_debug;
|
||||
if debug_enabled
|
||||
n_symbols_debug = ceil(N / obj.sps);
|
||||
obj.debug_struct.error = NaN(1,n_symbols_debug);
|
||||
obj.debug_struct.error_first_epoch = NaN(1,n_symbols_debug);
|
||||
obj.debug_struct.main_cursor = NaN(1,n_symbols_debug);
|
||||
obj.debug_struct.mu_nlms = NaN(1,n_symbols_debug);
|
||||
obj.debug_struct.update_gradient = NaN(1,n_symbols_debug);
|
||||
obj.debug_struct.mu_dc_eff = NaN(1,n_symbols_debug);
|
||||
obj.debug_struct.e_dc_eff = NaN(1,n_symbols_debug);
|
||||
|
||||
if training
|
||||
obj.debug_struct.error_tr = NaN(1,n_symbols_debug);
|
||||
obj.debug_struct.update_tr = NaN(1,n_symbols_debug);
|
||||
else
|
||||
obj.debug_struct.error_dd = NaN(1,n_symbols_debug);
|
||||
obj.debug_struct.update = NaN(1,n_symbols_debug);
|
||||
end
|
||||
end
|
||||
|
||||
for epoch = 1 : epochs
|
||||
symbol = 0;
|
||||
% obj.e_dc = 0;
|
||||
for sample = 1 : obj.sps : N
|
||||
|
||||
symbol = symbol+1;
|
||||
mu_dc_eff = 0;
|
||||
|
||||
U = x(obj.order+sample-1:-1:sample);
|
||||
|
||||
@@ -240,31 +274,42 @@ classdef FFE < handle
|
||||
end
|
||||
|
||||
if obj.mu_dc ~= 0
|
||||
obj.e_dc = obj.e_dc + obj.mu_dc * err(symbol);
|
||||
if obj.adaptive_dc_enabled
|
||||
delta_mu = gamma_dc * err(symbol) * err_prev * (U.'*U);
|
||||
obj.mu_dc = min(max(obj.mu_dc + delta_mu,mu_min),mu_max);
|
||||
err_prev = err(symbol);
|
||||
P_err = alpha*P_err + (1-alpha)*err(symbol)^2;
|
||||
mu_dc_eff = obj.mu_dc / (P_err + eps);
|
||||
else
|
||||
mu_dc_eff = obj.mu_dc;
|
||||
end
|
||||
|
||||
obj.e_dc = obj.e_dc + mu_dc_eff * err(symbol);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
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
|
||||
if debug_enabled && epoch == 1
|
||||
obj.debug_struct.error_first_epoch(1,symbol) = err(symbol) * err(symbol)';
|
||||
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);
|
||||
|
||||
if debug_enabled && epoch == epochs
|
||||
error_power = err(symbol) * err(symbol)';
|
||||
update_power = update.'*update ./ (rms(obj.e) + eps);
|
||||
obj.debug_struct.error(1,symbol) = error_power;
|
||||
obj.debug_struct.main_cursor(1,symbol) = abs(obj.e(maincursor_pos));
|
||||
obj.debug_struct.mu_nlms(1,symbol) = weight;
|
||||
obj.debug_struct.update_gradient(1,symbol) = grad.'*grad;
|
||||
obj.debug_struct.mu_dc_eff(1,symbol) = mu_dc_eff;
|
||||
obj.debug_struct.e_dc_eff(1,symbol) = obj.e_dc;
|
||||
|
||||
if training
|
||||
obj.debug_struct.error_tr(1,symbol) = error_power;
|
||||
obj.debug_struct.update_tr(1,symbol) = update_power;
|
||||
else
|
||||
obj.debug_struct.error_dd(1,symbol) = error_power;
|
||||
obj.debug_struct.update(1,symbol) = update_power;
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -272,17 +317,6 @@ classdef FFE < handle
|
||||
|
||||
end
|
||||
|
||||
function N_dd = ddLength(obj,N)
|
||||
if isempty(obj.dd_len_fraction) || obj.dd_len_fraction <= 0 || obj.dd_len_fraction >= 1
|
||||
N_dd = N;
|
||||
return
|
||||
end
|
||||
|
||||
N_dd = floor(N * obj.dd_len_fraction);
|
||||
N_dd = max(obj.sps,N_dd);
|
||||
N_dd = min(N,N_dd);
|
||||
end
|
||||
|
||||
function optimizeMus(obj,x,d)
|
||||
[x_opt,d_opt,N_opt] = obj.optimizationSignals(x,d);
|
||||
|
||||
@@ -333,6 +367,10 @@ classdef FFE < handle
|
||||
fprintf("\nFFE mu opt done: mu_tr=%9.3e, BER=%9.3e\n", ...
|
||||
obj.mu_tr,obj.mu_optimization.MinObjective);
|
||||
end
|
||||
|
||||
if obj.plot_mu_optimization
|
||||
obj.plotMuOptimization();
|
||||
end
|
||||
end
|
||||
|
||||
function [x_opt,d_opt,N_opt] = optimizationSignals(obj,x,d)
|
||||
@@ -402,5 +440,99 @@ classdef FFE < handle
|
||||
obj.save_debug = old_debug;
|
||||
obj.mu_dc = old_mu_dc;
|
||||
end
|
||||
|
||||
function plotMuOptimization(obj)
|
||||
if isempty(obj.mu_optimization)
|
||||
return
|
||||
end
|
||||
|
||||
X = obj.mu_optimization.XTrace;
|
||||
objective = obj.mu_optimization.ObjectiveTrace;
|
||||
objective = objective(:);
|
||||
valid = isfinite(objective);
|
||||
|
||||
if isempty(X) || ~any(valid)
|
||||
return
|
||||
end
|
||||
|
||||
var_names = X.Properties.VariableNames;
|
||||
n_vars = numel(var_names);
|
||||
eval_idx = (1:numel(objective)).';
|
||||
objective_plot = obj.positiveObjectiveForLogPlot(objective);
|
||||
best_plot = obj.positiveObjectiveForLogPlot(cummin(objective));
|
||||
|
||||
figure(obj.mu_optimization_fignum);
|
||||
clf;
|
||||
t = tiledlayout(2,2,"TileSpacing","compact","Padding","compact");
|
||||
title(t,"FFE Bayesian mu optimization");
|
||||
|
||||
nexttile;
|
||||
h_candidate = semilogy(eval_idx,objective_plot,"o-","DisplayName","candidate");
|
||||
obj.addOptimizationDataTips(h_candidate,X,objective,objective_plot,eval_idx,var_names);
|
||||
hold on;
|
||||
h_best_trace = semilogy(eval_idx,best_plot,"k-","LineWidth",1.2,"DisplayName","best so far");
|
||||
h_best_trace.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow("Evaluation",eval_idx);
|
||||
h_best_trace.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow("Best BER",best_plot);
|
||||
grid on;
|
||||
xlabel("Evaluation");
|
||||
ylabel("BER");
|
||||
legend("Location","best");
|
||||
|
||||
if n_vars < 2
|
||||
return
|
||||
end
|
||||
|
||||
pairs = nchoosek(1:n_vars,2);
|
||||
n_pair_plots = min(size(pairs,1),3);
|
||||
[~,best_idx] = min(objective);
|
||||
|
||||
for pair_idx = 1:n_pair_plots
|
||||
nexttile;
|
||||
x_name = var_names{pairs(pair_idx,1)};
|
||||
y_name = var_names{pairs(pair_idx,2)};
|
||||
x_data = X.(x_name);
|
||||
y_data = X.(y_name);
|
||||
c_data = log10(objective_plot);
|
||||
|
||||
h_scatter = scatter(log10(x_data),log10(y_data),35,c_data,"filled");
|
||||
obj.addOptimizationDataTips(h_scatter,X,objective,objective_plot,eval_idx,var_names);
|
||||
hold on;
|
||||
h_best = plot(log10(x_data(best_idx)),log10(y_data(best_idx)),"kp", ...
|
||||
"MarkerSize",12, ...
|
||||
"MarkerFaceColor","y", ...
|
||||
"DisplayName","best");
|
||||
obj.addOptimizationDataTips(h_best,X(best_idx,:),objective(best_idx),objective_plot(best_idx),eval_idx(best_idx),var_names);
|
||||
grid on;
|
||||
xlabel("log10(" + string(x_name) + ")");
|
||||
ylabel("log10(" + string(y_name) + ")");
|
||||
cb = colorbar;
|
||||
cb.Label.String = "log10(BER)";
|
||||
title(string(x_name) + " vs " + string(y_name));
|
||||
end
|
||||
end
|
||||
|
||||
function addOptimizationDataTips(~,plot_handle,X,objective,objective_plot,eval_idx,var_names)
|
||||
plot_handle.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow("Evaluation",eval_idx);
|
||||
plot_handle.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow("BER",objective);
|
||||
plot_handle.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow("BER shown",objective_plot);
|
||||
|
||||
for var_idx = 1:numel(var_names)
|
||||
var_name = var_names{var_idx};
|
||||
plot_handle.DataTipTemplate.DataTipRows(end+1) = dataTipTextRow(var_name,X.(var_name));
|
||||
end
|
||||
end
|
||||
|
||||
function objective_plot = positiveObjectiveForLogPlot(~,objective)
|
||||
objective_plot = objective;
|
||||
positive_values = objective(isfinite(objective) & objective > 0);
|
||||
|
||||
if isempty(positive_values)
|
||||
floor_value = 1e-12;
|
||||
else
|
||||
floor_value = min(positive_values) / 10;
|
||||
end
|
||||
|
||||
objective_plot(~isfinite(objective_plot) | objective_plot <= 0) = floor_value;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user