P(solve) и зона ближайшего развития
Имея для каждого микро-навыка, мы можем предсказать, с какой вероятностью ученик решит конкретную задачу прямо сейчас — и подобрать ту, что ему сейчас в самый раз.
Для одного навыка задачи:
Это «знает И не оплошает» плюс «не знает, но угадает».
Численно:
| 0.0 | 0.20 |
| 0.2 | 0.34 |
| 0.5 | 0.55 |
| 0.7 | 0.69 |
| 0.9 | 0.83 |
| 1.0 | 0.90 |
То есть P(solve) всегда между и —
расчёт никогда не опускается до 0 (всегда есть шанс угадать) и не
поднимается до 1 (всегда есть шанс ошибиться).
Что такое ZPD (зона ближайшего развития)
Заголовок раздела «Что такое ZPD (зона ближайшего развития)»Лев Выготский, советский психолог, в 1930-х сформулировал ключевую идею для всей педагогики:
Ученик растёт быстрее всего на задачах, которые немного выше его текущего уровня — не на тех, что уже умеет (скучно, нет роста), и не на тех, что слишком далеки (фрустрация, бросит).
Это и есть Zone of Proximal Development (ZPD).
Численно: «немного выше» в исследованиях обычно соответствует — задача, где ученик примерно в 70% случаев справляется. Не слишком близко к гарантированному успеху, не слишком далеко.
Применение в селекторе
Заголовок раздела «Применение в селекторе»Алгоритм выбора задачи:
- Для каждой задачи в базе — посчитать ученика.
- Найти ту, у которой минимально.
- Эту задачу и предложить.
В коде это делается через гауссиану — функция «близости к цели»:
// Closeness to target — Gaussian-ish, peaks at target=0.7 const closeness = Math.exp(-Math.pow(pSolveJoint - target, 2) / 0.03);Чем ближе к 0.7, тем выше closeness; пик ровно в 0.7.
closeness 1.0 ┤ ● 0.8 ┤ ● ● ● 0.6 ┤ ● ● 0.4 ┤ ● ● 0.2 ┤ ● ● 0.0 ┤●● ●● 0.0 0.3 0.7 0.9 1.0 P(solve)Почему именно гауссиана, а не «модуль разности»
Заголовок раздела «Почему именно гауссиана, а не «модуль разности»»Гауссиана:
- симметрична вокруг 0.7;
- быстро штрафует задачи, далёкие от цели;
- гладкая — нет острых углов, что даёт стабильное поведение селектора.
Параметр 0.03 в знаменателе — это «ширина» допуска:
- ⇒ задачи в диапазоне имеют closeness > 0.5;
- — слишком жёстко: «строго 0.7 ± 0.05»;
- — слишком мягко: «всё, что между 0.4 и 1.0, одинаково хорошо».
Это число можно подгонять, но 0.03 даёт хороший разброс на практике.
А что, если ZPD занят слабым навыком
Заголовок раздела «А что, если ZPD занят слабым навыком»Учительский кейс: у Ивана арифметика на 0.85, скобки на 0.40. Какую задачу дать?
Если просто искать «» — мы можем случайно выбрать задачу на арифметику (которая ему относительно сложна по причине комбинации с другими микро-навыками) и так и не коснуться скобок.
Поэтому селектор добавляет rare-skill bonus:
// Rarity bonus: how many of this task's skills are below 0.4? const undertrained = task.microskills.filter( (s) => (state.mastery[s] ?? params.pInit) < 0.4 ).length; const rarity = undertrained / task.microskills.length;
const score = closeness + rareBonus * rarity;Перевод: если у задачи большая доля «недотренированных» навыков (те, у которых ), мы её слегка «приподнимаем» в рейтинге. Это исследовательский компонент — модель не зависает в зоне комфорта.
Поиграй: ZPD-кривая
Заголовок раздела «Поиграй: ZPD-кривая»Двигай target и σ². Видно, как меняется «окно» ZPD: уже σ² — острее пик, селектор станет педантичнее по отношению к target.
closeness = exp(−(p−target)²/σ²). Выше у пика, быстро падает к краям. Чем меньше σ², тем уже «ZPD-окно».
Что в итоге выбирает селектор
Заголовок раздела «Что в итоге выбирает селектор»Возвращаясь к Ивану после 6 задач (см. предыдущую главу):
- для скобок.
- задачи только на скобки = .
Эта задача слишком сложна — closeness ≈ 0.0, селектор её не выберет. Лучше:
- задача с двумя навыками (скобки + знакомая арифметика);
- так — ближе к ZPD;
- модель тренирует слабое место без полной фрустрации.