File size: 6,790 Bytes
2248c41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import os
import shutil
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

plt.style.use('seaborn-v0_8-whitegrid' if 'seaborn-v0_8-whitegrid' in plt.style.available else 'default')

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
RESULTS_DIR = os.environ.get("LITHO_RESULTS_DIR", os.path.join(BASE_DIR, "results"))

CSV_PATH = os.path.join(RESULTS_DIR, "MobileNetV5", "machine_1", "machine_1_scientific_analysis.csv")
if not os.path.exists(CSV_PATH):
    CSV_PATH = os.path.join(RESULTS_DIR, "consolidated", "csv", "lithotheque_scientific_analysis.csv")

if not os.path.exists(CSV_PATH):
    raise FileNotFoundError(f"Cannot find scientific analysis dataset: {CSV_PATH}")

df = pd.read_csv(CSV_PATH)
print(f"[INFO] Loaded dataset from: {CSV_PATH}")
print(df.groupby(["Format", "Backend"]).agg({"Latency_ms": ["count", "mean", "std", "min", "max"]}))

# ==============================================================================
# Graph 1: Comparative Latency Across Backends and Quantizations (Error Bar Chart)
# ==============================================================================
fig, ax = plt.subplots(figsize=(10, 6), dpi=300)

summary = df.groupby(["Format", "Backend"])["Latency_ms"].agg(["mean", "std"]).reset_index()
order = [
    ("INT8", "Tensor_Cores_INT8"),
    ("INT8", "CPU_x64"),
    ("W4A8", "Tensor_Cores_INT4"),
    ("W4A8", "CPU_x64")
]
summary["order"] = summary.apply(lambda r: order.index((r["Format"], r["Backend"])) if (r["Format"], r["Backend"]) in order else 99, axis=1)
summary = summary.sort_values("order")

labels = [
    "INT8\n(Machine 1 GPU Tensor Cores)",
    "INT8\n(Machine 1 CPU Intel Core i3)",
    "W4A8\n(Machine 1 GPU Tensor Cores)",
    "W4A8\n(Machine 1 CPU Intel Core i3)"
]
means = summary["mean"].values
stds = summary["std"].values
colors = ["#10b981", "#ef4444", "#3b82f6", "#f59e0b"]

bars = ax.bar(labels, means, yerr=stds, capsize=8, color=colors, edgecolor="black", alpha=0.88, width=0.55)

for bar, mean in zip(bars, means):
    yval = bar.get_height()
    ax.text(bar.get_x() + bar.get_width() / 2.0, yval + 80, f"{mean:.1f} ms", ha='center', va='bottom', fontsize=11, fontweight='bold')

ax.set_ylabel("Inference Latency (ms) - Lower is Better", fontsize=12, fontweight='bold')
ax.set_title("MobileNetV5 (512x512) - Inference Latency Across Backends\nMachine 1: Workstation RTX 5060 vs Intel Core i3-12100F", fontsize=13, fontweight='bold', pad=15)
ax.set_ylim(0, max(means) * 1.22)
ax.grid(axis='y', linestyle='--', alpha=0.6)

plt.tight_layout()
chart1_dir = os.path.join(RESULTS_DIR, "MobileNetV5", "machine_1")
os.makedirs(chart1_dir, exist_ok=True)
chart1_path = os.path.join(chart1_dir, "latency_comparison_machine_1.png")
fig.savefig(chart1_path)
plt.close(fig)
print(f"[OK] Generated Graph 1: {chart1_path}")

# ==============================================================================
# Graph 2: Empirical Latency Stability Across Iterations (Boxplot Distribution)
# ==============================================================================
fig, ax = plt.subplots(figsize=(10, 6), dpi=300)

data_groups = []
labels_box = []
for fmt, bk, lbl in [
    ("INT8", "Tensor_Cores_INT8", "INT8 Tensor Cores\n(Machine 1 GPU)"),
    ("W4A8", "Tensor_Cores_INT4", "W4A8 Tensor Cores\n(Machine 1 GPU)"),
    ("INT8", "CPU_x64", "INT8 CPU\n(Machine 1 CPU)"),
    ("W4A8", "CPU_x64", "W4A8 CPU\n(Machine 1 CPU)")
]:
    sub = df[(df["Format"] == fmt) & (df["Backend"] == bk)]["Latency_ms"].values
    data_groups.append(sub)
    labels_box.append(lbl)

try:
    bplot = ax.boxplot(data_groups, patch_artist=True, tick_labels=labels_box, medianprops=dict(color='black', linewidth=2))
except TypeError:
    bplot = ax.boxplot(data_groups, patch_artist=True, labels=labels_box, medianprops=dict(color='black', linewidth=2))
for patch, color in zip(bplot['boxes'], colors):
    patch.set_facecolor(color)
    patch.set_alpha(0.8)

ax.set_ylabel("Inference Latency (ms)", fontsize=12, fontweight='bold')
ax.set_title("Empirical Latency Stability Across Iterations (Variance & Outliers)\nMobileNetV5 Rock Classification Pipeline", fontsize=13, fontweight='bold', pad=15)
ax.grid(axis='y', linestyle='--', alpha=0.6)

plt.tight_layout()
chart2_dir = os.path.join(RESULTS_DIR, "consolidated", "images")
os.makedirs(chart2_dir, exist_ok=True)
chart2_path = os.path.join(chart2_dir, "latency_stability_distribution.png")
fig.savefig(chart2_path)
plt.close(fig)
print(f"[OK] Generated Graph 2: {chart2_path}")

# ==============================================================================
# Graph 3: Pareto Frontier (Inference Latency vs Top-1 Accuracy)
# ==============================================================================
fig, ax = plt.subplots(figsize=(9, 6), dpi=300)

pts = [
    {"label": "INT8 (Machine 1 GPU)", "lat": df[(df["Format"] == "INT8") & (df["Backend"] == "Tensor_Cores_INT8")]["Latency_ms"].mean(), "acc": 83.33, "color": "#10b981", "size": 180},
    {"label": "W4A8 (Machine 1 GPU)", "lat": df[(df["Format"] == "W4A8") & (df["Backend"] == "Tensor_Cores_INT4")]["Latency_ms"].mean(), "acc": 80.33, "color": "#3b82f6", "size": 180},
    {"label": "INT8 (Machine 1 CPU)", "lat": df[(df["Format"] == "INT8") & (df["Backend"] == "CPU_x64")]["Latency_ms"].mean(), "acc": 83.33, "color": "#ef4444", "size": 140},
    {"label": "W4A8 (Machine 1 CPU)", "lat": df[(df["Format"] == "W4A8") & (df["Backend"] == "CPU_x64")]["Latency_ms"].mean(), "acc": 80.33, "color": "#f59e0b", "size": 140},
    {"label": "Machine 2 CPU INT8 (Oryon ARM64)", "lat": 5695.84, "acc": 83.33, "color": "#8b5cf6", "size": 140},
    {"label": "Machine 2 CPU W4A8 (Oryon ARM64)", "lat": 7119.80, "acc": 80.33, "color": "#ec4899", "size": 140}
]

for p in pts:
    ax.scatter(p["lat"], p["acc"], color=p["color"], s=p["size"], edgecolors="black", zorder=4)
    ax.annotate(p["label"], (p["lat"], p["acc"]), textcoords="offset points", xytext=(10, 8 if "INT8" in p["label"] else -16),
                fontsize=9.5, fontweight='bold', bbox=dict(boxstyle="round,pad=0.3", fc="white", ec=p["color"], alpha=0.9))

ax.set_xlabel("Inference Latency (ms) - Log/Linear Scale", fontsize=12, fontweight='bold')
ax.set_ylabel("Top-1 Accuracy (%)", fontsize=12, fontweight='bold')
ax.set_title("Pareto Efficiency: Geological Accuracy vs Inference Latency\nComparison Across Machine 1 & Machine 2 Environments", fontsize=13, fontweight='bold', pad=15)
ax.set_ylim(78.5, 85.5)
ax.set_xlim(-200, 7800)
ax.grid(True, linestyle='--', alpha=0.5)

plt.tight_layout()
chart3_path = os.path.join(chart2_dir, "accuracy_vs_latency_pareto.png")
fig.savefig(chart3_path)
plt.close(fig)
print(f"[OK] Generated Graph 3: {chart3_path}")
print("[SUCCESS] All scientific figures successfully generated in English.")