ИИ для инженера: основы Машинное обучение: картинки, звук, текст
0%

Машинное обучение: картинки, звук, текст

Машинное обучение: картинки, звук, текст

Фрагмент лекции: «Все что нужно знать про ИИ айтишнику», 12:15 — отсюда взято содержание этой главы.

Есть утверждение, которое стоит принять до того, как в тексте появится слово «нейросеть»:

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

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

Три семейства методов и три домена данных

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

Полезнее другое различение — по тому, откуда берётся решающее правило:

Семейство Откуда берётся правило Пример
Детерминированные алгоритмы Программист выписал его руками Перцептивный хеш, OCR по эталонным глифам
Поисковая оптимизация (SBSE) Правило известно, но нужно найти хороший вариант в огромном пространстве Генерация тестов, автоматический ремонт кода
Машинное обучение Правило не выписывается, параметры подбираются по данным Классификатор изображений, распознавание речи

Про среднюю строку отдельно, потому что в лекции аббревиатура употреблена неточно. SBSE — Search-Based Software Engineering, применение метаэвристической поисковой оптимизации (генетические алгоритмы, локальный поиск, роевые методы) к задачам разработки программного обеспечения. Термин ввели Марк Харман и Брайан Джонс в 2001 году в работе «Search-based software engineering» (Information and Software Technology, 43(14), DOI). Это не про цепи Маркова и не про «просто перебор»: перебор — вырожденный частный случай, а весь смысл направления в том, чтобы не перебирать всё. Пересказывать здесь нечего — на портале есть целый трек по SBSE.

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

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

Изображения: перцептивный хеш

Пользователь загружает фотографию котика, в базе лежит миллион фотографий, вопрос: есть ли среди них эта же самая или почти эта же самая? Побайтовое сравнение бесполезно — пережатие в JPEG с другим качеством, изменение размера на пиксель, водяной знак в углу меняют файл целиком. Криптографический хеш (SHA-256) бесполезен ещё сильнее: он спроектирован так, чтобы один изменённый бит на входе полностью менял выход.

Значит, нужна функция, у которой всё ровно наоборот: похожие входы дают похожие выходы. Такая функция называется перцептивным хешем.

Алгоритм aHash

Самый простой рабочий вариант — average hash. Ровно тот, который в лекции рисуют на доске.

Каждый шаг здесь выбрасывает ровно тот вид информации, который мешает:

  1. Уменьшение до крошечной сетки убивает разрешение и мелкие детали. После него уже не важно, был оригинал 400×400 или 4000×4000, и не важен шум матрицы.
  2. Градации серого выбрасывают цвет. Для задачи «то же ли это изображение» цветовой сдвиг от другого профиля камеры — помеха.
  3. Порог по среднему значению самой картинки, а не по константе. Именно поэтому равномерное осветление или затемнение всей фотографии хеш не меняет: среднее уезжает вместе с пикселями.
  4. Остаётся битовая строка — грубая карта «где светлее, где темнее». Это и есть отпечаток.
from PIL import Image


def average_hash(path: str, size: int = 8) -> int:
    """Перцептивный хеш изображения (aHash).

    Возвращает целое число, младшие size*size бит которого и есть хеш.
    При size=8 это привычные 64 бита.
    """
    # Шаг 1-2: уменьшаем сетку и убираем цвет.
    # convert("L") — перевод в один канал яркости (градации серого).
    img = Image.open(path).convert("L").resize((size, size), Image.LANCZOS)

    pixels = list(img.getdata())            # size*size значений яркости 0..255

    # Шаг 3: порог считается по самому изображению, а не задан константой.
    avg = sum(pixels) / len(pixels)

    # Шаг 4: каждый пиксель превращается ровно в один бит.
    bits = 0
    for p in pixels:
        bits = (bits << 1) | (1 if p >= avg else 0)
    return bits


def hamming_distance(a: int, b: int) -> int:
    """Расстояние Хэмминга: в скольких битовых позициях числа различаются.

    XOR ставит единицу там, где биты не совпали; остаётся их посчитать.
    int.bit_count() доступен с Python 3.10.
    """
    return (a ^ b).bit_count()

Сложность. Уменьшение изображения — O(W*H) по времени и памяти на исходную картинку, это доминирующая часть. Всё остальное работает над n = size*size элементами: среднее O(n), бинаризация O(n), память O(n); при size = 8 это 64 операции, то есть бесплатно. Сравнение двух хешей — O(n / w) машинных слов, для 64 бит одна инструкция процессора. Поиск по базе наивно O(N) сравнений на запрос: для миллиона хешей это микросекунды, для миллиарда — уже нет, и тогда берут BK-деревья или multi-index hashing (хеш режется на куски, при малом пороге хотя бы один кусок обязан совпасть точно и ищется обычным индексом).

Родственники: dHash и pHash

aHash — самый грубый член семейства, и он чувствителен к изменению контраста. dHash отличается от кода выше буквально одной строкой: сетка берётся size+1 на size, а бит ставится по сравнению соседних пикселей (px[i] > px[i+1]), а не со средним. Кодируется градиент яркости, поэтому любое монотонное преобразование яркости хеш не меняет; зато появляется чувствительность к сдвигу кадра. pHash объясняет цифру «32×32» из лекции: картинка уменьшается до 32×32, к ней применяется дискретное косинусное преобразование, и берётся верхний левый блок 8×8 — низкие частоты, то есть общая структура без деталей. Он устойчивее всех к масштабу, гамме и лёгкой обрезке и заметно дороже остальных. Готовые реализации всех трёх лежат в библиотеке imagehash.

Чем перцептивный хеш отличается от криптографического

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

Свойство Криптографический хеш (SHA-256) Перцептивный хеш (aHash, pHash)
Изменение одного бита входа Полностью меняет выход (лавинный эффект) Почти не меняет выход
Близкие входы Дают далёкие выходы — это цель Дают близкие выходы — это цель
Расстояние между хешами Не несёт смысла Мера непохожести объектов
Задача Целостность, подписи, пароли Поиск похожего, дедупликация
Атакующий может Практически не может подобрать коллизию Легко подбирает коллизию намеренно

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

Порог: откуда берётся число

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

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

Подбирают порог так: берут размеченную выборку пар («это одна и та же картинка» / «разные»), считают расстояния для всех пар, строят зависимость доли ложных срабатываний и доли пропусков от порога и выбирают точку по цене ошибок. Порог зависит и от длины хеша: 10 несовпавших бит из 64 и 10 из 256 — это разные степени непохожести, поэтому переносить число между алгоритмами нельзя.

Это ровно та дисциплина, которой посвящена статья про оценку моделей: precision, recall, ROC-кривая и выбор рабочей точки. И это же первый звоночек темы всей главы — один параметр здесь уже подбирается по данным, а не выписывается из первых принципов.

Расстояние Хэмминга: откуда оно на самом деле

Расстояние Хэмминга между двумя строками одинаковой длины — это количество позиций, в которых символы различаются. 10110 и 10011 различаются в двух позициях, расстояние равно 2.

В лекции сказано, что оно «из теории игр», и рядом упоминается равновесие Нэша. Это неверно, и повторять не нужно. Расстояние Хэмминга ввёл Ричард Хэмминг в 1950 году в теории кодирования, в работе «Error Detecting and Error Correcting Codes» (Bell System Technical Journal, 29(2), DOI). Задача была сугубо инженерная: перфокарты и линии связи вносили ошибки в биты, и требовалось не только заметить искажение, но и восстановить исходное сообщение. Отсюда вся конструкция: если любые два допустимых кодовых слова отстоят друг от друга минимум на d, то код гарантированно обнаруживает d - 1 ошибок и исправляет (d - 1) / 2 — принятое слово относят к ближайшему допустимому. Коды Хэмминга до сих пор работают в оперативной памяти с ECC. Для нашей задачи важно и то, что это метрика: неотрицательность, симметричность, неравенство треугольника. Благодаря этому по хешам можно строить метрические индексы (те самые BK-деревья) и говорить о «ближайшем соседе» осмысленно.

Границы применимости

Перцептивный хеш не переживает поворот и зеркальное отражение (лечится грубо: хешируют все четыре поворота и отражение) и разваливается на обрезке, потому что кроп сдвигает всю сетку — там нужны локальные признаки (SIFT, ORB) или нейросетевые эмбеддинги. Но главное ограничение другое: два разных рыжих кота — это два разных изображения. Хеш отвечает на вопрос «это тот же файл?», а не «это тот же объект?»; за второй отвечают свёрточные сети. Разница между этими двумя вопросами и есть граница главы: первый решается кодом, второй — нет.

Звук: спектр, спектрограмма, отпечаток

Звук в файле — это последовательность чисел: амплитуда давления, замеренная 44 100 раз в секунду. Сравнивать эти числа напрямую бессмысленно: сдвиг записи на одну тысячную секунды меняет их все, а на слух не меняет ничего. Поэтому переходят к спектру. Преобразование Фурье раскладывает сигнал на сумму синусоид: вместо «какая амплитуда в момент времени t» получается «какая мощность на частоте f». Ноту «ля» первой октавы задаёт основной тон 440 Гц, а тембр — набор обертонов, кратных частот 880, 1320, 1760 Гц и далее, с индивидуальным для каждого инструмента распределением мощности. Скрипка и труба на одной ноте различаются именно распределением мощности по обертонам.

Одна беда: спектр всей записи выбрасывает время. Поэтому сигнал режут на короткие окна (обычно 20–50 мс с перекрытием) и считают спектр в каждом окне. Результат — спектрограмма, двумерная карта «время × частота», где значение — мощность. Изображение. И дальше со звуком работают ровно теми же приёмами, что и с картинками.

Аудиоотпечаток: пики и пары пиков

Наивная идея «взять спектрограмму и сравнить целиком» не работает: в кафе на запись накладывается шум посуды, динамик заваливает низа, телефон режет верха. Нужны признаки, которые переживут всё это. Такими признаками оказались локальные пики спектрограммы — точки, которые громче всех соседей в окрестности. Шум добавляет энергии, но редко создаёт новые локальные максимумы там, где их не было, и почти не убирает существующие. Дальше — ключевой ход из работы Ави Ванга «An Industrial-Strength Audio Search Algorithm» (ISMIR, 2003), той самой, по которой построен Shazam: хешируется не отдельный пик, а пара пиков — две частоты и временной интервал между ними. Такой хеш гораздо специфичнее одиночного пика и при этом не зависит от абсолютного времени.

import numpy as np
from scipy.signal import stft
from scipy.ndimage import maximum_filter


def fingerprints(samples: np.ndarray, rate: int, fan_out: int = 5, dt_max: float = 5.0):
    """Отпечаток записи: хеши пар пиков спектрограммы.

    Отдаёт пары «(частота якоря, частота цели, интервал) -> время якоря».
    Абсолютное время в сам хеш не входит, поэтому отпечаток фрагмента
    совпадает с отпечатком того же места в полной записи.
    """
    freqs, times, z = stft(samples, fs=rate, nperseg=1024, noverlap=512)
    mag = np.abs(z)                          # мощность по осям (частота, время)

    # Пик — точка, максимальная в своей окрестности и при этом достаточно
    # громкая: слабые локальные максимумы порождает шум, а не музыка.
    is_peak = (maximum_filter(mag, size=20) == mag) & (mag > np.percentile(mag, 99))
    f_idx, t_idx = np.nonzero(is_peak)
    peaks = sorted(zip(times[t_idx], freqs[f_idx]))   # [(время, частота), ...]

    for i, (t1, f1) in enumerate(peaks):
        # Каждый якорь связывается с несколькими ближайшими следующими пиками.
        for t2, f2 in peaks[i + 1: i + 1 + fan_out]:
            if 0 < t2 - t1 <= dt_max:
                yield (int(f1), int(f2), round(t2 - t1, 2)), t1

Сложность. STFT — O(K * W log W) при K окнах длины W, память O(K * W) на спектрограмму. Поиск пиков линеен по её размеру, генерация отпечатков — O(P * fan_out) при P пиках. Поиск по базе — константа на хеш при хеш-индексе, дальше линейное голосование по найденным совпадениям.

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

Открытая реализация той же идеи — Chromaprint / AcoustID. Обучения здесь по-прежнему нет: всё считается формулами, подбираются только несколько порогов.

Распознавание речи: где заканчивается эта аналогия

В лекции распознавание речи описано как «работа с паттернами»: не разбираемся, как физически произносится буква «А», а сравниваем спектральные шаблоны. Для доглубинных систем это описание верное, и именно так строились промышленные распознаватели с 1980-х по начало 2010-х:

  • MFCC (мел-частотные кепстральные коэффициенты) — сжатие спектра каждого окна в 13–40 чисел с учётом того, что человеческий слух различает низкие частоты тоньше высоких. Это ручные признаки: формула написана человеком.
  • HMM (скрытые марковские модели) — модель того, как скрытые состояния (фонемы) порождают наблюдаемые векторы признаков и переходят друг в друга. Прямая родня цепей Маркова из предыдущей главы, только состояния не наблюдаются напрямую. Каноническая работа — обзор Лоуренса Рабинера 1989 года «A Tutorial on Hidden Markov Models and Selected Applications in Speech Recognition» (DOI).

Связка MFCC + HMM + отдельная языковая модель была отраслевым стандартом два десятилетия. Но это ровно та точка, где нужно сказать прямо: современные системы распознавания речи устроены иначе. Ручные признаки и марковские состояния заменены нейросетевыми энкодерами, которые учат представление звука прямо из данных, а декодирование делается end-to-end. Whisper, на котором, кстати, расшифрована исходная лекция, — модель этого поколения (статья OpenAI, 2022). Как устроены рекуррентные энкодеры, с которых начался этот переход, — в статье про RNN и LSTM.

Текст: OCR

OCR (Optical Character Recognition, оптическое распознавание символов) — превращение изображения текста в текст. Классический конвейер целиком состоит из выписанных руками шагов:

  1. Бинаризация. Серое изображение → чёрное и белое. Глобальный порог работает только на идеальном скане; на фотографии с неравномерным светом нужен адаптивный (метод Оцу, локальные пороги).
  2. Выравнивание (deskew). Скан почти всегда положен под углом. Угол оценивают по преобразованию Хафа или по проекционным профилям и поворачивают изображение.
  3. Сегментация. Разделение на блоки, строки, слова, символы. Обычно — по горизонтальным и вертикальным профилям плотности чёрного: между строками плотность падает до нуля.
  4. Нормализация глифа. Вырезанный символ обрезается по границам, масштабируется к канонической сетке (например, 16×16), центрируется по центру масс. После этого «А» кеглем 10 и кеглем 40 выглядят одинаково.
  5. Сопоставление с эталонами. Нормализованный глиф сравнивается с эталонными изображениями букв. Побеждает ближайший.
  6. Языковая модель поверх. Символы, которые не различаются уверенно, доопределяются по контексту.

Шаги 4–5 — буквально та же схема, что и с картинками: свести к маленькой битовой сетке и сравнить расстоянием Хэмминга.

from math import log


def match_glyph(glyph: int, templates: dict[str, int]) -> list[tuple[str, int]]:
    """Кандидаты для глифа, отсортированные по расстоянию Хэмминга.

    glyph и эталоны — битовые маски одной сетки (например, 16x16).
    Это буквально метод ближайшего соседа, только метрика битовая.
    """
    return sorted(((ch, (glyph ^ m).bit_count()) for ch, m in templates.items()),
                  key=lambda pair: pair[1])


def pick_with_context(candidates, prev_char: str, bigrams: dict, alpha: float = 8.0):
    """Итоговый выбор: цена = непохожесть картинки минус доверие к языку.

    bigrams[(a, b)] — вероятность того, что за символом a идёт b, по корпусу;
    это цепь Маркова первого порядка. alpha задаёт баланс между картинкой
    и языком и подбирается по размеченной выборке, а не назначается.
    """
    def cost(pair):
        ch, distance = pair
        # Сглаживание: нулевых вероятностей быть не должно, иначе log уйдёт в -inf.
        return distance - alpha * log(bigrams.get((prev_char, ch), 1e-6))

    return min(candidates, key=cost)[0]

Сложность. Сопоставление одного глифа — O(A) сравнений при алфавите из A эталонов, каждое сравнение O(1) для маски в машинное слово; для страницы из S символов это O(S * A), память O(A) на эталоны. Даже с несколькими начертаниями на букву — тысячи операций на страницу.

Языковая модель поверх: связь с цепями Маркова

Пятый шаг ошибается предсказуемо: 0 и O, 1 и l и I, rn и m, русские с, о, а и латинские c, o, a. По картинке они различаются на единицы пикселей, и никакое улучшение эталонов эту проблему не снимает — информации в изображении просто нет. Зато она есть в языке. Вероятность биграммы «ЩЪ» в русском тексте практически нулевая, а «СТ» — высокая. Ровно эта конструкция разбиралась в главе про цепи Маркова: вероятность следующего символа при условии предыдущего, посчитанная по корпусу. В коде выше она и стоит: сначала картинка даёт список кандидатов с ценой похожести, потом язык переоценивает их своей ценой, и выбирается лучший по сумме.

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

Про историю: что было на самом деле

В лекции история OCR перевёрнута: там звучат «патент под Apple» и «сделано в Советском Союзе» в одном предложении. Восстановим проверяемую часть без выдуманных подробностей.

  • Систему рукописного ввода Calligrapher для карманного компьютера Apple Newton MessagePad разработала компания ParaGraph International, основанная Степаном Пачиковым. Это тот самый распознаватель, который угадывал написанное стилусом на экране, — предок жестового ввода на современных планшетах.
  • Российская компания ABBYY выпускает OCR-систему FineReader — один из самых известных промышленных распознавателей документов (abbyy.com). Про патенты, приоритеты и «кто был первым» здесь ничего не утверждается: без источника это домыслы.

Из открытых движков стоит знать Tesseract. Его история сама по себе иллюстрирует тему главы: до версии 4 он работал по описанному выше классическому конвейеру, а начиная с версии 4 распознавание строки выполняет LSTM-сеть. Тот же самый переход, что и в распознавании речи, и по той же причине.

Где кончается алгоритм и начинается обучение

Теперь можно сформулировать вывод главы — и он же мост в следующую.

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

Возьмите три разобранных алгоритма. В каждом человек знал, на что смотреть: на карту светлого и тёмного, на локальные максимумы спектрограммы, на форму глифа в нормализованной сетке. Работа программиста состояла в том, чтобы описать это знание формулой. Обучение здесь не нужно, потому что нечему учиться: правило уже известно.

А теперь задачи, где так не выходит. Отличить кошку от собаки на произвольной фотографии — какой признак? Уши бывают любые, кадр любой, свет любой. Понять, доволен ли клиент по тексту отзыва — список «плохих слов» ломается на первом же сарказме. Распознать речь в шумном помещении с акцентом — спектральных шаблонов не хватает, вариативность больше, чем можно перечислить.

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

Переход не бинарный, и это важнее, чем кажется. Порог расстояния Хэмминга — уже один параметр, подобранный по данным. Коэффициент alpha в OCR-переоценке — второй. Таблица биграмм — третий, и уже целая таблица. Дальше параметров становится десятки, тысячи, миллиарды, и в какой-то момент перестаёт иметь смысл спрашивать, что значит каждый из них: разница между alpha = 8.0 и весами трансформера количественная, а не качественная.

Практический вывод, который стоит унести в работу: не начинайте с обучения. Если признак выписывается — выпишите. Детерминированный алгоритм отлаживается, воспроизводится, объясняется пользователю и не требует ни разметки, ни видеокарты; перцептивный хеш дедуплицирует миллион фотографий на ноутбуке за минуты, и никакая нейросеть не даст здесь выигрыша, соразмерного её стоимости. Обучение — это то, к чему переходят, когда код измеримо не справился, а не то, с чего начинают. О том, что такое «признаки» и как их готовят, — в статье про данные и признаки; о сопоставлении с эталоном как о полноценном методе машинного обучения — в статье про kNN и наивный Байес, потому что match_glyph выше и есть метод ближайшего соседа.

Источники

  • Hamming R. W. «Error Detecting and Error Correcting Codes» // Bell System Technical Journal, 29(2), 1950 — DOI
  • Wang A. «An Industrial-Strength Audio Search Algorithm» // ISMIR, 2003 — PDF
  • Rabiner L. R. «A Tutorial on Hidden Markov Models and Selected Applications in Speech Recognition» // Proceedings of the IEEE, 77(2), 1989 — DOI
  • Harman M., Jones B. F. «Search-based software engineering» // Information and Software Technology, 43(14), 2001 — DOI
  • Radford A. et al. «Robust Speech Recognition via Large-Scale Weak Supervision» (Whisper), 2022 — arXiv
  • Krawetz N. Looks Like It — разбор перцептивных хешей; рабочие реализации: imagehash, Chromaprint / AcoustID, Tesseract

Мини-итог

  • Изображение, звук и текст — это домены данных, а не разделы машинного обучения; схема у всех трёх классических алгоритмов одна: свести сырые данные к короткому устойчивому представлению и сравнивать представления, а не данные.
  • Перцептивный хеш — не сжатие и не шифрование, а хеш, у которого намеренно сломан лавинный эффект: близкие входы дают близкие выходы. Криптографический хеш строится ровно наоборот.
  • Расстояние Хэмминга — из теории кодирования, введено Ричардом Хэммингом в 1950 году для обнаружения и исправления ошибок передачи; к теории игр отношения не имеет.
  • Порог расстояния не берётся из головы: он подбирается по размеченной выборке как компромисс между ложными срабатываниями и пропусками и зависит от длины хеша.
  • Аудиоотпечаток строится на локальных пиках спектрограммы и хешах пар пиков, а решение принимается не по факту совпадения, а по согласованности временных смещений.
  • MFCC и HMM были стандартом распознавания речи два десятилетия, но современные системы работают на нейросетевых энкодерах; то же произошло и с OCR внутри Tesseract.
  • Граница проста: признак выписывается руками — пишите код; не выписывается — подбирайте параметры по данным. Переход количественный, и начинать всегда стоит с кода.

Что дальше

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

Нейросети: как обучают модель

Нашли неточность? Выделите фрагмент текста — рядом появится жучок.

Нужен разбор именно вашей ситуации?

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

Доска запросов