314 lines
13 KiB
Python
314 lines
13 KiB
Python
"""
|
||
Co-MADDPG Visualization Module | Co-MADDPG 可视化模块
|
||
|
||
This module handles the generation of IEEE-standard figures for the resource
|
||
allocation performance evaluation. It maps specifically to Section VII (Experimental
|
||
Results) of the associated research paper.
|
||
|
||
本模块负责生成符合 IEEE 标准的资源分配性能评估图表。它专门对应于相关研究论文的
|
||
第七节(实验结果)。
|
||
|
||
Reference Figures (from Section VII):
|
||
- Fig 2: Training convergence curves | 训练收敛曲线
|
||
- Fig 3: System QoE vs. SNR | 系统 QoE 随 SNR 的变化
|
||
- Fig 4: Jain's Fairness Index vs. SNR | Jain 公平性指数随 SNR 的变化
|
||
- Fig 5: System QoE vs. Total Users (K) | 系统 QoE 随总用户数 (K) 的变化
|
||
- Fig 6: Rate Satisfaction Ratio vs. Total Users (K) | 速率满足率随总用户数 (K) 的变化
|
||
- Fig 7: Trajectory of λ(t) over time | λ(t) 随时间的变化轨迹
|
||
- Fig 8: Correlation scatter of λ and System QoE | λ 与系统 QoE 的相关性散点图
|
||
- Fig 9: System QoE vs. Semantic User Ratio | 系统 QoE 随语义用户比例的变化
|
||
- Fig 10: Ablation study results | 消融实验结果
|
||
- Fig 11: Sensitivity analysis of β | β 参数的敏感性分析
|
||
- Fig 12: Sensitivity analysis of Q_th | Q_th 阈值的敏感性分析
|
||
"""
|
||
|
||
import os
|
||
import numpy as np
|
||
import matplotlib
|
||
# Use non-interactive backend to avoid requiring an X server or display
|
||
# 使用非交互式后端以避免需要 X 服务器或显示器
|
||
matplotlib.use('Agg')
|
||
import matplotlib.pyplot as plt
|
||
|
||
from utils.metrics import moving_average
|
||
|
||
# IEEE-quality plotting defaults | IEEE 质量绘图默认设置
|
||
plt.rcParams.update({
|
||
'font.family': 'serif',
|
||
'font.serif': ['Times New Roman', 'DejaVu Serif'],
|
||
'font.size': 12,
|
||
'axes.grid': True,
|
||
'figure.figsize': (8, 6),
|
||
'figure.autolayout': True, # Equivalent to tight_layout | 等同于 tight_layout
|
||
'savefig.dpi': 300,
|
||
'savefig.bbox': 'tight'
|
||
})
|
||
|
||
# Consistent algorithm styles | 一致的算法绘图风格
|
||
# Color and marker choices distinguish between proposed, baselines, and ablation variants
|
||
# 颜色和标记的选择用于区分建议算法、基准算法和消融变体
|
||
ALGO_STYLES = {
|
||
'Co-MADDPG': {'color': '#E24A33', 'marker': 'o', 'linestyle': '-'}, # Proposed (Red) | 建议算法(红色)
|
||
'Pure Cooperative': {'color': '#348ABD', 'marker': 's', 'linestyle': '--'}, # Baseline (Blue) | 基准(蓝色)
|
||
'Pure Competitive': {'color': '#988ED5', 'marker': '^', 'linestyle': '--'}, # Baseline (Purple) | 基准(紫色)
|
||
'Single-Agent DQN': {'color': '#777777', 'marker': 'D', 'linestyle': '-.'}, # Baseline (Gray) | 基准(灰色)
|
||
'IDDPG': {'color': '#FBC15E', 'marker': 'v', 'linestyle': '-.'}, # Baseline (Yellow) | 基准(黄色)
|
||
'Fixed λ=0.5': {'color': '#8EBA42', 'marker': 'p', 'linestyle': ':'}, # Ablation (Green) | 消融(绿色)
|
||
'Equal Allocation': {'color': '#FFB5B8', 'marker': '*', 'linestyle': ':'}, # Baseline (Pink) | 基准(粉色)
|
||
'Semantic-Only': {'color': '#6d904f', 'marker': 'h', 'linestyle': ':'}, # Baseline (Olive) | 基准(橄榄色)
|
||
}
|
||
|
||
|
||
class Plotter:
|
||
"""
|
||
IEEE-quality plotting module for all paper figures. | 用于所有论文图表的 IEEE 质量绘图模块。
|
||
"""
|
||
def __init__(self):
|
||
pass
|
||
|
||
def _get_style(self, algo_name):
|
||
"""
|
||
Helper to get plotting style for an algorithm or a sensible default.
|
||
获取算法的绘图风格或合理的默认值。
|
||
"""
|
||
return ALGO_STYLES.get(algo_name, {'color': 'k', 'marker': '', 'linestyle': '-'})
|
||
|
||
def _save_plot(self, save_path):
|
||
"""
|
||
Helper to save plot in both PDF and PNG formats at 300 DPI.
|
||
以 300 DPI 的分辨率将图表保存为 PDF 和 PNG 格式。
|
||
"""
|
||
os.makedirs(os.path.dirname(os.path.abspath(save_path)), exist_ok=True)
|
||
# Strip extension if the user provided one, to consistently save both .pdf and .png
|
||
# 如果用户提供了扩展名,则将其去除,以便一致地保存 .pdf 和 .png
|
||
base_path = os.path.splitext(save_path)[0]
|
||
|
||
plt.savefig(f"{base_path}.pdf", format='pdf')
|
||
plt.savefig(f"{base_path}.png", format='png', dpi=300)
|
||
plt.close()
|
||
|
||
def plot_convergence(self, data_dict, save_path):
|
||
"""
|
||
Fig 2: Episode QoE_sys curves. | 图 2:每回合系统 QoE 曲线。
|
||
Shows how the algorithm improves over training episodes.
|
||
展示算法在训练回合中如何改进。
|
||
|
||
data_dict: {algo_name: [episode_qoe_values]}
|
||
"""
|
||
plt.figure()
|
||
for algo, qoe_vals in data_dict.items():
|
||
style = self._get_style(algo)
|
||
# Remove markers for dense convergence plots to maintain clean look
|
||
# 为密集的收敛图移除标记以保持画面整洁
|
||
plot_style = style.copy()
|
||
if 'marker' in plot_style:
|
||
plot_style.pop('marker')
|
||
|
||
smoothed_qoe = moving_average(qoe_vals, window=50)
|
||
x_vals = np.arange(len(smoothed_qoe))
|
||
plt.plot(x_vals, smoothed_qoe, label=algo, **plot_style)
|
||
|
||
plt.xlabel('Episode')
|
||
plt.ylabel('System QoE')
|
||
plt.title('Training Convergence')
|
||
plt.legend()
|
||
self._save_plot(save_path)
|
||
|
||
def plot_qoe_vs_snr(self, data_dict, save_path):
|
||
"""
|
||
Fig 3: QoE vs SNR. | 图 3:QoE 随 SNR 的变化。
|
||
Evaluates system robustness under different noise levels.
|
||
评估不同噪声水平下的系统鲁棒性。
|
||
|
||
data_dict: {algo_name: [qoe_per_snr_point]}
|
||
"""
|
||
plt.figure()
|
||
snr_vals = [0, 5, 10, 15, 20, 25, 30]
|
||
for algo, qoe_vals in data_dict.items():
|
||
style = self._get_style(algo)
|
||
plt.plot(snr_vals, qoe_vals, label=algo, **style)
|
||
|
||
plt.xlabel('SNR (dB)')
|
||
plt.ylabel('System QoE')
|
||
plt.title('System QoE vs. SNR')
|
||
plt.legend()
|
||
self._save_plot(save_path)
|
||
|
||
def plot_fairness_vs_snr(self, data_dict, save_path):
|
||
"""
|
||
Fig 4: Jain Fairness Index vs SNR. | 图 4:Jain 公平性指数随 SNR 的变化。
|
||
Measures the balance of resource allocation across users.
|
||
衡量不同用户之间资源分配的平衡性。
|
||
|
||
data_dict: {algo_name: [fairness_per_snr_point]}
|
||
"""
|
||
plt.figure()
|
||
snr_vals = [0, 5, 10, 15, 20, 25, 30]
|
||
for algo, fairness_vals in data_dict.items():
|
||
style = self._get_style(algo)
|
||
plt.plot(snr_vals, fairness_vals, label=algo, **style)
|
||
|
||
plt.xlabel('SNR (dB)')
|
||
plt.ylabel('Jain Fairness Index')
|
||
plt.title('Fairness vs. SNR')
|
||
plt.legend()
|
||
self._save_plot(save_path)
|
||
|
||
def plot_qoe_vs_users(self, data_dict, save_path):
|
||
"""
|
||
Fig 5: QoE vs Total Users K. | 图 5:QoE 随总用户数 K 的变化。
|
||
Tests system scalability as user density increases.
|
||
测试随着用户密度增加系统的可扩展性。
|
||
|
||
data_dict: {algo_name: [qoe_per_k_point]}
|
||
"""
|
||
plt.figure()
|
||
users_vals = [4, 6, 8, 10, 12]
|
||
for algo, qoe_vals in data_dict.items():
|
||
style = self._get_style(algo)
|
||
plt.plot(users_vals, qoe_vals, label=algo, **style)
|
||
|
||
plt.xlabel('Total Users (K)')
|
||
plt.ylabel('System QoE')
|
||
plt.title('System QoE vs. Total Users')
|
||
plt.legend()
|
||
self._save_plot(save_path)
|
||
|
||
def plot_rate_satisfaction_vs_users(self, data_dict, save_path):
|
||
"""
|
||
Fig 6: Rate Satisfaction Ratio vs Total Users K. | 图 6:速率满足率随总用户数 K 的变化。
|
||
Evaluates the ability to meet minimum QoS requirements.
|
||
评估满足最小 QoS 要求的能力。
|
||
|
||
data_dict: {algo_name: [rate_satisfaction_per_k_point]}
|
||
"""
|
||
plt.figure()
|
||
users_vals = [4, 6, 8, 10, 12]
|
||
for algo, sat_vals in data_dict.items():
|
||
style = self._get_style(algo)
|
||
plt.plot(users_vals, sat_vals, label=algo, **style)
|
||
|
||
plt.xlabel('Total Users (K)')
|
||
plt.ylabel('Rate Satisfaction Ratio')
|
||
plt.title('Rate Satisfaction vs. Total Users')
|
||
plt.legend()
|
||
self._save_plot(save_path)
|
||
|
||
def plot_lambda_trajectory(self, lambda_values, save_path):
|
||
"""
|
||
Fig 7: Lambda Trajectory. | 图 7:Lambda 轨迹。
|
||
Visualizes the dynamic switching between cooperation and competition.
|
||
可视化协作与竞争之间的动态切换。
|
||
|
||
lambda_values: list of lambda(t) values.
|
||
"""
|
||
plt.figure()
|
||
time_steps = np.arange(len(lambda_values))
|
||
plt.plot(time_steps, lambda_values, label=r'$\lambda(t)$', color='#348ABD', linestyle='-')
|
||
# Reference line for fixed weighting | 固定权重的参考线
|
||
plt.axhline(y=0.5, color='#E24A33', linestyle='--', label=r'Reference ($\lambda=0.5$)')
|
||
|
||
plt.xlabel('Time Step')
|
||
plt.ylabel(r'$\lambda(t)$')
|
||
plt.title(r'Trajectory of Allocation Parameter $\lambda$')
|
||
plt.legend()
|
||
self._save_plot(save_path)
|
||
|
||
def plot_lambda_qoe_scatter(self, lambdas, qoes, save_path):
|
||
"""
|
||
Fig 8: Scatter of (lambda, QoE_sys). | 图 8:(lambda, QoE_sys) 散点图。
|
||
Shows the correlation between the dynamic parameter and system performance.
|
||
展示动态参数与系统性能之间的相关性。
|
||
"""
|
||
plt.figure()
|
||
time_steps = np.arange(len(lambdas))
|
||
# Color points by time to show evolution | 按时间为点着色以显示演化过程
|
||
sc = plt.scatter(lambdas, qoes, c=time_steps, cmap='viridis', alpha=0.7)
|
||
cbar = plt.colorbar(sc)
|
||
cbar.set_label('Time Step')
|
||
|
||
plt.xlabel(r'$\lambda$')
|
||
plt.ylabel('System QoE')
|
||
plt.title(r'Correlation between $\lambda$ and System QoE')
|
||
self._save_plot(save_path)
|
||
|
||
def plot_qoe_vs_ratio(self, data_dict, ratios, save_path):
|
||
"""
|
||
Fig 9: QoE vs Semantic User Ratio. | 图 9:QoE 随语义用户比例的变化。
|
||
Studies the impact of increasing semantic communication prevalence.
|
||
研究语义通信普及率增加的影响。
|
||
|
||
data_dict: {algo_name: [qoe_values]}
|
||
"""
|
||
plt.figure()
|
||
for algo, qoe_vals in data_dict.items():
|
||
style = self._get_style(algo)
|
||
plt.plot(ratios, qoe_vals, label=algo, **style)
|
||
|
||
plt.xlabel('Semantic User Ratio')
|
||
plt.ylabel('System QoE')
|
||
plt.title('System QoE vs. Semantic User Ratio')
|
||
plt.legend()
|
||
self._save_plot(save_path)
|
||
|
||
def plot_ablation(self, data, save_path):
|
||
"""
|
||
Fig 10: Horizontal bar chart for ablation study. | 图 10:消融研究的水平条形图。
|
||
Compares the full Co-MADDPG against its stripped-down variants.
|
||
将完整的 Co-MADDPG 与其简化变体进行比较。
|
||
|
||
data: {variant_label: qoe_value}
|
||
"""
|
||
plt.figure()
|
||
labels = list(data.keys())
|
||
values = list(data.values())
|
||
|
||
y_pos = np.arange(len(labels))
|
||
# Highlight Co-MADDPG (Full) in red if present | 如果存在,用红色高亮 Co-MADDPG (Full)
|
||
colors = ['#E24A33' if 'Co-MADDPG' in label and 'Full' in label else '#348ABD' for label in labels]
|
||
|
||
plt.barh(y_pos, values, align='center', color=colors)
|
||
plt.yticks(y_pos, labels)
|
||
plt.xlabel('System QoE')
|
||
plt.title('Ablation Study')
|
||
|
||
self._save_plot(save_path)
|
||
|
||
def plot_beta_sensitivity(self, data_dict, betas, save_path):
|
||
"""
|
||
Fig 11: QoE vs Beta values. | 图 11:QoE 随 Beta 值的变化。
|
||
Analyzes sensitivity to the sigmoid steepness parameter.
|
||
分析对 Sigmoid 陡峭度参数的敏感性。
|
||
|
||
data_dict: {label: qoe_value_list}
|
||
"""
|
||
plt.figure()
|
||
for algo, qoe_vals in data_dict.items():
|
||
style = self._get_style(algo)
|
||
plt.plot(betas, qoe_vals, label=algo, **style)
|
||
|
||
plt.xlabel(r'$\beta$ Parameter')
|
||
plt.ylabel('System QoE')
|
||
plt.title(r'Sensitivity Analysis of $\beta$')
|
||
plt.legend()
|
||
self._save_plot(save_path)
|
||
|
||
def plot_qth_sensitivity(self, data_dict, qths, save_path):
|
||
"""
|
||
Fig 12: QoE vs Q_th values. | 图 12:QoE 随 Q_th 值的变化。
|
||
Analyzes sensitivity to the cooperation threshold.
|
||
分析对协作阈值的敏感性。
|
||
|
||
data_dict: {label: qoe_value_list}
|
||
"""
|
||
plt.figure()
|
||
for algo, qoe_vals in data_dict.items():
|
||
style = self._get_style(algo)
|
||
plt.plot(qths, qoe_vals, label=algo, **style)
|
||
|
||
plt.xlabel(r'$Q_{th}$ Threshold')
|
||
plt.ylabel('System QoE')
|
||
plt.title(r'Sensitivity Analysis of $Q_{th}$')
|
||
plt.legend()
|
||
self._save_plot(save_path)
|