import%20marimo%0A%0A__generated_with%20%3D%20%220.23.16%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20METADATA%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22id%22%3A%20%22metrics%22%2C%0A%20%20%20%20%20%20%20%20%22name%22%3A%20%22Metrics%22%2C%0A%20%20%20%20%20%20%20%20%22kind%22%3A%20%22concept%22%2C%0A%20%20%20%20%20%20%20%20%22difficulty%22%3A%20%22beginner%22%2C%0A%20%20%20%20%20%20%20%20%22status%22%3A%20%22complete%22%2C%0A%20%20%20%20%20%20%20%20%22topics%22%3A%20%5B%22classification_metrics%22%2C%20%22evaluation%22%5D%2C%0A%20%20%20%20%20%20%20%20%22related_models%22%3A%20%5B%22logistic_regression%22%2C%20%22decision_tree%22%2C%20%22transformer%22%5D%2C%0A%20%20%20%20%20%20%20%20%22prerequisites%22%3A%20%5B%22train_validation_test%22%5D%2C%0A%20%20%20%20%7D%0A%20%20%20%20mo.md(f%22%23%20%7BMETADATA%5B'name'%5D%7D%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20In%20one%20sentence%0A%0A%20%20%20%20A%20metric%20compresses%20model%20behavior%20into%20a%20number%2C%20so%20choosing%20one%20means%20choosing%20which%20mistakes%20matter.%0A%0A%20%20%20%20%23%23%20Mental%20model%0A%0A%20%20%20%20A%20metric%20is%20a%20lens%2C%20not%20a%20verdict.%20Precision%20looks%20at%20predicted%20positives%2C%20recall%20looks%20at%20real%20positives%2C%20and%20neither%20says%20what%20operating%20threshold%20the%20product%20can%20afford.%0A%0A%20%20%20%20%23%23%20Why%20it%20matters%0A%0A%20%20%20%20Two%20models%20can%20have%20the%20same%20accuracy%20while%20creating%20radically%20different%20consequences%20when%20positives%20are%20rare%20or%20one%20type%20of%20error%20is%20expensive.%0A%0A%20%20%20%20%23%23%20Experiment%0A%0A%20%20%20%20**Question%3A**%20how%20does%20moving%20one%20classification%20threshold%20change%20the%20apparent%20quality%20of%20the%20same%20underlying%20scores%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20from%20sklearn.metrics%20import%20confusion_matrix%2C%20precision_recall_fscore_support%0A%0A%20%20%20%20rng%20%3D%20np.random.default_rng(9)%0A%20%20%20%20y_true%20%3D%20np.r_%5Bnp.zeros(160%2C%20dtype%3Dint)%2C%20np.ones(40%2C%20dtype%3Dint)%5D%0A%20%20%20%20scores%20%3D%20np.r_%5Brng.beta(2%2C%206%2C%20160)%2C%20rng.beta(5%2C%202.8%2C%2040)%5D%0A%20%20%20%20thresholds%20%3D%20np.linspace(0.05%2C%200.95%2C%2080)%0A%20%20%20%20precision%2C%20recall%2C%20f1%20%3D%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%0A%20%20%20%20for%20threshold%20in%20thresholds%3A%0A%20%20%20%20%20%20%20%20predicted%20%3D%20scores%20%3E%3D%20threshold%0A%20%20%20%20%20%20%20%20p%2C%20r%2C%20f%2C%20_%20%3D%20precision_recall_fscore_support(y_true%2C%20predicted%2C%20average%3D%22binary%22%2C%20zero_division%3D0)%0A%20%20%20%20%20%20%20%20precision.append(p)%0A%20%20%20%20%20%20%20%20recall.append(r)%0A%20%20%20%20%20%20%20%20f1.append(f)%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20confusion_matrix%2C%0A%20%20%20%20%20%20%20%20f1%2C%0A%20%20%20%20%20%20%20%20np%2C%0A%20%20%20%20%20%20%20%20plt%2C%0A%20%20%20%20%20%20%20%20precision%2C%0A%20%20%20%20%20%20%20%20recall%2C%0A%20%20%20%20%20%20%20%20scores%2C%0A%20%20%20%20%20%20%20%20thresholds%2C%0A%20%20%20%20%20%20%20%20y_true%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20confusion_matrix%2C%0A%20%20%20%20f1%2C%0A%20%20%20%20np%2C%0A%20%20%20%20plt%2C%0A%20%20%20%20precision%2C%0A%20%20%20%20recall%2C%0A%20%20%20%20scores%2C%0A%20%20%20%20thresholds%2C%0A%20%20%20%20y_true%2C%0A)%3A%0A%20%20%20%20chosen%20%3D%200.5%0A%20%20%20%20matrix%20%3D%20confusion_matrix(y_true%2C%20scores%20%3E%3D%20chosen)%0A%20%20%20%20fig%2C%20axes%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(10%2C%204))%0A%20%20%20%20axes%5B0%5D.plot(thresholds%2C%20precision%2C%20label%3D%22precision%22)%0A%20%20%20%20axes%5B0%5D.plot(thresholds%2C%20recall%2C%20label%3D%22recall%22)%0A%20%20%20%20axes%5B0%5D.plot(thresholds%2C%20f1%2C%20label%3D%22F1%22)%0A%20%20%20%20axes%5B0%5D.axvline(chosen%2C%20color%3D%22black%22%2C%20linestyle%3D%22--%22%2C%20label%3D%22chosen%20threshold%22)%0A%20%20%20%20axes%5B0%5D.set(title%3D%22One%20score%20model%2C%20many%20operating%20points%22%2C%20xlabel%3D%22threshold%22%2C%20ylabel%3D%22metric%22)%0A%20%20%20%20axes%5B0%5D.legend()%0A%20%20%20%20image%20%3D%20axes%5B1%5D.imshow(matrix%2C%20cmap%3D%22Blues%22)%0A%20%20%20%20for%20row%2C%20column%20in%20np.ndindex(matrix.shape)%3A%0A%20%20%20%20%20%20%20%20axes%5B1%5D.text(column%2C%20row%2C%20matrix%5Brow%2C%20column%5D%2C%20ha%3D%22center%22%2C%20va%3D%22center%22)%0A%20%20%20%20axes%5B1%5D.set(title%3D%22Confusion%20matrix%20at%20threshold%200.50%22%2C%20xlabel%3D%22predicted%22%2C%20ylabel%3D%22actual%22)%0A%20%20%20%20axes%5B1%5D.set_xticks(%5B0%2C%201%5D%2C%20%5B%22negative%22%2C%20%22positive%22%5D)%0A%20%20%20%20axes%5B1%5D.set_yticks(%5B0%2C%201%5D%2C%20%5B%22negative%22%2C%20%22positive%22%5D)%0A%20%20%20%20fig.colorbar(image%2C%20ax%3Daxes%5B1%5D%2C%20fraction%3D0.046)%0A%20%20%20%20plt.tight_layout()%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Common%20mistake%0A%0A%20%20%20%20Selecting%20accuracy%20by%20habit%2C%20especially%20when%20the%20positive%20class%20is%20rare%2C%20or%20choosing%20a%20threshold%20on%20the%20final%20test%20set.%0A%0A%20%20%20%20%23%23%20Diagnosis%0A%0A%20%20%20%20Inspect%20the%20confusion%20matrix%2C%20precision%E2%80%93recall%20behavior%2C%20calibration%2C%20and%20performance%20across%20important%20groups.%20Translate%20false%20positives%20and%20false%20negatives%20into%20real%20costs.%0A%0A%20%20%20%20%23%23%20Practical%20rule%0A%0A%20%20%20%20Choose%20the%20metric%20from%20the%20decision%20cost%2C%20then%20report%20complementary%20diagnostics%20and%20select%20the%20operating%20threshold%20on%20validation%20data.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
0381486ef8e25d243c089bf1ae0491a0