Brandon Rohrer

Brandon Rohrer

@brandonrohrer.com

Robotics and Reinforcement Learning tinkerer. brandonrohrer.org Wrangler of algorithms. Eater of bread. Sipper of whisky. Reports to a Shih Tzu.

3.7K followers2.2K following998 posts

One big step forward is the addition of additive smoothing (alpha) and upward-biased additive smoothing (beta) parameters. These helped to avoid false detections and increase precision - an important precursor to building ensemble models.

The other big step was choosing a per-model optimization criterion, F-rho. This allowed a two-phase hyperparameter optimization approach where individual models were tuned before being combined. That leaves fewer free hyperparameters in the ensemble, making that secondary tuning more practicable.

View full thread

Usage 1. Start with an evaluation function def evaluate(*, a, b, c): return a * b**3 % c (The leading * tells Python that everything that follows is a required keyword argument) 2. Build a collection of values to try for each parameter values = {"a": [4, 7, 9], "b": [2, 5, 6], "c": [5, 8, 11]}

3. Call the optimizer from redsho.optimizer import optimize error, params = optimize(evaluate, values) where error is the lowest error achieved, and params is the parameter values that achieved it.

Cool Python trick: Sometimes you want functions to have keyword arguments, but you also want them to be required. This is especially useful when you're passing required arguments using dictionary expansion, like `function(**arg_dict)`.

View full thread

This means that now when I write ``` def sum(*, a=None, b=None): return a + b ``` I no longer have to check that `a` and `b` are not `None` in the function, and I can call it with ``` arg_dict = {'a': 4, 'b': 9} print(sum(**arg_dict)) ```

You can still put positional and optional keywords before the asterisk. `def estimate(a, b, verbose=False, *, method=None, n_iter=None):` It doesn't matter what default value these required kwargs get because it will always be overwritten.

Cool Python trick: Sometimes you want functions to have keyword arguments, but you also want them to be required. This is especially useful when you're passing required arguments using dictionary expansion, like `function(**arg_dict)`.

I always did this by setting all the parameter keyword defaults to `None`, then checking for any `None` values in the function. But there's a better way: using the bare `*` in the argument list. Everything after the `*` will be a required keyword argument.

Optimizing models with lots of hyperparameters and options is a slog that usually requires a combination community wisdom, obscure blog posts, and tedious trial and error. Automated methods tend to rely on strong assumptions of smoothness or brute force their way through every permutation.

View full thread

Optimizing models with lots of hyperparameters and options is a slog that usually requires a combination community wisdom, obscure blog posts, and tedious trial and error. Automated methods tend to rely on strong assumptions of smoothness or brute force their way through every permutation.

All of these options kind of suck. I couldn't find a solution I liked to this problem so I built one: redsho, a robust evolutionary direction set hyperparameter optimizer.

redsho takes a middle ground approach for when the effects of parameters and options can be wildly non-linear and exhaustive grid search would take longer than we want to spend. Its distinguishing feature is that it is evolutionary in nature.

I steer them away from false positives with a variation of additive smoothing that includes a strong upward bias. P(AB|A) = count(AB) + beta / count(A) + beta Whether this is a "hack" or a "method" will depend on how important it ends up being in the proofreader's performance.

Perfect for sitting down with a hot beverage for a few minutes a day and letting the current flow around you. (No promotional consideration here. I paid full price and I regret nothing.)

There are several command line incantations that I have had to look up at least a dozen times. Finding a string in Python files grep -r --include \*.py 'string I am looking for' . Find files by name find . -name '*partial_name*'

Find and replace all occurrences of a string in a directory's Python files sed -i '.bak' -e 's/old string/new string/g' *.py To drill deeper on any of these run man <command>. I find the examples section at the end most helpful. I'm compiling a list of these here brandonrohrer.org/shell_tricks...

brandonrohrer.orgbrandonrohrer.orgThere are several command line incantations that I have had to look up at least a dozen times. I'm compiling a handy cheat sheet of them here.

Heads up ruff users - with the release of 0.16.0 this week the number of default rules went up from 59 to to 413. This means that if you're ruff version auto updates, your CI pipelines might start failing on you all of a sudden.

Simon Willison@simonwillison.net

Ruff 0.16.0 - Astral's fast Python linter - came out a few days ago and increased the number of default-enabled rules from 59 to 413, which highlighted all sorts of problems across my projects (1618 in sqlite-utils alone) simonwillison.net/2026/Jul/25/...

If you want to avoid this you can pin your ruff version to 0.15.22. And for those who track such things, the last ruff release (Mar 12) before the OpenAI acquisition announcement (Mar 19) was 0.15.6

Living small is part of the artisanal process. The constraints are not a barrier to the final product. They are an important shaping force. You can't come in at the end and magically shrink it. You can only build small if you start small and work with what you've got as you go. brandonrohrer.org

the biggest difference I've noticed between data scientists and machine learning engineers is that MLEs will do absolutely anything to avoid looking at their data

Some are minor tweaks to existing methods, oknn (online k-nearest neighbors). Some are grander in scope, like Ziptie and Cartographer, which give a new way for robots to model their worlds. But they share a thread of curiosity, experimentation, and visceral satisfaction of pieces snapping into place

We never maximize for what will be most efficient over a decade or even a year. No one has the patience for that kind of measurement. Instead of we optimize what can be measured in a week or two, even if that means the whole system crashes and burns before our children are out of primary school.