<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Bounded Rationality</title><link>http://bjlkeng.github.io/</link><description>Understanding math, machine learning, and data to a satisfactory degree.</description><atom:link href="http://bjlkeng.github.io/rss.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Tue, 28 Jul 2026 02:38:03 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Annotated Deep Learning Course</title><link>http://bjlkeng.github.io/posts/annotated-deep-learning-course/</link><dc:creator>Brian Keng</dc:creator><description>&lt;div&gt;&lt;p&gt;For the past five years, one of the most enjoyable things I've done outside of
my day job is teaching. From 2020 to 2025, I had the pleasure of teaching a
course in the Master of Management Analytics (MMA) program at the Rotman School
of Management (UofT). Now that I've wrapped up that course (on to the next
one), I decided to package up the material and put it online for posterity.&lt;/p&gt;
&lt;p&gt;You can find the full set of annotated lecture notes here: &lt;a class="reference external" href="https://dlcourse.bjlkeng.io/"&gt;dlcourse.bjlkeng.io&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://bjlkeng.github.io/posts/annotated-deep-learning-course/"&gt;Read more…&lt;/a&gt; (1 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>annotated</category><category>course</category><category>deep learning</category><category>Rotman</category><guid>http://bjlkeng.github.io/posts/annotated-deep-learning-course/</guid><pubDate>Tue, 10 Mar 2026 20:41:56 GMT</pubDate></item><item><title>The Logic Behind the Maximum Entropy Principle</title><link>http://bjlkeng.github.io/posts/the-logic-behind-entropy/</link><dc:creator>Brian Keng</dc:creator><description>&lt;div&gt;&lt;p&gt;For a while now, I've really enjoyed diving deep to understand
probability and related fundamentals (see
&lt;a class="reference external" href="http://bjlkeng.github.io/posts/probability-the-logic-of-science/"&gt;here&lt;/a&gt;,
&lt;a class="reference external" href="http://bjlkeng.github.io/posts/maximum-entropy-distributions/"&gt;here&lt;/a&gt;, and
&lt;a class="reference external" href="http://bjlkeng.github.io/posts/an-introduction-to-stochastic-calculus/"&gt;here&lt;/a&gt;).
Entropy is a topic that comes up all over the place from physics to information
theory, and of course, machine learning.  I written about it in various
different forms but always taken it as a given as the "expected information".
Well I found a few of good explanations about how to "derive" it and thought
that I should share.&lt;/p&gt;
&lt;p&gt;In this post, I'll be showing a few of derivations of the maximum entropy
principle, where entropy appears as part of the definition.  These derivations
will show why it is a reasonable and natural thing to maximize, and how it is
determined from some well thought out reasoning.  This post will be more math
heavy but hopefully it will give you more insight into this wonderfully
surprising topic.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://bjlkeng.github.io/posts/the-logic-behind-entropy/"&gt;Read more…&lt;/a&gt; (16 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>entropy</category><category>information</category><category>Jaynes</category><category>mathjax</category><category>Shannon</category><category>Wallis</category><guid>http://bjlkeng.github.io/posts/the-logic-behind-entropy/</guid><pubDate>Sat, 03 Aug 2024 00:44:59 GMT</pubDate></item><item><title>Iterative Summarization using LLMs</title><link>http://bjlkeng.github.io/posts/iterative-summarization-using-llms/</link><dc:creator>Brian Keng</dc:creator><description>&lt;div&gt;&lt;p&gt;After being busy for the first part of the year, I finally have a bit of time
to work on this blog.  After a lot of thinking about how to best fit it into my
schedule, I've decided to &lt;em&gt;attempt&lt;/em&gt; to write shorter posts.  Although I do get
a lot of satisfaction writing long posts, it's not practical because of the
time commitment.  Better to break it up into smaller parts to be able to
"ship" often rather than perfect each post.
This also allows me to experiment with smaller scoped topics, which hopefully
will keep more more motivated as well.  Speaking of which...&lt;/p&gt;
&lt;p&gt;This post is about answering a random thought I had the other day: what would
happen if I kept passing an LLM's output back to itself?  I ran a few
experiments of trying to get the LLM to iteratively summarize or rephrase a
piece of text and the results are...  pretty much what you would expect.  But
if you don't know what to expect, then read on and find out what happened!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://bjlkeng.github.io/posts/iterative-summarization-using-llms/"&gt;Read more…&lt;/a&gt; (8 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>blog</category><category>fixed point</category><category>LLM</category><category>mathjax</category><category>OpenAI</category><category>summarization</category><guid>http://bjlkeng.github.io/posts/iterative-summarization-using-llms/</guid><pubDate>Tue, 04 Jun 2024 00:21:43 GMT</pubDate></item><item><title>A Look at The First Place Solution of a Dermatology Classification Kaggle Competition</title><link>http://bjlkeng.github.io/posts/a-look-at-the-first-place-solution-of-a-dermatology-classification-kaggle-competition/</link><dc:creator>Brian Keng</dc:creator><description>&lt;div&gt;&lt;p&gt;One interesting thing I often think about is the gap between academic and real-world
solutions.  In general academic solutions play in the realm of idealized problem
spaces, removing themselves from needing to care about the messiness of the real-world.
&lt;a class="reference external" href="https://www.kaggle.com/competitions"&gt;Kaggle&lt;/a&gt;
competitions are a (small) step in the right direction towards dealing with messiness,
usually providing a true blind test set (vs. overused benchmarks), and opening a
few degrees of freedom in terms the techniques that can be used, which
usually eschews novelty in favour of more robust methods.  To this end, I
thought it would be useful to take a look at a more realistic problem (via a
Kaggle competition) and understand the practical details that result in a
superior solution.&lt;/p&gt;
&lt;p&gt;This post will cover the &lt;a class="reference external" href="https://arxiv.org/abs/2010.05351"&gt;first place solution&lt;/a&gt; [&lt;a class="reference internal" href="http://bjlkeng.github.io/posts/a-look-at-the-first-place-solution-of-a-dermatology-classification-kaggle-competition/#id2"&gt;1&lt;/a&gt;] to the
&lt;a class="reference external" href="https://www.kaggle.com/competitions/siim-isic-melanoma-classification/overview"&gt;SIIM-ISIC Melanoma Classification&lt;/a&gt; [&lt;a class="reference internal" href="http://bjlkeng.github.io/posts/a-look-at-the-first-place-solution-of-a-dermatology-classification-kaggle-competition/#id1"&gt;0&lt;/a&gt;] challenge.
In addition to using tried and true architectures (mostly EfficientNets), they
have some interesting tactics they use to formulate the problem, process the
data, and train/validate the model.  I'll cover background on the
ML techniques, competition and data, architectural details, problem formulation, and
implementation.  I've also run some experiments to better understand the
benefits of certain choices they made.  Enjoy!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://bjlkeng.github.io/posts/a-look-at-the-first-place-solution-of-a-dermatology-classification-kaggle-competition/"&gt;Read more…&lt;/a&gt; (36 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>augmentation</category><category>CNN</category><category>data</category><category>dermatology</category><category>EfficientNet</category><category>mathjax</category><category>MobileNet</category><category>Noisy Student</category><category>validation set</category><guid>http://bjlkeng.github.io/posts/a-look-at-the-first-place-solution-of-a-dermatology-classification-kaggle-competition/</guid><pubDate>Sat, 23 Dec 2023 00:09:46 GMT</pubDate></item><item><title>LLM Fun: Building a Q&amp;A Bot of Myself</title><link>http://bjlkeng.github.io/posts/building-a-qa-bot-of-me-with-openai-and-cloudflare/</link><dc:creator>Brian Keng</dc:creator><description>&lt;div&gt;&lt;p&gt;Unless you've been living under a rock, you've probably heard of large language
models (LLM) such as ChatGPT or Bard.  I'm not one for riding a hype train but
I do think LLMs are here to stay and either are going to have an impact as big
as mobile as an interface (my current best guess) or perhaps something as big as
the Internet itself.  In either case, it behooves me to do a bit more
investigation into this popular trend &lt;a class="footnote-reference brackets" href="http://bjlkeng.github.io/posts/building-a-qa-bot-of-me-with-openai-and-cloudflare/#id2" id="id1"&gt;1&lt;/a&gt;.  At the same time, there are a bunch
of other developer technologies that I've been wondering about like serverless
computing, modern dev tools, and LLM-based code assistants, so I thought why not
kill multiple birds with one stone.&lt;/p&gt;
&lt;p&gt;This post is going to describe how I built a question and answering bot of myself using
LLMs as well as my experience using the relevant developer tools such as
&lt;a class="reference external" href="https://chat.openai.com"&gt;ChatGPT&lt;/a&gt;, &lt;a class="reference external" href="https://github.com/features/copilot"&gt;Github Copilot&lt;/a&gt;, &lt;a class="reference external" href="https://workers.cloudflare.com/"&gt;Cloudflare workers&lt;/a&gt;, and a couple of other related ones.
I start out with my motivation for doing this project, some brief background
on the technologies, a description of how I built everything including some
evaluation on LLM outputs, and finally some commentary.  This post is a lot
less heavy on the math as compared to my previous ones but it still has some
good stuff so read on!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://bjlkeng.github.io/posts/building-a-qa-bot-of-me-with-openai-and-cloudflare/"&gt;Read more…&lt;/a&gt; (41 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>Cloudflare</category><category>GPT</category><category>Javascript</category><category>LangChain</category><category>large language models</category><category>LLM</category><category>mathjax</category><category>OpenAI</category><category>Q&amp;A</category><guid>http://bjlkeng.github.io/posts/building-a-qa-bot-of-me-with-openai-and-cloudflare/</guid><pubDate>Mon, 25 Sep 2023 00:56:42 GMT</pubDate></item><item><title>Bayesian Learning via Stochastic Gradient Langevin Dynamics and Bayes by Backprop</title><link>http://bjlkeng.github.io/posts/bayesian-learning-via-stochastic-gradient-langevin-dynamics-and-bayes-by-backprop/</link><dc:creator>Brian Keng</dc:creator><description>&lt;div&gt;&lt;p&gt;After a long digression, I'm finally back to one of the main lines of research
that I wanted to write about.  The two main ideas in this post are not that
recent but have been quite impactful (one of the
&lt;a class="reference external" href="https://icml.cc/virtual/2021/test-of-time/11808"&gt;papers&lt;/a&gt; won a recent ICML
test of time award).  They address two of the topics that are near and dear to
my heart: Bayesian learning and scalability.  Dare I even ask who wouldn't be
interested in the intersection of these topics?&lt;/p&gt;
&lt;p&gt;This post is about two techniques to perform scalable Bayesian inference.  They
both address the problem using stochastic gradient descent (SGD) but in very
different ways.  One leverages the observation that SGD plus some noise will
converge to Bayesian posterior sampling &lt;a class="citation-reference" href="http://bjlkeng.github.io/posts/bayesian-learning-via-stochastic-gradient-langevin-dynamics-and-bayes-by-backprop/#welling2011" id="id1"&gt;[Welling2011]&lt;/a&gt;, while the other generalizes the
"reparameterization trick" from variational autoencoders to enable non-Gaussian
posterior approximations &lt;a class="citation-reference" href="http://bjlkeng.github.io/posts/bayesian-learning-via-stochastic-gradient-langevin-dynamics-and-bayes-by-backprop/#blundell2015" id="id2"&gt;[Blundell2015]&lt;/a&gt;.  Both are easily implemented in the modern deep
learning toolkit thus benefit from the massive scalability of that toolchain.
As usual, I will go over the necessary background (or refer you to my previous
posts), intuition, some math, and a couple of toy examples that I implemented.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://bjlkeng.github.io/posts/bayesian-learning-via-stochastic-gradient-langevin-dynamics-and-bayes-by-backprop/"&gt;Read more…&lt;/a&gt; (53 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>Bayes by Backprop</category><category>Bayesian</category><category>elbo</category><category>HMC</category><category>Langevin</category><category>mathjax</category><category>rmsprop</category><category>sgd</category><category>SGLD</category><category>variational inference</category><guid>http://bjlkeng.github.io/posts/bayesian-learning-via-stochastic-gradient-langevin-dynamics-and-bayes-by-backprop/</guid><pubDate>Wed, 08 Feb 2023 23:25:40 GMT</pubDate></item><item><title>An Introduction to Stochastic Calculus</title><link>http://bjlkeng.github.io/posts/an-introduction-to-stochastic-calculus/</link><dc:creator>Brian Keng</dc:creator><description>&lt;div&gt;&lt;p&gt;Through a couple of different avenues I wandered, yet again, down a rabbit hole
leading to the topic of this post.  The first avenue was through my main focus
on a particular machine learning topic that utilized some concepts from
physics, which naturally led me to stochastic calculus.  The second avenue was
through some projects at work in the quantitative finance space, which is one
of the main applications of stochastic calculus.  Naively, I thought I could
write a brief post on it that would satisfy my curiosity -- that didn't work
out at all! The result is this extra long post.&lt;/p&gt;
&lt;p&gt;This post is about stochastic calculus, an extension of regular calculus to
stochastic processes.  It's not immediately obvious
but the rigour needed to properly understand some of the key ideas requires
going back to the measure theoretic definition of probability theory, so
that's where I start in the background. From there I quickly move on to
stochastic processes, the Wiener process, a particular flavour of stochastic
calculus called Itô calculus, and finally end with a couple of applications.
As usual, I try to include a mix of intuition, rigour where it helps intuition,
and some simple examples.  It's a deep and wide topic so I hope you enjoy my
digest of it.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://bjlkeng.github.io/posts/an-introduction-to-stochastic-calculus/"&gt;Read more…&lt;/a&gt; (72 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>Black-Scholes-Merton</category><category>Brownian motion</category><category>Langevin</category><category>mathjax</category><category>measure theory</category><category>probability</category><category>sigma algebra</category><category>stochastic calculus</category><category>Weiner process</category><category>white noise</category><guid>http://bjlkeng.github.io/posts/an-introduction-to-stochastic-calculus/</guid><pubDate>Mon, 12 Sep 2022 01:05:55 GMT</pubDate></item><item><title>Normalizing Flows with Real NVP</title><link>http://bjlkeng.github.io/posts/normalizing-flows-with-real-nvp/</link><dc:creator>Brian Keng</dc:creator><description>&lt;div&gt;&lt;p&gt;This post has been a long time coming.  I originally started working on it several posts back but
hit a roadblock in the implementation and then got distracted with some other ideas, which took
me down various rabbit holes (&lt;a class="reference external" href="http://bjlkeng.github.io/posts/hamiltonian-monte-carlo/"&gt;here&lt;/a&gt;,
&lt;a class="reference external" href="http://bjlkeng.github.io/posts/lossless-compression-with-asymmetric-numeral-systems/"&gt;here&lt;/a&gt;, and
&lt;a class="reference external" href="http://bjlkeng.github.io/posts/lossless-compression-with-latent-variable-models-using-bits-back-coding/"&gt;here&lt;/a&gt;).
It feels good to finally get back on track to some core ML topics.
The other nice thing about not being an academic researcher (not that I'm
really researching anything here) is that there is no pressure to do anything!
If it's just for fun, you can take your time with a topic, veer off track, and
the come back to it later.  It's nice having the freedom to do what you want (this applies to
more than just learning about ML too)!&lt;/p&gt;
&lt;p&gt;This post is going to talk about a class of deep probabilistic generative
models called normalizing flows.  Alongside &lt;a class="reference external" href="http://bjlkeng.github.io/posts/variational-autoencoders/"&gt;Variational Autoencoders&lt;/a&gt;
and autoregressive models &lt;a class="footnote-reference brackets" href="http://bjlkeng.github.io/posts/normalizing-flows-with-real-nvp/#id3" id="id1"&gt;1&lt;/a&gt; (e.g. &lt;a class="reference external" href="http://bjlkeng.github.io/posts/pixelcnn/"&gt;Pixel CNN&lt;/a&gt; and
&lt;a class="reference external" href="http://bjlkeng.github.io/posts/autoregressive-autoencoders/"&gt;Autoregressive autoencoders&lt;/a&gt;),
normalizing flows have been one of the big ideas in deep probabilistic generative models (I don't count GANs because they are not quite probabilistic).
Specifically, I'll be presenting one of the earlier normalizing flow
techniques named &lt;em&gt;Real NVP&lt;/em&gt; (circa 2016).
The formulation is simple but surprisingly effective, which makes it a good
candidate to understand more about normalizing flows.
As usual, I'll go over some background, the method, an implementation
(with commentary on the details), and some experimental results.  Let's get into the flow!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://bjlkeng.github.io/posts/normalizing-flows-with-real-nvp/"&gt;Read more…&lt;/a&gt; (32 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>CELEBA</category><category>CIFAR10</category><category>generative models</category><category>mathjax</category><category>MNIST</category><category>normalizing flows</category><guid>http://bjlkeng.github.io/posts/normalizing-flows-with-real-nvp/</guid><pubDate>Sat, 23 Apr 2022 23:36:05 GMT</pubDate></item><item><title>Hamiltonian Monte Carlo</title><link>http://bjlkeng.github.io/posts/hamiltonian-monte-carlo/</link><dc:creator>Brian Keng</dc:creator><description>&lt;div&gt;&lt;p&gt;Here's a topic I thought that I would never get around to learning because it was "too hard".
When I first started learning about Bayesian methods, I knew enough that I
should learn a thing or two about MCMC since that's the backbone
of most Bayesian analysis; so I learned something about it
(see my &lt;a class="reference external" href="http://bjlkeng.github.io/posts/markov-chain-monte-carlo-mcmc-and-the-metropolis-hastings-algorithm/"&gt;previous post&lt;/a&gt;).
But I didn't dare attempt to learn about the infamous Hamiltonian Monte Carlo (HMC).
Even though it is among the standard algorithms used in Bayesian inference, it
always seemed too daunting because it required "advanced physics" to
understand.  As usual, things only seem hard because you don't know them yet.
After having some time to digest MCMC methods, getting comfortable learning
more maths (see
&lt;a class="reference external" href="http://bjlkeng.github.io/posts/tensors-tensors-tensors/"&gt;here&lt;/a&gt;,
&lt;a class="reference external" href="http://bjlkeng.github.io/posts/manifolds/"&gt;here&lt;/a&gt;, and
&lt;a class="reference external" href="http://bjlkeng.github.io/posts/hyperbolic-geometry-and-poincare-embeddings/"&gt;here&lt;/a&gt;),
all of a sudden learning "advanced physics" didn't seem so tough (but there
sure was a lot of background needed)!&lt;/p&gt;
&lt;p&gt;This post is the culmination of many different rabbit holes (many much deeper
than I needed to go) where I'm going to attempt to explain HMC in simple and
intuitive terms to a satisfactory degree (that's the tag line of this blog
after all).  I'm going to begin by briefly motivating the topic by reviewing
MCMC and the Metropolis-Hastings algorithm then move on to explaining
Hamiltonian dynamics (i.e., the "advanced physics"), and finally discuss the HMC
algorithm along with some toy experiments I put together.  Most of the material
is based on [1] and [2], which I've found to be great sources for their
respective areas.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://bjlkeng.github.io/posts/hamiltonian-monte-carlo/"&gt;Read more…&lt;/a&gt; (52 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>Bayesian</category><category>Hamiltonian</category><category>mathjax</category><category>MCMC</category><category>Monte Carlo</category><guid>http://bjlkeng.github.io/posts/hamiltonian-monte-carlo/</guid><pubDate>Fri, 24 Dec 2021 00:07:05 GMT</pubDate></item><item><title>Lossless Compression with Latent Variable Models using Bits-Back Coding</title><link>http://bjlkeng.github.io/posts/lossless-compression-with-latent-variable-models-using-bits-back-coding/</link><dc:creator>Brian Keng</dc:creator><description>&lt;div&gt;&lt;p&gt;A lot of modern machine learning is related to this idea of "compression", or
maybe to use a fancier term "representations".  Taking a huge dimensional space
(e.g. images of 256 x 256 x 3 pixels = 196608 dimensions) and somehow compressing it into
a 1000 or so dimensional representation seems like pretty good compression to
me!  Unfortunately, it's not a lossless compression (or representation).
Somehow though, it seems intuitive that there must be a way to use what is learned in
these powerful lossy representations to help us better perform &lt;em&gt;lossless&lt;/em&gt;
compression, right?  Of course there is! (It would be too anti-climatic of a
setup otherwise.)&lt;/p&gt;
&lt;p&gt;This post is going to introduce a method to perform lossless compression that
leverages the learned "compression" of a machine learning latent variable
model using the Bits-Back coding algorithm.  Depending on how you first think
about it, this &lt;em&gt;seems&lt;/em&gt; like it should either be (a) really easy or (b) not possible at
all.  The reality is kind of in between with an elegant theoretical algorithm
that is brought down by the realities of discretization and imperfect learning
by the model.  In today's post, I'll skim over some preliminaries (mostly
referring you to previous posts), go over the main Bits-Back coding algorithm
in detail, and discuss some of the implementation details and experiments that
I did while trying to write a toy version of the algorithm.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://bjlkeng.github.io/posts/lossless-compression-with-latent-variable-models-using-bits-back-coding/"&gt;Read more…&lt;/a&gt; (25 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>asymmetric numeral systems</category><category>Bits-Back</category><category>compression</category><category>lossless</category><category>mathjax</category><category>MNIST</category><category>variational autoencoder</category><guid>http://bjlkeng.github.io/posts/lossless-compression-with-latent-variable-models-using-bits-back-coding/</guid><pubDate>Tue, 06 Jul 2021 16:00:00 GMT</pubDate></item></channel></rss>