Files
FYS-STK4155/doc/LectureNotes/.ipynb_checkpoints/exercisesweek43-checkpoint.ipynb
T
Morten Hjorth-Jensen d51dd09ac3 typos
2025-10-20 13:15:40 +02:00

648 lines
19 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"cells": [
{
"cell_type": "markdown",
"id": "860d70d8",
"metadata": {
"editable": true
},
"source": [
"<!-- HTML file automatically generated from DocOnce source (https://github.com/doconce/doconce/)\n",
"doconce format html exercisesweek43.do.txt -->\n",
"<!-- dom:TITLE: Exercises week 43 -->"
]
},
{
"cell_type": "markdown",
"id": "119c0988",
"metadata": {
"editable": true
},
"source": [
"# Exercises week 43 \n",
"**October 20-24, 2025**\n",
"\n",
"Date: **Deadline Friday October 24 at midnight**"
]
},
{
"cell_type": "markdown",
"id": "909887eb",
"metadata": {
"editable": true
},
"source": [
"# Overarching aims of the exercises for week 43\n",
"\n",
"The aim of the exercises this week is to gain some confidence with\n",
"ways to visualize the results of a classification problem. We will\n",
"target three ways of setting up the analysis. The first and simplest\n",
"one is the\n",
"1. so-called confusion matrix. The next one is the so-called\n",
"\n",
"2. ROC curve. Finally we have the\n",
"\n",
"3. Cumulative gain curve.\n",
"\n",
"We will use Logistic Regression as method for the classification in\n",
"this exercise. You can compare these results with those obtained with\n",
"your neural network code from project 2 without a hidden layer.\n",
"\n",
"In these exercises we will use binary and multi-class data sets\n",
"(the Iris data set from week 41).\n",
"\n",
"The underlying mathematics is described here."
]
},
{
"cell_type": "markdown",
"id": "1e1cb4fb",
"metadata": {
"editable": true
},
"source": [
"### Confusion Matrix\n",
"\n",
"A **confusion matrix** summarizes a classifiers performance by\n",
"tabulating predictions versus true labels. For binary classification,\n",
"it is a $2\\times2$ table whose entries are counts of outcomes:"
]
},
{
"cell_type": "markdown",
"id": "7b090385",
"metadata": {
"editable": true
},
"source": [
"$$\n",
"\\begin{array}{l|cc} & \\text{Predicted Positive} & \\text{Predicted Negative} \\\\ \\hline \\text{Actual Positive} & TP & FN \\\\ \\text{Actual Negative} & FP & TN \\end{array}.\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "1e14904b",
"metadata": {
"editable": true
},
"source": [
"Here TP (true positives) is the number of cases correctly predicted as\n",
"positive, FP (false positives) is the number incorrectly predicted as\n",
"positive, TN (true negatives) is correctly predicted negative, and FN\n",
"(false negatives) is incorrectly predicted negative . In other words,\n",
"“positive” means class 1 and “negative” means class 0; for example, TP\n",
"occurs when the prediction and actual are both positive. Formally:"
]
},
{
"cell_type": "markdown",
"id": "e93ea290",
"metadata": {
"editable": true
},
"source": [
"$$\n",
"\\text{TPR} = \\frac{\\text{TP}}{\\text{TP} + \\text{FN}}, \\quad \\text{FPR} = \\frac{\\text{FP}}{\\text{FP} + \\text{TN}},\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "c80bea5b",
"metadata": {
"editable": true
},
"source": [
"where TPR and FPR are the true and false positive rates defined below.\n",
"\n",
"In multiclass classification with $K$ classes, the confusion matrix\n",
"generalizes to a $K\\times K$ table. Entry $N_{ij}$ in the table is\n",
"the count of instances whose true class is $i$ and whose predicted\n",
"class is $j$. For example, a three-class confusion matrix can be written\n",
"as:"
]
},
{
"cell_type": "markdown",
"id": "a0f68f5f",
"metadata": {
"editable": true
},
"source": [
"$$\n",
"\\begin{array}{c|ccc} & \\text{Pred Class 1} & \\text{Pred Class 2} & \\text{Pred Class 3} \\\\ \\hline \\text{Act Class 1} & N_{11} & N_{12} & N_{13} \\\\ \\text{Act Class 2} & N_{21} & N_{22} & N_{23} \\\\ \\text{Act Class 3} & N_{31} & N_{32} & N_{33} \\end{array}.\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "869669b2",
"metadata": {
"editable": true
},
"source": [
"Here the diagonal entries $N_{ii}$ are the true positives for each\n",
"class, and off-diagonal entries are misclassifications. This matrix\n",
"allows computation of per-class metrics: e.g. for class $i$,\n",
"$\\mathrm{TP}_i=N_{ii}$, $\\mathrm{FN}_i=\\sum_{j\\neq i}N_{ij}$,\n",
"$\\mathrm{FP}_i=\\sum_{j\\neq i}N_{ji}$, and $\\mathrm{TN}_i$ is the sum of\n",
"all remaining entries.\n",
"\n",
"As defined above, TPR and FPR come from the binary case. In binary\n",
"terms with $P$ actual positives and $N$ actual negatives, one has"
]
},
{
"cell_type": "markdown",
"id": "2abd82a7",
"metadata": {
"editable": true
},
"source": [
"$$\n",
"\\text{TPR} = \\frac{TP}{P} = \\frac{TP}{TP+FN}, \\quad \\text{FPR} =\n",
"\\frac{FP}{N} = \\frac{FP}{FP+TN},\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "2f79325c",
"metadata": {
"editable": true
},
"source": [
"as used in standard confusion-matrix\n",
"formulations. These rates will be used in constructing ROC curves."
]
},
{
"cell_type": "markdown",
"id": "0ce65a47",
"metadata": {
"editable": true
},
"source": [
"### ROC Curve\n",
"\n",
"The Receiver Operating Characteristic (ROC) curve plots the trade-off\n",
"between true positives and false positives as a discrimination\n",
"threshold varies. Specifically, for a binary classifier that outputs\n",
"a score or probability, one varies the threshold $t$ for declaring\n",
"**positive**, and computes at each $t$ the true positive rate\n",
"$\\mathrm{TPR}(t)$ and false positive rate $\\mathrm{FPR}(t)$ using the\n",
"confusion matrix at that threshold. The ROC curve is then the graph\n",
"of TPR versus FPR. By definition,"
]
},
{
"cell_type": "markdown",
"id": "d750fdff",
"metadata": {
"editable": true
},
"source": [
"$$\n",
"\\mathrm{TPR} = \\frac{TP}{TP+FN}, \\qquad \\mathrm{FPR} = \\frac{FP}{FP+TN},\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "561bfb2c",
"metadata": {
"editable": true
},
"source": [
"where $TP,FP,TN,FN$ are counts determined by threshold $t$. A perfect\n",
"classifier would reach the point (FPR=0, TPR=1) at some threshold.\n",
"\n",
"Formally, the ROC curve is obtained by plotting\n",
"$(\\mathrm{FPR}(t),\\mathrm{TPR}(t))$ for all $t\\in[0,1]$ (or as $t$\n",
"sweeps through the sorted scores). The Area Under the ROC Curve (AUC)\n",
"quantifies the average performance over all thresholds. It can be\n",
"interpreted probabilistically: $\\mathrm{AUC} =\n",
"\\Pr\\bigl(s(X^+)>s(X^-)\\bigr)$, the probability that a random positive\n",
"instance $X^+$ receives a higher score $s$ than a random negative\n",
"instance $X^-$ . Equivalently, the AUC is the integral under the ROC\n",
"curve:"
]
},
{
"cell_type": "markdown",
"id": "5ca722fe",
"metadata": {
"editable": true
},
"source": [
"$$\n",
"\\mathrm{AUC} \\;=\\; \\int_{0}^{1} \\mathrm{TPR}(f)\\,df,\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "30080a86",
"metadata": {
"editable": true
},
"source": [
"where $f$ ranges over FPR (or fraction of negatives). A model that guesses at random yields a diagonal ROC (AUC=0.5), whereas a perfect model yields AUC=1.0."
]
},
{
"cell_type": "markdown",
"id": "9e627156",
"metadata": {
"editable": true
},
"source": [
"### Cumulative Gain\n",
"\n",
"The cumulative gain curve (or gains chart) evaluates how many\n",
"positives are captured as one targets an increasing fraction of the\n",
"population, sorted by model confidence. To construct it, sort all\n",
"instances by decreasing predicted probability of the positive class.\n",
"Then, for the top $\\alpha$ fraction of instances, compute the fraction\n",
"of all actual positives that fall in this subset. In formula form, if\n",
"$P$ is the total number of positive instances and $P(\\alpha)$ is the\n",
"number of positives among the top $\\alpha$ of the data, the cumulative\n",
"gain at level $\\alpha$ is"
]
},
{
"cell_type": "markdown",
"id": "3e9132ef",
"metadata": {
"editable": true
},
"source": [
"$$\n",
"\\mathrm{Gain}(\\alpha) \\;=\\; \\frac{P(\\alpha)}{P}.\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "75be6f5c",
"metadata": {
"editable": true
},
"source": [
"For example, cutting off at the top 10% of predictions yields a gain\n",
"equal to (positives in top 10%) divided by (total positives) .\n",
"Plotting $\\mathrm{Gain}(\\alpha)$ versus $\\alpha$ (often in percent)\n",
"gives the gain curve. The baseline (random) curve is the diagonal\n",
"$\\mathrm{Gain}(\\alpha)=\\alpha$, while an ideal model has a steep climb\n",
"toward 1.\n",
"\n",
"A related measure is the {\\em lift}, often called the gain ratio. It is the ratio of the models capture rate to that of random selection. Equivalently,"
]
},
{
"cell_type": "markdown",
"id": "e5525570",
"metadata": {
"editable": true
},
"source": [
"$$\n",
"\\mathrm{Lift}(\\alpha) \\;=\\; \\frac{\\mathrm{Gain}(\\alpha)}{\\alpha}.\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "18ff8dc2",
"metadata": {
"editable": true
},
"source": [
"A lift $>1$ indicates better-than-random targeting. In practice, gain\n",
"and lift charts (used e.g.\\ in marketing or imbalanced classification)\n",
"show how many positives can be “gained” by focusing on a fraction of\n",
"the population ."
]
},
{
"cell_type": "markdown",
"id": "c3d3fde8",
"metadata": {
"editable": true
},
"source": [
"### Other measures: Precision, Recall, and the F$_1$ Measure\n",
"\n",
"Precision and recall (sensitivity) quantify binary classification\n",
"accuracy in terms of positive predictions. They are defined from the\n",
"confusion matrix as:"
]
},
{
"cell_type": "markdown",
"id": "f1f14c8e",
"metadata": {
"editable": true
},
"source": [
"$$\n",
"\\text{Precision} = \\frac{TP}{TP + FP}, \\qquad \\text{Recall} = \\frac{TP}{TP + FN}.\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "422cc743",
"metadata": {
"editable": true
},
"source": [
"Precision is the fraction of predicted positives that are correct, and\n",
"recall is the fraction of actual positives that are correctly\n",
"identified . A high-precision classifier makes few false-positive\n",
"errors, while a high-recall classifier makes few false-negative\n",
"errors.\n",
"\n",
"The F$_1$ score (balanced F-measure) combines precision and recall into a single metric via their harmonic mean. The usual formula is:"
]
},
{
"cell_type": "markdown",
"id": "621a2e8b",
"metadata": {
"editable": true
},
"source": [
"$$\n",
"F_1 =2\\frac{\\text{Precision}\\times\\text{Recall}}{\\text{Precision} + \\text{Recall}}.\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "62eee54a",
"metadata": {
"editable": true
},
"source": [
"This can be shown to equal"
]
},
{
"cell_type": "markdown",
"id": "7a6a2e7a",
"metadata": {
"editable": true
},
"source": [
"$$\n",
"\\frac{2\\,TP}{2\\,TP + FP + FN}.\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "b96c9ff4",
"metadata": {
"editable": true
},
"source": [
"The F$_1$ score ranges from 0 (worst) to 1 (best), and balances the\n",
"trade-off between precision and recall.\n",
"\n",
"For multi-class classification, one computes per-class\n",
"precision/recall/F$_1$ (treating each class as “positive” in a\n",
"one-vs-rest manner) and then averages. Common averaging methods are:\n",
"\n",
"Micro-averaging: Sum all true positives, false positives, and false negatives across classes, then compute precision/recall/F$_1$ from these totals.\n",
"Macro-averaging: Compute the F$1$ score $F{1,i}$ for each class $i$ separately, then take the unweighted mean: $F_{1,\\mathrm{macro}} = \\frac{1}{K}\\sum_{i=1}^K F_{1,i}$ . This treats all classes equally regardless of size.\n",
"Weighted-averaging: Like macro-average, but weight each classs $F_{1,i}$ by its support $n_i$ (true count): $F_{1,\\mathrm{weighted}} = \\frac{1}{N}\\sum_{i=1}^K n_i F_{1,i}$, where $N=\\sum_i n_i$. This accounts for class imbalance by giving more weight to larger classes .\n",
"\n",
"Each of these averages has different use-cases. Micro-average is\n",
"dominated by common classes, macro-average highlights performance on\n",
"rare classes, and weighted-average is a compromise. These formulas\n",
"and concepts allow rigorous evaluation of classifier performance in\n",
"both binary and multi-class settings."
]
},
{
"cell_type": "markdown",
"id": "9274bf3f",
"metadata": {
"editable": true
},
"source": [
"## Exercises\n",
"\n",
"Here is a simple code example which uses the Logistic regression machinery from **scikit-learn**.\n",
"At the end it sets up the confusion matrix and the ROC and cumulative gain curves.\n",
"Feel free to use these functionalities (we don't expect you to write your own code for say the confusion matrix)."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "be9ff0b9",
"metadata": {
"collapsed": false,
"editable": true,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"%matplotlib inline\n",
"\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"from sklearn.model_selection import train_test_split \n",
"# from sklearn.datasets import fill in the data set\n",
"from sklearn.linear_model import LogisticRegression\n",
"\n",
"# Load the data, fill inn\n",
"mydata.data = ?\n",
"\n",
"X_train, X_test, y_train, y_test = train_test_split(mydata.data,cancer.target,random_state=0)\n",
"print(X_train.shape)\n",
"print(X_test.shape)\n",
"# Logistic Regression\n",
"# define which type of problem, binary or multiclass\n",
"logreg = LogisticRegression(solver='lbfgs')\n",
"logreg.fit(X_train, y_train)\n",
"\n",
"from sklearn.preprocessing import LabelEncoder\n",
"from sklearn.model_selection import cross_validate\n",
"#Cross validation\n",
"accuracy = cross_validate(logreg,X_test,y_test,cv=10)['test_score']\n",
"print(accuracy)\n",
"print(\"Test set accuracy with Logistic Regression: {:.2f}\".format(logreg.score(X_test,y_test)))\n",
"\n",
"import scikitplot as skplt\n",
"y_pred = logreg.predict(X_test)\n",
"skplt.metrics.plot_confusion_matrix(y_test, y_pred, normalize=True)\n",
"plt.show()\n",
"y_probas = logreg.predict_proba(X_test)\n",
"skplt.metrics.plot_roc(y_test, y_probas)\n",
"plt.show()\n",
"skplt.metrics.plot_cumulative_gain(y_test, y_probas)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "51760b3e",
"metadata": {
"editable": true
},
"source": [
"### Exercise a)\n",
"\n",
"Convince yourself about the mathematics for the confusion matrix, the ROC and the cumlative gain curves for both a binary and a multiclass classification problem."
]
},
{
"cell_type": "markdown",
"id": "c1d42f5f",
"metadata": {
"editable": true
},
"source": [
"### Exercise b)\n",
"\n",
"Use a binary classification data available from **scikit-learn**. As an example you can use\n",
"the MNIST data set and just specialize to two numbers. To do so you can use the following code lines"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "d20bb8be",
"metadata": {
"collapsed": false,
"editable": true,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"from sklearn.datasets import load_digits\n",
"digits = load_digits(n_class=2) # Load only two classes, e.g., 0 and 1\n",
"X, y = digits.data, digits.target"
]
},
{
"cell_type": "markdown",
"id": "828ea1cd",
"metadata": {
"editable": true
},
"source": [
"Alternatively, you can use the _make$\\_$classification_\n",
"functionality. This function generates a random $n$-class classification\n",
"dataset, which can be configured for binary classification by setting\n",
"n_classes=2. You can also control the number of samples, features,\n",
"informative features, redundant features, and more."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "d271f0ba",
"metadata": {
"collapsed": false,
"editable": true,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"from sklearn.datasets import make_classification\n",
"X, y = make_classification(n_samples=1000, n_features=20, n_informative=10, n_redundant=5, n_classes=2, random_state=42)"
]
},
{
"cell_type": "markdown",
"id": "0068b032",
"metadata": {
"editable": true
},
"source": [
"You can use this option for the multiclass case as well, see the next exercise.\n",
"If you prefer to study other binary classification datasets, feel free\n",
"to replace the above suggestions with your own dataset.\n",
"\n",
"Make plots of the confusion matrix, the ROC curve and the cumulative gain curve."
]
},
{
"cell_type": "markdown",
"id": "c45f5b41",
"metadata": {
"editable": true
},
"source": [
"### Exercise c) week 43\n",
"\n",
"As a multiclass problem, we will use the Iris data set discussed in\n",
"the exercises from weeks 41 and 42. This is a three-class data set and\n",
"you can set it up using **scikit-learn**,"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "3b045d56",
"metadata": {
"collapsed": false,
"editable": true,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"source": [
"from sklearn.datasets import load_iris\n",
"iris = load_iris()\n",
"X = iris.data # Features\n",
"y = iris.target # Target labels"
]
},
{
"cell_type": "markdown",
"id": "14cc859c",
"metadata": {
"editable": true
},
"source": [
"Make plots of the confusion matrix, the ROC curve and the cumulative\n",
"gain curve for this (or other) multiclass data set."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.9.15"
}
},
"nbformat": 4,
"nbformat_minor": 5
}