Как сеть «видит» картинку

Для нейросети нет «кошки» и нет «собаки» — есть огромная таблица чисел, в которой слой за слоем проступают сначала линии, потом формы, и только в самом конце — ответ.

Главная мысль урока: сеть не смотрит на картинку, как ты. Она видит сетку из чисел-пикселей и постепенно собирает из них всё более крупные подсказки — края, потом узоры, потом «округлые уши» — пока не наберёт достаточно, чтобы сказать «скорее кошка».

Зачем тебе это понимать

Открой галерею в телефоне и набери в поиске «кот». Телефон мгновенно найдёт все фотки с котами, хотя никто вручную их не подписывал. Залей селфи в любое приложение с масками — оно за долю секунды поймёт, где у тебя глаза, нос и рот. Загрузи мем в соцсеть — и иногда тебе прилетает предупреждение, что на картинке что-то запрещённое. Всё это делает нейросеть, которая «смотрит» на изображение.

Но вот в чём фокус: у сети нет глаз и нет понятия «кот». Когда ты глядишь на фото кошки, ты сразу видишь кошку целиком. Сеть так не умеет. Для неё картинка — это просто прямоугольник из чисел. И самое удивительное, что из этой кучи чисел она всё-таки вытаскивает ответ. К концу урока ты поймёшь, как именно: как фото превращается в числа и как слои сети по шажку добираются от отдельных точек до вывода «это кошка».

Мы продолжаем нашу сквозную задачу — отличить кошку от собаки. В прошлом уроке про веса, связи и слои мы разобрали, как нейроны соединяются в слои и передают сигнал дальше. Сегодня посмотрим, что вообще попадает на вход этим нейронам, когда речь идёт о картинке.

Пиксель — это одна крошечная точка изображения. Любая фотография — это сетка из таких точек, и каждая точка хранит число (или несколько чисел), описывающее её цвет.

Шаг первый: картинка — это таблица чисел

Представь миллиметровую бумагу в клеточку. Возьми чёрно-белый рисунок и закрась каждую клетку в зависимости от того, насколько она тёмная: совсем чёрная — поставь 0, совсем белая — 255, серая — что-то посередине. Поздравляю, ты только что превратил картинку в таблицу чисел ровно так же, как это делает компьютер.

Вот, например, как может выглядеть крошечное изображение 5 на 5 клеток, где из тёмных точек проступает галочка (значок «готово»):

0000200
0002000
200020000
0200000
00000

Глазами ты видишь галочку из светлых клеток на тёмном фоне. Сеть видит именно эти 25 чисел — и больше ничего. Никаких «линий» и «форм» на входе нет, только числа.

А если картинка цветная

С цветом всё почти так же, просто чисел больше. Каждый пиксель цветного фото хранит не одно число, а три: сколько в нём красного, сколько зелёного и сколько синего (это называют каналами R, G, B). Смешивая эти три в разных пропорциях, можно получить любой цвет. То есть цветная фотка — это уже не одна таблица чисел, а три таблицы, сложенные стопкой.

Посчитаем, насколько это много. Обычное фото с телефона — это примерно 3000 на 4000 пикселей, да ещё умножить на 3 канала. Получается больше 36 миллионов чисел в одной картинке. Неудивительно, что сеть не может просто «глянуть» — ей приходится перемалывать гигантскую таблицу.

Шаг второй: зачем нужны слои

Окей, на входе — куча чисел. Но как из «пикселя номер 14 равен 200» получить «это кошка»? Одним прыжком — никак. Поэтому сеть действует поэтапно, слой за слоем, и на каждом этапе ищет что-то покрупнее, чем на предыдущем.

Лучшая метафора тут — то, как ты сам разглядываешь незнакомую картинку издалека. Сначала твой глаз цепляется за отдельные штрихи и края. Потом из штрихов складываются фигуры: круг, треугольник, дуга. Потом фигуры собираются в знакомые части: «о, это похоже на ухо», «а это глаз». И только когда частей набралось достаточно, мозг выдаёт: «это морда кошки». Нейросеть для картинок устроена ровно по этой лестнице.

СлойЧто он находитПример для кошки
Первые слоиПростейшие края и линии: где светлое сменяется тёмнымКонтур уха, граница шерсти и фона
Средние слоиУзоры и формы из этих краёвТреугольное ухо, круглый глаз, полоски на шерсти
Поздние слоиЦелые части объекта«Кошачья мордочка», «лапа», «усы»
Последний слойИтоговое решениеКошка — 0.92, собака — 0.08

Обрати внимание: каждый следующий слой работает не с пикселями напрямую, а с тем, что нашёл предыдущий. Первый слой говорит «вот тут есть наклонный край». Второй слой видит группу краёв и говорит «а это похоже на треугольное ухо». Так признаки растут от мелких к крупным, как снежный ком.

Признак — это измеримая характеристика, по которой модель принимает решение. Раньше мы придумывали признаки вручную («форма ушей»). Сеть для картинок находит признаки сама, слой за слоем, и они становятся всё сложнее с глубиной.

Чем это отличается от ручных признаков

Помнишь самые первые уроки про кошку и собаку? Тогда мы сами решали, какие признаки важны: длина ушей, форма морды, громкость лая. Человек придумывал список характеристик, а модель только взвешивала их.

С картинками так не выйдет — никто не сможет вручную описать миллионы пикселей правилами вроде «если пиксель 14 тёмный, то...». Поэтому глубокая сеть делает шаг вперёд: она сама изобретает себе признаки. Первый слой сам приходит к тому, что полезно искать края. Средний — что полезно искать уши и глаза. Никто не задаёт это вручную — всё это выучивается из данных тем же спуском по ошибке, что мы разбирали раньше. В этом и сила: ты не объясняешь сети, как выглядит кошка, ты просто показываешь ей тысячи кошек.

Шаг третий: как слой находит край

Давай заглянем чуть глубже в самый первый слой — как он вообще понимает, что «тут край». Идея простая: край — это место, где соседние пиксели резко отличаются. Внутри ровной шерсти соседние числа похожи. А на границе уха и фона рядом стоят, например, 30 и 210 — резкий скачок. Вот этот скачок слой и ловит.

Сеть берёт маленькое окошко (например, 3 на 3 пикселя), скользит им по всей картинке и в каждом месте проверяет: есть ли тут перепад яркости и в какую сторону. Если рядом стоят похожие числа — края нет. Если резкий перепад — есть, и слой отмечает это место. Покажем эту проверку «на пальцах» в коде. Тут небольшой кусочек строки пикселей, и мы ищем, где яркость прыгает сильнее всего.

// одна строка пикселей: яркость от 0 (чёрный) до 255 (белый)
const row = [20, 22, 19, 21, 200, 205, 198, 202];
//   слева ровная тёмная шерсть, потом резкий скачок к светлому фону

console.log("позиция -> перепад яркости между соседями:");
for (let i = 1; i < row.length; i++) {
  const jump = Math.abs(row[i] - row[i - 1]);
  const mark = jump > 100 ? "  <-- КРАЙ!" : "";
  console.log("между " + (i - 1) + " и " + i + ": перепад = " + jump + mark);
}

Вывод:

позиция -> перепад яркости между соседями:
между 0 и 1: перепад = 2
между 1 и 2: перепад = 3
между 2 и 3: перепад = 2
между 3 и 4: перепад = 179  <-- КРАЙ!
между 4 и 5: перепад = 5
между 5 и 6: перепад = 7
между 6 и 7: перепад = 4
между 7 и 8: перепад = ...

Видишь? Внутри тёмной шерсти перепады крошечные — 2, 3, 2. А между позициями 3 и 4, где тёмное сменяется светлым, перепад огромный — 179. Именно тут слой и говорит: «здесь край». Настоящая сеть делает то же самое, только сразу по всей картинке и во всех направлениях — а какие именно перепады считать важными, она выучивает сама, подкручивая веса.

Шаг четвёртый: возвращаемся к кошке против собаки

Соберём всё вместе на нашей сквозной задаче. Что происходит, когда ты показываешь обученной сети фото кошки?

  1. Фото превращается в таблицу из миллионов чисел-пикселей.
  2. Первый слой пробегает по ней и отмечает все края: контуры ушей, границу шерсти и фона, линию усов.
  3. Средние слои собирают из краёв формы: треугольное ухо, круглый глаз, узкий вертикальный зрачок.
  4. Поздние слои складывают формы в части: «кошачья морда», «лапа».
  5. Последний слой смотрит на собранные части и выдаёт два числа: насколько это похоже на кошку и насколько на собаку. Скажем, 0.92 против 0.08.

Сравни это с тем, как мы решали ту же задачу в самых первых уроках. Тогда человек вручную задавал признаки вроде «форма ушей», и модель взвешивала готовый список. Теперь сеть сама добывает признаки прямо из пикселей — и поэтому ей не нужно объяснять, что такое ухо. Та же задача, но на новом уровне глубины. Это и есть нить, которую мы тянем через весь курс: одна и та же кошка-против-собаки, только понятая всё подробнее.

Очень важно: сеть не «понимает» картинку

Тут легко поверить в магию, поэтому остановимся честно. Когда сеть выдаёт «кошка — 0.92», она не понимает, что такое кошка, как понимаешь ты. Она не знает, что кошка мурлычет, боится пылесоса и любит коробки. Для неё «кошка» — это просто такая комбинация чисел-признаков, при которой обученные веса дают высокий балл в нужной ячейке.

Из-за этого случаются забавные и поучительные провалы:

  • Покажи сети кошку в необычной позе или в темноте — и она может растеряться, ведь таких пикселей среди обучающих примеров было мало.
  • Известны случаи, когда модель путала пушистый круассан с щенком — потому что по пикселям они правда похожи, а смысла «это еда, а это животное» у сети нет.
  • Можно подсунуть картинку с еле заметным специально подобранным шумом, который человек вообще не замечает, — а сеть уверенно назовёт кошку собакой. Это называют атакой на модель, и она возможна именно потому, что сеть оперирует числами, а не смыслом.

Так что «видит» в заголовке мы взяли в кавычки не зря. Сеть не видит и не понимает — она очень хорошо считает совпадение чисел с выученными узорами. Это мощно и полезно, но это не зрение и не сознание.

Частые ошибки и подводные камни

Вот о что обычно спотыкаются, когда впервые разбираются, как сеть работает с картинками.

1. Думать, что сеть видит объект целиком

Самое частое заблуждение. Кажется, что сеть как-то «глядит» на фото и узнаёт кошку одним махом. На деле на входе нет ни кошки, ни даже линий — только таблица чисел. Всё остальное сеть строит сама, по слою за раз. Держи в голове именно лестницу «пиксели → края → формы → части → ответ».

2. Путать «больше пикселей» с «умнее»

Кажется, что фото в сверхвысоком разрешении сеть поймёт лучше. Но огромная картинка — это просто ещё больше чисел перемалывать, дольше и тяжелее. Сети для распознавания обычно сжимают вход до небольшого размера (вроде 224 на 224), потому что важны не мельчайшие детали, а общие формы. Размер ещё не ум.

3. Считать, что первые слои уже «видят кошку»

Нет. Первый слой умеет только замечать края и перепады яркости. Он понятия не имеет про ухо или морду — это работа поздних слоёв. Сложность признаков растёт с глубиной, и пытаться найти «нейрон кошки» в первом слое бессмысленно.

4. Верить, что сеть нельзя обмануть

Раз она так точна, кажется, что её не проведёшь. Но именно потому, что она считает числа, а не понимает смысл, её обманывают и необычным ракурсом, и специальным шумом, и просто непохожим на обучающие примеры случаем. Высокая точность на тесте не значит надёжность в любой ситуации.

5. Забывать про разметку

Сеть не родилась со знанием, как выглядит кошка. Кто-то заранее показал ей тысячи фото с метками «кошка» и «собака» — это всё то же обучение с учителем из прошлых уроков. Без размеченных примеров никакие слои сами по себе ничего бы не нашли.

Мини-практика: нарисуй цифру числами

Закрепим всё руками, без компьютера. Возьми лист в клетку и карандаш.

  1. Начерти сетку 7 на 7 клеток.
  2. Закрась клетки так, чтобы получилась цифра, например 7 или 1 — пусть тёмные клетки будут телом цифры.
  3. Теперь подпиши в каждой клетке число: 0 для пустой (белой) клетки и, скажем, 200 для закрашенной (тёмной).
  4. Получилась таблица из 49 чисел. Это ровно то, что увидела бы сеть на входе — без всякой «цифры».
  5. Теперь сыграй за первый слой: обведи каждое место, где тёмная клетка стоит рядом со светлой. Это и есть края, которые нашёл бы первый слой.

Бонус для смелых: попробуй в коде из четвёртого шага поменять массив row на свою строку пикселей и подбери порог (сейчас 100) так, чтобы он ловил твои перепады. Поэкспериментируй: что будет, если в строке вообще нет резких скачков? А если их несколько? Так ты на пальцах почувствуешь, как слой решает, где край, а где ровная поверхность.

Итоги

Сегодня ты разобрал, что на самом деле происходит, когда нейросеть «смотрит» на картинку.

  • Любая картинка для сети — это таблица чисел-пикселей. Чёрно-белая — одна таблица, цветная — три (каналы R, G, B). Никаких линий и форм на входе нет.
  • Сеть работает слоями: первые находят простые края, средние — формы, поздние — целые части, а последний выдаёт ответ. Признаки растут от мелких к крупным.
  • В отличие от ручных признаков из первых уроков, глубокая сеть сама изобретает себе признаки прямо из пикселей — её этому никто не учит правилами, она выучивает их из размеченных данных.
  • Та же сквозная задача «кошка или собака» поднялась на новый уровень: вместо заданных человеком характеристик сеть добывает их из самого изображения.
  • И главное по-честному: сеть не понимает картинку. Она очень хорошо считает совпадение чисел с выученными узорами — поэтому её можно сбить необычным ракурсом или специальным шумом.

Теперь у тебя есть полная картина того, как нейросеть обрабатывает изображение — от пикселя до ответа. Но кошки с собаками — это про зрение. А что с нашим вторым сквозным примером, фразой «Кошка пьёт ...»? Текст ведь не разложишь по клеточкам, как фото. В следующих уроках мы разберёмся, как сеть превращает в числа слова, — и встретим эмбеддинги и токены, по пути к тому, как устроен ChatGPT.

Проверьте себя
1. Что попадает на вход нейросети, когда ей показывают фотографию?
AГотовое описание объекта на картинке
BСетка из чисел-пикселей, где каждое число — яркость или цвет точки
CКонтуры и линии, заранее обведённые человеком
DСамо слово «кошка» или «собака»
2. Сколько чисел хранит один пиксель цветного фото?
AОдно число — общую яркость
BДва числа — светлоту и тень
CТри числа — сколько красного, зелёного и синего (R, G, B)
DНисколько, цвет хранится отдельно от пикселей
3. Что находят самые первые слои сети, обрабатывающей изображение?
AСразу целую кошачью морду
BПростейшие края и перепады яркости
CГотовый ответ «кошка» или «собака»
DПороду животного
4. Чем подход глубокой сети к картинкам отличается от ручных признаков из первых уроков?
AСеть сама находит признаки прямо из пикселей, а не получает их готовым списком от человека
BСеть вообще не использует признаки
CЧеловек по-прежнему вручную описывает каждый пиксель правилами
DРазницы нет, это одно и то же
5. Почему в заголовке слово «видит» взято в кавычки?
AПотому что сеть видит только чёрно-белые картинки
BПотому что сеть не понимает смысл, а лишь считает совпадение чисел с выученными узорами
CПотому что у сети есть настоящие глаза, но плохое зрение
DЭто просто опечатка автора
6. Почему сеть можно обмануть необычным ракурсом или специально подобранным шумом?
AПотому что у сети мало памяти
BПотому что она оперирует числами и узорами, а не смыслом объекта
CПотому что сеть устаёт после многих картинок
DПотому что цветные фото всегда сбивают модель