44app = marimo .App (width = "medium" )
55
66with app .setup (hide_code = True ):
7+ import marimo as mo
8+
9+
10+ @app .cell (hide_code = True )
11+ async def _ ():
12+ import sys
13+
14+ # Seaborn isn't installed by default in Pyodide, so we install it here (only if the notebook runs on WebAssembly):
15+ if "pyodide" in sys .modules :
16+ import micropip
17+ await micropip .install ("seaborn" )
18+ import seaborn as sns
19+ else :
20+ import seaborn as sns
21+ return (sns ,)
22+
23+
24+ @app .cell (hide_code = True )
25+ def _ ():
726 import base64
827 from pathlib import Path
928 from io import BytesIO
1029 import time
1130 from pickle import dump
1231
13- import marimo as mo
14-
1532 import numpy as np
1633 import pandas as pd
1734 from PIL import Image
1835
1936 import matplotlib .pyplot as plt
2037 from matplotlib .colors import ListedColormap
2138
22- import seaborn as sns
2339 import altair as alt
2440
2541 from skimage .io import imread
2844
2945 from sklearn .metrics import confusion_matrix , ConfusionMatrixDisplay
3046
47+ return (
48+ BytesIO ,
49+ ConfusionMatrixDisplay ,
50+ Image ,
51+ ListedColormap ,
52+ Path ,
53+ alt ,
54+ base64 ,
55+ confusion_matrix ,
56+ dump ,
57+ imread ,
58+ np ,
59+ pd ,
60+ plt ,
61+ rescale_intensity ,
62+ )
63+
3164
3265@app .cell (hide_code = True )
3366def _ ():
@@ -119,7 +152,7 @@ def _():
119152
120153@app .cell
121154def _ ():
122- dataset_path = mo .notebook_location () / "./ dataset"
155+ dataset_path = mo .notebook_location () / "public" / " dataset"
123156
124157 path_exists = "✅ yes" if dataset_path .exists () else "❌ no"
125158
@@ -149,7 +182,7 @@ def _():
149182
150183
151184@app .cell
152- def _ (dataset_path , img2url , load_dataset_btn ):
185+ def _ (Path , dataset_path , img2url , imread , load_dataset_btn , pd ):
153186 mo .stop (not load_dataset_btn .value , mo .md ("Click the button to load the dataset." ))
154187
155188 def read_image (image_path ) -> str :
@@ -189,7 +222,7 @@ def _():
189222
190223
191224@app .cell
192- def _ (df ):
225+ def _ (df , imread , np ):
193226 images = np .array ([imread (f ) for f in df ['image_path' ]])
194227
195228 mo .md (f"✅ Read all the images into a Numpy array of shape **{ images .shape } ** corresponding to (N, X, Y)." )
@@ -213,7 +246,7 @@ def _(class_labels):
213246
214247
215248@app .cell
216- def _ (class_dropdown , df , images ):
249+ def _ (class_dropdown , df , images , np , plt ):
217250 def show_images_selection (images_selection , ncols = 7 ):
218251 nrows = int (np .ceil (len (images_selection ) / ncols ))
219252 fig , axes = plt .subplots (nrows = nrows , ncols = ncols , figsize = (12 , 6 ))
@@ -251,7 +284,7 @@ def _():
251284
252285
253286@app .cell
254- def _ (df , measurements_btn , url2img ):
287+ def _ (df , measurements_btn , np , url2img ):
255288 mo .stop (not measurements_btn .value , mo .md ("Click the button to compute the measurements." ))
256289
257290 def compute_mean_intensity (base64_image : str ):
@@ -337,15 +370,15 @@ def _():
337370
338371
339372@app .cell
340- def _ (images ):
373+ def _ (images , np , rescale_intensity ):
341374 images_normed = np .array ([rescale_intensity (img , out_range = (0 , 1 )) for img in images ])
342375
343376 mo .md (f"➡️ Shape of images (normalized): **{ images_normed .shape } **" )
344377 return (images_normed ,)
345378
346379
347380@app .cell
348- def _ (images , images_normed ):
381+ def _ (images , images_normed , np , plot_image_before_after_normalization ):
349382 random_idx = np .random .randint (len (images ))
350383
351384 img_before = images [random_idx ]
@@ -364,7 +397,7 @@ def _():
364397
365398
366399@app .cell
367- def _ (images_normed ):
400+ def _ (images_normed , np ):
368401 pixel_features = np .reshape (images_normed , (len (images_normed ), - 1 ))
369402
370403 mo .md (f"➡️ Shape of pixel value features: **{ pixel_features .shape } **" )
@@ -388,7 +421,7 @@ def _():
388421
389422
390423@app .cell
391- def _ (df , pixel_features , valid_fract_slider ):
424+ def _ (df , pd , pixel_features , valid_fract_slider ):
392425 from sklearn .model_selection import train_test_split
393426
394427 X = pixel_features
@@ -527,39 +560,42 @@ def _():
527560 return
528561
529562
530- @app .function
531- def fit_and_evaluate_classifier (model , x_train , y_train , x_val , y_val ):
532- """Fit a Scikit-Learn classifier on the training set and report evaluation metrics on the validation set."""
533- # Fit on the training set
534- model .fit (X = x_train , y = y_train )
563+ @app .cell
564+ def _ (ConfusionMatrixDisplay , confusion_matrix ):
565+ def fit_and_evaluate_classifier (model , x_train , y_train , x_val , y_val ):
566+ """Fit a Scikit-Learn classifier on the training set and report evaluation metrics on the validation set."""
567+ # Fit on the training set
568+ model .fit (X = x_train , y = y_train )
569+
570+ # Score on the training set
571+ acc_train = model .score (X = x_train , y = y_train )
535572
536- # Score on the training set
537- acc_train = model .score (X = x_train , y = y_train )
573+ # Score on the validation set
574+ acc_val = model .score (X = x_val , y = y_val )
538575
539- # Score on the validation set
540- acc_val = model .score ( X = x_val , y = y_val )
576+ # Predict on the training set
577+ y_pred_train = model .predict ( x_train )
541578
542- # Predict on the training set
543- y_pred_train = model .predict (x_train )
579+ # Predict on the validation set
580+ y_pred_val = model .predict (x_val )
544581
545- # Predict on the validation set
546- y_pred_val = model .predict (x_val )
582+ # Confusion matrices
583+ cm_train = confusion_matrix (y_train , y_pred_train , labels = model .classes_ )
584+ disp_train = ConfusionMatrixDisplay (confusion_matrix = cm_train , display_labels = model .classes_ )
547585
548- # Confusion matrices
549- cm_train = confusion_matrix (y_train , y_pred_train , labels = model .classes_ )
550- disp_train = ConfusionMatrixDisplay (confusion_matrix = cm_train , display_labels = model .classes_ )
586+ cm_val = confusion_matrix (y_val , y_pred_val , labels = model .classes_ )
587+ disp_val = ConfusionMatrixDisplay (confusion_matrix = cm_val , display_labels = model .classes_ )
551588
552- cm_val = confusion_matrix (y_val , y_pred_val , labels = model .classes_ )
553- disp_val = ConfusionMatrixDisplay (confusion_matrix = cm_val , display_labels = model .classes_ )
589+ return {
590+ "accuracy_training" : acc_train ,
591+ "accuracy_validation" : acc_val ,
592+ "confusion_matrix_training" : disp_train ,
593+ "confusion_matrix_validation" : disp_val ,
594+ "n_train" : len (x_train ),
595+ "n_validation" : len (x_val ),
596+ }
554597
555- return {
556- "accuracy_training" : acc_train ,
557- "accuracy_validation" : acc_val ,
558- "confusion_matrix_training" : disp_train ,
559- "confusion_matrix_validation" : disp_val ,
560- "n_train" : len (x_train ),
561- "n_validation" : len (x_val ),
562- }
598+ return (fit_and_evaluate_classifier ,)
563599
564600
565601@app .cell (hide_code = True )
@@ -582,6 +618,7 @@ def _():
582618
583619@app .cell
584620def _ (
621+ fit_and_evaluate_classifier ,
585622 fit_baseline_btn ,
586623 print_classification_results ,
587624 x_train_projected ,
@@ -629,6 +666,7 @@ def _():
629666
630667@app .cell
631668def _ (
669+ fit_and_evaluate_classifier ,
632670 fit_linear_model_btn ,
633671 print_classification_results ,
634672 x_train_projected ,
@@ -725,6 +763,7 @@ def _():
725763
726764@app .cell
727765def _ (
766+ fit_and_evaluate_classifier ,
728767 fit_decision_tree_btn ,
729768 max_depth_selector ,
730769 print_classification_results ,
@@ -865,6 +904,7 @@ def _():
865904def _ (
866905 LogisticRegression ,
867906 PCA ,
907+ fit_and_evaluate_classifier ,
868908 n_components_slider ,
869909 print_classification_results ,
870910 x_train ,
@@ -993,7 +1033,7 @@ def _():
9931033
9941034
9951035@app .cell
996- def _ (pipe , save_btn ):
1036+ def _ (Path , dump , pipe , save_btn ):
9971037 mo .stop (not save_btn .value , mo .md ("Click the button to save the pipeline." ))
9981038
9991039 pipeline_file = Path ("./pipeline.pkl" )
@@ -1054,7 +1094,7 @@ def _():
10541094
10551095
10561096@app .cell
1057- def _ ():
1097+ def _ (BytesIO , Image , alt , base64 , np ):
10581098 def url2img (base64_image : str ) -> np .ndarray :
10591099 header , encoded = base64_image .split ("," , 1 )
10601100 img = Image .open (BytesIO (base64 .b64decode (encoded )))
@@ -1116,23 +1156,26 @@ def create_altair_chart(df, x_col, y_col, show_images, size=700):
11161156 return create_altair_chart , img2url , url2img
11171157
11181158
1119- @app .function
1120- def predict_on_regular_grid (model , extent , nx = 200 , ny = 200 ):
1121- """Run a classifier on a regular grid in a given domain."""
1122- xx , yy = np .meshgrid (
1123- np .linspace (extent [0 ], extent [1 ], nx ),
1124- np .linspace (extent [2 ], extent [3 ], ny ),
1125- )
1126- grid_yx = np .c_ [xx .ravel (), yy .ravel ()]
1127- preds_grid = model .predict (grid_yx )
1128- label2id = {cls : i for i , cls in enumerate (model .classes_ )}
1129- preds_grid_idx = np .array ([label2id [c ] for c in preds_grid ]).reshape (ny , nx )
1159+ @app .cell
1160+ def _ (np ):
1161+ def predict_on_regular_grid (model , extent , nx = 200 , ny = 200 ):
1162+ """Run a classifier on a regular grid in a given domain."""
1163+ xx , yy = np .meshgrid (
1164+ np .linspace (extent [0 ], extent [1 ], nx ),
1165+ np .linspace (extent [2 ], extent [3 ], ny ),
1166+ )
1167+ grid_yx = np .c_ [xx .ravel (), yy .ravel ()]
1168+ preds_grid = model .predict (grid_yx )
1169+ label2id = {cls : i for i , cls in enumerate (model .classes_ )}
1170+ preds_grid_idx = np .array ([label2id [c ] for c in preds_grid ]).reshape (ny , nx )
1171+
1172+ return preds_grid_idx
11301173
1131- return preds_grid_idx
1174+ return ( predict_on_regular_grid ,)
11321175
11331176
11341177@app .cell
1135- def _ ():
1178+ def _ (ListedColormap , pd , plt , predict_on_regular_grid , sns ):
11361179 def plot_classification_results (model , X , y , results , extent , split = "validation" , palette_name = "pastel" ):
11371180 # Prediction on a regular grid
11381181 preds_grid_idx = predict_on_regular_grid (model , extent )
@@ -1208,23 +1251,26 @@ def print_classification_results(results: dict):
12081251 return plot_classification_results , print_classification_results
12091252
12101253
1211- @app .function
1212- def plot_image_before_after_normalization (img_before , img_after ):
1213- """TODO: add docsting"""
1214- fig , axes = plt .subplots (ncols = 2 )
1215- im0 = axes [0 ].imshow (img_before , cmap = "gray" , vmin = 0 , vmax = 255 )
1216- axes [0 ].set_title ("Original image" )
1217- axes [0 ].set_axis_off ()
1218- fig .colorbar (im0 , ax = axes [0 ], fraction = 0.046 , pad = 0.04 )
1219- im1 = axes [1 ].imshow (img_after , cmap = "gray" , vmin = 0 , vmax = 1 )
1220- axes [1 ].set_title ("Intensity rescaled" )
1221- axes [1 ].set_axis_off ()
1222- fig .colorbar (im1 , ax = axes [1 ], fraction = 0.046 , pad = 0.04 )
1223- return fig
1254+ @app .cell
1255+ def _ (plt ):
1256+ def plot_image_before_after_normalization (img_before , img_after ):
1257+ """TODO: add docsting"""
1258+ fig , axes = plt .subplots (ncols = 2 )
1259+ im0 = axes [0 ].imshow (img_before , cmap = "gray" , vmin = 0 , vmax = 255 )
1260+ axes [0 ].set_title ("Original image" )
1261+ axes [0 ].set_axis_off ()
1262+ fig .colorbar (im0 , ax = axes [0 ], fraction = 0.046 , pad = 0.04 )
1263+ im1 = axes [1 ].imshow (img_after , cmap = "gray" , vmin = 0 , vmax = 1 )
1264+ axes [1 ].set_title ("Intensity rescaled" )
1265+ axes [1 ].set_axis_off ()
1266+ fig .colorbar (im1 , ax = axes [1 ], fraction = 0.046 , pad = 0.04 )
1267+ return fig
1268+
1269+ return (plot_image_before_after_normalization ,)
12241270
12251271
12261272@app .cell
1227- def _ (fit_model_with_pca ):
1273+ def _ (fit_model_with_pca , np , plt ):
12281274 def plot_accuracy_vs_pca_components (model , x_train , x_val , y_train , y_val , max_components = 20 ):
12291275 """Does this show up in live docs?"""
12301276 train_accs = []
0 commit comments