Всем привет!
Почти все лето не было постов – то одолевала лень что-либо писать, то события поглощали и не оставалось времени. Постараюсь вкратце описать это лето по рабочим и личным аспектам.
Работа:
1) Решал задачу с классификацией автомобилей по цветам. Решил, расскажу детали, было любопытно.
2) Приступил к задаче Car Detection – у нас, оказывается, был предобученный детектор YOLOv8, который часто выдавал кривые типы автомобилей (грузовик превращался в автобус или иное). Там для большей точности потребовались данные в нашем домене (российский транспорт), я их собрал и попробовал заказать разметку со стороны – ждем вместе с тимлидом теперь ответ директора, сверху согласовывают...
3) Сейчас решаю задачу Person Re-identification. Это, пожалуй, первая действительно серьезная задача, буквально неделю ей занимаюсь, расскажу впоследствии во всех подробностях.
Жизнь:
1) Первый раз побывал в двухнедельном отпуске. Появилось ясное понимание, что студенчества и каникул больше не будет – дальше только работа, семья и следующие итерации жизненного цикла.
2) Переехал в СПб. Вероятно, на какое-то время, но не менее года. Работаю на удаленке, уже обустроился, веду насколько это возможно активную социальную жизнь, даже (тьфу-тьфу) нашел потенциальную команду на ближайший волейбольный сезон. А кто будет в Питере – обязательно пишите, пообщаемся и по работе, и в целом)
Суммируя вышесказанное – все медленно, но верно идет к лучшему, о чем и постараюсь рассказывать в ближайшее время. Пока есть идеи лишь для 2-3 постов, и если будут какие-нибудь пожелания, обязательно предлагайте либо здесь, либо в личку
#self #progress
Почти все лето не было постов – то одолевала лень что-либо писать, то события поглощали и не оставалось времени. Постараюсь вкратце описать это лето по рабочим и личным аспектам.
Работа:
1) Решал задачу с классификацией автомобилей по цветам. Решил, расскажу детали, было любопытно.
2) Приступил к задаче Car Detection – у нас, оказывается, был предобученный детектор YOLOv8, который часто выдавал кривые типы автомобилей (грузовик превращался в автобус или иное). Там для большей точности потребовались данные в нашем домене (российский транспорт), я их собрал и попробовал заказать разметку со стороны – ждем вместе с тимлидом теперь ответ директора, сверху согласовывают...
3) Сейчас решаю задачу Person Re-identification. Это, пожалуй, первая действительно серьезная задача, буквально неделю ей занимаюсь, расскажу впоследствии во всех подробностях.
Жизнь:
1) Первый раз побывал в двухнедельном отпуске. Появилось ясное понимание, что студенчества и каникул больше не будет – дальше только работа, семья и следующие итерации жизненного цикла.
2) Переехал в СПб. Вероятно, на какое-то время, но не менее года. Работаю на удаленке, уже обустроился, веду насколько это возможно активную социальную жизнь, даже (тьфу-тьфу) нашел потенциальную команду на ближайший волейбольный сезон. А кто будет в Питере – обязательно пишите, пообщаемся и по работе, и в целом)
Суммируя вышесказанное – все медленно, но верно идет к лучшему, о чем и постараюсь рассказывать в ближайшее время. Пока есть идеи лишь для 2-3 постов, и если будут какие-нибудь пожелания, обязательно предлагайте либо здесь, либо в личку
#self #progress
👍7
*По версии Яндекс.Практикума.
Прошел я тут у них недавно курс Алгоритмы и структуры данных благодаря щедрости нашей компании. Поделюсь впечатлениями, а там уже сами думайте, надо оно вам или не надо.
Если вообще захочется лезть в курсы, важно понимать, какой у тебя бэкграунд. У меня на тот момент уже были за спиной 6 лет вышки + полгода опыта работы. С алгоритмами я был знаком из вузовских курсов, где мы писали условные рекурсии на плюсах, ну и ещё где-то как-то между делом.
И вот здесь как раз таилась главная проблема – я ожидал, что курс будет ± на уровне вуза, т.е. полноценные лекции, мб доказательства, строгие формулировки и все в этом духе. Все оказалось вообще не так.
Кто-то на этом моменте облегченно выдохнет, а я наоборот озабоченно вдохнул, потому что хотелось погрузиться в эту тему с головой, раз уж надо будет уделять курсу время. Но там даже не дали определение функции О "большое" (или Big O notation
Если же кайф реально погрузиться в тему – книжку в руки и вперед, а если запутался, можно спросить у ChatGPT или, кстати, у Mistral, который полностью в открытом доступе и терпимо справляется с кодом.
Ну а я в результате курса убедился, что практически все концепции и без того знал, дополнительно попрактиковался в некоторых задачах – были и классные, которые я когда-то давно считал загадочной магией, типа расстояния Левенштейна – и получил на выходе удостоверение о повышении квалификации, футболку и значок – прикольно, что его можно под настроение перевешивать
#progress #hard #tips
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1
Не я первый, не я последний, но все же спустя 1.5 года реального опыта поделюсь находками, которые в 2-3 и более раз ускорили выполнение задач и разгрузили мозг от ненужных действий, да и в целом подняли качество кода и позволили сократить число ошибок.
Большинство этих инструментов я использую каждый день, поэтому и решил о них рассказать.
1) CLI Fuzzy finder
Если дословно, то это "Нечеткий искатель"
Он хорошо и, что важно, очень быстро справляется с поиском файлов и ранее выполненных команд в терминале по их примерным названиям. Я лично использую почти всегда именно для команд, поскольку бывает – подключился ты к какому-то очередному серваку или запустил скрипт, там куча параметров, это запомнить просто невозможно, проходит какое-то время и тебе нужно повторить это действие, а искать, где, когда и как – просто мучительно. А если есть fzf – открыл терминал, Ctrl + R, ввел кусочек команды (название скрипта или одного параметра, который помнишь) и сразу нашел её в истории. И вместо нескольких минут прописывания команд или их поиска у себя в сохраненках, за пару секунд удается найти все, что нужно.
2) Code assistants
Будь то бесплатный Codeium, платный Copilot, целая IDE типа Cursor или какое-либо другое решение – помощники в написании кода на основе ИИ – это огромный буст к скорости работы. Причем да, порой косячит, но даже в бесплатном виде как инструмент для дописывания следующих одной-двух строк кода или написания документации – это вещь незаменимая. Кто еще не пробовал, настоятельно советую.
3) LLM
В наше время, особенно программистам, грешно не пользоваться халявным джуном в чатике. Разумеется, лидерами здесь пока являются OpenAI с их моделями, однако есть полностью доступный и бесплатный Mistral, который по моему опыту в кодинге лучше того же ChatGPT 4o.
Эта штука действительно заменяет привычный пока StackOverFlow, поскольку сразу помогает с нужной тебе задачей, являясь end-to-end решением без необходимости в самостоятельном допиливании результата (почти). И что еще важно — она порой закидывает прикольные best practices, которые ты бы сам мог и не встретить никогда.
4) Питон и все сопутствующее
Это уже только для питонистов и только для начинающих, которые, как и я в начале пути, нейросетки делают в jupyter, прости господи. Все просто: вместо ноутбуков – скрипты + argparse. Для работы с путями и директориями вместо os.path – pathlib. Остальное, начиная от timeit, tqdm, pyyaml, заканчивая numpy, pandas, torch, lightning, kornia, jax в отдельном пояснении не нуждаются, потому что их очень много и каждый здесь найдет что-то свое и более подходящее под конкретную задачу, благо выбор есть.
Напоследок скажу, что в зависимостях мне помогает разобраться conda и установленный туда pip. При публикации проекта и conda environment есть, и pip requirements для тех, кому conda неудобна. Но вообще, конечно, в планах потрогать poetry, а docker, возможно, начать применять не только для окончательной сборки проекта. Однако по соотношению минимум гемора / максимум результата в целом пока хватает.
Если вы применяете какие-нибудь полезные инструменты или библиотеки, которые круто закрывают какие-то ваши задачи, обязательно делитесь, я всегда рад узнавать новое и пробовать это в работе. Надеюсь, что мой опыт тоже будет для вас полезен, обратная связь приветствуется)
#hard #tips
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - junegunn/fzf: :cherry_blossom: A command-line fuzzy finder
:cherry_blossom: A command-line fuzzy finder. Contribute to junegunn/fzf development by creating an account on GitHub.
👍4
Сказано – сделано
Любимые коллеги реализовали запрошенную фичу, уложились во все сроки и даже сумели добиться эффекта присутствия за счет объема
Вывод: нельзя закидывать программистам идеи, к осуществлению которых ты можешь быть не готов...✍️
#offtopic
Любимые коллеги реализовали запрошенную фичу, уложились во все сроки и даже сумели добиться эффекта присутствия за счет объема
Вывод: нельзя закидывать программистам идеи, к осуществлению которых ты можешь быть не готов...
#offtopic
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
😁8✍1
Итоги года 🥴
Ну че, потихоньку переваливаемся в 2025-й (ой, как не хочется – ничего хорошего нас там не ждет...), пора подвести итоги уходящего года.
Как и всегда, что-то получалось, а что-то пошло не по плану, но если пройтись по ключевым событиям в порядке убывания значимости:
1️⃣ Закончил магистратуру
2️⃣ Вырос по грейду фактически, дважды – успел до нг, однако, можно засчитать и в следующий год
3️⃣ Прошел курс по алгоритмам
4️⃣ Переехал между городами с разницей в 1800 км
5️⃣ Закрыл кучу интересных задач по работе, писал о них, хотя и редко
6️⃣ Взял в руки гитару и учусь с преподавателем
7️⃣ Присел с 120 кг (при весе в 75)
8️⃣ Поиграл в любительской суперлиге по волейболу
9️⃣ Освоил сноуборд
🔟 Начал полноценно контрибьютить в опенсорс
Когда я начинал писать этот пост, возникла мысль: "Да год как год, пункта 3 наберется небось". А потом я прокрутил эти и другие события, которые произошли за 2024-й, и понял, что это самый насыщенный год в моей жизни. Очень большое количество изменений, новых навыков, новых людей, событий и мест. Однако, много и трудностей, через которые пришлось пройти, и важнее всего то, что результаты оправдывают этот труд.
Конечно, по сравнению со всякими крутыми ресерчерами и прочими товарищами, я не выиграл конференцию/соревнование/жизнь, но это и не так важно на фоне самой жизни, а для всех остальных достижений будет следующий год.
Поэтому, если вдруг какие-то ваши ожидания не оправдались, если грандиозный понедельник для спортзала так и не наступил, помните – скоро у всех нас будет еще 365 дней, которые можно просрать😐
С наступающим Новым годом!🎄
#progress
Ну че, потихоньку переваливаемся в 2025-й (ой, как не хочется – ничего хорошего нас там не ждет...), пора подвести итоги уходящего года.
Как и всегда, что-то получалось, а что-то пошло не по плану, но если пройтись по ключевым событиям в порядке убывания значимости:
Когда я начинал писать этот пост, возникла мысль: "Да год как год, пункта 3 наберется небось". А потом я прокрутил эти и другие события, которые произошли за 2024-й, и понял, что это самый насыщенный год в моей жизни. Очень большое количество изменений, новых навыков, новых людей, событий и мест. Однако, много и трудностей, через которые пришлось пройти, и важнее всего то, что результаты оправдывают этот труд.
Конечно, по сравнению со всякими крутыми ресерчерами и прочими товарищами, я не выиграл конференцию/соревнование/жизнь, но это и не так важно на фоне самой жизни, а для всех остальных достижений будет следующий год.
Поэтому, если вдруг какие-то ваши ожидания не оправдались, если грандиозный понедельник для спортзала так и не наступил, помните – скоро у всех нас будет еще 365 дней, которые можно просрать
С наступающим Новым годом!
#progress
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾7👍2❤1👏1
Давно я ничего не писал – всё не видел достойных поводов для постов, однако сейчас такой появился.
Я сделаю небольшую серию публикаций на тему глобальной оптимизации:
Пример
Представьте, что у вас есть какая-то бизнес- или математическая задача. Например — купить мясо и напитки к столу на фиксированный бюджет. Цель — потратить минимум времени. Зададим переменные и ограничим их диапазон, чтобы совсем с ума не сходить:
x1: Сколько людей мы отправим: от 1 до 4
x2: Каких именно людей мы отправим: пускай будет выборка из 6 человек.
x3: День недели: пятница или суббота
x4: В какое время суток отправлять: с 8 до 16 часов
x5: На какой рынок отправиться: пускай будет 3 варианта наиболее удачных рынков в городе.
Давайте попробуем решить эту задачу, опираясь на жизненный опыт. Я опишу свои мысли, а вы можете прикинуть сами и потом читать дальше.
х2 — кого отправим: здесь нужны люди пунктуальные и желательно с большим опытом в организации таких мероприятий.
х3 — день недели: лучше в пятницу, чем в субботу, очевидно.
х4 — время суток: я бы выбрал 10 утра, потому что в это время уже все, кому надо, на работе, и отправленные на рынок люди уже проснулись и бодрствуют, тормозить не будут.
х5 — рынок: здесь не буду предполагать, но можно учесть местоположение людей, которых отправляем, и взять тот рынок, который по среднему расстоянию будет ближе всего.
Разумеется, это достаточно простая жизненная задача, однако к 20-25 годам у нас уже есть набор знаний и опыта, который позволяет оценить поведение этой функции в зависимости от переменных, и выбрать некоторую субоптимальную комбинацию параметров. Но как, очутившись в мире, где есть только люди, рынки и мясо для шашлыка, такой опыт можно получить и каким образом достичь цели быстрее всего? Перепробовать все комбинации — точно сработает, но долго. Попробовать случайные 5-6 — а достаточно ли это хороший подход?
Задача
Теперь с опорой на пример сформулируем общую задачу: есть функция многих переменных, f(x1, x2, ..., x_n), для которой мы предполагаем существование глобального минимума или максимума — нужно его найти.
Оптимизация гиперпараметров
С помощью примера выше мы показали, что в жизни таких задач очень много — практически каждый процесс можно сформулировать как задачу оптимизации, в том числе и эволюционный (это важное замечание). И раз уж я не владелец кафе а-ля Шашлычный Мир, а CV/ML-инженер, расскажу про реальную задачу, где нам нужна глобальная оптимизация.
Обучаем мы нейросеть, задаем различные гиперпараметры, начиная с оптимизатора, learning rate и batch size, заканчивая аугментациями и регуляризациями и смотрим на точность после обучения. Важно отметить, что в силу невозможности продифференцировать такую функцию, мы имеем более общую задачу и медленную сходимость. Как будем подбирать самую хорошую комбинацию? Жизненный опыт — это хорошо, но его долго получать, нет гарантий, что он верный и сработает как нам надо, а также его не так легко обосновать.
Люди, которые касались этой задачи, сразу же вспомнят про GridSearch – поиск по сетке, где мы задаем для каждого параметра набор значений, которые нужно перебрать каждый с каждым. Однако есть высокая вероятность не попасть даже в хороший локальный максимум. Ну и вспомним RandomSearch – поиск по случайным наборам параметров. Любопытно, что у него даже теоретически доказанная сходимость заметно лучше, чем у поиска по сетке, но он тоже не вызывает чувство спокойствия по поводу обоснованности сделанного выбора.
Как раз о таких методах, которые помогут спать спокойно, в следующих постах и пойдет речь.
#learn #hard #cases
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4👍3
Я тут наконтрибьютил за прошлую неделю на релиз 11.0.9 -> 12.0.0 в библиотеке boxmot для Multi-object Tracking 🤓
С прошлого года плотно занимаюсь задачей трекинга, параллельно дорабатывая репозиторий, с помощью которого сравниваюсь с другими трекерами, и уже сейчас получил классные результаты — может даже скоро будет, что рассказать на эту тему🔥
#progress #results #code
С прошлого года плотно занимаюсь задачей трекинга, параллельно дорабатывая репозиторий, с помощью которого сравниваюсь с другими трекерами, и уже сейчас получил классные результаты — может даже скоро будет, что рассказать на эту тему
#progress #results #code
Please open Telegram to view this post
VIEW IN TELEGRAM
😁3❤2
На днях окажусь на IML в СПб, послушаю, что там умные люди сделали за прошедший год
Пишите, буду рад пообщаться на мероприятии😎
Пишите, буду рад пообщаться на мероприятии
Please open Telegram to view this post
VIEW IN TELEGRAM
🎉3
Я выступлю на DataFest 2025 👨💻
Пару месяцев назад я говорил о том, что плотно занялся задачей трекинга и получил классные результаты, так вот:
Я добавлял независимую ре-идентификацию в трекер, придумал интересную универсальную добавочку, не требующую никакого дообучения моделей, которая почти сразу дала SOTA-1 результат по метрике HOTA на датасете MOT17. Расскажу в подробностях, как это было сделано, через что пришлось пройти, покажу подробные метрики. Ну и наверное это хорошая отсечка, чтобы сказать, что я-таки стал норррмальным Middle CV-инженером.👨💻
📆 Выступление 27 мая в 18:00 по московскому времени, это онлайн-секция, в этот день фест будет в Белграде.
P.S. Мне сказали, что доклад очень интересный и хороший, поэтому ссылаясь на экспертов жду вас в гости в этот день и время, ссылочку приложу как только она у меня будет.
#path #recommend #soft #hard #results #progress
Пару месяцев назад я говорил о том, что плотно занялся задачей трекинга и получил классные результаты, так вот:
Я добавлял независимую ре-идентификацию в трекер, придумал интересную универсальную добавочку, не требующую никакого дообучения моделей, которая почти сразу дала SOTA-1 результат по метрике HOTA на датасете MOT17. Расскажу в подробностях, как это было сделано, через что пришлось пройти, покажу подробные метрики. Ну и наверное это хорошая отсечка, чтобы сказать, что я-таки стал норррмальным Middle CV-инженером.
P.S. Мне сказали, что доклад очень интересный и хороший, поэтому ссылаясь на экспертов жду вас в гости в этот день и время, ссылочку приложу как только она у меня будет.
#path #recommend #soft #hard #results #progress
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5❤🔥3🆒1
Как и обещал, ссылочка на сегодняшний DataFest с моим выступлением: https://ods.ai/events/df2025-27-may-online
Кто сможет и захочет, смотрите в онлайне сегодня в 18:00 по мск, а кто захочет, но не сможет – будет запись, впоследствии тоже выложу
Кто сможет и захочет, смотрите в онлайне сегодня в 18:00 по мск, а кто захочет, но не сможет – будет запись, впоследствии тоже выложу
🔥5🆒1
Log & roll
Попробую сегодня новый формат постов, который мне предложили коллеги.
Изначальная проблема в том, что мне особо нечего рассказывать, потому что работа состоит из двух фаз:
1️⃣ 99.99% времени ресерчить, страдать, дебажить
2️⃣ 0.01% времени все работает – ура, но надо работать дальше 👍
И если раньше между этими фазами я что-нибудь мог написать, потому что задачи были небольшими и закрывались, то сейчас – смерть.
Другие каналы в основном превратились в Release notes для LLM, поэтому атмосферу все равно разбавлю.
Суть формата: я попробую рассказывать, что я делалэтим летом на неделе и что из этого вышло. Если это какая-то шляпа и неинтересно, говорите, я учту (или не учту).
Ну и соответствующий хештег — #lognroll
Попробую сегодня новый формат постов, который мне предложили коллеги.
Изначальная проблема в том, что мне особо нечего рассказывать, потому что работа состоит из двух фаз:
И если раньше между этими фазами я что-нибудь мог написать, потому что задачи были небольшими и закрывались, то сейчас – смерть.
Другие каналы в основном превратились в Release notes для LLM, поэтому атмосферу все равно разбавлю.
Суть формата: я попробую рассказывать, что я делал
Ну и соответствующий хештег — #lognroll
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4❤🔥1🆒1
Log & roll первой недели июня
🔫 Занимался разметкой данных
Писал я про задачу с временными рядами: кластеризация раз, два, классификация раз. И очень уж я хотел, чтобы эта задача закончилась, но она по всей видимости переживет и меня, и нас, и наших детей.
Важный вывод: не полагайтесь на чужой профессионализм, если можно не полагаться. Не в смысле "сделай все сам", а в смысле "создай условия, чтобы результат был наиболее предсказуемым и управляемым". Потому что спустя год я столкнулся с тем, что вообще не доверяю разметке данных, и у меня нет идей, как поменять эту ситуацию, т.к. это затрагивает весь процесс, а не только мою зону ответственности.
✍️ Начал писать статью на Хабр
Мы решили из доклада на DataFest сделать статью, она будет по сути дублировать доклад + больше визуализаций, анимаций, деталей и замечаний. Пока накидываю основной скелет, может, скоро будет, что показать.
🧑💻 Оформил свой профиль на GitHub.
Сделал вот такую штуку. Года два назад хотел, но руки не доходили. Дошли.
Узнал, что по рейтингу гитхаба у меня уровень C+ (Top 87.5%) — ну что ж, спасибо и на этом, теперь надеюсь однажды добраться хотя бы до медианы...
👨💻 Сел за капитальный рефакторинг BoxMOT
Это, пожалуй, самое приятное за неделю. На текущий момент библиотекой можно пользоваться только в режиме CLI, и в общем-то это хорошо, но не юзер-френдли:
С одной стороны, начинающие зачастую не умеют в запуск скриптов — они пишут всё в IDE и нажимают "запустить".
С другой стороны, продолжающие/заканчивающие могут встраивать отдельные части проекта к себе, и удобнее не выдирать куски кода и оборачивать, а импортировать уже готовый кусок из либы и возможно накидывать пару патчей.
Поэтому я предложил идею полной реструктуризации проекта, чтобы сделать его максимально простым и понятным. Обычно с этих слов начинается превращение проекта в чудовище Франкенштейна, но я искренне верю, что на этот раз все будет иначе . В общем-то, все мои идеи были приняты, и я начал пилить код.
Пока что основная задача в том, чтобы подбить одинаковые сущности в общую структуру. Приведу пример: модели детекции сейчас существуют через пайплайн Ultralytics с приколачиванием к нему гвоздями preprocess/postprocess и замены модели на YOLOX, когда нужно. А модели ReID — через класс
Я подумал-подумал и придумал: сделаем базовый класс
Кстати, отдельно отмечу, что с этапом описания архитектуры и взаимосвязей ChatGPT не справился, причем совсем. Все его идеи на первый взгляд были нормальными, но второй и третий взгляды выявляли полную несостоятельность этого бреда. Зато с отдельными функциями он справился хорошо.
🗃 В общем-то, на этом все. Подобную сводку я думаю делать раз в неделю-две, обратная связь приветствуется 🙂
#lognroll
Писал я про задачу с временными рядами: кластеризация раз, два, классификация раз. И очень уж я хотел, чтобы эта задача закончилась, но она по всей видимости переживет и меня, и нас, и наших детей.
Важный вывод: не полагайтесь на чужой профессионализм, если можно не полагаться. Не в смысле "сделай все сам", а в смысле "создай условия, чтобы результат был наиболее предсказуемым и управляемым". Потому что спустя год я столкнулся с тем, что вообще не доверяю разметке данных, и у меня нет идей, как поменять эту ситуацию, т.к. это затрагивает весь процесс, а не только мою зону ответственности.
Мы решили из доклада на DataFest сделать статью, она будет по сути дублировать доклад + больше визуализаций, анимаций, деталей и замечаний. Пока накидываю основной скелет, может, скоро будет, что показать.
Сделал вот такую штуку. Года два назад хотел, но руки не доходили. Дошли.
Узнал, что по рейтингу гитхаба у меня уровень C+ (Top 87.5%) — ну что ж, спасибо и на этом, теперь надеюсь однажды добраться хотя бы до медианы...
Это, пожалуй, самое приятное за неделю. На текущий момент библиотекой можно пользоваться только в режиме CLI, и в общем-то это хорошо, но не юзер-френдли:
С одной стороны, начинающие зачастую не умеют в запуск скриптов — они пишут всё в IDE и нажимают "запустить".
С другой стороны, продолжающие/заканчивающие могут встраивать отдельные части проекта к себе, и удобнее не выдирать куски кода и оборачивать, а импортировать уже готовый кусок из либы и возможно накидывать пару патчей.
Поэтому я предложил идею полной реструктуризации проекта, чтобы сделать его максимально простым и понятным. Обычно с этих слов начинается превращение проекта в чудовище Франкенштейна, но я искренне верю, что на этот раз все будет иначе . В общем-то, все мои идеи были приняты, и я начал пилить код.
Пока что основная задача в том, чтобы подбить одинаковые сущности в общую структуру. Приведу пример: модели детекции сейчас существуют через пайплайн Ultralytics с приколачиванием к нему гвоздями preprocess/postprocess и замены модели на YOLOX, когда нужно. А модели ReID — через класс
ReIDAutoBackend, где автоматически выбирается бэкенд (pytorch, tflite, tensorrt и тд), и внутри сложно разобраться, где заканчивается препроцессинг, где начинается постпроцессинг и так далее.Я подумал-подумал и придумал: сделаем базовый класс
Backend с методами load, preprocess, process, postprocess, а оттуда уже пусть наследуются все другие бэкенды типа PyTorchBackend и переопределяют нужные функции. И только затем появляются классы Detector, ReID, которые НЕ наследуются от бэкендов, потому что по смыслу это НЕ бэкенды, а то, что должно их дергать внутри. Ну и пускай они существуют как базовые классы, внутри которых будет self.backend, куда они смогут отправлять данные и получать ответ. И разумеется, у них будет свой preprocess, process, postprocess. Таким образом, можно легко изменить чужой детектор/ReID или сделать свой, приделать туда препроцессинг-постпроцессинг, если надо, и пользоваться в любом из поддерживаемых бэкендов, а если надо, то и там переприсвоить функции на свои. В общем, делайте че хотите — вот вам универсальный масштабируемый пайплайн. Звучит вроде логично, а на практике посмотрим.Кстати, отдельно отмечу, что с этапом описания архитектуры и взаимосвязей ChatGPT не справился, причем совсем. Все его идеи на первый взгляд были нормальными, но второй и третий взгляды выявляли полную несостоятельность этого бреда. Зато с отдельными функциями он справился хорошо.
#lognroll
Please open Telegram to view this post
VIEW IN TELEGRAM
Telegram
Fley's flow
💬 Кластеризация временных рядов (часть 1: описание)
Сегодня наконец расскажу, как решал реальную задачу кластеризации временных рядов и даже получил приемлемый результат (сам не верил).
Постановка задачи кластеризации
Здесь я буду краток, потому что либо…
Сегодня наконец расскажу, как решал реальную задачу кластеризации временных рядов и даже получил приемлемый результат (сам не верил).
Постановка задачи кластеризации
Здесь я буду краток, потому что либо…
🔥12
Log & roll №2
🏖 Отпуск
На этот раз я всю неделю провел в отпуске, и мне есть, чем поделиться.
Благодаря семье, за первые 20 лет жизни я побывал в разных городах и странах – не слишком много, но все же получилось увидеть. В силу текущих обстоятельств, да и вообще интереса к разным уголкам нашей страны, важным гештальтом для меня стал Калининград (или Königsberg).
1️⃣ Калининград
Интересным образом история этого анклава переплетается с историей нашей страны сквозь века. Я считал, что Калининград исторически и культурно был оторван от России, а сейчас выяснил, что он единожды уже входил в состав Российской империи, хоть и на каких-то три года.
Сам Калининград практически не создает впечатление европейского города – по крайней мере, относительно моих ожиданий. Редкие старые домики и разрушенные форты, небрежно разбросанные по всему городу, и за парой исключений на этом все. В то же время, туристический потенциал у города огромный, и видно, что сейчас на это наконец обратили внимание.
Наибольший интерес представляет остров в центре города – ныне он носит имя Имманиула Канта (прожившего практически всю жизнь в Кёнигсберге), а ранее носивший имя Кнайпхоф. Некогда целый город, сейчас – одно-единственное здание кафедрального собора, уцелевшее во время ВОВ. Внутри собора установлен самый большой в России органный комплекс, и концерт оставляет сильные впечатления даже у тех, кто далек от музыки – просто сходите, если будет возможность. Отдельно отмечу, что формат мини-концерта мне понравился, потому что с непривычки больше часа можно и не выдержать.
Не меньшее впечатление оставил музей Канта, а если точнее, история и образ жизни философа. Такие вещи сложно описывать словами, но если в общих чертах – это про переоценку ценностей. А еще теперь у меня есть хорошее оправдание для тех, кто не успел взять ипотеку: Иммануил Кант впервые обзавелся собственным жильем в 59 лет.
В остальном же город оставляет скорее печальное напоминание о том, что здесь когда-то был крупный международный экономический хаб с сопутствующими этому статусу инфраструктурой и культурой. Надеюсь, что со временем это изменится, или что такие впечатления остались только у меня.
На этот раз я всю неделю провел в отпуске, и мне есть, чем поделиться.
Благодаря семье, за первые 20 лет жизни я побывал в разных городах и странах – не слишком много, но все же получилось увидеть. В силу текущих обстоятельств, да и вообще интереса к разным уголкам нашей страны, важным гештальтом для меня стал Калининград (или Königsberg).
Интересным образом история этого анклава переплетается с историей нашей страны сквозь века. Я считал, что Калининград исторически и культурно был оторван от России, а сейчас выяснил, что он единожды уже входил в состав Российской империи, хоть и на каких-то три года.
Сам Калининград практически не создает впечатление европейского города – по крайней мере, относительно моих ожиданий. Редкие старые домики и разрушенные форты, небрежно разбросанные по всему городу, и за парой исключений на этом все. В то же время, туристический потенциал у города огромный, и видно, что сейчас на это наконец обратили внимание.
Наибольший интерес представляет остров в центре города – ныне он носит имя Имманиула Канта (прожившего практически всю жизнь в Кёнигсберге), а ранее носивший имя Кнайпхоф. Некогда целый город, сейчас – одно-единственное здание кафедрального собора, уцелевшее во время ВОВ. Внутри собора установлен самый большой в России органный комплекс, и концерт оставляет сильные впечатления даже у тех, кто далек от музыки – просто сходите, если будет возможность. Отдельно отмечу, что формат мини-концерта мне понравился, потому что с непривычки больше часа можно и не выдержать.
Не меньшее впечатление оставил музей Канта, а если точнее, история и образ жизни философа. Такие вещи сложно описывать словами, но если в общих чертах – это про переоценку ценностей. А еще теперь у меня есть хорошее оправдание для тех, кто не успел взять ипотеку: Иммануил Кант впервые обзавелся собственным жильем в 59 лет.
В остальном же город оставляет скорее печальное напоминание о том, что здесь когда-то был крупный международный экономический хаб с сопутствующими этому статусу инфраструктурой и культурой. Надеюсь, что со временем это изменится, или что такие впечатления остались только у меня.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍3
Сложно описать, насколько велик контраст между Калининградом и Зеленоградском, несмотря на то, что между ними 30 минут на электричке. Если первый в ходе войны практически сровняли с землёй, то второй остался нетронутым, и будучи курортом-лечебницей для состоятельных граждан, сохранил и свой курортный вид до сегодняшнего дня. И вот здесь-то сделали все по уму.
Первое, что вводит в ступор при входе в город с вокзала – это выложенные плиткой улицы, дороги, пешеходные переходы, а полоса у тротуара и вовсе подсвечивается цветом светофора – вероятно, для удобства тех, кто живет в смартфоне.
Но основное впечатление оставляет общая атмосфера в городе, который хочется назвать скорее островом – это шаг куда-то далеко за пределы того, что происходит во внешнем мире.
Больше всего этому способствует то, что это город кошек. По всему городку можно встретить кошачьи домики-копии старых особняков, самих кошек на улицах, скамейках и в заведениях; граффити с ними на домах, статуэтки на пешеходном проспекте, нетрудно найти их на люках и столбиках – есть даже кошачий светофор. И музей кошек, разумеется.
Стоит лишь взять крендель и выбрать скамейку, как у тебя на коленях уже трется местный упитанный котяра. И это все не какое-то одно кафе, а целый город.
Конечно же, важно и то, что весь город усыпан старинными немецкими домиками и особняками, да и новая многоэтажная застройка за пределами центра города стилистически старается соответствовать традициям.
Еще один интересный новый опыт – сёрфинг. Большим удивлением для меня стало то, что такое вообще у нас есть, особенно для простых людей. По ощущениям это совсем не было похоже на сноуборд, хотя у всех, кто смог встать на ноги, включая меня, был опыт катания, поэтому какая-то корреляция, похоже, имеет место быть. Не могу и не стану рассказывать подробнее, потому что это надо пробовать и оценивать самостоятельно, но если сравнивать, для меня все-таки сноубординг >> сёрфинг.
Местные кухня и пиво однозначно требуют повторной оценки. Возможно, неоднократной. Это очень вкусно, не считая цеппелины и клопсы
Если подводить черту, хочу сказать, что отпуск выдался просто шикарный – как с точки зрения обывательского туризма, так и с точки зрения погружения в историю региона, ответов на многие внутренние вопросы, понимания, кто мы, и того, насколько велика и разнообразна наша страна.
Теперь же пора возвращаться к трудовым будням, ближайший месяц обещает быть интересным
#lognroll
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8❤6
Log & roll №3
У меня все равно плохо получается регулярно о чем-либо сообщать, потому что бывают такие моменты, когда написать нечего — рутина и рутина. В первую неделю после отпуска, сколько бы я ни был заряжен на работу, она вообще не шла в том темпе, в котором хотелось бы. Но за три недели что-то да накопилось.
💼 Работа
Я продолжил заниматься задачей по временным рядам, хорошо по ней продвинулся: добавил недостающие метрики, сделал кучу фиксов, написал огромную доку по каждому аспекту, докинул разные аугментации — в основном рутина, но отдельные моменты отмечу:
1️⃣ Подбор гиперпараметров
Оформил подбор гиперпараметров в максимально удобный скрипт, запустил и получил результаты. Скажу так: это шикарная возможность поднять метрики, особенно если есть ресурс на 20+ запусков обучения, а в моем случае это было возможно, поскольку модель очень легковесная. Здесь важно понимать, какой метод вам подойдет — будь то ASHA, которая при шаге, равном полному обучению, вырождается в Random Search, или же Model-based методы типа Байеса (однажды я напишу статью об этом...).
Капля дегтя – разные методы поддерживают разные типы данных – где-то есть поддержка категорий, где-то ее нет, где-то даже была поддержка квантованных (для русских людей – просто с меньшим числом значений после запятой, чтобы не было потом 0.232545589 в конфиге), но её убрали в новых версиях.
2️⃣ Пайплайн проекта
В этой задаче для разных типов временных рядов используются разные предобработки и модели, в связи с чем была необходимость в реализации достаточно серьезного пайплайна. Основная цель — сделать так, чтобы на вход можно было просто отправить практически любой ряд + его тип, а на выходе получить верный ответ. Я подошел к реализации с помощью Triton Business Logic Scripting (BLS). Я думал написать пост о нем, но не сложилось. (Если нужно, сообщите в комментах, потому что у меня в сохраненках два текста по нему, оба бросил👍 ).
Если кратко, то BLS — это скрипт на Python, который в Triton Inference Server трактуется как независимая модель. То есть, к ней так же пишется конфиг с I/O модели, внутри скрипта
Самое неприятное в этой задаче — куча разных мелочей, которые вылезают, потому что человеческий мозг (окей, подмножество {мой мозг}) не вмещает все нюансы разом. Это различные размерности, это правильная конвертация тензоров одного бэкенда в другой, это... в общем, об этом читать неинтересно. Главное — оно заработало, а я задолбался.
3️⃣ Документация
Документации было много, вплоть до ссылки на другие README внутри основного, но это не главное. Оказывается, в Gitlab есть поддержка Mermaid-графов, которые позволяют шикарно визуализировать пайплайн модели. Причем, судя по всему, эта поддержка есть уже давно. Да, достаточно просто написать '''mermaid, описать диаграмму и она появится в доке. Магия да и только. К сожалению, в Github не завезли.
👨💻 Продолжил рефакторинг BoxMOT
Я обнаружил еще одну важную проблему — в проекте мало того, что дублируется, так еще и разбросана в разных местах логика скачивания весов моделей. Я решил сделать так: назвал эту сущность
Затем у меня была долгая дилемма по поводу связывания различных сущностей вместе, но решилось это примерно так: роль скачивания берет на себя
Негусто, но немного продвинулся.
В иных аспектах пока тоже все в порядке — жизнь бьет ключом, пока что не по голове.
#lognroll
У меня все равно плохо получается регулярно о чем-либо сообщать, потому что бывают такие моменты, когда написать нечего — рутина и рутина. В первую неделю после отпуска, сколько бы я ни был заряжен на работу, она вообще не шла в том темпе, в котором хотелось бы. Но за три недели что-то да накопилось.
Я продолжил заниматься задачей по временным рядам, хорошо по ней продвинулся: добавил недостающие метрики, сделал кучу фиксов, написал огромную доку по каждому аспекту, докинул разные аугментации — в основном рутина, но отдельные моменты отмечу:
Оформил подбор гиперпараметров в максимально удобный скрипт, запустил и получил результаты. Скажу так: это шикарная возможность поднять метрики, особенно если есть ресурс на 20+ запусков обучения, а в моем случае это было возможно, поскольку модель очень легковесная. Здесь важно понимать, какой метод вам подойдет — будь то ASHA, которая при шаге, равном полному обучению, вырождается в Random Search, или же Model-based методы типа Байеса (однажды я напишу статью об этом...).
Капля дегтя – разные методы поддерживают разные типы данных – где-то есть поддержка категорий, где-то ее нет, где-то даже была поддержка квантованных (для русских людей – просто с меньшим числом значений после запятой, чтобы не было потом 0.232545589 в конфиге), но её убрали в новых версиях.
В этой задаче для разных типов временных рядов используются разные предобработки и модели, в связи с чем была необходимость в реализации достаточно серьезного пайплайна. Основная цель — сделать так, чтобы на вход можно было просто отправить практически любой ряд + его тип, а на выходе получить верный ответ. Я подошел к реализации с помощью Triton Business Logic Scripting (BLS). Я думал написать пост о нем, но не сложилось. (Если нужно, сообщите в комментах, потому что у меня в сохраненках два текста по нему, оба бросил
Если кратко, то BLS — это скрипт на Python, который в Triton Inference Server трактуется как независимая модель. То есть, к ней так же пишется конфиг с I/O модели, внутри скрипта
model.py реализуется класс с методом execute, а дальше делай с питоном все, что захочешь. И я сделал две обычные TensorRT модели, дописал BLS-скрипт, в котором вся-вся логика предобработки + отправка рядов в нужную модель + логика постобработки. Разумеется, сделал асинхронное обращение к моделям.Самое неприятное в этой задаче — куча разных мелочей, которые вылезают, потому что человеческий мозг (окей, подмножество {мой мозг}) не вмещает все нюансы разом. Это различные размерности, это правильная конвертация тензоров одного бэкенда в другой, это... в общем, об этом читать неинтересно. Главное — оно заработало, а я задолбался.
Документации было много, вплоть до ссылки на другие README внутри основного, но это не главное. Оказывается, в Gitlab есть поддержка Mermaid-графов, которые позволяют шикарно визуализировать пайплайн модели. Причем, судя по всему, эта поддержка есть уже давно. Да, достаточно просто написать '''mermaid, описать диаграмму и она появится в доке. Магия да и только. К сожалению, в Github не завезли.
Я обнаружил еще одну важную проблему — в проекте мало того, что дублируется, так еще и разбросана в разных местах логика скачивания весов моделей. Я решил сделать так: назвал эту сущность
ModelRegistry, дал ей геттеры, чтобы узнавать URL/названия доступных моделей, а также метод download. И все ее наследники должны просто прокинуть свои словарики с URL весов и прочей информацией, которая нужна для загрузки. Затем у меня была долгая дилемма по поводу связывания различных сущностей вместе, но решилось это примерно так: роль скачивания берет на себя
ModelRegistry, роль инициализации pytorch-модели берет на себя непосредственно класс модели — ReID или Detector, назовем этот метод build, а в PytorchBackend на вход будем подавать модель + веса. Негусто, но немного продвинулся.
В иных аспектах пока тоже все в порядке — жизнь бьет ключом, пока что не по голове.
#lognroll
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤1
А вот ссылка на всю секцию Computer Vision.
#links
Please open Telegram to view this post
VIEW IN TELEGRAM
❤🔥3👍1
Log & roll №4
Сперва отпуск и выход из него, потом задачи — короче, как всегда, регулярно писать посты не хочу и не буду. Расскажу немного про инсайды трекинга, что увидел, над чем работаю и вам советую.
1️⃣ Еще в июле изучил статью TrackTrack (это последний SOTA-1 трекер, который был на paperswithcode, больше их не будет в связи с закрытием сайта 😞 ).
В принципе, на первый взгляд весьма неплохо. Наконец-то зашли с той стороны, с которой на моей памяти не заходили — решили заменить венгерский алгоритм (задача о назначениях).
1) Они решили устроить своеобразный жадный алгоритм и матчить в несколько итераций.
2) Помимо этого применяют NMS к детекциям, чтобы не плодить два трека одному человеку.
3) Потом делают мощный пост-процессинг (!), получают хорошие метрики и называют статью Focusing on Track for Online (!) Multi-Object Tracking.
Не знаю, в какой момент в сфере трекинга стандартом стала такая подмена понятий, но опустим и допустим. В остальном выглядит бодро, трогать пока некогда, но интересно будет заменить обычный венгерский алгоритм и посмотреть на результаты.
2️⃣ Опять удивился тому, насколько все плохо в публикациях по трекингу
Давайте обратимся к SOTA-трекеру BoostTrack:
1) Используют они для ReID модельку
2) Видим в README надпись: "We use the same weights as Deep OC-SORT". Идем к ним в гости.
3) Находим там конфиг для обучения ReID и его содержание:
То есть, одни чуваки ссылаются на других, которые обучаются и получают метрики на одних и тех же данных. Не думаю, что это заслуживает каких-либо комментариев.
2️⃣ Продолжил думать над улучшением трекинга через ReID.
Собрал из MOT17 свой бенчмарк:
Почему собрал из MOT17? Потому что остальные доступные датасеты я пытаюсь использовать в обучении, а здесь в целом нормальный набор доменов — и азиаты, и европейцы, и сверху, и снизу, и сбоку, и днем, и ночью.
Сильно портит настроение bias каждого ReID-датасета, пытаюсь учить сразу на нескольких с архитектурными трюками внутри модели, по метрикам валидации хорошо, а по метрикам бенчмарка судя по всему модель выучивает N разных bias👍 . Вроде бы и неплохо модель справляется, но вопросы пока есть.
3️⃣ А что, если?
Решил рассмотреть вариант модели детекция + сегментация, чтобы удалять фон и получать более высокие метрики на ReID. Коллега из Швеции, автор boxmot, сказал, что это дало хороший прирост по метрикам, показал даже старый эксперимент, а я подумал — почему нет?
Проверил — конечно же все не так хорошо, как хотелось бы. Модель перестает узнавать одного и того же человека, хвосты распределений интра/интер расстояний становятся сильно шире, в общем — с первого раза не запустилось. Хочу поставить обучаться модель ReID с аугментацией в виде удаления фона — основная и скорее всего верная гипотеза состоит в том, что это происходит из-за сильного изменения распределения внутри данных и модель к такому не готова. Глобально ставки у меня небольшие на эту механику.
Сперва отпуск и выход из него, потом задачи — короче, как всегда, регулярно писать посты не хочу и не буду. Расскажу немного про инсайды трекинга, что увидел, над чем работаю и вам советую.
В принципе, на первый взгляд весьма неплохо. Наконец-то зашли с той стороны, с которой на моей памяти не заходили — решили заменить венгерский алгоритм (задача о назначениях).
1) Они решили устроить своеобразный жадный алгоритм и матчить в несколько итераций.
2) Помимо этого применяют NMS к детекциям, чтобы не плодить два трека одному человеку.
3) Потом делают мощный пост-процессинг (!), получают хорошие метрики и называют статью Focusing on Track for Online (!) Multi-Object Tracking.
Не знаю, в какой момент в сфере трекинга стандартом стала такая подмена понятий, но опустим и допустим. В остальном выглядит бодро, трогать пока некогда, но интересно будет заменить обычный венгерский алгоритм и посмотреть на результаты.
Давайте обратимся к SOTA-трекеру BoostTrack:
1) Используют они для ReID модельку
sbs_S50.pth. Причем под каждый датасет свою: MOT17, MOT20, DanceTrack. Уже сомнительно, копаем дальше.2) Видим в README надпись: "We use the same weights as Deep OC-SORT". Идем к ним в гости.
3) Находим там конфиг для обучения ReID и его содержание:
_BASE_: ../Base-SBS.yml
MODEL:
BACKBONE:
NAME: build_resnest_backbone
# Вот здесь
DATASETS:
NAMES: ("MOT17",)
TESTS: ("MOT17",)
OUTPUT_DIR: logs/MOT17/sbs_S50
То есть, одни чуваки ссылаются на других, которые обучаются и получают метрики на одних и тех же данных. Не думаю, что это заслуживает каких-либо комментариев.
Собрал из MOT17 свой бенчмарк:
видос/айди_человека/фотка_n.jpg. Считаю intra-inter расстояния, смотрю устойчивость к различным аугментациям, всякие там хитрые матрички рисую и т.д. Благодаря этому бенчмарку я, кстати, и понял, что там в BoostTrack дело нечисто — слишком хорошие были метрики, по моему опыту такого в жизни не бывает — опыт подтвердился.Почему собрал из MOT17? Потому что остальные доступные датасеты я пытаюсь использовать в обучении, а здесь в целом нормальный набор доменов — и азиаты, и европейцы, и сверху, и снизу, и сбоку, и днем, и ночью.
Сильно портит настроение bias каждого ReID-датасета, пытаюсь учить сразу на нескольких с архитектурными трюками внутри модели, по метрикам валидации хорошо, а по метрикам бенчмарка судя по всему модель выучивает N разных bias
Решил рассмотреть вариант модели детекция + сегментация, чтобы удалять фон и получать более высокие метрики на ReID. Коллега из Швеции, автор boxmot, сказал, что это дало хороший прирост по метрикам, показал даже старый эксперимент, а я подумал — почему нет?
Проверил — конечно же все не так хорошо, как хотелось бы. Модель перестает узнавать одного и того же человека, хвосты распределений интра/интер расстояний становятся сильно шире, в общем — с первого раза не запустилось. Хочу поставить обучаться модель ReID с аугментацией в виде удаления фона — основная и скорее всего верная гипотеза состоит в том, что это происходит из-за сильного изменения распределения внутри данных и модель к такому не готова. Глобально ставки у меня небольшие на эту механику.
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - vukasin-stanojevic/BoostTrack
Contribute to vukasin-stanojevic/BoostTrack development by creating an account on GitHub.
🔥3❤1
Я решил, что пора уже хорошенько туда влезть и навести порядок. Во-первых, разумеется, что-то нужно делать с параметрами — они подобраны непонятно кем и когда, я даже не смог найти следы (хотя когда-то находил в Github issues к какому-то репозиторию отсылку на чью-то статью/книгу, но потерял и не хочу снова искать). Есть две матрицы:
1) Q — ковариация процесса, т.е. насколько мы уверены в том, что человек резко не побежит или внезапно не уменьшится.
2) R — ковариация датчика, которая отражает наше доверие к детектору.
И вот мало того, что параметры подобраны неизвестным образом, так эти матрицы еще и идентичны. То есть у нас уверенность в процессе такая же, как в детекторе, хотя, объективно говоря, это абсурд. У нас достаточно простой процесс — ходят люди, и достаточно сложный случай для датчика — постоянно люди то пропадают, то перекрывают друг друга, то детектор банально косячит.
Но и это не все — изучил я несколько любопытных статей на тему модификаций фильтров Калмана и нашел одну очень интересную штуку, при проверке которой удалось сразу же воспроизвести результат из статьи (репозитория не было). Там был прирост натурально +1.5 по HOTA без дополнительного тюнинга.
В общем, если делаете трекинг и хотите получить премию на работе, смело влезайте в фильтр Калмана, ковыряйте там параметры, закидывайте адекватные улучшения, смотрите матмодель. Там поле непаханое.
Чтобы еще больше приобщиться к празднику "День железнодорожника", взял еще одну задачу из ЖД. Об этом если и расскажу, то потом на какой-нибудь конференции для настоящих стрелочников
В жизни тоже всё идёт своим чередом, понемногу готовлюсь к новому зимнему сезону — купил сноуборд и все сопутствующее, теперь есть полный комплект. Вернулся к занятиям музыкой с новой силой и упорством, получаю кайф оттого, что результаты оправдывают и даже опережают затраченные силы. Почти готов к новому спортивному сезону — остался буквально шаг до преодоления 10 км в нужном темпе. Неделю-две назад считал себя последним лентяем, перечитал текст и передумал, но любопытно — насколько странно и необъективно порой работает механизм самооценки, особенно когда читаешь о чужих успехах и невольно думаешь, что ни черта полезного не делаешь.
#lognroll
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🔥2🏆1