CoolFace
Apppublic

jordyvl/ece

sourceHugging Faceupdated 2y agoView on Hugging Face
4likes
local_app.py197 linesDownload Raw Back to root
1import evaluate2import json3import sys4from pathlib import Path5import gradio as gr6 7import numpy as np8import pandas as pd9import ast10 11# from ece import ECE  # loads local instead12 13 14import matplotlib.pyplot as plt15import matplotlib.patches as mpatches16 17"""18import seaborn as sns19sns.set_style('white')20sns.set_context("paper", font_scale=1)21"""22# plt.rcParams['figure.figsize'] = [10, 7]23plt.rcParams["figure.dpi"] = 30024plt.switch_backend(25    "agg"26)  # ; https://stackoverflow.com/questions/14694408/runtimeerror-main-thread-is-not-in-main-loop27 28sliders = [29    gr.Slider(0, 100, value=10, label="n_bins"),30    gr.Slider(31        0, 100, value=None, label="bin_range", visible=False32    ),  # DEV: need to have a double slider33    gr.Dropdown(choices=["equal-range", "equal-mass"], value="equal-range", label="scheme"),34    gr.Dropdown(choices=["upper-edge", "center"], value="upper-edge", label="proxy"),35    gr.Dropdown(choices=[1, 2, np.inf], value=1, label="p"),36]37 38slider_defaults = [slider.value for slider in sliders]39 40# example data41df = dict()42df["predictions"] = [[0.6, 0.2, 0.2], [0, 0.95, 0.05], [0.7, 0.1, 0.2]]43df["references"] = [0, 1, 2]44 45component = gr.Dataframe(46    headers=["predictions", "references"], col_count=2, datatype="number", type="pandas"47)48 49component.value = [50    [[0.6, 0.2, 0.2], 0],51    [[0.7, 0.1, 0.2], 2],52    [[0, 0.95, 0.05], 1],53]54sample_data = [[component] + slider_defaults]  ##json.dumps(df)55 56 57local_path = Path(sys.path[0])58metric = evaluate.load("jordyvl/ece")59# ECE()60# module = evaluate.load("jordyvl/ece")61# launch_gradio_widget(module)62 63"""l64Switch inputs and compute_fn65"""66 67 68def default_plot():69    fig = plt.figure()70    ax1 = plt.subplot2grid((3, 1), (0, 0), rowspan=2)71    ax2 = plt.subplot2grid((3, 1), (2, 0))72    ranged = np.linspace(0, 1, 10)73    ax1.plot(74        ranged,75        ranged,76        color="darkgreen",77        ls="dotted",78        label="Perfect",79    )80 81    # Bin differences82    ax1.set_ylabel("Conditional Expectation")83    ax1.set_ylim([0, 1.05])  # respective to bin range84    ax1.set_title("Reliability Diagram")85    ax1.set_xlim([-0.05, 1.05])  # respective to bin range86 87    # Bin frequencies88    ax2.set_xlabel("Confidence")89    ax2.set_ylabel("Count")90    ax2.legend(loc="upper left")  # , ncol=291    ax2.set_xlim([-0.05, 1.05])  # respective to bin range92 93    return fig, ax1, ax294 95 96def reliability_plot(results):97    # DEV: might still need to write tests in case of equal mass binning98    # DEV: nicer would be to plot like a polygon99    # see: https://github.com/markus93/fit-on-the-test/blob/main/Experiments_Synthetic/binnings.py100 101    def over_under_confidence(bins, patches):102        colors = []103        for j, bin in enumerate(bins):104            perfect = bin105            if j == len(patches):106              j = len(patches) -1107            empirical = patches[j].get_height()108 109            bin_color = (110                "limegreen"111                if np.allclose(perfect, empirical)112                else "dodgerblue"113                if empirical < perfect114                else "orangered"115            )116            colors.append(bin_color)117        return colors118 119    fig, ax1, ax2 = default_plot()120 121    # Bin differences122    bins_with_left_edge = np.insert(results["y_bar"], 0, 0, axis=0)123    B, bins, patches = ax1.hist(124        results["y_bar"],125        weights=np.nan_to_num(results["p_bar"][:-1], copy=True, nan=0),126        bins=bins_with_left_edge,127    )128    colors = over_under_confidence(bins, patches)129    for b in range(len(B)):130        patches[b].set_facecolor(colors[b])  # color based on over/underconfidence131    132    ax1handles = [133        mpatches.Patch(color="orangered", label="Overconfident"),134        mpatches.Patch(color="limegreen", label="Perfect", linestyle="dotted"),135        mpatches.Patch(color="dodgerblue", label="Underconfident"),136    ]137 138    # Bin frequencies139    anindices = np.where(~np.isnan(results["p_bar"][:-1]))[0]140    n_bins = len(results["y_bar"])141    bin_freqs = np.zeros(n_bins)142    bin_freqs[anindices] = results["bin_freq"]143    B, newbins, patches = ax2.hist(144        results["y_bar"], weights=bin_freqs, color="midnightblue", bins=bins_with_left_edge145    )146 147    acc_plt = ax2.axvline(x=results["accuracy"], ls="solid", lw=3, c="black", label="Accuracy")148    conf_plt = ax2.axvline(149        x=results["p_bar_cont"], ls="dotted", lw=3, c="#444", label="Avg. confidence"150    )151 152    ax1.legend(loc="lower right", handles=ax1handles)153    ax2.legend(handles=[acc_plt, conf_plt])154    ax1.set_xticks(bins_with_left_edge)155    ax2.set_xticks(bins_with_left_edge)156    plt.tight_layout()157    return fig158 159 160def compute_and_plot(data, n_bins, bin_range, scheme, proxy, p):161    # DEV: check on invalid datatypes with better warnings162 163    if isinstance(data, pd.DataFrame):164        data.dropna(inplace=True)165 166    predictions = [167        ast.literal_eval(prediction) if not isinstance(prediction, list) else prediction168        for prediction in data["predictions"]169    ]170    references = [reference for reference in data["references"]]171 172    results = metric._compute(173        predictions,174        references,175        n_bins=n_bins,176        scheme=scheme,177        proxy=proxy,178        p=p,179        detail=True,180    )181    print(results)182    plot = reliability_plot(results)183    return results["ECE"], plot184 185 186outputs = [gr.outputs.Textbox(label="ECE"), gr.Plot(label="Reliability diagram")]187# outputs[1].value = default_plot().__dict__ #Does not work; yet needs to be JSON encoded188 189iface = gr.Interface(190    fn=compute_and_plot,191    inputs=[component] + sliders,192    outputs=outputs,193    description=metric.info.description,194    article=evaluate.utils.parse_readme(local_path / "README.md"),195    title=f"Metric: {metric.name}",196    # examples=sample_data; # ValueError: Examples argument must either be a directory or a nested list, where each sublist represents a set of inputs.197).launch()