This is a write-up of some notes from teaching the MIDAS Summer Academy, a program for scientists and engineers to learn AI and data science methods with the goal of helping them advance their research. I run the second week of the program, after mathematical theory foundations, about putting the concepts into practice via Python programming.

Usually when teaching programming, as soon as I call breaktime a line of folks carrying their laptops forms at the podium to get another set of eyes on why their notebook isn’t running (it is almost always a syntax problem). This year, that happened a LOT less. I think this is because we discovered mid-flight that Google Colab has autocomplete on by default? Or students picked up using the Gemini built-in assistant very quickly upon hitting errors–I’m not sure. I do know that some students preferred to turn off the autocomplete default in Colab, because they wanted to practice without it. In any case, there was a truly astounding drop-off in syntax-related notebook-jamming issues this year.

There were a couple flavors of questions that still came up reliably, though, and I think they’re worth mentioning. They seem like desire paths (when you design walkways after observing how people actually cut across a lawn) for curriculum design.

Where does the Colab session begin and end? Students want to know what representations persist after they close their Google Colab instance, what’s on their local machine vs. their Google Drive vs. only inside the notebook session temporarily, and how to get data into and out of the session in a persistent form (data from local .xlsx to Colab, model results to file). Some of this was particular to Colab, but I imagine similar questions about any locally run Python session would occur.

Why is the code written this way? Why doesn’t df.shape have parentheses, why do we pass errors='coerce', why did we specify axis….? This question in all its forms seems to be where students interface with the irreducible complexity of pandas–if we don’t make certain choices explicit, our asks are underspecified to the computer. Students also ran into complexity about data representation (pd.Series vs. pd.DataFrame): an interesting pain point occurred when students tried to run .value_counts(subset = ...) on an object that was actually a pd.Series, and couldn’t figure out why (that argument worked fine just a few lines of code above, when called exactly the same way!) And so it was really unavoidable that at some point, we had to discuss the difference between the two ways Pandas can represent data objects, and we looked in the docs to see the distinction. I’m sure that the Gemini in-notebook assistant could’ve smoothed this over but that would not have been a very satisfying answer.

Is this arbitrary or principled? This came up in the context of embeddings dimensions (why is it 384-long? Could I have asked for any size array to come out of a particular embedding model?) and I suspect is part of the “why did we write the code this way” questions, too. This seems actually a rather important skill for assessing code you didn’t write–having a mental model for how you can distinguish a choice from a convention. I’m not sure I had any good answer for you learn to spot those sort of things other than practice/familiarity/knowing where to look (we know what embedding size to expect because it’s a property of how the model was trained, and we can check it on the model card….).

What is possible to do? Can you get a null count instead of a non-null count, print with commas, glob a bunch of JSON files instead of .csv like in the example, etc….? Perhaps because I’ve been around Python for a while I’m used to the answer being “yes, just a matter of tinkering”…. maybe this is an artifact of some scientific programming languages that students might have been exposed to previously being much stricter?

Untidying Claude’s Code

I also had an observation about a friction Claude Code introduced for me…by removing too much friction. I had excellent experiences using CC to set up continuous integration workflows for all the summer school notebooks: it was a huge upgrade to have student-facing notebooks push automatically upon changes. Drafting code for lessons was tougher than I expected, though: CC often wraps functions in wrappers that print the outputs with a pleasant-to-read format, and this gets in the way of the lesson I want the students to have. For example, while teaching sklearn model evaluation, CC will suggest a function like evaluate_binary_classifier(model, X_test, y_test) that predicts on X_test, then calculates several different metrics and prints them all in a tidy table. Fine. But the first time I am showing someone sklearn, I want them to see the pattern–you take the fitted model object, you use it to make new predictions (see? We are just passing in X_test here….and notice that it doesn’t automatically print anything. Huh, what happened? What shape is y_pred? Why is it that shape?). We then compare those predictions to y_test. And we choose which metric(s) we want to report. I think there is some value in running each step one by one, seeing what comes out (or doesn’t)–at least once, particularly if an agent is going to draft their sklearn pipelines forevermore. Wrapping everything into one convenient function hides too much from the students, I think. It took a fair amount of attention to stay on top of this tendency (especially supervising post-docs, who were also using agents to draft code with my encouragement–next year I will write up a shareable AGENTS.md file with instructions about this).

Other field notes

What infrastructure should we teach in? Colab has obvious advantages for providing a standardized environment that works no matter what university students are coming from. But plenty of folks want — or, for data privacy, have — to work on a local machine, a lab computer, or a cluster, and setting up your workspace for the first time is still a burden (maybe, hopefully less, with agents? Though I’ve yet to actually watch a beginner set up their local Python from scratch with agent assistance to confirm).

When it came time to do an agentic coding demo, I just showed them Claude Code on my local machine, acknowledging that this wasn’t going to be replicable without a Claude license (which feels sad). We could switch to using GitHub Codespaces, but I am concerned about the free tier (and it feels likely to encourage us to move out of notebooks, which is a design choice I’d want to make consciously). I hope there are some more options next year.

How should we teach using hosted model APIs? I wanted to show students how to use an API endpoint in a data processing pipeline (pulling study details from scientific abstracts and then building out an evaluation plan based on Hamel Husain and Shreya Shankar’s evals work ). We used Groq’s free tier models for the demo, but at first, the IP address many of us were on got blocked! I suppose they thought all of us pinging at once was suspicious? We found some workarounds, but it was touch and go for a bit. If anyone has suggestions for teaching around a free-tier API that doesn’t require a credit card, please do send.