Skip to content

Commit a0810ad

Browse files
committed
roc_curve.typ and assets1
- increment title from "117 Scientific Diagrams" to "118 Scientific Diagrams" in readme - update badge links for Typst from "96" to "98" - convert complex-sign-function.tex to Typst Cetz
1 parent 392835e commit a0810ad

File tree

9 files changed

+845
-34
lines changed

9 files changed

+845
-34
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#import "@preview/cetz:0.3.4": canvas, draw, vector, matrix
2+
#import draw: set-transform, scale, content, line, rect, group
3+
4+
#set page(width: auto, height: auto, margin: 8pt)
5+
#set text(size: 8pt)
6+
7+
#canvas({
8+
draw.set-style(line: (stroke: none))
9+
// Set up the transformation matrix for 3D perspective
10+
set-transform(matrix.transform-rotate-dir((1, 1, -2), (0, 2, .3)))
11+
scale(x: 1.5, z: -1)
12+
13+
let arrow-style = (mark: (end: "stealth", fill: black, scale: 0.5))
14+
15+
// Add vertical z-lines at corners and origin
16+
for (x, y) in ((-1, -1), (1, -1), (-1, 1), (1, 1)) {
17+
draw.line((x, y, -1.2), (x, y, 1.2), stroke: gray + .3pt)
18+
}
19+
draw.line((0, 0, -1.2), (0, 0, 1.2), stroke: gray + .3pt, ..arrow-style)
20+
21+
22+
// Draw the zero plane (gray, semi-transparent)
23+
group({
24+
draw.rect((-1, -1, 0), (1, 1, 0), fill: rgb(128, 128, 128, 20), stroke: none)
25+
})
26+
27+
// Draw the blue quadrants (s = -1)
28+
group({
29+
draw.on-layer(
30+
-1,
31+
{
32+
draw.line(
33+
(-1, 0, -1),
34+
(0, 0, -1),
35+
(0, 1, -1),
36+
(-1, 1, -1),
37+
fill: rgb(173, 216, 230),
38+
)
39+
draw.line(
40+
(0, -1, -1),
41+
(1, -1, -1),
42+
(1, 0, -1),
43+
(0, 0, -1),
44+
fill: rgb(173, 216, 230),
45+
)
46+
},
47+
)
48+
})
49+
50+
// Draw the orange quadrants (s = 1)
51+
group({
52+
draw.line(
53+
(0, 0, 1),
54+
(1, 0, 1),
55+
(1, 1, 1),
56+
(0, 1, 1),
57+
fill: rgb(255, 165, 0),
58+
)
59+
draw.line(
60+
(-1, -1, 1),
61+
(0, -1, 1),
62+
(0, 0, 1),
63+
(-1, 0, 1),
64+
fill: rgb(255, 165, 0),
65+
)
66+
})
67+
68+
// Draw grid lines
69+
for x in range(-1, 2) {
70+
let style = if x == 0 { arrow-style } else { () }
71+
draw.line((x, -1, 0), (x, 1, 0), stroke: gray + .3pt, ..style)
72+
}
73+
for y in range(-1, 2) {
74+
let style = if y == 0 { arrow-style } else { () }
75+
draw.line((-1, y, 0), (1, y, 0), stroke: gray + .3pt, ..style)
76+
}
77+
78+
content((1.45, .1, 0), [$"Re"(p_0)$])
79+
content((0, 1.6, 0), [$"Im"(p_0)$])
80+
content((0, 0, 1.5), [$s(p_0)$])
81+
})

assets/heatmap/heatmap.typ

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
#canvas({
77
let cell-size = .7 // Size of each heatmap cell
8-
let data = (
8+
let cell-data = (
99
(74, 25, 39, 20, 3, 3, 3, 3, 3),
1010
(25, 53, 31, 17, 7, 7, 2, 3, 2),
1111
(39, 31, 37, 24, 3, 3, 3, 3, 3),
@@ -16,7 +16,7 @@
1616
(3, 3, 3, 5, 0, 0, 1, 23, 1),
1717
(3, 2, 3, 5, 0, 0, 1, 1, 78),
1818
)
19-
let row-labels = ("a", "b", "c", "d", "e", "f", "g", "h", "i")
19+
let row-labels = "abcdefghi".split("").slice(1)
2020

2121
// Draw column labels (1-9)
2222
for col in range(9) {
@@ -39,7 +39,7 @@
3939
// Draw heatmap cells
4040
for row in range(9) {
4141
for col in range(9) {
42-
let value = data.at(row).at(col)
42+
let value = cell-data.at(row).at(col)
4343
rect(
4444
((col + 1) * cell-size - cell-size / 2, -(row + 1) * cell-size - cell-size / 2),
4545
((col + 1) * cell-size + cell-size / 2, -(row + 1) * cell-size + cell-size / 2),

assets/roc-curve/roc-curve-hd.png

60.6 KB
Loading

assets/roc-curve/roc-curve.pdf

14.8 KB
Binary file not shown.

assets/roc-curve/roc-curve.png

26.4 KB
Loading

assets/roc-curve/roc-curve.svg

+602
Loading

assets/roc-curve/roc-curve.typ

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#import "@preview/cetz:0.3.4": canvas, draw
2+
#import "@preview/cetz-plot:0.1.1": plot
3+
4+
#set page(width: auto, height: auto, margin: 8pt)
5+
6+
// ROC curve functions for different classifiers
7+
#let perfect_classifier(x) = {
8+
if x == 0 { return 0 }
9+
if x == 1 { return 1 }
10+
if x > 0 { return 0.99 }
11+
return 0
12+
}
13+
14+
#let excellent_classifier(x) = {
15+
if x <= 0 { return 0 }
16+
if x >= 1 { return 1 }
17+
return calc.pow(x, 0.15)
18+
}
19+
20+
#let good_classifier(x) = {
21+
if x <= 0 { return 0 }
22+
if x >= 1 { return 1 }
23+
return calc.pow(x, 0.3)
24+
}
25+
26+
#let fair_classifier(x) = {
27+
if x <= 0 { return 0 }
28+
if x >= 1 { return 1 }
29+
return calc.pow(x, 0.6)
30+
}
31+
32+
#let poor_classifier(x) = {
33+
if x <= 0 { return 0 }
34+
if x >= 1 { return 1 }
35+
return 0.2 * x + 0.8 * x * x
36+
}
37+
38+
#let random_classifier(x) = x
39+
40+
#canvas({
41+
let mark = (end: "stealth", fill: black, scale: 0.7)
42+
draw.set-style(
43+
axes: (
44+
y: (label: (anchor: "south-east", offset: 1.2, angle: 90deg), mark: mark),
45+
x: (label: (anchor: "south-east", offset: 1.2), mark: mark),
46+
),
47+
)
48+
49+
plot.plot(
50+
size: (8, 8),
51+
x-label: "False Positive Rate (1-Specificity)",
52+
y-label: "True Positive Rate (Sensitivity)",
53+
x-min: 0,
54+
x-max: 1,
55+
y-min: 0,
56+
y-max: 1,
57+
x-tick-step: 0.25,
58+
y-tick-step: 0.25,
59+
x-grid: true,
60+
y-grid: true,
61+
axis-style: "left",
62+
legend: "inner-north",
63+
legend-style: (item: (spacing: 0.15), padding: 0.15, stroke: none, offset: (7.8, 0.3)),
64+
{
65+
plot.add(
66+
style: (stroke: gray),
67+
domain: (0, 1),
68+
samples: 2,
69+
random_classifier,
70+
label: "Random Guess (AUC = 0.5)",
71+
)
72+
73+
plot.add(
74+
style: (stroke: green),
75+
domain: (0, 1),
76+
samples: 50,
77+
perfect_classifier,
78+
label: "Near-Perfect Classifier (AUC = 0.99)",
79+
)
80+
81+
plot.add(
82+
style: (stroke: blue),
83+
domain: (0, 1),
84+
samples: 100,
85+
excellent_classifier,
86+
label: "Excellent Classifier (AUC = 0.93)",
87+
)
88+
89+
plot.add(
90+
style: (stroke: purple),
91+
domain: (0, 1),
92+
samples: 100,
93+
good_classifier,
94+
label: "Good Classifier (AUC = 0.85)",
95+
)
96+
97+
plot.add(
98+
style: (stroke: orange),
99+
domain: (0, 1),
100+
samples: 100,
101+
fair_classifier,
102+
label: "Fair Classifier (AUC = 0.73)",
103+
)
104+
105+
plot.add(
106+
style: (stroke: red),
107+
domain: (0, 1),
108+
samples: 100,
109+
poor_classifier,
110+
label: "Poor Classifier (AUC = 0.65)",
111+
)
112+
},
113+
)
114+
})

assets/roc-curve/roc-curve.yml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
title: ROC Curve
2+
tags:
3+
- statistics
4+
- classification
5+
- machine learning
6+
- performance metrics
7+
- data science
8+
- model evaluation
9+
description: |
10+
The Receiver Operating Characteristic (ROC) curve is a widely used evaluation tool in statistics that plots the True Positive Rate (Sensitivity) against the False Positive Rate (1-Specificity) at various classification thresholds.
11+
12+
This visualization compares classifiers of different performance levels, from near-perfect (AUC = 0.99) to poor (AUC = 0.65), with a random classifier (AUC = 0.5) as baseline. The Area Under the Curve (AUC) serves as a threshold-independent measure of classifier performance, with values closer to 1.0 indicating better discrimination ability.
13+
14+
ROC curves are particularly valuable in domains requiring careful trade-off between sensitivity and specificity, such as medical diagnostics (balancing false negatives vs. false positives), fraud detection (minimizing false alerts while catching true fraud), and information retrieval (evaluating ranking algorithms). They provide insights into model behavior across all possible decision thresholds, allowing practitioners to select operating points that best align with application requirements and costs of different types of errors.

0 commit comments

Comments
 (0)