<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://xenxeon.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://xenxeon.github.io/" rel="alternate" type="text/html" /><updated>2026-06-11T03:05:26+01:00</updated><id>https://xenxeon.github.io/feed.xml</id><title type="html">Tahir Hasan</title><subtitle>Computer vision and machine learning researcher — MSc Computer Vision, Robotics and Machine Learning at the University of Surrey. Works on hierarchical medical image analysis, continuous sign language recognition, and explainable AI.</subtitle><author><name>Tahir Hasan</name></author><entry><title type="html">Why a router network reduces inter-class confusion in GI imaging</title><link href="https://xenxeon.github.io/blog/2026/router-networks-gi-confusion/" rel="alternate" type="text/html" title="Why a router network reduces inter-class confusion in GI imaging" /><published>2026-06-08T00:00:00+01:00</published><updated>2026-06-08T00:00:00+01:00</updated><id>https://xenxeon.github.io/blog/2026/router-networks-gi-confusion</id><content type="html" xml:base="https://xenxeon.github.io/blog/2026/router-networks-gi-confusion/"><![CDATA[<p>Look at the confusion matrix of any flat GI endoscopy classifier and the
mistakes aren’t spread evenly — they pile up in small blocks of visually
similar classes. The model almost never confuses an anatomical landmark with a
polyp; it confuses <em>kinds</em> of similar findings with each other. That structure
is an invitation: factor the prediction,</p>

\[P(y \mid x) \;=\; \sum_{k} P(y \mid x, k)\, P(k \mid x),\]

<p>where \(k\) indexes a coarse group. If \(P(k \mid x)\) is nearly free —
and empirically it is — then all the hard work lives in \(P(y \mid x, k)\),
and a specialist trained only within group \(k\) faces a dramatically easier
decision boundary than one trained over all classes at once.</p>

<p>In code the inference path is almost embarrassingly simple:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">group_logits</span> <span class="o">=</span> <span class="n">router</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>              <span class="c1"># cheap, high-accuracy decision
</span><span class="n">k</span> <span class="o">=</span> <span class="n">group_logits</span><span class="p">.</span><span class="n">argmax</span><span class="p">(</span><span class="n">dim</span><span class="o">=-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">fine_logits</span> <span class="o">=</span> <span class="n">specialists</span><span class="p">[</span><span class="n">k</span><span class="p">](</span><span class="n">x</span><span class="p">)</span>       <span class="c1"># capacity spent where confusion lives
</span></code></pre></div></div>

<!-- TODO: full post. Outline below. -->

<p><strong>Outline of the full post:</strong></p>

<ol>
  <li>The block structure of GI confusion matrices — with a real figure from my
dissertation experiments.</li>
  <li>The mixture decomposition above, and what hard routing throws away
(when \(\operatorname{argmax}\) is safe, and when it isn’t).</li>
  <li>Why specialists beat one big model at matched parameter count —
an experiment, not a slogan.</li>
  <li>Failure mode: routing errors are unrecoverable; measuring the router’s
ceiling on end-to-end accuracy.</li>
  <li>What I’d try next: top-2 soft routing, specialist abstention, calibration.</li>
</ol>]]></content><author><name>Tahir Hasan</name></author><category term="research" /><category term="medical-imaging" /><summary type="html"><![CDATA[The intuition (and a little math) behind coarse-to-fine routing: confusion concentrates within groups, so that's where the capacity should go.]]></summary></entry><entry><title type="html">Lessons from building a 9,010-video sign language dataset</title><link href="https://xenxeon.github.io/blog/2026/lessons-9010-video-dataset/" rel="alternate" type="text/html" title="Lessons from building a 9,010-video sign language dataset" /><published>2026-05-18T00:00:00+01:00</published><updated>2026-05-18T00:00:00+01:00</updated><id>https://xenxeon.github.io/blog/2026/lessons-9010-video-dataset</id><content type="html" xml:base="https://xenxeon.github.io/blog/2026/lessons-9010-video-dataset/"><![CDATA[<p>Papers make dataset building sound like a procedure. It’s logistics:
scheduling humans, fighting storage, and discovering that your labelling
convention from week one fails on a sign you meet in week six. We collected
9,010 videos of continuous Bangla Sign Language across 530 word classes; the
model that consumes them took a fraction of the effort the dataset did. This
post is the honest accounting.</p>

<!-- TODO: full post. Outline below. -->

<p><strong>Outline of the full post:</strong></p>

<ol>
  <li>Picking 530 words — frequency lists vs. communicative coverage, and who
should make that call (hint: signers, not engineers).</li>
  <li>Continuous vs. isolated recording — why we chose the harder option, and what
it cost in annotation time.</li>
  <li>The annotation pipeline: tooling, label alignment, and the QC pass that
caught the most errors.</li>
  <li>Storage, backup, and the boring infrastructure that saved the project twice.</li>
  <li>What I’d redo: things I’d standardise on day one, and the metadata I wish
we’d captured.</li>
</ol>]]></content><author><name>Tahir Hasan</name></author><category term="datasets" /><category term="sign-language" /><summary type="html"><![CDATA[What actually consumed the time — and what I'd do differently — collecting a 530-class continuous BdSL video dataset.]]></summary></entry><entry><title type="html">From mechatronics to computer vision: what transfers</title><link href="https://xenxeon.github.io/blog/2026/mechatronics-to-computer-vision/" rel="alternate" type="text/html" title="From mechatronics to computer vision: what transfers" /><published>2026-04-12T00:00:00+01:00</published><updated>2026-04-12T00:00:00+01:00</updated><id>https://xenxeon.github.io/blog/2026/mechatronics-to-computer-vision</id><content type="html" xml:base="https://xenxeon.github.io/blog/2026/mechatronics-to-computer-vision/"><![CDATA[<p>I came to computer vision from a mechatronics degree — DH parameters and PID
loops, not transformers. The retraining was real, but less of it was wasted
than I expected: most of what an engineering education actually teaches is how
to debug a system you don’t fully understand, and that skill transfers to
machine learning embarrassingly well.</p>

<!-- TODO: full post. Outline below. -->

<p><strong>Outline of the full post:</strong></p>

<ol>
  <li>Kinematics is just geometry — and geometry is half of classical vision
(camera models, homographies, my Modified-DH habit of writing frames down
explicitly).</li>
  <li>Control loops → training loops: feedback, stability, and why “the loss went
down” is the same trap as “the step response looks fine”.</li>
  <li>Hardware debugging discipline: change one thing, log everything, distrust
the sensor first — i.e., distrust the dataloader first.</li>
  <li>What didn’t transfer: the statistics gap, and how I closed it.</li>
  <li>Advice for engineers crossing over (what I’d tell 2022-me).</li>
</ol>]]></content><author><name>Tahir Hasan</name></author><category term="career" /><category term="robotics" /><summary type="html"><![CDATA[Kinematics, control loops, and sensor debugging turn out to be surprisingly good preparation for ML research.]]></summary></entry></feed>