К книге
Психометрика в EdTech. Первые шаги. Инструменты для методистов, аналитиков, исследователей и продакт-менеджеров в образованииГлава 4. Базовые (психо)метрики контента
44%
Глава 4. Базовые (психо)метрики контента
8

Для того чтобы обрисовать современное представление о психометрическом моделировании, обратимся к метафоре. Представьте двух атлетов. Оба стараются изо всех сил, чтобы добиться желаемого результата. Это значит, что на результат оказывают влияние оба одновременно. Однако в результате поединка один одержит победу, а второй проиграет. Но кто из двух? Более сильный и ловкий, не так ли? Чтобы прогнозировать результат поединка, мы изучаем характеристику каждого атлета, статистику их побед и поражений, динамику массы тела и прошлых травм, отмечаем любимые приемы и слабые места, смену тренеров и команд, анализируем их предыдущие поединки, мысленно сравниваем друг с другом. А чтобы объяснить результаты текущего поединка, обращаем внимание на их взаимодействие, на условия поединка: кто оказался в новом для себя климате, а у кого произошла смена часовых поясов.

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

В этой главе мы познакомимся с характеристиками задач в узком смысле и учебного контента – в широком. И разберем несколько метрик заданий по принципу от простого к сложному.

Начиная с этой главы, я буду приводить примеры кода для расчетов метрик на языке R. Поскольку части книги, включающие вычислительный код, рассчитаны на начинающих EdTech-аналитиков или методистов с базовым знанием языков программирования, объяснения будут подробно аннотированы.

Доля верных ответов при одной попытке

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

Самый простой способ – рассчитать долю верных ответов. Для этого определяем долю верных ответов на это задание относительно общего количества ответов на него. Или, другими словами, вычисляем долю студентов, которые справились с этим заданием, от числа всех студентов, приступивших к его решению. Этот способ пришел из классической психометрической теории (или классической теории тестирования). Доля верных ответов будет иметь границы от 0 до 1, где 0 означает, что с заданием не справился никто из студентов, и 1 – что с задачей справились все студенты. Как было отмечено, доля верных ответов часто интерпретируется как трудность задания. Но важно обратить внимание, что высокие значения соответствуют простым задачам, то есть чем выше доля верных ответов, тем легче задание.

Рассчитаем долю верных ответов на реальном примере. У нас есть датасет (скачайте этот файл под названием book_dataset_1.tsv по ссылке clck.ru/3EivRg и поместите в рабочую директорию R). Он содержит несколько переменных: student_id, course_id, topic_id, lesson_id, task_id, is_correct, но для расчета доли верных ответов в этом простейшем случае нужны только три: student_id, task_id и is_correct. Первая представляет анонимизированный идентификатор студента, вторая – идентификатор задания, а третья – маркировку ответа студента на задание, где 1 – ответ верный и 0 – ответ неверный. У студентов из этого примера была только одна попытка решения, поэтому в датасете только одна пара «студент – задание» с соответствующей этой паре маркировкой ответа.

Начнем с того, что подгрузим этот датасет с помощью следующей строчки кода:

df <– read.table("book_dataset_1.tsv", header = TRUE, quote = "", sep = "\t")

Проще всего познакомиться со структурой и содержанием датасета с помощью команды которая всегда выводит первые шесть строк данных – head(as.data.frame(df)). Выполнив ее, вы получите следующее (скрин. 1):

Скриншот 1

Мы видим идентификатор студента, идентификаторы курса, темы, урока и задания и маркировку ответа на задание. Мы понимаем, что студент с идентификатором d8800e0cba2cf3dce798f3dd4aec441f справился со вторым, четвертым, пятым и шестым заданиями и не справился с первым и вторым. Все шесть заданий относятся к курсу с идентификатором 50a9e052, при этом первые пять – к теме с идентификатором 9f44ae60, а шестое – к теме с идентификатором 48b34158. Первые три задания относятся к уроку 3ada2f9f, четвертое и пятое – к уроку d59bafc3 и шестое – к уроку 09544a3d. В этом продукте задания вложены в уроки, уроки в темы, темы в курсы, а курс составляет отдельный продукт (в этом датасете он один).

Далее нам нужно установить и загрузить пакет dplyr. Сделать это можно последовательно с помощью команд install.packages("dplyr") и library(dplyr). Первую нужно использовать один раз, так как она скачивает необходимый пакет и устанавливает его на ваш компьютер. А вторую команду важно задействовать каждый раз перед началом рабочей сессии (открыли R, воспользовались командой и далее применяем код из этой книги).

Итак, для того чтобы рассчитать долю верных ответов, необходимо воспользоваться следующим кодом:

Разберем этот код последовательно. Сначала данные df группируются по заданиям с помощью команды group_by(task_id). Условно все ответы на отдельное задание раскладываются по корзинкам, каждая из которых соответствует одному заданию и маркируется его идентификатором. Затем в каждой корзинке считаем количество верных ответов (n_Correct) с помощью команды n_Correct = sum(is_correct == 1) и количество неверных ответов (n_Incorrect) с помощью команды n_Incorrect = sum(is_correct == 0). После мы можем рассчитать долю верных ответов в каждой корзинке, то есть для каждого задания, с помощью команды p_i = round (n_Correct / (n_Correct + n_Incorrect), 2). Вы видите, что мы вычисляем долю студентов, справившихся с заданием верно (n_Correct), от общего числа студентов, решавших это задание и, соответственно, давших верный и неверный ответы (n_Correct + n_Incorrect). В результате получаем значение доли верных ответов (p_i) в каждой корзинке. Эти значения помещаются в таблицу с аналогичным названием (p_i), где p – proportion (proportion correct, доля верных ответов), а i – это индекс, которым обычно обозначают задания (от слова items). В таблице имеются два столбца: первый с идентификатором задания task_id, а второй – с соответствующей ему долей верных ответов p_i.

Рассмотрим иллюстрационную (а не рассчитанную на датасете) таблицу (табл. 9).

Таблица 9. Доли верных ответов для четырех заданий

Мы видим, что значения доли верных ответов варьируются. С первым заданием с идентификатором t001 справились 12 % студентов, со вторым – 97 %, с третьим и четвертым заданиями – 35 и 81 % соответственно. Как интерпретировать эти значения?

С точки зрения учебных заданий оптимальными считаются те, доля верных решений в которых составляет 75–95 %. Наша практика показывает, что оптимальных учебных результатов (например, получают более высокие оценки за проектные работы и с наибольшей вероятностью завершают обучение) добиваются те студенты, у которых доля успехов в учебном процессе составляет 75–95 %. Такую долю успеха формируют учебные задания с соответствующей долей верных решений (при условии только одной попытки на их решение). Задания с долей верных решений в интервале от 50 до 75 % считаются субоптимальными; с долей верных решений ниже 50 % – фрустрирующими (или фрустрирующе трудными), а с долей верных решений выше 95 % – скучными.

Эти градации я подсчитывал и валидировал во время работы в международном Практикуме (ныне TripleTen), поэтому их названия в оригинале были сформулированы на английском языке: frustrating (фрустрирующие, < 50 %), suboptimal (субоптимальные, от 50 до 75 %), optimal (оптимальные, от 75 до 95 %) и boring (скучные, выше 95 %). Отмечу, что в одном из современных исследований, опубликованном во влиятельном журнале Nature[12] в 2019 году, ученые из США эмпирически рассчитали оптимальную долю успехов и провалов в обучении: 85/15. Как видно, эта оптимальная категория находится ровно в середине нашей оптимальной категории (75–95 %). Для удобства представим референсные значения в виде таблицы (табл. 10).

Таблица 10. Референсные интервалы с интерпретациями для доли верных ответов

Если же рассуждать не об учебных, а о проверочных заданиях или экзаменах, то существуют конвенциональные границы, предложенные в классической психометрической теории (или классической теории тестирования): задания с трудностью менее 0,1 считаются очень трудными (их верно решило менее 10 % выборки); с трудностью от 0,1 до 0,2 – просто трудными; диапазон от 0,2 до 0,8 наиболее продуктивен для измерений с целью подведения итогов или отбора лучших; задания с трудностью выше 0,8 оцениваются как легкие, а выше 0,9 – очень легкие.

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

Мини-практикум. С помощью команды head(as.data.frame(p_i)) выведите первые шесть рассчитанных значений доли верных ответов. К каким категориям с точки зрения доли верных ответов относится каждое из этих шести заданий?

Правильный ответ: 0,90 (оптимальное), 0,55 (субоптимальное), 0,84 (оптимальное), 1,00 (скучное), 0,77 (оптимальное), 1,00 (скучное).

Доля верных ответов при условии нескольких попыток

А теперь усложним рассмотренный случай и представим, что у студентов есть возможность совершить несколько попыток. В этом случае в датасете каждая строка будет показывать результат одной попытки решения задания. В предыдущей главе мы говорили о том, что если студенту доступны несколько попыток для решения задания, то обязательным условием является добавление переменной timestamp (то есть сведений о времени выполнения действия; в приведенном примере эта переменная называется timestamp).

Соответственно, минимально достаточная структура датасета должна быть представлена уже четырьмя столбцами: student_id, task_id, is_correct и timestamp. В нашем втором датасете эти переменные есть (скачайте соответствующий датасет под названием book_dataset_2a.tsv по ссылке clck.ru/3Eivwc и поместите в рабочую директорию R), но кроме них в датасете содержатся еще и переменные course_id, topic_id и lesson_id, показывающие иерархическую вложенность содержания.

Доля верных ответов в первой попытке

Есть несколько способов выразить свойство задания (условно – его трудность). Один из них – рассчитать долю верных ответов по первой попытке. Давайте сделаем это. Сначала подгрузим данные с помощью команды df <– read.table("book_dataset_2a.tsv", header = TRUE, quote = "", sep = "\t"). Выведем первые шесть строк этого датасета с помощью уже знакомой нам команды head(as.data.frame(df)) и убедимся в наличии необходимых переменных (student_id, task_id, is_correct и timestamp, скрин. 2).

Скриншот 2

Однако для расчетов недостаточно иметь метку времени (timestamp). Необходима отдельная переменная, которая содержит номер попытки, и ее нужно вычислить. Воспользуемся следующим кодом:

В этом коде данные группируются по студентам и заданиям: команда group_by(student_id, task_id) формирует корзинки, в каждой из которых один студент и одно задание. Если студент совершил несколько попыток, в соответствующей корзинке окажутся несколько (дублирующихся) пар для этого студента и этого задания со своей индивидуальной меткой времени. Затем с помощью команды arrange(timestamp) каждая корзинка упорядочивается по метке времени от самых ранних к самым поздним решениям. Наконец, команда mutate(attempt = row_number()) последовательно нумерует упорядоченные строки в каждой корзинке и называет полученную переменную attempt. Эта нумерация отражает попытки, последовательно предпринятые студентом при решении каждого задания. В результате, снова воспользовавшись командой head(as.data.frame(df)), мы теперь увидим в данных не четыре, а пять столбцов, и последний – новая переменная attempt (скрин. 3).

Скриншот 3

Далее рассчитаем собственно долю верных решений по первой попытке с помощью следующего кода:

Этот код вам уже знаком. Его единственное отличие от кода для расчета доли верных ответов в заданиях с одной попыткой, что мы рассматривали ранее, заключается в добавленной команде filter(attempt == 1). Она отбирает только первые попытки, и далее расчет не меняется. Результирующая переменная и сама таблица будут называться p_i1, где индекс 1 обозначает первую попытку.

Интерпретировать полученные значения можно опираясь на границы, приведенные в таблице 10. Так, каждое значение будет отнесено к одной из четырех категорий: скучное, оптимальное, субоптимальное или фрустрирующее. Пожалуй, достоинство этого подхода состоит в том, что мы можем интерпретировать результаты заданий как с одной попыткой, так и с несколькими, используя одни референсные значения (потому что в заданиях с несколькими попытками мы используем только первую для расчетов). Однако существенным ограничением этого подхода является то, что мы теряем всю информацию о свойстве задания, которая находится за пределами первой попытки.

Мини-практикум. Какова доля верных решений с первой попытки в заданиях с идентификаторами 43f464b92996aa28, 5f596b6d2bf8eb9b, 67e3272b9bf1e589 и 92fecefdabe81f5c. Как интерпретировать эти значения?

Правильный ответ: 0,98 (скучное), 0,26 (фрустрирующее), 0,87 (оптимальное), 0,54 (субоптимальное)[13].

Транзитивная доля верных ответов

Для того чтобы выразить свойство задания (его трудность), существует способ, который отчасти снимает указанное ограничение: нужно подсчитать долю верных ответов для первых, например трех, попыток. В случае первой попытки считаем долю студентов, справившихся с задачей верно относительно тех, кто ее решал. Для второй попытки нужно обеспечить общее количество студентов, равное тому, что было при первой попытке. Как это сделать? Нужно количество студентов, решивших задачу с первой попытки (соответственно, они не воспользовались второй попыткой), сложить с количеством студентов, которые справились с задачей со второй попытки, и поделить на число, которое только что получилось, плюс количество студентов, которые не справились с задачей со второй попытки. Такой подход я назвал транзитивной долей верных ответов. Мы просто переносим долю справившихся корректно из попытки в попытку, чтобы сохранить общее количество студентов в каждой попытке. Это дает возможность сравнивать значения между попытками.

В предыдущем пункте этой главы мы уже рассчитали переменную попытки (attempt) на основании переменной метки времени (timestamp); она уже есть в наших данных (df). Но на новых датасетах эту процедуру необходимо повторить, так как для дальнейшего расчета нам нужна переменная attempt.

Так мы можем приступить к расчету транзитивной доли верных ответов по отдельным попыткам. Для этого понадобится код:

Разберемся, что делает этот код. Сначала с помощью команды filter(attempt <= 3) отбираем первые три попытки. Моя практика показывает, что первые три попытки обычно наиболее информативны для расчета транзитивной доли верных ответов (можно брать и большее число попыток, например пять, – все зависит от специфики вашего продукта). Затем с помощью команды group_by(task_id, attempt) группируем данные по большим корзинкам, объединяющим задание, и внутри каждой большой корзинки собираем три маленькие, каждая из которых представляет собой первую, вторую и третью попытки. Затем в каждой маленькой корзинке рассчитываем количество верных и неверных ответов с помощью команд n_Correct = sum(is_correct == 1) и n_Incorrect = sum(is_correct == 0) соответственно. Затем внутри каждой большой корзинки, соответствующей заданию (group_by(task_id)), определяем транзитивную корректность каждой попытки, применяя команду cum_n_Correct = cumsum(n_Correct). По сути, для первой попытки это просто значение количества верных ответов; для второй мы суммируем количество верных ответов в первой и во второй попытках, вместе взятых, а для третьей суммируем количество верных ответов в первой, второй и третьей попытках. В итоге с помощью команды p_ia = round(cum_n_Correct / (cum_n_Correct + n_Incorrect), 2) рассчитываем долю верных ответов с учетом транзитивности для каждой попытки каждого задания. В результате применения получаем таблицу p_ia (чтобы познакомиться с первыми шестью строками этой таблицы, воспользуйтесь командой head(as.data.frame(p_ia))), состоящую из трех столбцов: task_id, attempt и p_ia. В ней мы видим значение доли верных ответов, соответствующее заданию task_id и попытке attempt. В названии таблицы и интересующей нас переменной (p_ia) добавленная буква a обозначает попытку (attempt), чтобы различить индексы для доли верных ответов и транзитивной доли верных ответов по попыткам.

Однако такое отображение (в длинном формате, в котором для интерпретации требуется сопоставлять задание и номер попытки) может показаться пользователю не очень удобным для сравнения доли верных ответов внутри задания. Поэтому перегруппируем результаты в более удобное представление – широкий формат, где каждая строка соответствует отдельному заданию, а в столбцах приводятся номера попыток. Для этого сначала загрузим дополнительную библиотеку (это единственный случай, когда нам нужна дополнительная библиотека), последовательно применив команды install.packages("tidyr") и library(tidyr), а затем воспользуемся командой

В итоге получаем таблицу в удобном для работы виде, где p_i1, p_i2 и p_i3 – значения транзитивной доли верных попыток соответственно для первой, второй и третьей попыток. Перед тем как вы увидите результаты расчетов примера, рассмотрим иллюстративную (а не рассчитанную на датасете) таблицу (табл. 11).

Таблица 11. Транзитивные доли верных ответов пяти заданий для первых трех попыток

Задание с идентификатором t005 может считаться скучным: с первой попытки с ним справляется 97 % студентов. Второе задание (t006) является оптимальным по первой попытке, так как доля верных решений составляет 76 % и студентам не требуется больше двух попыток, чтобы с ним справиться. Третье задание (t007) относится к категории фрустрирующих с долей верных решений с первой попытки 42 %, но мы видим существенный прирост во второй и третьей попытках. Четвертое задание (t008) субоптимальное по первой попытке. Здесь важно отметить, что у некоторых попыток вместо доли верных ответов располагается обозначение NA (not available). Это происходит в трех случаях: либо студенты не пользовались соответствующей попыткой, либо в задании было ограничение на попытки, либо студенты переходили к следующему заданию, не добившись верного решения по текущему. Пятое задание (t009) фрустрирующее (доля верных решений с первой попытки равна 37 %), и, кроме того, от попытки к попытке происходит незначительный прирост в доле верных ответов. Если первые попытки мы можем интерпретировать по уже знакомой нам шкале, то как интерпретировать значения прироста доли верных ответов от попытки к попытке? Моя практика показывает, что задание, которое является фрустрирующим или субоптимальным, можно считать сбалансированным с точки зрения прироста, если прирост доли верных ответов от первой ко второй попытке составляет больше трети от предыдущей попытки. Например, если с первой попытки с заданием справились 45 % (соответственно условная треть составляет 15 %) и со второй – более 60 % студентов, такое задание можно считать сбалансированным. Настораживать должны фрустрирующие или субоптимальные задания, в которых прирост крайне мал, что может свидетельствовать о низком качестве задания (или обратной связи, встроенной в него). Такие задания негативно сказываются на учебном опыте студентов.

Таким образом, третье задание можно считать хотя и фрустрирующим при первом прохождении, но сбалансированным с точки зрения прироста от попытки к попытке. Тогда как пятое задание – низкого качества: оно и фрустрирующее по первой попытке, и проблемное по приросту от попытки к попытке.

Мини-практикум. Каковы транзитивные доли верных ответов для первых шести заданий в таблице wide_p_ia? В каком задании были востребованы все три попытки? Оно является фрустрирующе трудным с первой попытки, но сбалансированным с точки зрения прироста от первой ко второй попытке? Какое задание является субоптимальным, но при этом сбалансированным с точки зрения прироста? В каких из шести заданий студенты не пользовались третьей попыткой?

Правильный ответ: в первом задании транзитивные доли верных ответов составляют 0,91; 1,00; NA; во втором – 0,89; 0,91; 0,94; в третьем – 0,39; 1,00; NA; в четвертом – 0,47; 0,69; 0,84; в пятом – 0,58; 0,96; 0,98 и в шестом – 0,95; 1,00; NA. В четвертом задании были востребованы все три попытки, оно является фрустрирующе трудным с первой попытки, но сбалансированным с точки зрения прироста от первой ко второй попытке. Пятое задание – субоптимальное, но при этом сбалансированное с точки зрения прироста. В первом, третьем и шестом заданиях студенты не пользовались третьей попыткой[14].

Квартили попыток

Для заданий с несколькими попытками решений существует альтернативная метрика – расчет квартилей попыток. Для расчета нужно начать с определения эффективной попытки.

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

Для вычисления эффективной попытки продолжим работать с датасетом book_dataset_2a.tsv и применим следующий код:

В этом коде в знакомых нам корзинках «студент – задание» мы сначала упорядочиваем попытки по времени, используя команду arrange(timestamp), а затем с помощью команды filter(is_correct == 1) отбираем только верные ответы (ведь нас не интересуют попытки, не давшие верного решения) и после, используя команду slice(1), берем ту самую эффективную попытку (первую по порядку), где студент дал верный ответ.

Далее на основе полученных данных нужно распределить все эффективные попытки по корзинкам, соответствующим заданиям. Затем необходимо в каждой корзинке упорядочить эффективные попытки по возрастающей; далее разделить студентов на четыре равные группы (квартили) и взять значения числа попыток, находящиеся на границах этих групп, включая наименьшее и наибольшее. Всего получится пять значений. Например, если мы увидим 1, 3, 5, 6 и 12, это значит, что минимальное и максимальное количество попыток для решения этой задачи было 1 и 12. Четверть студентов решили задачу с 1–3 попыток, еще четверть – с 3–5, еще четверть – с 5–6, и, наконец, еще четверть – с 6–12. Мы также видим, что половина студентов, находящаяся в середине (второй и третий квартили вместе) решили задачу с 3–6 попыток. А квартиль студентов послабее и посильнее справились с задачкой соответственно с 6 попыток и более и 3 попыток и менее. При этом самый слабый и самый сильный студенты потратили на решение задачи соответственно 12 попыток и 1. Все это можно определить с помощью следующего кода:

В результате получим таблицу с названием qa_i, где qa – квартиль попытки (attempt quartile), а i – задание. Таблица содержит идентификатор задания (task_id), минимальное количество попыток, потребовавшихся на решение задания студентами (Min), границы первого, второго, и третьего квартилей (Q1, Q2, Q3 соответственно) и максимальное количество попыток, потребовавшихся на решение задания студентами (Max).

Интерпретация этой метрики проводится совместно с методистами. Насторожить должны задания, которые все решают с одной попытки (если только это задание не имеет мотивирующего назначения и специально создано максимально простым), и задания, которые существенная часть аудитории (например, половина) решает только с большого числа попыток: они могут демотивировать; возможно, для таких заданий необходимы помогающие механики или корректировка контента.

Мини-практикум: Каковы квартили попыток для задания с идентификатором d2028fff833be67a? Интерпретируйте эти значения.

Правильный ответ: 1, 2, 3, 6, и 23. Минимальное и максимальное число попыток – 1 и 23 соответственно. Первая четверть студентов решает задания с 2 и менее попыток, вторая четверть – с 2–3 попыток, третья четверть – с 3–6, четвертой четверти требуется 6 и более попыток[15].

Средняя попытка

Представлять количество попыток можно средним значением. Оно рассчитывается также для эффективных попыток (код для определения показан выше). Наши данные (df) уже содержат только эффективные попытки, что также сделано выше. Расчет среднего значения для эффективных попыток производится с помощью кода

Этот код сначала группирует эффективные попытки по корзинкам, соответствующим отдельным заданиям (group_by(task_id)), а затем рассчитывает среднее значение в каждой корзинке (avga_i = round(mean(attempt), 0)). Индекс avga_i представляет собой avga как сокращение от среднего (average), кроме того, a – попытка (attempt); i – индекс, принятый для заданий.

В результате получается таблица, состоящая из двух столбцов, в которой каждому заданию (task_id) соответствует среднее значение попыток (avga_i), затраченных студентами для поиска верного решения.

Однако при явной компактности такая визуализация имеет и недостатки: мы не получаем общего представления о распределении попыток решения задания во всей выборке студентов, что возможно при использовании квартилей. Кроме того, важно помнить, что средние значения очень чувствительны к экстремальным значениям. Например, если к выборке из 99 студентов, которые решали задание с 1–2 попыток, присоединится студент, который решил его с 30-й попытки, среднее будет искажено. Эта проблема особенно актуальна для небольших групп (например, школьного класса).

Иными словами, метрика среднего расчета количества попыток лучше, чем отсутствие метрики учета попыток, но менее информативна, чем поквартильный подход.

Заметьте, что и транзитивная доля верных ответов, и квартили попыток, и среднее значение по попыткам – это различные способы отразить свойство задания, для решения которого студент может прибегнуть к попыткам. Всего одна дополнительная механика минимального учебного действия – попытка – существенно увеличивает количество необходимых расчетов, чтобы мы могли сформировать впечатление о трудности.

Мини-практикум. Каково среднее значение эффективных попыток для задания dcc90c3f53d93c00? Что мы можем сказать об этом задании, если узнаем, что среднее значение эффективных попыток по продукту в целом равно 2? Найдите для этого задания распределение по квартилям эффективных попыток и транзитивную долю верных ответов. Что вы можете сказать о задании?

Правильный ответ: среднее значение равно 7[16]. Это задание существенно труднее среднего по продукту. Квартили попыток для этого задания составляют 1, 2, 5, 10 и 20[17]. Мы видим, что половина студентов затрачивает 5 и более попыток на решение этого задания, а максимальное значение попыток равно 20. Транзитивные доли верных ответов для первых трех попыток равны 0,24; 0,35; 0,41[18]. Это фрустрирующее задание по первым трем попыткам. При этом прирост в доле верных решений от первой ко второй попытке можно считать сбалансированным (составляет больше трети), тогда как от второй попытки к третьей прирост недостаточен (составляет меньше трети). В целом можно считать, что это задание является проблемным ввиду его высокой трудности.

Нагрузка помогающими механиками

Теперь еще более усложним наш модельный кейс и представим, что студентам доступна (одна) подсказка как помогающая механика. В этом случае полезно подсчитать еще одну (психо)метрику на стороне контента – нагрузку подсказками, или нагрузку помогающими механиками. Для этого каждую пару студент – задача (вне зависимости от количества попыток) помечаем дополнительной переменной, отражающей факт использования подсказки студентом при решении задания (1 – подсказка использовалась, 0 – подсказка не использовалась). Данные при этом должны включать идентификатор студента (student_id), идентификатор задания (task_id), результат попытки (is_correct), переменную об использовании студентом подсказки для решения этого задания (hint) и метку времени (timestamp). Этот датасет повторяет тот, с которым мы работали, исследуя попытки, но в него добавлена переменная hint (сами подсказки изначально были доступны в продукте, но, чтобы не отвлекать ваше внимание от работы с попытками, эту переменную временно удалили из датасета).

Важно отметить, что нагрузка подсказками считается также для эффективных попыток. С кодом для расчета переменной попытки и последующего отбора эффективных попыток вы уже знакомы. Поэтому, скачав файл с данными book_dataset_2b.tsv по ссылке clck.ru/3Eiw4A, можете самостоятельно произвести эти операции[19].

Дальнейший расчет в этом пункте опирается на уже отобранные эффективные попытки.

Итак, мы определили эффективные попытки. Далее нагрузка задания подсказками рассчитывается как доля студентов, которые использовали подсказку при решении задания среди тех, кто ее использовал и не использовал. При этом в расчет мы берем только тех, кто решил задание верно (так как при определении эффективной попытки используем первую успешную попытку). Полученное значение нагрузки подсказками будет находиться в интервале (включительно) от 0 (когда никто из студентов не прибегал к подсказке при решении этого задания) до 1 (когда все студенты использовали подсказку при решении этого задания).

Метрику можно вычислить с помощью следующего кода:

В этом коде данные группируются по корзинкам, каждая из которых соответствует заданию (group_by(task_id)), а затем с помощью команды h_i = round(mean(hint), 2) в каждой корзинке рассчитывается среднее по переменной hint.

В результате получается таблица под названием h_i (h – подсказка (hint), i – задание (item)), состоящая из двух столбцов: первый с идентификатором задания, а второй с соответствующим значением нагрузки подсказками. Рассмотрим иллюстрационную (а не рассчитанную на датасете) таблицу (табл. 12).

Таблица 12. Нагрузка подсказками для трех заданий

В первом задании (t010) нагрузка подсказками равна 0. Это значит, что ни один из студентов не пользовался подсказкой при его решении. Во втором задании (t011) нагрузка подсказками равна 0,53, что говорит о том, что немногим больше половины верных решений этого задания получены с использованием подсказки. Наконец, в третьем задании (t012) все студенты воспользовались подсказкой.

Эта метрика очень полезна в оптимизации задач. Например, если мы видим для каких-то задач значения 1, означающие, что ни один студент не справился с задачей без использования подсказки, значит, задание сформулировано недостаточно для выполнения без подсказки. Следовательно, стоит рассмотреть вариант перенесения подсказки в тело самого задания, а саму подсказку заменить на какую-то другую (работающую именно как подсказка).

В случае если подсказок в задании больше одной, нагрузку можно считать аналогичным образом для каждой помогающей механики. Но тогда полезно посчитать еще одну дополнительную метрику – среднюю нагрузку помогающими механиками. Для этого нужно сложить все нагрузки и разделить полученное число на количество доступных помогающих механик. В результате увидим, какими помогающими механиками и в каких долях пользуются студенты. А также поймем, насколько в среднем помогающие механики востребованы при решении каждого задания. Мой опыт подсказывает, что оптимальным будет равномерное распределение нагрузки по разным помогающим механикам, а среднее значение не должно быть очень большим (не должно быть близким к 1).

Мини-практикум: в предыдущем пункте мы подробно разбирали задание dcc90c3f53d93c00. Какова его нагрузка подсказками? Что вы можете сказать об этом задании, учитывая, что средняя нагрузка подсказками в продукте равна 0,18?

Правильный ответ: нагрузка подсказками для этого задания равна 0,64. Это значит, что 64 % студентов, работая с ним, используют подсказку. Такое значение более чем в три раза выше средней нагрузки подсказками по продукту. Мы получаем еще одно подтверждение тому, что задание является очень, очень трудным[20].

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

Как видно, чем более сложным становится взаимодействие студента с заданием и чем больше элементов этого взаимодействия (потенциально) оказывают влияние на его результаты, тем больше становится метрик. При этом все метрики с разных сторон выражают свойство задания – его трудность. А чем больше метрик, тем больше требуется внимания и усилий, чтобы их проанализировать, интерпретировать и принять соответствующие решения. И даже если эти метрики имеют единую шкалу с понятной интерпретацией, это довольно громоздко в использовании. Я часто в своей практике встречал запрос от продактов, методистов и других коллег о разработке одной метрики. И у меня нашлось решение. Но об этом позднее.

А пока познакомимся с базовыми (психо)метриками студентов.

Предыдущая главаГлава 8 из 18Следующая глава