<?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://aryanp2107.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://aryanp2107.github.io/" rel="alternate" type="text/html" /><updated>2026-08-16T11:58:50-04:00</updated><id>https://aryanp2107.github.io/feed.xml</id><title type="html">Aryan Patel’s Projects</title><subtitle>I love studying the Human Brain and watching sports.</subtitle><author><name>Aryan Patel</name></author><entry><title type="html">Class-Agnostic Maritime Obstacle Detection with Simulated IMU-Guided Horizon Stabilization for Autonomous Surface Vessels</title><link href="https://aryanp2107.github.io/projects/maritime-obstacle-detection/" rel="alternate" type="text/html" title="Class-Agnostic Maritime Obstacle Detection with Simulated IMU-Guided Horizon Stabilization for Autonomous Surface Vessels" /><published>2026-08-15T00:00:00-04:00</published><updated>2026-08-15T00:00:00-04:00</updated><id>https://aryanp2107.github.io/projects/maritime-obstacle-detection</id><content type="html" xml:base="https://aryanp2107.github.io/projects/maritime-obstacle-detection/"><![CDATA[<h2 id="overview">Overview</h2>

<p>Course project for CS5330 (Pattern Recognition and Computer Vision, Prof. Bruce Maxwell) with Ananda Sangli and Julee Chung. We built a class-agnostic obstacle detection pipeline for autonomous surface vessels — one that treats every floating obstacle as “hit-or-not-hit” rather than trying to classify it, because on the water what you need to avoid isn’t neatly categorizable.</p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/70D5531bZ5Y?autoplay=1&amp;mute=1&amp;controls=0&amp;loop=1&amp;playlist=70D5531bZ5Y" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""></iframe>

<h2 id="two-questions-we-set-out-to-answer">Two questions we set out to answer</h2>

<p><strong>RQ1: Does synthetic IMU-based horizon stabilization improve detection on rocking footage?</strong></p>

<p>Boats pitch and roll. Detectors trained on stable dashcam data assume a level horizon, and every degree of roll shifts objects relative to the frame. We synthesized IMU readings from video motion and applied rotational homography to stabilize each frame before detection — asking whether removing the roll before inference beats letting the detector figure it out.</p>

<p><strong>RQ2: Does Kalman-filter tracking reduce bounding-box jitter and identity flicker across frames?</strong></p>

<p>Frame-by-frame detection produces boxes that shimmer and swap IDs across consecutive frames — bad for downstream avoidance logic. We ran detections through a Kalman filter that models each obstacle’s position and velocity, smoothing box coordinates and maintaining stable identity across occlusions.</p>

<h2 id="approach">Approach</h2>

<p><strong>Dataset.</strong> Unified benchmark from USVTrack (tracking annotations) and LaRS (semantic segmentation for the maritime domain). Combining them gave us both the class-agnostic labels we wanted and the domain variance (open water, harbors, obstacles at different scales) needed for a generalizable detector.</p>

<p><strong>Detector.</strong> YOLOv8n — nano variant chosen for real-time inference budgets on the kind of hardware an actual surface vessel would carry. Not the largest model available, deliberately.</p>

<p><strong>RQ1 pipeline.</strong></p>
<ol>
  <li>Estimate roll angle per frame from video motion (synthetic IMU)</li>
  <li>Apply rotational homography to level the horizon</li>
  <li>Run YOLOv8n on the stabilized frame</li>
  <li>Compare mAP / recall against the unstabilized baseline</li>
</ol>

<p><strong>RQ2 pipeline.</strong></p>
<ol>
  <li>Take raw YOLOv8n detections per frame</li>
  <li>Feed into a Kalman filter tracking position + velocity per obstacle</li>
  <li>Measure bounding box jitter and ID switch rate against the unfiltered baseline</li>
</ol>

<h2 id="results">Results</h2>

<p>Full result videos across all test scenarios — including RQ1 horizon stabilization comparisons and RQ2 Kalman-filtered tracking sequences — are available in the <a href="https://drive.google.com/drive/folders/1hVo72Dl8oZ0iFva8McKMr67D0-OpRV-n?usp=sharing">project results folder on Google Drive</a>.</p>

<h2 id="stack">Stack</h2>

<ul>
  <li><strong>Detector:</strong> YOLOv8n (Ultralytics)</li>
  <li><strong>Benchmark:</strong> USVTrack + LaRS (unified)</li>
  <li><strong>Stabilization:</strong> synthetic IMU + rotational homography (OpenCV)</li>
  <li><strong>Tracking:</strong> custom Kalman filter (position + velocity state)</li>
  <li><strong>Language:</strong> Python, PyTorch</li>
  <li><strong>Evaluation:</strong> mAP, recall, ID switch rate, bounding-box jitter metrics</li>
</ul>

<h2 id="resources">Resources</h2>

<ul>
  <li><strong>Report (IEEE format):</strong> <a href="assets/CS5330_Final_Report.pdf">PDF</a></li>
  <li><strong>Code:</strong> <a href="https://github.com/aryanp2107/maritime_obstacle_detection">github.com/aryanp2107/maritime_obstacle_detection</a></li>
  <li><strong>Team:</strong> Aryan Patel, Ananda Sangli, Julee Chung</li>
  <li><strong>Course:</strong> CS5330 (Pattern Recognition and Computer Vision), Prof. Bruce Maxwell, Northeastern University</li>
</ul>]]></content><author><name>Aryan Patel</name></author><category term="projects" /><category term="object-detection" /><category term="maritime" /><category term="yolo" /><category term="kalman-filter" /><category term="computer-vision" /><summary type="html"><![CDATA[Class-agnostic obstacle detection for autonomous surface vessels on the unified USVTrack + LaRS benchmark, with synthetic IMU horizon stabilization and Kalman-filtered tracking for identity stability.]]></summary></entry><entry><title type="html">Transformers and Vision Transformers</title><link href="https://aryanp2107.github.io/teaching/transformers-and-vision-transformers-explained/" rel="alternate" type="text/html" title="Transformers and Vision Transformers" /><published>2026-08-01T00:00:00-04:00</published><updated>2026-08-01T00:00:00-04:00</updated><id>https://aryanp2107.github.io/teaching/transformers-and-vision-transformers-explained</id><content type="html" xml:base="https://aryanp2107.github.io/teaching/transformers-and-vision-transformers-explained/"><![CDATA[<p>Recorded for Prof. Bruce Maxwell’s CS5330 (Pattern Recognition and Computer Vision) at Northeastern. The goal was to walk through the Transformer architecture from Vaswani et al. (2017) end-to-end, then show how Dosovitskiy et al. (2021) ported the whole thing to images with the Vision Transformer.</p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/T5hza77LqfM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""></iframe>

<ul>
  <li>Vaswani et al. (2017). Attention Is All You Need. <a href="https://arxiv.org/abs/1706.03762">arXiv:1706.03762</a></li>
  <li>Dosovitskiy et al. (2021). An Image Is Worth 16×16 Words. <a href="https://arxiv.org/abs/2010.11929">arXiv:2010.11929</a></li>
  <li>Johnson, J. (2022). EECS 498/598 Lecture 18: Vision Transformers. University of Michigan</li>
  <li>Bugnot (2025); Mazurek (2021); Arora / Bukhari (2021) — additional explainer resources listed in the deck</li>
</ul>]]></content><author><name>Aryan Patel</name></author><category term="teaching" /><category term="transformers" /><category term="vision-transformer" /><category term="self-attention" /><category term="deep-learning" /><summary type="html"><![CDATA[A CS5330 teaching video building up the Transformer from tokenization to self-attention to the MLP block, then porting the whole architecture to images with ViT.]]></summary></entry><entry><title type="html">Yann LeCun: Architect of Modern Computer Vision</title><link href="https://aryanp2107.github.io/teaching/yann-lecun-architect-of-modern-cv/" rel="alternate" type="text/html" title="Yann LeCun: Architect of Modern Computer Vision" /><published>2026-07-28T00:00:00-04:00</published><updated>2026-07-28T00:00:00-04:00</updated><id>https://aryanp2107.github.io/teaching/yann-lecun-architect-of-modern-cv</id><content type="html" xml:base="https://aryanp2107.github.io/teaching/yann-lecun-architect-of-modern-cv/"><![CDATA[<p>For CS5330 (Pattern Recognition and Computer Vision), Prof. Bruce Maxwell asked each of us to present on a figure who shaped the field. I picked Yann LeCun.</p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/acaC7b89EK8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""></iframe>]]></content><author><name>Aryan Patel</name></author><category term="teaching" /><category term="computer-vision" /><category term="history" /><category term="presentation" /><summary type="html"><![CDATA[A CS5330 presentation on my favorite figure in computer vision]]></summary></entry><entry><title type="html">The Fourier Transform</title><link href="https://aryanp2107.github.io/teaching/The-Fourier-Transform/" rel="alternate" type="text/html" title="The Fourier Transform" /><published>2026-07-14T00:00:00-04:00</published><updated>2026-07-14T00:00:00-04:00</updated><id>https://aryanp2107.github.io/teaching/The-Fourier-Transform</id><content type="html" xml:base="https://aryanp2107.github.io/teaching/The-Fourier-Transform/"><![CDATA[<p>The video was captured as a part of my CS5330 course at Northeastern</p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/N2lX1ULf0Aw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>]]></content><author><name>Aryan Patel</name></author><category term="teaching" /><summary type="html"><![CDATA[An overview of the Fourier Transform]]></summary></entry><entry><title type="html">Multi-class brain tumor classifier</title><link href="https://aryanp2107.github.io/projects/brain-tumor-mri-cnn-vs-vit/" rel="alternate" type="text/html" title="Multi-class brain tumor classifier" /><published>2026-05-06T00:00:00-04:00</published><updated>2026-05-06T00:00:00-04:00</updated><id>https://aryanp2107.github.io/projects/brain-tumor-mri-cnn-vs-vit</id><content type="html" xml:base="https://aryanp2107.github.io/projects/brain-tumor-mri-cnn-vs-vit/"><![CDATA[<h2 id="overview">Overview</h2>

<p>A multi-class brain tumor classifier deployed on Arxelos, comparing a 30-layer CNN I built from scratch against ViT-B/16 on the same MRI scans. Every prediction ships with interpretability maps.</p>

<h2 id="the-most-interesting-failure">The most interesting failure</h2>

<p>A pituitary tumor scan. The CNN classified it as “no tumor” at <strong>97% confidence</strong>. The ViT correctly identified it as pituitary at <strong>50.3% confidence</strong>.</p>

<p>That confidence asymmetry is the actual finding, not the misclassification. The CNN wasn’t uncertain and wrong — it was <em>confidently</em> wrong, which is the worst kind of failure mode for a clinical model. The ViT wasn’t confidently right — it was hedging but correct, which is honest calibration in the face of an ambiguous case.</p>

<h2 id="the-agreement-case--same-tools-different-story">The agreement case — same tools, different story</h2>

<p>To make the interpretability comparison honest, I ran the same tooling on a “no tumor” scan both models correctly classified.</p>

<p>CNN Grad-CAM was broad and warm, centered on ventricles, thalami, and basal ganglia — reasonable attention to normal anatomical landmarks. When the CNN is right, it’s at least looking in the right neighborhood.</p>

<p>ViT Attention Rollout was tightly focused on bilateral hotspots corresponding to choroid plexus / thalamic structures — the ViT was using anatomical symmetry as evidence of normalcy. A more sophisticated reasoning strategy than the CNN’s “everything looks normal-shaped.”</p>

<h2 id="stack">Stack</h2>

<ul>
  <li><strong>CNN:</strong> 30-layer architecture built from scratch in TensorFlow/Keras, 96.2% test accuracy on the multi-class task</li>
  <li><strong>ViT:</strong> ViT-B/16, fine-tuned from <code class="language-plaintext highlighter-rouge">google/vit-base-patch16-224</code></li>
  <li><strong>Interpretability:</strong> Grad-CAM (<code class="language-plaintext highlighter-rouge">pytorch-grad-cam</code>), Attention Rollout (custom implementation), SmoothGrad</li>
  <li><strong>Serving:</strong> FastAPI backend, Docker container, deployed on Azure Container Apps</li>
  <li><strong>Frontend:</strong> the live neuro-AI page on Arxelos, with per-prediction visualization overlays and a focus-region extractor for both models</li>
</ul>

<h2 id="what-id-change-next">What I’d change next</h2>

<p><strong>Consensus confidence.</strong> The 97% wrong CNN vs. 50% correct ViT pattern is the argument for a joint metric that penalizes disagreement rather than displaying either raw softmax. Multiplying the two distributions and renormalizing is the naive version; a properly calibrated ensemble is the real move. Either way, showing 97% confidence on the CNN’s misclassification without context is a UI failure I want to fix.</p>

<p><strong>Sharper Attention Rollout.</strong> My current implementation averages heads uniformly. The Chefer et al. (2021) method that combines gradients with attention would produce cleaner localization, particularly for smaller lesions where uniform-head averaging blurs the signal.</p>

<p><strong>Annotation audit.</strong> In the pituitary failure case, the ViT’s attention on the parietal region (not the sellar area where pituitary tumors actually sit) suggests the ground-truth label may itself be wrong on that scan. Before extending the training set, I’d want to review the annotations on the ambiguous cases with someone who reads MRIs for a living.</p>

<h2 id="links">Links</h2>

<ul>
  <li>Live: <a href="https://arxelos.com/neuro-ai">arxelos.com/neuro-ai</a></li>
  <li>Github: <a href="https://github.com/aryanp2107/Arxelos/blob/main/Brain_tumor_detection.ipynb">github.com/aryanp2107</a></li>
</ul>]]></content><author><name>Aryan Patel</name></author><category term="projects" /><category term="medical-imaging" /><category term="interpretability" /><category term="vision-transformer" /><category term="grad-cam" /><summary type="html"><![CDATA[A 30-layer CNN I built from scratch vs. ViT-B/16 on brain MRI for 4 types of brain tumors.]]></summary></entry><entry><title type="html">Autonomous Perception Ensemble: RT-DETR + U-Net + MiDaS on BDD100K</title><link href="https://aryanp2107.github.io/projects/autonomous-perception-ensemble-bdd100k/" rel="alternate" type="text/html" title="Autonomous Perception Ensemble: RT-DETR + U-Net + MiDaS on BDD100K" /><published>2026-04-03T00:00:00-04:00</published><updated>2026-04-03T00:00:00-04:00</updated><id>https://aryanp2107.github.io/projects/autonomous-perception-ensemble-bdd100k</id><content type="html" xml:base="https://aryanp2107.github.io/projects/autonomous-perception-ensemble-bdd100k/"><![CDATA[<h2 id="overview">Overview</h2>

<p>A self-driving perception stack in miniature. Three complementary models running on the same BDD100K dashcam frame — RT-DETR tells you <em>what</em> is in the scene, a from-scratch U-Net tells you <em>where</em> you can drive, MiDaS tells you <em>how far</em> everything is. Each handles a different piece of the scene-understanding problem; together they form a full spatial picture from a single frame.</p>

<p>Deployed live at <a href="https://arxelos.com/perception">arxelos.com/perception</a>.</p>

<h2 id="the-stack">The stack</h2>

<ul>
  <li><strong>Detection:</strong> RT-DETR, real-time transformer-based detector, trained on BDD100K’s 10 object classes (cars, trucks, pedestrians, cyclists, traffic signs, etc.)</li>
  <li><strong>Segmentation:</strong> U-Net implemented from scratch in PyTorch for drivable area segmentation</li>
  <li><strong>Depth:</strong> MiDaS for monocular depth estimation</li>
  <li><strong>Deployment:</strong> All three exported to ONNX for cross-platform inference; served through the Arxelos FastAPI backend</li>
</ul>

<h2 id="the-bug-that-taught-me-the-most-the-missing-69000-images">The bug that taught me the most: the missing 69,000 images</h2>

<p>When I first started training RT-DETR on BDD100K, my data loader reported only 1,156 training images. The dataset should have had ~70,000. That’s a factor of 60 off.</p>

<p>First instinct was a wrong path or incomplete download, but <code class="language-plaintext highlighter-rouge">du -sh</code> on the directory checked out — the bytes were there. Ran two globs side by side:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">glob</span><span class="p">.</span><span class="n">glob</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">IMG_TRAIN</span><span class="si">}</span><span class="s">/*.jpg"</span><span class="p">)</span>           <span class="c1"># → 1,156
</span><span class="n">glob</span><span class="p">.</span><span class="n">glob</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">IMG_TRAIN</span><span class="si">}</span><span class="s">/**/*.jpg"</span><span class="p">,</span> <span class="n">recursive</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>  <span class="c1"># → ~70,000
</span></code></pre></div></div>

<p>The images existed, just not where my code was looking. BDD100K’s zip stores training images across four subdirectories — <code class="language-plaintext highlighter-rouge">trainA/</code>, <code class="language-plaintext highlighter-rouge">trainB/</code>, <code class="language-plaintext highlighter-rouge">testA/</code>, <code class="language-plaintext highlighter-rouge">testB/</code> — inside <code class="language-plaintext highlighter-rouge">images/100k/train/</code>. A non-recursive glob only caught what was sitting in the top-level directory.</p>

<p><strong>But the recursive glob alone wasn’t enough.</strong> Ultralytics (the RT-DETR training framework) uses a path-swapping convention where it replaces <code class="language-plaintext highlighter-rouge">images/</code> with <code class="language-plaintext highlighter-rouge">labels/</code> to find annotation files. With images nested in subdirectories but labels stored flat, the path swap would silently break — training would run but on wrong image/label pairs.</p>

<p>Fix required two changes: switch to <code class="language-plaintext highlighter-rouge">recursive=True</code> globs everywhere, <em>and</em> flatten all subdirectory images into the top-level <code class="language-plaintext highlighter-rouge">train/</code> and <code class="language-plaintext highlighter-rouge">val/</code> directories with <code class="language-plaintext highlighter-rouge">shutil.move()</code>. That restored the one-to-one <code class="language-plaintext highlighter-rouge">images/</code> ↔ <code class="language-plaintext highlighter-rouge">labels/</code> mapping Ultralytics expects.</p>

<p><strong>Takeaway.</strong> The code fix was ~10 lines. The lesson was bigger: never trust assumptions about dataset layout, and never trust that a training framework’s file-path conventions are documented where you’d expect. I now run a recursive file count as the <em>first</em> step after downloading any dataset, before writing a line of training code. Cheap insurance against silent training failures — the kind where loss goes down and metrics look reasonable, but the model is learning on the wrong data.</p>

<h2 id="what-id-change-next">What I’d change next</h2>

<ul>
  <li><strong>Temporal consistency.</strong> Right now each frame is processed independently. Adding a lightweight tracker (ByteTrack, SORT) across detections would give stable IDs and enable higher-level reasoning like “this pedestrian just entered the crosswalk”</li>
  <li><strong>Depth calibration.</strong> MiDaS outputs relative depth, not metric. Calibrating to real distances (using known scene geometry, camera intrinsics, or a small labeled subset) would make the output actually usable for downstream decisions</li>
  <li><strong>Late fusion.</strong> The three models currently run in parallel and their outputs are visualized side-by-side. A fusion step — “which detections lie on drivable area and at what depth?”  would produce a genuinely joint scene representation rather than three overlaid maps</li>
</ul>

<h2 id="links">Links</h2>

<ul>
  <li>Live demo: <a href="https://arxelos.com/perception">arxelos.com/perception</a></li>
  <li>Github: <a href="https://github.com/aryanp2107/Autonomous-Perception-Ensemble">github.com/aryanp2107/Autonomous-Perception-Ensemble</a></li>
</ul>]]></content><author><name>Aryan Patel</name></author><category term="projects" /><category term="autonomous-driving" /><category term="object-detection" /><category term="segmentation" /><category term="depth-estimation" /><category term="onnx" /><summary type="html"><![CDATA[A miniature self-driving perception stack on 70K BDD100K dashcam images. RT-DETR for detection, U-Net (from scratch) for drivable area, MiDaS for depth. All three exported to ONNX and deployed live on Arxelos.]]></summary></entry><entry><title type="html">Arxelos: A Deployed AI/ML Platform</title><link href="https://aryanp2107.github.io/projects/arxelos-ai-platform/" rel="alternate" type="text/html" title="Arxelos: A Deployed AI/ML Platform" /><published>2026-03-21T00:00:00-04:00</published><updated>2026-03-21T00:00:00-04:00</updated><id>https://aryanp2107.github.io/projects/arxelos-ai-platform</id><content type="html" xml:base="https://aryanp2107.github.io/projects/arxelos-ai-platform/"><![CDATA[<h2 id="overview">Overview</h2>

<p>Arxelos is the platform I built to deploy my AI/ML work under one roof — not scattered notebooks.</p>

<p><a href="https://arxelos.com">arxelos.com</a>.</p>

<p>Building one platform forced decisions individual notebooks avoid:</p>

<ul>
  <li><strong>Consistent model serving.</strong> Every model behind the same FastAPI backend, containerized, deployed to Azure Container Apps. One request/response contract, one latency budget, one error-handling path.</li>
  <li><strong>ONNX across frameworks.</strong> All models exported to ONNX so PyTorch, TensorFlow, and pre-trained checkpoints run through the same serving code without framework-specific glue.</li>
  <li><strong>Interpretability and structured outputs as first-class citizens.</strong> Grad-CAM, Attention Rollout, SmoothGrad, depth colormaps, segmentation overlays, citations. Every prediction ships with the artifacts a user needs to interpret it, not just a scalar output.</li>
</ul>

<h2 id="stack">Stack</h2>

<ul>
  <li><strong>Frontend:</strong> the arxelos.com site itself, with per-module visualization</li>
  <li><strong>Backend:</strong> FastAPI, containerized with Docker</li>
  <li><strong>Deployment:</strong> Azure Container Apps</li>
  <li><strong>Models:</strong> TensorFlow/Keras (custom CNN), PyTorch (ViT, U-Net from scratch), pre-trained checkpoints (RT-DETR, MiDaS)</li>
  <li><strong>Model format:</strong> ONNX across the board</li>
  <li><strong>RAG stack:</strong> LangChain, ChromaDB, PubMed as source corpus</li>
  <li><strong>Interpretability:</strong> <code class="language-plaintext highlighter-rouge">pytorch-grad-cam</code>, custom Attention Rollout, SmoothGrad</li>
</ul>

<h2 id="what-id-change-next">What I’d change next</h2>

<ul>
  <li><strong>Observability.</strong> No logging or per-endpoint telemetry yet. Adding request logs, latency histograms, and prediction-distribution tracking would let me detect drift and debug production failures properly.</li>
  <li><strong>Shared uncertainty layer.</strong> Each module surfaces confidence differently — softmax on the classifier, IoU on segmentation, retrieval scores on RAG. A shared calibrated-uncertainty layer across modules would make outputs comparable.</li>
  <li><strong>RAG improvements.</strong> Retrieval is fine on well-formed clinical queries, degrades on vague ones. Reranking, query rewriting, and hybrid dense-plus-sparse search are the next moves.</li>
</ul>

<h2 id="links">Links</h2>

<ul>
  <li>platform: <a href="https://arxelos.com">arxelos.com</a></li>
</ul>]]></content><author><name>Aryan Patel</name></author><category term="projects" /><category term="platform" /><category term="deployment" /><category term="fastapi" /><category term="onnx" /><category term="azure" /><summary type="html"><![CDATA[A solo-built, production-deployed platform hosting my AI/ML work under one roof — brain tumor classification with CNN vs ViT interpretability, an autonomous perception ensemble on BDD100K, and a PubMed-grounded literature RAG pipeline.]]></summary></entry><entry><title type="html">Demographic-Aware Face Generation: Per-Ethnicity FID for a Fairness cGAN</title><link href="https://aryanp2107.github.io/projects/demographic-aware-face-generation-cgan/" rel="alternate" type="text/html" title="Demographic-Aware Face Generation: Per-Ethnicity FID for a Fairness cGAN" /><published>2026-02-11T00:00:00-05:00</published><updated>2026-02-11T00:00:00-05:00</updated><id>https://aryanp2107.github.io/projects/demographic-aware-face-generation-cgan</id><content type="html" xml:base="https://aryanp2107.github.io/projects/demographic-aware-face-generation-cgan/"><![CDATA[<h2 id="overview">Overview</h2>

<p>Sports video games (EA FC, NBA 2K, Madden) auto-generate faces for scouted international players — badly. Same faces recur, ethnic demographics don’t match countries, and detail is allocated unevenly across groups. Four-person course project exploring whether a conditional GAN could produce a fairer baseline for auto-generated player faces.</p>

<h2 id="the-finding">The finding</h2>

<p><strong>No significant ethnic bias detected at the model’s capability level.</strong> Trained on FairFace (62,575 images filtered to ages 20–49, resized to 128×128), the cGAN produced faces of comparable quality across all 7 ethnic categories at the optimal checkpoint (epoch 33 of 50):</p>

<ul>
  <li><strong>Per-ethnicity FID:</strong> 139.3–155.2, ~3% variance across groups</li>
  <li><strong>Human perceptual rating:</strong> 4.2–6.8 / 10, ~7.7% variance</li>
</ul>

<p>The important word is <em>comparable</em>. Absolute quality was limited — an FID around 150 means generated faces are far from photorealistic, and the perceptual survey confirmed the ceiling. But the <em>distribution</em> of quality across ethnicities was flat, which was the fairness question being tested.</p>

<h2 id="my-role">My role</h2>

<p>Owned hyperparameter tuning, model training, and optimal checkpoint selection across two full training runs on a Colab A100. Trade-offs I was navigating:</p>

<ul>
  <li><strong>Generator vs. discriminator learning rates:</strong> settled on 2e-4 / 1e-4 to keep D from dominating and collapsing the generator</li>
  <li><strong>Batch size</strong> at 128 balanced training stability against A100 memory</li>
  <li><strong>Checkpoint selection</strong> turned out to matter more than expected — model quality peaked at epoch 33 of 50, with later checkpoints showing signs of mode collapse. Tracking per-ethnicity FID across epochs was necessary rather than just using final weights</li>
</ul>

<p>Teammates handled evaluation methodology (Caleb Lee), data pipeline (Gaurav Bhatnagar) and UI (Yohanan Ben-Gad).</p>

<h2 id="stack">Stack</h2>

<ul>
  <li><strong>Model:</strong> cGAN with projection discriminator (Miyato &amp; Koyama 2018), spectral normalization (Miyato et al. 2018)</li>
  <li><strong>Data:</strong> FairFace (Karkkainen &amp; Joo 2021), 62,575 images, 7 ethnic categories, 128×128</li>
  <li><strong>Training:</strong> PyTorch, Colab A100, batch size 128, 50 epochs</li>
  <li><strong>Evaluation:</strong> clean-fid for per-group FID, human perceptual survey (1–10 scale)</li>
  <li><strong>Referenced work:</strong> TTUR (Heusel et al. 2017)</li>
</ul>

<h2 id="what-id-change-next">What I’d change next</h2>

<p>The model at ~100K parameters is undersized for the problem — that’s the ceiling on realism, and it’s why FID sits around 150. A larger backbone (StyleGAN2 at even a modest scale) would likely bring FID into the 30–50 range. The interesting piece — per-ethnicity variance under 3% is the methodology that carries forward, and it should hold or improve at higher model capacity.</p>

<h2 id="links">Links</h2>
<ul>
  <li>Github: <a href="https://github.com/calebl37/demographic-aware-face-generation">github.com/calebl37/demographic-aware-face-generation</a></li>
</ul>]]></content><author><name>Aryan Patel</name></author><category term="projects" /><category term="generative-models" /><category term="cgan" /><category term="fairness" /><category term="computer-vision" /><summary type="html"><![CDATA[Conditional GAN for face generation across 7 ethnic categories. Per-ethnicity FID variance <3% and human perceptual variance <8% — no significant ethnic bias at the model's capability level.]]></summary></entry><entry><title type="html">100 Days of ML: A Structured Self-Study Curriculum</title><link href="https://aryanp2107.github.io/projects/100-days-of-ml-structured-self-study/" rel="alternate" type="text/html" title="100 Days of ML: A Structured Self-Study Curriculum" /><published>2025-11-13T00:00:00-05:00</published><updated>2025-11-13T00:00:00-05:00</updated><id>https://aryanp2107.github.io/projects/100-days-of-ml-structured-self-study</id><content type="html" xml:base="https://aryanp2107.github.io/projects/100-days-of-ml-structured-self-study/"><![CDATA[<h2 id="overview">Overview</h2>

<p>A structured self-study challenge that walks ML end-to-end, from NumPy fundamentals to transformers and GANs. Three phases, capstone projects between them, so each phase forces a synthesis before moving on.</p>

<h2 id="progress">Progress</h2>

<p><strong>46/100 days complete.</strong> Phase 1 and Phase 2 done, Phase 3 in progress.</p>

<ul>
  <li><strong>Phase 1 — Data Foundations (Days 1–15):</strong> NumPy/pandas, missing data, outliers, feature engineering, PCA, EDA, time series, geospatial. Capstone: rain prediction on Australian weather data.</li>
  <li><strong>Phase 2 — Classical ML (Days 16–40):</strong> regression, trees, random forests, XGBoost, SVMs, KNN, clustering (K-Means, DBSCAN, hierarchical, GMM), ensembles, SHAP interpretability. Capstone: loan default prediction on Lending Club data.</li>
  <li><strong>Phase 3 — Deep Learning (Days 41–60):</strong> neural networks, CNNs, transfer learning, augmentation, object detection, RNNs, transformers, GloVe, autoencoders, VAEs, GANs, U-Nets, autonomous perception, RL basics.</li>
</ul>

<h2 id="why-this-format">Why this format</h2>

<p>The capstones between phases are the point. It’s easy to work through tutorials and feel like you understand something; it’s harder to build an end-to-end pipeline that has to run. Requiring a synthesis project before moving on makes gaps visible — feature engineering isn’t a concept until I’ve built a pipeline for it, SHAP isn’t understood until I’ve explained it on my own model.</p>

<h2 id="featured-capstones">Featured capstones</h2>

<p><strong>Rain prediction (Day 15).</strong> Binary classification on Australian weather. Missing data handling → encoding → feature scaling → model selection.</p>

<p><strong>Loan default prediction (Days 38–40).</strong> End-to-end pipeline on Lending Club data: EDA → feature engineering → hyperparameter tuning → SHAP interpretability → production pipeline. <a href="https://github.com/aryanp2107/loan-default-prediction">Standalone repo</a>.</p>

<h2 id="stack">Stack</h2>

<ul>
  <li><strong>Languages:</strong> Python</li>
  <li><strong>ML:</strong> scikit-learn, XGBoost, LightGBM</li>
  <li><strong>Deep learning:</strong> PyTorch, TensorFlow/Keras</li>
  <li><strong>Data:</strong> pandas, NumPy</li>
  <li><strong>Viz:</strong> matplotlib, seaborn</li>
  <li><strong>Interpretability:</strong> SHAP</li>
</ul>

<h2 id="links">Links</h2>

<ul>
  <li>Full repo: <a href="https://github.com/aryanp2107/100-ML-Projects">github.com/aryanp2107/100-ML-Projects</a></li>
  <li>Loan default capstone: <a href="https://github.com/aryanp2107/loan-default-prediction">github.com/aryanp2107/loan-default-prediction</a></li>
</ul>]]></content><author><name>Aryan Patel</name></author><category term="projects" /><category term="self-study" /><category term="machine-learning" /><category term="deep-learning" /><category term="curriculum" /><summary type="html"><![CDATA[A 100-day self-designed ML curriculum in three phases — data foundations, classical ML, deep learning — with capstones between phases. Currently at 67/100]]></summary></entry><entry><title type="html">Lung Disease Detection: Comparing Sequential, Functional and VGG-16 CNNs</title><link href="https://aryanp2107.github.io/projects/lung-disease-detection-comparing-cnn-architectures/" rel="alternate" type="text/html" title="Lung Disease Detection: Comparing Sequential, Functional and VGG-16 CNNs" /><published>2025-01-19T00:00:00-05:00</published><updated>2025-01-19T00:00:00-05:00</updated><id>https://aryanp2107.github.io/projects/lung-disease-detection-comparing-cnn-architectures</id><content type="html" xml:base="https://aryanp2107.github.io/projects/lung-disease-detection-comparing-cnn-architectures/"><![CDATA[<h2 id="overview">Overview</h2>

<p>Undergraduate research paper co-authored with Rohit Chauhan and Suryajeet Gupta at Quantum University. We benchmarked three CNN variants — a custom sequential model, a custom functional (multi-branch) model, and a VGG-16 transfer-learning setup across chest X-ray and CT-scan classification for three conditions.</p>

<h2 id="results">Results</h2>

<ul>
  <li><strong>Pneumonia (sequential, chest X-ray):</strong> F1 98.55%, accuracy 98.43%, recall 96.33%</li>
  <li><strong>Tuberculosis (sequential, chest X-ray):</strong> F1 97.99%, accuracy 99.4%, recall 98.88%</li>
  <li><strong>Lung cancer (functional, CT scans):</strong> accuracy 99.9%, specificity 99.89%</li>
</ul>

<p>Sequential model outperformed on X-ray tasks; the functional model (7×7 and 1×1 branches concatenated, feeding five 3×3 conv layers) generalized better on CT cancer classification.</p>

<h2 id="stack">Stack</h2>

<ul>
  <li><strong>Framework:</strong> TensorFlow / Keras</li>
  <li><strong>Datasets:</strong> Covid-19 radiography database (Kaggle), Mendeley chest X-ray posteroanterior collection, lung CT-scan dataset</li>
  <li><strong>Preprocessing:</strong> 224×224 resize; horizontal flip, zoom, shear, rotation, rescale augmentation</li>
  <li><strong>Sequential:</strong> 5 conv layers, LeakyReLU (α=0.66), max pooling, Adam @ lr=1e-4, 50 epochs</li>
  <li><strong>Functional:</strong> 7×7 and 1×1 branches over 3×3, concatenated, then five 3×3 conv layers</li>
  <li><strong>Pretrained:</strong> VGG-16 with ImageNet weights</li>
</ul>

<h2 id="what-id-change-next">What I’d change next</h2>

<p>The reported accuracies are strong but the test sets are small (85 images for TB, 278 for cancer) and the training data leaves external validity unproven. A properly held-out external cohort, cross-validation, and interpretability checks would be table stakes today — themes that motivated my later work.</p>

<h2 id="links">Links</h2>
<ul>
  <li>Preprint (unpublished): <a href="/assets/ResearchPaper(LungDamage).pdf">PDF</a></li>
  <li>Notebook: <a href="https://github.com/aryanp2107/DL-Projects/blob/main/Lung_Disease_%7C_TensorCTScan.ipynb">github.com/aryanp2107/DL-Projects</a></li>
</ul>]]></content><author><name>Aryan Patel</name></author><category term="projects" /><category term="deep-learning" /><category term="medical-imaging" /><category term="cnn" /><category term="transfer-learning" /><summary type="html"><![CDATA[Three CNN architectures benchmarked across pneumonia, tuberculosis, and lung cancer detection from chest X-rays and CT scans. Sequential won the X-ray tasks (F1 98%+); functional won CT cancer classification (99.9% accuracy).]]></summary></entry></feed>