File size: 88,814 Bytes
91ed952
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from scipy.special import log_softmax\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import torch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test priors: [0.49 0.51]\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>steps</th>\n",
       "      <th>alphas</th>\n",
       "      <th>betas</th>\n",
       "      <th>ner</th>\n",
       "      <th>nce</th>\n",
       "      <th>train_priors</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>seed</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1568</td>\n",
       "      <td>0.272969</td>\n",
       "      <td>[0.0, 0.0]</td>\n",
       "      <td>0.163265</td>\n",
       "      <td>0.344810</td>\n",
       "      <td>[0.47368421052631576, 0.5263157894736842]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1576</td>\n",
       "      <td>0.280585</td>\n",
       "      <td>[0.0, 0.0]</td>\n",
       "      <td>0.173469</td>\n",
       "      <td>0.374176</td>\n",
       "      <td>[0.631578947368421, 0.3684210526315789]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1467</td>\n",
       "      <td>0.350538</td>\n",
       "      <td>[0.0, 0.0]</td>\n",
       "      <td>0.163265</td>\n",
       "      <td>0.377032</td>\n",
       "      <td>[0.47368421052631576, 0.5263157894736842]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>[0.0, 0.0]</td>\n",
       "      <td>0.137755</td>\n",
       "      <td>0.662122</td>\n",
       "      <td>[0.42105263157894735, 0.5789473684210527]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1424</td>\n",
       "      <td>0.436886</td>\n",
       "      <td>[0.0, 0.0]</td>\n",
       "      <td>0.158163</td>\n",
       "      <td>0.364137</td>\n",
       "      <td>[0.7368421052631579, 0.2631578947368421]</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      steps    alphas       betas       ner       nce  \\\n",
       "seed                                                    \n",
       "0      1568  0.272969  [0.0, 0.0]  0.163265  0.344810   \n",
       "1      1576  0.280585  [0.0, 0.0]  0.173469  0.374176   \n",
       "2      1467  0.350538  [0.0, 0.0]  0.163265  0.377032   \n",
       "3         1  1.000000  [0.0, 0.0]  0.137755  0.662122   \n",
       "4      1424  0.436886  [0.0, 0.0]  0.158163  0.364137   \n",
       "\n",
       "                                   train_priors  \n",
       "seed                                             \n",
       "0     [0.47368421052631576, 0.5263157894736842]  \n",
       "1       [0.631578947368421, 0.3684210526315789]  \n",
       "2     [0.47368421052631576, 0.5263157894736842]  \n",
       "3     [0.42105263157894735, 0.5789473684210527]  \n",
       "4      [0.7368421052631579, 0.2631578947368421]  "
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def load_steps(dataset, size, method=\"dpcal\", old=True):\n",
    "    steps = []\n",
    "    for seed in range(5):\n",
    "        filename = f\"../outputs/{'old/' if old else ''}lora_plus_{method}/llama3.2-1b-instruct/{dataset}/size={size}/seed={seed}/lora_ans_no_es/0.0-0.7/0.0-0.3/0.7-1.0/state.ckpt\"\n",
    "        state = torch.load(filename, weights_only=False)\n",
    "        steps.append(state[\"best_step_count\"])\n",
    "    return steps\n",
    "\n",
    "def load_params(dataset, size, method=\"dpcal\", old=True):\n",
    "    alphas, betas = [], []\n",
    "    for seed in range(5):\n",
    "        filename = f\"../outputs/{'old/' if old else ''}lora_plus_{method}/llama3.2-1b-instruct/{dataset}/size={size}/seed={seed}/lora_ans_no_es/0.0-0.7/0.0-0.3/0.7-1.0/state.ckpt\"\n",
    "        state = torch.load(filename, weights_only=False)\n",
    "        alphas.append(state['best_model']['alpha'].cpu().item())\n",
    "        betas.append(state['best_model']['beta'].cpu().numpy().astype(float))\n",
    "    return alphas, betas\n",
    "\n",
    "def load_priors(dataset, size):\n",
    "    priors = []\n",
    "    for seed in range(5):\n",
    "        filename = f\"../outputs/finetune_lora/llama3.2-1b-instruct/{dataset}/size={size}/seed={seed}/lora_ans_no_es/0.0-0.7/0.0-0.3/test={dataset}/list=0.7-1.0\"\n",
    "        labels = pd.read_csv(f\"{filename}/labels.csv\", header=None, index_col=0).values.astype(int).flatten()\n",
    "        priors.append(np.bincount(labels) / len(labels))\n",
    "    return priors\n",
    "\n",
    "def compute_ner(dataset, size, method=\"dpcal\", old=True):\n",
    "    ner = []\n",
    "    for seed in range(5):\n",
    "        filename = f\"../outputs/{'old/' if old else ''}lora_plus_{method}/llama3.2-1b-instruct/{dataset}/size={size}/seed={seed}/lora_ans_no_es/0.0-0.7/0.0-0.3/0.7-1.0/test={dataset}/list=test_400\"\n",
    "        logits = pd.read_csv(f\"{filename}/logits.csv\", header=None, index_col=0).values.astype(float)\n",
    "        labels = pd.read_csv(f\"{filename}/labels.csv\", header=None, index_col=0).values.astype(int).flatten()\n",
    "        priors = np.bincount(labels) / len(labels)\n",
    "        er = np.mean(logits.argmax(axis=1) != labels)\n",
    "        er_priors = np.mean(priors.argmax() != labels)\n",
    "        ner.append(er / er_priors)\n",
    "    return ner\n",
    "\n",
    "def compute_nce(dataset, size, method=\"dpcal\", old=True):\n",
    "    nce = []\n",
    "    for seed in range(5):\n",
    "        filename = f\"../outputs/{'old/' if old else ''}lora_plus_{method}/llama3.2-1b-instruct/{dataset}/size={size}/seed={seed}/lora_ans_no_es/0.0-0.7/0.0-0.3/0.7-1.0/test={dataset}/list=test_400\"\n",
    "        logits = pd.read_csv(f\"{filename}/logits.csv\", header=None, index_col=0).values.astype(float)\n",
    "        logits = log_softmax(logits, axis=1)\n",
    "        labels = pd.read_csv(f\"{filename}/labels.csv\", header=None, index_col=0).values.astype(int).flatten()\n",
    "        priors = np.bincount(labels) / len(labels)\n",
    "        ce = -np.mean(logits[np.arange(len(labels)), labels])\n",
    "        ce_priors = -np.mean(np.log(priors[labels]))\n",
    "        nce.append(ce / ce_priors)\n",
    "    return nce\n",
    "\n",
    "def load_test_priors(dataset, size, method=\"dpcal\", old=True):\n",
    "    # filename = f\"../outputs/finetune_lora/llama3.2-1b-instruct/{dataset}/size={size}/seed={seed}/lora_ans_no_es/0.0-0.7/0.0-0.3/test={dataset}/list=0.7-1.0\"\n",
    "    filename = f\"../outputs/{'old/' if old else ''}lora_plus_{method}/llama3.2-1b-instruct/{dataset}/size={size}/seed=0/lora_ans_no_es/0.0-0.7/0.0-0.3/0.7-1.0/test={dataset}/list=test_400\"\n",
    "    labels = pd.read_csv(f\"{filename}/labels.csv\", header=None, index_col=0).values.astype(int).flatten()\n",
    "    priors = np.bincount(labels) / len(labels)\n",
    "    return priors\n",
    "\n",
    "\n",
    "dataset = \"sst2\"\n",
    "size = 32\n",
    "method = \"tempscaling\"\n",
    "old = False\n",
    "steps = load_steps(dataset, size, method, old=old)\n",
    "alphas, betas = load_params(dataset, size, method, old=old)\n",
    "train_priors = load_priors(dataset, size)\n",
    "ner = compute_ner(dataset, size, method, old=old)\n",
    "nce = compute_nce(dataset, size, method, old=old)\n",
    "test_priors = load_test_priors(dataset, size, method, old=old)\n",
    "print(\"Test priors:\", test_priors)\n",
    "\n",
    "pd.DataFrame({\n",
    "    \"steps\": steps,\n",
    "    \"alphas\": alphas,\n",
    "    \"betas\": betas,\n",
    "    \"ner\": ner,\n",
    "    \"nce\": nce,\n",
    "    \"train_priors\": train_priors\n",
    "}, index=pd.Index(range(5), name=\"seed\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test priors: [0.23   0.2625 0.2575 0.25  ]\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>steps</th>\n",
       "      <th>alphas</th>\n",
       "      <th>betas</th>\n",
       "      <th>ner</th>\n",
       "      <th>nce</th>\n",
       "      <th>train_priors</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>seed</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2</td>\n",
       "      <td>1.000133</td>\n",
       "      <td>[0.0, 0.0, 0.0, 0.0]</td>\n",
       "      <td>0.305085</td>\n",
       "      <td>0.772099</td>\n",
       "      <td>[1.0]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>1.000152</td>\n",
       "      <td>[0.0, 0.0, 0.0, 0.0]</td>\n",
       "      <td>0.159322</td>\n",
       "      <td>0.350738</td>\n",
       "      <td>[0.25, 0.0, 0.5, 0.25]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2687</td>\n",
       "      <td>0.085351</td>\n",
       "      <td>[0.0, 0.0, 0.0, 0.0]</td>\n",
       "      <td>0.383051</td>\n",
       "      <td>0.737915</td>\n",
       "      <td>[0.0, 0.5, 0.5]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>567</td>\n",
       "      <td>0.664049</td>\n",
       "      <td>[0.0, 0.0, 0.0, 0.0]</td>\n",
       "      <td>0.233898</td>\n",
       "      <td>0.401422</td>\n",
       "      <td>[0.25, 0.5, 0.0, 0.25]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1196</td>\n",
       "      <td>1.521518</td>\n",
       "      <td>[0.0, 0.0, 0.0, 0.0]</td>\n",
       "      <td>0.230508</td>\n",
       "      <td>0.685006</td>\n",
       "      <td>[0.0, 0.25, 0.25, 0.5]</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      steps    alphas                 betas       ner       nce  \\\n",
       "seed                                                              \n",
       "0         2  1.000133  [0.0, 0.0, 0.0, 0.0]  0.305085  0.772099   \n",
       "1         2  1.000152  [0.0, 0.0, 0.0, 0.0]  0.159322  0.350738   \n",
       "2      2687  0.085351  [0.0, 0.0, 0.0, 0.0]  0.383051  0.737915   \n",
       "3       567  0.664049  [0.0, 0.0, 0.0, 0.0]  0.233898  0.401422   \n",
       "4      1196  1.521518  [0.0, 0.0, 0.0, 0.0]  0.230508  0.685006   \n",
       "\n",
       "                train_priors  \n",
       "seed                          \n",
       "0                      [1.0]  \n",
       "1     [0.25, 0.0, 0.5, 0.25]  \n",
       "2            [0.0, 0.5, 0.5]  \n",
       "3     [0.25, 0.5, 0.0, 0.25]  \n",
       "4     [0.0, 0.25, 0.25, 0.5]  "
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataset = \"agnews\"\n",
    "size = 8\n",
    "method = \"tempscaling\"\n",
    "old = False\n",
    "steps = load_steps(dataset, size, method, old=old)\n",
    "alphas, betas = load_params(dataset, size, method, old=old)\n",
    "train_priors = load_priors(dataset, size)\n",
    "ner = compute_ner(dataset, size, method, old=old)\n",
    "nce = compute_nce(dataset, size, method, old=old)\n",
    "test_priors = load_test_priors(dataset, size, method, old=old)\n",
    "print(\"Test priors:\", test_priors)\n",
    "\n",
    "pd.DataFrame({\n",
    "    \"steps\": steps,\n",
    "    \"alphas\": alphas,\n",
    "    \"betas\": betas,\n",
    "    \"ner\": ner,\n",
    "    \"nce\": nce,\n",
    "    \"train_priors\": train_priors\n",
    "}, index=pd.Index(range(5), name=\"seed\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Calibrated CE: 0.20321426528170855\n",
      "Calibrated NCE: 0.35259800781306166\n"
     ]
    },
    {
     "data": {
      "image/png": "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SQlycnLg6+srJavW1DthuOeee/Dtt9+id+/emDx5MubMmYMvvvgCR44cwWOPPVavfe3btw9vvfUWjh49iszMTHz11VcYNWqU2cksXboUH330EfLz8zFw4ECsXbsWUVFRUpm8vDw888wz+O677yCXyzF69GisXr0aXl5eUpnff/8dcXFxOHz4MFq0aIFnnnkG8+bNM4tl27ZtWLx4MS5duoSoqCi8+eabePDBB+t7eYiIiIhuikwmQ2hoKNLS0nD58mV7h0PNgK+vL0JCQuosV++EYf369TAajQCAuLg4BAQEIDk5GQ8//DBmzJhRr30VFxejZ8+emDJlisVkY8WKFXj33XexadMmREREYPHixYiNjcWff/4pTS4xfvx4ZGZmIjExEeXl5Zg8eTKmT5+OzZs3AxAnZLn//vsxbNgwrFu3DidOnMCUKVPg6+srzdiXnJyMcePGYfny5Rg5ciQ2b96MUaNG4dixY+jWrVt9LxERERHRTVEqlYiKimKzJGp0rq6uddYsmNR7pufGIpPJzGoYBEFAWFgYnn/+ebzwwgsAgIKCAgQHB2Pjxo0YO3YsTp06hS5duuDw4cPo06cPAGDnzp148MEHcfXqVYSFhWHt2rV46aWXkJWVBaVSCQBYsGABvv76a5w+fRoAMGbMGBQXF2P79u1SPP3790evXr2wbt06m+J3pJkiiYiIbivNZKZnIkdlUw3D77//bvMOe/TocdPBVJWWloasrCwMGzZMWubj44N+/fohJSUFY8eORUpKCnx9faVkAQCGDRsGuVyOgwcP4tFHH0VKSgoGDx4sJQsAEBsbizfffBM3btyAn58fUlJSkJCQYHb82NhYfP3111bj02q10Gq10nuNRtMAZ01ERERE5FhsShh69eoFmUxWZ6dmmUwGg8HQIIFlZWUBAIKDg82WBwcHS+uysrIQFBRktt7FxQX+/v5mZSIiImrsw7TOz88PWVlZtR7HkuXLl2PZsmU3cWZERERERM7DpoQhLS2tseNwOgsXLjSrldBoNAgPD7djREREREREDc+mhKFNmzaNHUcNph7b2dnZCA0NlZZnZ2ejV69eUpmcnByz7fR6PfLy8qTtQ0JCkJ2dbVbG9L6uMrX1GlepVFCpVDdxZkREREREzqPeA/wuX74cH3/8cY3lH3/8Md58880GCQoAIiIiEBISgj179kjLNBoN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jdizZw/i4+PtGxxRM8KEgZpEeno68vLykJ6eDoPBII3XHhkZCS8vL9x///3o0qULnnrqKaxYsQJZWVlYtGgR4uLiajzFbO5iYmLg5+eHiRMnYsmSJXB3d8dHH32EtLQ0jBgxwt7hOTy1Wo2ZM2di6dKlCA8PR5s2bfDWW28BAP72t7/ZOTrn0Lp1a7P3Xl5eAID27dujVatW9gjJqfz1118YMmQI2rRpg3/961+4du2atI5PzWtKSEjAxIkT0adPH/Tt2xerVq1CcXExJk+ebO/QiJoNJgzUJJYsWWLWTKF3794AgJ9//hlDhgyBQqHA9u3b8Y9//AMxMTHw9PTExIkT8corr9grZIcVGBiInTt34qWXXsI999yD8vJydO3aFd988w169uxp7/CcwltvvQUXFxc89dRTKC0tRb9+/fDTTz+x0zg1icTERJw/fx7nz5+vkWAJgmCnqBzXmDFjcO3aNSxZsgRZWVno1asXdu7cWaMjNBE1HpnAv05ERERERGQFG00SEREREZFVTBiIiIiIiMgqJgxERERERGQVEwYiIiIiIrKKCQMREREREVnFhIGIiIiIiKxiwkBERERERFYxYSAiIiIiIquYMBARERERkVVMGIiIiIiIyComDEREREREZBUTBiIiIiIisur/AfXQrrbqLrl5AAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def plot_distributions(dataset, size, seed, nbins=20, method=\"dpcal\"):\n",
    "\n",
    "    # Miscalibrated posteriors\n",
    "    filename = f\"../outputs/finetune_lora/llama3.2-1b-instruct/{dataset}/size={size}/seed={seed}/lora_ans_no_es/0.0-0.7/0.0-0.3/test={dataset}/list=0.7-1.0\"\n",
    "    miscal_logits = pd.read_csv(f\"{filename}/logits.csv\", header=None, index_col=0).values.astype(float)\n",
    "    miscal_logits = log_softmax(miscal_logits, axis=1)\n",
    "    miscal_labels = pd.read_csv(f\"{filename}/labels.csv\", header=None, index_col=0).values.astype(int).flatten()\n",
    "\n",
    "    # Calibrated posteriors\n",
    "    filename = f\"../outputs/old/lora_plus_{method}/llama3.2-1b-instruct/{dataset}/size={size}/seed={seed}/lora_ans_no_es/0.0-0.7/0.0-0.3/0.7-1.0/state.ckpt\"\n",
    "    state = torch.load(filename, weights_only=False)\n",
    "    alpha, beta = state[\"best_model\"][\"alpha\"].cpu().numpy(), state[\"best_model\"][\"beta\"].cpu().numpy()\n",
    "    cal_logits = log_softmax(miscal_logits * alpha + beta, axis=1)\n",
    "    cal_labels = miscal_labels.copy()\n",
    "\n",
    "    ce = -np.mean(cal_logits[np.arange(len(cal_labels)), cal_labels])\n",
    "    priors = np.bincount(cal_labels) / len(cal_labels)\n",
    "    ce_priors = -np.mean(np.log(priors[cal_labels]))\n",
    "    print(\"Calibrated CE:\", ce)\n",
    "    print(\"Calibrated NCE:\", ce / ce_priors)\n",
    "\n",
    "    num_classes = miscal_logits.shape[1]\n",
    "    fig, ax = plt.subplots(num_classes, 1, sharex=True)\n",
    "    for i in range(num_classes):\n",
    "        for j in range(num_classes):\n",
    "            # hist, edges = np.histogram(miscal_logits[miscal_labels==j, i]-miscal_logits[miscal_labels==j, 0], bins=nbins, density=True)\n",
    "            # ax[i].plot(edges[:-1], hist, label=f'class {j} pre-cal', alpha=0.5, color=f'C{j}', linestyle='-')\n",
    "            # hist, edges = np.histogram(cal_logits[cal_labels==j, i]-cal_logits[cal_labels==j, 0], bins=nbins, density=True)\n",
    "            # ax[i].plot(edges[:-1], hist, label=f'class {j} post-cal', alpha=0.5, color=f'C{j}', linestyle='--')\n",
    "            hist, edges = np.histogram(miscal_logits[miscal_labels==j, i], bins=nbins, density=True)\n",
    "            ax[i].plot(edges[:-1], hist, label=f'class {j} pre-cal', alpha=0.5, color=f'C{j}', linestyle='-')\n",
    "            hist, edges = np.histogram(cal_logits[cal_labels==j, i], bins=nbins, density=True)\n",
    "            ax[i].plot(edges[:-1], hist, label=f'class {j} post-cal', alpha=0.5, color=f'C{j}', linestyle='--')\n",
    "            # hist, edges, bar = ax[i].hist(miscal_logits[miscal_labels==j, i], bins=nbins, density=True, label=f'class {j} pre-cal', alpha=0.5, color=f'C{j}')\n",
    "            # print(hist, edges)\n",
    "\n",
    "            # print(miscal_logits[miscal_labels==j, i])\n",
    "            # ax[i].hist(cal_logits[cal_labels==j, i], bins=nbins, density=True, label=f'class {j} post-cal', alpha=0.5, color=f'C{j}')\n",
    "        ax[i].set_ylabel(f'class {i}')\n",
    "    ax[-1].legend(loc='upper right', bbox_to_anchor=(1.4, 1))\n",
    "    \n",
    "plot_distributions(dataset, size, 4, nbins=20, method=method)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Calibrated CE: 0.20321426528170855\n",
      "Calibrated NCE: 0.35259800781306166\n"
     ]
    },
    {
     "data": {
      "image/png": "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8uRJrVixQpKUkJCgXr166Y033pBUdtWj2NhYPfLII3rqqacuWrvNZlNERITy8vKYkgQAgI/g9zdwcXVqDUNeXp4kqXHjxpW2v//++/rf//1fRUdH67bbbtMzzzyjkJAQSVJmZqa6dOniCguSlJSUpIceekg7duzQNddco8zMTA0YMKDSMZOSkpSamipJKioq0ubNmzVlyhTXfj8/Pw0YMECZmZnnrdVut8tut7ue22y2S3/jF1BU4tDpolKZzSaFWurUPxcAAMBFORwOFRUVGV0GzhEQECCz2VytsXXmL1CHw6HU1FRdf/316ty5s2v73XffrdatWysmJkZbt27V5MmTtXv3bv3f//2fJMlqtVYKC5Jcz61W6wXH2Gw2nT59WidOnFBpael5x+zateu89aanp+u55577bW+6GrKPFuqzbYcU2zhEv+/B5d4AAIDvKCoqUnZ2thwOh9Gl4DwaNmyo6Ojoiy76rzOBITk5Wdu3b9fXX39dafv48eNdX3fp0kXNmzfXTTfdpB9//FFXXnllbZfpMmXKFKWlpbmeV1yWDQAAAGU3xTt06JDMZrNiY2O5MV4d4nQ6derUKdda3ebNm19wfJ0IDCkpKVq2bJnWrl170ZumJCQkSJJ++OEHXXnllYqOjq5yNaPc3FxJUnR0tOu/FdvOHhMeHq7g4GCZzWaZzebzjqk4xrksFossFkv13yQAAMBlpKSkRKdOnVJMTIxrKjnqjuDgYEnS4cOHFRkZecHpSYZGPafTqZSUFC1ZskRffvml4uLiLvo9WVlZkn5NQomJidq2bVulqxllZGQoPDxcnTp1co1ZtWpVpeNkZGQoMTFRkhQYGKgePXpUGuNwOLRq1SrXGAAAAFRfaWmppLK/s1A3VQS54uLiC44ztMOQnJysBQsW6JNPPlFYWJhrzUFERISCg4P1448/asGCBbrlllvUpEkTbd26VRMnTlSfPn3UtWtXSdLAgQPVqVMn3XPPPXrppZdktVr19NNPKzk52dUBePDBB/XGG29o0qRJuv/++/Xll19q0aJFWr58uauWtLQ0jR49Wj179lTv3r01c+ZMFRYWasyYMbV/YgAAAOoJbopXd1X338bQwDBnzhxJZZdOPds777yj++67T4GBgfriiy9cf7zHxsZq2LBhevrpp11jzWazli1bpoceekiJiYlq0KCBRo8ereeff941Ji4uTsuXL9fEiRM1a9YstWzZUn//+9+VlJTkGjN8+HAdOXJE06ZNk9VqVXx8vFasWFFlITQAAABwOalT92HwZd66jvNuaz5XSQIAwEu4D4P3nDlzRtnZ2YqLi1NQUJDR5dRLF7tf2cVU99+I5eoAAAAA3CIwAAAAAJfocrgpHYEBAAAAKNe3b1+lpKQoJSVFERERatq0qZ555hlVzOJv06aN/vKXv+jee+9VeHi4655hX3/9tW688UYFBwcrNjZWjz76qAoLCy/4WidPntSECRMUFRWloKAgde7cWcuWLZMkHTt2TCNHjlSLFi0UEhKiLl266IMPPvDum3eDwAAAAACvczqdKipxGPKo6ZLdd999V/7+/tq4caNmzZqlv/71r/r73//u2v/f//3f6tatm7777js988wz+vHHHzVo0CANGzZMW7du1cKFC/X1118rJSXF7Ws4HA4NHjxY33zzjf73f/9X33//vV588UXX/RDOnDmjHj16aPny5dq+fbvGjx+ve+65p8r9x2pDnbhxGwAAAOq34lKnZn/1gyGvndyvrQL9q39519jYWL366qsymUxq3769tm3bpldffVXjxo2TJPXv31+PP/64a/wDDzygUaNGKTU1VZLUrl07vfbaa/rd736nOXPmnHdB8RdffKGNGzdq586duuqqqyRJV1xxhWt/ixYt9MQTT7ieP/LII1q5cqUWLVqk3r171+j9/1Z0GAAAAICzXHvttZXuUZCYmKi9e/e6bkbXs2fPSuP/85//aP78+QoNDXU9kpKS5HA4lJ2drf/6r/+qtC8nJ0dZWVlq2bKlKyycq7S0VH/5y1/UpUsXNW7cWKGhoVq5cqVycnK898bdoMMAAAAArwswm5Tcr61hr+1JDRo0qPS8oKBAEyZM0KOPPlplbKtWrfTggw/qj3/8o2tbTEyMgoODL/gaL7/8smbNmqWZM2eqS5cuatCggVJTUw1ZZE1gAAAAgNeZTKYaTQsy0oYNGyo9X79+vdq1a+daX3Cu7t276/vvv1fbtucPRI0bN1bjxo0rbevatasOHDigPXv2nLfL8M033+iOO+7Qn/70J0llax727NmjTp06Xcpb+k2YkgQAAACcJScnR2lpadq9e7c++OADvf7663rsscfcjp88ebLWrVunlJQUZWVlae/evfrkk08uuOj5d7/7nfr06aNhw4YpIyND2dnZ+vzzz7VixQpJZesgMjIytG7dOu3cuVMTJkxQbm6ux99rddBhAAAAAM5y77336vTp0+rdu7fMZrMee+wx1+VTz6dr165as2aNpk6dqhtvvFFOp1NXXnmlhg8ffsHX+fjjj/XEE09o5MiRKiwsVNu2bfXiiy9Kkp5++mnt27dPSUlJCgkJ0fjx4zV06FDl5eV59L1Wh8lZ0+tM4by8dWv53dZ8fbbtkGIbh+j3PVp67LgAAMB7v79RdlnQ7OxsxcXFnfcqQXVV3759FR8fr5kzZxpditdV99+IKUkAAAAA3CIwAAAAAHCLNQwAAABAudWrVxtdQp1DhwEAAACAWwQGAAAAAG4RGAAAAAC4RWAAAAAA4BaBAQAAAIBbhgaG9PR09erVS2FhYYqMjNTQoUO1e/fuSmPOnDmj5ORkNWnSRKGhoRo2bFiV22Ln5ORoyJAhCgkJUWRkpJ588kmVlJRUGrN69Wp1795dFotFbdu21fz586vUM3v2bLVp00ZBQUFKSEjQxo0bPf6eAQAAAF9iaGBYs2aNkpOTtX79emVkZKi4uFgDBw5UYWGha8zEiRP1z3/+U4sXL9aaNWt08OBB3XXXXa79paWlGjJkiIqKirRu3Tq9++67mj9/vqZNm+Yak52drSFDhqhfv37KyspSamqqHnjgAa1cudI1ZuHChUpLS9P06dO1ZcsWdevWTUlJSTp8+HDtnAwAAADAQ+677z4NHTrUI8cyOZ1Op0eO5AFHjhxRZGSk1qxZoz59+igvL0/NmjXTggUL9Pvf/16StGvXLnXs2FGZmZm69tpr9fnnn+vWW2/VwYMHFRUVJUmaO3euJk+erCNHjigwMFCTJ0/W8uXLtX37dtdrjRgxQidPntSKFSskSQkJCerVq5feeOMNSZLD4VBsbKweeeQRPfXUUxet3Vu3lt9tzddn2w4ptnGIft+jpceOCwAAvPf7G2WzRLKzsxUXF6egoCCjy6kTVq9erX79+unEiRNq2LChV1/rvvvu08mTJ7V06VK3Y6r7b1Sn1jDk5eVJkho3bixJ2rx5s4qLizVgwADXmA4dOqhVq1bKzMyUJGVmZqpLly6usCBJSUlJstls2rFjh2vM2ceoGFNxjKKiIm3evLnSGD8/Pw0YMMA1BgAAALgc1ZnA4HA4lJqaquuvv16dO3eWJFmtVgUGBlZJYFFRUbJara4xZ4eFiv0V+y40xmaz6fTp0zp69KhKS0vPO6biGOey2+2y2WyVHgAAAPBtffv2VUpKilJSUhQREaGmTZvqmWeeUcWknBMnTujee+9Vo0aNFBISosGDB2vv3r2u7//555912223qVGjRmrQoIGuvvpqffbZZ/rpp5/Ur18/SVKjRo1kMpl03333ua3Dbrdr8uTJio2Nda3B/Z//+R9JZVPyx44dq7i4OAUHB6t9+/aaNWuW186Jv9eOXEPJycnavn27vv76a6NLqZb09HQ999xzRpcBAADgG5xOqbTYmNc2B0gmU7WHv/vuuxo7dqw2btyob7/9VuPHj1erVq00btw43Xfffdq7d68+/fRThYeHa/Lkybrlllv0/fffKyAgQMnJySoqKtLatWvVoEEDff/99woNDVVsbKw+/vhjDRs2TLt371Z4eLiCg4Pd1nDvvfcqMzNTr732mrp166bs7GwdPXpUUtkH7S1bttTixYvVpEkTrVu3TuPHj1fz5s31xz/+8TefrnPVicCQkpKiZcuWae3atWrZ8td5+tHR0SoqKtLJkycrdRlyc3MVHR3tGnPu1YwqrqJ09phzr6yUm5vr+ocym80ym83nHVNxjHNNmTJFaWlpruc2m02xsbE1fOcAAACXidJi6d+vGPPaNz4u+QdWe3hsbKxeffVVmUwmtW/fXtu2bdOrr76qvn376tNPP9U333yj6667TpL0/vvvKzY2VkuXLtUf/vAH5eTkaNiwYerSpYsk6YorrnAdt2LafWRk5AXXMOzZs0eLFi1SRkaGa8r82ccJCAio9MF1XFycMjMztWjRIq8EBkOnJDmdTqWkpGjJkiX68ssvFRcXV2l/jx49FBAQoFWrVrm27d69Wzk5OUpMTJQkJSYmatu2bZWuZpSRkaHw8HB16tTJNebsY1SMqThGYGCgevToUWmMw+HQqlWrXGPOZbFYFB4eXukBAAAA33fttdfKdFZHIjExUXv37tX3338vf39/JSQkuPY1adJE7du3186dOyVJjz76qF544QVdf/31mj59urZu3XrB13r//fcVGhrqevz73/9WVlaWzGazfve737n9vtmzZ6tHjx5q1qyZQkNDNW/ePOXk5PzGd35+hnYYkpOTtWDBAn3yyScKCwtzrReIiIhQcHCwIiIiNHbsWKWlpalx48YKDw/XI488osTERF177bWSpIEDB6pTp06655579NJLL8lqterpp59WcnKyLBaLJOnBBx/UG2+8oUmTJun+++/Xl19+qUWLFmn58uWuWtLS0jR69Gj17NlTvXv31syZM1VYWKgxY8bU/okBAACob8wBZZ/0G/XateSBBx5QUlKSli9frn/9619KT0/XK6+8okceeeS842+//fZKAaRFixb64osvLvgaH374oZ544gm98sorSkxMVFhYmF5++WVt2LDBo++lgqGBYc6cOZLKFpec7Z133nEtAnn11Vfl5+enYcOGyW63KykpSW+++aZrrNls1rJly/TQQw8pMTFRDRo00OjRo/X888+7xsTFxWn58uWaOHGiZs2apZYtW+rvf/+7kpKSXGOGDx+uI0eOaNq0abJarYqPj9eKFSuqLIQGAADAJTCZajQtyEjn/uG9fv16tWvXTp06dVJJSYk2bNjgmpJ07Ngx7d692zWzRSqb0vTggw/qwQcf1JQpU/S3v/1NjzzyiAIDy95/aWmpa2xYWJjCwsIqvV6XLl3kcDi0Zs2aKlf6lOSaEvXwww+7tv3444+//Y27YWhgqM4tIIKCgjR79mzNnj3b7ZjWrVvrs88+u+Bx+vbtq+++++6CYypWxAMAAODylZOTo7S0NE2YMEFbtmzR66+/rldeeUXt2rXTHXfcoXHjxumtt95SWFiYnnrqKbVo0UJ33HGHJCk1NVWDBw/WVVddpRMnTuirr75Sx44dJZX9zWoymbRs2TLdcsstCg4OVmhoaJXXb9OmjUaPHq3777/ftej5559/1uHDh/XHP/5R7dq103vvvaeVK1cqLi5O//jHP7Rp06Yq0/s9pc5cVhUAAACoC+69916dPn1avXv3VnJysh577DGNHz9eUtlMmB49eujWW29VYmKinE6nPvvsMwUElE17Ki0tVXJysjp27KhBgwbpqquucs2OadGihZ577jk99dRTioqKuuAH1XPmzNHvf/97Pfzww+rQoYPGjRunwsJCSdKECRN01113afjw4UpISNCxY8cqdRs8rU7d6dmXcadnAAB8D3d69h5fvdNz3759FR8fr5kzZxpditf55J2eAQAAANQtBAYAAAAAbtWJG7cBAAAAdcHq1auNLqHOocMAAAAAwC0CAwAAAAC3CAwAAADwGi7IWXc5HI5qjWMNAwAAADwuICBAJpNJR44cUbNmzWQymYwuCeWcTqeKiop05MgR+fn5ue5A7Q6BAQAAAB5nNpvVsmVLHThwQD/99JPR5eA8QkJC1KpVK/n5XXjSEYEBAAAAXhEaGqp27dqpuLjY6FJwDrPZLH9//2p1fggMAAAA8Bqz2Syz2Wx0GfgNWPQMAAAAwC0CAwAAAAC3CAwAAAAA3CIwAAAAAHCLwAAAAADALQIDAAAAALc8FhhOnDih9957z1OHAwAAAFAHeCww5OTkaMyYMZ46HAAAAIA6oNqBwWazXfCRn59f4xdfu3atbrvtNsXExMhkMmnp0qWV9t93330ymUyVHoMGDao05vjx4xo1apTCw8PVsGFDjR07VgUFBZXGbN26VTfeeKOCgoIUGxurl156qUotixcvVocOHRQUFKQuXbros88+q/H7AQAAAOqbat/puWHDhhe8dbTT6azWraXPVlhYqG7duun+++/XXXfddd4xgwYN0jvvvON6brFYKu0fNWqUDh06pIyMDBUXF2vMmDEaP368FixYIKks6AwcOFADBgzQ3LlztW3bNt1///1q2LChxo8fL0lat26dRo4cqfT0dN16661asGCBhg4dqi1btqhz5841ek8AAABAfWJyOp3O6gyMiIjQ1KlTlZCQcN79e/fu1YQJE1RaWnpphZhMWrJkiYYOHeradt999+nkyZNVOg8Vdu7cqU6dOmnTpk3q2bOnJGnFihW65ZZbdODAAcXExGjOnDmaOnWqrFarAgMDJUlPPfWUli5dql27dkmShg8frsLCQi1btsx17GuvvVbx8fGaO3duteq32WyKiIhQXl6ewsPDL+EMnN9ua74+23ZIsY1D9PseLT12XAAA4L3f30B9Uu0OQ/fu3SVJv/vd7867v2HDhqpm9qiR1atXKzIyUo0aNVL//v31wgsvqEmTJpKkzMxMNWzY0BUWJGnAgAHy8/PThg0bdOeddyozM1N9+vRxhQVJSkpK0owZM3TixAk1atRImZmZSktLq/S6SUlJboOKJNntdtntdtdzm83moXcMAAAA1B3VXsNw9913KygoyO3+6OhoTZ8+3SNFVRg0aJDee+89rVq1SjNmzNCaNWs0ePBgVxfDarUqMjKy0vf4+/urcePGslqtrjFRUVGVxlQ8v9iYiv3nk56eroiICNcjNjb2t71ZAAAAoA6qdodh3LhxF9wfFRXl8cAwYsQI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",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def plot_scores(dataset, size, seed, nbins=20, method=\"dpcal\"):\n",
    "\n",
    "    # Miscalibrated posteriors\n",
    "    filename = f\"../outputs/finetune_lora/llama3.2-1b-instruct/{dataset}/size={size}/seed={seed}/lora_ans_no_es/0.0-0.7/0.0-0.3/test={dataset}/list=0.7-1.0\"\n",
    "    miscal_logits = pd.read_csv(f\"{filename}/logits.csv\", header=None, index_col=0).values.astype(float)\n",
    "    miscal_logits = log_softmax(miscal_logits, axis=1)\n",
    "    miscal_labels = pd.read_csv(f\"{filename}/labels.csv\", header=None, index_col=0).values.astype(int).flatten()\n",
    "\n",
    "    # Calibrated posteriors\n",
    "    filename = f\"../outputs/old/lora_plus_{method}/llama3.2-1b-instruct/{dataset}/size={size}/seed={seed}/lora_ans_no_es/0.0-0.7/0.0-0.3/0.7-1.0/state.ckpt\"\n",
    "    state = torch.load(filename, weights_only=False)\n",
    "    alpha, beta = state[\"best_model\"][\"alpha\"].cpu().numpy(), state[\"best_model\"][\"beta\"].cpu().numpy()\n",
    "    cal_logits = log_softmax(miscal_logits * alpha + beta, axis=1)\n",
    "    cal_labels = miscal_labels.copy()\n",
    "\n",
    "    ce = -np.mean(cal_logits[np.arange(len(cal_labels)), cal_labels])\n",
    "    priors = np.bincount(cal_labels) / len(cal_labels)\n",
    "    ce_priors = -np.mean(np.log(priors[cal_labels]))\n",
    "    print(\"Calibrated CE:\", ce)\n",
    "    print(\"Calibrated NCE:\", ce / ce_priors)\n",
    "\n",
    "    num_classes = miscal_logits.shape[1]\n",
    "    fig, ax = plt.subplots(num_classes, 1, sharex=True)\n",
    "    for i in range(num_classes):\n",
    "        miscal_scores = -miscal_logits[miscal_labels==i,i]\n",
    "        hist, edges = np.histogram(miscal_scores, bins=nbins, density=True)\n",
    "        ax[i].plot(edges[:-1], hist, label=f'pre-cal', alpha=0.5, color=f'tab:blue', linestyle='-')\n",
    "        cal_scores = -cal_logits[cal_labels==i,i]\n",
    "        hist, edges = np.histogram(cal_scores, bins=nbins, density=True)\n",
    "        ax[i].plot(edges[:-1], hist, label=f'post-cal', alpha=0.5, color=f'tab:orange', linestyle='-')\n",
    "        ax[i].set_ylabel(f'class {i}')\n",
    "    ax[-1].legend(loc='upper right', bbox_to_anchor=(1.4, 1))\n",
    "    \n",
    "plot_scores(dataset, size, 4, nbins=20, method=method)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Calibrated CE: 2.2178437021873257e-06\n",
      "Calibrated NCE: 3.848190824339659e-06\n",
      "alpha: Parameter containing:\n",
      "tensor(9.0929, dtype=torch.float64, requires_grad=True)\n"
     ]
    }
   ],
   "source": [
    "from psrcal.calibration import AffineCalLogLoss\n",
    "import torch\n",
    "\n",
    "def calibrate(dataset, size, seed):\n",
    "\n",
    "    # Miscalibrated posteriors\n",
    "    filename = f\"../outputs/finetune_lora/llama3.2-1b-instruct/{dataset}/size={size}/seed={seed}/lora_ans_no_es/0.0-0.7/0.0-0.3/test={dataset}/list=0.7-1.0\"\n",
    "    miscal_logits = pd.read_csv(f\"{filename}/logits.csv\", header=None, index_col=0).values.astype(float)\n",
    "    miscal_logits = torch.from_numpy(log_softmax(miscal_logits, axis=1))\n",
    "    miscal_labels = torch.from_numpy(pd.read_csv(f\"{filename}/labels.csv\", header=None, index_col=0).values.astype(int).flatten())\n",
    "\n",
    "    model = AffineCalLogLoss(miscal_logits, miscal_labels, bias=True, scale=True, priors=None)\n",
    "    model.train()\n",
    "\n",
    "    cal_logits = model.calibrate(miscal_logits).cpu().detach().numpy()\n",
    "    cal_labels = miscal_labels.cpu().detach().numpy()\n",
    "\n",
    "    ce = -np.mean(cal_logits[np.arange(len(cal_labels)), cal_labels])\n",
    "    priors = np.bincount(cal_labels) / len(cal_labels)\n",
    "    ce_priors = -np.mean(np.log(priors[cal_labels]))\n",
    "    print(\"Calibrated CE:\", ce)\n",
    "    print(\"Calibrated NCE:\", ce / ce_priors)\n",
    "    print(\"alpha:\", model.temp)\n",
    "\n",
    "calibrate(\"sst2\", 32, 4)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "llmcal",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}