<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Miriam Alonso</title>
    <description>The latest articles on DEV Community by Miriam Alonso (@miriam_alonso_01).</description>
    <link>https://dev.to/miriam_alonso_01</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4086748%2F2db4110c-fac9-4492-a873-68f0f2b90f10.jpg</url>
      <title>DEV Community: Miriam Alonso</title>
      <link>https://dev.to/miriam_alonso_01</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/miriam_alonso_01"/>
    <language>en</language>
    <item>
      <title>5 LinkedIn mistakes that filter engineers out before anyone reads the CV</title>
      <dc:creator>Miriam Alonso</dc:creator>
      <pubDate>Thu, 20 Aug 2026 13:04:21 +0000</pubDate>
      <link>https://dev.to/miriam_alonso_01/5-linkedin-mistakes-that-filter-engineers-out-before-anyone-reads-the-cv-8jd</link>
      <guid>https://dev.to/miriam_alonso_01/5-linkedin-mistakes-that-filter-engineers-out-before-anyone-reads-the-cv-8jd</guid>
      <description>&lt;p&gt;Recruiter search on LinkedIn is a list view. Small photo on the left, name, headline, current company. That's the whole unit of decision for the first pass, and most people never look at their profile in that format.&lt;/p&gt;

&lt;p&gt;Five things that go wrong there, roughly in order of how often I see them.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The photo only works at full size
&lt;/h2&gt;

&lt;p&gt;Your profile page shows your photo at around 400px. Recruiter search results show it at about 48px, and the messaging sidebar goes smaller than that.&lt;/p&gt;

&lt;p&gt;At 48 pixels you have roughly 2,300 to work with. A face fills maybe half. Everything you liked about the photo, the depth of field, the environment, the fact that you're holding a coffee, is gone. What's left is a shape and two or three colours.&lt;/p&gt;

&lt;p&gt;The test takes 10 seconds. Zoom out in your image viewer until the photo is the size of a favicon. If you can't tell it's a person facing forward, neither can anyone scrolling a list of 40 candidates.&lt;/p&gt;

&lt;p&gt;Tighter crop fixes most of it. Chin to just above the hairline, face filling most of the square. It feels aggressive when you're looking at it full size, which is the point, because nobody is looking at it full size.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Your background has the same tone as your hair
&lt;/h2&gt;

&lt;p&gt;This one's specific and it costs more than it should.&lt;/p&gt;

&lt;p&gt;At small sizes the only thing separating you from the background is contrast. If you've got dark hair against a dark bookshelf, or light hair against a bright window, the two merge and your head loses its outline. The thumbnail reads as a smudge.&lt;/p&gt;

&lt;p&gt;Look at your photo in greyscale. If your head doesn't have a clear edge against what's behind it, the colour version won't fix it. A plain wall a couple of shades away from your hair beats an interesting room, at least at the size where the decision gets made.&lt;/p&gt;

&lt;p&gt;If you want a second opinion rather than eyeballing it, there's &lt;a href="https://www.betterpic.io/free-tools/ai-linkedin-picture-analyzer" rel="noopener noreferrer"&gt;a free analyser that scores it&lt;/a&gt; on contrast, crop and framing. Faster than asking a friend who'll tell you it's fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Your headline is your job title
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Senior Software Engineer at Acme&lt;/code&gt; tells a recruiter nothing they didn't already get from the company field two lines down.&lt;/p&gt;

&lt;p&gt;LinkedIn indexes the headline heavily for recruiter search. It's 220 characters of prime keyword real estate and most engineers spend 30 of them.&lt;/p&gt;

&lt;p&gt;The version that works is boring and specific: the stack, the domain, and what you actually do. &lt;code&gt;Senior backend engineer. Go, Postgres, payments infrastructure. Previously fintech, now healthcare.&lt;/code&gt; Someone searching for a Go engineer with payments experience finds that. They don't find &lt;code&gt;Senior Software Engineer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You don't need to be clever. Clever headlines rank for nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Your skills use your vocabulary, not theirs
&lt;/h2&gt;

&lt;p&gt;Recruiters search for the words in the job description they were handed. Those words are frequently not the words you'd use.&lt;/p&gt;

&lt;p&gt;You wrote &lt;code&gt;k8s&lt;/code&gt;. The req says &lt;code&gt;Kubernetes&lt;/code&gt;. You wrote &lt;code&gt;CI/CD&lt;/code&gt;. The req says &lt;code&gt;Jenkins&lt;/code&gt;. You listed &lt;code&gt;JS&lt;/code&gt; and they searched &lt;code&gt;JavaScript&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Neither of you is wrong, and the search still doesn't match. Put both forms in. It looks slightly redundant on the page and it doubles the surface area you're findable on.&lt;/p&gt;

&lt;p&gt;Same for job titles. If your company calls you a &lt;code&gt;Member of Technical Staff&lt;/code&gt;, nobody is searching for that. Put the industry-standard equivalent somewhere in the profile text.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. The photo is 3 years and one haircut old
&lt;/h2&gt;

&lt;p&gt;Not a vanity thing. A calibration thing.&lt;/p&gt;

&lt;p&gt;If your photo doesn't match what walks into the interview, the first 5 seconds of the call are spent recalibrating instead of listening to you. It's a small tax and it's entirely avoidable.&lt;/p&gt;

&lt;p&gt;The reason people don't update is that the alternative feels like a project. Book a photographer, take an afternoon off, spend 200 quid.&lt;/p&gt;

&lt;p&gt;It doesn't have to be. Decent &lt;a href="https://www.betterpic.io/linkedin-headshots" rel="noopener noreferrer"&gt;LinkedIn headshots&lt;/a&gt; come out of a phone camera and 10 minutes near a window, as long as you get the two things above right: tight crop, contrasting background. If you already have a photo you half-like, you can &lt;a href="https://www.betterpic.io/free-tools/profile-picture-editor" rel="noopener noreferrer"&gt;resize and re-crop it&lt;/a&gt; rather than starting over. Most photos that "don't work" are just badly cropped.&lt;/p&gt;

&lt;h2&gt;
  
  
  The order to do these in
&lt;/h2&gt;

&lt;p&gt;If you only do one, do the 48px test. It's free, it takes 10 seconds, and it catches the failure that affects every single impression your profile gets.&lt;/p&gt;

&lt;p&gt;Then the headline. That one decides whether you show up in the search at all, which is upstream of everything else on this list.&lt;/p&gt;

&lt;p&gt;The rest can wait for a rainy Sunday.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: I work on BetterPic, one of the tools linked above.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Background removal without a green screen is an underdetermined problem. Here's what the maths is doing.</title>
      <dc:creator>Miriam Alonso</dc:creator>
      <pubDate>Thu, 20 Aug 2026 13:04:02 +0000</pubDate>
      <link>https://dev.to/miriam_alonso_01/background-removal-without-a-green-screen-is-an-underdetermined-problem-heres-what-the-maths-is-3id</link>
      <guid>https://dev.to/miriam_alonso_01/background-removal-without-a-green-screen-is-an-underdetermined-problem-heres-what-the-maths-is-3id</guid>
      <description>&lt;p&gt;Every pixel in a photograph of a person against a wall is a blend of two things. The compositing equation is the whole problem in one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C = αF + (1 - α)B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;C&lt;/code&gt; is the pixel you can see. &lt;code&gt;F&lt;/code&gt; is the foreground colour, &lt;code&gt;B&lt;/code&gt; is the background colour, and &lt;code&gt;α&lt;/code&gt; is how much of that pixel belongs to the foreground. Solid shirt, α is 1. Empty wall, α is 0. A single strand of hair crossing that pixel, α is 0.3 and the pixel is genuinely part person, part wall.&lt;/p&gt;

&lt;p&gt;Now count the unknowns. &lt;code&gt;F&lt;/code&gt; is 3 numbers, &lt;code&gt;B&lt;/code&gt; is 3 numbers, &lt;code&gt;α&lt;/code&gt; is 1. That's 7. And you know 3, the RGB of &lt;code&gt;C&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Seven unknowns, three equations. The problem is underdetermined and no amount of cleverness makes it not underdetermined. Everything that follows is about finding constraints from somewhere else.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a green screen actually buys you
&lt;/h2&gt;

&lt;p&gt;It gives you &lt;code&gt;B&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you know the background is &lt;code&gt;(0, 177, 64)&lt;/code&gt; everywhere, you've eliminated 3 unknowns and the system becomes solvable per pixel. That's chroma keying, and it's why it's been in use since the 1930s. It turns an ill-posed inverse problem into a colour distance test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pixel&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;key_colour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;alpha&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;tolerance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;softness&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the core of it. Everything else in a keyer is refinement around the edges.&lt;/p&gt;

&lt;p&gt;The reason nobody shoots headshots on green is that the green bounces. Light hits the screen, reflects, and lands on the side of your subject's face and hair. Now your foreground colour &lt;code&gt;F&lt;/code&gt; is contaminated by the thing you're trying to remove, and you need spill suppression, which is its own pile of heuristics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Without a green screen, you get two families of approach
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Segmentation.&lt;/strong&gt; Train a network to output a mask directly. U²-Net and IS-Net are the ones most background removal tools are built on, and they're doing binary-ish classification: person or not person, per pixel.&lt;/p&gt;

&lt;p&gt;This is fast, runs in a browser via ONNX, and handles the 95% of the image that's obviously shirt or obviously wall. It falls apart on exactly the pixels where α is between 0 and 1, because the model is being asked for a yes or no on a pixel where the honest answer is 0.3.&lt;/p&gt;

&lt;p&gt;That's why cheap background removal gives you either a jagged cut-out edge or a soft halo of the old background. The model picked, and picking was the wrong operation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Alpha matting.&lt;/strong&gt; Split the image into three regions first: definitely foreground, definitely background, and an unknown band around the boundary. That's a trimap. Then solve for α only inside the unknown band, using the known regions as colour samples to constrain the equation.&lt;/p&gt;

&lt;p&gt;Closed-form matting does this by assuming &lt;code&gt;F&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; are locally smooth, which turns the whole thing into a sparse linear system you can actually solve. Deep matting approaches learn the same thing end to end.&lt;/p&gt;

&lt;p&gt;Matting is where the quality lives, and it's slower by an order of magnitude, which is why not everything uses it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hair is the whole difficulty
&lt;/h2&gt;

&lt;p&gt;I want to be precise about why, because "hair is hard" gets said a lot without the mechanism.&lt;/p&gt;

&lt;p&gt;A human hair is about 70 micrometres across. Photographed at portrait distance on a phone, that's well under one pixel wide. So a pixel containing hair contains hair &lt;strong&gt;and&lt;/strong&gt; whatever is behind it, permanently mixed at capture time. The information about where one ends and the other begins was destroyed by the sensor.&lt;/p&gt;

&lt;p&gt;You cannot recover it. You can only make a plausible guess, and the guess is constrained by the colours around it.&lt;/p&gt;

&lt;p&gt;Which leads to a rule that's genuinely useful when you're taking the photo: &lt;strong&gt;the recoverability of your hair edge depends on the contrast between your hair and the wall.&lt;/strong&gt; Dark hair against a dark bookshelf is unrecoverable, because the mixed pixel and the pure background pixel are the same colour and no algorithm can tell them apart. Dark hair against a light grey wall separates cleanly.&lt;/p&gt;

&lt;p&gt;That's not a limitation of the tool. It's information theory. The tool cannot invent a distinction that isn't in the file.&lt;/p&gt;

&lt;h2&gt;
  
  
  The second failure: colour spill survives a correct alpha
&lt;/h2&gt;

&lt;p&gt;Say you nailed α. You composite onto a new background:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C_new = αF + (1 - α)B_new
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it still looks wrong. There's a faint fringe of the old wall around the shoulders and through the hair.&lt;/p&gt;

&lt;p&gt;That's because &lt;code&gt;F&lt;/code&gt; itself was contaminated. Light from the old background bounced onto your subject. The semi-transparent pixels carry a colour cast that has nothing to do with the new scene, and mathematically your α was fine.&lt;/p&gt;

&lt;p&gt;Spill suppression is a separate pass, and most automatic tools either skip it or apply something crude like desaturating the boundary band. Which is why swapped backgrounds so often have a grey rim that reads as "cut out" even when you can't name what's wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means if you're taking the photo
&lt;/h2&gt;

&lt;p&gt;Everything above collapses into four shooting decisions.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Stand a metre or more off the wall.&lt;/strong&gt; Less bounce onto you, less spill in &lt;code&gt;F&lt;/code&gt;, and the background goes slightly out of focus which helps segmentation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick a wall that contrasts with your hair, not your shirt.&lt;/strong&gt; Hair is where the algorithm needs the signal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid backlight.&lt;/strong&gt; A window behind you puts a bright rim through your hair, which is beautiful and which destroys the hair edge for matting, because now the hair pixels are the same brightness as the background.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plain beats interesting.&lt;/strong&gt; A busy background gives the segmentation model more edges to confuse with your outline.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Do those and even a mediocre segmentation model gives you a clean result. Skip them and the best matting implementation in the world is working with a file that doesn't contain the answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Doing it in practice
&lt;/h2&gt;

&lt;p&gt;If you just want to swap the backdrop on a photo you already have, the &lt;a href="https://www.betterpic.io/headshot-backgrounds" rel="noopener noreferrer"&gt;background options&lt;/a&gt; that come out of a matting pipeline look very different from the ones that come out of a plain segmentation mask, and it's usually obvious at the hair line which you're looking at. Zoom in on the edge before you commit to anything.&lt;/p&gt;

&lt;p&gt;For the crop and the export you can &lt;a href="https://www.betterpic.io/free-tools/profile-picture-editor" rel="noopener noreferrer"&gt;do it in a browser&lt;/a&gt; without installing anything, and if the source photo is the problem rather than the background, &lt;a href="https://www.betterpic.io/ai-headshots" rel="noopener noreferrer"&gt;BetterPic&lt;/a&gt; generates from selfies instead, which sidesteps the matting question entirely because the background was never real to begin with.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway that isn't obvious
&lt;/h2&gt;

&lt;p&gt;Background removal quality is decided at capture, not in post. The algorithm can only redistribute information that's already in the file, and the mixed pixels at the hair boundary either contain a recoverable distinction or they don't.&lt;/p&gt;

&lt;p&gt;One metre off the wall and a background that contrasts with your hair. That's most of it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: I work on BetterPic, one of the tools linked above.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>machinelearning</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How AI headshot generators actually work: LoRA, 15 selfies, and the overfitting problem</title>
      <dc:creator>Miriam Alonso</dc:creator>
      <pubDate>Thu, 20 Aug 2026 13:04:01 +0000</pubDate>
      <link>https://dev.to/miriam_alonso_01/how-ai-headshot-generators-actually-work-lora-15-selfies-and-the-overfitting-problem-43p</link>
      <guid>https://dev.to/miriam_alonso_01/how-ai-headshot-generators-actually-work-lora-15-selfies-and-the-overfitting-problem-43p</guid>
      <description>&lt;p&gt;Every AI headshot product works roughly the same way under the hood, and once you know the shape of it, most of the weird results stop being weird.&lt;/p&gt;

&lt;p&gt;You upload 10 to 20 selfies. Twenty minutes later you get 100 portraits back. Some look exactly like you. Some look like your cousin. One looks like you wearing a jacket you've never owned, in an office you've never been to, and that one is usually the most interesting failure.&lt;/p&gt;

&lt;p&gt;Here's what's happening in between.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pipeline has four stages
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Face detection and crop.&lt;/strong&gt; Your uploads get run through a face detector, cropped square, aligned so the eyes sit on roughly the same horizontal line, and resized. Anything where the detector fails, or finds two faces, gets dropped.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Captioning.&lt;/strong&gt; Each image gets a text caption, usually auto-generated, containing a rare trigger token. Something like &lt;code&gt;sks person, wearing a blue shirt, indoor lighting&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fine-tuning.&lt;/strong&gt; A small adapter is trained on top of a frozen base model so the trigger token means your face.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generation.&lt;/strong&gt; The adapter gets loaded, and the product runs its own prompt library against it. &lt;code&gt;sks person, corporate headshot, grey backdrop, softbox lighting&lt;/code&gt;, a few hundred times with different seeds.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Stage 3 is where all the quality lives, so that's the one worth understanding.&lt;/p&gt;

&lt;h2&gt;
  
  
  LoRA in one paragraph that isn't hand-wavy
&lt;/h2&gt;

&lt;p&gt;A diffusion model has a few billion parameters. Fine-tuning all of them for one person's face would take hours on serious hardware and produce a multi-gigabyte file per customer. Nobody's running a business on that.&lt;/p&gt;

&lt;p&gt;LoRA, Low-Rank Adaptation, sidesteps it. Instead of updating a big weight matrix &lt;code&gt;W&lt;/code&gt;, you freeze &lt;code&gt;W&lt;/code&gt; and learn two skinny matrices &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; whose product has the same shape. At inference you compute &lt;code&gt;W + BA&lt;/code&gt;. If &lt;code&gt;W&lt;/code&gt; is 1024x1024 and you pick rank 16, then &lt;code&gt;A&lt;/code&gt; is 16x1024 and &lt;code&gt;B&lt;/code&gt; is 1024x16. That's 32,768 trained numbers instead of 1,048,576, so about 3%.&lt;/p&gt;

&lt;p&gt;These adapters get injected into the attention layers, which is where the model decides what a thing looks like rather than where it goes. Train for a few hundred steps, ship a file that's a few megabytes, load it in milliseconds.&lt;/p&gt;

&lt;p&gt;The rank is the knob. Low rank, say 4 to 8, and the adapter doesn't have enough capacity to hold your specific face, so you get a generic person who vaguely resembles you. High rank, 64 and up, and it has enough capacity to memorise your training set wholesale, which sounds good and isn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why 15 photos and not 500
&lt;/h2&gt;

&lt;p&gt;This surprises people. More data is supposed to be better.&lt;/p&gt;

&lt;p&gt;The problem is that the adapter learns everything your photos have in common, and it has no way to know which of those things you consider "your face".&lt;/p&gt;

&lt;p&gt;Upload 15 selfies taken in the same week and 12 of them will have the same haircut, the same lighting from the same window, and the same three t-shirts. The model learns &lt;code&gt;sks person&lt;/code&gt; means a face &lt;strong&gt;plus&lt;/strong&gt; that lighting &lt;strong&gt;plus&lt;/strong&gt; those shirts. Then you ask for a corporate headshot and it fights itself, because half of what it learned about you is a grey marl t-shirt in a bedroom.&lt;/p&gt;

&lt;p&gt;That's overfitting, and on faces it shows up in a specific way: the generated images look great and they all look like the same photo. Same angle, same expression, same background tone. The model isn't generating your face in new situations. It's reconstructing your training set with slight variation.&lt;/p&gt;

&lt;p&gt;Fifteen genuinely different photos beat 100 near-duplicates, every time. Different days, different rooms, different clothes, a couple of different angles.&lt;/p&gt;

&lt;h2&gt;
  
  
  The failure everyone hits: identity drift
&lt;/h2&gt;

&lt;p&gt;The opposite failure is more common in the cheap tools. You get 100 clean, well-lit, professional portraits of somebody who is nearly you.&lt;/p&gt;

&lt;p&gt;Two things usually cause it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Undertrained adapter.&lt;/strong&gt; The trigger token never fully bound to your face, so the base model's idea of "a person" is doing most of the work. You get a composite of you and the average face in the model's training data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prior preservation pulling too hard.&lt;/strong&gt; To stop the adapter from destroying the model's general concept of "person", training usually mixes in generated images of random people alongside yours. Too much of that and your identity gets regularised away.&lt;/p&gt;

&lt;p&gt;There's a measurable version of this. Take a face embedding model, generate an embedding for your input photos and for each output, and compute cosine similarity. Anything above about 0.65 reads as clearly the same person. Below 0.5 and most people looking at it will say "that's not quite you", even if they can't say why.&lt;/p&gt;

&lt;p&gt;If a product isn't filtering its outputs on something like that score, you're doing the filtering by hand, which is what it feels like when you get 100 images back and 12 are usable.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this changes about the photos you upload
&lt;/h2&gt;

&lt;p&gt;The practical version, given all of the above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vary the background more than the pose.&lt;/strong&gt; The background is the thing most likely to get baked into your identity, because it occupies the most pixels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Include at least 3 different tops.&lt;/strong&gt; Clothing is the second thing that gets baked in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One or two photos where you're not smiling.&lt;/strong&gt; If every input is a grin, every output is a grin, and it will look like the same grin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skip anything with a second face in it&lt;/strong&gt;, even blurred in the background. Detectors get confused and the crop goes wrong.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skip heavy filters.&lt;/strong&gt; Instagram-style colour grading gets learned as part of your face.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Roughly 15 photos, ideally from more than one occasion. The person who takes 15 selfies in one sitting in one room gets noticeably worse results than the person who digs 15 out of their camera roll from the last year.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trying it without paying for it
&lt;/h2&gt;

&lt;p&gt;If you want to see what the pipeline does with your photos before committing, most of the products have a free tier that runs a smaller version. You can put a handful of selfies through &lt;a href="https://www.betterpic.io/free-tools/free-ai-headshot-generator" rel="noopener noreferrer"&gt;a free generator&lt;/a&gt; and see the identity-drift problem for yourself, which is a faster education than reading about it.&lt;/p&gt;

&lt;p&gt;The paid versions of &lt;a href="https://www.betterpic.io/ai-headshots" rel="noopener noreferrer"&gt;AI headshots&lt;/a&gt; mostly differ in how much they spend on stage 4, the generation and filtering, rather than on anything exotic in stage 3. Everyone's doing LoRA or something close to it. The difference is how many candidates get generated and how aggressively the bad ones are thrown away before you see them.&lt;/p&gt;

&lt;p&gt;Which is also why the outputs vary so much between products at the same price. If you want to see the difference in practice, it's worth looking at &lt;a href="https://www.betterpic.io/compare/aragon" rel="noopener noreferrer"&gt;BetterPic side by side with Aragon&lt;/a&gt; rather than trusting anyone's sample gallery, including ours. Sample galleries are cherry-picked by definition.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one thing worth remembering
&lt;/h2&gt;

&lt;p&gt;The model has no concept of "your face" as separate from "the pixels in your uploads". Everything consistent across your training images becomes part of your identity as far as the adapter is concerned.&lt;/p&gt;

&lt;p&gt;So the quality of your result is decided almost entirely before you hit upload.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: I work on BetterPic, one of the tools linked above.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>ai</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I probed GitHub's avatar CDN. Your 4000px profile picture is 3KB by the time anyone sees it.</title>
      <dc:creator>Miriam Alonso</dc:creator>
      <pubDate>Thu, 20 Aug 2026 13:03:40 +0000</pubDate>
      <link>https://dev.to/miriam_alonso_01/i-probed-githubs-avatar-cdn-your-4000px-profile-picture-is-3kb-by-the-time-anyone-sees-it-5bmc</link>
      <guid>https://dev.to/miriam_alonso_01/i-probed-githubs-avatar-cdn-your-4000px-profile-picture-is-3kb-by-the-time-anyone-sees-it-5bmc</guid>
      <description>&lt;p&gt;GitHub serves every avatar through &lt;code&gt;avatars.githubusercontent.com&lt;/code&gt; with a size parameter stuck on the end. You've seen these URLs if you've ever opened devtools on a PR page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://avatars.githubusercontent.com/u/1?s=40&amp;amp;v=4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I was curious what &lt;code&gt;s&lt;/code&gt; actually does, so I pulled the same avatar at seven different values and measured the bytes that came back.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;s=40      3,144 bytes
s=80     10,710 bytes
s=128    25,298 bytes
s=260    94,255 bytes
s=400   215,383 bytes
s=460   282,530 bytes
s=1000  282,530 bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things fall out of that.&lt;/p&gt;

&lt;p&gt;460 is the ceiling. Ask for 1000 and you get the 460 file back, byte for byte. GitHub stores your avatar at 460x460 and throws away everything above it, whatever you uploaded.&lt;/p&gt;

&lt;p&gt;Then look at the top row again. The avatar next to your name on every issue comment, every review, every commit in the timeline, is 3,144 bytes. That's 1.1% of the file GitHub is holding for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nobody sees your profile page
&lt;/h2&gt;

&lt;p&gt;Think about where your face actually appears on GitHub.&lt;/p&gt;

&lt;p&gt;Your profile page renders it at 260px. That page gets visited when someone is deliberately looking you up, which is rare.&lt;/p&gt;

&lt;p&gt;Everywhere else it's 40px. Comment threads, review requests, the contributors list, the commit history. 40 pixels, on a screen, next to a username.&lt;/p&gt;

&lt;p&gt;So the picture you agonised over is being judged at roughly the size of this: ●&lt;/p&gt;

&lt;p&gt;At 40px you have about 1,600 pixels to work with. A face fills maybe half of that. You're not communicating an expression at that resolution. You're communicating a shape and two or three colours.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bit that surprised me
&lt;/h2&gt;

&lt;p&gt;I assumed the small sizes were just the big file scaled down in the browser. They're not. GitHub is generating and caching a separate encode at each size, and the compression at 40px is aggressive enough that fine detail is gone before it reaches the client.&lt;/p&gt;

&lt;p&gt;Which means the usual advice, upload the highest resolution you have, is only half right. Resolution above 460 does nothing on GitHub. What matters is whether the image still reads when a JPEG encoder has 3KB to describe it.&lt;/p&gt;

&lt;p&gt;Two things survive that budget: contrast between the subject and the background, and how much of the frame the face occupies. Everything else, the texture in your jumper, the bookshelf behind you, the lanyard, turns into mush.&lt;/p&gt;

&lt;h2&gt;
  
  
  Every platform disagrees with every other platform
&lt;/h2&gt;

&lt;p&gt;This is where it gets annoying if you keep one photo across your accounts.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Stored&lt;/th&gt;
&lt;th&gt;Rendered small&lt;/th&gt;
&lt;th&gt;File cap&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GitHub&lt;/td&gt;
&lt;td&gt;460x460&lt;/td&gt;
&lt;td&gt;40px in threads&lt;/td&gt;
&lt;td&gt;1MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LinkedIn&lt;/td&gt;
&lt;td&gt;up to 7680px wide&lt;/td&gt;
&lt;td&gt;~48px in feed&lt;/td&gt;
&lt;td&gt;8MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Slack&lt;/td&gt;
&lt;td&gt;512 to 1024&lt;/td&gt;
&lt;td&gt;24px in message list&lt;/td&gt;
&lt;td&gt;1MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discord&lt;/td&gt;
&lt;td&gt;512 recommended&lt;/td&gt;
&lt;td&gt;128px, often 32px in member list&lt;/td&gt;
&lt;td&gt;8MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I've checked GitHub myself. The others come from each platform's own documentation, so treat them as roughly right rather than gospel, and note that Slack's 1MB cap is a lot tighter than people expect.&lt;/p&gt;

&lt;p&gt;The practical version: export one square at 512x512, keep it under 1MB, and every platform in that table will take it and scale down cleanly. 512 divides evenly into 256, 128, 64 and 32, which means fewer resampling artefacts on the small renders than you'd get from, say, 460 or 400.&lt;/p&gt;

&lt;p&gt;If you want to check the crop at several sizes before you commit, a &lt;a href="https://www.betterpic.io/free-tools/profile-picture-editor" rel="noopener noreferrer"&gt;free profile picture editor&lt;/a&gt; will do the square crop and the export without opening anything heavier.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this changes about the photo itself
&lt;/h2&gt;

&lt;p&gt;I went back through my own avatars with the 40px test in mind and the pattern was pretty clear.&lt;/p&gt;

&lt;p&gt;The ones that worked had the face taking up most of the frame and a background that was one flat tone away from my skin and hair. The ones that didn't were technically better photographs. Nice depth of field, interesting environment, more of my shoulders in shot. At 40px they read as a grey smudge.&lt;/p&gt;

&lt;p&gt;So the checklist is short:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Crop tighter than feels right. Chin to just above the hairline.&lt;/li&gt;
&lt;li&gt;Pick a background that contrasts with your hair, not with your shirt.&lt;/li&gt;
&lt;li&gt;Look at it at 40px before you upload. Zoom out in your image viewer until it's the size of a favicon. If you can't tell it's you, nobody else can either.&lt;/li&gt;
&lt;li&gt;Skip the sunglasses, the hat brim shadow, and the busy patterned shirt. All three vanish or turn to noise.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Step 3 is the one people skip and it's the only one that actually tests anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you don't have a usable photo
&lt;/h2&gt;

&lt;p&gt;Plenty of us don't. I went about four years with a photo my flatmate took in a kitchen because the alternative was booking a studio.&lt;/p&gt;

&lt;p&gt;The generated options have got good enough to be worth a look. You can run a &lt;a href="https://www.betterpic.io/free-tools/free-ai-headshot-generator" rel="noopener noreferrer"&gt;free AI headshot generator&lt;/a&gt; on a handful of selfies and see what comes out before paying for anything.&lt;/p&gt;

&lt;p&gt;One thing that carries over from the 40px problem: the prompt controls framing and background separation, which are exactly the two variables that decide whether the result survives being shrunk. Tight crop and flat background beat cinematic lighting every time at this size. There's a decent breakdown of &lt;a href="https://www.betterpic.io/blog/ai-prompt-for-professional-headshot" rel="noopener noreferrer"&gt;prompt patterns that survive a diffusion model&lt;/a&gt; if you want to skip the trial and error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it on your own
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;s &lt;span class="k"&gt;in &lt;/span&gt;40 80 128 260 460 1000&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"s=&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="s2"&gt;  "&lt;/span&gt;
  curl &lt;span class="nt"&gt;-sL&lt;/span&gt; &lt;span class="s2"&gt;"https://avatars.githubusercontent.com/u/YOUR_ID?s=&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;v=4"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s1"&gt;'%{size_download} bytes\n'&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Swap &lt;code&gt;YOUR_ID&lt;/code&gt; for your numeric GitHub user ID, which you can get from &lt;code&gt;https://api.github.com/users/YOUR_USERNAME&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If your 460 number is close to 1MB you're near GitHub's upload cap and the smaller encodes are working harder than they need to. Re-export at 512 and it'll come down a lot.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: I work on BetterPic, one of the tools linked above.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>career</category>
      <category>productivity</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
