emoji Machine Learning Roadmap 2025: большая карта входа в ML без сказок про “нейросети за месяц

Большой русскоязычный roadmap по машинному обучению: от первого import numpy до LLM, RAG, fine-tuning, AI-агентов и MLOps и даже вабкодинга.

Внутри нормальная структура: что учить, в каком порядке, зачем это нужно и что должно получиться на практике после каждого этапа.

Roadmap разбит на 7 треков:

1. Фундамент: Python, математика, статистика, инструменты
2. Классический ML: scikit-learn, табличные данные, метрики, валидация
3. Deep Learning: PyTorch, CNN, RNN, training loop
4. LLM и трансформеры: attention, KV-cache, RAG, LoRA, агенты
5. Generative AI: изображения, видео, аудио, мультимодальность
6. MLOps и прод: Docker, Kubernetes, CI/CD, monitoring, serving
7. Специализация: CV, NLP, RecSys, RL, Safety

Roadmap не продаёт иллюзию “обучил модель - стал ML-инженером”.

В реальной работе много времени уходит на данные, метрики, деплой, мониторинг, воспроизводимость и разбор ошибок. Модель - только часть системы.

Хорошая мысль из roadmap: LLM не делает джуна сеньором. Она ускоряет того, кто уже понимает базу. Без базы человек просто становится оператором Copilot, который не может объяснить, почему всё сломалось.

По времени тоже без сказок:

1. 0-3 месяца: математика, классический ML
2. 3-6 месяцев: Deep Learning и PyTorch
3. 6-12 месяцев: LLM, RAG, fine-tuning, AI-агенты
4. 12+ месяцев: MLOps, прод, масштабирование, специализация

Тут же собрано 7 болших бесплатных курсов по машинному обучению, математике и вайбкодингу!

Если давно хотели зайти в ML системно, а не прыгать между роликами про ChatGPT, Stable Diffusion и “топ-10 библиотек”, это хороший ориентир.

https://github.com/justxor/MachineLearningRoadmap
1 12 286
Форма логина и JWT-токен — ещё не безопасность приложения. На практике ошибки в аутентификации и авторизации становятся причиной утечек данных, проблем с доступом и уязвимостей, которые сложно обнаружить до выхода системы в production.

26 мая в 20:00 МСК приглашаем вас на открытый урок курса «C# ASP.NET Core-разработчик». На занятии разберём, как в ASP.NET Core устроены pipeline, middleware и схемы аутентификации. Покажем, как правильно использовать JWT, cookies, claims, роли и policy-based авторизацию для гибкого и безопасного контроля доступа.

Отдельно обсудим типичные ошибки, которые встречаются в production: небезопасное хранение токенов, ошибки настройки схем и проблемы в логике авторизации. Урок будет полезен .NET-разработчикам, которые хотят систематизировать знания по безопасности веб-приложений и увереннее работать с ASP.NET Core в реальных проектах.

Регистрация уже открыта:
https://otus.pw/tDF66/?erid=2W5zFGbdS73


Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.
1 3 473
C# Roadmap: с нуля до профи

Практическое руководство по росту в C#-разработке. Материал собран для тех, кто хочет получить инженерную глубину, а не просто накликать CRUD по туториалам.

Здесь последовательность изучения, лучшие практики, ресурсы и трезвый разбор того, как работать с ИИ-инструментами и оставаться востребованным.

https://github.com/Develp10/Csharp_Roadmap/
6 98 1.4K
⏱️ Ускоряем async-код в C#: не просто await, а нормальная параллельность

Одна из частых ошибок в C# - писать независимые асинхронные операции так, будто они зависят друг от друга:


await GetUserAsync();
await GetOrdersAsync();
await GetRecommendationsAsync();


Выглядит нормально, но по факту это последовательное выполнение.

Если каждый запрос занимает примерно 1 секунду, весь блок будет выполняться около 3 секунд. Не потому что async медленный, а потому что мы сами заставили код ждать каждый шаг по очереди.

Правильнее запускать независимые операции сразу:


var userTask = GetUserAsync();
var ordersTask = GetOrdersAsync();
var recsTask = GetRecommendationsAsync();

await Task.WhenAll(userTask, ordersTask, recsTask);


Теперь все запросы стартуют одновременно, а общее время будет примерно равно самому долгому из них.

Но есть важный нюанс.

Task.WhenAll не делает CPU-код магически параллельным. Он особенно полезен для I/O-bound задач:

- запросы в базу
- HTTP-вызовы
- чтение файлов
- обращения к внешним API
- независимые операции с сетью

И ещё один момент: после WhenAll лучше доставать результаты уже из завершённых задач:


var user = await userTask;
var orders = await ordersTask;
var recs = await recsTask;

Так код остаётся читаемым, ошибки нормально пробрасываются, а логика не превращается в кашу.

Async/await сам по себе не ускоряет код. Он просто даёт возможность не блокировать поток. Ускорение появляется тогда, когда вы правильно запускаете независимые операции вместе, а не ждёте их по одной.
11 36 1.8K
На Stepik обновили курс «C# с нуля до профи»

Представьте: через четыре месяца вы открываете чужой .NET-проект и читаете его как книгу.

IServiceCollection не вызывает ступора. async Task<IActionResult> пишется на автомате. Вы точно знаете, почему EF Core сгенерировал именно такой SQL - и как переписать запрос, чтобы он летал.

Это не фантазия. Это результат после 16 модулей, в которых каждая концепция объясняется через код и закрепляется практикой.

ООП, SOLID, LINQ, async/await, DI, EF Core, ASP.NET Core, Docker, Kubernetes - всё, что казалось магией, станет рабочим инструментом.

А бонусом - портфолио проектов: от CLI-утилит и REST API до собственного SaaS с multi-tenancy, JWT и деплоем в Kubernetes под TLS.

Скидка - 58% доступна 48 часов: https://stepik.org/a/282984/
1 13 1.4K
emoji UUID v7 - это почти ULID, только нативно в .NET

Раньше в .NET для идентификаторов чаще всего использовали обычный Guid.NewGuid().

Проблема в том, что классический UUID случайный. Для уникальности это удобно, но для базы данных - не всегда.

Когда значения генерируются хаотично, новые записи вставляются в разные части индекса. Отсюда:

- больше фрагментации
- дороже вставки
- чаще перестраиваются страницы индекса
- хуже поведение на больших таблицах

Поэтому многие разработчики начали использовать ULID.

ULID состоит из двух частей:

- timestamp
- random

За счет timestamp такие ID сортируются по времени, а значит база может вставлять новые записи более последовательно.

Но начиная с .NET 9 появился встроенный вариант:

Guid.CreateVersion7()

UUID v7 тоже содержит временную часть, поэтому лучше подходит для индексируемых ключей, чем полностью случайный UUID.

Главное отличие:

ULID - отдельный формат и часто сторонняя библиотека.
UUID v7 - обычный Guid, который уже поддерживается в .NET.

Для новых проектов это выглядит как более разумный дефолт:

- не Guid.NewGuid()
- не отдельный ULID-пакет
- а Guid.CreateVersion7()

Особенно если Guid используется как primary key в базе.
1 27 1.3K
Что выведет код?


using System;

class Program
{
static void Main()
{
int x = 10;

Console.WriteLine(x++ + ++x);
}
}



Правильный ответ: 22

Почему: выражение считается слева направо. Сначала x++ возвращает 10, но потом увеличивает x до 11. Затем ++x сначала увеличивает x до 12, потом возвращает 12. В итоге 10 + 12 = 22.
3 2 2K
🚀 ASP.NET Core в 2026: если не знаешь это - ты отстал

Одна картинка закрывает почти весь стек, который реально нужен в проде. Без воды и устаревших практик.

Сейчас ASP.NET Core уже не про «сделать API», а про систему: от роутинга и DI до очередей, кешей и realtime. Если ты всё ещё пишешь просто контроллеры и думаешь, что этого достаточно - плохие новости.

Что важно:

• основа осталась той же, но усложнился прод
• логирование и мониторинг теперь обязательны
• кеш без стратегии уже не спасает
• без resilience и retry твой сервис падает при первой же проблеме

Отдельно бросается в глаза тренд:

минимум магии, максимум контроля
ручной mapping вместо AutoMapper
явная архитектура вместо «оно само работает»

И ещё момент, который многие игнорят:

• экосистема вокруг стала важнее самого фреймворка
• Redis, Kafka, OpenAPI, gRPC, SignalR - это уже не «дополнительно», это база

Если коротко:

ASP.NET Core сейчас это не про backend
это про сборку полноценной распределённой системы

И вопрос уже не в том, знаешь ли ты .NET
а в том, умеешь ли ты строить сервисы, которые живут под нагрузкой
4 112 2K
Почему async void ломает ваш код

В C# у async void есть дурная репутация, и не зря. Такой метод не возвращает Task, а значит, его нельзя await-ить, нельзя встроить в пайплайн и невозможно корректно отследить завершение.

Исключения из него не ловятся обычным образом — они пробиваются в синхронизационный контекст или в пул потоков, где легко превращаются в необработанные и могут уронить процесс.


// Контроллер ASP.NET Core
[HttpPost]
public async void Create() { await _svc.DoAsync(); } // Исключения мимо pipeline

// Библиотека
public async void SaveAsync(Item item) { await _repo.Save(item); } // Вызывающему не сконтролировать


Правильно — всегда возвращать Task:

[HttpPost]
public async Task<IActionResult> Create() { await _svc.DoAsync(); return Ok(); }

public Task Invoke(HttpContext ctx) => _next(ctx);

public Task SaveAsync(Item item) => _repo.Save(item);


Единственный сценарий, где async void уместен, — обработчики событий в UI-фреймворках вроде WPF или WinForms, где сигнатура задаётся самим фреймворком. Там приходится мириться, но даже там стоит ловить исключения локально и логировать их.
3 19 1.9K
Когда Hash Join быстрее Nested Loops

Внутри SQL-движка соединение таблиц — это не магия, а конкретный алгоритм. Сравним два подхода к соединению таблиц.

Nested Loops работает буквально так, как звучит: берём строку из первой таблицы и ищем совпадения во второй. Если вторая таблица имеет подходящий индекс, поиск по нему будет очень быстрым, и такой алгоритм блестяще справляется с задачей маленькое соединяется с большим.

Hash Join подходит там, где Nested Loops захлёбывается. Он сначала строит хэш-таблицу по одной из входных таблиц, а затем пробегается по второй и ищет совпадения через хэш-функцию. Это даёт огромный выигрыш, когда нужно соединить два больших набора данных, и когда индексов для ускорения поиска нет. Цена такого подхода — расход памяти.

В итоге — если речь идёт о маленьком наборе строк против большого и есть индекс, Nested Loops окажется быстрее. Но если обе таблицы крупные и индексы не спасают, Hash Join чаще всего становится оптимальным выбором.

#dotnet_challenge
3 11 2.1K
🔥 Ты не проверишь весь код, если он большой, но нужные инструменты проверят

Невозможно вручную ревьюить каждую строчку. Даже в маленьком проекте что-то ускользает.

Здесь и подключается статический анализ.

Он работает как второй слой контроля прямо во время разработки. Подсвечивает баги, плохие паттерны и потенциальные уязвимости ещё до запуска кода.

В итоге ты ловишь проблемы на раннем этапе, а не после релиза.

Для C# это особенно просто внедряется. Пара настроек и у тебя уже есть автоматический аудит кода без лишней боли.

Если пишешь на C# и не используешь статический анализ, ты реально теряешь быстрые фиксы и чистоту кода.

Начать можно отсюда
2 40 2.1K
🚨 «Нет времени на тесты» уже не работает

В 2026 писать тесты стало проще, чем придумывать оправдания
ИИ генерит шаблоны, дописывает кейсы и закрывает рутину

Если у тебя есть нормальная структура, всё остальное ускоряется в разы

Вот минимальный стек, который покрывает почти всё

• Для юнитов
• xUnit остаётся стандартом
• TUnit можно смотреть как более современную альтернативу

Для ассёртов
• Shouldly даёт максимально читаемые проверки
• FluentAssertions теперь платный, это стоит учитывать

Для интеграционных тестов
Aspire сильно упрощает жизнь
WebApplicationFactory плюс TestContainers дают реальные зависимости в тестах
Respawn чистит базу между прогонами

Для фронта
• Playwright сейчас лучший выбор
• Selenium уже больше про легаси

Для моков
• NSubstitute самый чистый по API
• Moq как дефолт, если привык

Для данных
Bogus и AutoFixture закрывают генерацию тестовых сценариев

Для перфома нса
• BenchmarkDtNet для микро-бенчей
• k6 для нагрузки
• NBomber если хочешь остаться в C#

Что по факту важно

Тебе не нужен весь этот стек сразу
Достаточно двигаться по порядку

• Сначала юнит-тесты
• Потом интеграция
• Потом нагрузка
• Потом E2E

Самый частый фейл не в инструментах
А в том, что тесты откладывают «на потом»

В 2026 это уже странное решение

Гайд по интеграционным тестам в Aspire
https://antondevtips.com/blog/dotnet-aspire-integration-testing-best-practices-for-distributed-applications?utm_source=twitter&utm_medium=social&utm_campaign=09-04-2026
7 57 2.1K
avatar
C# 1001 notes
Переслано от канала
23.03.2026 15:00
🚀 Почему этот EF Core код тормозит?

Технически - всё ок.
По производительности не очень.

Вот типичная ошибка:

❌ Загружаешь всю сущность (все колонки)
❌ Потом фильтруешь и мапишь уже в памяти

Что происходит:
- лишние данные тянутся из БД
- растёт нагрузка на сеть
- увеличивается потребление памяти
- замедляется приложение

✅ Как правильно:

Используй проекцию через `.Select()` прямо в запросе:

- берёшь только нужные поля
- меньше данных из БД
- быстрее запрос
- меньше нагрузка на систему

📌 Правило простое:
Не тащи всё - бери только то, что используешь

Именно такие мелочи чаще всего дают x2–x10 к скорости.
8 15 2.3K
Полезный паттерн для Minimal APIs в .NET, если вы хотите организовать проект по принципу Vertical Slice Architecture.

Идея очень простая.

Вместо того чтобы держать все роуты в Program.cs, каждый endpoint выносится в отдельный класс.

Создаётся небольшой интерфейс:


public interface IEndpoint
{
void MapEndpoint(IEndpointRouteBuilder app);
}


Дальше каждый endpoint просто реализует этот интерфейс:

public class GetFollowerStats : IEndpoint
{
public void MapEndpoint(IEndpointRouteBuilder app)
{
app.MapGet("users/{userId}/followers/stats", async (
Guid userId,
ISender sender) =>
{
var query = new GetFollowerStatsQuery(userId);

Result<FollowerStatsResponse> result = await sender.Send(query);

return result.Match(Results.Ok, CustomResults.Problem);
})
.WithTags(Tags.Users);
}
}


Что это даёт:
• endpoints изолированы по фичам
• код становится намного чище
• проще масштабировать API
• удобно использовать вместе с CQRS / MediatR

Регистрация таких endpoints занимает буквально пару миллисекунд при старте приложения.

Отличный способ держать Minimal API структурированным даже в больших проектах.
6 33 2.7K
avatar
C# 1001 notes
Переслано от канала
16.03.2026 16:45
Vector Search - как это работает (и почему это важно для .NET разработчиков)

Vector search ищет смысловую близость, а не просто точные совпадения.

Он сравнивает данные - текст, изображения или аудио - используя векторные эмбеддинги в многомерном пространстве.

То есть система ищет не одинаковые слова, а похожие по смыслу объекты.

Почему это важно?

Vector search лежит в основе многих AI-функций:

- семантический поиск
- рекомендательные системы
- интеграции с LLM
- умные ассистенты внутри приложений

Добавив векторный поиск в приложение, разработчик может создавать намного более умные продукты, которые понимают смысл запросов пользователя.

Это дает реальную бизнес-ценность - от поиска по документам до персонализированных рекомендаций.

📍 Полный пример реализации
6 45 2K
⚡️ Языки программирования и их самые любимые фичи

• 🐍 Python - чистый и читаемый синтаксис
• 🖥️ BASIC - очень дружелюбен для новичков
• 📊 Visual Basic - простое создание GUI
• 🟨 JavaScript - запускается везде и сразу
• 🐘 PHP - очень простой деплой веб-приложений
• 💎 Ruby - красивый и элегантный синтаксис
• 🎵 Groovy - бесшовная интеграция с Java
• ☕ Java - огромная экосистема и стабильность
• 🟣 C# - отличные инструменты и IDE
• 🐹 Go - простая и быстрая конкурентность
• 🐦 Swift - современный и безопасный дизайн
• 🅺 Kotlin - встроенная защита от null
• 🎯 Dart - отлично работает с Flutter
• 🧮 Fortran - сверхбыстрые научные вычисления
• 🔧 C - полный контроль над железом
• 🍎 Objective-C - мощная динамическая runtime-система
• 🔺 Scala - сочетание функционального и ООП
• ⚡ Zig - простой и предсказуемый системный код
• 🐪 Perl - невероятно мощная обработка текста
• 🚀 C++ - высокая производительность и контроль
• 🦀 Rust - безопасность памяти без garbage collector
• ⚙️ Assembly - максимальный контроль и производительность
7 11 3K
В .NET 8 появился простой способ сделать HttpClient устойчивым к сбоям — буквально одной строкой.

Microsoft добавила библиотеку Microsoft.Extensions.Http.Resilience, в которой уже есть готовые pipeline’ы для обработки ошибок при HTTP-запросах.

Что это даёт из коробки:
- Retry при временных сбоях
- Timeout
- Circuit Breaker
- Rate limiting
- Защиту от перегрузки

Подключается максимально просто:


services.AddHttpClient<GitHubService>(static httpClient =>
{
httpClient.BaseAddress = new Uri("https://api.github.com/");
})
.AddStandardResilienceHandler();
2 84 3.9K
⚡️ URL shortener за <100 строк на .NET - реально

Идея простая: у тебя есть входной URL -> генеришь короткий код -> сохраняешь в БД -> по коду делаешь редирект.

Что нужно собрать

- Генератор уникального кода
Делай base62 (0-9, a-z, A-Z) длиной 6-8 символов.
Главное - гарантировать уникальность:
- либо проверка в БД и повтор генерации при коллизии
- либо уникальный индекс по Code и ретрай при ошибке сохранения

- База данных
Таблица ShortenedUrl:
- Id (Guid)
- LongUrl (string)
- Code (string, unique)
- CreatedOnUtc (DateTime)
Опционально:
- ExpiresOnUtc
- Clicks
- CreatedByIp

- 2 эндпоинта (Minimal API)
- POST /shorten
- валидируешь URL (Uri.TryCreate)
- генеришь code
- формируешь shortUrl из scheme + host + code
- сохраняешь в БД
- возвращаешь shortUrl
- GET /{code}
- ищешь code в БД
- если нет - 404
- если есть - Results.Redirect(LongUrl)

Почему чаще всего "падают" такие сервисы

- Коллизии кода -> решается unique index + retry
- Открытый редирект на мусор -> валидируй UriKind.Absolute и при желании режь опасные схемы (только http/https)
- Производительность поиска -> индекс по Code обязателен
- Правильный shortUrl за прокси -> если сервис за nginx/cloudflare, учитывай Forwarded Headers, иначе host/scheme будут неправильными

Если делать максимально чисто - генератор кода отдельным сервисом, модель + DbContext, и два эндпоинта. Это и укладывается в <100 строк.
4 36 3.5K