{"id":644,"date":"2026-04-06T19:16:21","date_gmt":"2026-04-06T11:16:21","guid":{"rendered":"https:\/\/www.artixels.com\/wp1\/?p=644"},"modified":"2026-04-06T19:19:24","modified_gmt":"2026-04-06T11:19:24","slug":"pixel-space-diffusion-model-from-scratch","status":"publish","type":"post","link":"https:\/\/www.artixels.com\/wp1\/2026\/04\/06\/pixel-space-diffusion-model-from-scratch\/","title":{"rendered":"Pixel-space Diffusion Model from scratch"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"has-small-font-size wp-block-paragraph\">Diffusion models available today often present themselves as powerful and generic image or video generator that they produce content based on user text prompts. This impression was simply a direct result of the design choices of these models. Driven by a goal of understanding better how diffusion model works, I trained a diffusion model from scratch myself for an image subject that I truly enjoy to photograph or sometimes to simulate using physically based methods. Summer cumulus clouds is what I love the most to photograph.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"747\" height=\"704\" src=\"https:\/\/www.artixels.com\/wp1\/wp-content\/uploads\/2026\/04\/tinyDiff_dataset.jpg\" alt=\"\" class=\"wp-image-663\" srcset=\"https:\/\/www.artixels.com\/wp1\/wp-content\/uploads\/2026\/04\/tinyDiff_dataset.jpg 747w, https:\/\/www.artixels.com\/wp1\/wp-content\/uploads\/2026\/04\/tinyDiff_dataset-300x283.jpg 300w\" sizes=\"auto, (max-width: 747px) 100vw, 747px\" \/><\/figure>\n\n\n\n<p class=\"has-small-font-size wp-block-paragraph\">Most images were shot during the 2025 Summer in Hong Kong, using the telephoto lens of an iPhone 15 Pro (it shoots like a 70mm lens I guess).  The main article I follow was a SIGGRAPH 2023 paper titled  &#8221; Iterative \ud835\udefc-(de)Blending: a Minimalist Deterministic Diffusion Model&#8221; by Heitz, Belcour and Chambon, and they even prepared a very good <a href=\"https:\/\/ggx-research.github.io\/publication\/2023\/05\/10\/publication-iadb.html\">explainer<\/a>.<\/p>\n\n\n\n<p class=\"has-small-font-size wp-block-paragraph\">At the beginning, I followed their sample code but I quickly realized that they simply relied on the Diffusion UNet from the HuggingFace library and this was not what I expected because I wanted to understand how various comopments in the models contribute to the end result with experiments.  At the end, I coded the model from scratch using PyTorch layers.  To be honest, to put together a model in PyTorch is a fairly straight forward task especially when we compare to any rendering research effort.  This from-scratch exercise allowed me to learn and catch up many latest development in machine learning since I completed <a href=\"https:\/\/www.artixels.com\/wp1\/2025\/04\/21\/deep-residual-denoising-for-mc-rendering\/\">my last ResNet based denoiser<\/a> project (my Ph.D. Thesis)<\/p>\n\n\n\n<p class=\"has-small-font-size wp-block-paragraph\">The final model architecture I chose is minimalistic, it is basically a 6-layer denoising UNet (on both downsample and upsample direction) using group normalization and the required time-embedding.  Absolutely no attention layer is used.   A model size of 22MB is good enough to learn the statistics very well and I even managed to push for a very small one of size 9.5MB.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1022\" height=\"1024\" src=\"https:\/\/www.artixels.com\/wp1\/wp-content\/uploads\/2026\/04\/diff_output_01_04O-1022x1024.jpg\" alt=\"\" class=\"wp-image-666\" srcset=\"https:\/\/www.artixels.com\/wp1\/wp-content\/uploads\/2026\/04\/diff_output_01_04O-1022x1024.jpg 1022w, https:\/\/www.artixels.com\/wp1\/wp-content\/uploads\/2026\/04\/diff_output_01_04O-300x300.jpg 300w, https:\/\/www.artixels.com\/wp1\/wp-content\/uploads\/2026\/04\/diff_output_01_04O-150x150.jpg 150w, https:\/\/www.artixels.com\/wp1\/wp-content\/uploads\/2026\/04\/diff_output_01_04O-768x770.jpg 768w, https:\/\/www.artixels.com\/wp1\/wp-content\/uploads\/2026\/04\/diff_output_01_04O.jpg 1024w\" sizes=\"auto, (max-width: 1022px) 100vw, 1022px\" \/><\/figure>\n\n\n\n<p class=\"has-small-font-size wp-block-paragraph\">The images above are generated from a model with the filter configuration (# of filters in each denoising layer) of {32, 64, 96, 128, 160, 192}, 32 for group normalization and time-embedding dimension of 512.  Since a simple pixel-space diffusion model functions like a filter, so it&#8217;s possible to feed image of arbitrary size into the denoiser, and the image below is from an input of 1024 x 1024 noisy image.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/www.artixels.com\/wp1\/wp-content\/uploads\/2026\/04\/combined_1024x1024.jpg\" alt=\"\" class=\"wp-image-667\" srcset=\"https:\/\/www.artixels.com\/wp1\/wp-content\/uploads\/2026\/04\/combined_1024x1024.jpg 1024w, https:\/\/www.artixels.com\/wp1\/wp-content\/uploads\/2026\/04\/combined_1024x1024-300x300.jpg 300w, https:\/\/www.artixels.com\/wp1\/wp-content\/uploads\/2026\/04\/combined_1024x1024-150x150.jpg 150w, https:\/\/www.artixels.com\/wp1\/wp-content\/uploads\/2026\/04\/combined_1024x1024-768x768.jpg 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"has-small-font-size wp-block-paragraph\">At the moment, many improved diffusion approaches are already available, e.g. flow matching or mean flow for one-step denoising etc.  I am planning to extend the experiment for conditional generation.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Diffusion models available today often present themselves as powerful and generic image or video generator that they produce content based on user text prompts. This impression was simply a direct result of the design choices of these models. Driven by a goal of understanding better how diffusion model works, I trained a diffusion model from [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":666,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,10,8],"tags":[],"class_list":["post-644","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ml","category-pin","category-rnd"],"_links":{"self":[{"href":"https:\/\/www.artixels.com\/wp1\/wp-json\/wp\/v2\/posts\/644","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.artixels.com\/wp1\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.artixels.com\/wp1\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.artixels.com\/wp1\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.artixels.com\/wp1\/wp-json\/wp\/v2\/comments?post=644"}],"version-history":[{"count":5,"href":"https:\/\/www.artixels.com\/wp1\/wp-json\/wp\/v2\/posts\/644\/revisions"}],"predecessor-version":[{"id":668,"href":"https:\/\/www.artixels.com\/wp1\/wp-json\/wp\/v2\/posts\/644\/revisions\/668"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.artixels.com\/wp1\/wp-json\/wp\/v2\/media\/666"}],"wp:attachment":[{"href":"https:\/\/www.artixels.com\/wp1\/wp-json\/wp\/v2\/media?parent=644"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.artixels.com\/wp1\/wp-json\/wp\/v2\/categories?post=644"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.artixels.com\/wp1\/wp-json\/wp\/v2\/tags?post=644"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}