File size: 5,101 Bytes
0d67035
 
 
 
 
535a496
 
 
6ee7257
 
535a496
0d67035
535a496
0d67035
6ee7257
 
0d67035
6ee7257
0d67035
535a496
6ee7257
0d67035
535a496
6ee7257
0d67035
6ee7257
535a496
 
6ee7257
 
535a496
 
 
 
 
 
 
 
 
6ee7257
 
535a496
 
 
6ee7257
 
535a496
 
 
 
 
 
 
 
 
6ee7257
 
535a496
6ee7257
535a496
6ee7257
 
 
535a496
 
 
 
 
 
 
 
 
6ee7257
535a496
6ee7257
 
535a496
 
6ee7257
535a496
6ee7257
 
535a496
0d67035
6ee7257
0d67035
535a496
6ee7257
0d67035
535a496
6ee7257
0d67035
6ee7257
535a496
6ee7257
 
535a496
0d67035
6ee7257
535a496
0d67035
 
6ee7257
 
535a496
6ee7257
 
 
535a496
6ee7257
 
 
 
535a496
6ee7257
 
 
 
 
 
 
 
535a496
6ee7257
 
 
535a496
6ee7257
 
0d67035
6ee7257
535a496
6ee7257
 
 
 
535a496
6ee7257
535a496
 
 
 
 
 
 
 
 
0d67035
6ee7257
535a496
 
 
0d67035
6ee7257
535a496
6ee7257
 
 
535a496
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
"""
Visualization functions for DeathMath Leaderboard analytics.
Provides bar charts and radar plots for model comparison.
"""

import itertools as it
import random

import matplotlib.pyplot as plt
import numpy as np
import plotly.graph_objects as go
from matplotlib.figure import Figure

from src.leaderboard import build_leaderboard_df


def create_plot(selected_models: list[str]) -> Figure:
    """
    Create bar chart visualization comparing selected models.

    Args:
        selected_models: List of model names to display

    Returns:
        Matplotlib figure with bar chart comparing metrics across models
    """
    models_df = build_leaderboard_df()

    if not selected_models or models_df.empty:
        fig, ax = plt.subplots(figsize=(10, 6))
        ax.text(
            0.5,
            0.5,
            "Нет данных для отображения",
            horizontalalignment="center",
            verticalalignment="center",
            transform=ax.transAxes,
            fontsize=14,
        )
        ax.set_axis_off()
        return fig

    models_to_show = models_df[models_df["model"].isin(selected_models)]

    if models_to_show.empty:
        fig, ax = plt.subplots(figsize=(10, 6))
        ax.text(
            0.5,
            0.5,
            "Выбранные модели не найдены в данных",
            horizontalalignment="center",
            verticalalignment="center",
            transform=ax.transAxes,
            fontsize=14,
        )
        ax.set_axis_off()
        return fig

    fig, ax = plt.subplots(figsize=(12, 8))

    bar_width = 0.25
    models_count = len(models_to_show)
    indices = np.arange(models_count)
    colors = ["#1f77b4", "#ff7f0e", "#2ca02c"]

    ax.bar(indices - bar_width, models_to_show["math_score"], bar_width, label="RussianMath Score", color=colors[0])
    ax.bar(indices, models_to_show["physics_score"], bar_width, label="RussianPhysics Score", color=colors[1])
    ax.bar(indices + bar_width, models_to_show["score"], bar_width, label="Combined Score", color=colors[2])

    ax.set_xlabel("Модели")
    ax.set_ylabel("Баллы")
    ax.set_title("Сравнение производительности моделей на DeathMath benchmark")
    ax.set_xticks(indices)
    ax.set_xticklabels(models_to_show["model"], rotation=45, ha="right")
    ax.legend()
    ax.set_ylim(0, 1.0)
    ax.grid(axis="y", linestyle="--", alpha=0.7)

    plt.tight_layout()

    return fig


def create_radar_plot(selected_models: list[str]) -> go.Figure:
    """
    Create radar chart visualization comparing selected models.

    Args:
        selected_models: List of model names to display

    Returns:
        Plotly figure with interactive radar chart
    """
    models = build_leaderboard_df()
    metrics = ["math_score", "physics_score", "score"]
    metric_labels = ["RussianMath", "RussianPhysics", "Combined"]

    min_colour_distance_between_models = 100
    seed = 42

    def generate_colours(min_distance: int, seed: int) -> dict[str, tuple[int, int, int]]:
        """Generate distinct colors for each model."""
        colour_mapping = {}
        all_models = selected_models

        for i in it.count():
            min_colour_distance = min_distance - i
            retries_left = 10 * len(all_models)

            for model_id in all_models:
                random.seed(hash(model_id) + i + seed)
                r, g, b = 0, 0, 0
                too_bright, similar_to_other_model = True, True

                while (too_bright or similar_to_other_model) and retries_left > 0:
                    r, g, b = tuple(random.randint(0, 255) for _ in range(3))
                    too_bright = np.min([r, g, b]) > 200
                    similar_to_other_model = any(
                        np.abs(np.array(colour) - np.array([r, g, b])).sum() < min_colour_distance
                        for colour in colour_mapping.values()
                    )
                    retries_left -= 1

                colour_mapping[model_id] = (r, g, b)
            if len(colour_mapping) == len(all_models):
                break

        return colour_mapping

    colour_mapping = generate_colours(min_colour_distance_between_models, seed)
    fig = go.Figure()

    for _, model_data in models.iterrows():
        model_name = model_data["model"]
        if model_name not in selected_models:
            continue

        values = [model_data[metric] for metric in metrics]
        color = f"rgb{colour_mapping[model_name]}"

        fig.add_trace(
            go.Scatterpolar(
                r=values,
                theta=metric_labels,
                name=model_name,
                fill="toself",
                fillcolor=f"rgba{colour_mapping[model_name] + (0.6,)}",
                line={"color": color},
            )
        )

    fig.update_layout(
        polar={"radialaxis": {"visible": True, "range": [0, 1]}},
        showlegend=True,
        title="Сравнение моделей на DeathMath",
        template="plotly_dark",
    )

    return fig