def create_axes(self): self.x_scale = bqplot.OrdinalScale() self.y_scale = bqplot.OrdinalScale(reverse=False) self.x_axis = bqplot.Axis(scale=self.x_scale) self.y_axis = bqplot.Axis(scale=self.y_scale, orientation='vertical') self.x_axis.color = blackish self.y_axis.color = blackish self.x_axis.label_color = blackish self.y_axis.label_color = blackish # self.y_axis.tick_style = {'fill': blackish, 'stroke':'none'} self.y_axis.grid_color = blackish self.x_axis.grid_color = blackish self.x_axis.label_offset = "2em" self.y_axis.label_offset = "3em" self.x_axis.grid_lines = 'none' self.y_axis.grid_lines = 'none' self.axes = [self.x_axis, self.y_axis]
def __init__(self, lineFig): """ """ self.lineFig = lineFig self.marks = self.lineFig.marks y_ord = bq.OrdinalScale() x_sc = bq.LinearScale() legendLabels = [] self.colours = [] for mark in self.marks: legendLabels += mark.labels self.colours += mark.colors[:len(mark.labels)] self.bars = bq.Bars( y=[1] * len(legendLabels), # all bars have a amplitude of 1 ## ? x=legendLabels, scales={ 'y': x_sc, 'x': y_ord }, colors=self.colours, padding=0.6, orientation='horizontal', stroke='white') ## remove the black border around the bar self.bars.opacities = [ScatLegend.OPAC_BRIGHT] * len(self.bars.x) ax_y = bq.Axis(scale=y_ord, orientation="vertical") ax_x = bq.Axis(scale=x_sc) ax_x.visible = False margin = dict(top=40, bottom=0, left=110, right=5) self.fig = bq.Figure(marks=[self.bars], axes=[ax_y, ax_x], fig_margin=margin) # Variable height depending on number of bars in legend self.fig.layout.height = str(45 + 20 * len(legendLabels)) + 'px' self.fig.layout.width = '170px' self.fig.min_aspect_ratio = 0.000000000001 # effectively remove aspect ratio constraint self.fig.max_aspect_ratio = 999999999999999 # effectively remove aspect ratio constraint self.fig.background_style = {'fill': 'White'} self.bars.on_element_click(self.changeOpacity)
def metrics(id, y_true, y_pred, protected, desc, x_ticks, pname, backend="bqplot"): """Plot a stack of figures for the three metrics.""" figure_name = f"Fairness_{id}_{desc}" dis = protected.astype(bool) tn_adv, fp_adv, fn_adv, tp_adv = confusion_matrix(y_true[~dis], y_pred[~dis]).ravel() tn_dis, fp_dis, fn_dis, tp_dis = confusion_matrix(y_true[dis], y_pred[dis]).ravel() # Also just count all positives and negatives pos_adv = tp_adv + fp_adv # all positives pos_dis = tp_dis + fp_dis neg_adv = tn_adv + fn_adv # all negatives neg_dis = tn_dis + fn_dis # Demographic Parity dem_par = (pos_dis / (pos_dis + neg_dis)) / (pos_adv / (pos_adv + neg_adv)) # Equal Opportunity eq_opp = (tp_dis / (tp_dis + fn_dis)) / (tp_adv / (tp_adv + fn_adv)) acc_adv = np.mean(y_true[~dis] == y_pred[~dis]) acc_dis = np.mean(y_true[dis] == y_pred[dis]) print("Acc adv: {}".format(acc_adv)) print("Acc dis: {}".format(acc_dis)) def normalise(nd): numer, denom = nd numer = np.asarray(numer, float) denom = np.asarray(denom, float) total = numer + denom total /= 100. # make percentage numer = numer / total denom = denom / total return [numer, denom] def describe(rate): rate = np.round(rate, 2) # make a percent if rate < 0.5: return f"{rate:.0%} as often" elif rate == 0.5: return "half as often" elif rate < 1.: return f"{1. - rate:.0%} less often" elif rate == 1.: return "equally often" elif rate < 2.: return f"{rate - 1.:.0%} more often" elif rate == 2.: return "twice as often" elif rate < 4: return f"{rate:.1f}x as often" elif rate < 10: return f"{rate:.0f}x as often" else: return "significantly more often" # if eo > 0.995: # stake = f"Suitable {groups[0].capitalize()} and {groups[1]} are selected at equal rates." def bqbars(values, colors, title, stake): fig = plt.figure() eo_bars = plt.bar(x_ticks, values, colors=colors) plt.ylabel("Fraction (%)") plt.xlabel(stake) fig.title = title return fig def matplotbars(ax, values, colors, title, stake): b0 = ax.bar(x_ticks, values[0], width=0.5, color=colors[0]) b1 = ax.bar(x_ticks, values[1], bottom=values[0], width=0.5, color=colors[1]) ax.set_ylabel("Fraction (%)") ax.set_xlabel(stake) ax.set_title(title) return b0, b1 eov = normalise([[tp_adv, tp_dis], [fn_adv, fn_dis]]) eov_title = "Opportunity{}".format(desc) eov_stake = f"Suitable {pname} are selected {describe(eq_opp)}." eov_colors = ["green", "lightgreen"] dpv = normalise([[pos_adv, pos_dis], [neg_adv, neg_dis]]) dpv_title = "Selection Rates{}".format(desc) dpv_stake = f"{pname} are selected {describe(dem_par)}." dpv_colors = ["black", "gray"] ppv = normalise([[tp_adv, tp_dis], [fp_adv, fp_dis]]) # error rates (false Discovery Rate parity) prec_par = (tp_dis / pos_dis) / (tp_adv / pos_adv) ppv_title = "Precision{}".format(desc) #ppv_stake = f"{pname.capitalize()} are selected {describe(prec_par)}.".replace("often", "precisely") ppv_stake = f"Selected {pname} are profitable {describe(prec_par)}." ppv_colors = ["green", "red"] print("Selection: {}".format(dpv)) print("Opportunity: {}".format(eov)) print("Precision: {}".format(ppv)) if backend == "bqplot": scales = { "x": bq.OrdinalScale(), "y": bq.LinearScale(), } eo_fig = bqbars(eov, eov_colors, eov_title, eov_stake) dp_fig = bqbars(dpv, dpv_colors, dpv_title, dpv_stake) pp_fig = bqbars(ppv, ppv_colors, ppv_title, ppv_stake) fairbox = widgets.HBox(( dp_fig, eo_fig, pp_fig, )) fairbox.layout.width = "99%" display(fairbox) eo_fig.axes[0].color = eo_fig.axes[1].color = "Black" dp_fig.axes[0].color = dp_fig.axes[1].color = "Black" pp_fig.axes[0].color = pp_fig.axes[1].color = "Black" else: fig, ax = mplt.subplots(1, 3, figsize=(9, 3), dpi=DPI) def clean(strv): # We have a bit more room for better sentences val = strv.replace("SE Asian", "SE Asians").replace("x ", " times ") # split the line s = len(val) // 2 a = val[s:].find(' ') b = val[:s][::-1].find(' ') split = s + a if (b >= 0 and b < a) or (a < 0): split = s - b - 1 val = val[:split] + "\n" + val[split + 1:] return val sa, na = matplotbars(ax[0], dpv, dpv_colors, dpv_title, clean(dpv_stake)) es, en = matplotbars(ax[1], eov, eov_colors, eov_title, clean(eov_stake)) _, ii = matplotbars(ax[2], ppv, ppv_colors, ppv_title, clean(ppv_stake)) mplt.legend( (es, en, sa, na, ii), ( "Profitable (Selected)", "Profitable (Rejected)", "Selected (All)", "Rejected (All)", "Not Profitable (Selected)", ), bbox_to_anchor=(1.25, 0.75), ) mplt.tight_layout() fig.savefig("images/" + figure_name + ".png", bbox_inches="tight")
def scale_ordinal(): return bqplot.OrdinalScale(allow_padding=False)
VBox(confidence_list_slider) ]) ]), header_rel_html ] #, VBox(list_relative_controls), VBox([floattext_confidence])] def updatecontrolinui(): UI_model.children[0].children = UI_viewcontrol updateviewcontrol() # END OF ************************************************************************************* GUI portion of the code that contains various labels,checkboxes etc. *********************** # START OF ************************************************************************************************************** Build bar charts (use of bqp) *********************** x_ord = bqp.OrdinalScale() y_sc = bqp.LinearScale() y_sc.max = 1 #Plot #1 i.e. Creation of the bar plot bar = bqp.Bars( x=[], y=[], scales={ 'x': x_ord, 'y': y_sc }, orientation="horizontal", display_legend=True, labels=[
def scale_ordinal(): return bqplot.OrdinalScale(min=0, max=1, allow_padding=False)