1+ {
2+ "cells" : [
3+ {
4+ "cell_type" : " markdown" ,
5+ "metadata" : {},
6+ "source" : [
7+ " # Basic Example: Fairlex Calibration\n " ,
8+ " \n " ,
9+ " This example illustrates how to construct a membership matrix and target\n " ,
10+ " totals, call the weight-fair leximin calibration, and inspect the resulting\n " ,
11+ " weights and diagnostics."
12+ ]
13+ },
14+ {
15+ "cell_type" : " code" ,
16+ "execution_count" : null ,
17+ "metadata" : {},
18+ "outputs" : [],
19+ "source" : [
20+ " import numpy as np\n " ,
21+ " from fairlex import evaluate_solution, leximin_weight_fair"
22+ ]
23+ },
24+ {
25+ "cell_type" : " markdown" ,
26+ "metadata" : {},
27+ "source" : [
28+ " ## Setting up the problem\n " ,
29+ " \n " ,
30+ " Suppose we survey five people and want to calibrate on sex and age.\n " ,
31+ " Each margin is represented by two rows: the indicator for the\n " ,
32+ " first category and the second category. We also include a total row."
33+ ]
34+ },
35+ {
36+ "cell_type" : " code" ,
37+ "execution_count" : null ,
38+ "metadata" : {},
39+ "outputs" : [],
40+ "source" : [
41+ " # Define the membership matrix A\n " ,
42+ " A = np.array(\n " ,
43+ " [\n " ,
44+ " # sex: female\n " ,
45+ " [1, 0, 1, 0, 1],\n " ,
46+ " # sex: male\n " ,
47+ " [0, 1, 0, 1, 0],\n " ,
48+ " # age: young (<=40)\n " ,
49+ " [1, 1, 0, 0, 1],\n " ,
50+ " # age: old (>40)\n " ,
51+ " [0, 0, 1, 1, 0],\n " ,
52+ " # total\n " ,
53+ " [1, 1, 1, 1, 1],\n " ,
54+ " ],\n " ,
55+ " dtype=float,\n " ,
56+ " )\n " ,
57+ " \n " ,
58+ " print(\" Membership matrix A:\" )\n " ,
59+ " print(A)"
60+ ]
61+ },
62+ {
63+ "cell_type" : " code" ,
64+ "execution_count" : null ,
65+ "metadata" : {},
66+ "outputs" : [],
67+ "source" : [
68+ " # Base weights (e.g. equal weights in a simple random sample)\n " ,
69+ " w0 = np.ones(5)\n " ,
70+ " print(\" Base weights:\" , w0)\n " ,
71+ " \n " ,
72+ " # Target totals for the population (feasible with max weight 2.0 per person)\n " ,
73+ " # Note: with 5 people and max weight 2.0, total achievable is 10\n " ,
74+ " target = np.array([6, 4, 6, 4, 10], dtype=float)\n " ,
75+ " print(\" Target totals:\" , target)"
76+ ]
77+ },
78+ {
79+ "cell_type" : " markdown" ,
80+ "metadata" : {},
81+ "source" : [
82+ " ## Performing calibration\n " ,
83+ " \n " ,
84+ " We use the weight-fair leximin calibration with modest weight bounds."
85+ ]
86+ },
87+ {
88+ "cell_type" : " code" ,
89+ "execution_count" : null ,
90+ "metadata" : {},
91+ "outputs" : [],
92+ "source" : [
93+ " # Perform calibration with modest bounds\n " ,
94+ " result = leximin_weight_fair(A, target, w0, min_ratio=0.5, max_ratio=2.0)\n " ,
95+ " print(\" Calibrated weights:\" , result.w)\n " ,
96+ " print(\" Optimization status:\" , result.status)\n " ,
97+ " print(\" Solver message:\" , result.message)"
98+ ]
99+ },
100+ {
101+ "cell_type" : " markdown" ,
102+ "metadata" : {},
103+ "source" : [
104+ " ## Evaluating the solution\n " ,
105+ " \n " ,
106+ " Let's examine the quality of our calibrated weights using various diagnostics."
107+ ]
108+ },
109+ {
110+ "cell_type" : " code" ,
111+ "execution_count" : null ,
112+ "metadata" : {},
113+ "outputs" : [],
114+ "source" : [
115+ " # Evaluate solution quality\n " ,
116+ " metrics = evaluate_solution(A, target, result.w, base_weights=w0)\n " ,
117+ " \n " ,
118+ " print(\" Solution Diagnostics:\" )\n " ,
119+ " print(\" ====================\" )\n " ,
120+ " for key, value in metrics.items():\n " ,
121+ " print(f\" {key}: {value:.4f}\" )"
122+ ]
123+ },
124+ {
125+ "cell_type" : " markdown" ,
126+ "metadata" : {},
127+ "source" : [
128+ " ## Understanding the results\n " ,
129+ " \n " ,
130+ " The diagnostics show us:\n " ,
131+ " - **Residual metrics**: How well we achieved our target totals\n " ,
132+ " - **Weight distribution**: Statistical properties of the final weights\n " ,
133+ " - **Relative deviations**: How much the weights changed from their base values\n " ,
134+ " - **ESS (Effective Sample Size)**: Measure of variance inflation\n " ,
135+ " - **Design Effect**: Ratio of actual to nominal sample size"
136+ ]
137+ }
138+ ],
139+ "metadata" : {
140+ "kernelspec" : {
141+ "display_name" : " Python 3" ,
142+ "language" : " python" ,
143+ "name" : " python3"
144+ },
145+ "language_info" : {
146+ "codemirror_mode" : {
147+ "name" : " ipython" ,
148+ "version" : 3
149+ },
150+ "file_extension" : " .py" ,
151+ "mimetype" : " text/x-python" ,
152+ "name" : " python" ,
153+ "nbconvert_exporter" : " python" ,
154+ "pygments_lexer" : " ipython3" ,
155+ "version" : " 3.12.0"
156+ }
157+ },
158+ "nbformat" : 4 ,
159+ "nbformat_minor" : 4
160+ }
0 commit comments