## Noname manuscript No.

(will be inserted by the editor)

## Understanding Feedback Mechanisms in Machine Learning Jupyter Notebooks

Arumoy Shome

·

Lu´ ıs Cruz

·

Diomidis

Spinellis

· Arie van Deursen

Received: date / Accepted: date

Abstract The machine learning development lifecycle is characterized by iterative and exploratory processes that rely on feedback mechanisms to ensure data and model integrity. Despite the critical role of feedback in machine learning engineering, no prior research has been conducted to identify and understand these mechanisms. To address this knowledge gap, we mine 297.8 thousand Jupyter notebooks and analyse 2.3 million code cells. We identify three key feedback mechanisms-assertions, print statements and last cell statements-and further categorize them into implicit and explicit forms of feedback. Our findings reveal extensive use of implicit feedback for critical design decisions and the relatively limited adoption of explicit feedback mechanisms. By conducting detailed case studies with selected feedback instances, we uncover the potential for automated validation of critical assumptions in ML workflows using assertions. Finally, this study underscores the need for improved documentation, and provides practical recommendations on how existing feedback mechanisms in the ML development workflow can be effectively used to mitigate technical debt and enhance reproducibility.

Keywords SE4AI, Feedback Mechanisms, Jupyter notebooks, Assertions, Technical Debt

A. Shome

Delft University of Technology

E-mail: a.shome@tudelft.nl

L. Cruz Delft University of Technology E-mail: l.cruz@tudelft.nl

D. Spinellis Delft University of Technology E-mail: d.spinellis@tudelft.nl

A. V. Deursen Delft University of Technology E-mail: arie.vandeursen@tudelft.nl

## 1 Introduction

The machine learning development lifecycle (MLDL) encompasses a multifaceted series of entangled stages. Significant effort is invested in gathering and assembling the required data from diverse sources. The data then undergoes cleaning and preprocessing to ensure high quality and usability, in the subsequent stages. MLDL is dominated by the model development phase which is highly experimental and iterative. This stage involves exploratory data analysis (EDA) to uncover underlying patterns, fitting the data to various models, and rigorously analysing the results. Often, this stage may lead to additional rounds of feature engineering, where new attributes are created based on insights gained from initial models to enhance model performance. Practitioners may also engage in comparing and contrasting different models to identify the most effective approach, followed by fine-tuning selected models to optimize performance. The final model is then deployed into production where it is continuously monitored, and periodically retrained to adapt to new data or changing conditions (Haakman et al., 2021; Amershi et al., 2019; Sculley et al., 2015).

The MLDL is fundamentally iterative, closely resembling Agile software engineering principles, which emphasize incorporating early feedback and working in small, manageable iterations (Betz, 2018). Similarly, CRISP-DMthe dominant process model in data mining-outlines a cyclical process that evolves from understanding the business objectives and data, to data preparation, modelling, evaluation and finally deployment and monitoring (MartinezPlumed et al., 2021). Both systems advocate for a dynamic, iterative approach that enhances adaptability and effectiveness in dealing with complex, changing systems like those encountered in ML projects.

Computational notebooks-specifically Jupyter notebooks -have been ubiq1 uitously adopted by the ML community for developing ML enabled systems (Pimentel et al., 2019; Quaranta et al., 2021; Psallidas et al., 2019; Perkel, 2018). Jupyter notebooks provide an interactive computing environment that allow users to break the development of complex workflows into smaller, more manageable code chunks. Each notebook is composed of a series of code cells, which can be executed independently in a read-eval-print loop (REPL) style of interactive software development. This REPL approach allows users to write a piece of code, run it, and immediately see the results thus facilitating an incremental and iterative style of software development. This modular structure of notebooks provides users the flexibility to experiment with different approaches and algorithms. Users can test hypotheses, debug issues, and make incremental changes with immediate feedback. The ability to visualize data and results inline and document the process in a narrative form further enhances their utility (Kery et al., 2018; Head et al., 2019; Rule et al., 2018; Chattopadhyay et al., 2020).

1 https://jupyter.org/

Notebook users can obtain feedback using implicit or explicit mechanisms. Implicit feedback mechanisms require manual validation by the user. For instance, a common prerequisite for all ML models is that the features in the dataset are all numerical. This can be verified with a print statement in a code cell and manually checking the output. This code statement however, will continue to execute even if the data type of a feature changes in subsequent batches of training data.

In contrast, explicit feedback mechanisms document the expected conditions of the code and halt execution if these conditions are not met. For instance, the implicit validation method mentioned above can be replaced with an explicit assertion: assert all(df[col].dtype in ['int64', 'float64'] for col in df.columns), "Not all columns are of numerical type" . This assert statement will stop the execution if the condition is not satisfied and provide immediate feedback with a clear message explaining the issue.

As machine learning pipelines developed within Jupyter notebooks become business-critical, they are frequently transitioned into automated scripts for production environments (Kery et al., 2018; Rule et al., 2018). In these contexts, it is crucial to shift from implicit feedback mechanisms to explicit ones. This transition reduces the reliance on manual verification, thereby enhancing the robustness and maintainability of ML pipelines.

To the best of our knowledge, no prior studies have been conducted to understand how feedback mechanisms are used by practitioners when developing ML pipelines inside Jupyter notebooks. To address this gap, we conduct a series of empirical studies to understand the role of various feedback mechanisms within Jupyter notebooks. We focus on implicit form of feedback obtained from print statements and output generated by the last statement of code cells, as well as explicit form of feedback obtained from assertions. The research questions along with the contributions of this study are presented below.

## RQ1. What feedback mechanisms are employed in the development of ML Jupyter notebooks?

Wemine 297.8 thousand Jupyter notebooks written in Python from GitHub and Kaggle. We analyse 2.3 million code cells obtained from the notebooks and identify three key feedback mechanisms used in ML notebooksexplicit feedback from assertions and implicit feedback from print and last cell statements.

We create a public dataset of 89.6 thousand assertions, 1.4 million print statements and 1 million last cell statements. We perform a descriptive and lexical analysis of the dataset and report the key characteristics of feedback mechanisms used in ML Jupyter notebooks. The dataset along with the replication package is shared publicly under the Creative Commons Attribution (CC-BY) licence . 2

RQ2. How is explicit feedback from assert statements used to validate ML code written in Jupyter notebooks?

2 https://doi.org/10.6084/m9.figshare.26372140.v1

To gain a deeper understanding of Python assertions written in Jupter notebooks, we conduct individual case-studies with 82 assert statements. We analyse the assertion along with the surrounding code to understand its purpose. Additionally, we analyse the entire code cell, the previous and next cells along with the purpose of the notebook to bring in rich context. RQ3. How is implicit feedback from print statements and last cell statements used when writing ML code in Jupyter notebooks? Similarly, we conduct individual case-studies with 44 print statements and 27 last cell statements. During each case-study, we analyse the code statement along with the raw output to understand its purpose.

Our findings indicate that implicit feedback mechanisms are extensively utilized for making critical design and implementation decisions during the MLDL. While manual validation of these outputs is common, it is also prone to inconsistencies thus highlighting the need for automated validation mechanisms. Assertions are identified as a potential solution, capable of verifying data distributions and ensuring model performance metrics meet predefined thresholds. However, the study also notes the limited use of assertions, with only 8.5% of the notebooks analysed incorporating them, suggesting a significant gap in current testing practices within the ML community. The findings underscore the necessity for developing ML-specific testing tools that are deeply integrated into the ML development workflow to ensure consistent and reliable validation processes.

## 2 Background

This section introduces relevant prior concepts for this study.

## 2.1 REPLs, Interactive Computing and Project Jupyter

A Read-Eval-Print Loop (REPL) is an interactive programming environment that takes single user inputs (Read), executes them (Eval), returns the result to the user (Print) and then waits for the next command (Loop). REPLs offer an immediate feedback loop for quickly testing and debugging code snippets. The Python standard distribution includes a Python REPL with a command line interface to execute Python code in real-time. IPython-a more advanced alternative to the Python REPL-extends the capabilities of the standard Python shell with additional features such as powerful introspection, additional shell syntax, tab completion, and command history. Jupyter notebooks (and its successor Jupyter lab) leverage the IPython kernel to execute Python code and extends its capabilities with a graphical user interface (GUI). Resembling the literate programming paradigm (Knuth, 1984), Jupyter notebooks offer a web-based interface where users can create and share documents that contain live code, equations, visualizations, and narrative text.

Fig. 1: Example Jupyter notebook with code and markdown cells, adapted from (Pimentel et al., 2019, Figure 1).

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-89840ef6-07a5-420f-9b4e-d8a68afc7189.jpg)

## 2.2 Anatomy of Jupyter Notebooks

Figure 1 shows an example Jupyter notebook with markdown and code cells. The data comprised within Jupyter notebooks is stored using the JSON schema specified by nbformat 3 , and thus can be parsed programmatically. A notebook consists of cells which can be of three types-'markdown', 'code' and 'raw'. All cells of a notebook are stored as a list under the top-level cells key in the JSON representation. Within this list, each cell is represented as a JSON object. The contents of the cell are stored as a list of strings inside the source key.

Only code cells in Jupyter notebooks can generate outputs. As shown in Figure 1, outputs can come from three main sources in the source codeprint statements, the last statement in the code cell, and statements that create a visualization. The outputs produced by code cells are stored as JSON objects under the outputs key in the corresponding JSON representation of the notebook. Text outputs (such as those produced by the last statement of a cell or print statements) are stored under the text key. Visual outputs have a sightly different JSON schema and are stored under the data key. The image itself is represented as a base64 encoded string which is stored inside the data object, under the image/png key.

3 https://nbformat.readthedocs.io/en/latest/index.html

Fig. 2: Overview of data collection methodology used in this study

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-5f3e2347-b2b0-436e-bb01-980f9744f799.jpg)

## 2.3 Python Abstract Syntax Tree

The Python ast module enables the parsing, manipulation, and analysis of Python source code by converting it into an abstract syntax tree (AST) 4 . The ast module can parse source code strings into AST objects, traverse and modify the tree and compile it back into executable code, providing a powerful tool for dynamic code manipulation. In Python, assert statements are represented in the AST by the Assert class. The Assert node includes the test attribute-which contains the condition being asserted-and the msg attribute-which holds an optional message displayed if the assertion fails. Print statements are treated as a call to the built-in print function. Function calls are represented in the AST by the Call class. The Call node includes the func attribute representing the print function, and args which lists the arguments passed.

## 3 Methodology

## 3.1 Data Collection

Figure 2 illustrates the data collection process employed in this study to gather Jupyter notebooks written in Python from GitHub and Kaggle. We used GitHub's advanced search syntax , 5 with the following search query: language:"Jupyter Notebook" to mine 49.9 thousand Jupyter notebooks from public repositories on GitHub . 6 We used the pre-existing dataset KGTorrent (Quaranta et al., 2021) for Kaggle since it does not support advanced code-based search like GitHub. To the best of our knowledge, KGTorrent is the largest dataset of Python Jupyter notebooks obtained from Kaggle, consisting of 247.9 thousand notebooks. Consequently, we started with 283 GB of data comprising 297.8 thousand Python Jupyter notebooks.

Since the focus of this study is on the analysis of Python code, we only include notebooks that have a valid underlying JSON structure and contain at least one code cell. Finally, to focus on Python code written specifically for ML projects, we only include notebooks that import at least one of the following popular ML libraries-Scikit Learn (Pedregosa et al., 2011), Pytorch (Paszke et al., 2017), Tensorflow (Abadi et al., 2015) and Keras (Chollet et al., 2015). The libraries are selected based on the import analysis conducted by Psallidas et al. (2019) on 6 million Jupyter notebooks collected from GitHub. We use the Python ast module to extract the assert, print and last statements from all code cells. Prior to conducting the analysis for RQ2 and RQ3, we remove duplicate data points resulting in a data set of 27.1 thousand assertions, 498.3 thousand print statements and 373.6 thousand last cell statements.

## 3.2 Case Studies

For RQ2 and RQ3, we allocated a fixed time resource of 200 hours to conduct the case study analysis of all candidate assertions, print statements and last cell statements. To surface interesting candidates for the case studies, we apply text processing techniques as described below.

The assertions, print statements and last cell statements are first tokenizedspecial characters and alphanumeric words shorter than two characters are removed. Two stop words namely 'assert' and 'print' are removed since they appear in all assertions and print statements respectively. The term frequency (TF) for all tokens is calculated and then normalized using their interdocument frequency (IDF) such that tokens that appear less frequently are assigned a higher value. We apply stratified random sampling to identify the candidates for the case study analysis. The subgroups are created by adding TF-IDF of the tokens in each candidate to produce an aggregate value. The

4 https://docs.python.org/3/library/ast.html

5 https://docs.github.com/en/search-github/searching-on-github/searching-code

6 Collected on June 22, 2023

Fig. 3: Overview of various feedback mechanism groups identified in this study.

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-fb8c4e8d-4377-4ef6-bf7f-a99cb67c0d95.jpg)

candidates are then divided into quartiles based on the aggregate value. A candidate is randomly drawn from each bin and analysed as an in-depth case study. The analysis is stopped when the time resource is exhausted.

During each case study, we analyse the code of the candidate to understand its purpose. Additionally, we analyse the entire code cell, the previous cell, next cell and the notebook's purpose to bring in rich context. For case studies where the first author was unable to determine the purpose of the candidate, it was additionally analysed by the second and third authors. Further discussions were held with all authors until a consensus was reached.

## 4 Results

The results of the study are presented in this section. For the case studies conducted for RQ2 and RQ3, we group the candidates based on their similarity to each other. This is done only to structure the paper in a meaningful

Fig. 4: 10 most common methods used in assertions written using external testing libraries.

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-f4137277-8b69-48f2-bc29-451afcbcc3d1.jpg)

manner and for ease of reporting the results. Figure 3 provides an overview of the various feedback mechanism groups identified in this study with additional details provided in Section 4.2 and Section 4.3. Throughout the text, we reference the candidate (A) ssertions, (P) rint statements and (L) ast cell statements using their unique identifiers as examples. These can be viewed on our online appendix . 7

4.1 (RQ1) What feedback mechanisms are employed in the development of ML Jupyter notebooks?

25 thousand (8.5%) notebooks contained at least one assertion. From the 8.5% notebooks, we collected 89.6 thousand assertions. 4.8 thousand assertions (5%) used methods from external testing libraries. 85 thousand assertions (95%) however were written using the assert statement provided by the builtin Python standard library. We removed duplicate assertions for the remainder of the analysis, thus resulting in 27.1 thousand assertions.

Figure 4 presents the 10 most common methods used in the 5% assertions written using external testing libraries. We manually tracked the source of the methods to the numpy, pandas, torch and unittest libraries. The most frequently used methods include assert\_almost\_equal and assert\_equal , each with over 250 instances. Methods such as assert\_almost\_equal , assert\_array\_almost\_equal and AssertAlmostEqual accommodate the stochastic nature of ML, where results can vary slightly due to inherent randomness in data processing and model training. We also find methods such as assert\_array\_equal and assert\_frame\_equal that are specifically tailored for comparing high-dimensional data structures such as numpy arrays and pandas dataframes.

7 https://arumoy.me/shome2023notebook

Fig. 5: 10 most common AST nodes in the test attribute of assert statements.

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-aedc9a4b-664c-492e-9740-4675fc9d2a37.jpg)

Fig. 6: 10 most common operators used in assert statements that perform a comparison check.

Table 1: Examples of the most common tests performed in assert statements.

| Comparison Check                                                                      | Function Call                                                                                                       |
|---------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|
| type(train_dataset[0]) == tuple torch.__version__ > '1.10.0' len(x_dev) == len(y_dev) | (np.unique(y_test) == [-1, 1]).all() isinstance(transmat, pd.dataframe) np.allclose(np.linalg.norm(wio, axis=0), 1) |

Finding 1.1 25 thousand (8.5%) notebooks contained at least one assertion. 95% of the 89.6 thousand assertions were written using the built-in Python assert statement and 5% using external testing libraries. Methods such as assert\_almost\_equal and assert\_array\_equal from the numpy and pandas libraries were frequently used to accomodate for the stochastic nature of ML algorithms and comparing high-dimensional data structures.

We focus the remainder of the analysis on the 95% of the assertions written using the assert statement. Figure 5 shows the most frequent AST nodes that occur in assert statements. The figure indicates that the most common test performed in the assert statements include a comparison check and a function call. Table 1 provides a few examples of assertions for each of the tests above. In Figure 6 we see the most common operators used in assert statements that perform a comparison check. We observe that overwhelming majority of the asserts ensure that two values are equal to each other. Figure 7 and Figure 8 show the most common bi-grams that appear in the LHS and RHS of the comparison statements respectively. The figures collectively show that the shape and size of data structures are frequently checked.

Of the 95% assert statements, 28.4 thousand (31.7%) have a failure message. Figure 9 shows the most frequent bi-grams that appear in these failure messages. Similar to the analysis presented above, we removed the duplicate

Fig. 7: Most common bi-grams that appear in the LHS of comparison statements.

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-224cd8ec-d0ec-4354-91cc-ab93b53169b5.jpg)

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-6ebe2dba-5fff-42c2-a9f1-4f3cd3cf1a10.jpg)

Fig. 8: Most common bi-grams that appear in the RHS of comparison statements.

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-5a49b784-b4bc-40e7-b162-77d9f5f9ef03.jpg)

Fig. 9: Most common bi-grams in the failure messages of assert statements.

messages prior to analysing the bi-grams resulting in 5.9 thousand unique messages. The bi-grams indicate that the shape and data type of data structures are frequently verified.

Finding 1.2 31.7% of the assertions written using the built-in assert statement have a failure message. These assertions frequently perform a comparison check or call an external function. The comparison checks frequently verify that the shape and size of data structures is equal to a specified value.

We collected 1.4 million print statements from 180 thousand notebooks (60% of the total notebooks analysed in this study). Unlike assert statements, print statements do not have a fixed lexical semantic since the Python ast module interprets them as regular function calls. Additionally, print statements can be written in several forms-the print function may have multiple arguments, any form of string interpolation supported by Python or output

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-4ec447d7-655d-4282-be92-33ddd07616d0.jpg)

Fig. 10: Most common AST nodes inside print statements

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-8caf76c7-991e-4037-bcfe-7dfbdc35c561.jpg)

Fig. 11: Most common type of constant inside print statements

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-c188b4e7-a982-42c8-8fd1-cd7445792dac.jpg)

Fig. 12: Most common bi-grams that appear in natural text of print statements.

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-d433c4cb-44dd-4d3c-882b-f84a9496c78b.jpg)

Fig. 13: Most common bi-grams that appear in the code of print statements.

from function calls. Figure 10 shows that the most common AST nodes inside of print statements are constants followed by function calls. Figure 11 further validates that the constants are almost entirely of type string. Based on these observations, we dissect the print statements into two components-text written in natural language (from the Constant nodes) and code (from all other nodes). Figure 12 and Figure 13 present the most common bi-grams that appear in the natural text and code of print statements respectively. Both figures collectively indicate that print statements are frequently used to print various performance metrics of ML models.

Finding 1.3 Print statements are most commonly used to display various performance metrics of ML models.

We collected 1 million last cell statements from 119 thousand notebooks (40% of the total notebooks analysed in this study). Figure 14 shows that Call

Fig. 14: Most common AST nodes in the last cell statements.

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-88c880c8-0f4e-489c-b1c1-53d290a49062.jpg)

Fig. 15: Most common Python modules and objects used in the Call nodes of last cell statements.

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-6c53b874-0d1b-409a-b37c-29a2d8fc7d8b.jpg)

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-e117408d-51ca-4b5e-8f2b-33dd34c37c63.jpg)

Fig. 16: Most common functions used in the Call nodes of last cell statements.

nodes frequently occur in the AST of last cell statements. Figure 15 shows the most common Python modules and objects while Figure 16 show the most common functions used inside these Call nodes. The figures highlight the prominence of data visualization libraries seaborn ( sns ) and matplotlib ( plt ) and visualization functions such as plot and countplot in the notebooks. The data analysis tool pandas (represented by df and pd ) also features prominently with many data exploration and preprocessing functions such as head , value\_counts and describe being used frequently. The presence of train and model Python objects along with the fit function indicates the use of ML libraries.

Finding 1.4 Libraries and functions for data visualization, data exploration and machine learning are most common in last cell statements.

Wefurther analysed the most common functions called on pandas dataframes by isolating the last cell statements that contain data or df objects. This is shown in Figure 17 which reveals a focus on exploratory data analysis and

Fig. 17: Most common functions called on pandas dataframes.

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-ea4e8006-e27e-4b42-9e7e-e3ed31054d08.jpg)

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-0e758d96-cca1-44d9-8dea-e0efdeb0bda1.jpg)

Fig. 18: Most common visualization functions used in last statements.

statistical operations. The frequent use of functions such as value\_counts , head , and unique , indicate an emphasis on understanding the structure and content of the data. Visualization functions like plot and hist suggest that practitioners often create quick visualizations directly from dataframes. Descriptive statistics are also prominent, with functions like describe , mean , and sum being commonly used.

Similarly, we also analysed the most common visualization functions used in notebooks by isolating the last cell statements where the module is sns or plt . This is shown in Figure 18 which indicates that categorical data visualization appears to be a primary focus, with countplot and barplot ranking high among the most frequently used functions. The prominence of heatmap and boxplot functions indicates a regular need for visualizing correlations and statistical distributions. For continuous data, functions like distplot , scatterplot , and scatter are commonly used. The presence of imshow suggests that image-related visualizations are also significant in many notebooks.

Finding 1.5 Common functions called on pandas dataframes focus on exploratory data analysis, statistical operations and quick visualizations. In visualizations, functions for categorical data, correlation and distribution are frequently used.

4.2 (RQ2) How is explicit feedback from assert statements used to validate ML code written in Jupyter notebooks?

$$4. 2. 1 \, D a t a \, s h a p e \, c h e c k \, \left ( N = 2 6 \right )$$

Data shape checks can be considered the 'Swiss army knife' of assertions, as they are ubiquitous and serve multiple purposes throughout the MLDL.

We encountered a vast array of assert statements that verify the dimensions of various data structures, including input features ( A17, A90 ), labels ( A5, A29 ), predictions, images ( A76, A93 ), sequences, and embeddings ( A76, A93 ). These assertions ensure that the data adheres to the expected format and dimensions required by different components of the machine learning pipeline.

Finding 2.1 26 assertions verify the dimensions of various data structures such as input features, labels, predictions, images, sequences, and text embeddings. These checks ensure data consistency and compatibility throughout the ML pipeline, preventing runtime errors and ensuring accurate model training and evaluation.

## 4.2.2 Data validation check ( N = 14 )

We found assert statements that perform various validation checks on data structures, such as NumPy arrays and Pandas dataframes. Common data validation checks include verifying the presence of specific values or ranges within arrays or columns( A41, A65 ) and verifying the equality or closeness of arrays to a target value within a specified absolute tolerance ( A44, A46 ). Some assertions also focus on validating the uniqueness or cardinality of values ( A52 ) while others validate the presence of specific values or conditions within data structures ( A73 ).

Finding 2.2 Fourteen assertions perform validation checks on data structures, ensuring the presence of specific values, verifying value ranges, and confirming uniqueness or cardinality of values. These checks catch potential errors or inconsistencies early, ensuring data meets specific criteria or constraints for robust ML applications.

4.2.3 Model performance check ( N = 11 )

## assert np.isclose(accuracy , 0.9666666666666667)

Listing 1: Assertion A58 used to check that the accuracy of a model is close to the specified value. The use of np.isclose allows for small deviations in the accuracy thus accounting for the stochastic nature of ML models.

This study finds several assertions used to test model performance against predefined thresholds for key metrics such as accuracy, precision, recall and F1 score. Range checks confirm that the performance metrics fall within acceptable boundaries, indicating good predictive performance without overfitting ( A38 ). Direct comparisons of model outputs with expected results, validate the model's predictive accuracy and reliability under operational conditions

( A15 ). Other assertions ensure that the learned parameters align closely with theoretically or empirically derived values, further cementing the model's statistical validity ( A19 ). Finally, assertions are also used to check for the expected number of neighbours as an indirect measure of model performance in specific scenarios like clustering ( A7 ).

The use of np.isclose in Listing 1 is particularly noteworthy. This method accounts for the stochastic nature of many ML models, where slight variations in performance metrics can occur due to differences in initial conditions, random seed settings, or inherent randomness in algorithms. By allowing a small tolerance in the comparison, np.isclose ensures that the model's performance is consistently close to the expected benchmark despite the stochastic elements.

Finding 2.3 Eleven assertions evaluate model performance against predefined thresholds for accuracy, precision, recall, F1 score, and other metrics. These checks validate the model's predictive accuracy and reliability, ensuring it meets expected performance standards despite the stochastic nature of ML models.

## 4.2.4 Existence check ( N = 8 )

Existence checks are primarily used during the data preprocessing stage in the MLDL to ensure data integrity before analysis and modelling. These checks primarily focus on verifying the presence of necessary columns and the absence of missing values within those columns ( A23, A42, A79, A86 ). Such validations are especially crucial after data preprocessing steps, where transformations might inadvertently introduce NaN values ( A50, A51, A63 ) or result in an empty dataframe ( A43 ). These checks are also crucial for maintaining the accuracy and efficiency of data handling processes, ensuring that the datasets are ready for robust ML applications.

Finding 2.4 Eight assertions ensure the presence of specific columns in the dataset and the absence of missing values. These checks prevent operations on empty datasets and confirm the absence of NaN values, maintaining data integrity and reliability for model training.

4.2.5 Resource check ( N = 7 )

## assert svm.fit\_status\_ == 0, 'Forgot to train the SVM!'

Listing 2: Assertion A37 used to ensure that an ML model has not reached an inconsistent state due to out-of-order or re-execution of code cells.

Resource check assertions are used to ensure the availability and validity of essential resources, preventing runtime errors, and maintaining the integrity of the data, models, and visualizations. One set of assertions verify the existence of files on the file system, such as pre-trained models ( A10 ) or data files ( A74 ). Subsequently, assertions are employed to validate the successful loading of models ( A14 ) and the completion of model training processes ( A37 ).

A unique aspect of working with notebooks is the ability to re-run cells while experimenting, which can lead to unintended consequences. Assertion A37 presented in Listing 2 addresses this scenario by checking if the SVM model has been properly trained before proceeding with further operations. This check prevents inconsistent model states from executing cells out of order or multiple times. Other interesting assertions unique to computational notebooks include verifying the presence of data in visualizations ( A60 ) and explicitly verifying the versions of critical libraries ( A18, A67 ).

Finding 2.5 Seven assertions confirm the availability of essential resources like pre-trained models, data files, successful model loading, and completion of training processes. These checks prevent runtime errors and ensure proper code execution, maintaining the reliability and robustness of the ML workflows.

## 4.2.6 Type check ( N = 5 )

Type check assertions are used to maintain data integrity, ensure compatibility between different components of the ML pipeline, and preventing errors and unexpected behaviour. Type checks are commonly performed to ensure that the input features are PyTorch float tensors or NumPy arrays, a requirement for many deep learning models and scientific computing operations respectively ( A2, A88 ). Type checks are also applied to verify the type of the ML models ( A40 ), data structures and intermediate objects ( A35 ) and individual columns or elements within a dataset ( A81 ).

Finding 2.6 Five assertions validate the data types of input features, models, and intermediate objects. These checks ensure compatibility with ML models and operations, preventing errors from incompatible methods or attributes, thus maintaining the reliability of the ML workflow.

## 4.2.7 Mathematical property check ( N = 4 )

When working with neural networks and other statistical models, it is imperative to ensure that mathematical properties are preserved throughout operations involving arrays and matrices. This rigour is captured though assertions that ensure convolution operations are dimensionally consistent ( A3 ), checking for the symmetry of matrices ( A64 ) and monitoring the standard deviation

of outputs to decide the appropriateness of using batch normalization ( A25 ). These assertions are not just precautionary but are vital for confirming that the underpinnings of ML algorithms align with expected mathematical principles.

Finding 2.7 Four assertions validate key mathematical properties of data and model outputs. These include ensuring dimensional consistency in convolution operations, monitoring standard deviation for batch normalization suitability, verifying uniformity in computations, and checking matrix symmetry. These checks confirm the robustness and reliability of model computations.

## 4.2.8 Batch size check ( N = 3 )

In the context of neural networks, the practice of using batch processing is a key strategy to enhance computational efficiency and hardware utilization. Batching stabilizes the learning curve by updating the model weights based on the average gradient of a batch thereby optimizing learning and enhancing generalizability of the model. Ensuring the batch size matches the hardware capacity is crucial to avoid memory overflow issues that can halt training. Assertions are used to check that the batch size divides evenly into the training dataset size which ensures that each training epoch is computationally efficient ( A21 ). Additionally, assertions are used to ensure that the size of the training data is larger than the batch size ( A70 ) and that image dimensions are suitably divisible by the patch size which is essential for certain convolutional networks ( A28 ).

Finding 2.8 This study identifies three assertions validating batch size configurations. These assertions ensure batch sizes are divisible by dataset sizes, image dimensions are appropriately divided by patch sizes, and the number of images exceeds the batch size. These checks are crucial for optimizing computational efficiency and ensuring stable and smooth model training.

## 4.2.9 Network architecture check ( N = 3 )

When integrating pre-trained models or leveraging transfer learning techniques, it is crucial to ensure the compatibility of the custom neural network architecture with the pre-trained components. This is particularly important when combining convolutional layers from different sources, as the spatial dimensions and channel configurations must align correctly. Checks include assertions that verify the output and input dimensions of consecutive convolutional layers match ( A11 ), checking that shape of the activations have

the right number of channels ( A62 ) and that the appropriate regularization parameter is set ( A75 ). Such architectural checks are crucial for preventing potential issues during the forward pass of the neural network and ensuring that the custom and pre-trained components are compatible with each other.

Finding 2.9 Three assertions verify the consistency of neural network architecture. These include ensuring weight dimensions match across layers and that activation shapes and regularization parameters are as expected. These checks ensure that the neural network is correctly configured and integrated with pre-trained models, maintaining the integrity of data flow during training.

4.2.10 Data leakage check ( N = 1 )

```
        assert len(
        set(tr_df.PetID.unique()).intersection(valid_df.PetID.unique())
        ) == 0
```

Listing 3: Assertion A33 used to ensure that the training and validation sets do not contain any overlapping values.

Ensuring the absence of data leakage between training and validation datasets is a fundamental best practice in ML to prevent overfitting. To guarantee that the model can generalize effectively to new examples, it is crucial to verify that the training and validation sets are completely distinct with no shared examples. By strictly separating these datasets, the validation phase provides an unbiased evaluation of the model's ability to generalize to data similar to, but not identical to that which it was trained on. This is demonstrated by Assertion A33 in Listing 3 which ensures that there are no overlapping PetID values between the training set and the validation set, thereby preventing any possibility of data leakage.

Finding 2.10 This study identifies one assertion to ensure there are no overlapping values between training and validation sets to prevent data leakage. Preventing data leakage is essential to avoid overfitting and ensure the model's ability to generalize to new data. This practice maintains the integrity and validity of the model evaluation metrics.

4.3 (RQ3) How is implicit feedback from print statements and last cell statements used when writing ML code in Jupyter notebooks?

## 4.3.1 Model performance check ( N = 33 )

During the model development phase, the performance of an ML model is often printed to facilitate comparisons against other models or variations. Throughout this continuous experimentation phase, authors may adjust model parameters or modify the data by engineering new features. The model is then re-trained to check if these changes lead to performance improvements. Besides the accuracy of the model ( P3, P18 ), we also see checks for the Root Mean Square Error (RMSE) ( P6 ) and the use of the classification report ( P50 ) provided by scikit-learn 8 which reports the accuracy , precision , recall and f1 score for all labels present in the target feature. In addition, we find the use of heatmaps ( L3 ) to visualize the confusion matrix of a multi-label classification task and custom functions ( L52 ) to manually evaluate an image classification model on a random sample of input images.

Finding 3.1 The study identifies 33 implicit checks to monitor the performance of trained ML models. These include outputs that print key performance metrics, a normalized heatmap used to visualize the confusion matrix of a model's predictions and a custom function written for manual evaluation of model predictions on random input samples. These checks are used throughout the iterative model development phase, enabling practitioners to compare different models or variations, adjust parameters, and refine features to improve performance.

4.3.2 Data distribution check ( N = 7 )

Understanding the distribution of data is crucial for making informed decisions about necessary transformation steps in data analysis. For instance, visualizations can efficiently determine if scaling, normalizing, or handling outliers is needed. During the exploratory data analysis phase, visualizations and pandas dataframes are commonly used to assess the distribution of specific columns ( L9 ), helping identify features related to the target variable ( L2, L14 )and informing feature inclusion in model training. Additionally, descriptive statistics are used post-transformation to manually verify the effectiveness of data transformation steps and ensuring that the data conforms to the expected format for further analysis ( L48, L25 ).

Finding 3.2 The study identifies seven implicit data distribution checks, including visualizations like categorical plots, kernel density estimate plots and count plots, and statistical summaries from pandas dataframes. These checks are used for making informed decisions about data transformations

8 https://scikit-learn.org/stable/modules/generated/sklearn.metrics.classification report.html

such as scaling, normalizing and handling outliers, ensuring data integrity and improving model training reliability during the exploratory data analysis phase.

## 4.3.3 Resource check ( N = 7 )

Similar to the assertions identified in Section 4.2.5, we also find print and last cell statements that validate the availability of essential resources on the system where the notebooks are being executed. This includes checks for the availability of compute resources such as a GPU or a TPU ( P68, P82, P86 ), verifying that a dataset or a pre-trained model has been successfully loaded into memory ( P107, L66 ) and ensuring that a certain version of an external library is present on the system ( P71 ).

Finding 3.3 The study identifies seven implicit checks used to verify resource availability on the systems where the Jupyter notebooks are being executed. These checks include confirming the availability of compute resources like GPUs and TPUs, ensuring datasets or pre-trained models are successfully loaded, and verifying the presence of specific library versions. These checks are used for ensuring that the computational environment is correctly set up, preventing execution errors, and facilitating smooth workflow execution.

$$4. 3. 4 \, S p o t \ c h e c k \left ( N = 5 \right )$$

Performing value or spot checks can be an essential practice for ensuring data integrity and model accuracy at various stages of development. These checks are crucial for verifying that operations such as data transformations, model predictions, and feature engineering are functioning as expected. Common checks include verifying the number of features in the data matches expectations after applying feature selection or dimensionality reduction techniques ( L60 ), assessing the correctness of one-hot encoding ( P114 ) and ensuring that data retains its expected properties after manipulation ( P64 ).

Finding 3.4 This study finds five implicit spot checks performed at various stages of the MLDL. Spot checks are used to ensure data integrity by verifying data transformation and feature engineering steps meet expectations.

## 4.3.5 Model training check ( N = 4 )

During training, it is common practice to monitor the progress periodically and use this feedback to adjustment training parameters or stop training early to

prevent overfitting. This can be done by checking the best parameters found through tuning methods ( L42 ), fitting the model to the training data ( L31 ) or printing the training loss and accuracy to give real-time feedback on the learning efficacy of the model ( L8 ).

Finding 3.5 The study identifies four implicit checks used to monitor model training progress. These checks provide real-time feedback on training loss and accuracy, validate model adherence to expected data patterns, and identify optimal parameters through tuning methods. These checks facilitate timely adjustments during the training process to prevent overfitting and ensure model performance optimization.

## 4.3.6 Missing value check ( N = 3 )

Checking for missing values is a critical step in the preprocessing phase of an ML project because it significantly influences the quality and performance of the model. Missing data can lead to biased or incorrect conclusions if not handled properly, potentially skewing the model's performance by training on incomplete or non-representative samples (Shome et al., 2022). Many ML algorithms demand complete numerical datasets to perform calculations such as matrix multiplication. Missing values interrupt these calculations, leading to errors or the inability to execute algorithms entirely. These checks can be performed in code ( P74, L36 ) and using visualizations such as a heatmap ( L12 ).

Finding 3.6 The study identifies three implicit checks for missing data. Missing values can lead to biased or incorrect conclusions as many ML algorithms require complete numerical datasets for accurate calculations. Identifying and addressing missing data during preprocessing is essential to avoid errors and improve model reliability.

$$4. 3. 7 \, S h a p e \ c h e c k \, \left ( N = 3 \right )$$

Ensuring that data dimensions align with expectations is important particularly following data pre-processing or transformation steps. Primarily, the number of features in the training set must match those in the testing set ( P4, P32, P117 ). This alignment is crucial because statistical ML models are trained on specific data dimensions and expect the same dimensional structure during inference to perform accurately. Similarly, in neural network architectures, the configuration of input layers depends directly on the shape of the training data, dictating the number of input neurons needed. Furthermore, the correspondence between the number of test examples and their respective labels is essential for accurately computing performance metrics.

Table 2: Last cell statements used to verify linear relationship between features in the data.

![Image](https://ac.marcodsn.me/arxiv-markdown-images/2408.00153v1-figure-f35d80a6-cd15-48a2-be64-90ab69d4e6f0.jpg)

| Key   | Code                                                                                                    | Output   |
|-------|---------------------------------------------------------------------------------------------------------|----------|
| L6    | b = sns.relplot(x='SIZE', y='Cash', hue='CLARITY', alpha=0.9, palette='muted', height=8, data=raw_data) |          |
| L10   | sns.regplot(x='X4 number of convenience stores', y='Y house price of unit area', data=data)             |          |

Finding 3.7 The study identifies three implicit checks used to validate the shape of data. These checks are used to ensure data dimensions align with expectations, particularly after preprocessing or transformation steps.

4.3.8 Data relationship check ( N = 2 )

Linear ML models achieve optimal performance when the target variable can be expressed as a linear combination of the input features. However, features within a dataset that exhibit a linear relationship are considered redundant as they convey the same information to the model during training. Consequently, the feature engineering stage often involves removing such features to create a more efficient training dataset (Shome et al., 2022). Table 2 illustrates two last cell statements found in this study for identifying linear relationships among features in the data. In addition to the code, the raw output of the cell is also shown since both case-studies produce a visualization. In L6 , the practitioner assesses the linearity between the features Cash and SIZE . L10 is a visualization of the feature X4 alongside the target variable Y , accompanied by a fitted linear regression model.

Finding 3.8 The study identifies two last cell statements used to verify linear relationships between features in the data. Visualizations such as a scatter plot with a regression line and a line plot are employed to assess the linearity between features. These checks are used for identifying and potentially removing redundant features or performing feature selection to ensure that the training dataset is optimized for linear ML models.

$$4. 3. 9 \ T y p e \ c h e c k \left ( N = 2 \right )$$

Type checks are crucial not only for confirming the current state of the data but also for determining the specific transformations required to make the data suitable for subsequent modelling steps. Ensuring data types align with model requirements is a fundamental step in the exploratory data analysis phase. Since all ML algorithms perform mathematical operations, they require the input data to be entirely numerical to avoid computational errors ( P43, L71 ). The process of checking data types helps in identifying the necessary pre-processing or transformation steps to convert the data into a form that is compatible with these models. For example, numerical features often require normalization to bring them within a specific scale and categorical features must be converted into a numerical format through methods like one-hot encoding to ensure they can be effectively integrated into the model.

Finding 3.9 The study identifies two implicit checks used to verify the data types of features in the dataset. These checks are used to determine the necessary preprocessing or transformation steps required to make the data suitable for training. Type checks are also used to ensure that all features are numerical prior to performing mathematical operations such as matrix multiplication, which is used in several ML models.

4.3.10 Execution time check ( N = 1 )

## print('Total Run Time:')

Listing 4: Print statement P66 used to check the total execution time of training an ML model with various hyper-parameter configurations.

While training multiple ML models for a single task is common, choosing the best model considers not only its performance but also its training speed. Faster training times are more cost-effective for iterative tasks and promote sustainability in the long run (Shome et al., 2022). Listing 4 presents print statement P66 that prints the total execution time of a code cell which trains an ML model with various hyperparameter configurations using a grid-search.

Finding 3.10 The study identifies one print statement used to check the total execution time of training and cross-validating an ML model. The print statement can be used to evaluate the efficiency of model training, especially when multiple models are trained iteratively.

## 4.3.11 Network architecture check ( N = 1 )

Printing the structure of a neural network ( P92 ) serves crucial purposes such as verifying the correct implementation of the architecture, aiding in debugging by ensuring layer compatibility, and providing a clear, human-readable format for documentation and educational insights. It helps in verifying configurations like layer dimensions and operations before initiating computationally intensive training and ensuring that the model is set up efficiently for the intended tasks.

Finding 3.11 The study identifies one print statement used to show the architecture of a neural network. Such outputs can be used during the model development phase to ensure compatibility between the layers of a neural network, for understanding and learning about the architecture of pre-trained models and for documentation purposes.

## 5 Discussion

Drawing from the results of this study, we discuss implications and future work in this section.

## 5.1 Documentation and Technical Debt

Jupyter notebooks are primarily used to explore different ideas or approaches, often neglecting software development best practices in favour of rapid experimentation (Kery et al., 2018; Rule et al., 2018; Pimentel et al., 2019). Once the code is finalized, it is typically transferred into a script that is run in a production environment. Alternatively, the notebook may contain significant exploratory work such as developing a model or performing data exploration. To effectively communicate the information present in the notebooks with clients, collaborators or teammates, the practitioners add annotations and structure to the notebook using markdown cells (Kery et al., 2018; Rule et al., 2018). In both scenarios, practitioners need to revisit the notebooks to obtain upto-date and accurate requirements, their rationale and design decisions, and tests-artefacts which are usually missing in the original notebooks (Pimentel et al., 2019; Psallidas et al., 2019; Grotov et al., 2022).

Our findings indicate that structured information can be effectively derived from the feedback mechanisms available in Jupyter notebooks. The results demonstrate that practitioners utilise assertions, print statements, code cell outputs, and visualisations to inform data preprocessing techniques, detect erroneous assumptions, create new features to enhance model performance, and verify hardware and software dependencies. As data, personnel, and system environments inevitably change, undocumented decisions can lead to accumulation of technical debt. This not only prolongs time required for debugging and troubleshooting, but also incurs additional costs and resource expenditures (Sculley et al., 2015; Amershi et al., 2019; Sambasivan et al., 2021).

Our results from RQ3 reveal that implicit feedback from print and last cell statements are used in Jupyter notebooks to make design and implementation decisions throughout the machine learning development lifecycle. Unlike assertions, undocumented decisions based on implicit feedback mechanisms incur higher technical debt since they don't stop the execution despite violating the underlying assumptions of the code.

We recommend that ML practitioners document insights derived from implicit feedback mechanisms, especially for visualizations. Visual cues and trends in visualizations are open to interpretation, meaning that different practitioners may interpret the same plot differently (Heer et al., 2010). By documenting these visual insights, practitioners can ensure that the knowledge encapsulated in the visualizations, along with its interpretation and the subsequent decisions made, is preserved and consistently applied throughout the ML lifecycle. Although writing documentation from implicit and explicit feedback mechanisms still requires significant manual effort and resources, the dataset contributed by this study provides a valuable resource for ongoing efforts to automatically generate documentation from code written in Jupyter notebooks (Yang et al., 2021).

## 5.2 Automated Data Validation

Catching data errors are critical since ML models trained using dirty data will lead to poor and incorrect predictions. This is a cause for concern since these models may be deployed in production and their output may be used by other services which will then also perform poorly. The output of the ML models are often also used to capture new training data, thus leading to a feedback loop which over time will degrade the model performance (Sculley et al., 2015; Breck et al., 2019).

Breck et al. (2017) view ML training as analogous to compilation and recommend that training data be tested, similar to code in traditional software. They propose a rubric to assess the production readiness of an ML pipeline, which includes several recommendations for data testing. In subsequent work, Breck et al. (2019) introduce TensorFlow Data Validation , an automated tool for data validation that works on principles borrowed from the database community. Data expectations are specified in a schema, and each new data batch

is validated against this schema to ensure it meets the expected criteria or prompts schema updates if requirements change.

The results from RQ2 indicate that assertions can be used to automatically validate critical assumptions in ML workflows. Embedding assertions into the code helps ensure that any deviation from expected conditions is promptly flagged. This reduces the reliance on manual verification thus enhancing the robustness and maintainability of ML pipelines. Assertions also serve as an executable form of documentation that captures the assumptions and decisions made during model development. This is particularly important in collaborative environments where multiple practitioners might work on the same project. Assertions ensure that all team members have a clear understanding of the requirements and constraints across the entire ML pipeline, facilitating smoother transitions and handovers. Moreover, assertions may enhance the reproducibility of ML experiments by ensuring that the same validation checks are applied consistently, regardless of the execution order of the notebook cells (Wang et al., 2020b).

Results from RQ2 and RQ3 show that assertions, print statements and last cell statements are predominantly used in the upstream, data-intensive stages of the MLDL. For instance, this study identifies several assertions that perform data validation checks to ensure data meets specific criteria or constraints. Similarly, we find assertions, print statements, and last cell statements that conduct type, shape, and distribution checks to safeguard against data inconsistencies. These results show a missed opportunity in data validation tasks. We argue that when integrating dedicated data validation tools into an operational ML pipeline, the existing feedback mechanisms in notebooks can be effectively used to write the data validation schema.

## 5.3 ML Testing Literacy

Despite the potential benefits, our results from RQ1 reveal that assertions are not widely used in Jupyter notebooks. The relatively low adoption rate compared to implicit feedback mechanisms, suggests that there is significant room for growth and improvement in the integration of assertions into ML development workflows.

We hypothesize that this limited use of assertions is due to a lack of knowledge among practitioners regarding testing approaches and the absence of adequate tooling to support the assertion of data and model properties. Guidelines and curricula on ML coding practices have historically focused on building better models. We argue that the focus must shift towards building reliable ML-enabled systems by incorporating decades of research from the software engineering community with ML. Our recommendation is evident in the recent developments within the software engineering research community that steer education and research towards addressing the specific challenges faced when developing ML-enabled software systems (K¨stner and Kang, 2020). Fostering a a deeper understanding of testing practices and providing tools tailored to ML

development can help promote more rigorous and reliable testing methodologies within the community.

The assertions analysed in RQ1 and RQ2 further reveal two significant challenges in the current landscape of testing in ML Jupyter notebooks. First, the assertions identified in this study lack the support of dedicated testing libraries. This suggests that the culture of testing ML code is still in its infancy, and ML practitioners are not yet fully exploring or leveraging software testing libraries. Secondly, existing testing libraries are not specifically tuned to the needs of ML code, leading practitioners to rely on basic built-in approaches. This highlights the necessity for developing specialized testing frameworks that cater to the unique requirements of ML projects.

## 5.4 Machine Learning Bugs

The findings of this study align with prior research on real-world defects in ML systems. Humbatova et al. (2020) propose a taxonomy of faults in DL systems, while Morovati et al. (2023) curate Defects4ML , a dataset consisting of ML bugs. Both studies identify defects arising from the use of incorrect data types and shapes, deprecated APIs, and missing GPU resources. Our study identifies several explicit assertions that can catch such data errors. Additionally, we find several implicit checks performed using print and last cell statements to verify the presence of compute resources and libraries, monitor model training, and check the architecture of neural networks.

This study further reveals several avenues for research. We primarily focused on identifying feedback mechanisms used when writing ML code in Jupyter notebooks and subsequently exploring a limited subset of them. Further research is required to explore the feedback mechanisms in more detail and organize the knowledge into a taxonomy based on specific ML validation tasks. Future work can focus on mapping the feedback mechanisms in Jupyter notebooks to the ML defects identified by Humbatova et al. (2020) and Morovati et al. (2023) which can aid practitioners in debugging or preventing faults using the appropriate feedback technique.

## 5.5 Code Quality and Conformance to Standards

Results from RQ1 show that 68% of the assertions do not contain a failure message. This can lead to problems such as unclear error diagnostics, difficulty in debugging, and increased time to identify and resolve issues. Vidoni (2021) investigated the testing culture in open-source R packages and identified several anti-patterns that lead to the accumulation of testing technical debt. The dataset contributed by this study can be used by researchers to replicate the Vidoni (2021) study using assertions written in Python.

## 6 Threats to Validity

Internal Validity This study examines Jupyter notebooks written in Python, specifically focusing on machine learning code. We do this by only considering notebooks that utilize popular ML libraries. Consequently, we may miss notebooks that are ML-related but do not use these specific libraries. Additionally, notebooks that import popular ML libraries but do not actively use them in the code could lead to misclassification. To mitigate this threat, we specifically look for ML libraries that facilitate model training rather than more generalpurpose libraries such as pandas, numpy, and scipy, which can be used for a variety of non-ML tasks.

We enforced a time resource limit of 200 hours for conducting the case studies in RQ2 and RQ3, potentially constraining the depth and breadth of our investigation. The stratified random sampling used for selecting the case study candidates mitigates this threat by ensuring that a representative cross-section of the population is sampled within the time constraint. While this sampling method enhances the generalizability of our results, the time limitation should still be considered when interpreting and applying the study's findings.

The case studies conducted in RQ2 and RQ3 are subject to bias from the first author's individual perspective and understanding which could limit the interpretation of data and potentially overlook alternative viewpoints or explanations. To mitigate this threat, we implemented a rigorous review process involving multiple rounds of discussion with the second and third authors. These discussions continued until a consensus was reached on the interpretations and findings.

External Validity Our analysis is based on ML notebooks publicly available on GitHub and Kaggle. Consequently, the findings may not be generalizable to Python notebooks that do not concentrate on ML. Additionally, the results may not be applicable to notebooks authored in other statistical programming languages (such as R or Julia), or to proprietary notebooks hosted on different platforms.

## 7 Related Work

## 7.1 Assertions and Software Bugs

Kochhar and Lo (2017) conducted a partial replication of a prior study on assertion usage, expanding the analysis to 185 Java projects from GitHub. Vidoni (2021) conducted a comprehensive study on the unit testing practices within 177 systematically selected open-source R packages hosted on GitHub. The research addressed the quality of testing, identified testing goals, and pinpointed potential sources of testing technical debt.

Humbatova et al. (2020) developed a comprehensive taxonomy of faults in deep learning systems through the manual analysis of 1059 artefacts from

GitHub and Stack Overflow, complemented by structured interviews with 20 researchers and practitioners. The study categorized faults into five top-level categories, encompassing model, data, training, deployment, and infrastructurerelated faults. Morovati et al. (2023) addressed the challenge of assessing the quality and performance of tools designed to improve the reliability of machine learning components by creating a standard fault benchmark called defect4ML. This benchmark consists of 100 reproducible bugs reported by ML developers on GitHub and Stack Overflow, focusing on the TensorFlow and Keras ML frameworks.

In contrast to prior work, our research focuses on the feedback mechanisms used within Jupyter notebooks for ML development. While previous work has provided insights into assertion usage and fault taxonomies, our study specifically examines the role of implicit and explicit feedback in ensuring data and model integrity within interactive development environment provided by Jupyter notebooks.

## 7.2 Computational Notebooks and Software Engineering

Psallidas et al. (2019) provide an overview of the evolving landscape of computational notebooks by analysing six million Python notebooks, two million enterprise Data Science (DS) pipelines, source code and metadata from over 900 releases of 12 important DS libraries. Their findings can be used by system builders for improving DS tools and also by DS practitioners to understand the current trends in technologies they should focus on. Pimentel et al. (2019) mined 1.4 million notebooks from GitHub to conduct an empirical study on the coding practices in computational notebooks. Based on their analysis, the authors propose guidelines on improving reproducibility of computational notebooks. To enable future research on computational notebooks, Quaranta et al. (2021) mine Kaggle and present KGTorrent , a public dataset consisting of approximately 250 thousand Jupyter notebooks written in Python. The dataset also contains a relational database dump of metadata regarding publicly available notebooks on Kaggle.

Studies with human subjects have been conducted to gain a deeper understanding of the challenges faced by ML practitioners when developing ML models inside notebooks. The results indicate that ML practitioners work in a highly iterative fashion, often experimenting with multiple strategies to analyse the data or produce meaningful visualizations (Kandel et al., 2012; Kery et al., 2018; Liu et al., 2019; Chattopadhyay et al., 2020). Studies have also been conducted to understand how practitioners generate, evaluate and manage alternative hypothesis, visual designs, methods, tools, algorithms and data sources to arrive at the final implementation (Liu et al., 2019; Kandel et al., 2012). The findings from these studies can be used as guidelines for improving existing notebook technologies or designing new ones.

To manage and prune multiple versions of code that accumulate over time when developing in notebooks, Head et al. (2019) propose a code gathering

tool that allows practitioners to review and only keep the relevant version of code. Other tools such as WrangleDoc and VizSmith have also been proposed to aid ML practitioners when working within computational notebooks (Yang et al., 2021; Bavishi et al., 2021).

Jupyter notebooks have been widely adopted by the DS and ML communities to develop ML pipelines (Wang et al., 2020b; Pimentel et al., 2019; Quaranta et al., 2021). Computational notebooks provide a rich source of data in the form of natural text, code and visualizations. Computational notebooks also allow ML practitioners to present the knowledge gained from the analysis in a narrative that can be shared with others (Rule et al., 2018).

Our study builds on this foundation by focusing on the specific feedback mechanisms used within Jupyter notebooks during ML development. We examine both implicit and explicit feedback methods, providing a detailed analysis of their usage and effectiveness in maintaining robust ML workflows.

## 7.3 ML Testing

Existing scientific literature on ML testing broadly focuses on two aspects. First, on functional properties such as correctness and robustness of the model towards unseen data. And second, on non-functional properties such as fairness, interpretability and privacy (Zhang et al., 2022; Mehrabi et al., 2021; Chen et al., 2022).

To test the correctness of ML models, several improvements over existing test adequacy metrics have been proposed. Tools such as DeepXplore and DeepGauge propose new test adequacy metrics such as neuron coverage adapted for ML enabled software systems (Pei et al., 2017; Ma et al., 2018; Gerasimou et al., 2020). Formal verification methods have also been proposed that try to provide formal guarantee of robustness against adversarial examples. Such methods however are only feasible for statistical ML models and become computationally expensive for more complex models such as deep neural networks (Zhu et al., 2021; Baluta et al., 2021). Several studies have been conducted on generating and detecting adversarial inputs for ML models. Data augmentation techniques based on fuzzing, search based software testing and mutation testing have been proposed to generate adversarial examples that can be used during model training to improve its robustness (Braiek and Khomh, 2019; Gao et al., 2020; Wang et al., 2021; Zhang et al., 2020). It is however not possible to include all variations of adversarial examples into the training data. Thus, methods have been proposed to detect adversarial inputs during runtime (Xiao et al., 2021; Wang et al., 2020a, 2019; Berend et al., 2020).

Despite these advancements, there is a notable gap in practical, day-to-day testing practices within ML development environments. Our study addresses this gap by analysing the feedback mechanisms in Jupyter notebooks, highlighting how assertions and print statements are used to validate data and model performance, and proposing ways to integrate these practices more effectively into the ML development lifecycle.

## 7.4 Visualizations and Machine Learning

As ML augment software systems in safety-critical domains, emphasis has been put into explainability of ML models. ML models and the underlying data is complex and multidimensional. To combat the 'curse of dimensionality', visual analytics has been widely adopted by the ML community to understand the data and the internal workings of ML models (Yuan et al., 2021; Hohman et al., 2019; Wexler et al., 2019).

Prior studies have been conducted to understand how visual analytics techniques are currently being used in ML. Yuan et al. (2021) conduct a systematic review of 259 papers and propose a taxonomy of visual analytics techniques for ML. Hohman et al. (2019) conduct a survey of visual analytics techniques for Deep Learning Models. The findings of the study indicate that visual analytics has been widely adopted in ML for model explanation, interpretation, debugging and improvement.

Several tools have been proposed by the visual analytics research community to aid practitioners in understanding how their ML models operate. Wexler et al. (2019) propose What-If , a visual analytics tool to explore alternative hypotheses, generate counterfactual reasoning, investigate decision boundaries of the model and how change in data affects the model predictions. To reduce the cognitive load of ML practitioners during model building phase, Amershi et al. (2019) propose ModelTracker . Given a trained model and a sample dataset, ModelTracker presents all the information in traditional summary statistics along with the performance of the model.

ESCAPE GAM Coach Angler , , and Drava are a few other tools that have been proposed to handle specialized use-cases such as identifying systematic errors in ML models, generating counterfactual explanations for Generalized Additive Models, prioritizing machine translation model improvements and relating human concepts with semantic dimensions extracted by ML models during disentangled representation learning (Ahn et al., 2023; Wang et al., 2023b; Robertson et al., 2023; Wang et al., 2023a).

Unlike prior work that focuses on standalone visual analytics tools, our study explores how visualizations within Jupyter notebooks are used by ML practitioners. We analyse the motivations behind creating these visualizations and the insights they provide, offering a nuanced understanding of their role in the iterative ML development process.

## 8 Conclusion

This study provides a comprehensive analysis of feedback mechanisms employed within Jupyter notebooks during the machine learning development lifecycle. Our findings indicate that while implicit feedback mechanisms such as print statements and last cell statements are extensively utilized, there is a significant gap in the adoption of explicit feedback mechanisms like assertions. This reliance on manual validation highlights the potential for auto-

mated data validation to enhance the robustness and maintainability of ML pipelines. This study also underscores the necessity for better documentation practices to mitigate technical debt and ensure the reproducibility of ML experiments. Feedback mechanisms are used throughout the ML development workflow to achieve more reliable and efficent model development processes. Future work should focus on developing specialized tools and frameworks to support these practices, thereby advancing the field of ML engineering.

## References

Abadi M, Agarwal A, Barham P, Brevdo E, Chen Z, Citro C, Corrado GS, Davis A, Dean J, Devin M, Ghemawat S, Goodfellow I, Harp A, Irving G, Isard M, Jia Y, Jozefowicz R, Kaiser L, Kudlur M, Levenberg J, Man´ e D, Monga R, Moore S, Murray D, Olah C, Schuster M, Shlens J, Steiner B, Sutskever I, Talwar K, Tucker P, Vanhoucke V, Vasudevan V, Vi´ egas F, Vinyals O, Warden P, Wattenberg M, Wicke M, Yu Y, Zheng X (2015) TensorFlow: Large-scale machine learning on heterogeneous systems. URL

- https://www.tensorflow.org/ , software available from tensorflow.org

Ahn Y, Lin YR, Xu P, Dai Z (2023) Escape: Countering systematic errors from machine's blind spots via interactive visual analysis. In: Proceedings of the 2023 CHI Conference on Human Factors in Computing Systems, pp 1-16

Amershi S, Begel A, Bird C, DeLine R, Gall H, Kamar E, Nagappan N, Nushi B, Zimmermann T (2019) Software engineering for machine learning: A case study. In: 2019 IEEE/ACM 41st International Conference on Software Engineering: Software Engineering in Practice (ICSESEIP), IEEE, DOI 10.1109/icse-seip.2019.00042, URL https://doi.org/ 10.1109/icse-seip.2019.00042

Baluta T, Chua ZL, Meel KS, Saxena P (2021) Scalable quantitative verification for deep neural networks. In: 2021 IEEE/ACM 43rd International Conference on Software Engineering (ICSE), IEEE, pp 312-323

Bavishi R, Laddad S, Yoshida H, Prasad MR, Sen K (2021) Vizsmith: Automated visualization synthesis by mining data-science notebooks. In: 2021 36th IEEE/ACM International Conference on Automated Software Engineering (ASE), IEEE, pp 129-141

Berend D, Xie X, Ma L, Zhou L, Liu Y, Xu C, Zhao J (2020) Cats are not fish: Deep learning testing calls for out-of-distribution awareness. In: Proceedings of the 35th IEEE/ACM International Conference on Automated Software Engineering, pp 1041-1052

Betz C (2018) Managing digital: Concepts and practices. URL https://pubs.opengroup.org/opengrouppress/managing-digital/ chapter-app-deliv.html , [Online; accessed 2024-05-05]

Braiek HB, Khomh F (2019) Deepevolution: A search-based testing approach for deep neural networks. In: 2019 IEEE International Conference on Software Maintenance and Evolution (ICSME), IEEE, pp 454-458

Breck E, Cai S, Nielsen E, Salib M, Sculley D (2017) The ml test score: A rubric for ml production readiness and technical debt reduction. In: 2017 IEEE International Conference on Big Data (Big Data), IEEE, pp 11231132

Breck E, Polyzotis N, Roy S, Whang S, Zinkevich M (2019) Data validation for machine learning. In: MLSys

- Chattopadhyay S, Prasad I, Henley AZ, Sarma A, Barik T (2020) What's wrong with computational notebooks? pain points, needs, and design opportunities. In: Proceedings of the 2020 CHI conference on human factors in computing systems, pp 1-12

Chen Z, Zhang JM, Hort M, Sarro F, Harman M (2022) Fairness testing: A comprehensive survey and analysis of trends. arXiv e-prints pp arXiv-2207 Chollet F, et al. (2015) Keras. https://keras.io

Gao X, Saha RK, Prasad MR, Roychoudhury A (2020) Fuzz testing based data augmentation to improve robustness of deep neural networks. In: 2020 IEEE/ACM 42nd International Conference on Software Engineering (ICSE), IEEE, pp 1147-1158

Gerasimou S, Eniser HF, Sen A, Cakan A (2020) Importance-driven deep learning system testing. In: 2020 IEEE/ACM 42nd International Conference on Software Engineering (ICSE), IEEE, pp 702-713

Grotov K, Titov S, Sotnikov V, Golubev Y, Bryksin T (2022) A large-scale comparison of python code in jupyter notebooks and scripts. In: Proceedings of the 19th International Conference on Mining Software Repositories, ACM, MSR '22, DOI 10.1145/3524842.3528447, URL http://dx.doi.org/ 10.1145/3524842.3528447

Haakman M, Cruz L, Huijgens H, van Deursen A (2021) Ai lifecycle models need to be revised: An exploratory study in fintech. Empirical Software Engineering 26(5), DOI 10.1007/s10664-021-09993-1, URL http://dx.doi. org/10.1007/s10664-021-09993-1

Head A, Hohman F, Barik T, Drucker SM, DeLine R (2019) Managing messes in computational notebooks. In: Proceedings of the 2019 CHI Conference on Human Factors in Computing Systems, pp 1-12

Heer J, Bostock M, Ogievetsky V (2010) A tour through the visualization zoo. Communications of the ACM 53(6):59-67, DOI 10.1145/1743546.1743567, URL http://dx.doi.org/10.1145/1743546.1743567

Hohman F, Kahng M, Pienta R, Chau DH (2019) Visual analytics in deep learning: An interrogative survey for the next frontiers. IEEE Transactions on Visualization and Computer Graphics 25(8):2674-2693, DOI 10.1109/ tvcg.2018.2843369, URL https://doi.org/10.1109/tvcg.2018.2843369 P ProceedEnhttp:

Humbatova N, Jahangirova G, Bavota G, Riccio V, Stocco A, Tonella (2020) Taxonomy of real faults in deep learning systems. In: ings of the ACM/IEEE 42nd International Conference on Software gineering, ACM, ICSE '20, DOI 10.1145/3377811.3380395, URL //dx.doi.org/10.1145/3377811.3380395

Kandel S, Paepcke A, Hellerstein JM, Heer J (2012) Enterprise data analysis and visualization: An interview study. IEEE transactions on visualization

and computer graphics 18(12):2917-2926

Kery MB, Radensky M, Arya M, John BE, Myers BA (2018) The story in the notebook: Exploratory data science using a literate programming tool. In: Proceedings of the 2018 CHI conference on human factors in computing systems, pp 1-11

Knuth DE (1984) Literate programming. The Computer Journal 27(2):97-111, DOI 10.1093/comjnl/27.2.97, URL http://dx.doi.org/10.1093/comjnl/ 27.2.97

Kochhar PS, Lo D (2017) Revisiting assert use in github projects. In: Proceedings of the 21st International Conference on Evaluation and Assessment in Software Engineering, ACM, EASE'17, DOI 10.1145/3084226.3084259, URL http://dx.doi.org/10.1145/3084226.3084259

K¨ astner C, Kang E (2020) Teaching software engineering for ai-enabled systems. URL https://arxiv.org/abs/2001.06691 , 2001.06691

Liu J, Boukhelifa N, Eagan JR (2019) Understanding the role of alternatives in data analysis practices. IEEE transactions on visualization and computer graphics 26(1):66-76

Ma L, Juefei-Xu F, Zhang F, Sun J, Xue M, Li B, Chen C, Su T, Li L, Liu Y, et al. (2018) Deepgauge: Multi-granularity testing criteria for deep learning systems. In: Proceedings of the 33rd ACM/IEEE international conference on automated software engineering, pp 120-131

Martinez-Plumed F, Contreras-Ochando L, Ferri C, Hernandez-Orallo J, Kull M, Lachiche N, Ramirez-Quintana MJ, Flach P (2021) CRISP-DM twenty years later: From data mining processes to data science trajectories. IEEE Transactions on Knowledge and Data Engineering 33(8):3048-3061, DOI 10. 1109/tkde.2019.2962680, URL http://dx.doi.org/10.1109/TKDE.2019. 2962680

Mehrabi N, Morstatter F, Saxena N, Lerman K, Galstyan A (2021) A survey on bias and fairness in machine learning. ACM Computing Surveys (CSUR) 54(6):1-35

Morovati MM, Nikanjam A, Khomh F, Jiang ZM (2023) Bugs in machine learning-based systems: a faultload benchmark. Empirical Software Engineering 28(3), DOI 10.1007/s10664-023-10291-1, URL http://dx.doi. org/10.1007/s10664-023-10291-1

Paszke A, Gross S, Chintala S, Chanan G, Yang E, DeVito Z, Lin Z, Desmaison A, Antiga L, Lerer A (2017) Automatic differentiation in pytorch

Pedregosa F, Varoquaux G, Gramfort A, Michel V, Thirion B, Grisel O, Blondel M, Prettenhofer P, Weiss R, Dubourg V, Vanderplas J, Passos A, Cournapeau D, Brucher M, Perrot M, Duchesnay E (2011) Scikit-learn: Machine learning in Python

Pei K, Cao Y, Yang J, Jana S (2017) Deepxplore: Automated whitebox testing of deep learning systems. In: proceedings of the 26th Symposium on Operating Systems Principles, pp 1-18

Perkel JM (2018) Why jupyter is data scientists' computational notebook of choice. Nature 563(7729):145-146, DOI 10.1038/d41586-018-07196-1, URL http://dx.doi.org/10.1038/d41586-018-07196-1

- Pimentel JF, Murta L, Braganholo V, Freire J (2019) A large-scale study about quality and reproducibility of jupyter notebooks. In: 2019 IEEE/ACM 16th international conference on mining software repositories (MSR), IEEE, pp 507-517
- Psallidas F, Zhu Y, Karlas B, Interlandi M, Floratou A, Karanasos K, Wu W, Zhang C, Krishnan S, Curino C, et al. (2019) Data science through the looking glass and what we found there. arXiv preprint arXiv:191209536
- Quaranta L, Calefato F, Lanubile F (2021) Kgtorrent: A dataset of python jupyter notebooks from kaggle. In: 2021 IEEE/ACM 18th International Conference on Mining Software Repositories (MSR), IEEE, pp 550-554

Robertson S, Wang ZJ, Moritz D, Kery MB, Hohman F (2023) Angler: Helping machine translation practitioners prioritize model improvements. In: Proceedings of the 2023 CHI Conference on Human Factors in Computing Systems, pp 1-20

Rule A, Tabard A, Hollan JD (2018) Exploration and explanation in computational notebooks. In: Proceedings of the 2018 CHI Conference on Human Factors in Computing Systems, pp 1-12

Sambasivan N, Kapania S, Highfill H, Akrong D, Paritosh P, Aroyo LM (2021) 'everyone wants to do the model work, not the data work': Data cascades in high-stakes ai. In: proceedings of the 2021 CHI Conference on Human Factors in Computing Systems, pp 1-15

- Sculley D, Holt G, Golovin D, Davydov E, Phillips T, Ebner D, Chaudhary V, Young M, Crespo JF, Dennison D (2015) Hidden technical debt in machine learning systems. Advances in neural information processing systems 28:2503-2511

Shome A, Cruz L, van Deursen A (2022) Data smells in public datasets. In: Proceedings of the 1st International Conference on AI Engineering: Software Engineering for AI, ACM, CAIN '22, DOI 10.1145/3522664.3528621, URL http://dx.doi.org/10.1145/3522664.3528621

Vidoni M (2021) Evaluating unit testing practices in r packages. In: 2021 IEEE/ACM 43rd International Conference on Software Engineering (ICSE), IEEE, DOI 10.1109/icse43902.2021.00136, URL http://dx.doi.org/10. 1109/ICSE43902.2021.00136

Wang H, Xu J, Xu C, Ma X, Lu J (2020a) Dissector: Input validation for deep learning applications by crossing-layer dissection. In: 2020 IEEE/ACM 42nd International Conference on Software Engineering (ICSE), IEEE, pp 727738

Wang J, Dong G, Sun J, Wang X, Zhang P (2019) Adversarial sample detection for deep neural network through model mutation testing. In: 2019 IEEE/ACM 41st International Conference on Software Engineering (ICSE), IEEE, pp 1245-1256

- Wang J, Kuo Ty, Li L, Zeller A (2020b) Assessing and restoring reproducibility of jupyter notebooks. In: Proceedings of the 35th IEEE/ACM International Conference on Automated Software Engineering, pp 138-149
- Wang J, Chen J, Sun Y, Ma X, Wang D, Sun J, Cheng P (2021) Robot: robustness-oriented testing for deep learning systems. In: 2021 IEEE/ACM

43rd International Conference on Software Engineering (ICSE), IEEE, pp 300-311

Wang Q, L'Yi S, Gehlenborg N (2023a) Drava: Aligning human concepts with machine learning latent dimensions for the visual exploration of small multiples. In: Proceedings of the 2023 CHI Conference on Human Factors in Computing Systems, pp 1-15

Wang ZJ, Wortman Vaughan J, Caruana R, Chau DH (2023b) Gam coach: Towards interactive and user-centered algorithmic recourse. In: Proceedings of the 2023 CHI Conference on Human Factors in Computing Systems, pp 1-20

Wexler J, Pushkarna M, Bolukbasi T, Wattenberg M, Viegas F, Wilson J (2019) The what-if tool: Interactive probing of machine learning models. IEEE Transactions on Visualization and Computer Graphics p 1-1, DOI 10. 1109/tvcg.2019.2934619, URL http://dx.doi.org/10.1109/TVCG.2019. 2934619

Xiao Y, Beschastnikh I, Rosenblum DS, Sun C, Elbaum S, Lin Y, Dong JS (2021) Self-checking deep neural networks in deployment. In: 2021 IEEE/ACM 43rd International Conference on Software Engineering (ICSE), IEEE, pp 372-384

Yang C, Zhou S, Guo JL, K¨ astner C (2021) Subtle bugs everywhere: Generating documentation for data wrangling code. In: 2021 36th IEEE/ACM International Conference on Automated Software Engineering (ASE), IEEE, pp 304-316

Yuan J, Chen C, Yang W, Liu M, Xia J, Liu S (2021) A survey of visual analytics techniques for machine learning. Computational Visual Media 7:336

Zhang JM, Harman M, Ma L, Liu Y (2022) Machine learning testing: Survey, landscapes and horizons. IEEE Transactions on Software Engineering 48(1):1-36, DOI 10.1109/tse.2019.2962027, URL http://dx.doi.org/10. 1109/TSE.2019.2962027

Zhang P, Wang J, Sun J, Dong G, Wang X, Wang X, Dong JS, Dai T (2020) White-box fairness testing through adversarial sampling. In: Proceedings of the ACM/IEEE 42nd International Conference on Software Engineering, pp 949-960

Zhu D, Chen J, Shang W, Zhou X, Grossklags J, Hassan AE (2021) Deepmemory: Model-based memorization analysis of deep neural language models. In: 2021 36th IEEE/ACM International Conference on Automated Software Engineering (ASE), IEEE, pp 1003-1015
Arumoy Shome Luis Cruz Diomidis Spinellis Arie van Deursen
Understanding Feedback Mechanisms in Machine Learning Jupyter Notebooks
The machine learning development lifecycle is characterized by iterative and
exploratory processes that rely on feedback mechanisms to ensure data and model
integrity. Despite the critical role of feedback in machine learning
engineering, no prior research has been conducted to identify and understand
these mechanisms. To address this knowledge gap, we mine 297.8 thousand Jupyter
notebooks and analyse 2.3 million code cells. We identify three key feedback
mechanisms -- assertions, print statements and last cell statements -- and
further categorize them into implicit and explicit forms of feedback. Our
findings reveal extensive use of implicit feedback for critical design
decisions and the relatively limited adoption of explicit feedback mechanisms.
By conducting detailed case studies with selected feedback instances, we
uncover the potential for automated validation of critical assumptions in ML
workflows using assertions. Finally, this study underscores the need for
improved documentation, and provides practical recommendations on how existing
feedback mechanisms in the ML development workflow can be effectively used to
mitigate technical debt and enhance reproducibility.