<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>Vadzim Tsitko</title>
 <link href="https://vtitko.com/atom.xml" rel="self"/>
 <link href="https://vtitko.com/"/>
 <updated>2026-04-23T11:14:15+00:00</updated>
 <id>https://vtitko.com</id>
 <author>
   <name></name>
   <email></email>
 </author>

 
 <entry>
   <title>How to Find a Data Science Job in 2024 (with experience)</title>
   <link href="https://vtitko.com/2024/04/13/find-data-science-job/"/>
   <updated>2024-04-13T00:00:00+00:00</updated>
   <id>https://vtitko.com/2024/04/13/find-data-science-job</id>
   <content type="html">&lt;p&gt;At the end of 2023, I decided to change my job. I had worked previously in multiple companies as a Data Scientist (Machine Learning Engineer): an outsourcing firm, a small startup, and a medium-sized mobile applications publisher. But I had never worked before in big tech or similar companies, so my main focus was to find a job in one of those.&lt;/p&gt;

&lt;p&gt;In this article, I will tell you about how I found a new job, how I prepared for the interviews, and what my success rate was. And because experience matters a lot, I will provide my background information below.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I am a Data Scientist with 4 years of experience.&lt;/li&gt;
  &lt;li&gt;I have a bachelor’s degree in Computer Science.&lt;/li&gt;
  &lt;li&gt;I was looking for a job in Europe because I am living there.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;preparation&quot;&gt;Preparation&lt;/h1&gt;

&lt;p&gt;In this part, I will tell you how I prepared for the interviews. Some parts could be relevant to any Software Engineering position, while other apply only to Data Scientists or Machine Learning Engineers. You can skip the parts you are not interested in.&lt;/p&gt;

&lt;h2 id=&quot;coding&quot;&gt;Coding&lt;/h2&gt;

&lt;p&gt;Because my main focus was big tech companies, it made sense to improve my LeetCode skills. In university, I took multiple algorithms courses, read a couple of books on algorithms and completed one or two online courses. So, I was not a novice at all. But still, knowing general algorithms and solving LeetCode tasks in 20 minutes are quite different tasks.&lt;/p&gt;

&lt;p&gt;I started solving LeetCode problems. My plan was to solve at least one per day. And I did so roughly for 3 months, with a one-week break for vacation. In the beginning, I spent around 3-4 hours a day. In the last month, I just solved the daily challenge as fast as I could.&lt;/p&gt;

&lt;p&gt;As a result, I solved 300 tasks. I think it is much more than you actually need. But I loved the process.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2024-04-13-find-data-science-job/leetcode.png&quot; alt=&quot;LeetCode results&quot; class=&quot;center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You need theoretical knowledge to solve those questions. Again, I could be biased because I learned this stuff in university and by myself for a couple of years beforehand. But from the experience of my friends, solving the Udemy course &lt;a href=&quot;https://www.udemy.com/course/master-the-coding-interview-data-structures-algorithms/&quot;&gt;Master the Coding Interview: Data Structures + Algorithms&lt;/a&gt; and reading &lt;a href=&quot;https://www.amazon.com/Grokking-Algorithms-illustrated-programmers-curious/dp/1617292230&quot;&gt;Grokking Algorithms: An Illustrated Guide for Programmers and Other Curious People&lt;/a&gt; will be enough to begin. I did it too, just a little earlier.&lt;/p&gt;

&lt;p&gt;But theory will not take you far. You need lots of practice. And for that, we all use LeetCode. From my standpoint, it will be enough to solve the whole &lt;a href=&quot;https://www.techinterviewhandbook.org/grind75&quot;&gt;Grind 75&lt;/a&gt; or &lt;a href=&quot;https://neetcode.io/roadmap&quot;&gt;neetcode.io&lt;/a&gt;, which will take you a couple of weeks with a tight schedule.&lt;/p&gt;

&lt;p&gt;I think the best approach will be to spend 30-40 minutes on each task. I always begin by drawing needed structures and conditions. This leads me to the initial solution, which then I optimize if needed. After that, I write the solution in pseudo-code on paper. And then transform it into my Python solution. This may sound like overkill. But in reality, the first step takes most of the time. If you have a drawing of your solution, then writing the code will be a piece of cake.&lt;/p&gt;

&lt;p&gt;If you are not able to solve the task by yourself, watch the solution on the &lt;a href=&quot;https://www.youtube.com/@NeetCode&quot;&gt;NeetCode&lt;/a&gt; YouTube channel, and then code the solution again by yourself. This way, you will memorize and understand the solution much better than simply copying it from the Solutions tab.&lt;/p&gt;

&lt;p&gt;If some topic is not understandable to you, I recommend spending a couple of hours on YouTube. For example, the legendary channel of &lt;a href=&quot;https://www.youtube.com/@abdul_bari&quot;&gt;Abdul Bari&lt;/a&gt;. And I suggest implementing the new structure or algorithm in your programming language from scratch. It will solidify your base and understanding of the basic Computer Science topics.&lt;/p&gt;

&lt;p&gt;And remember, you don’t need to be a genius to solve those tasks. You need patience, time, and consistency. I still can’t solve some of the medium tasks, and I skip hard tasks altogether. Don’t be hard on yourself, just stick to it, and you will succeed.&lt;/p&gt;

&lt;h2 id=&quot;data-science-and-machine-learning&quot;&gt;Data Science and Machine Learning&lt;/h2&gt;

&lt;p&gt;Those topics are really broad and everybody expects different things from those specialists. Some companies need to build matching systems, some LLM-powered tools, and some analytical dashboards. Therefore, it’s crucial to adapt according to the job description. But, there is general knowledge which you should know for most interviews.&lt;/p&gt;

&lt;p&gt;I think Chip Huyen did an amazing job writing the &lt;a href=&quot;https://huyenchip.com/ml-interviews-book/&quot;&gt;Machine Learning Interviews Book&lt;/a&gt;. To prepare for the interview, I recommend reading this book and solving tasks in which you are not proficient. For example, I forgot probability theory. Working through tasks from this book, along with a few additional ones from the internet, allowed me to refresh my knowledge.&lt;/p&gt;

&lt;p&gt;Also, going through the list of popular questions is helpful too, for example, &lt;a href=&quot;https://github.com/youssefHosni/Data-Science-Interview-Questions-Answers/tree/main&quot;&gt;Data-Science-Interview-Questions-Answers&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;machine-learning-system-design&quot;&gt;Machine Learning System Design&lt;/h2&gt;

&lt;p&gt;This topic is growing rapidly. But I still have some resources that I love.&lt;/p&gt;

&lt;p&gt;First of all, these two books:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.amazon.com/Designing-Machine-Learning-Systems-Production-Ready/dp/1098107969?&amp;amp;_encoding=UTF8&amp;amp;tag=chiphuyen-20&amp;amp;linkCode=ur2&amp;amp;linkId=0a1dbab0e76f5996e29e1a97d45f14a5&amp;amp;camp=1789&amp;amp;creative=9325&quot;&gt;Designing Machine Learning Systems: An Iterative Process for Production-Ready Applications&lt;/a&gt; by Chip Huyen (again)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.manning.com/books/machine-learning-system-design&quot;&gt;Machine Learning System Design&lt;/a&gt; by Valerii Babushkin and Arseny Kravchenko&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These books are great; they are not about interviews but about the general approach to building ML Systems.&lt;/p&gt;

&lt;p&gt;I also loved this &lt;a href=&quot;https://towardsdatascience.com/how-to-answer-any-machine-learning-system-design-interview-question-a98656bb7ff0&quot;&gt;article&lt;/a&gt; by Stefan Hosein. It provides you with a practical approach to handling this type of interview. Last, but not least, I do recommend &lt;a href=&quot;https://www.youtube.com/watch?v=VPg2Uu1MYgI&amp;amp;list=PLBRXq5LaddfzDBjg6soIwJJA2klXXs6ni&amp;amp;index=18&amp;amp;ab_channel=karpov.courses&quot;&gt;ML System Design Interview videos&lt;/a&gt; from karpov.courses. These are originally in Russian, but in my opinion, they are the best videos on the topic. So I strongly suggest you watch them with English subtitles. And by the way, they are hosted by Valerii Babushkin, one of the authors of the Machine Learning System Design book.&lt;/p&gt;

&lt;p&gt;Generally, reading articles and being curious about the field pays off in this interview.&lt;/p&gt;

&lt;h2 id=&quot;mock-interviews&quot;&gt;Mock Interviews&lt;/h2&gt;

&lt;p&gt;These are crucial. You can test your interviewing abilities in a controlled environment. There are services for which you can pay, but I recommend using the help of your friends or reaching out to people on LinkedIn and asking them for help. You will be surprised how many people are willing to help you for free. They gain experience from it too!&lt;/p&gt;

&lt;h2 id=&quot;resume&quot;&gt;Resume&lt;/h2&gt;

&lt;p&gt;There is an infinite amount of information on this topic. My general recommendations are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Keep it to just one page.&lt;/li&gt;
  &lt;li&gt;Do not add your photo. I know you are pretty, but a picture takes up space.&lt;/li&gt;
  &lt;li&gt;Use a simple and minimalistic &lt;a href=&quot;https://townsquare.media/site/393/files/2013/09/Redmon-Resume.pdf&quot;&gt;design&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Sort blocks by importance, from top to bottom.&lt;/li&gt;
  &lt;li&gt;Add not only technical but also business information. For example, “By building X, I improved retention by Y.”&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;interviews&quot;&gt;Interviews&lt;/h1&gt;

&lt;p&gt;The interviewing process sucks. It is not the best proxy for your job performance, but it is the main one we use. I think there is a lot of information on how to prepare for interviews mentally.&lt;/p&gt;

&lt;p&gt;My main advice for anybody is to gain experience. Do mock interviews, and interview for companies you are not interested in first. Don’t worry about rejections. Interviewing is a skill in itself. To become better, you need to practice.&lt;/p&gt;

&lt;p&gt;With the companies you want to work for, you can significantly boost your chances using simple things.&lt;/p&gt;

&lt;p&gt;First of all, try to have at least a couple of real interviews with other companies before you interview with the company of your dreams.&lt;/p&gt;

&lt;p&gt;Second, research the company and the role. Try to think of tasks you can potentially solve in this company. Prepare answers to the basic behavioral questions and prepare your questions for the interviewer. Read the interview section on the company’s Glassdoor page.&lt;/p&gt;

&lt;p&gt;Third, apply to the companies using a referral system. For example, via an acquaintance of yours. Or again, find a person who works there on LinkedIn and ask them to refer you. Most people will refer you without any problems. They want to get a bonus if you wind up in their company.&lt;/p&gt;

&lt;p&gt;Fourth, don’t freak out about rejections. You can reapply after half a year in most cases. And then you will be much more experienced and prepared.&lt;/p&gt;

&lt;h2 id=&quot;duration&quot;&gt;Duration&lt;/h2&gt;

&lt;p&gt;Searching for a job takes time. I think you should expect the process to take 3 to 6 months, from the application to the first day in the company. Typically, with smaller companies or startups, it takes less time, while with big tech companies, the process is longer.&lt;/p&gt;

&lt;h2 id=&quot;questions&quot;&gt;Questions&lt;/h2&gt;

&lt;p&gt;Do not be afraid to ask questions. If anything, it will make things better, not worse.&lt;/p&gt;

&lt;p&gt;Before each interview, ask your HR questions about the interview. What will this interview be about? How should I prepare? Can I look at the LinkedIn profile of the interviewer? These questions will allow you to prepare much better. You will know what to expect, which will take some of the anxiety off you.&lt;/p&gt;

&lt;p&gt;Ask questions during the interview if you think that you didn’t understand your task fully. Sometimes interviewers ask ambiguous questions and expect you to ask clarifying questions in response. Or they simply weren’t able to formulate the question correctly.&lt;/p&gt;

&lt;p&gt;And finally, at the end of each interview, you will be able to ask your questions. Use this time wisely. Ask questions that are worrying you, about the role and the company. Before the interview, prepare a list of general questions you will ask every company and a separate list for the company you are interviewing with. This way, you will learn something useful about the company. And, which is also important, the interviewer will notice that you are prepared and that you are interested in the company. If you can’t come up with your list, use the &lt;a href=&quot;https://github.com/viraptor/reverse-interview&quot;&gt;reverse-interview&lt;/a&gt; GitHub repository as your muse.&lt;/p&gt;

&lt;p&gt;Overall, questions are extremely important. And sometimes asking the right questions will make a lot of impact.&lt;/p&gt;

&lt;h2 id=&quot;my-latest-experience&quot;&gt;My Latest Experience&lt;/h2&gt;

&lt;p&gt;Below, you can see the table I used to track my interviewing progress with all the companies in 2024. Looks scary, doesn’t it? Most of those are rejections or ignoring of my applications. If you like the table, you can duplicate it from &lt;a href=&quot;https://www.notion.so/7f482df8d44e47c78205227f4c21d74f?pvs=21&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2024-04-13-find-data-science-job/stats.png&quot; alt=&quot;Interview Outcomes Table&quot; class=&quot;center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Let’s look at the pie plot below. Am I a Data Scientist or not?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2024-04-13-find-data-science-job/pie_chart.png&quot; alt=&quot;Interview Success Rate&quot; class=&quot;center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Again, it looks scary. My hit rate is 3.6%, just 3 out of 83 companies. It would be fair to say that with companies under the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stopped&lt;/code&gt; label, I was pretty deep in the process. However, by this stage, I had already accepted an offer. So, I didn’t want to waste people’s time on myself.&lt;/p&gt;

&lt;p&gt;In the table below, you can find the absolute numbers if you are interested.&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Offer&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Stopped&lt;/td&gt;
      &lt;td&gt;6&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;No answer&lt;/td&gt;
      &lt;td&gt;32&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Rejection&lt;/td&gt;
      &lt;td&gt;42&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Total&lt;/td&gt;
      &lt;td&gt;83&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Luckily, I got an offer from the company I wanted to work for — &lt;a href=&quot;https://www.revolut.com/careers/&quot;&gt;Revolut&lt;/a&gt;. I visited their meet-ups and used their application daily. A colleague from one of my previous jobs works there, so he referred me for the position I wanted. And I was able to pass all the interviews and got the role! But without all the preparation, I wouldn’t have been able to do this.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;For the most part, finding a job is a numbers game. But, using an analytical approach, you will maximize your chances of getting offers from the companies you want to work for.&lt;/p&gt;

&lt;p&gt;Take your time. Learn from your failures. Be prepared and practice a lot. Hard work will pay off sooner or later.&lt;/p&gt;

&lt;p&gt;And a huge thanks to &lt;a href=&quot;https://www.linkedin.com/in/maria-zakharevich/&quot;&gt;Maria Zakharevich&lt;/a&gt; and &lt;a href=&quot;https://www.linkedin.com/in/antonmasiukevich/&quot;&gt;Anton Masiukevich&lt;/a&gt; for their invaluable assistance with this article.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>What I’ve Learned After 200 Random Coffees</title>
   <link href="https://vtitko.com/2023/12/04/random-coffee/"/>
   <updated>2023-12-04T00:00:00+00:00</updated>
   <id>https://vtitko.com/2023/12/04/random-coffee</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-12-04-random-coffee/woman_cafe_res.png&quot; alt=&quot;woman_cafe_res.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Many of us have been on first dates. For the first 10 minutes, it’s usually awkward, but then you find common topics to discuss, share a few jokes, and enjoy a coffee. As a result, you have a great time and learn something new. Even if you don’t plan to see that person again, it’s still a valuable experience.&lt;/p&gt;

&lt;p&gt;Random Coffees are quite similar. You meet with a stranger, perhaps through your company’s random coffee program, an online community, or a mobile app. You have an hour to talk about anything you want: careers, sports, books, films, dogs, or even relationships.&lt;/p&gt;

&lt;p&gt;And the best thing is, it’s periodic—once a week, for example. This lets you meet a ton of new people and establish a wonderful habit.&lt;/p&gt;

&lt;h2 id=&quot;why-i-started-doing-random-coffees&quot;&gt;Why I Started Doing Random Coffees&lt;/h2&gt;

&lt;p&gt;I began participating in Random Coffees four years ago when I was a Junior Machine Learning Engineer at a small company. I realized that to advance professionally, I needed to hone my listening and communication skills. And as they say, the best way to learn is by doing. Random Coffees became my method of choice. I signed up for the activity within a professional community.&lt;/p&gt;

&lt;p&gt;I can still recall my first Random Coffee—it was with an ML Engineer from Snapchat. Over the course of an hour, we discussed the latest ML technologies, the inner workings of big tech companies, interview strategies, and a wide array of other topics. He even suggested I apply for their trainee program—something I never got around to doing, of course.&lt;/p&gt;

&lt;p&gt;After the call, I felt completely energized and motivated to improve as a professional. From that moment, I began to engage in Random Coffees with more or less consistency—certainly with greater regularity than my dating life.&lt;/p&gt;

&lt;p&gt;I’ve met numerous fascinating individuals from various firms, including Google, Microsoft, JetBrains, Yandex, and many more. Our conversations ranged over a multitude of topics, from technology to travel and art.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Once, I talked to a person who, years earlier, had encouraged me in a chat to share my code with the world. He didn’t remember it, but for me, it was a significant moment.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;h2 id=&quot;what-i-learned&quot;&gt;What I Learned&lt;/h2&gt;

&lt;p&gt;Naturally, I’ve picked up insights on some new technologies and ML papers, but that isn’t the heart of what I’ve gained. From these meetings, I’ve learned something far more important: how to engage in open communication with others, overcome shyness during first-time interactions, and keep conversations flowing even when topics seem scarce. These are skills you can’t lean from books – they only come with practice.&lt;/p&gt;

&lt;p&gt;This experience has been valuable during job interviews and in my daily life. It’s now much easier for me to make a phone call addressing a problem with my documents or to initiate a chat with a fellow dog owner on a walk.&lt;/p&gt;

&lt;p&gt;Certainly, the first calls were challenging, especially when the person on the line was shy or having a bad day. I’ve had calls where the other person was so unresponsive that getting any understandable answer felt impossible. Yet, it’s exactly these situations that provide the richest lessons.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;After one of those extremely hard calls, where the person couldn’t share even two words, I ended up exhausted and soaked in sweat. The lesson I learned from that conversation: sometimes it’s best to end things early.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;h2 id=&quot;how-to-maximize-the-benefits&quot;&gt;How to Maximize the Benefits&lt;/h2&gt;

&lt;p&gt;But my greatest advise is: just show up. This way sooner or later you will became better at this ancient skill of communicating.&lt;/p&gt;

&lt;p&gt;To begin with, simply show up. Don’t constantly reschedule or ignore the other person. Better yet, take the initiative and reach out first. And do it consistently. Aiming for a weekly meetings is ideal.&lt;/p&gt;

&lt;p&gt;Once you’re more accustomed to the process, spend 15 minutes researching the other person’s LinkedIn or Instagram profiles. This preparation will help you find potential conversation starters. For example, discovering that the individual enjoys skydiving can lead to a great topic of conversation.&lt;/p&gt;

&lt;p&gt;Additionally, prepare some general questions to ask everyone you meet. My go-to question is, “What’s the best book you’ve read ever?” As an constant reader, I often find myself in a twenty-minute discussion about literature alone.&lt;/p&gt;

&lt;p&gt;Make notes about each person you meet. Maybe it is a little creepy. But this way, you can use this connection in the future. For instance, someone working at Microsoft might be willing to refer you to their HR department, even if you’ve only met once.&lt;/p&gt;

&lt;p&gt;As you grow more confident, consider reaching out directly to individuals on LinkedIn who interest you, and propose a call. This proactive approach can provide you with great insights into a company you’re eager to join or a technology that fascinates you.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;By using this approach, I connected with someone whose YouTube courses taught me Deep Learning years ago. Our dialogue was somewhat life-changing.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;But the most important piece of advice I can offer you is this: just show up. It will inevitably boost your skills in the art of communication.&lt;/p&gt;

&lt;h2 id=&quot;should-i-do-it&quot;&gt;“Should I Do It?”&lt;/h2&gt;

&lt;p&gt;Yes. Without a doubt. 100%.&lt;/p&gt;

&lt;p&gt;This skill will benefit every area of your life, and it only requires an hour a week. Many large companies and communities offer this activity. So, why not join?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to use Diffusion Models for Data Augmentations</title>
   <link href="https://vtitko.com/2023/08/28/diffusion-augmentations/"/>
   <updated>2023-08-28T00:00:00+00:00</updated>
   <id>https://vtitko.com/2023/08/28/diffusion-augmentations</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-08-28-diffusion-augmentations/header.png&quot; alt=&quot;header.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Data augmentations are an essential part of training any Deep Learning algorithm. There are numerous options to choose from, such as flips, color jittering, MixUps, crops, and more. However, in the era of modern Machine Learning, we can explore the use of Generative AI for augmentations.&lt;/p&gt;

&lt;p&gt;In this article, we will look into relevant research papers and benchmarks, compare various approaches, and determine whether diffusion models are effective tools for data augmentation.&lt;/p&gt;

&lt;h2 id=&quot;approaches-to-data-augmentation-with-diffusion-models&quot;&gt;Approaches to Data Augmentation with Diffusion Models&lt;/h2&gt;

&lt;p&gt;Data augmentation is a technique that helps reducing overfitting by enhancing our dataset with modified versions of existing samples. For instance, when training an image classification model, we can apply random horizontal flips to each sample during the training process. Let’s explore which techniques can be employed to enable data augmentation with diffusion models.&lt;/p&gt;

&lt;h3 id=&quot;boomerang&quot;&gt;Boomerang&lt;/h3&gt;

&lt;p&gt;In the paper titled “&lt;a href=&quot;https://arxiv.org/pdf/2210.12100.pdf&quot;&gt;Boomerang: Local sampling on image manifolds using diffusion models&lt;/a&gt;”, researchers use Stable Diffusion to make small changes to each dataset sample. They apply img2img with a limited number of diffusion steps, resulting in images that appeared similar but were actually different. Let’s take a look at an example.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-08-28-diffusion-augmentations/diffusion.png&quot; alt=&quot;Images looks kind of the same, but details are slightly different&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The paper reports increased accuracy on CIFAR-10 and ImageNet-200 datasets. However, it’s not entirely clear from the paper what augmentations were used for the baseline, thus making the results less representative. In this article, we will explore another paper that compares Boomerang with other approaches.&lt;/p&gt;

&lt;h3 id=&quot;prompt-conditioning&quot;&gt;Prompt Conditioning&lt;/h3&gt;

&lt;p&gt;This method involves generating images of the required class using Stable Diffusion. We can condition the model using prompts that include the name of the class. For instance, prompts like “a photo of the n” or “a HQ image of the n” can be used. Additionally, instead of using the vanilla Stable Diffusion 1.5, we can use a fine-tuned version, which may yield more photorealistic results. For the images presented below, I used fine-tune &lt;a href=&quot;https://huggingface.co/XpucT/Deliberate&quot;&gt;Deliberate&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-08-28-diffusion-augmentations/leopard1.png&quot; alt=&quot;prompt: a photo of the leopard&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prompt: a photo of the leopard&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-08-28-diffusion-augmentations/leopard2.png&quot; alt=&quot;prompt: a HQ image of the leopard&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prompt: a HQ image of the leopard&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;textual-inversion&quot;&gt;Textual Inversion&lt;/h3&gt;

&lt;p&gt;Textual Inversion is a technique that allows us to teach a diffusion model novel concepts using only a small number of example images. The concept was introduced in the paper “&lt;a href=&quot;https://arxiv.org/pdf/2208.01618.pdf&quot;&gt;An Image is Worth One Word&lt;/a&gt;”. With this approach, we teach SD models on concepts from our own dataset. This becomes particularly valuable when our domain is not properly represented in the datasets on which SD was initially trained. For example, if we are training a model to classify various types of furniture or exotic flowers, Textual Inversion can help us in achieving better results.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-08-28-diffusion-augmentations/textual_inversion.png&quot; alt=&quot;Image from the HuggingFace diffusers [Textual Inversion documentation](https://huggingface.co/docs/diffusers/training/text_inversion)&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The downside is that we need to train textual inversion for every concept in our dataset. For large datasets like ImageNet, which can contain thousands of concepts, this approach can become time and resource-consuming.&lt;/p&gt;

&lt;p&gt;Also, we can fine-tune the entire model on our images, or we can fine-tune just the text encoder, which, in the case of SD, is CLIP. However, these techniques suffer from the same problems.&lt;/p&gt;

&lt;h2 id=&quot;comparison&quot;&gt;Comparison&lt;/h2&gt;

&lt;p&gt;For the comparison, we will use data from the amazing paper “&lt;a href=&quot;https://arxiv.org/pdf/2304.10253.pdf&quot;&gt;A data augmentation perspective on diffusion models and retrieval.&lt;/a&gt;” I highly encourage you to read this paper, as it provides a nice overview of the field.&lt;/p&gt;

&lt;h3 id=&quot;baseline&quot;&gt;Baseline&lt;/h3&gt;

&lt;p&gt;To simulate the training pipeline when training data is scarce, the authors sampled only 10% of the ImageNet-1000 dataset.&lt;/p&gt;

&lt;h3 id=&quot;upper-bound-model&quot;&gt;Upper-bound Model&lt;/h3&gt;

&lt;p&gt;To establish an upper-bound model, they used the same training routine but with 20% of the ImageNet-1000 dataset. This allows us to compare not only how diffusion augmentations perform compared to the baseline, but also to compare the results of diffusion augmentations to the model that has more real-world data.&lt;/p&gt;

&lt;h3 id=&quot;nearest-neighbor-retrieval&quot;&gt;Nearest Neighbor Retrieval&lt;/h3&gt;

&lt;p&gt;We can retrieve samples from the Stable Diffusion training dataset, Laion 5B. We can do this based on their CLIP similarity to the classes from ImageNet-1000. This way, we will be able to see if it is reasonable to use Stable Diffusion for augmentations, or if it is better to retrieve data from the Stable Diffusion training dataset. For your projects, you can use &lt;a href=&quot;https://rom1504.github.io/clip-retrieval/?back=https%3A%2F%2Fknn.laion.ai&amp;amp;index=laion5B-H-14&amp;amp;useMclip=false&quot;&gt;tools&lt;/a&gt; that simplify the process of CLIP retrieval.&lt;/p&gt;

&lt;p&gt;The authors evaluated the entire ImageNet validation split. They applied random resizing and cropping augmentations to each method mentioned above. The baseline model utilized a ResNet-50 classifier trained on this data. For each method, they used the original 10% of the ImageNet as the training data and supplemented it with additional augmented data. The diffusion augmentations were performed using Stable Diffusion 1.4.&lt;/p&gt;

&lt;p&gt;Let’s dig into the results.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Augmentation method&lt;/th&gt;
      &lt;th&gt;Top-1 accuracy (%)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;10% ImageNet&lt;/td&gt;
      &lt;td&gt;57.2 ± 0.2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;20% ImageNet&lt;/td&gt;
      &lt;td&gt;70.2 ± 0.3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Boomerang&lt;/td&gt;
      &lt;td&gt;56.3 ± 0.3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Prompt Conditioning (CLIP prompts)&lt;/td&gt;
      &lt;td&gt;60.9 ± 0.2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Textual Inversion&lt;/td&gt;
      &lt;td&gt;61.0 ± 0.4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Nearest Neighbor Retrieval&lt;/td&gt;
      &lt;td&gt;62.6 ± 0.1&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;As expected, the model trained with 20% of ImageNet performed the best. It proves that it is always better to collect more real-world data. Interestingly, Bommerang performed poorly, even worse than the model trained on 10% of ImageNet. My guess is that this is because Bommerang doesn’t significantly change the data, which could lead to overfitting. Below, you can see how little information changed in the images.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-08-28-diffusion-augmentations/boomerang.png&quot; alt=&quot;Image from the “[A data augmentation perspective on diffusion models and retrieval](https://arxiv.org/pdf/2304.10253.pdf)” paper&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Maybe if authors applied more diffusion steps and combined this with Prompt Conditioning, it would yield better results.&lt;/p&gt;

&lt;p&gt;The most interesting thing from the paper is that Nearest Neighbor Retrieval gives the best result among all discussed techniques except for 20% ImageNet-1000. And, once again, it proves that real-world data rocks. And that the CLIP retrieval is a quite powerful technique.&lt;/p&gt;

&lt;p&gt;An important thing to mention in this article is that the authors used Stable Diffusion 1.4 for their experiments. However, at the time of this writing, SD 1.5 and 2.1 are already available, and the release of SDXL 1.0 is &lt;a href=&quot;https://stability.ai/blog/sdxl-09-stable-diffusion&quot;&gt;just&lt;/a&gt; around the corner. The generation quality of these newer models is significantly better than SD 1.4. Considering this progress, it is likely that in the upcoming months, we will see new research papers that more successfully utilize diffusion models for augmentations or even zero-shot tasks.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Using diffusion models is a beneficial way to enrich your data, particularly in tricky cases where Textual Inversion or similar techniques can be applied. However, it is even more advantageous to obtain additional real-world data. To achieve this, you can leverage CLIP and utilize a large-scale dataset, such as Laion-5B.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Let’s Understand Stable Diffusion Inpainting</title>
   <link href="https://vtitko.com/2023/08/16/stable-diffusion-inpainting/"/>
   <updated>2023-08-16T00:00:00+00:00</updated>
   <id>https://vtitko.com/2023/08/16/stable-diffusion-inpainting</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-08-28-stable-diffusion-inpainting/smiling_boy.png&quot; alt=&quot;smiling_boy.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In this article, we will explore the simplest approach to use Stable Diffusion for image inpainting. We all know, that the best way to grasp a concept is by implementing it. We will enhance the existing &lt;a href=&quot;https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion_img2img.py#L101&quot;&gt;StableDiffusionImg2ImgPipeline&lt;/a&gt; from diffusers to solve inpainting tasks.&lt;/p&gt;

&lt;p&gt;👨🏻‍🎨 It is better to use either &lt;a href=&quot;https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion_inpaint.py&quot;&gt;StableDiffusionInpaintPipeline&lt;/a&gt; or &lt;a href=&quot;https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion_inpaint_legacy.py&quot;&gt;StableDiffusionInpaintPipelineLegacy&lt;/a&gt; from the 🤗 Diffusers library for your real-world tasks. These options are more comprehensive. The first one is specifically designed to work with SD models that have been fine-tuned for inpainting tasks.&lt;/p&gt;

&lt;p&gt;All the code, images and requirements can be found in my GitHub repository &lt;a href=&quot;https://github.com/Vadbeg/diffusers-inpainting&quot;&gt;diffusers-inpainting&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;how-stable-diffusion-works&quot;&gt;How Stable Diffusion Works&lt;/h2&gt;

&lt;p&gt;Let’s begin with a brief theory lesson. Stable Diffusion is a diffusion model that generates images by operating on the latent representations of those images. The algorithm looks like this:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Stable Diffusion retrieves the latents of the given image from a variational autoencoder (VAE).&lt;/li&gt;
  &lt;li&gt;It uses CLIP to obtain embeddings of the given prompt.&lt;/li&gt;
  &lt;li&gt;The diffusion process takes place using a UNet-like model, utilizing the latents from the first step and the prompt embeddings from the second step.&lt;/li&gt;
  &lt;li&gt;Finally, the result of the diffusion process is decoded using the VAE.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If we want to focus only on text-to-image generation without the need for image-to-image, we can skip the first step and begin the diffusion process directly from noise. This scheme is oversimplified, but it accurately captures the main idea.&lt;/p&gt;

&lt;p&gt;But what is the diffusion process? It is a process in which a UNet-like model receives latents and prompt embeddings as inputs. Then, it adds noise to the latents or starts directly from noise if it is not an image-to-image task. The amount of noise added is determined by a hyperparameter.&lt;/p&gt;

&lt;p&gt;The UNet, given initial latents and prompt embeddings, predicts noise, which is then subtracted from the input. The resulting output is passed through the UNet again, making it an iterative algorithm. So at each diffusion step, model “cleans out” noise from the latents. After several dozen iterations, we obtain VAE latents that can be decoded into an image. The number of iterations is also a hyperparameter.&lt;/p&gt;

&lt;p&gt;This process is depicted in the diagram below. If you want to understand this process better, I advise you to read &lt;a href=&quot;https://arxiv.org/abs/2112.10752&quot;&gt;High-Resolution Image Synthesis with Latent Diffusion Models&lt;/a&gt; paper. And go threw &lt;a href=&quot;https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion_img2img.py#L101&quot;&gt;StableDiffusionImg2ImgPipeline&lt;/a&gt; implementation.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-08-28-stable-diffusion-inpainting/architecture.png&quot; alt=&quot;**[High-Resolution Image Synthesis with Latent Diffusion Models](https://arxiv.org/abs/2112.10752) paper**&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;how-to-make-inpainting-work&quot;&gt;How To Make Inpainting Work&lt;/h2&gt;

&lt;p&gt;There are several approaches to incorporate Stable Diffusion (SD) for inpainting tasks. One such method is to fine-tune the original SD model. RunwayML has implemented this approach, making &lt;a href=&quot;https://huggingface.co/runwayml/stable-diffusion-inpainting&quot;&gt;runwayml/stable-diffusion-inpainting&lt;/a&gt; checkpoint:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;First 595k steps regular training, then 440k steps of inpainting training at resolution 512x512 on “laion-aesthetics v2 5+”. For inpainting, the UNet has 5 additional input channels (4 for the encoded masked-image and 1 for the mask itself) whose weights were zero-initialized after restoring the non-inpainting checkpoint.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;But lots of finetunes were not trained on inpainting task at all. So how can we use them for this task?&lt;/p&gt;

&lt;p&gt;At each iteration step, we can substitute the area that is not under the mask with the original image latents plus the amount of noise needed for this step. The area under the mask we will leave untouched. This way, we will make sure SD only changes the masked area. And at the same time, SD will know about the area that needs to stay the same.&lt;/p&gt;

&lt;p&gt;Let’s see how we can update &lt;a href=&quot;https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion_img2img.py#L101&quot;&gt;StableDiffusionImg2ImgPipeline&lt;/a&gt;, to work this way. At each step I will provide GitHub link to the needed line in &lt;a href=&quot;https://github.com/Vadbeg/diffusers-inpainting&quot;&gt;diffusers-inpainting&lt;/a&gt; repository.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/Vadbeg/diffusers-inpainting/blob/3efd045e431ddfb40019809554285c5d3e62722e/pipelines/pipeline_stable_diffusion_img2img_simple_inpaint.py#L727&quot;&gt;Add&lt;/a&gt; new parameter mask to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__call__&lt;/code&gt; method&lt;/p&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;n&quot;&gt;mask_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Union&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FloatTensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PIL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/Vadbeg/diffusers-inpainting/blob/3efd045e431ddfb40019809554285c5d3e62722e/pipelines/pipeline_stable_diffusion_img2img_simple_inpaint.py#L827&quot;&gt;Check&lt;/a&gt;, that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mask_image&lt;/code&gt; is not None&lt;/p&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mask_image&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
 		&lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;`mask_image` input cannot be undefined.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/Vadbeg/diffusers-inpainting/blob/3efd045e431ddfb40019809554285c5d3e62722e/pipelines/pipeline_stable_diffusion_img2img_simple_inpaint.py#L862&quot;&gt;Preprocess&lt;/a&gt; the mask&lt;/p&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;n&quot;&gt;mask&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prepare_mask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mask&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mask_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/Vadbeg/diffusers-inpainting/blob/3efd045e431ddfb40019809554285c5d3e62722e/pipelines/pipeline_stable_diffusion_img2img_simple_inpaint.py#L883&quot;&gt;Resize&lt;/a&gt; input mask to the size of the latents, which VAE outputs&lt;/p&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;n&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;mask&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;functional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;interpolate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
     &lt;span class=&quot;n&quot;&gt;mask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
 				&lt;span class=&quot;n&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vae_scale_factor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
 				&lt;span class=&quot;n&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vae_scale_factor&lt;/span&gt;
 		&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;At the end of each diffusion step &lt;a href=&quot;https://github.com/Vadbeg/diffusers-inpainting/blob/3efd045e431ddfb40019809554285c5d3e62722e/pipelines/pipeline_stable_diffusion_img2img_simple_inpaint.py#L933&quot;&gt;substitue&lt;/a&gt; area which is not under the mask, with original input latents plus noise needed for this step. Area under the mask leave untuched.&lt;/p&gt;

    &lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;c1&quot;&gt;# Adding noise to original latents
&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init_latents_proper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scheduler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_noise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
     &lt;span class=&quot;n&quot;&gt;init_latents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;noise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
 &lt;span class=&quot;c1&quot;&gt;# Using mask
&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mask&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mask&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prompt_embeds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dtype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;latents_with_noise&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
     &lt;span class=&quot;n&quot;&gt;mask&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;latents_with_noise&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;init_latents_proper&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s it. With this setup, we will make SD generate something inside the masked area. The unmasked area will be left untouched because we substituted it with the original latents at each diffusion step. And because SD can change only the area under the mask, it will force itself to make it consistent with the whole image. At the same time, it will try to follow the prompt.&lt;/p&gt;

&lt;h2 id=&quot;examples&quot;&gt;Examples&lt;/h2&gt;

&lt;p&gt;Below you can find the result of this algorithm, generated with the model &lt;a href=&quot;https://huggingface.co/redstonehero/Yiffymix_Diffusers&quot;&gt;redstonehero/Yiffymix_Diffusers&lt;/a&gt;, which doesn’t have any inpainting checkpoint.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-08-28-stable-diffusion-inpainting/inpainting.png&quot; alt=&quot;Face of a yellow cat, high resolution, sitting on a park bench&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Gif below shows denoising process for this image&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-08-28-stable-diffusion-inpainting/inpainting_process.gif&quot; alt=&quot;Denoising process for inpainting algorithm&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This algorithm works and can give decent results. However, it performs poorly when we want to simply remove the object from the masked area. Let’s compare the performance of runwayml/stable-diffusion-v1-5 using our pipeline with runwayml/stable-diffusion-inpainting using the &lt;a href=&quot;https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion_inpaint.py&quot;&gt;StableDiffusionInpaintPipeline&lt;/a&gt;. It’s important to note that runwayml/stable-diffusion-inpainting was specifically trained for the inpainting task.&lt;/p&gt;

&lt;p&gt;To remove an object from the image, let’s provide an empty prompt to the model. With an empty prompt, the model will attempt to make the masked area as consistent with the rest of the image as possible.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-08-28-stable-diffusion-inpainting/test_inpainting_compare.png&quot; alt=&quot;Comparison of simple and specifically trained pipelines&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So, we can see that our algorithm failed, but SD inpainting performed quite well. Additionally, a model specifically fine-tuned on the inpainting task will be able to produce better and more consistent results for text-guided image inpainting.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The algorithm we have implemented today can be a good choice if there is no inpainting model available for fine-tuning. However, if there is an inpainting model specifically trained for the task, it is undoubtedly better to use it.&lt;/p&gt;

&lt;p&gt;If this article was useful, don’t forget to clap and leave a star in the &lt;a href=&quot;https://github.com/Vadbeg/diffusers-inpainting&quot;&gt;diffusers-inpainting&lt;/a&gt; repository. If you have any questions, feel free to reach out to me on &lt;a href=&quot;https://www.linkedin.com/in/vadtitko/&quot;&gt;LinkedIn&lt;/a&gt;. I will gladly help! 😁&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to Deploy Neural Networks on iOS</title>
   <link href="https://vtitko.com/2023/02/05/how-to-deploy-nns-on-ios/"/>
   <updated>2023-02-05T00:00:00+00:00</updated>
   <id>https://vtitko.com/2023/02/05/how-to-deploy-nns-on-ios</id>
   <content type="html">&lt;p&gt;You can find the slides for this article &lt;a href=&quot;https://docs.google.com/presentation/d/1bj8QCb9MZ7q9F0o6Dwp26qdgDTfCfxHc0yUfJ2_w4e4/edit?usp=sharing&quot;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-02-05-how-to-deploy-nns-on-ios/thumbnail.png&quot; alt=&quot;thumbnail&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Let’s assume we have a problem that requires a solution through an ML algorithm. To solve this problem, we generally need to follow these steps:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Analyze the problem&lt;/li&gt;
  &lt;li&gt;Collect, clean, and preprocess the data&lt;/li&gt;
  &lt;li&gt;Build the ML algorithm that solves the problem&lt;/li&gt;
  &lt;li&gt;Deploy the algorithm&lt;/li&gt;
  &lt;li&gt;Monitor the results&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While we often find the 3rd step exciting, with all the reading and training, we tend to forget about the crucial step of deployment. Deployment is a critical component of any ML product, and we should plan for it from the early stages of the project.&lt;/p&gt;

&lt;p&gt;In this article, I’ll provide a general overview of deploying Neural Networks models on iOS devices. But first, why do we need to deploy the model directly on the device instead of using a server?&lt;/p&gt;

&lt;h2 id=&quot;server-side-vs-client-side-deployment&quot;&gt;Server-side vs Client-side Deployment&lt;/h2&gt;

&lt;p&gt;In general, there are two solutions for deploying Neural Networks models.&lt;/p&gt;

&lt;p&gt;The first solution is to deploy the model on a server. This can be done using frameworks such as ONNX, OpenVINO, TensorRT, etc. This approach is flexible, as we can change the model without modifying the client. Additionally, we are not restricted by the computational resources of the device.&lt;/p&gt;

&lt;p&gt;However, this solution requires an internet connection on the client side and incurs additional costs for server maintenance.&lt;/p&gt;

&lt;p&gt;The second solution is to deploy the model directly on the device. This approach is cost-effective and provides complete privacy. There are no scalability issues with this approach, and our server costs won’t skyrocket if our application becomes popular.&lt;/p&gt;

&lt;p&gt;The drawback of this approach is that mobile devices have limited computational resources, and some models may be too heavy to run on the device. Furthermore, some devices may not have adequate support for neural network operations.&lt;/p&gt;

&lt;p&gt;In conclusion, the right approach depends on the problem. In my experience, it’s best to deploy models on the device whenever possible, and only use a server when it is not possible or a more flexible solution is required.&lt;/p&gt;

&lt;h2 id=&quot;deployment-frameworks&quot;&gt;Deployment Frameworks&lt;/h2&gt;

&lt;p&gt;When training Neural Networks models, most developers use PyTorch or TensorFlow. However, deploying these models on iOS devices requires a different approach.&lt;em&gt;**&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;pytorch&quot;&gt;PyTorch&lt;/h3&gt;

&lt;p&gt;PyTorch offers TorchScript for deployment on iOS devices. While there are examples of apps on the PyTorch website, this approach comes with several challenges:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;TorchScript doesn’t support the Apple GPU or Apple Neural Engine.&lt;/li&gt;
  &lt;li&gt;There is no native support for TorchScript on iOS.&lt;/li&gt;
  &lt;li&gt;Developers need to write Objective-C or Objective-C++ wrappers for TorchScript.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-02-05-how-to-deploy-nns-on-ios/jit.png&quot; alt=&quot;JIT&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you want to explore this approach further, you can visit the PyTorch iOS deployment &lt;a href=&quot;https://pytorch.org/mobile/ios/&quot;&gt;page&lt;/a&gt; for more information.&lt;/p&gt;

&lt;h3 id=&quot;tensorflow&quot;&gt;TensorFlow&lt;/h3&gt;

&lt;p&gt;TensorFlow allows for deployment on iOS devices using TensorFlow Lite. While TensorFlow provides examples of apps, it still faces similar challenges as PyTorch:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;There is no native support for TensorFlow Lite on iOS.&lt;/li&gt;
  &lt;li&gt;Developers need to write Objective-C or Objective-C++ wrappers.&lt;/li&gt;
  &lt;li&gt;TensorFlow Lite has support for iOS GPU, but this support is limited and available only in a nightly version. The number of supported operations is also limited.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-02-05-how-to-deploy-nns-on-ios/tflite.png&quot; alt=&quot;TFLite&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can find more information about TensorFlow Lite deployment &lt;a href=&quot;https://www.tensorflow.org/lite/performance/coreml_delegate&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;https://www.tensorflow.org/lite/guide/ios&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;coreml&quot;&gt;CoreML&lt;/h3&gt;

&lt;p&gt;Core ML is an Apple framework that enables the integration of machine learning models into iOS apps. It is optimized for on-device performance, making use of the CPU, GPU, and Neural Engine, while keeping its memory footprint and power consumption low. To learn in-dep about Core ML, I recommend visiting &lt;a href=&quot;https://developer.apple.com/documentation/coreml&quot;&gt;this&lt;/a&gt; page.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-02-05-how-to-deploy-nns-on-ios/coreml.png&quot; alt=&quot;CoreML&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When a Core ML model is added to a Xcode project, it automatically generates interfaces for the model. The framework supports image inputs and outputs and makes it easy to integrate pre- and post-processing.&lt;/p&gt;

&lt;p&gt;So, using Core ML is the best option for integrating machine learning models into iOS apps. But during the development of these models, we typically use PyTorch or TensorFlow, not Core ML. What do we do then?&lt;/p&gt;

&lt;h3 id=&quot;coremltools&quot;&gt;coremltools&lt;/h3&gt;

&lt;p&gt;To convert these models to the Core ML format, we use the coremltools framework. This framework can convert machine learning models from various third-party libraries, including PyTorch, TensorFlow 1 or 2, scikit-learn, and XGBoost.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-02-05-how-to-deploy-nns-on-ios/coreml2.png&quot; alt=&quot;CoreML2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For PyTorch models, the conversion process involves first converting the model to TorchScript, and then to Core ML. There are various input and output options that can be selected, such as setting the input to an image. This makes it possible for an iOS developer to pass the image to the model directly from the camera without having to perform any additional conversions.&lt;/p&gt;

&lt;p&gt;Quantization is another option available during the conversion process. The model can be quantized to 16 bits, or even from 1 to 8 bits. However, the lower the number of bits, the greater the risk of reduced accuracy. The extent of the loss in accuracy depends on the specific model and may vary. In general, quantizing to 16 bits should be safe and is unlikely to have a significant impact on accuracy.&lt;/p&gt;

&lt;p&gt;While the process may seem simple, there are always details that can make things more challenging. Core ML does not support all operations, particularly newly introduced ones, which can make it difficult to convert state-of-the-art models. However, with each new version, the situation is improving, although coremltools can still lag behind.&lt;/p&gt;

&lt;h2 id=&quot;custom-layers&quot;&gt;Custom layers&lt;/h2&gt;

&lt;p&gt;You can write your own custom operations, but the official documentation suggests using this option only as a last resort. Writing a custom operation requires implementation in Swift or Objective-C and separate implementations for CPU and GPU, using different frameworks.&lt;/p&gt;

&lt;p&gt;It is often better to use a different model or retrain your existing model with layers that are already supported by Core ML. You can also try converting your model to Core ML before training, deploying it on iOS, and comparing the results with PyTorch. If everything checks out, then you can proceed with training. For a practical example, check out &lt;a href=&quot;https://machinethink.net/blog/coreml-custom-layers/&quot;&gt;this&lt;/a&gt; blog post.&lt;/p&gt;

&lt;h2 id=&quot;processing-units&quot;&gt;Processing units&lt;/h2&gt;

&lt;p&gt;Modern iOS devices can run neural networks on the CPU, GPU, and Neural Engine.&lt;/p&gt;

&lt;p&gt;The CPU and GPU are well understood, but what is the Neural Engine?&lt;/p&gt;

&lt;p&gt;The Apple Neural Engine (ANE) is a type of Neural Processing Unit (NPU) that accelerates neural network operations, such as convolutions and matrix multiplies. Unlike a GPU, which accelerates graphics, an NPU accelerates neural network computations. You can see the ANE and GPU cores as separate areas on the A12 Bionic chip.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-02-05-how-to-deploy-nns-on-ios/cpu.png&quot; alt=&quot;A12 Bionic chip&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The ANE isn’t the only NPU on the market, as other companies have developed their own AI accelerator chips as well. A well-known NPU besides the Neural Engine is Google’s TPU.&lt;/p&gt;

&lt;p&gt;The first iteration of the Apple Neural Engine was introduced in the A11 chip, which was found in the iPhone X in 2017. It had a maximum processing power of 0.6 teraflops in half-precision and was utilized to efficiently run on-device ML features such as Face ID and Memoji.&lt;/p&gt;

&lt;p&gt;In 2021, the fifth-generation 16-core ANE has advanced significantly, boasting 26 times more processing power, or 15.8 TFlops.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/public/images/posts/2023-02-05-how-to-deploy-nns-on-ios/benchmark.png&quot; alt=&quot;Benchmark&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Core ML automatically selects the device (CPU, GPU, or Neural Engine) on which your model will run. However, it allows you to limit the device selection by specifying the following options:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;CPU only&lt;/li&gt;
  &lt;li&gt;CPU and GPU&lt;/li&gt;
  &lt;li&gt;All (Neural Engine, CPU, and GPU)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a comparison of performance for neural networks on CPU, GPU, and ANE, see &lt;a href=&quot;https://blog.xmartlabs.com/blog/how-to-get-the-best-performance-for-ml-models-on-ios/&quot;&gt;this blog post&lt;/a&gt;. If you want to dive into the technical details of the Apple Neural Engine, visit &lt;a href=&quot;https://github.com/hollance/neural-engine&quot;&gt;this GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In conclusion, deploying a neural network on iOS can be a challenge, but with the right approach and tools, it can be done successfully. Start by testing the conversion to CoreML, as many state-of-the-art networks may not be convertible. Consider using an older algorithm that solves your problem and converts to CoreML or replacing non-convertible operations with convertible ones.&lt;/p&gt;

&lt;p&gt;In most cases, a few percentage differences in the target metric may not be worth spending weeks trying to solve conversion problems. When you have found an architecture that supports CoreML, you can then train it for your specific task.&lt;/p&gt;

&lt;p&gt;Quantizing your model to half-precision and changing input and output nodes to ImageType instead of FloatType can also improve inference speed and save time for iOS developers. If speed is a concern, ensure that your model uses the GPU or ANE. If it doesn’t, use XCode utilities for debugging.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Make Your Python Code Cleaner in One Easy Step</title>
   <link href="https://vtitko.com/2022/10/24/python-code-cleaner/"/>
   <updated>2022-10-24T00:00:00+00:00</updated>
   <id>https://vtitko.com/2022/10/24/python-code-cleaner</id>
   <content type="html">&lt;p&gt;Everybody knows that code needs to be understandable and easy to read. But at the same time, everybody forgets to write typings, sort imports, or follow PEP8. There is a solution — &lt;a href=&quot;https://pre-commit.com/&quot;&gt;pre-commit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This tool will trigger different hooks every time you commit your code. So, let’s integrate it into our project.&lt;/p&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;

&lt;p&gt;Let’s install pre-commit into the environment&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip install pre-commit&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then we need to add two files to the root directory of your project&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.pre-commit-config.yaml&lt;/code&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;exclude&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;_pb2\.py$&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;repos&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://github.com/psf/black&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;22.3.0&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;black&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;--skip-string-normalization&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt;   &lt;span class=&quot;na&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://github.com/pre-commit/pre-commit-hooks&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v4.0.1&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;check-docstring-first&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;check-json&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;check-merge-conflict&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;check-yaml&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;debug-statements&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;end-of-file-fixer&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;trailing-whitespace&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;requirements-txt-fixer&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://github.com/pre-commit/pygrep-hooks&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;v1.9.0&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;python-check-mock-methods&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;python-use-type-annotations&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://github.com/pre-commit/mirrors-mypy&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;v0.910&apos;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mypy&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;--ignore-missing-imports&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;--warn-no-return&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;--warn-redundant-casts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;--disallow-incomplete-defs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;additional_dependencies&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;types-all&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;repo&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://github.com/PyCQA/isort&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;5.9.3&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;isort&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;--profile&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;black&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;--filter-files&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pyproject.toml&lt;/code&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tool.black&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;line-length = &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;88&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;target-version = [&quot;py38&quot;]&lt;/span&gt;

&lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tool.isort&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;profile = &quot;black&quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;multi_line_output = 3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And now, you have to install the hooks that you’ve added.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pre-commit install&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git commit -m &quot;new brave code&quot;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Yep, that’s it. Now, every time you’ll commit your code, those hooks will trigger. And automatically:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;sort imports&lt;/li&gt;
  &lt;li&gt;format code for PEP8&lt;/li&gt;
  &lt;li&gt;check the correctness of your yaml and json files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And mypy will not pass your code if it’s not statically typed. So you’ll have to use typings in the right way.&lt;/p&gt;

&lt;h2 id=&quot;explanation&quot;&gt;Explanation&lt;/h2&gt;

&lt;p&gt;In the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.pre-commit-config.yaml&lt;/code&gt; file, you specify which hooks you will use. For example, in the provided file, we use &lt;a href=&quot;https://github.com/psf/black&quot;&gt;black&lt;/a&gt; code formatter of version 22.3.0. And ask not to change &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;‘&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;&lt;/code&gt; using a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--skip-string-normalization&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;In the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pyproject.toml&lt;/code&gt; you specify parameters for those individual hooks. For example, you set the maximum line length to 88.&lt;/p&gt;
</content>
 </entry>
 

</feed>
