BRAGA

02 Writing02-02 Notes02-02-034

Infinite cardinality

Published 16 Apr 202611 min read
Contents
  1. 01Deep Breakdown
  2. 02Flowchart
  3. 03Real-world use
  4. 04The formula, piece by piece
  5. 05The formula in words
  6. 06Critical Concepts
  7. 07Step-by-step calculation (tiny example)
  8. 08Code examples
ℵ\aleph
(1)

Deep Breakdown

What it tells me (Situation Awareness): ℵ\aleph (aleph, the first letter of the Hebrew alphabet) is the symbol for transfinite cardinal numbers — the "sizes" of infinite sets. The most important values are ℵ0\aleph_0 (aleph-null or aleph-nought) and c\mathfrak{c} (the cardinality of the continuum). ℵ0=∣N∣\aleph_0 = |\mathbb{N}| is the cardinality of the natural numbers — the "smallest" infinity, the size of any countably infinite set. c=∣R∣\mathfrak{c} = |\mathbb{R}| is larger — uncountably infinite. Georg Cantor proved in 1874 that ∣R∣>∣N∣|\mathbb{R}| > |\mathbb{N}| (you cannot pair up real numbers with natural numbers without leftovers). In DA/DS, infinite cardinality is directly relevant when reasoning about continuous vs. discrete feature spaces, the difference between integer indices (countable) and floating-point feature values (uncountable approximation of ℝ), and the limits of enumeration-based approaches. Understanding that ∣R∣≫∣N∣|\mathbb{R}| \gg |\mathbb{N}| explains why you cannot enumerate all possible floating-point feature combinations — the search space is uncountably large.

Flowchart

Cardinality ='size' of a setFinite: |{1,2,3}| =3Infinite: |ℕ| = ℵ₀(countablyinfinite)Countable: ℕ, ℤ,ℚ all havecardinality ℵ₀Uncountable: ℝhas cardinality 𝔠ℵ₀Cantor'sdiagonal: ℝcannot be listed— uncountableDA: discretefeatures(categories) =countabledomainDA: continuousfeatures(float64) ≈uncountabledomainPractical:|dataset| finite,but featurespace may behuge

Real-world use

Where it is used

Understanding why some problems are computationally intractable: if a feature takes values in R\mathbb{R}, its domain is uncountably infinite — you cannot enumerate all possible values. Why K-nearest neighbors degrades in high dimensions (the volume of high-dimensional space is "too large"). Why categorical features with high cardinality (many unique values) cause memory and sparsity problems in one-hot encoding. Why exact lookup tables for continuous features are impossible (you'd need ∣R∣|\mathbb{R}| entries). The concept of cardinality also directly informs database indexing strategies — low-cardinality columns are bad candidates for B-tree indexes.

Problem it solves

Without a concept of different "sizes" of infinity, it would be unclear why some infinite sets are fundamentally harder to deal with than others. The distinction between countable (ℵ0\aleph_0) and uncountable (c\mathfrak{c}) explains the structural difference between discrete and continuous problems. It also grounds the concept of "high cardinality" columns in databases: a column with 10610^6 unique values is "large but finite"; a continuous float column is "effectively uncountable" for enumeration purposes.

How it solves the problem

Cantor's key insight: two sets have the same cardinality if and only if there exists a bijection (one-to-one correspondence) between them. ∣N∣=∣Z∣=∣Q∣=ℵ0|\mathbb{N}| = |\mathbb{Z}| = |\mathbb{Q}| = \aleph_0 because you can construct a bijection between each. ∣R∣>ℵ0|\mathbb{R}| > \aleph_0 because no bijection from N\mathbb{N} to R\mathbb{R} can exist (Cantor's diagonal argument). For DA/DS, this justifies binning, discretization, and cardinality reduction as engineering choices for continuous variables.

Example in a business

Feature engineering for a recommendation model: user IDs (1 to 10M) have finite but high cardinality — manageable with embeddings. Product price (a float64 column) has "effectively uncountable" cardinality — you must bin it into ranges. Order date has finite cardinality but high dimensionality if one-hot encoded — extract features like day-of-week, month, quarter instead. Each choice is grounded in the cardinality of the domain.

The formula, piece by piece

Breaking the notation:

  • ℵ\aleph: the Hebrew letter "aleph." Used by Georg Cantor (1874) to denote transfinite cardinals.
  • ℵ0\aleph_0: "aleph-null" or "aleph-nought" — the cardinality of the natural numbers N\mathbb{N}. The smallest infinite cardinal.
  • ℵ1\aleph_1: the next infinite cardinal after ℵ0\aleph_0 in the well-ordering of cardinals.
  • c=2ℵ0\mathfrak{c} = 2^{\aleph_0}: the cardinality of the continuum (∣R∣|\mathbb{R}|). The continuum hypothesis says c=ℵ1\mathfrak{c} = \aleph_1, but this is independent of ZFC set theory.

Key facts:

  • ∣N∣=∣Z∣=∣Q∣=ℵ0|\mathbb{N}| = |\mathbb{Z}| = |\mathbb{Q}| = \aleph_0 (all countably infinite).
  • ∣R∣=∣Rn∣=c>ℵ0|\mathbb{R}| = |\mathbb{R}^n| = \mathfrak{c} > \aleph_0 (uncountably infinite).
  • ∣P(N)∣=2ℵ0=c|\mathcal{P}(\mathbb{N})| = 2^{\aleph_0} = \mathfrak{c} (power set of a countable set is uncountable).
  • A set is countable if its cardinality is ≤ℵ0\leq \aleph_0 (finite or countably infinite).
  • A set is uncountable if its cardinality is >ℵ0> \aleph_0.

Practical equivalents:

  • ℵ0\aleph_0 sets: integers, rationals, strings over a finite alphabet, Python range(n) as n→∞n \to \infty.
  • c\mathfrak{c} sets: reals, floats (in theory), continuous functions, probability distributions.

The formula in words

"ℵ0\aleph_0 is the size of the list 1,2,3,4,…1, 2, 3, 4, \ldots — you can count it forever but never finish. c\mathfrak{c} (the size of R\mathbb{R}) is so much bigger that even if you tried to list every real number, Cantor proved you'd always miss some. In practice: integer-valued columns are countable (you can index them); float-valued columns are not enumerable — you need binning or embeddings."

Critical Concepts

  1. Countable vs. uncountable in feature engineering: a categorical column with kk distinct values has cardinality kk (finite). An integer ID column has cardinality ≤ℵ0\leq \aleph_0. A continuous float column has cardinality c\mathfrak{c}. One-hot encoding is only feasible for finite, low-cardinality sets.
  2. Cardinality in databases: the term "cardinality" in SQL and database indexing refers to the number of distinct values in a column — a finite version of the mathematical concept. High-cardinality columns (many unique values) are good for B-tree indexes; low-cardinality columns (few unique values) are better served by bitmap indexes.
  3. Why float64 is finite but "acts" uncountable: IEEE 754 float64 has exactly 2642^{64} possible values — finite but astronomically large. For practical purposes, treating a float column as having countably infinite or uncountable domain is correct: you cannot enumerate all distinct float64 values in a feature.
  4. Bijection and equal cardinality: ∣N∣=∣Z∣|\mathbb{N}| = |\mathbb{Z}| seems paradoxical (integers include negatives!), but a bijection exists: f(n)=n/2f(n) = n/2 for even nn, f(n)=−(n+1)/2f(n) = -(n+1)/2 for odd nn enumerates all integers. This is why "infinity" requires careful treatment — naive size comparison fails.
  5. Practical ℵ₀ in DA: any time you have a theoretically unbounded stream of discrete events (user clicks, log lines, transactions), the eventual size is ℵ0\aleph_0.

But at any given moment, you hold a finite sample. The distinction matters for streaming vs. batch architectures.

Step-by-step calculation (tiny example)

Task: classify columns in a dataset by their cardinality type and choose the right encoding strategy.

Step 1: Identify cardinality type for each column

  • country_code: 195 distinct values → finite, low cardinality → one-hot encoding feasible.
  • user_id: up to 10810^8 distinct values → finite but very high cardinality → embedding or hashing.
  • price_eur: float64, continuous → effectively c\mathfrak{c} → must bin: low (<50), medium (50–200), high (>200).
  • event_timestamp: datetime with microsecond precision → very high but finite → extract features (hour, day, month).

Step 2: Apply cardinality-aware encoding

  • Finite low-cardinality (k≤∼50k \leq \sim 50): one-hot encoding → adds kk binary columns.
  • Finite high-cardinality (k>50k > 50): target encoding, embedding, or hashing.
  • Continuous (effectively uncountable): binning → convert to ordinal or one-hot on bins.

Step 3: Estimate memory One-hot of user_id with 10810^8 values: 10810^8 columns × 10610^6 rows = 101410^{14} cells. At 1 bit each: 101310^{13} bytes = 10 TB. Infeasible. Embedding dimension 32: 108×32=3.2×10910^8 \times 32 = 3.2 \times 10^9 floats ≈ 12.8 GB — feasible.

Code examples

Beginner example (Python)

python
# Infinite cardinality concepts applied to DA
# Practical cardinality: count distinct values
import pandas as pd
import numpy as np
np.random.seed(42)
N = 10_000
df = pd.DataFrame({ "country_code": np.random.choice(["AT", "DE", "US", "GB", "CH"], N), "user_id": np.random.randint(1, 100_001, N), "price_eur": np.random.uniform(0.5, 999.99, N), "event_hour": np.random.randint(0, 24, N),
})
print("Column Cardinality Report")
print("=" * 55)
for col in df.columns:
    n_unique = df[col].nunique()
    col_type = df[col].dtype
    if col_type in ["float64", "float32"]:
        card_class = "continuous (~𝔠)"
        strategy = "binning / normalization"
    elif n_unique <= 50:
        card_class = f"finite low ({n_unique})"
        strategy = "one-hot encoding"
    elif n_unique <= 10_000:
        card_class = f"finite medium ({n_unique})"
        strategy = "target / ordinal encoding"
    else:
        card_class = f"finite high ({n_unique})"
    strategy = "embedding / hashing[["
print(f"]] {col:<16}: {card_class:<25} → {strategy}")
print()   # Demonstrate why one-hot fails for high cardinality
user_ids = df["user_id"].unique()
one_hot_memory_gb = len(df) * len(user_ids) * 1 / (8 * 1e9)   # 1-bit cells
embedding_memory_gb = len(user_ids) * 32 * 4 / 1e9   # 32-dim float32 print(f"User ID one-hot memory estimate: {one_hot_memory_gb:.2f} GB ← infeasible")
print(f"User ID embedding (dim=32): {embedding_memory_gb:.4f} GB ← feasible")   # Countable vs uncountable in Python
integers = range(10**9)   # countable — enumerable in principle
floats = np.linspace(0, 1, 10**6)   # finite sample from an uncountable domain (10**9 floats would take 8 GB)
print(f"\nInteger range (countable): type={type(integers)}, len representable")
print(f"Float sample (from ℝ ≈ 𝔠): {len(floats)} samples, but domain is uncountable")
print(f"Distinct floats in sample: {len(set(floats[:100]))}")   # each unique

Beginner example (R)

r
# Cardinality analysis in R
library(dplyr)
set.seed(42)
N <- 10000
df <- data.frame( country_code = sample(c("AT", "DE", "US", "GB", "CH"), N, replace = TRUE), user_id = sample(1:100000, N, replace = TRUE), price_eur = runif(N, 0.5, 999.99), event_hour = sample(0:23, N, replace = TRUE), stringsAsFactors = FALSE
)  # Cardinality of each column
cardinality <- df %>% summarise(across(everything(), n_distinct)) %>% tidyr::pivot_longer(everything(), names_to = "column", values_to = "n_unique")
cat("Column Cardinality (distinct values per column):\n")
print(cardinality)  # Classify by cardinality type
classify_cardinality <- function(col_name, n_unique, col_class) { if (col_class %in% c("numeric", "double") && n_unique > 1000) { return(paste0("continuous (~𝔠) → bin it"))
  }
  else
  if (n_unique <= 50) { return(paste0("low (", n_unique, ") → one-hot"))
  }
  else { return(paste0("high (", n_unique, ") → embed/hash"))
  }
}
cat("\nEncoding recommendations:\n")
for (col in names(df)) { nu <- n_distinct(dfcol)
  cls <- class(dfcol)
  strat <- classify_cardinality(col, nu, cls)
  cat(sprintf(" %-16s: %s\n", col, strat))
}

Professional example (Python)

python
import pandas as pd
import numpy as np
from typing import Literal   # Scenario: automated cardinality audit with encoding recommendations
# Classify each column by mathematical cardinality type
# and generate an encoding strategy report for a modeling pipeline
np.random.seed(42)
N = 50_000   # Simulate a realistic e-commerce dataset
df = pd.DataFrame({ "user_id": np.random.randint(1, 500_001, N),   # high cardinality
    "session_id": np.random.randint(1, N + 1, N),   # near-unique
    "country_code": np.random.choice(["AT", "DE", "US", "GB", "CH", "FR", "ES"], N),   # low cardinality
    "product_cat": np.random.choice(["Electronics", "Apparel", "Home", "Sports"], N),   # low cardinality
    "price_eur": np.random.exponential(80, N).round(2),   # continuous
    "revenue": np.random.uniform(5, 2000, N).round(2),   # continuous
    "page_views": np.random.poisson(5, N),   # integer counts
    "hour_of_day": np.random.randint(0, 24, N),   # bounded integer
})
CardinalityType = Literal["low", "medium", "high", "continuous"]

def classify_column( series: pd.Series, low_threshold: int = 30, medium_threshold: int = 5_000,
) -> dict:
    """ Classify a column by cardinality type and recommend encoding strategy. Args: series: Column to classify. low_threshold: Max distinct values for "low" cardinality. medium_threshold: Max distinct values for "medium" cardinality. Returns: Dict with cardinality class, count, and encoding recommendation. """
    n_unique = series.nunique()
    is_float = series.dtype in [np.float64, np.float32]
    if is_float and n_unique > medium_threshold:
        card_type = "continuous (~𝔠)"
        strategy = "bin (quantile/fixed) or normalize (z-score / min-max)"
    elif n_unique <= low_threshold:
        card_type = f"low ({n_unique})"
        strategy = "one-hot encoding"
    elif n_unique <= medium_threshold:
        card_type = f"medium ({n_unique})"
        strategy = "ordinal or target encoding"
    else:
        card_type = f"high ({n_unique:,})"
    strategy = "embedding (dim ≈ n_unique^0.25) or feature hashing"
    return { "column": series.name, "dtype": str(series.dtype), "n_unique": n_unique, "cardinality": card_type, "strategy": strategy, }
report = pd.DataFrame([classify_column(df[col]) for col in df.columns])
print("Cardinality Audit and Encoding Strategy Report")
print("=" * 80)
print(report.to_string(index=False))
print("\nMemory estimates for user_id encoding:")
n_users = df["user_id"].nunique()
n_rows = len(df)
one_hot_gb = n_rows * n_users * 1 / (8 * 1e9)
embed_dim = int(n_users ** 0.25)
embed_gb = n_users * embed_dim * 4 / 1e9
print(f" Distinct user IDs: {n_users:,}")
print(f" One-hot (1-bit cells): {one_hot_gb:,.1f} GB ← cardinality ℵ₀ problem")
print(f" Embedding (dim={embed_dim}): {embed_gb:.4f} GB ← tractable")

Professional example (R)

r
# Cardinality audit: high-cardinality columns and encoding strategy
set.seed(42)
df <- data.frame( user_id = sample(1:100000, 50000, replace = TRUE), category = sample(letters[1:5], 50000, replace = TRUE)
)
classify_column <- function(col) { n_unique <- length(unique(col))
  n_rows <- length(col)
  rec <- if (n_unique == n_rows) "IDENTIFIER"
  else
  if (n_unique <= 10) "ONE-HOT"
  else
  if (n_unique <= 200) "TARGET ENCODE"
  else "HASH or EMBED" data.frame(column = deparse(substitute(col)), cardinality = n_unique, n_rows = n_rows, recommendation = rec)
}
report <- do.call(rbind, lapply(names(df), function(nm) { r <- classify_column(dfnm) r$column <- nm r
}))
cat("Cardinality Audit and Encoding Strategy\n")
print(report)
n_users <- length(unique(df$user_id))
cat("\nMemory: one-hot vs embedding for user_id (high cardinality)\n")
cat(" Distinct user IDs:", n_users, "\n")

Source: AIO p. 30 of 286

#foundations#maths-symbols#set-theory

Keyboard shortcuts

Single keys, ignored while typing in a field or with Cmd, Ctrl or Alt held.

0
Home
1 2 3 4
Work, Writing, Tools, About
j / k
Next / previous section on this page
n / p
Next / previous project or essay
u
Up one level
l
Deutsch
t
Light or dark theme
?
This list
Esc
Close