Демо: отличаем кошку от собаки

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

Главная мысль урока: «отличить кошку от собаки» — это не магия и не понимание. Это конвейер: картинка превращается в признаки, признаки умножаются на веса, веса складываются в одно число, и по этому числу сеть говорит «кошка» или «собака». Сегодня ты проследишь весь конвейер от начала до конца на нашем сквозном примере.

Зачем тебе это демо

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

Этот урок — сборка. Мы уже разбирали по кусочкам: что такое признак, что такое вес, как сеть видит картинку, как она учится на ошибках. Сегодня мы соединим все кусочки в одну работающую цепочку на нашем сквозном примере «кошка или собака». Никакого нового матана — только то, что ты уже знаешь, но теперь целиком.

Классификация — это когда модель раскладывает объекты по заранее известным классам-папкам. У нас две папки: «кошка» и «собака». Задача сети — для новой картинки выбрать правильную папку.

Метафора: сортировщик на конвейере

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

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

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

Сортировщик на складеНейросеть для кошек/собак
Коробка на лентеКартинка на входе
Приметы: усы, размер, цветПризнаки: форма ушей, текстура шерсти, форма морды
Насколько он доверяет приметеВес у признака
Сложил приметы в головеСумма «признак × вес»
Две тележкиДва класса: кошка / собака
Бросил в тележкуФинальное предсказание

Держи эту картинку в голове весь урок. Всё дальнейшее — просто детализация этого конвейера.

Шаг за шагом: от пикселей к ответу

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

Стадия 1. Картинка → числа

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

Стадия 2. Числа → признаки

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

Стадия 3. Признаки → одно число (score)

Вот сердце конвейера. У каждого признака есть свой вес. Сеть умножает каждый признак на его вес и всё складывает — получается одно число, назовём его score. Чем оно больше, тем сильнее сеть склоняется к «кошке».

Стадия 4. Score → ответ и уверенность

Score — это пока просто число вроде 2.3 или -1.1. Чтобы превратить его в понятный ответ, сеть прогоняет score через сжимающую функцию, которая выдаёт вероятность от 0 до 1. Близко к 1 — «уверенно кошка», близко к 0 — «уверенно собака», около 0.5 — «сеть в растерянности». Вот и весь путь.

Разбираем на коде: конвейер целиком

Давай оживим эти четыре стадии. Возьмём три простых признака для нашего сквозного примера. Каждый признак — число от 0 до 1, где 1 — «ярко выражено». Веса — те, что сеть как будто бы уже выучила: положительный вес тянет к кошке, отрицательный — к собаке.

// Стадия 2: картинка уже свёрнута в три признака (0..1)
const cat = { roundEars: 0.9, furSoft: 0.8, longSnout: 0.1 };
const dog = { roundEars: 0.2, furSoft: 0.4, longSnout: 0.9 };

// Веса, которые сеть выучила при обучении
const weights = { roundEars: 2.0, furSoft: 1.0, longSnout: -2.5 };
const bias = -0.2; // лёгкий сдвиг "по умолчанию"

// Стадия 3: признаки * веса, всё складываем -> score
function score(animal) {
  return (
    animal.roundEars * weights.roundEars +
    animal.furSoft   * weights.furSoft +
    animal.longSnout * weights.longSnout +
    bias
  );
}

// Стадия 4: сжимаем score в вероятность 0..1
function sigmoid(x) {
  return 1 / (1 + Math.exp(-x));
}

function classify(name, animal) {
  const s = score(animal);
  const p = sigmoid(s);
  const answer = p > 0.5 ? "кошка" : "собака";
  console.log(
    name + ": score=" + s.toFixed(2) +
    ", вероятность кошки=" + p.toFixed(2) +
    " -> " + answer
  );
}

classify("Картинка A", cat);
classify("Картинка B", dog);

Вывод:

Картинка A: score=2.35, вероятность кошки=0.91 -> кошка
Картинка B: score=-1.85, вероятность кошки=0.14 -> собака

Смотри, что произошло. Для картинки A признаки кошачьи: круглые уши (0.9), мягкая шерсть (0.8), морда короткая (longSnout = 0.1). Круглые уши с весом 2.0 дали большой плюс, длинная морда почти не сработала. Score взлетел до 2.35, сигмоида сжала его в 0.91 — сеть уверенно говорит «кошка».

Для картинки B всё наоборот: морда длинная (0.9) с весом -2.5 утащила score глубоко в минус, до -1.85. Вероятность кошки 0.14 — то есть вероятность собаки 0.86. Сеть говорит «собака». Заметь: нигде в коде нет слова «понять» или «узнать морду». Есть только умножения и сложения. Это и есть весь интеллект на данном уровне.

Где здесь веса из прошлых уроков

Объект weights — это ровно те самые числа, которые в прошлых уроках подкручивались на ошибках, спускаясь по склону. Я вписал их вручную, чтобы конвейер было видно целиком, но на деле сеть нашла бы их сама, прогнав тысячи размеченных картинок. Большой положительный вес 2.0 у круглых ушей означает «сеть выучила: круглые уши — сильный признак кошки». Отрицательный -2.5 у длинной морды — «длинная морда тянет к собаке». Веса — это вся память сети о том, что она видела.

Когда конвейер ошибается

Самое интересное начинается, когда картинка пограничная. Возьмём пушистую собаку с подозрительно круглыми ушами — например молодого шпица. Признаки перепутаются, и мы увидим, как сеть теряется.

const weights = { roundEars: 2.0, furSoft: 1.0, longSnout: -2.5 };
const bias = -0.2;

function sigmoid(x) { return 1 / (1 + Math.exp(-x)); }

function classify(name, a) {
  const s = a.roundEars * weights.roundEars +
            a.furSoft   * weights.furSoft +
            a.longSnout * weights.longSnout + bias;
  const p = sigmoid(s);
  console.log(
    name + ": вероятность кошки=" + p.toFixed(2) +
    " -> " + (p > 0.5 ? "кошка" : "собака")
  );
}

// Пушистый шпиц: уши круглые, шерсть мягкая, но морда длинноватая
classify("Пушистый шпиц", { roundEars: 0.8, furSoft: 0.9, longSnout: 0.5 });
// Сфинкс: кошка без шерсти и с большими ушами
classify("Кошка-сфинкс", { roundEars: 0.5, furSoft: 0.0, longSnout: 0.2 });

Вывод:

Пушистый шпиц: вероятность кошки=0.74 -> кошка
Кошка-сфинкс: вероятность кошки=0.62 -> кошка

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

А сфинкс — настоящая кошка — еле-еле прошёл как кошка (0.62), хотя должен бы пройти уверенно: у него нет мягкой шерсти, и важный признак не сработал. Чуть-чуть других весов — и сеть записала бы его в собаки. Вот ровно так и рождаются ошибки распознавания, о которых ты, может, читал мемы.

Та же история, но со словами

Наш второй сквозной пример — фраза «Кошка пьёт ...» — устроен точь-в-точь так же, просто признаки там не «уши», а контекст из предыдущих слов. Сеть превращает слова в числа, умножает на веса, складывает и для каждого возможного следующего слова получает score. У слова «молоко» score высокий, у «кирпич» — низкий. После сжатия score'ов в вероятности сеть выдаёт что-то вроде: молоко — 0.6, вода — 0.3, кирпич — 0.001. Тот же конвейер «признаки → веса → score → вероятность», только классов не два, а весь словарь. Когда дойдём до ChatGPT, ты увидишь, что и там внутри живёт этот же конвейер, просто очень-очень большой.

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

На этом сборочном уроке новички спотыкаются о несколько штук. Разберём, чтобы у тебя в голове осталась честная картинка.

1. Думать, что сеть «видит» картинку, как ты

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

2. Путать score и вероятность

Score — это сырое число, оно может быть и -5, и +8, его трудно сравнивать между картинками. Вероятность — это score, сжатый в диапазон от 0 до 1, её уже можно читать как «уверенность». Когда говорят «сеть на 90% уверена», имеют в виду вероятность 0.90, а не score.

3. Верить, что высокая уверенность = правильный ответ

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

4. Считать, что веса задаёт программист

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

5. Забывать про границу 0.5

Ответ «кошка или собака» получается сравнением вероятности с порогом 0.5. Но порог — это наше решение, а не закон природы. Если ошибиться, приняв собаку за кошку, для нас не страшно — можно сдвинуть порог. А вот в медицине или в беспилотнике цена ошибки разная для разных классов, и порог двигают осознанно. Граница 0.5 — удобная, но не священная.

Мини-практика: сломай и почини конвейер

Теперь твоя очередь покрутить ручки. Возьми за основу первый пример (объекты cat, dog, weights и функцию classify) и поэкспериментируй:

  1. Добавь четвёртый признак — например loudBark (громко лает, 0..1) с весом, который тянет к собаке. Какой знак у этого веса — плюс или минус? Включи признак в score и проверь, изменился ли ответ для шпица.
  2. Найди такие три признака, при которых сеть выдаёт ровно 0.50 — полную растерянность. Что это говорит о картинке?
  3. Урони вес круглых ушей с 2.0 до 0.1. Что станет с ответом для кошки-сфинкса и почему? Так ты увидишь, как «забывание» одного признака ломает распознавание.
  4. Сделай мысленный эксперимент со вторым сквозным примером: придумай три «слова-признака» для фразы «Кошка пьёт ...» и реши, у какого следующего слова score должен быть выше — у «молоко» или у «бетон».

Лучший способ понять конвейер — не прочитать про него, а сломать его своими руками и посмотреть, в каком месте посыпался ответ.

Итоги

Сегодня ты собрал всю цепочку распознавания воедино — на нашем сквозном примере кошки и собаки.

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

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

Проверьте себя
1. Какова правильная последовательность стадий, через которые проходит картинка в нашей сети?
AПризнаки → пиксели → ответ → score
BКартинка → пиксели → признаки → score → вероятность и ответ
CScore → признаки → веса → картинка
DКартинка → ответ → признаки → веса
2. Что в сети играет роль «насколько сортировщик доверяет примете»?
AПризнак
BВес
CScore
DПорог 0.5
3. Почему в примере пушистый шпиц был ошибочно классифицирован как кошка?
AВ коде была опечатка
BСеть устала и начала ошибаться
CКруглые уши и мягкая шерсть дали сильные кошачьи сигналы, перевесив длинную морду
DУ шпица не было ни одного признака
4. Чем score отличается от вероятности?
AЭто одно и то же число
BScore — сырое число любого размера, а вероятность — это score, сжатый в диапазон от 0 до 1
CВероятность всегда больше score
DScore измеряется в процентах, а вероятность — в пикселях
5. Что значит, что сеть выдала «кошка» с вероятностью 0.74, хотя на фото собака?
AСеть всегда права, значит это всё-таки кошка
BВысокая уверенность гарантирует правильный ответ
CСеть может быть уверенно неправа: по её признакам и весам объект сильно похож на кошку, но это не значит, что ответ верен
DВероятность 0.74 означает, что сеть выбрала собаку
6. Как связан этот конвейер с нашим вторым сквозным примером — фразой «Кошка пьёт ...»?
AНикак, текст обрабатывается совершенно иначе
BТам тот же конвейер «признаки → веса → score → вероятность», только признаки — это контекст слов, а классов не два, а весь словарь
CЯзыковая модель не использует веса
DДля слов вероятность не считается