Глава 12.
Тестирование, оптимизация
и развертывание моделей
481
Этот тест охватывает очень много всего, так что разобьем его на части. Сначала
мы создаем модель, используя вспомогательную функцию. В ходе этого теста нас
не интересует структура модели, мы обращаемся с ней как с «черным ящиком».
Контролируем формы входных и выходных сигналов:
expect(model.inputs.length).toEqual(1);
expect(model.inputs[0].shape).toEqual([null, maxLen]);
expect(model.outputs.length).toEqual(1);
expect(model.outputs[0].shape).toEqual([null, 1]);
Подобные тесты могут уловить проблемы неправильной идентификации измере
ния батчей — регрессия или классификация, форма выходного сигнала и т. д. Далее
мы компилируем и обучаем модель в течение очень маленького числа шагов. Наша
цель — просто убедиться в обучаемости модели, безошибочность, устойчивость
и сходимость нас пока что не волнуют:
const history = await model.fit(xs, ys, {epochs: 2, batchSize: 2})
expect(history.history.loss.length).toEqual(2);
expect(history.history.acc.length).toEqual(2);
Этот фрагмент кода также проверяет выдачу при обучении требуемых метрик
для анализа, ведь если бы мы обучали ее понастоящему, то хотели бы следить за
ходом обучения и степенью безошибочности полученной в его результате модели.
Наконец, пробуем простой вывод:
const predictOuts = model.predict(xs);
expect(predictOuts.shape).toEqual([2, 1]);
const values = predictOuts.arraySync();
expect(values[0][0]).toBeGreaterThanOrEqual(0);
expect(values[0][0]).toBeLessThanOrEqual(1);
expect(values[1][0]).toBeGreaterThanOrEqual(0);
expect(values[1][0]).toBeLessThanOrEqual(1);
Мы не сверяемся с какимто конкретным результатом предсказания, ведь они мо
гут меняться в зависимости от случайных начальных значений весовых коэффици
ентов или возможных будущих модификаций архитектуры модели. Мы проверяем
просто, что получили предсказание и его значение входит в ожидаемый диапазон,
в данном случае от 0 до 1.
Главный урок, который можно из этого извлечь: модель всегда должна успешно
проходить данный тест, вне зависимости от изменения внутренней архитектуры
модели, главное, чтобы не менялся входной/выходной API. Если же тест не прой
ден, значит, в модели есть проблемы. Это легкие и быстрые тесты, обеспечивающие
сильную уверенность в правильности API, подходящие для присоединения к любым
распространенным точкам подключения тестов.
12.1.2. Тестирование с помощью «золотых значений»
В предыдущем разделе мы говорили о модульном тестировании, для которого не тре
буется контроля порогового значения метрики или устойчивости/сходимости обуче
ния. Рассмотрим теперь виды тестирования полностью обученных моделей, начиная