Posts in Data-analysis (20 found)

How You Read My Content

A week ago, after chatting with Kev about his own findings , I created a similar survey (which is still open if you want to answer it) to collect a second set of data because why the heck not. Kev’s data showed that 84.5% of responses picked RSS, Fediverse was second at 7.6%, direct visits to the site were third at 5.4%, and email was last at 2.4%. My survey has a slightly different set of options and allows for multiple choices—which is why the % don’t add up to 100—but the results are very similar: This is the bulk of the data, but then there’s a bunch of custom, random answers, some of which were very entertaining to read: So the takeaway is: people still love and use RSS. Which makes sense, RSS is fucking awesome, and more people should use it. Since we’re talking data, I’m gonna share some more information about the numbers I have available, related to this blog and how people follow it. I don’t have analytics, and these numbers are very rough, so my advice is not to give them too much weight. 31 people in the survey said they read content in their inbox, but there are currently 103 people who are subscribed to my blog-to-inbox automated newsletter. RSS is a black box for the most part, and finding out how many people are subscribed to a feed is basically impossible. That said, some services do expose the number of people who are subscribed, and so there are ways to get at least an estimate of how big that number is. I just grabbed the latest log from my server, cleaned the data as best as I could in order to eliminate duplicates and also entries that feel like duplicates, for example: In this case, it’s obvious that those two are the same service, and at some point, one more person has signed up for the RSS. But how about these: All those IDs are different, but what should I do here? Do I keep them all? Who knows. Anyway, after cleaning up everything, keeping only requests for the main RSS feed, I’m left with 1975 subscribers, whatever that means. Are these actual people? Who knows. Running the exact same log file (it’s the NGINX access log from Jan 10th to Jan 13th at ~10AM) through Goaccess, with all the RSS entries removed, tells me the server received ~50k requests from ~8000 unique IPs. 33% of those hits are from tools whose UA is marked as “Unknown” by Goaccess. Same story when it comes to reported OS: 35% is marked as “Unknown”. Another 15% on both of those tables is “Crawlers”, which to me suggests that at least half of the traffic hitting the website directly is bots. In conclusion, is it still worth serving content via RSS? Yes. Is the web overrun by bots? Also yes. Is somebody watching me type these words? Maybe. If you have a site and are going to run a similar experiment, let me know about it, and I’ll be happy to link it here. Also, if you want some more data from my logs, let me know. Thank you for keeping RSS alive. You're awesome. Email me :: Sign my guestbook :: Support for 1$/month :: See my generous supporters :: Subscribe to People and Blogs 80.1% reads the content inside their RSS apps 23.8% uses RSS to get notified, but then read in the browser 10.7% visits the site directly 4.9% reads in their inbox. 1 person said they follow on Mastodon, and I am not on Mastodon, so 🤷‍♂️ 1 person left a very useful message in German, a language I don’t speak, which was quite amusing 1 person lives in my house and looks over my shoulder when I write A couple of people mentioned that they read on RSS but check the site every now and again because they like the website

0 views

Bayes theorem and how we talk about medical tests

We want medical tests to give us a yes or no answer: you have the disease, you're cured. We treat them this way, often. My labs came back saying I'm healthy. I have immunity. I'm sick. Absolutely concrete results. The reality is more complicated, and tests do not give you a yes or no. They give you a likelihood. And most of the time, what the results mean for me , the test taker, is not immediately obvious or intuitive. They can mean something quite the opposite of what they seem. I ran into this recently on a page about celiac disease. The Celiac Disease Foundation has a page about testing for celiac disease . On this page, they give a lot of useful information about what different tests are available, and they point to some other good resources as well. In the section about one of the tests, it says (emphasis original): The tTG-IgA test will be positive in about 93% of patients with celiac disease who are on a gluten-containing diet. This refers to the test's sensitivity , which measures how correctly it identifies those with the disease. The same test will come back negative in about 96% of healthy people without celiac disease. This is the test's specificity . This is great information, and it tells you what you need to start figuring out what your chance of celiac disease is. The next paragraph says this, however: There is also a slight risk of a false positive test result, especially for people with associated autoimmune disorders like type 1 diabetes, autoimmune liver disease, Hashimoto's thyroiditis, psoriatic or rheumatoid arthritis, and heart failure, who do not have celiac disease. And this is where things are a little misleading. It says that there is a "slight risk" of a false positive test result. What do you think of as a slight risk? For me, it's maybe somewhere around 5%, maybe 10%. The truth is, the risk of a false positive is much higher (under many circumstances). When I take a test, I want to know a couple of things. If I get a positive test result, how likely is it that I have the disease? If I get a negative test result, how likely is it that I do not have the disease? The rates of positive and negative results listed above, the sensitivity and specificity, do not tell us these directly. However, they let us to calculate this with a little more information. Bayes' theorem says that . You can read as "the probability of A conditioned on B", or the chance that A happens if we know that B happens. What this formula lets us do is figure out one conditional probability we don't yet know in terms of other ones that we do know. In our case, we would say that is having celiac disease, and is getting a positive test result. This leaves as the chance that if you get a positive test result, that you do have celiac disease, which is exactly what we want to know. To compute this, we need a few more pieces of information. We already know that is 0.93, as we were told this above. And we can find prety easily. Let's say is 0.01, since about 1 in 100 people in the US have celiac disease. Estimates vary from 1 in 200 to 1 in 50, but this will do fine. That leaves us with . We have to compute it from both possibilities. If someone who has celiac disease takes the test, they have a 93% chance of it coming back positive, but they're only 1% of the population. On the other hand, someone without celiac disease has a 4% chance of it coming back positive (96% of the time it gives a true negative), and they're 99% of the population. We use these together to find that . Now we plug it all in! . Neat, 19%! So this says that, if you get a positive test result, you have a 19% chance of having celiac disease? Yes, exactly! It's less than 1 in 5! So if you get a positive test result, you have an 80% chance of it being a false positive. This is quite a bit higher than the aforementioned "slight risk." In fact, it means that the test doesn't so much diagnose you with celiac disease as say "huh, something's going on here" and strongly suggest further testing. Now let's look at the test the other way around, too. How likely is it you don't have celiac disease if you get a negative test result? Here we'd say that A is "we don't have it" and B is "we have a negative test". Doing some other calculations, pulled out of the oven fully baked in cooking show style, we can see that . So if you get a negative test result, you have a 99.9% chance of not having the disease. This can effectively rule it out! But... We know that 7% of people who take this test and do have celiac disease will get a negative result. How does this makes sense? The truth is, things are a little bit deeper. People don't actually present with exactly a 1% chance of having celiac's disease. That would be true if you plucked a random person from the population and subjected them to a blood test. But it's not true if you go to your doctor with GI symptoms which are consistent with celiac disease! If you're being tested for celiac disease, you probably are symptomatic. So that prior probability, ? It's better as something else, but how we set it is a good question. Let's say you present with symptoms highly consistent with celiac disease, and that this gives you a 10% chance of having celiac disease and a 90% chance of it being something else, given these symptoms . This changes the probability a lot. If you get a positive test in this case, then . So now a positive test is a 72% chance of having celiac disease, instead of just 20%. And a negative test here gives you a 10% chance of a false negative, better than the 0.1% chance before. The real question is how we go from symptoms to that prior probability accurately. I spent a lot of 2024 being poked with needles and tested for various diseases while we tried to figure out what was wrong with me. Ultimately it was Lyme disease, and the diagnosis took a while because of a false negative. That false negative happened because the test was calibrated for broad population sampling, not for testing individuals presenting with symptoms already. The whole story is a lot longer, and it's for another post. But maybe, just maybe, it would've been a shorter story if we'd learned reason about probabilities and medical tests better. Things are not intuitive, but Bayes is your friend, and Bayes' theorem can show us the information we really need to know. Or, we can keep going with things how they are. I mean, I did enjoy getting to know Barbara, my phlebotomist, from all my appointments. , the probability in general that the person taking the test has celiac disease. This is also called the prior probability , as it's what we would say the probability is if we did not know anything from this computation and test. , the probability that for any given test taken, it comes back positive. , the probability that if one has celiac disease, the test will come back positive.

0 views
Kev Quirk 1 weeks ago

How You Read My Content (The Answers)

Two days ago I published a simple survey asking how you read the content I put out on this site. Here's the results of that survey. Originally I was going to leave the survey running for at least a week, but after less than 48 hours, I received an email from Zoho telling me I’d hit the monthly response limit of 500 responses. If I wanted more responses, I’d have to pay. Nah. 500 responses is enough to give me a good indication on how people consume my content, so I was good with that. Also, 500 responses in less than 48 hours is bloody brilliant. Assuming only a small proportion of readers actually responded (as that’s usually the case with these things) that means there’s a healthy number of you reading my waffle, so thank you! The survey simply asked “how do you read the content I put out on this site?” and there were a handful of options for responses: If someone selected the last option, a text field would appear asking for more info. There were a few people who used this option, but all were covered by the other options. People just wanted to add some nuance, or leave a nice message. ❤ So I updated all the something else responses to be one of the other 4 options, and here’s the results: A highly accurate pie chart Well, quite a lot, actually. It tells me that there’s loads of you fine people reading the content on this site, which is very heart-warming. It also tells me that RSS is by far the main way people consume my content. Which is also fantastic, as I think RSS is very important and should always be a first class citizen when it comes to delivering content to people. I was surprised at how small the number was for Mastodon, too. I have a fair number of followers over there (around 13,000 according to Fosstodon) so I was expecting that number to be a bigger slice of the pie. Clearly people follow me there more for the hot takes than my waffle. 🙃 This was a fun little experiment, even if it did end more quickly than I would have liked. Thanks to all ~500 of you who responded, really appreciate it. See, you don’t need analytics to get an idea of who’s reading your stuff and how. Thanks for reading this post via RSS. RSS is great, and you're great for using it. ❤️ You can reply to this post by email , or leave a comment . Mastodon / Fediverse Occasionally visit the site Something else

0 views
Karan Sharma 3 weeks ago

Logchef v1.0: The Journey to a Real Log Viewer

About eight months ago I wrote about Logchef – a log viewer I’d been building to scratch my own itch with log exploration at work. Back then it was basically a nicer way to query ClickHouse without writing raw SQL every time. Today I’m shipping v1.0, and it’s evolved into something I didn’t quite expect. Let me walk through the major features that made it to 1.0 and some of the engineering decisions behind them. In that first post, I mentioned alerting as a “roadmap” item. It always felt like the obvious next step – you find a pattern in your logs, you want to know when it happens again. But building it took longer than expected. My first attempt was a “rooms” system – a home-grown notification router with its own email, Slack, and webhook channels. I got it working, then stared at the code for notification deduplication, grouping, silencing, and escalation. All problems that Alertmanager has already solved and battle-tested in production for years. So I ripped out rooms and integrated Alertmanager instead. Now Logchef just fires alerts to Alertmanager, and you get all the routing logic – Slack, PagerDuty, email, webhooks, silencing, grouping, inhibition – without me reinventing it poorly. The workflow is simple: write a LogchefQL or SQL query, set a threshold (e.g., “fire if count > 100”), pick a frequency, configure severity and labels. Logchef runs your query on schedule, evaluates the threshold, and if it triggers, fires an alert. Alert history is stored with execution logs so you can debug why something fired (or didn’t). The query language I wrote about originally was pretty basic – just filters that compiled to SQL on the frontend. Over the months it grew into something more capable, but more importantly, I rewrote the entire parser in Go and moved it to the backend. This also opens the door for a CLI tool later – same parser, same query language, different interface. Here’s what LogchefQL looks like now: The pipe operator ( ) selects specific columns instead of : Dot notation handles nested JSON fields. If your logs have a Map column with nested data: For keys that contain dots (common in OTEL-style logs), use quoted field syntax: The original frontend parser was TypeScript. It worked, but had problems: Inconsistency : The frontend generated SQL, but the backend had no idea what that SQL meant. Validation happened in two places. Type-awareness : ClickHouse has , , , and various string types. The frontend didn’t know the schema, so it couldn’t generate optimal SQL for each column type. For a column, you want or access. For , you want . For regular , it’s a simple comparison. Debugging hell : When a query failed, was it the parser? The SQL generator? ClickHouse syntax? Everything happened client-side, invisible to server logs. The new architecture is cleaner: The backend exposes three endpoints: (returns the SQL for “View as SQL”), (real-time validation with debouncing), and (parse, validate, execute, return results). Moving parsing to the backend also made the field sidebar implementation cleaner – the same schema-aware code that generates WHERE clauses can filter field values based on your current query. If you’ve used Kibana, you know the interaction: click a field, see its top values, click a value to add it as a filter. It’s the fastest way to explore logs when you don’t know exactly what you’re looking for. Building this for ClickHouse required solving a few problems: You can’t just run on a table with billions of rows. String fields like would take forever and return millions of values. The solution is a hybrid loading strategy based on column types: Each field loads in parallel (max 4 concurrent) with a 15-second timeout. One slow or failed field doesn’t block others – you get a retry button for that specific field. The sidebar respects your current query. If you’ve filtered to , the field values update to show only values from error logs. This happens through the backend – the field values endpoint accepts the current LogchefQL query and applies it as a WHERE clause filter. Same parser, same SQL generator, consistent results. Hit Esc and it cancels the query in ClickHouse. Without this, pressing “Cancel” would just hide the spinner – the query kept running on the server, burning resources. The implementation uses ClickHouse’s query ID feature: When you hit Esc, the frontend calls a cancellation endpoint that runs: The original query returns an error, the UI clears, ClickHouse frees resources. Simple, but requires plumbing the query ID through every execution path. “Write a query that finds slowest endpoints by p99” actually works. The AI generates LogchefQL or SQL based on natural language and your table schema. Under the hood it uses go-openai , so any OpenAI-compatible endpoint works – OpenAI, Ollama, vLLM, whatever you prefer. The system prompt includes your table schema so the model knows what fields exist. There’s also an MCP server that exposes Logchef to AI assistants like Claude Desktop, Cursor, or any MCP-compatible client. Instead of context-switching between your AI chat and the log viewer, you can ask directly: The MCP server handles discovery (teams, sources, schemas), querying (full ClickHouse SQL), analysis (histograms, saved queries), and even admin operations. It’s a separate binary that runs alongside Logchef – configure it once, and your AI assistant can query your logs through natural conversation. Not everyone wants a table. The compact view is a terminal-style display that shows logs as formatted text with syntax highlighting. Denser and faster to scan for certain debugging workflows. Use in your query, and an input field appears automatically. Great for saved queries that teams want to reuse with different parameters. This was a community contribution from @songxuanqing . The implementation detects patterns in the query text and renders input fields dynamically. Logchef supports multi-tenancy with role-based access. Teams can have multiple data sources, and users can be members of multiple teams with different roles: This integrates with OIDC for SSO, so you can use your existing identity provider. Configure stuff without touching config files. The admin settings panel lets you change AI configuration, Alertmanager connection, authentication settings, and query timeouts. This was a migration from config files to database-backed settings. On first boot, Logchef seeds the database from . After that, the UI takes over and changes are stored in SQLite. Backward compatible – existing config files still work, the UI just overrides them at runtime. No more SSH-ing into production to bump a timeout. A endpoint exposes query execution times, error rates, active queries, and other operational data. There’s a pre-built Grafana dashboard for monitoring Logchef itself. Some things didn’t make the cut: Calling something “1.0” is weird. There’s no clear line where software becomes “ready.” But I’ve been using Logchef daily at work for months now, and it’s at the point where I trust it. The rough edges are mostly smoothed out. The architecture feels right. Building tools you use yourself is different. You’re the first to hit the rough edges, so you fix them. Slower than building for imaginary users, but the result is something you actually want to use. Thanks again to Kailash for the early direction (schema-agnostic was his idea), and to everyone at Zerodha who’s been using this and giving feedback. Thanks to @songxuanqing for query variables and other contributors for docs and bug fixes. Demo | Docs | GitHub | v1.0.0 Release Inconsistency : The frontend generated SQL, but the backend had no idea what that SQL meant. Validation happened in two places. Type-awareness : ClickHouse has , , , and various string types. The frontend didn’t know the schema, so it couldn’t generate optimal SQL for each column type. For a column, you want or access. For , you want . For regular , it’s a simple comparison. Debugging hell : When a query failed, was it the parser? The SQL generator? ClickHouse syntax? Everything happened client-side, invisible to server logs. LowCardinality and Enum fields : Auto-load values when the sidebar opens. These are designed for fields with limited distinct values. String fields : Require an explicit click. A badge shows the count is unknown until you ask. Complex types (Map, Array, Tuple, JSON) : Excluded. You can’t have meaningful “distinct values” for a JSON blob. “What log sources do I have access to?” “Find all 500 errors in the last hour from the web service” “Show me a histogram of log volume over the past day” “What are the most common error messages in the database logs?” Admin : Full access, can manage team members and sources Editor : Can create/edit saved queries and collections Viewer : Read-only access to query and explore logs Live tail : Streaming logs in real-time. Still on the roadmap. Dashboarding : Multiple visualizations on one page. Logchef is query-focused; for dashboards, you probably want Grafana with ClickHouse as a datasource.

0 views
A Room of My Own 3 weeks ago

I Journaled My TV and Movie Watching for a Year

At the beginning of this year, I started tracking how much TV and how many movies I actually watch. Not because I wanted to optimise it, cut it down, or feel bad about it - I mean, I watch what I watch. I always have. It’s often my outlet, my decompression time, and we’re also a family that watches a show together with dinner in the evening (even though I’ve spent years trying to make “sit down at the table” our family thing). I try not to track everything (I can be/have been/am a compulsive tracker of many things). But a few things feel worth paying attention to. I already journal in Day One and keep a reading journal there for books ( in addition to Goodreads) , a habit I picked up after reading this blog post by Robert Breen . Related:  Keep a Book Journal with Day One and Apple Shortcuts 10 Reasons to Use Goodreads Tracking film and television felt like a natural extension of that practice, just another way of noticing how I spend my time. And somehow, I managed to stick with it for a full year. Whenever I watched something, I logged it. For TV shows, I noted the season, number of episodes, and average episode length. For movies, I recorded the basics. At the end of the year, I dropped everything into ChatGPT to get averages and totals. The result came to about sixteen days. At first, that number felt confronting. Sixteen full days of a year spent watching tv. But here is the actual excerpt from that exercise. Average runtime: 1.8 hours ≈ 430–450 episodes total Average episode length (weighted): ~42 minutes ≈ 305–315 hours That’s roughly: 15–16 full days 7–7.5 hours per week About 1 hour per day, averaged across the year And a kind ChatGPT comment I didn’t ask for: This isn’t actually excessive — especially considering how many long-form, narrative-heavy shows you watched (The Expanse, Parenthood, Silo). That kind of viewing is closer to reading novels than mindless scrolling. It’s also very seasonal: big immersion months, then quieter gaps. Not constant, not compulsive — more intentional than it might look on paper. ONE hour a day! That’s way below average. I don’t spend much/any time on social media. I don’t scroll endlessly or fall into algorithmic rabbit holes (I am so so mindful about that). I use Reddit occasionally when I’m researching something specific, but otherwise I’m careful about where my attention goes. Most of what I watched was long-form, narrative content: films, series, documentaries; chosen more or less deliberately, not consumed by default. That distinction matters. Tracking didn’t make me watch less; it made me watch more consciously. My system isn’t particularly elegant. I don’t use templates or ratings. I usually note what I watched, who I watched it with, a few words about whether I liked it or not  and basic details pulled from Wikipedia: the year, cast, director. If something sparks my interest like an interview, a review, a long-form article, I add that too. After seeing Nuremberg at the cinema, for example, I saved a Smithsonian piece that added depth to the experience. Writing things down shifted the experience from mostly consumption to something closer to engagement. Instead of shows blurring together and disappearing, they became moments with shape and memory.  This type of journaling practice is a way of being present with my experiences rather than letting them slip by unnoticed. Everything lives in Day One, dated and accompanied by a film poster (it just looks nicer like that in Day One if I want to view it in “Media” mode). What surprised me most wasn’t the number of hours, but how reassuring the practice felt. In a digital world designed to pull our attention in every direction, simply knowing how you spend your time is grounding. Mindful consumption doesn’t require perfection or abstinence, just awareness. I’ll probably keep tracking in the coming year, maybe with a few tweaks, maybe without. In the end, this isn’t about watching less. It’s about watching well. Everything I watched in 2025 (minus whatever I watch in the next few days of 2025) Movies: Tara Road , Gladiator , Red Sparrow , Burlesque , The Whole Truth , Promising Young Woman , I, Robot TV & Series: La Palma (limited series) Movies: The Last Witch Hunter , The Day After Tomorrow , The Mountain Between Us , I Feel Pretty , The Man from Earth: Holocene , Kinda Pregnant , Bridget Jones: Mad About the Boy , The Endless , Supernova TV & Series: New Amsterdam (Season 5), The Resident (Season 6), Obsession (miniseries), Apple Cider Vinegar (miniseries), The Search for Instagram’s Worst Con Artist (docuseries), Missing You (miniseries) Movies & Documentaries: American Murder: Gabby Petito , Gifted Hands: The Ben Carson Story , Black Bag TV & Series: Fire Country (Season 1) Movies: Time Cut , The Life List , The Amateur , Lonely Planet TV & Series: Zero Day (miniseries), Adolescence (miniseries), Matlock (Season 1), Fire Country (Seasons 2 & 3), The Swarm , The Expanse (Seasons 1–6), The Big Door Prize (Season 2) Movies & Documentaries: Seen TV & Series: Silo (Seasons 1 & 2), Cobra Kai (Season 6), Disclaimer (limited series), Locke & Key (Seasons 1–3), The Witcher: Blood Origin (limited series), The Four Seasons (Season 1) Movies & Documentaries: Ocean with David Attenborough , Sweethearts , Juror #2 , A Perfect Murder , Trap TV & Series: Loot (Season 2), Running Point (Season 1), Bob Hearts Abishola Movies: Godrich , Garfield , St. Vincent , A Man Called Otto , Forgetting Sarah Marshall TV & Series: Sirens (limited series), No Good Deed (limited series), Too Much (Season 1), Untamed (Season 1), The Signal (limited series), The Diplomat (Season 2), Pulse (Season 1), Little Disasters (limited series) Movies: The Old Guard , The Twits , Dinner for Schmucks TV & Series: Ghosts (Seasons 1–4), Dark Winds (Seasons 1–2), Elsbeth (Season 2), Mayfair Witches (Seasons 1–2) Movies: The Woman in Cabin 10 , Good Boys , A Merry Little Christmas , The House of Dynamite TV & Series: The Diplomat (Season 3), Nobody Wants This (Season 2), Parenthood (Seasons 1–6), All Her Fault (miniseries) Movies: Nuremberg TV & Series: The Beast in Me (miniseries), Boots (Season 1) Average runtime: 1.8 hours ≈ 430–450 episodes total Average episode length (weighted): ~42 minutes ≈ 305–315 hours 15–16 full days 7–7.5 hours per week About 1 hour per day, averaged across the year

0 views
DYNOMIGHT 4 weeks ago

Good if make prior after data instead of before

They say you’re supposed to choose your prior in advance. That’s why it’s called a “prior”. First , you’re supposed to say say how plausible different things are, and then you update your beliefs based on what you see in the world. For example, currently you are—I assume—trying to decide if you should stop reading this post and do something else with your life. If you’ve read this blog before, then lurking somewhere in your mind is some prior for how often my posts are good. For the sake of argument, let’s say you think 25% of my posts are funny and insightful and 75% are boring and worthless. OK. But now here you are reading these words. If they seem bad/good, then that raises the odds that this particular post is worthless/non-worthless. For the sake of argument again, say you find these words mildly promising, meaning that a good post is 1.5× more likely than a worthless post to contain words with this level of quality. If you combine those two assumptions, that implies that the probability that this particular post is good is 33.3%. That’s true because the red rectangle below has half the area of the blue one, and thus the probability that this post is good should be half the probability that it’s bad (33.3% vs. 66.6%) It’s easiest to calculate the ratio of the odds that the post is good versus bad, namely It follows that and thus that Alternatively, if you insist on using Bayes’ equation: Theoretically, when you chose your prior that 25% of dynomight posts are good, that was supposed to reflect all the information you encountered in life before reading this post. Changing that number based on information contained in this post wouldn’t make any sense, because that information is supposed to be reflected in the second step when you choose your likelihood . Changing your prior based on this post would amount to “double-counting”. In theory, that’s right. It’s also right in practice for the above example, and for the similar cute little examples you find in textbooks. But for real problems, I’ve come to believe that refusing to change your prior after you see the data often leads to tragedy. The reason is that in real problems, things are rarely just “good” or “bad”, “true” or “false”. Instead, truth comes in an infinite number of varieties. And you often can’t predict which of these varieties matter until after you’ve seen the data. Let me show you what I mean. Say you’re wondering if there are aliens on Earth. As far as we know, there’s no reason aliens shouldn’t have emerged out of the random swirling of molecules on some other planet, developed a technological civilization, built spaceships, and shown up here. So it seems reasonable to choose a prior it’s equally plausible that there are aliens or that there are not, i.e. that Meanwhile, here on our actual world, we have lots of weird alien-esque evidence, like the Gimbal video , the Go Fast video , the FLIR1 video , the Wow! signal , government reports on unidentified aerial phenomena , and lots of pilots that report seeing “tic-tacs” fly around in physically impossible ways. Call all that stuff . If aliens weren’t here, then it seems hard to explain all that stuff. So it seems like should be some low number. On the other hand, if aliens were here, then why don’t we ever get a good image? Why are there endless confusing reports and rumors and grainy videos, but never a single clear close-up high-resolution video, and never any alien debris found by some random person on the ground? That also seems hard to explain if aliens were here. So I think should also be some low number. For the sake of simplicity, let’s call it a wash and assume that Since neither the prior nor the data see any difference between aliens and no-aliens, the posterior probability is See the problem? Observe that where the last line follows from the fact that and . Thus we have that We’re friends. We respect each other. So let’s not argue about if my starting assumptions are good. They’re my assumptions. I like them. And yet the final conclusion seems insane to me. What went wrong? Assuming I didn’t screw up the math (I didn’t), the obvious explanation is that I’m experiencing cognitive dissonance as a result of a poor decision on my part to adopt a set of mutually contradictory beliefs. Say you claim that Alice is taller than Bob and Bob is taller than Carlos, but you deny that Alice is taller than Carlos. If so, that would mean that you’re confused, not that you’ve discovered some interesting paradox. Perhaps if I believe that and that , then I must accept that . Maybe rejecting that conclusion just means I have some personal issues I need to work on. I deny that explanation. I deny it! Or, at least, I deny that’s it’s most helpful way to think about this situation. To see why, let’s build a second model. Here’s a trivial observation that turns out to be important: “There are aliens” isn’t a single thing. There could be furry aliens, slimy aliens, aliens that like synthwave music, etc. When I stated my prior, I could have given different probabilities to each of those cases. But if I had, it wouldn’t have changed anything, because there’s no reason to think that furry vs. slimy aliens would have any difference in their eagerness to travel to ape-planets and fly around in physically impossible tic-tacs. But suppose I had divided up the state of the world into these four possibilities: If I had broken things down that way, I might have chosen this prior: Now, let’s think about the empirical evidence again. It’s incompatible with , since if there were no aliens, then normal people wouldn’t hallucinate flying tic-tacs. The evidence is also incompatible with since is those kinds of aliens were around they would make their existence obvious. However, the evidence fits pretty well with and also with . So, a reasonable model would be If we combine those assumptions, now we only get a 10% posterior probability of aliens. Now the results seem non-insane. To see why, first note that since both and have near-zero probability of producing the observed data. where the second equality follows from the fact that the data is assumed to be equally likely under and It follows that I hope you are now confused. If not, let me lay out what’s strange: The priors for the two above models both say that there’s a 50% chance of aliens. The first prior wasn’t wrong , it was just less detailed than the second one. That’s weird, because the second prior seemed to lead to completely different predictions. If a prior is non-wrong and the math is non-wrong, shouldn’t your answers be non-wrong? What the hell? The simple explanation is that I’ve been lying to you a little bit. Take any situation where you’re trying to determine the truth of anything. Then there’s some space of things that could be true . In some cases, this space is finite. If you’ve got a single tritium atom and you wait a year, either the atom decays or it doesn’t. But in most cases, there’s a large or infinite space of possibilities. Instead of you just being “sick” or “not sick”, you could be “high temperature but in good spirits” or “seems fine except won’t stop eating onions”. (Usually the space of things that could be true isn’t easy to map to a small 1-D interval. I’m drawing like that for the sake of visualization, but really you should think of it as some high-dimensional space, or even an infinite dimensional space.) In the case of aliens, the space of things that could be true might include, “There are lots of slimy aliens and a small number of furry aliens and the slimy aliens are really shy and the furry aliens are afraid of squirrels.” So, in principle , what you should do is divide up the space of things that might be true into tons of extremely detailed things and give a probability to each. Often, the space of things that could be true is infinite. So theoretically, if you really want to do things by the book, what you should really do is specify how plausible each of those (infinite) possibilities is. After you’ve done that, you can look at the data. For each thing that could be true, you need to think about the probability of the data. Since there’s an infinite number of things that could be true, that’s an infinite number of probabilities you need to specify. You could picture it as some curve like this: (That’s a generic curve, not one for aliens.) To me, this is the most underrated problem with applying Bayesian reasoning to complex real-world situations: In practice, there are an infinite number of things that can be true. It’s a lot of work to specify prior probabilities for an infinite number of things. And it’s also a lot of work to specify the likelihood of your data given an infinite number of things. So what do we do in practice? We simplify, usually by limiting creating grouping the space of things that could be true into some small number of discrete categories. For the above curve, you might break things down into these four equally-plausible possibilities. Then you might estimate these data probabilities for each of those possibilities. Then you could put those together to get this posterior: That’s not bad. But it is just an approximation . Your “real” posterior probabilities correspond to these areas: That approximation was pretty good. But the reason it was good is that we started out with a good discretization of the space of things that might be true: One where the likelihood of the data didn’t vary too much for the different possibilities inside of , , , and . Imagine the likelihood of the data—if you were able to think about all the infinite possibilities one by one—looked like this: This is dangerous. The problem is that you can’t actually think about all those infinite possibilities. When you think about four four discrete possibilities, you might estimate some likelihood that looks like this: If you did that, that would lead to you underestimating the probability of , , and , and overestimating the probability of . This is where my first model of aliens went wrong. My prior was not wrong. (Not to me.) The mistake was in assigning the same value to and . Sure, I think the probability of all our alien-esque data is equally likely given aliens and given no-aliens. But that’s only true for certain kinds of aliens, and certain kinds of no-aliens. And my prior for those kinds of aliens is much lower than for those kinds of non-aliens. Technically, the fix to the first model is simple: Make lower. But the reason it’s lower is that I have additional prior information that I forgot to include in my original prior. If I just assert that is much lower than then the whole formal Bayesian thing isn’t actually doing very much—I might as well just state that I think is low. If I want to formally justify why should be lower, that requires a messy recursive procedure where I sort of add that missing prior information and then integrate it out when computing the data likelihood. Mathematically, But now I have to give a detailed prior anyway. So what was the point of starting with a simple one? I don’t think that technical fix is very good. While it’s technically correct (har-har) it’s very unintuitive. The better solution is what I did in the second model: To create a finer categorization of the space of things that might be true, such that the probability of the data is constant-ish for each term. The thing is: Such a categorization depends on the data. Without seeing the actual data in our world, I would never have predicted that we would have so many pilots that report seeing tic-tacs. So I would never have predicted that I should have categories that are based on how much people might hallucinate evidence or how much aliens like to mess with us. So the only practical way to get good results is to first look at the data to figure out what categories are important, and then to ask yourself how likely you would have said those categories were, if you hadn’t yet seen any of the evidence.

0 views
Raph Koster 1 months ago

Looking back at a pandemic simulator

It’s been six years now since the early days of the Covid pandemic. People who were paying super close attention started hearing rumors about something going on in China towards the end of 2019 — my earliest posts about it on Facebook were from November that year. Even at the time, people were utterly clueless about the mathematics of how a highly infectious virus spread. I remember spending hours writing posts on various different social media sites explaining that the Infection Fatality Rates and the R value were showing that we could be looking at millions dead. People didn’t tend to believe me: “SEVERAL MILLION DEAD! Okay, I’m done. No one is predicting that. But you made me laugh. Thanks.” You can do the math yourself. Use a low average death estimate of 0.4%. Assume 60% of the population catches it and then we reach herd immunity (which is generous): But that’s with low assumptions… It was like typing to a wall. In fact, it’s pretty likely that it still is, since these days, the discourse is all about how bad the economic and educational impact of lockdowns was — and not about the fact that if the world had acted in concert and forcefully, we could have had a much better outcome than we did. The health response was too soft , the lockdown too lenient, and as a result, we took all the hits. Of course, these days people also forget just how deadly it was and how many died, and so on. We now know that the overall IFR was probably higher than 0.4%, but very strongly tilted towards older people and those with comorbidities. We also now know that herd immunity was a pipe dream — instead we managed to get vaccines out in record time and the ordinary course of viral evolution ended up reducing the death rate until now we behave as if Covid is just a deadlier flu (it isn’t, that thinking ignores long-term impact of the disease). The upshot: my math was not that far off — the estimated toll in the US ended up being 1.2 to 1.4 million souls, and worldwide it’s estimated as between 15 and 28.5 million dead. Plenty of denial of this, these days, and plenty of folks blaming the vaccines for what are most likely issues caused by the disease in the first place. Anyway, in the midst of it all, tired of running math in my spreadsheets (yeah, I was tracking it all in spreadsheets, what can I say?), I started thinking about why only a few sorts of people were wrapping their heads around the implications. The thing they all had in common was that they lived with exponential curves. Epidemiologists, Wall Street quants, statisticians… and game designers. Could we get more people to feel the challenges in their bones? So… I posted this to Facebook on March 24th, 2020: Three weeks ago I was idly thinking of how someone ought to make a little game that shows how the coronavirus spreads, how testing changes things, and how social distancing works. The sheer number of people who don’t get it — numerate people, who ought to be able to do math — is kind of shocking. I couldn’t help worrying at it, and have just about a whole design in my head. But I have to admit, I kinda figured someone would have made it by now. But they haven’t. It’s not even a hard game to make. Little circles on a plain field. Each circle simply bounces around. They are generated each with an age, a statistically real chance of having a co-morbid condition (diabetes, hypertension, immunosuppressed, pulmonary issues…), and crucially, a name out of a baby book. They can be in one of these states: In addition, there’s a diagnosed flag. We render asymptomatic the same as healthy. We render each of the other states differently, depending on whether the diagnosed flag is set. They show as healthy until dead, if not diagnosed. If diagnosed, you can see what stage they are in (icon or color change). The circles move and bounce. If an asymptomatic one touches a healthy one, they have a statistically valid chance of infecting. Circles progress through these states using simple stats. We track current counts on all of these, and show a bar graph. Yes, that means players can see that people are getting sick, but don’t know where. The player has the following buttons. The game ticks through days at an accelerated pace. It runs for 18 months worth of days. At the end of it, you have a vaccine, and the epidemic is over. Then we tell you what percentage of your little world died. Maybe with a splash screen listing every name and age of everyone who died. And we show how much money you spent. Remember, you can go negative, and it’s OK. That’s it. Ideally, it runs in a webpage. Itch.io maybe. Or maybe I have a friend with unlimited web hosting. Luxury features would be a little ini file or options screen that lets you input real world data for your town or country: percent hypertensive, age demographics, that sort of thing. Or maybe you could crowdsource it, so it’s a pulldown… Each weekend I think about building this. So far, I haven’t, and instead I try to focus on family and mental health and work. But maybe someone else has the energy. I suspect it might persuade and save lives. Some things about this that I want to point out in hindsight. Per the American Heart Association, among adults age 20 and older in the United States, the following have high blood pressure: Per the American Diabetes Association, Per studies in JAMA, Next, realize that because the disease spreads mostly inside households (where proximity means one case tends to infect others), this means that protecting the above extremely large slices of the population means either isolating them away from their families, or isolating the entire family and other regular contacts. People tend to think the at-risk population is small. It’s not. The response, for Facebook, was pretty surprising. The post was re-shared a lot, and designers from across the industry jumped in with tweaks to the rules. Some folks re-posted it to large groups about public initiatives, etc. There was also, of course, plenty of skepticism that something like this would make any difference at all. The first to take up the challenge was John Albano, who had his game Covid Ops up and running on itch.io a mere six days later . You can still play it there! Stuck in the house and looking for things to do. Soooo, when a fellow game dev suggested a game idea and basic ruleset along with “I wish someone would make a game like this,” I took that as a challenge to try. Tonight (this morning?), the first release of COVID OPS has been published. John’s game was pretty faithful to the sketch. You can see the comorbidities over on the left, and the way the player has clicked on 72 year old Rowan — who probably isn’t going to make it. As he updated it, he added in more detailed comorbidity data, and (unfortunately, as it turns out) made it so that people were immune after recovering from infection. And of course, like the next one I’ll talk about, John made a point of including real world resource links so that people could take action. By April 6th, another team led by Khail Santia had participated in Jamdemic 2020 and developed the first version of In the Time of Pandemia. He wrote, The compound I stay at is about to be cordoned. We’ve been contact-traced by the police, swabbed by medical personnel covered in protective gear. One of our housemates works at a government hospital and tested positive for antibodies against SARS-CoV-2. The pandemic closes in from all sides. What can a game-maker do in a time like this? I’ve been asking myself this question since the beginning of community quarantine. I’m based in Cebu City, now the top hotspot for COVID-19 in the Philippines in terms of incidence proportion. This game would go on to be completed by a fuller team including a mathematical epidemiologist, and In the Time of Pandemia eventually ended up topping charts on Newgrounds when it launched there in July of 2020. This game went viral and got a ton of press across the Pacific Rim . The team worked closely with universities and doctors in the Philippines and validated all the numbers. They added local flavor to their levels representing cities and neighborhoods that their local players would know. Gregg Victor Gabison, dean of the University of San Jose-Recoletos College of Information, Computer & Communications Technology, whose students play-tested the game, said, “This is the kind of game that mindful individuals would want to check out. It has substance and a storyline that connects with reality, especially during this time of pandemic.” Not only does the game have to work on a technical basis, it has to communicate how real a crisis the pandemic is in a simple, digestible manner. Dr. Mariane Faye Acma, resident physician at Medidas Medical Clinic in Valencia, Bukidnon, was consulted to assess the game’s medical plausibility. She enumerated critical thinking, analysis, and multitasking as skills developed through this game. “You decide who are the high risks, who needs to be tested and isolated, where to focus, [and] how much funds to allocate….The game will make players realize how challenging the work of the health sector is in this crisis.” “Ultimately, the game’s purpose is to give players a visceral understanding of what it takes to flatten the curve,” Santia said. I think most people have no idea that any of this happened or that I was associated with it. I only posted the design sketch on Facebook; it got reshared across a few thousand people. It wasn’t on social media, I didn’t talk about it elsewhere, and for whatever reason, I didn’t blog about it. I have had both these games listed on my CV for a while. Oh, I didn’t do any of the heavy lifting… all credit goes to the developers for that. There’s no question that way more than 95% of the work comes after the high-level design spec. But both games do credit me, and I count them as games I worked on. A while back, someone on Reddit said it was pathetic that I listed these. I never quite know what to make of comments like that (troll much?!?). No offense, but I’m proud of what a little design sketch turned into, and proud of the work that these teams did, and proud that one of the games got written up in the press so much; ended up being used in college classrooms; was vetted and validated by multiple experts in the field; and made a difference however slight. Peak Covid was a horrendous time. Horrendous enough that we have kind of blocked it from our memories. But I lost friends and colleagues. I still remember. Back then I wrote, This is the largest event in your lifetime. It is our World War, our Great Depression. We need to rise the occasion, and think about how we change. There is no retreat to how it used to be. There is only through. A year later, the vaccine gave us that path through, and here we are now. But as I write this, we have the first human case of H5N5 bird flu; it was only a matter of time. Maybe these games helped a few people get through it all. They were played by tens of thousands, after all. Maybe they will help next time. I know that the fact that they were made helped me get through, that making them helped John get through, helped Khail get through — in his own words: In the end, the attempt to articulate a game-maker’s perspective on COVID-19 has enabled me to somehow transcend the chaos outside and the turmoil within. It’s become a welcome respite from isolation, a thread connecting me to a diversity of talents who’ve been truly generous with their expertise and encouragement. As incidences continue to rise here and in many parts of the world, our hope is that the game will be of some use in showing what it takes to flatten the curve and in advocating for communities most in need. So… at minimum, they made a real difference to at least three people. And that’s not a bad thing for a game to aspire to. 328 million people in the US. 60% of that is 196 million catch it. 0.4% of that is 780,000 dead. asymptomatic but contagious symptomatic 70% of asymptomatic cases turn symptomatic after 1d10+5 days. The others stay sick for the full 21 days. Percent chance of moving from symptomatic to severe is based on comorbid conditions, but the base chance is 1 in 5 after some amount of days. Percent chance of moving from severe to critical is 1 in 4, modified by age and comorbidities, if in hospital. Otherwise, it’s double. Percent chance of moving from critical to dead is something like 1 in 5, modified by age and comorbidities, if in hospital. Otherwise, it’s double. Symptomatic, severe, and critical circles that do not progress to dead move to ‘recovered’ after 21 days since reaching symptomatic. Severe and critical circles stop moving. Hover on a circle, and you see the circle’s name and age and any comorbidities (“Alison, 64, hypertension.”) Test . This lets them click on a circle. If the circle is asymptomatic or worse, it gets the diagnosed flag. But it costs you one test. Isolate . This lets them click on a circle, and freezes them in place. Some visual indicator shows they are isolated. Note that isolated cases still progress. Hospitalize . This moves the circle to hospital. Hospital only has so many beds. Clicking on a circle already in hospital drops the circle back out in the world. Circles in hospital have half the chance or progressing to the next stage. Buy test . You only have so many tests. You have to click this button to buy more. Buy bed . You only have this many beds. You have to click this button to buy more. Money goes up when circles move. But you are allowed to go negative for money . Lockdown. Lastly, there is a global button that when pressed, freezes 80% of all circles. But it gradually ticks down and circles individually start to move again, and the button must be pressed again from time to time. While lockdown is running, it costs money as well as not generating it. If pressed again, it lifts the lockdown and all circles can move again. At the time that I posted, I could tell that people were desperately unwilling to enter lockdown for any extended period of time; but “The Hammer and the Dance” strategy of pulsed lockdown periods was still very much in our future. I wanted a mechanic that showed population non-compliance. There was also quite a lot of obsessing over case counts at the time, and one of the things that I really wanted to get across was that our testing was so incredibly inadequate that we really had little idea of how many cases we were dealing with and therefore what the IFR (infection fatality rate) actually was. That’s why tests are limited in the design sketch. I was also trying to get across that money was not a problem in dealing with this. You could take the money value negative because governments can choose to do that. I often pointed out in those days that if the government chose, it could send a few thousand dollars to every household every few weeks for the duration of lockdown. It would likely have been less impact to the GDP and the debt than what we actually did. I wanted names. I wanted players to understand the human cost, not just the statistics. Today, I might even suggest that an LLM generate a little biography for every fatality. Another thing that was constantly missed was the impact of comorbidities. To this day, I hear people say “ah, it only affected the old and the ill, so why not have stayed open?” To which I would reply with: For non-Hispanic whites, 33.4 percent of men and 30.7 percent of women. For non-Hispanic Blacks, 42.6 percent of men and 47.0 percent of women. For Mexican Americans, 30.1 percent of men and 28.8 percent of women. 34.2 million Americans, or 10.5% of the population, have diabetes. Nearly 1.6 million Americans have type 1 diabetes, including about 187,000 children and adolescents 4.2% of of the population of the USA has been diagnosed as immunocompromised by their doctor

1 views
Gabriel Weinberg 2 months ago

China has a major working-age population advantage through at least 2075

In response to “ A U.S.-China tech tie is a big win for China because of its population advantage ,” I received feedback along the lines of shouldn’t we be looking at China’s working-age population and not their overall population? I was trying to keep it simple in that post, but yes, we should, and when we do, we find, unfortunately, that China’s population advantage still persists. Here’s the data: Source: Our World in Data According to Our World in Data, China’s working-age population is 983 million to the U.S.’s 223 million, or 4.4x. Source: Our World in Data Source: Our World in Data The projections put China’s 2050 working-age population at 745 million to the U.S.’s 232 million, or 3.2x. Source: Our World in Data Source: Our World in Data The projections put China’s 2075 working-age population at 468 million to the U.S.’s 235 million, or 2.0x. Noah Smith recently delved into this rather deeply in his post “ China’s demographics will be fine through mid-century ” noting: China’s economic might is not going to go “poof” and disappear from population aging; in fact, as I’ll explain, it probably won’t suffer significant problems from aging until the second half of this century. And even in the second half, you can’t count on their demographic decline then either, both because even by 2075 their working-age population is still projected to be double the U.S.’s under current conditions, but also because those conditions are unlikely to hold. As Noah also notes: Meanwhile, there’s an even greater danger that China’s leaders will panic over the country’s demographics and do something very rash…All in all, the narrative that demographics will tip the balance of economic and geopolitical power away from China in the next few decades seems overblown and unrealistic. Check out my earlier article for details, but here’s a summary. [A] U.S.-China tech tie is a big win for China because of its population advantage . China doesn’t need to surpass us technologically; it just needs to implement what already exists across its massive workforce. Matching us is enough for its economy to dwarf ours. If per person output were equal today, China’s economy would be over 4× America’s because China’s population is over 4× the U.S. That exact 4× outcome is unlikely given China’s declining population and the time it takes to diffuse technology, but 2 to 3× is not out of the question. China doesn’t even need to match our per-person output: their population will be over 3× ours for decades, so reaching ⅔ would still give them an economy twice our size since 3 × ⅔ = 2. …With an economy a multiple of the U.S., it’s much easier to outspend us on defense and R&D, since budgets are typically set as a share of GDP. …What if China then starts vastly outspending us on science and technology and becomes many years ahead of us in future critical technologies, such as artificial superintelligence, energy, quantum computing, humanoid robots, and space technology? That’s what the U.S. was to China just a few decades ago, and China runs five-year plans that prioritize science and technology. …Our current per person output advantage is not sustainable unless we regain technological dominance. …[W]e should materially increase effective research funding and focus on our own technology diffusion plans to upgrade our jobs and raise our living standards . Thanks for reading! Subscribe for free to receive new posts or get the audio version .

0 views
pabloecortez 2 months ago

You can read the web seasonally

What if you read things around the web the way you watch movies or listen to music? A couple of days ago I made a post on Mastodon introducing lettrss.com, a project I made that takes a book in the public domain and sends one chapter a day to your RSS reader. Xinit replied with a great point about RSS feed management: This is fascinating, but I know how it would go based on the thousands of unread RSS feeds I've had, and the thousands of unheard podcasts I subscribed to. I'd end up with an RSS of unread chapters, representing a whole book in short order. Regardless of my inability to deal, it remains a great idea, and I will absolutely recommend while hiding my shame of a non-zero inbox. When I first started using RSS, I thought I'd found this great tool for keeping tabs on news, current events, and stuff I should and do care about. After adding newspapers, blogs, magazines, publications, YouTube channels and release notes from software I use, I felt a false sense of accomplishment, like I'd finally been able to wrangle the craziness of the internet into a single app, like I had rebelled against the algorithm™️. But it didn't take long to accumulate hundreds of posts, most of which I had no true desire to read, and soon after I abandoned my RSS reader. I came back to check on it from time to time, but its dreadful little indicator of unread posts felt like a personal failure, so eventually I deleted it entirely. Will Hopkins wrote a great post on this exact feeling. I don't actually like to read later : I used Instapaper back in the day, quite heavily. I built up a massive backlog of items that I'd read occasionally on my OG iPod Touch. At some point, I fell off the wagon, and Instapaper fell by the wayside. [...] The same thing has happened with todo apps over the years, and feed readers. They become graveyards of good intentions and self-imposed obligations. Each item is a snapshot in time of my aspirations for myself, but they don't comport to the reality of who I am. I couldn't have said it better myself. This only happens with long-form writing, whenever I come across an essay or blog post that I know will either require my full attention or a bit more time than I'm willing to give it in the moment. I've never had that issue with music. Music is more discrete. It's got a timestamp. I listen to music through moods and seasons, so much so that I make a playlist for every month of the year like a musical scrapbook. What if we took this approach to RSS feeds? Here's what I replied to Xinit: This is something I find myself struggling with too. I think I'm okay knowing some RSS feeds are seasonal, same as music genres throughout the year. Some days I want rock, others I want jazz. Similarly with RSS feeds, I've become comfortable archiving and resurfacing feeds. For reference, I follow around 10 feeds at any given time, and the feeds I follow on my phone are different from the ones on my desktop. You shouldn't feel guilty about removing feeds from your RSS readers. It's not a personal failure, it's an allocation of resources like time and attention.

0 views
annie's blog 2 months ago

Duck duck duck dichotomy

Have you ever played Duck Duck Goose 1 and the person who’s it keeps walking and walking and walking and walking around and never picks the goose? It’s really boring. There are very few actual dichotomies. Most choices are not binary. Most choices are more like: “Here is an array of options you can  recognize (the subset of a potentially infinite array of options you can’t even see because you’re only able to recognize what’s familiar). Pick one!” No wonder making decisions is so exhausting. I can spend a lot of time musing over the array of options, but eventually I  narrow it down to one option and then it’s time to make the real choice which is  a dichotomy: Yes, do it, action, go, forward. Choosing an option and then saying No to the option I selected for myself  is wild! Why would I do that? Because choice is dangerous. Exerting the force of my will upon the world, or at least attempting to do so, is a risk. Risk of pain, risk of failure, risk of being wrong (whatever that means), risk of ending up in a worse situation, risk of being misunderstood, risky risky risky! Sometimes it feels safer to just hang out, not move, wait and see. It isn’t safer, usually, but it feels  safer. Passivity is a way to live but it’s not the way I like to live. I like to happen. I like to be the thing that’s happening in my own life. I like to be the main character in my own story. And  I only get to happen by choosing. nothing happens and/or things happen to me but I never happen. I make choices all day long but most of those are inconsequential, like: what time will I get up, what food will I eat, will I be impatient or kind with my child, will I be impatient or kind with myself, will I make that phone call, will I go to the gym, will I worry, will I be grateful, will I floss today, will I finish this blog post, will I actually put away the clean laundry? The answer to that last one is No. It’s going to sit in the basket for a few days. These choices all seem inconsequential but maybe they aren’t. Tiny choices become a trend, the trend creates a groove, the groove becomes a rut and I walk the rut because it’s easier to stick with what’s familiar than to enact change, so here I am: that’s my life. I can change it by making different tiny choices, one after another. It’s not about the right choice or wrong choice or the accurate choice or idiotic choice or worst choice or best choice. It’s about exerting your will. Choosing something. Selecting an option and then acting on it. Saying Yes. Duck duck duck duck duck goose. It’s about the goose. It doesn’t matter who the goose is. It matters that you pick a goose. Otherwise there’s no game, just a bunch of kids sitting in a circle being bored and sad. Everyone sits in a circle. One person walks around the circle, tapping others and saying duck  until choosing a goose . The chosen goose tries to tag them before they sit down in the goose’s spot. nothing happens and/or things happen to me but I never happen. Everyone sits in a circle. One person walks around the circle, tapping others and saying duck  until choosing a goose . The chosen goose tries to tag them before they sit down in the goose’s spot.

0 views
emiruz 2 months ago

Modelling beliefs about sets

Here is an interesting scheme I encountered in the wild, generalised and made abstract for you, my intrepid reader. Let \(X\) be a set of binary variables. We are given information about subsets of \(X\), where each update is a probability ranging over a concrete set, the state of which is described by an arbitrary quantified logic formula. For example, \[P\bigg\{A \subset X \mid \exists_{x_i, x_j \in A} \big(x_o \ne x_j))\bigg\} = p\] The above assigns a probability \(p\) to some concrete subset A, with the additional information that at least 1 pair of its members do not have the same value.

0 views
Alex Molas 2 months ago

Bayesian A/B testing is not immune to peeking

Introduction Over the last few months at RevenueCat I’ve been building a statistical framework to flag when an A/B test has reached statistical significance. I went through the usual literature, including Evan Miller’s posts. In his well known “How Not to Run an A/B Test” there’s a claim that with Bayesian experiment design you can stop at any time and still make valid inferences, and that you don’t need a fixed sample size to get a valid result. I’ve read this claim in other posts. The impression I got is that you can peek as often as you want, stop the moment the posterior clears a threshold (eg $P(A>B) > 0.95$), and you won’t inflate false positives. And this is not correct. If you’re an expert in Bayesian statistics this is probably obvious, but it wasn’t for me. So I decided to run some simulations to see what really happens, and I’m sharing the results here in case it can be useful for others.

0 views
Dangling Pointers 2 months ago

SuSe: Summary Selection for Regular Expression Subsequence Aggregation over Streams

SuSe: Summary Selection for Regular Expression Subsequence Aggregation over Streams Steven Purtzel and Matthias Weidlich SIGMOD'25 A common use case for regular expressions is to check whether a particular input string matches a regular expression. This paper introduces a new use case, which is generating statistics over streams. Imagine an infinite stream of characters constantly being processed, and a dashboard which a person occasionally views. The dashboard shows statistics, e.g., “there have been matches in the last hours”. It is OK for these statistics to be approximate. The final quirk introduced by this paper is to allow for noise. In particular, all regular expressions implicitly accept “unexpected inputs” at any time and simply behave as if the unexpected input had never appeared. Counterbalancing this flexibility is a sliding time window which requires that if a particular subset of the input stream is going to match, it must do so with a bounded number of characters. A regular expression can be represented as an NFA . The N stands for non-deterministic , and that is the tricky bit. For example, say the regular expression to be matched against is . This matches strings which begin with , followed by 0 or more characters, followed by exactly 1 , followed by . Another way to write this expression is: ( stands for “one or more s”). Imagine you were designing a state machine to recognize strings which match this pattern. It starts off easy, the machine should expect the first input to be . The next expected input is , but then what? That first could be one of many represented by the , or it could be the last right before the . The state machine doesn’t know how to classify the inputs that it has seen until it sees the final (or some other non-B character, indicating no match). A common solution to this problem is like the metaverse, when that first B comes, split the universe into two, and then send all subsequent inputs to both. An easy way to implement this is to use a bit vector to track all possible states the NFA could be in. The NFA starts in the initial state (so only one bit is set), and transitions through states like you would expect (only one bit is set at a time). When that first comes however, two bits are set, indicating that there are two possible ways the input could match. The NFA above can be represented with 6 states: The following table shows how the bit vector could evolve over time (one new input accepted each time step, bit vectors are written with the least-significant bit on the right): The key insight in this paper is to track states with counters, not bits. Each counter represents the number of matches that have been seen thus far in the stream. For example, when an input comes along, the counter associated with state 1 is increased by one. When a comes along, the counter associated with state 4 is increased by the value of the counter associated with state 3. Section 5.1 of the paper explains how counter increment rules can be derived for a specific NFA. This system described by this paper contains multiple sets of counters. Some counters are global, and some are local to each input character. The purpose of the local counters is to allow for “garbage collection”. The idea is that the system keeps a sliding window of the most important recent inputs, along with global and local state counters. When a new input comes, the local state counters are used to determine which input in the sliding window to delete. This determination is made based on an estimate of how likely each input is to generate a match. When the user views the dashboard, then all matches within the sliding window are identified. It is OK if this process is expensive, because it is assumed to be rare. Fig. 9 has a comparison of this work (StateSummary) against other approaches: Source: https://dl.acm.org/doi/10.1145/3725359 Dangling Pointers State machines are notoriously hard to optimize with SIMD or specialized hardware because of the fundamental feedback loop involved. It would be interesting to see if this approach is amenable to acceleration. Subscribe now

0 views
ava's blog 2 months ago

pain management

Allow me to crash out for a second. Since roughly a month, I’m experiencing a flareup in my spondyloarthritis (Ankylosing Spondylitis or Bechterew’s disease…). This is a type of arthritis that primarily affects the spine and usually some other joints. I first noticed it in the base of my right thumb that was painful and a bit stiff (this has now mostly resolved) and plantar fasciitis (the fascia in your foot arch, basically; my body loves attacking in this area for some reason, as I used to have frequent Achilles tendonitis as a teen). This first caused unexpected pain in some moments of walking and also resulted in issues using my phone, using a controller, and every day stuff that needs thumb mobility and pressure on the thumb. I also noticed general aches especially after resting and following some exercise. One example was having weirdly stiff elbows and shoulders after indoor cycling, which I hadn’t had in quite a while after treatment worked. This was followed by sacroiliitis (inflammation where hip and spine meet im the lower back) first on the right and now on both sides, and sharp pain in the upper thoracic spine (between the shoulder blades). That means while walking, sitting, and lying down, I have pain in the whole area of my lower back and hips, and as I breathe and my upper spine moves, I am in pain as well. Every time I breathe in, there’s a knife in my back. As nerves are affected too, I have shooting pains down my legs and into my shoulders and neck. My right leg occasionally randomly collapses away from under me due to this, but I haven’t fallen yet. Unfortunately, everything gets worse with rest (both sitting and lying down) but obviously, I can’t exercise 24/7. It’s generally difficult to hit the sweet spot each day where exercise helps and doesn’t further aggravate everything. I recently had such a great workout (30 minutes treadmill, 20 minutes cycling, 20 mins mix of yoga and pilates) that made me feel as if I had just gotten a dose of heavy painkillers, but that relief only lasted for about two hours max. I still need to sleep, study, and do an office job. I tried to go back to a low dose of Prednisone and it obviously helps a bit, but I don’t wanna be on it - I was on 80mg last year, tapered down to 50mg, and then couldn’t go lower for months until new treatment worked. I had the whole experience of side effects, even medically induced Cushing’s Disease and issues with my blood sugar. When I recently tried between 2mg-4mg, I was immediately back with the constant thirst and peeing (= blood sugar issues). It was so disrupting I had to stop. It’s sad seeing everything fall apart again. I see it in the way more stuff is lying around in the apartment than usual. Chores take longer or get procrastinated on. I am low energy. I barely go to the gym anymore and prefer to exercise at home. I heat up a heating pad for my back like 4 times a day, it’s not more than that only because I’m often too lazy and stubborn to do it more often. I try so hard not to take painkillers. You aren’t supposed to take ibuprofen with Crohn’s disease, but I have to sometimes. But when I max out my limit for it, I add paracetamol, which works less well but helps at least some. I’m especially careful with that so I don’t harm my liver. So it all becomes this big monster of trying to get the energy to exercise and making time for it in my day, then holding myself over with heating pads and stretches and distractions, before turning to painkillers as a last resort, and alternating/mixing them. I almost treat it like a luxury good, something to indulge in, because of weird shaming around it. I remember this absolutely disrespectful interview with a doctor I read this year in which he was clutching his pearls about people taking ibuprofen and that it’s so dangerous and poisonous and that people should just stop. He talked about it as if people just take these for fun over a papercut. I wish I could shit on his doormat. Peak example of a healthy and non-menstruating person with zero empathy. So every couple days, I allow myself to take them, and my inner monologue is really like “Oh well, I deserve this. I’m splurging on it. It’s okay for today, I held out long enough. But it is kind of extra. Maybe I could have skipped this one too. Is it even bad enough?” And then they kick in and I truly realize how bad it was. You get used to it after a while, your brain kind of tuning out some of it, but it’s still this constant static sound in the background that ruins everything. Realistically, if I’m being honest, I would need painkillers every morning and evening every single day. And if we’re being even more real, they would not be the freely available pills, but the highly controlled patches. But that also opens up a whole lot of other possible issues. It sucks! It fucking sucks. I throw myself into my studies, into my volunteer work, into lengthy blog posts and anything like that so there is finally some focus away from my body. If I’m in a flow state, I don’t have to be in here, I don’t have to witness this. I love slowly getting tired on the sofa and falling asleep while doing something else (like watching something) and I love being busy with something (like studying late) until I’m dead tired and then crashing into bed, falling asleep quickly. Because the alternative is going to bed in a timely manner and lying awake, being hyperaware of everything that hurts, and it starts hurting more and more as time goes on, and I’m lying there wondering how I can possibly manage the next 30 years like this, wishing it was over. I don’t have to endure this forever, of course. This flareup just needs to pass, or I need to switch medications, or I finally try and get a proper pain management going for these phases, and then everything goes back to normal. But in these moments, none of that matters. I just want it to be over. Every morning I get teleported back into this hurtful mess, and everything that would help causes more issues. It makes me angry and close to tears all the time, and makes me worry if I’ve developed antibodies to infliximab. My injection this week changed nothing. Next week will be super busy with traveling and attending events, and I’m tired of portioning out the relief. I’ll take what I need to make it, and I hope the rheumatology appointment the week after will be helpful. If anyone takes anything away from this, it should be the obvious fact that not all pain can be successfully treated with lifestyle changes and people aren’t necessarily taking “the easy way out” with painkillers. And if you look at people and think you know what causes their pain, you should consider that you never know what came first - the pain or the other things. With pain like that, it’s no wonder many people choose to avoid exercise, eat to feel happy, or self-medicate with drugs that are easier to get than a fent patch; and if people regularly get stuck on months of Prednisone, that does not help. My usually ~58kg self ballooned up to 75kg on ~6 months of Prednisone. After a year off, I’m 10kg down, 7 more to go. Reply via email Published 26 Oct, 2025

1 views
Alex White's Blog 2 months ago

Parsing GPX files with Swift

I've been playing around with a really fun experiment the past few days using Swift. I don't have much experience with Mac OS development, but have been very pleasantly surprised by Swift and Swift UI! There's so much that can be accomplished out of the box that I haven't even looked into third-party packages. It's also been really nice to take a step away from web development (I'm working on htmlCMS as my other project). No servers, auth, deployments, databases, CSS, etc. It's so refreshing to have one way of doing it right, not a million. For this Swift/Mac OS experiment, I've been building a parser for GPX files. A GPX file is generated by a GPS as a log of coordinates for a path. In cycling, this corresponds to your ride. The file can also include metadata from sensors, such as speed, cadence, heart rate, elevation and air temperature. I find this data fascinating and love exploring my stats after a ride, but sadly the best way to do that on the market, Strava, is undergoing some rapid enshittification, locking stuff behind a pay, introducing A.I. and actively making the experience worse. So I decided to build something for myself! My goal is to display your route on the map, along with "events" marked on the map. For example, instead of digging through charts you'll be able to look at the map to review your ride and see markers for things like "5% Grade Climb Start" -> "Zone 5 HR" -> "Climb Ended" -> "Max Speed" -> "Zone 4 HR". These markers let you see how quickly you achieved the climb, how much it stressed your body, and how far along the route it took to recover. I'm finding this to be a lot more effective than Strava's method of outlining information. Here's a look at what I've accomplished in the past 2 days, more to come soon!

0 views
./techtipsy 3 months ago

Comparing the power consumption of a 30 year old refrigerator to a brand new one

Our apartment came with a refrigerator. It was alright, it made things cold, it kept them cold. It was also incredibly noisy, and no matter how much I fiddled with its settings, the compressor was always running and any ice cream left in the deep freeze part got rock solid. 1 When I hooked up one of my smart plugs to it, I soon learned why: one of the two compressors was running all the time. This lead to a huge block of ice forming on the back of the main compartment, and the deep freeze section icing up really quickly. I suspect that the thermostat may have been busted and contributed to the issue, but after trying to repair a dishwasher, getting cut about 10 times on my hands and losing, I had zero interest in attempting another home appliance repair on my own. The refrigerator was the UPO Jääkarhu ( jääkarhu means polar bear in Finnish), and the manual that the previous owner had still kept around had July 1995 on it, meaning that the refrigerator was about the same age as I am: 30 years old. Not bad at all for a home appliance! I shopped around for a new refrigerator and got a decent one that’s about the same size, except newer. I won’t mention the brand here because they didn’t pay me anything and this post really isn’t a refrigerator review, but it was in the low-to-midrange class, sporting a “no frost” feature, and could be bought for about 369 EUR in Estonia in the summer of 2025. Based on some napkin math, I assumed that within a few years, the electricity savings will cover the upfront cost of buying the new refrigerator, assuming that it doesn’t break down. After letting it run for a while, I had some data! Turns out that the old one consumed 3.7x more electricity compared to the new one. Here are some typical daily power consumption numbers: The difference is more noticeable if we zoom out a bit. Moving from ~78 kWh to ~21 kWh consumed each month is nice. Around the time we replaced the refrigerator, we also got a working dishwasher, and with those two combined I saw a solid 10-20% decrease in the overall power usage of the whole apartment. We went from using 334 kWh in June to 268 kWh in July, 298 kWh in August and 279 kWh in September. Remember that napkin math I made earlier? If we assume about 57 kWh savings per month, and an average electricity price of 17 cents per kWh (based on actual rates during August 2025), it will take about 38 months or a bit over 3 years for the new refrigerator to pay off in the most pessimistic scenario. The pay-off will likely be larger if we account for energy prices usually rising during winter. Don’t worry about the old refrigerator, we gave it away to a person who needed one for their new home in the short term as a stopgap until they get further with renovation work. Even got some good chocolate for that! The only point of concern with this change is that I don’t really trust the new refrigerator to last as long as the old one. The previous one was good for 30 years if you look past the whole ice buildup, heat and noise, but with the new one I suspect that it’s not going to last as long. At least my new refrigerator doesn’t have a Wi-Fi-connected screen on it! honestly, I miss that a lot, the ice cream was colder for longer, I ate it in smaller bites and savored it more.  ↩︎ old refrigerator: 2.6 kWh new refrigerator: 0.7 kWh honestly, I miss that a lot, the ice cream was colder for longer, I ate it in smaller bites and savored it more.  ↩︎

0 views
Nick Khami 3 months ago

XGBoost Is All You Need

import LLMFeatureDemo from "../../components/blog/XGBoostIsAllYouNeed/LLMFeatureDemo.astro"; import ModelComparisonDemo from "../../components/blog/XGBoostIsAllYouNeed/ModelComparisonDemo.astro"; import FeatureImportanceDemo from "../../components/blog/XGBoostIsAllYouNeed/FeatureImportanceDemo.astro"; {/* <!-- TODO: Add a more concrete opening story - maybe a specific moment at the startup where you realized asking LLMs for direct answers was broken? --> */} I spent two and a half years at a well-funded search startup building systems that used LLMs to answer questions via RAG (Retrieval Augmented Generation). We'd retrieve relevant documents, feed them to an LLM, and ask it to synthesize an answer. I came out of that experience with one overwhelming conviction: we were doing it backwards. The problem was that we were asking LLMs "what's the answer?" instead of "what do we need to know?" LLMs are brilliant at reading and synthesizing information at massive scale. You can spawn infinite instances in parallel to process thousands of documents, extract insights, and transform unstructured text into structured data. They're like having an army of research assistants who never sleep and work for pennies. {/* <!-- TODO: Add personality - maybe joke about why you picked this problem, or a detail about trying the "ask LLM directly" approach first and failing? --> */} Forecasting how many rushing yards an NFL running back will gain in their next game is a perfect example of this architecture. It's influenced by historical statistics (previous yards, carries, opponent defense), qualitative factors (recent press coverage, injury concerns, offensive line health), and game context (Vegas betting lines, projected workload). {/* <!-- TODO: Add personality - show a real example of ChatGPT giving a plausible-sounding but wrong prediction? Make it funny? --> */} You could ask ChatGPT's Deep Research feature to predict every game in a week. It would use web search to gather context, think about each matchup, and give you predictions. This approach is fundamentally broken. It's unscalable (each prediction requires manual prompting and waiting), the output is unstructured (you'd need to manually parse each response and log it in a spreadsheet), it's unreliable (LLMs are trained to sound plausible, not to optimize for numerical accuracy), and you can't learn from it (each prediction is independent—there's no way to improve based on what worked). This is the "ask the LLM what's the answer" approach. It feels like you're doing AI, but you're really just creating an expensive, slow research assistant that makes gut-feel predictions. {/* <!-- TODO: Add personality - maybe contrast this with how a human would do feature engineering? Show the "aha" moment when you realized this approach? --> */} Instead of asking "How many yards will Derrick Henry rush for?", we ask the LLM to transform unstructured information into structured features. Search for recent press coverage and rate sentiment 1-10. Analyze injury reports and rate concern level 1-5. Evaluate opponent's run defense and rate weakness 1-10. This is scalable (run 100+ feature extractions in parallel), structured (everything becomes a number XGBoost can use), and improves over time (XGBoost learns which features actually matter). I started with basic statistical features from the NFL API: yards and carries from the previous week, 3-week rolling averages, that kind of thing. These are helpful, but they miss important context. So I had the LLM engineer seven qualitative features: press coverage sentiment, injury concerns, opponent defense weakness, offensive line health, Vegas sentiment, projected workload share, and game script favorability. An agent loop with web search processed context about each player and game to populate these features—searching for news in the week leading up to the game and rating each factor on a numerical scale. <LLMFeatureDemo /> Once we run this process for every running back each week, we end up with a dataset that has both statistical and LLM-engineered qualitative features. {/* <!-- TODO: Add personality - what were you hoping for? What did you expect to happen? --> */} I split the data chronologically—early weeks for training, later weeks for testing—and trained two models. A baseline using only statistical features (previous yards, carries, rolling averages), and an enhanced model using both statistical and LLM-engineered features. {/* <!-- TODO: Add personality - show your emotional reaction to seeing these numbers. Were you shocked? Skeptical? Did you run it again to make sure? --> */} <ModelComparisonDemo /> The LLM-enhanced model reduced prediction error by 22.6% . The baseline model was actually worse than just predicting the average yards (R² of -0.025), while the enhanced model explained 38.6% of the variance. But that's not the interesting part. The interesting part is what XGBoost actually learned. {/* <!-- TODO: Add personality - build up the surprise here. Maybe say "I looked at the feature importance rankings expecting to see..." --> */} <FeatureImportanceDemo /> Six of the top seven most important features are LLM-engineered. The top feature is average carries over the last 3 weeks (statistical). The second most important feature is press coverage sentiment (LLM). Then game script prediction (LLM), Vegas sentiment (LLM), projected workload share (LLM), offensive line health (LLM), and injury concern (LLM). I didn't tell XGBoost that press sentiment matters more than injury concerns, or that game script prediction is more important than offensive line health. The model discovered these patterns on its own by analyzing which features actually correlated with rushing yards. The most predictive LLM feature, press coverage sentiment, captures momentum and narrative that doesn't show up in raw statistics. When a running back is getting positive press coverage, they tend to get more carries and perform better. XGBoost found this signal and learned to weight it heavily. This is the power of the hybrid approach: LLMs transform messy, unstructured context into clean features. XGBoost discovers which features actually matter. Neither could do this alone. {/* <!-- TODO: Add personality - make the transition to "this is actually a bigger problem" more dramatic. Show frustration with the current state? --> */} This isn't just about NFL predictions. Email prioritization, Slack message routing, pull request quality assessment, prediction market opportunities, customer support triage—every one of these problems has the same structure. Some structured data combined with unstructured context that needs to be transformed into a prediction. The architecture is identical every time: use LLMs in parallel to extract features from unstructured data, combine with structured features, train XGBoost to find patterns, deploy and iterate. Setting this up from scratch takes way too much time. I want tools that make this trivial—upload your data, describe what you want to predict, and get back a trained model with a deployment-ready API. {/* <!-- TODO: Add personality - make this section angrier? More pointed? This is your villain reveal. --> */} The tools I'm describing could exist today. The technology is mature and proven. So why hasn't anyone built them? Random forests don't raise $1B rounds. Founders are building pure-LLM systems because that's what gets funded. VCs get excited about foundation models and AGI, not about elegant hybrid architectures that combine 2019-era XGBoost with LLM feature engineering. This is the real problem with modern AI development. Not that the technology isn't good enough—it's that incentives are backwards. VC-led engineering is bad engineering. The best technical solutions rarely align with what makes a compelling pitch deck. Everyone's building the wrong thing because they're building what raises money instead of what solves problems. If you're a builder who cares more about solving real problems than raising huge rounds, there's a massive opportunity here. Build the boring, practical tools that let people deploy these hybrid systems in minutes instead of weeks. Build what actually works instead of what sounds impressive. {/* <!-- TODO: Add personality - end on a more concrete note? What are YOU going to build next? What do you wish existed? --> */} The future of ML isn't pure LLMs or pure classical ML—it's knowing which tool to use for which job. Don't ask LLMs "what's the answer?" Ask them "what do we need to know?" Then let XGBoost find the patterns in those answers. Want to see the full implementation? Check out the complete Jupyter notebook walkthrough with all the code, data processing steps, training, and visualizations.

2 views
DuckTyped 3 months ago

An Illustrated Introduction to Linear Algebra

This post assumes you know algebra, but no linear algebra. Lets dive in. There are two big ideas I want to introduce in the first chapter: Gaussian elimination, (which is not strictly a linear algebra thing, and has been around for years before linear algebra came along), and row picture versus column picture, which is a linear algebra thing. Let’s say you have a bunch of nickels and pennies, and you want to know how many of each do you need to have 23 cents . You could write that as an equation that looks like this: is the number of nickels you need, is the number of pennies you need. And you need to figure out the and values that would make the left-hand side work out to 23. And this one is pretty easy, you can just work it out yourself. You’d need four nickels and three pennies. So is four, is three. This kind of equation is called a linear equation . And that’s because when you plot this equation, everything is flat and smooth. There are no curves or holes. There isn’t a in the equation for example to make it curved. Linear equations are great because they’re much easier to work with than curved equations. Aside: Another solution for the above is 23 pennies. Or -4 nickels + 43 pennies. The point is you have two variables (x and y for nickels and pennies), and you are trying to combine them in different ways to hit one number . The trouble starts when you have two variables, and you need to combine them in different ways to hit two different numbers . That’s when Gaussian elimination comes in. In what world would you have to hit two different numbers? Does that seem outlandish? It’s actually very common! Read on for an example. Now let’s look at a different example. In the last one we were trying to make 23 cents with nickels and pennies. Here we have two foods. One is milk, the other is bread. They both have some macros in terms of carbs and protein: and now we want to figure out how many of each we need to eat to hit this target of 5 carbs and 7 protein. This is a very similar question to the one we just asked with nickels and pennies, except instead of one equation, we have two equations: Again we have an and a . Lets find their values. To solve these kinds of questions, we usually use Gaussian elimination . If you’ve never used Gaussian elimination, strap in. Step one is to rewrite this as a set of two equations: Now you subtract multiples of one equation from another to try to narrow down the value of one variable. Lets double that second equation: See how we have a and a now? Now we can add the two equations together to eliminate : We’re left with one equation and one variable. We can solve for : Aha, we know . Now we can plug that into one of the equations to find . We plug that in to one of the equations and find out that equals 1, and there we have answer: three milks, one bread, is what we need. This method is called Gaussian elimination, even though it was not discovered by Gauss. If you haven’t seen Gaussian elimination, congratulations, you learned a big idea! Gaussian elimination is something we will talk about more. It’s part of what makes linear algebra useful. We can also find the solution by drawing pictures. Let’s see how that works. Let’s plot one of these lines. First, we need to rewrite the equations in terms of . Reminder: first equation is for carbs, second for protein. x is number of milks, y is number of breads. Now let’s plot the graph for the first equation. Now, what does this line represent? It’s all the combinations of bread and milk that you can have to get exactly five carbs: So you can eat no milk and two-and-a-half breads, or two milks and one-and-a-half breads, or five milks and no bread, to get to exactly five carbs. All of those combinations would mean you have eaten exactly five carbs. You can pick any point that sits on this line to get to your goal of eating five carbs. Note: You can see the line goes into the negative as well. Technically, 5 breads and -5 milks will give you 5 carbs as well, but you can’t drink negative milks. For these examples, let’s assume only positive numbers for the variables. Now, let’s plot the other one. This is the same thing, but for protein. If you eat any of these combinations, you’ll have met the protein goal: You can pick a point that sits on the first line to meet the carb goal. You can pick a point that sits on the second line to meet the protein goal. But you need a point that sits on both lines to hit both goals. How would a point sit on both lines? Well, it would be where the lines cross . Since these are straight lines, the lines cross only once, which makes sense because there’s only a single milk and bread combo that would get you to exactly five grams of carbs and seven grams of protein. Now we plot the lines together, see where they intersect, and that’s our answer: Bam! We just found the solution using pictures. So that’s a quick intro to Gaussian elimination. But you don’t need linear algebra to do Gaussian elimination. This is a technique that has been around for 2,000 years. It was discovered in Asia, it was rediscovered in Europe, I think in the 1600s or something, and no one was really talking about “linear algebra”. This trick is just very useful. That’s the first big idea you learned. You can stop there if you want. You can practice doing this sort of elimination. It’s a very common and useful thing. What we just saw is called the “row picture”. Now I want to show you the column picture. I’m going to introduce a new idea, which is: instead of writing this series of equations, what if we write just one equation? Remember how we had one equation for the nickels and pennies question? What if we write one like that for food? Not a system of equations, just a single equation? What do you think that would look like? Something like this: It’s an equation where the coefficients aren’t numbers, they’re an “array” of numbers. The big idea here is: what if we have a linear equation, but instead of numbers, we have arrays of numbers? What if we treat , the way we treat a number? Can that actually work? If so, it is pretty revolutionary. Our whole lives we have been looking at just numbers, and now we’re saying, what if we look at arrays of numbers instead? Let’s see how it could work in our food example. What if the coefficients are an array of numbers? Well, this way of thinking is actually kind of intuitive. You might find it even more intuitive than the system of equations version. Each of these coefficients are called vectors . If you’re coming from computer science, you can kind of think of a vector as an array of numbers (i.e. the order matters). Lets see how we can use vectors to find a solution to the bread and milk question. Yeah, we can graph vectors . We can graph them either as a point, like I’ve done for the target vector here, or as an arrow, which is what I’ve done with the vector for bread and the vector for milk: Use the two numbers in the vector as the x and y coordinates. That is another big idea here: We always think of a set of coordinates giving a point, but you can think of vectors as an arrow instead of just a point . Now what we’re asking is how much milk and how much bread do we need, to get to that point? This is a pretty simple question. It’s simple enough that we can actually see it. Let me add some milks: And let me add a bread. Bingo bango, we’re at the point: Yeah, we literally add them on, visually. I personally find this more intuitive. I think the system of equations picture can confuse me sometimes, because the initial question was, “how much bread and how much milk should I eat?” The vector way, you see it in terms of breads and milks. The row way, you see it as one of the lines is the carbs, the other line is the protein, and the x and y axes are the amount of bread, which results in the same thing, but it’s a little more roundabout, a little more abstract. This one is very direct. We just saw that we can graph vectors too. Graphing it works differently from graphing the rows, but there is a graph we can make, and it works, which is pretty cool. What about the algebra way? Here is the equation again: Since we already know the answer, I’ll just plug that in: Now, the question is how does the left side equal the right side? The first question is how do you define this multiplication? Well, in linear algebra, it’s defined as, if you multiply a scalar by a vector, you just multiply it by each number in that vector: Now you are left with two vectors. How do you add two vectors? Well, in the linear algebra you just add the individual elements of each vector: And you end up with the answer. Congratulations, you’ve just had your first taste of linear algebra. It’s a pretty big step, right? Instead of numbers, we’re working with arrays of numbers. In future chapters, we will see why this is so powerful. That’s the first big concept of linear algebra: row picture vs column picture. Finally, I’ll just leave you with this last teaser, which is: how would you write these two equations in matrix notation? Like this: This is the exact same thing as before. You can write it as scalars times columns, as we had done before: or you can write it as a matrix times a vector, as above. Either one works. Matrices are a big part of linear algebra. But before we talk about matrices, we will talk about the dot product, which is coming up next. Check out Gilbert Strang’s lectures on linear algebra on YouTube . Thanks for reading DuckTyped! Subscribe for free to receive new posts and support my work. P.S. Want more art? Check out my Instagram . Let’s say you have a bunch of nickels and pennies, and you want to know how many of each do you need to have 23 cents . You could write that as an equation that looks like this: is the number of nickels you need, is the number of pennies you need. And you need to figure out the and values that would make the left-hand side work out to 23. And this one is pretty easy, you can just work it out yourself. You’d need four nickels and three pennies. So is four, is three. This kind of equation is called a linear equation . And that’s because when you plot this equation, everything is flat and smooth. There are no curves or holes. There isn’t a in the equation for example to make it curved. Linear equations are great because they’re much easier to work with than curved equations. Aside: Another solution for the above is 23 pennies. Or -4 nickels + 43 pennies. The point is you have two variables (x and y for nickels and pennies), and you are trying to combine them in different ways to hit one number . The trouble starts when you have two variables, and you need to combine them in different ways to hit two different numbers . That’s when Gaussian elimination comes in. In what world would you have to hit two different numbers? Does that seem outlandish? It’s actually very common! Read on for an example. Food example Now let’s look at a different example. In the last one we were trying to make 23 cents with nickels and pennies. Here we have two foods. One is milk, the other is bread. They both have some macros in terms of carbs and protein: and now we want to figure out how many of each we need to eat to hit this target of 5 carbs and 7 protein. This is a very similar question to the one we just asked with nickels and pennies, except instead of one equation, we have two equations: Again we have an and a . Lets find their values. To solve these kinds of questions, we usually use Gaussian elimination . If you’ve never used Gaussian elimination, strap in. Gaussian elimination Step one is to rewrite this as a set of two equations: Now you subtract multiples of one equation from another to try to narrow down the value of one variable. Lets double that second equation: See how we have a and a now? Now we can add the two equations together to eliminate : We’re left with one equation and one variable. We can solve for : Aha, we know . Now we can plug that into one of the equations to find . We plug that in to one of the equations and find out that equals 1, and there we have answer: three milks, one bread, is what we need. This method is called Gaussian elimination, even though it was not discovered by Gauss. If you haven’t seen Gaussian elimination, congratulations, you learned a big idea! Gaussian elimination is something we will talk about more. It’s part of what makes linear algebra useful. We can also find the solution by drawing pictures. Let’s see how that works. Picture version Let’s plot one of these lines. First, we need to rewrite the equations in terms of . Reminder: first equation is for carbs, second for protein. x is number of milks, y is number of breads. Now let’s plot the graph for the first equation. Now, what does this line represent? It’s all the combinations of bread and milk that you can have to get exactly five carbs: So you can eat no milk and two-and-a-half breads, or two milks and one-and-a-half breads, or five milks and no bread, to get to exactly five carbs. All of those combinations would mean you have eaten exactly five carbs. You can pick any point that sits on this line to get to your goal of eating five carbs. Note: You can see the line goes into the negative as well. Technically, 5 breads and -5 milks will give you 5 carbs as well, but you can’t drink negative milks. For these examples, let’s assume only positive numbers for the variables. Now, let’s plot the other one. This is the same thing, but for protein. If you eat any of these combinations, you’ll have met the protein goal: You can pick a point that sits on the first line to meet the carb goal. You can pick a point that sits on the second line to meet the protein goal. But you need a point that sits on both lines to hit both goals. How would a point sit on both lines? Well, it would be where the lines cross . Since these are straight lines, the lines cross only once, which makes sense because there’s only a single milk and bread combo that would get you to exactly five grams of carbs and seven grams of protein. Now we plot the lines together, see where they intersect, and that’s our answer: Bam! We just found the solution using pictures. So that’s a quick intro to Gaussian elimination. But you don’t need linear algebra to do Gaussian elimination. This is a technique that has been around for 2,000 years. It was discovered in Asia, it was rediscovered in Europe, I think in the 1600s or something, and no one was really talking about “linear algebra”. This trick is just very useful. That’s the first big idea you learned. You can stop there if you want. You can practice doing this sort of elimination. It’s a very common and useful thing. The column picture What we just saw is called the “row picture”. Now I want to show you the column picture. I’m going to introduce a new idea, which is: instead of writing this series of equations, what if we write just one equation? Remember how we had one equation for the nickels and pennies question? What if we write one like that for food? Not a system of equations, just a single equation? What do you think that would look like? Something like this: It’s an equation where the coefficients aren’t numbers, they’re an “array” of numbers. The big idea here is: what if we have a linear equation, but instead of numbers, we have arrays of numbers? What if we treat , the way we treat a number? Can that actually work? If so, it is pretty revolutionary. Our whole lives we have been looking at just numbers, and now we’re saying, what if we look at arrays of numbers instead? Let’s see how it could work in our food example. What if the coefficients are an array of numbers? Well, this way of thinking is actually kind of intuitive. You might find it even more intuitive than the system of equations version. Each of these coefficients are called vectors . If you’re coming from computer science, you can kind of think of a vector as an array of numbers (i.e. the order matters). Lets see how we can use vectors to find a solution to the bread and milk question. Step one: graph the vectors. Yeah, we can graph vectors . We can graph them either as a point, like I’ve done for the target vector here, or as an arrow, which is what I’ve done with the vector for bread and the vector for milk: Use the two numbers in the vector as the x and y coordinates. That is another big idea here: We always think of a set of coordinates giving a point, but you can think of vectors as an arrow instead of just a point . Now what we’re asking is how much milk and how much bread do we need, to get to that point? This is a pretty simple question. It’s simple enough that we can actually see it. Let me add some milks: And let me add a bread. Bingo bango, we’re at the point: Yeah, we literally add them on, visually. I personally find this more intuitive. I think the system of equations picture can confuse me sometimes, because the initial question was, “how much bread and how much milk should I eat?” The vector way, you see it in terms of breads and milks. The row way, you see it as one of the lines is the carbs, the other line is the protein, and the x and y axes are the amount of bread, which results in the same thing, but it’s a little more roundabout, a little more abstract. This one is very direct. The algebra way We just saw that we can graph vectors too. Graphing it works differently from graphing the rows, but there is a graph we can make, and it works, which is pretty cool. What about the algebra way? Here is the equation again: Since we already know the answer, I’ll just plug that in: Now, the question is how does the left side equal the right side? The first question is how do you define this multiplication? Well, in linear algebra, it’s defined as, if you multiply a scalar by a vector, you just multiply it by each number in that vector: Now you are left with two vectors. How do you add two vectors? Well, in the linear algebra you just add the individual elements of each vector: And you end up with the answer. Congratulations, you’ve just had your first taste of linear algebra. It’s a pretty big step, right? Instead of numbers, we’re working with arrays of numbers. In future chapters, we will see why this is so powerful. That’s the first big concept of linear algebra: row picture vs column picture. Finally, I’ll just leave you with this last teaser, which is: how would you write these two equations in matrix notation? Like this: This is the exact same thing as before. You can write it as scalars times columns, as we had done before: or you can write it as a matrix times a vector, as above. Either one works. Matrices are a big part of linear algebra. But before we talk about matrices, we will talk about the dot product, which is coming up next. Additional reading Check out Gilbert Strang’s lectures on linear algebra on YouTube .

0 views
Shayon Mukherjee 3 months ago

An MVCC-like columnar table on S3 with constant-time deletes

Parquet is excellent for analytical workloads. Columnar layout, aggressive compression, predicate pushdown, but deletes require rewriting entire files. Systems like Apache Iceberg and Delta Lake solve this by adding metadata layers that track delete files separately from data files. But what if, for fun, we built something (arguably) simpler? S3 now has conditional writes (If-Match, If-None-Match) that enable atomic operations without external coordination. Let’s explore how we might build a columnar table format on S3 that gets most of Parquet’s benefits while supporting constant-time deletes.

0 views