import numpy as np
from matplotlib import pyplot as plt
from denspp.offline.plot_helper import (
cm_to_inch,
get_plot_color,
get_textsize_paper,
save_figure,
)
[docs]
def plot_loss(
loss_train: list,
loss_valid: list,
loss_type: str,
path2save: str = "",
epoch_zoom=None,
do_logy: bool = False,
show_plot: bool = False,
) -> None:
"""Plotting the loss of any DNN-based learning method
Args:
loss_train: List with loss values from training
loss_valid: List with loss values from validation
loss_type: Name of the metric type
path2save: Path to save the figure
epoch_zoom: Do zoom on defined range [list]
do_logy: Boolean for logarithmic y-axis scale
show_plot: Showing and blocking the plots
Return:
None
"""
# --- Pre-Processing
plot_metrics = np.zeros((len(loss_train), 2), dtype=float)
plot_metrics[:, 0] = np.array(loss_train)
plot_metrics[:, 1] = np.array(loss_valid)
# --- Plotting
plt.figure(figsize=(cm_to_inch(10), cm_to_inch(8)))
axs = list()
axs.append(plt.subplot(1, 1, 1))
epochs_ite = np.array([idx + 1 for idx in range(plot_metrics[:, 0].size)])
axs[0].plot(epochs_ite, plot_metrics[:, 0], color="k", marker=".", label="Train.")
axs[0].plot(epochs_ite, plot_metrics[:, 1], color="r", marker=".", label="Valid.")
pos = np.linspace(epochs_ite[0], epochs_ite[-1], num=11, endpoint=True, dtype=int)
plt.yscale("log" if do_logy else "linear")
plt.xticks(pos)
plt.xlim([pos[0], pos[-1]])
plt.grid()
plt.legend()
plt.title(f"{loss_type} = {plot_metrics.max() if 'Acc' in loss_type else plot_metrics.min():.3f}")
plt.xlabel("Epoch")
plt.ylabel(f"{loss_type}")
# --- Plot zooming component
if isinstance(epoch_zoom, list) and len(epoch_zoom) > 0:
x0 = int(epoch_zoom[0])
x1 = int(epoch_zoom[1]) if len(epoch_zoom) == 2 else int(plot_metrics.shape[0] - 1)
pos = np.arange(x0, x1)
min_value = np.min((plot_metrics[pos, 0], plot_metrics[pos, 1]))
max_value = np.max((plot_metrics[pos, 0], plot_metrics[pos, 1]))
axins0 = axs[0].inset_axes(
[0.45, 0.02, 0.5, 0.43],
xticklabels=[],
xlim=(x0 - 0.5, x1 + 0.5),
ylim=(0.99 * min_value, 1.01 * max_value),
)
axins0.plot(epochs_ite, plot_metrics[:, 0], color="k", marker=".", label="Train.")
axins0.plot(epochs_ite, plot_metrics[:, 1], color="r", marker=".", label="Valid.")
axins0.grid()
axs[0].tick_params(direction="in")
axs[0].indicate_inset_zoom(axins0, edgecolor="black")
addon = "_zoomed"
else:
addon = ""
plt.tight_layout()
if path2save:
save_figure(plt, path2save, f"report_metric_{loss_type}" + addon)
if show_plot:
plt.show(block=True)
[docs]
def plot_custom_loss_classifier(
data: list,
loss_name: str,
fold_num: int,
do_logy: bool = False,
epoch_zoom=None,
path2save: str = "",
show_plot: bool = False,
) -> None:
"""Plotting the custom loss of each epoch from training (e.g. Signal-to-Noise Ratio (SNR)
:param data: List with values from each epoch
:param loss_name: String with name of loss function
:param fold_num: Integer with fold number
:param do_logy: Boolean for plotting the y-axis logarithmic scale
:param epoch_zoom: Do zoom on defined range [list]
:param path2save: Path to save the figure
:param show_plot: If true, show plot
:return: None
"""
epochs_ite = np.array([idx + 1 for idx in range(len(data))])
metric0 = np.array(data) if "ptq_loss" not in loss_name else np.array(data).flatten()
pos = np.linspace(epochs_ite[0], epochs_ite[-1], num=11, endpoint=True, dtype=int)
plt.figure(figsize=(cm_to_inch(16), cm_to_inch(8)))
plt.rcParams.update({"font.size": get_textsize_paper()})
axs = list()
axs.append(plt.subplot(1, 1, 1))
axs[0].plot(epochs_ite, metric0, marker=".", markersize=5)
axs[0].set_xlabel("Epoch")
axs[0].set_ylabel(f"{loss_name}")
axs[0].set_yscale("log" if do_logy else "linear")
# --- Plot zooming component
if isinstance(epoch_zoom, list) and len(epoch_zoom) > 0:
x0 = int(epoch_zoom[0])
x1 = int(epoch_zoom[1]) if len(epoch_zoom) == 2 else int(metric0.shape[0] - 1)
pos = np.arange(x0, x1)
min_value = np.min(metric0[pos, :])
max_value = np.max(metric0[pos, :])
axins0 = axs[0].inset_axes(
[0.45, 0.02, 0.5, 0.43],
xticklabels=[],
xlim=(x0 - 0.5, x1 + 0.5),
ylim=(0.99 * min_value, 1.01 * max_value),
)
axins0.plot(epochs_ite, metric0, color="k", marker=".", markersize=6)
axins0.grid()
axs[0].tick_params(direction="in")
axs[0].indicate_inset_zoom(axins0, edgecolor="black")
addon = "_zoomed"
else:
addon = ""
plt.xticks(pos)
plt.xlim([pos[0], pos[-1]])
plt.grid()
plt.tight_layout(pad=0.5)
if path2save:
save_figure(plt, path2save, f"report_metric_{loss_name}_fold{fold_num:03d}" + addon)
if show_plot:
plt.show(block=True)
[docs]
def plot_custom_loss_autoencoder(
data: list,
loss_name: str,
do_boxplot: bool = False,
do_logy: bool = False,
epoch_zoom=None,
path2save: str = "",
show_plot: bool = False,
) -> None:
"""Plotting the custom loss of each epoch from training (e.g. Signal-to-Noise Ratio (SNR)
:param data: List with values from each epoch
:param loss_name: String with name of loss function
:param do_boxplot: If true, plot boxplot
:param do_logy: Boolean for plotting the y-axis logarithmic scale
:param epoch_zoom: Do zoom on defined range [list]
:param path2save: Path to save the figure
:param show_plot: If true, show plot
:return: None
"""
metric_processed = list()
if not do_boxplot:
metric0 = np.zeros(shape=(len(data), 3), dtype=float)
for idx, metric_epoch in enumerate(data):
metric0[idx, :] = (
metric_epoch.min(),
np.median(metric_epoch),
metric_epoch.max(),
)
metric_processed.append(metric0)
else:
metric_processed.append(data)
# --- Plotting
for idx, metric0 in enumerate(metric_processed):
epochs_ite = np.array([idx + 1 for idx in range(metric0[:, 0].size)])
pos = np.linspace(epochs_ite[0], epochs_ite[-1], num=11, endpoint=True, dtype=int)
plt.figure(figsize=(cm_to_inch(16), cm_to_inch(8)))
plt.rcParams.update({"font.size": get_textsize_paper()})
axs = list()
axs.append(plt.subplot(1, 1, 1))
axs[0].plot(epochs_ite, metric0, marker=".", markersize=5)
axs[0].set_xlabel("Epoch")
axs[0].set_ylabel(f"{loss_name} (dB)")
axs[0].set_yscale("log" if do_logy else "linear")
if not do_boxplot:
plt.plot(
epochs_ite,
metric0[:, 0],
color=get_plot_color(0),
marker=".",
label="min",
)
plt.plot(
epochs_ite,
metric0[:, 1],
color=get_plot_color(1),
marker=".",
label="mean",
)
plt.plot(
epochs_ite,
metric0[:, 2],
color=get_plot_color(2),
marker=".",
label="max",
)
plt.legend()
else:
plt.boxplot(data, patch_artist=True, showfliers=False)
# --- Plot zooming component
if isinstance(epoch_zoom, list) and len(epoch_zoom) > 0:
x0 = int(epoch_zoom[0])
x1 = int(epoch_zoom[1]) if len(epoch_zoom) == 2 else int(metric0.shape[0] - 1)
pos = np.arange(x0, x1)
min_value = np.min(metric0[pos, :])
max_value = np.max(metric0[pos, :])
axins0 = axs[0].inset_axes(
[0.45, 0.02, 0.5, 0.43],
xticklabels=[],
xlim=(x0 - 0.5, x1 + 0.5),
ylim=(0.99 * min_value, 1.01 * max_value),
)
axins0.plot(epochs_ite, metric0, color="k", marker=".", markersize=6)
axins0.grid()
axs[0].tick_params(direction="in")
axs[0].indicate_inset_zoom(axins0, edgecolor="black")
addon = "_zoomed"
else:
addon = ""
plt.xlim([pos[0], pos[-1]])
plt.grid()
plt.tight_layout(pad=0.5)
if path2save:
save_figure(plt, path2save, f"report_metric_{loss_name}_fold{idx:03d}" + addon)
if show_plot:
plt.show(block=True)
[docs]
def plot_statistic(
train_cl: np.ndarray,
valid_cl=None,
path2save: str = "",
cl_dict=None,
show_plot: bool = False,
) -> None:
"""Plotting the statistics of used dataset during training
:param train_cl: Numpy array of all classification labels from training dataset
:param valid_cl: Numpy array of all classification labels from validation dataset (optional)
:param path2save: Path to save the figure
:param cl_dict: Dictionary with keys for each label (otherwise number are used)
:param show_plot: If true, show plot
:return: None
"""
do_plots_avai = isinstance(valid_cl, np.ndarray | list)
dict_available = isinstance(cl_dict, np.ndarray | list | dict)
use_cl_dict = list()
if dict_available:
if isinstance(cl_dict, np.ndarray):
cl_dict0 = cl_dict.tolist()
else:
cl_dict0 = cl_dict
xtick_text = "vertical" if len(cl_dict0) > 3 else "horizontal"
else:
xtick_text = "horizontal"
plt.figure(figsize=(cm_to_inch(16), cm_to_inch(8)))
plt.rcParams.update({"font.size": 12})
plt.subplots_adjust(hspace=0, wspace=0.5)
axs = list()
for idx in range(0, 1 + do_plots_avai):
axs.append(plt.subplot(1, 1 + do_plots_avai, 1 + idx))
# Histogram of Training data
check = np.unique(train_cl, return_counts=True)
axs[0].bar(check[0], check[1], color="k", width=0.8)
if dict_available:
if not len(cl_dict) == 0:
if isinstance(cl_dict, dict):
for key in cl_dict.keys():
use_cl_dict.append(key)
else:
for idx in np.unique(train_cl):
use_cl_dict.append(cl_dict[int(idx)])
axs[0].set_xticks(
check[0],
(use_cl_dict if check[0].size != 1 else [use_cl_dict[0]]),
rotation=xtick_text,
)
else:
axs[0].set_xticks(check[0])
axs[0].set_ylabel("Bins")
axs[0].set_ylim([int(0.99 * check[1].min()), int(1.01 * check[1].max())])
axs[0].set_title("Training")
# Histogram of Validation data
if do_plots_avai:
check = np.unique(valid_cl, return_counts=True)
axs[1].bar(check[0], check[1], color="k", width=0.8)
if dict_available:
if not len(cl_dict) == 0:
axs[1].set_xticks(
check[0],
(use_cl_dict if check[0].size != 1 else [use_cl_dict[0]]),
rotation=xtick_text,
)
else:
axs[0].set_xticks(check[0])
axs[1].set_ylim([int(0.99 * check[1].min()), int(1.01 * check[1].max())])
axs[1].set_title("Validation")
for ax in axs:
ax.grid()
ax.set_xlabel("Cluster")
plt.tight_layout(pad=0.5)
# --- saving plots
if path2save:
save_figure(plt, path2save, "report_statistic_data")
if show_plot:
plt.show(block=True)