{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":126777,"databundleVersionId":15314950,"sourceType":"competition"},{"sourceId":14834180,"sourceType":"datasetVersion","datasetId":9487309}],"dockerImageVersionId":31259,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"### [Jaguar Re-Identification Challenge](https://www.kaggle.com/competitions/jaguar-re-id/code?competitionId=126777&sortBy=scoreDescending&excludeNonAccessedDatasources=true)\n\nHelp identify the jaguars in Brazil's Pantanal Park.\n\n| | | &nbsp; | | &nbsp; | &nbsp; | &nbsp; | &nbsp; |\n|:-|:-| :-: | :-: | :-: | :-: | :-: | :-: |\n| 1. | [0.930](https://www.kaggle.com/code/awallay/jaguar-re-identification-0-93-score/notebook?scriptVersionId=295739017) |&nbsp;v.2&nbsp;| [Jaguar Re-Identification 0.93 Score](https://www.kaggle.com/code/awallay/jaguar-re-identification-0-93-score/notebook) | contributor | [Austin Wallace](https://www.kaggle.com/awallay) | World | \n| 2. | [0.937](https://www.kaggle.com/code/lakhindarpal/jaguar-re-identification-challenge?scriptVersionId=293816898) |&nbsp;v.4&nbsp;| [Jaguar Re-Identification Challenge](https://www.kaggle.com/code/lakhindarpal/jaguar-re-identification-challenge) | expert | [Lakhindar Pal](https://www.kaggle.com/lakhindarpal) | India | \n| 3. | [0.938](https://www.kaggle.com/code/sanidhyavijay24/jaguar-re-id-0-938-eva-02-optimal-blending?scriptVersionId=296593856) |&nbsp;v.3&nbsp;| [🐆 Jaguar Re-ID: . EVA-02 + Optimal Blending](https://www.kaggle.com/code/sanidhyavijay24/jaguar-re-id-0-938-eva-02-optimal-blending) | contributor | [Sanidhya Vijay24](https://www.kaggle.com/sanidhyavijay24) | World | \n| 4. | [0.944](https://www.kaggle.com/code/kawaharataishi/pseudo-labeling?scriptVersionId=295771630) |&nbsp;v.1&nbsp;| [Pseudo-Labeling](https://www.kaggle.com/code/kawaharataishi/pseudo-labeling) | contributor | [T.Kawahara](https://www.kaggle.com/kawaharataishi) | Japan | \n||||||||\n||||**main weight** %|**asc/desc** %|**correct weight** %|\n|  | [0.944](https://www.kaggle.com/code/nina2025/jaguar-re-identification-h-blend?scriptVersionId=297605985) | [v.1](#h-blend) | [ 1.,2.,3.,4. ] . [[ +0.05 +0.10 +0.11 +0.74 ](#h-blend)] | 30 x 70 | [[ +5, -5,-5, +5 ](#h-blend)] / 100 |\n|  | [0.944](https://www.kaggle.com/code/nina2025/jaguar-re-identification-h-blend?scriptVersionId=297606557) | [v.2](#h-blend) | [ 1.,2.,3.,4. ] . [[ +0.04 +0.08 +0.09 +0.79 ](#h-blend)] | 30 x 70 | [[ +5, -5,-5, +5 ](#h-blend)] / 100 |\n|  | [?](https://) | [v.3](#h-blend) | [ 1.,2.,3.,4. ] . [[ +0.01 +0.02 +0.02 +0.95 ](#h-blend)] | 30 x 70 | [[ +1, -1,-1, +1 ](#h-blend)] / 100 |","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\nimport os,ast,shutil,copy\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport warnings; warnings.filterwarnings('ignore')\n\nfrom bokeh.plotting import figure, gridplot \nfrom bokeh.io import output_file, show, output_notebook\noutput_notebook()\n\n\ndef bokeh_show(\n        params,\n        df_cross,\n        show_figures1, \n        show_figures2, wps_fig2,\n        color_cross):\n\n    colors = [subm['color'] for subm in params['subm']]\n    \n    def dossier(js,subms,cols):\n        def quant(i,js,subms,cols):\n            return {\"c\" : i, \"q\" : sum([1 for subm in cols[i] if subm == subms[js]])}\n        return {\n            'name' : subms[js],\n            'q_in' : [quant(i,js,subms,cols) for i in range(len(subms))]\n        }\n    alls = pd.read_csv(f'tida_desc.csv')\n    matrix = [ast.literal_eval(str(row.alls)) for row in alls.itertuples()]\n    subms = sorted(matrix[0])\n    cols = [[data[i] for data in matrix] for i in range(len(subms))]\n    df_subms = pd.DataFrame({f'col_{i}': [x[i] for x in matrix] for i in range(len(subms))})\n    dossiers = [dossier(js,subms,cols) for js in range(len(subms))]\n    subm_names = [one_dossier['name'] for one_dossier in dossiers]\n    figures1,qss,i = [],[],0\n    height = 100 if len(colors)==2\\\n        else 134 if len(colors)==3 else (154 if len(colors)==4 else 174)\n    for one_dossier in dossiers: \n        i_col = 'alls. ' + str(one_dossier['q_in'][i]['c'])\n        qs = [one['q'] for one in one_dossier['q_in']]\n        x_names = [name.replace(\"Group\",\"\").replace(\"subm_\",\"\") for name in subm_names]\n        width = 140\n        f = figure(x_range=x_names,width=width, height=height, title=i_col)\n        f.vbar(x=x_names, width=0.585, top=qs, color=colors)\n        figures1.append(f)\n        qss.append(qs)\n        i+=1\n    grid = gridplot([figures1])\n    output_file('tida_alls.html')\n    if show_figures1 == True: show(grid)\n    sub_wts = params['subwts']\n    main_wts = [subm['weight'] for subm in params['subm']]\n    mms,acc_mass = [],[]\n    for j in range(len(dossiers)):\n        one_dossier = dossiers[j]\n        qs = [one['q'] for one in one_dossier['q_in']]\n        mm = [qs[h] * (main_wts[j] + sub_wts[h]) for h in range(len(sub_wts))]\n        mass = sum(mm)\n        mms.append(mm)\n        acc_mass.append(round(mass))                        #subm_names[::-1]\n    y_names = [name + \" - \" + str(mass) for name,mass in zip(subm_names,acc_mass)]\n    f1 = figure(y_range=y_names, width=270, height=height, title='relations of general masses')\n    f1.hbar(y=y_names, height=0.555, right=acc_mass, left=0, color=colors)\n    output_file('tida_alls2.html')\n    alls = [f'alls.{i}' for i in range(len(dossiers))]\n    subm = [f'sub{i}'   for i in range(len(dossiers))] \n    mmsT  = np.asarray(mms).T\n    data = {'cols' : alls}\n    for i in range(len(dossiers)): data[f'sub{i}'] = mmsT[i,:]\n    f2 = figure(y_range=alls, height=height, width=270, title=\"relations of columns masses\")\n    f2.hbar_stack(subm, y='cols', height=0.555, color=colors, source=data)\n    qssT  = np.asarray(qss).T\n    data = {'cols' : alls}\n    for i in range(len(dossiers)): data[f'sub{i}'] = qssT[i,:]\n    f3 = figure(y_range=alls, height=height, width=245, title=\"ratios in columns\")\n    f3.hbar_stack(subm, y='cols', height=0.555, color=colors, source=data)\n    grid = gridplot([[f3,f2,f1]])\n    show(grid)\n    if show_figures2 == True:\n        def read(params,i):\n            FiN = params[\"path\"] + params[\"subm\"][i][\"name\"] + \".csv\"\n            target_name_back = {'target':params[\"target\"],'pred':params[\"target\"]}\n            return pd.read_csv(FiN).rename(columns=target_name_back)\n        dfs = [read(params,i) for i in range(len(params[\"subm\"]))] + [df_cross]\n        _height = 358 if len(params[\"subm\"]) == 11 else 254\n        f   = figure(width=785, height=_height)\n        f.title.text = 'Click on legend entries to mute the corresponding lines'\n        b,e        = 21000,21154\n        line_x     = [dfs[i][b:e]['row_id']         for i in range(len(dfs))]\n        line_y     = [dfs[i][b:e]['similarity'] for i in range(len(dfs))]\n        color      = colors + [color_cross]\n        alpha      = [0.8 for i in range(len(dfs)-1)] + [0.95]\n        lws        = [1.0 for i in range(len(dfs)-1)] + [1.00]\n        legend = subm_names + ['cross']\n        for i in range(len(legend)):\n            f.line(line_x[i], line_y[i], line_width=lws[i], color=color[i], alpha=alpha[i],\n                   muted_color='white',legend_label=legend[i])\n        f.legend.location = \"top_left\"\n        f.legend.click_policy=\"mute\"\n        show(f)\n\n# An example of working with Seaborn is taken from a notebook:\n# https://www.kaggle.com/code/likithagedipudi/kaggle-success-factors\n# Presented by an expert from Buffalo, New York, United States - Likitha Gedipudi\n# https://www.kaggle.com/likithagedipudi\n\ndef seaborn_display_1(params,\n                      df_cross,\n                      show_figures1, show_figures2, color_cross):\n\n    colors = [subm['color'] for subm in params['subm']]\n    \n    def dossier(js,subms,cols):\n        def quant(i,js,subms,cols):\n            return {\"c\" : i, \"q\" : sum([1 for subm in cols[i] if subm == subms[js]])}\n        return {\n            'name' : subms[js],\n            'q_in' : [quant(i,js,subms,cols) for i in range(len(subms))]\n        }\n    alls = pd.read_csv(f'tida_desc.csv')\n    matrix = [ast.literal_eval(str(row.alls)) for row in alls.itertuples()]\n    subms = sorted(matrix[0])\n    cols = [[data[i] for data in matrix] for i in range(len(subms))]\n    df_subms = pd.DataFrame({f'col_{i}': [x[i] for x in matrix] for i in range(len(subms))})\n    dossiers = [dossier(js,subms,cols) for js in range(len(subms))]\n    subm_names = [one_dossier['name'] for one_dossier in dossiers]\n    \n    nqs,qss,i = [],[],0\n    \n    for one_dossier in dossiers: \n        qs = [one['q'] for one in one_dossier['q_in']]\n        x_names = [name.replace(\"Group\",\"\").replace(\"subm_\",\"\") for name in subm_names]\n        qss.append(qs)\n        nqs.append({'n':x_names, 'q':qs})\n        i+=1\n    \n    plt.style.use('seaborn-v0_8-whitegrid')\n    plt.rcParams['font.size']      = 7\n    plt.rcParams['axes.titlesize'] = 9\n    plt.rcParams['axes.labelsize'] = 8\n\n    len_nqs = len(nqs) if len(nqs) > 3 else 4\n\n    fig, axes = plt.subplots(2, len_nqs, figsize=(2.1*len_nqs, 4))\n    \n    def ric(j, i, n, q, colors):\n        ax1 = axes[j, i]\n        bars1 = ax1.bar(n, q, color=colors)\n        ax1.set_title(f'ratios in alls.col {i}', fontweight='bold')\n        ax1.set_xticklabels(n, rotation=45, ha='right')\n        i = 0\n        for bar, val in zip(bars1, q):\n            if i != 0:\n                ax1.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 50, \n                         f'{val:,.0f}', ha='center', va='bottom', fontsize=8)\n            i += 1\n\n    lm_max = 0\n    for i in range(len(nqs)):\n        for q in nqs[i]['q']:\n            if q > lm_max: lm_max = q  \n    lm_colors = ['lemonchiffon'] + colors\n    for nq in nqs:\n        nq['n'].insert(0,'')\n        nq['q'].insert(0, lm_max*1.13)\n\n    for i in range(len(nqs)): ric(0, i, nqs[i]['n'], nqs[i]['q'], lm_colors)\n\n    ax10 = axes[1, 0]\n    #--------------------------------------------------------------------------------\n    sub_wts = params['subwts']\n    main_wts = [subm['weight'] for subm in params['subm']]\n    mms,acc_mass = [],[]\n    for j in range(len(dossiers)):\n        one_dossier = dossiers[j]\n        qs = [one['q'] for one in one_dossier['q_in']]\n        mm = [qs[h] * (main_wts[j] + sub_wts[h]) for h in range(len(sub_wts))]\n        mass = sum(mm)\n        mms.append(mm)\n        acc_mass.append(round(mass))\n    acc_mass = acc_mass\n    y_names = [str(mass) + \" - \" + name for name,mass in zip(subm_names,acc_mass)]\n    colors  .insert(0,'lemonchiffon')\n    y_names .insert(0,'')\n    acc_mass.insert(0, max(acc_mass) * 1.13)\n    irbis = ax10.barh(y_names[::-1], acc_mass[::-1], color=colors[::-1])\n    ax10.set_title('relations of g.masses', fontweight='bold')\n    ax10.set_xlabel('weights')\n\n\n    ax11 = axes[1, 1]\n    #--------------------------------------------------------------------------------\n    corr_matrix = alls[subm_names].corr()\n    mask = np.triu(np.ones_like(corr_matrix, dtype=bool))\n    mask = 0.5*mask\n    sns.heatmap(corr_matrix, mask=mask, annot=True, cmap='RdBu_r', \n                center=0,fmt='.3f', square=True, linewidths=0.5, ax=ax11,\n                cbar_kws={'shrink': 0.8})\n    ax11.set_title('Correlation Matrix', fontweight='bold', fontsize=9)\n    ax11.set_xticklabels(subm_names, rotation=45, ha='right')\n\n    ax13 = axes[1,3]\n    #--------------------------------------------------------------------------------\n    ip1 = len(nqs)-1\n    ip2 = len(nqs)-2\n    sample  = alls.sample(min(100_000, len(alls)), random_state=42)\n    scatter = ax13.scatter(np.log10(sample[subm_names[ip2]] + 1), \n                           np.log10(sample[subm_names[ip1]] + 1), \n                           c=sample['similarity'], cmap='viridis', alpha=0.5, s=10)\n    ax13.set_title(f'{subm_names[ip2]} vs {subm_names[ip1]}', fontweight='bold', fontsize=8)\n    plt.colorbar(scatter, ax=ax13, label='Score')\n\n    ax12 = axes[1, 2]\n    #--------------------------------------------------------------------------------\n    colors = [subm['color'] for subm in params['subm']]\n    \n    for subm,color in zip(subm_names,colors):\n        subm_data = alls[subm]\n        ax12.hist(np.log10(subm_data + 1), bins=30, alpha=0.5, label=subm, color=color)\n    ax12.set_title('(Log Scale)', fontweight='bold')\n    ax12.set_xlabel('log10')\n    ax12.set_ylabel('Frequency')\n    ax12.legend()\n \n    plt.tight_layout()\n    plt.show()\n\n\ndef seaborn_display_2(params, file_name_cross=\"\"):\n    plt.figure(figsize=(9, 2.5))\n    for subm in params['subm']:\n        pred = pd.read_csv(params['path']+subm['name']+'.csv')[params['id_target'][1]]\n        sns.kdeplot(pred, label = subm['name'], linewidth = 0.5)\n    if file_name_cross != '':\n        pred = pd.read_csv(file_name_cross)[params['id_target'][1]]\n        sns.kdeplot(pred, label = 'blend', linewidth = 1, linestyle = 'dashed')\n    plt.title(\"KDE\")\n    plt.xlabel(\"target\")\n    plt.ylabel(\"Density\")\n    plt.legend()\n    plt.grid(alpha=0.3)\n    plt.show()\n\n\ndef matrix_vs(path,fs_names):\n    def load(path,fs_names):\n        dfs = [pd.read_csv(path + name_subm +'.csv') for name_subm in fs_names]\n        for i in range(len(dfs)):\n            dfs[i] = dfs[i].rename(columns={\"similarity\": f'{fs_names[i]}'})\n        dfsm = pd.merge(dfs[0], dfs[1], on=\"row_id\")\n        for i in range(2,len(dfs)):\n            dfsm = pd.merge(dfsm,dfs[i],on='row_id')\n        return dfsm   \n    def make_list_vs(fs_names):\n        list = []\n        for i in range(0,len(fs_names)-1):\n            for j in range(i+1,len(fs_names)):\n                list.append(fs_names[i] + \"_vs_\" + fs_names[j])\n        return list\n    def get_mvs(dfs, list_vs):\n        def get_abs_distance(x,t1,t2):\n            return abs(x[t1]-x[t2])\n        for vs in list_vs:\n            t = vs.split('_vs_')\n            dfs[vs] = dfs.apply(lambda x: get_abs_distance(x,t[0],t[1]), axis=1)\n        return dfs   \n    def distance_vs(name, st_names, list_vs, dfs):\n        distances = []\n        for st in st_names:\n            vs_between = name + \"_vs_\" + st\n            if vs_between not in list_vs:\n                distances.append(0)\n            else: distances.append(round(dfs[vs_between].sum()))\n        return distances\n    dfs = load(path,fs_names)\n    list_vs = make_list_vs(fs_names)\n    mvs = get_mvs(dfs, list_vs)\n    m1 = pd.DataFrame({'subm':fs_names})\n    m2 = pd.DataFrame({ name :distance_vs(name, fs_names, list_vs, mvs) for name in fs_names})\n    matrix = pd.concat([m1,m2],axis=1)\n    return matrix\n\n\ndef display_distances(params):\n    files = [subm['name'] for subm in params['subm']]\n    distances = matrix_vs ( params['path'], files )            \n    display(distances)\n\n\ndef arr_colors(color):\n    dskb,mvr = 'deepskyblue','mediumvioletred'\n    sg = ['darkgray','silver','gainsboro']\n    if color=='red'   or color=='R': return ['firebrick','red','crimson','tomato']     + sg\n    if color=='Red'   or color=='r': return ['red','tomato','crimson']                 + sg\n    if color=='Green' or color=='G': return ['darkgreen','limegreen','green','lime']   + sg\n    if color=='Blue'  or color=='B': return ['midnightblue','blue','mediumblue',dskb]  + sg\n    if color=='RGB'   or color=='S': return ['mediumblue','darkgreen','crimson']       + sg\n    if color=='RGBM'  or color=='M': return [mvr,'darkorchid','darkmagenta','magenta'] + sg\n    return ['black','dimgray','gray'] + sg\n\n\ndef convert(schema):\n    colors = arr_colors(schema[2])\n    dicts  = [\n        {'name': schema[0][i],'weight':schema[1][i],'color':colors[i]} \n        for i in range(len(schema[0]))\n    ]\n    return {'subm':dicts}\n\n\ndef h_blend(\n        params, _update={},\n        cross='silver',\n        details=False,\n        fig1=False, fig2=False, wf2=555, \n        dtls=False, dist=False, subm=''):\n\n    if isinstance(params, list): params = convert(params)\n\n    if 'path' in _update: params.update(_update)\n    \n    color_cross, dk  = cross, copy.deepcopy(params)\n\n    if details == True:\n        dist = True\n        show_details,show_figures1,show_figures2 = True,True,True\n    else:\n        show_details,show_figures1,show_figures2 = dtls,fig1,fig2\n        \n    file_short_names = [subm['name'] for subm in params['subm']]\n    type_sort    = params['type_sort'][0]\n    dk['asc']    = params['type_sort'][1]\n    dk['desc']   = params['type_sort'][2]\n    dk['id']     = params['id_target'][0]\n    dk['target'] = params['id_target'][1]\n    \n    def read(dk,i):\n        tnm = dk[\"subm\"][i][\"name\"]\n        FiN = dk[\"path\"] + tnm + \".csv\"\n        return pd.read_csv(FiN).rename(columns={\n            'target':tnm, 'pred':tnm, dk[\"target\"]:tnm})\n        \n    def merge(dfs_subm):\n        df_subms = pd.merge(dfs_subm[0],  dfs_subm[1], on=[dk['id']])\n        for i in range(2, len(dk[\"subm\"])): \n            df_subms = pd.merge(df_subms, dfs_subm[i], on=[dk['id']])\n        return df_subms\n        \n    def da(dk,sorting_direction,show_details):\n        \n        df_subms = merge([read(dk,i) for i in range(len(dk[\"subm\"]))])\n        cols = [col for col in df_subms.columns if col != dk['id']]\n        short_name_cols = [c for c in cols]\n        \n        def alls1(x, sd=sorting_direction,cs=cols):\n            reverse = True if sd=='desc' else False\n            tes = {c: x[c] for c in cs}.items()\n            subms_sorted = [t[0] for t in sorted(tes,key=lambda k:k[1],reverse=reverse)]\n            return subms_sorted\n\n        import random\n\n        def alls2(x, sd=sorting_direction,cs=cols):\n            reverse = True if sd=='desc' else False\n            tes = {c: x[c] for c in cs}.items()\n            subms_random = [t[0] for t in tes]\n            random.shuffle(subms_random)\n            return subms_random\n\n        alls = alls1 if type_sort == 'asc/desc' else alls2\n            \n        def summa(x,cs,wts,ic_alls): \n            return sum([x[cs[j]] * (wts[0][j] + wts[1][ic_alls[j]]) for j in range(len(cs))])\n            \n        wts = [[[e['weight'] for e in dk[\"subm\"]], [w for w in dk[\"subwts\"]]]]\n          \n        def correct(x, cs=cols, wts=wts):\n            i = [x['alls'].index(c) for c in short_name_cols]\n            return summa(x,cs,wts[0],i)\n\n        if len(wts) == 1:\n            correct_sub_weights = [wt for wt in dk[\"subwts\"]]\n            weights = [subm['weight'] for subm in dk[\"subm\"]]\n            def correct(x, cs=cols, w=weights, cw=correct_sub_weights):\n                ic = [x['alls'].index(c) for c in short_name_cols]\n                cS = [x[cols[j]] * (w[j] + cw[ic[j]]) for j in range(len(cols))]\n                return sum(cS)\n                \n        if len(wts) > 1 or \"subwts2\" in dk:\n\n            wts = [\n                [[e['weight'] for e in dk[\"subm\"]], [w for w in dk[\"subwts\" ]]],\n                [[e['weight'] for e in dk[\"subm2\"]],[w for w in dk[\"subwts2\"]]],\n                [[e['weight'] for e in dk[\"subm3\"]],[w for w in dk[\"subwts3\"]]],\n            ]\n\n            def correct(x, cs=cols, wts=wts):\n                i = [x['alls'].index(c) for c in short_name_cols]\n                if   0.0540 < x['mx-m'] <= 0.0740: return summa(x,cs,wts[2],i)\n                if   0.0000 < x['mx-m'] <= 0.0050: return summa(x,cs,wts[1],i)\n                else:                              return summa(x,cs,wts[0],i)\n                   \n        def amxm(x, cs=cols):\n            list_values = x[cs].to_list()\n            mxm = abs(max(list_values)-min(list_values))\n            return mxm\n\n        if len(wts) > 1 or \"subwts2\" in dk:\n            df_subms['mx-m']   = df_subms.apply(lambda x: amxm   (x), axis=1)\n        df_subms['alls']       = df_subms.apply(lambda x: alls   (x), axis=1)\n        df_subms[dk[\"target\"]] = df_subms.apply(lambda x: correct(x), axis=1)\n        schema_rename = { old_nc:new_shnc for old_nc, new_shnc in zip(cols, short_name_cols) }\n        df_subms = df_subms.rename(columns=schema_rename)\n        df_subms = df_subms.rename(columns={dk[\"target\"]:\"ensemble\"})\n        df_subms.insert(loc=1, column=' _ ', value=['   '] * len(df_subms))\n        df_subms[' _ '] = df_subms[' _ '].astype(str)\n        pd.set_option('display.max_rows',100)\n        pd.set_option('display.float_format', '{:.5f}'.format)\n        if len(wts) > 1: \n            vcols = [dk['id']] + [' _ '] + short_name_cols + [' _ '] + ['mx-m'] + [' _ '] +\\\n                      ['alls'] + [' _ '] + ['ensemble']\n        else:\n            vcols = [dk['id']] + [' _ '] + short_name_cols + [' _ '] +\\\n                      ['alls'] + [' _ '] + ['ensemble']\n        df_subms = df_subms[vcols]\n        if show_details and sorting_direction=='desc': display(df_subms.head(5))\n        pd.set_option('display.float_format', '{:.5f}'.format)\n        df_subms = df_subms.rename(columns={\"ensemble\":dk[\"target\"]})\n        if sorting_direction=='desc': \n            df_subms.to_csv(f'tida_{sorting_direction}.csv', index=False)\n        return df_subms[[dk['id'],dk['target']]]\n   \n    def ensemble_da(dk,        show_details): \n        dfD    = da(dk,'desc', show_details)\n        dfA    = da(dk,'asc',  show_details)\n        dfA[dk['target']] = dk['desc']*dfD[dk['target']] + dfA[dk['target']]*dk['asc']\n        return dfA\n\n    da = ensemble_da(dk,show_details)\n\n    # bokeh_show(dk, da, show_figures1, False, wf2, color_cross)\n\n    if subm != '': da.to_csv(subm, index=False)\n\n    seaborn_display_1(dk, da, show_figures1, False, color_cross)\n\n    display_distances(params)\n\n    seaborn_display_2(params, file_name_cross=subm)\n    \n    return  da","metadata":{"trusted":true,"_kg_hide-input":true,"jupyter":{"source_hidden":true},"execution":{"iopub.status.busy":"2026-02-14T02:40:22.495740Z","iopub.execute_input":"2026-02-14T02:40:22.496061Z","iopub.status.idle":"2026-02-14T02:40:22.577737Z","shell.execute_reply.started":"2026-02-14T02:40:22.496036Z","shell.execute_reply":"2026-02-14T02:40:22.576773Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## h-blend","metadata":{}},{"cell_type":"code","source":"%%time\n\nparams = {\n      'path'     : f'/kaggle/input/datasets/nina2025/jaguar/',            \n      'id_target': ['row_id','similarity'],          \n      'type_sort': ['asc/desc',0.30,0.70 ],\n      'subwts'   : [w/100 for w in [ +1, -1,-1, +1 ]],\n      'subm'     : [\n          {'name': f'0.930', 'weight':+0.01, 'color':'mediumblue'},\n          {'name': f'0.937', 'weight':+0.02, 'color':'orange'},\n          {'name': f'0.938', 'weight':+0.02, 'color':'green'},\n          {'name': f'0.944', 'weight':+0.95, 'color':'crimson'},]\n}\ndf = h_blend(params, details=True, subm='cross.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-14T02:44:17.036526Z","iopub.execute_input":"2026-02-14T02:44:17.037082Z","iopub.status.idle":"2026-02-14T02:44:43.113081Z","shell.execute_reply.started":"2026-02-14T02:44:17.037052Z","shell.execute_reply":"2026-02-14T02:44:43.112149Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for file in 'cross,tida_desc'.split(','): \n    if os.path.isfile(file+'.csv'): os.remove(file+'.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-14T02:45:18.918051Z","iopub.execute_input":"2026-02-14T02:45:18.918477Z","iopub.status.idle":"2026-02-14T02:45:18.927805Z","shell.execute_reply.started":"2026-02-14T02:45:18.918448Z","shell.execute_reply":"2026-02-14T02:45:18.926776Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Submit","metadata":{}},{"cell_type":"code","source":"df.to_csv('submission.csv',index=False)\ndf","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-14T02:45:21.183646Z","iopub.execute_input":"2026-02-14T02:45:21.184417Z","iopub.status.idle":"2026-02-14T02:45:21.501543Z","shell.execute_reply.started":"2026-02-14T02:45:21.184380Z","shell.execute_reply":"2026-02-14T02:45:21.500671Z"}},"outputs":[],"execution_count":null}]}