27 мая 2014 г.

Байесовы сети в R: пакет bnlearn

Описание модели

На протяжении семестра каждый студент проходит две текущих аттестации (получая от 0 до 45 баллов на каждой) и одну итоговую (получая от 1 до 5 баллов). Рассмотрим взаимодействие с байесовой сетью на примере анализа этих результатов.

Сведения о результатах промежуточной и итоговой аттестации студентов представим в виде объекта data.frame:

> head(rating)
        subj type id rate
1 Теория игр    1  1   35
2 Теория игр    1  2   25
3 Теория игр    1  3   35
4 Теория игр    1  4   25
5 Теория игр    1  5   10
6 Теория игр    1  6   35

Где:
subj — наименование дисциплины;
type — вид аттестации (1-я, 2-я и 3-я, итоговая);
id — идентификатор студента;
rate — соответствующая оценка.

Для формирования байесовой сети необходимо сформировать из этих данных набор переменных. В зависимости от целей последующего анализа, эти переменные могут содержать:

  • вектора оценок студентов по паросочетаниям предмет — номер аттестации;
  • вектора оценок по предметам в паросочетаниях студент — номер аттестации.

В первом случае байесова сеть накапливает знания о связях между результатами аттестации в рамках одного предмета, во втором — о связях между результатами аттестации одного студента по всем предметам.

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

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

Обучение байесовой сети

Обратите внимание, представление оценок студентов в интервальной шкале методически ошибочно, пример ниже иллюстрирует исключительно работу с пакетом bnlearn и не дает возможности делать содержательные выводы.

Сформируем связи переменных в байесовой сети на основании экспертных знаний:

> net <- model2network("[A1][A2|A1][A3|A1:A2]")

Структура связей этой сети изображена на рисунке.


Структура зависимостей переменных в байесовой сети.

Сформируем набор переменных с результатами аттестаций по дисциплине «Теория игр»:

> a1 <- rating$rate[rating$subj == "Теория игр" & rating$type == 1]
> a2 <- rating$rate[rating$subj == "Теория игр" & rating$type == 2]
> a3 <- rating$rate[rating$subj == "Теория игр" & rating$type == 3]

В обучении байесовой сети пакет bnlearn может использовать объект типа data.frame, содержащий таблицу переменных типа num. Тип переменных a1, a2 и a3int, что необходимо учитывать при обучении сети:

> str(a1)
 int [1:8] 35 25 35 25 10 35 25 30
> str(a2)
 int [1:8] 35 25 35 25 20 25 25 25
> str(a3)
 int [1:8] 5 3 5 3 3 5 4 4
> rate <- data.frame(A1 = as.numeric(a1), A2 = as.numeric(a2), A3 = as.numeric(a3))
> net.rate <- bn.fit(net, rate)

Если эту особенность проигнорировать, произойдет следующее:

> rate <- data.frame(A1 = a1, A2 = a2, A3 = a3)
> net.rate <- bn.fit(net, rate)
Ошибка в check.data(data) : 
  variables must be either all real numbers or all factors.

Объект net.rate хранит обученную байесову сеть. Используя его, мы можем получать ответы на вероятностные вопросы. Естественно, эти ответы зависят от обучающей выборки.

Прогнозирование на основе обученной байесовой сети

Ниже приведены примеры построения прогнозов на основе байесовой сети net.rate.

  1. Какова вероятность получить положительную оценку для студента, если результаты его аттестаций по дисциплине пока неизвестны?
  2. > cpquery(net.rate, (A3 > 2.5), TRUE)
    [1] 0.9393
  3. Какова вероятность для студента получить «удовлетворительно», «хорошо» или «отлично» при тех же условиях?
  4. > cpquery(net.rate, (A3 > 2.5 & A3 < 3.5), TRUE)
    [1] 0.2479667
    > cpquery(net.rate, (A3 > 3.5 & A3 < 4.5), TRUE)
    [1] 0.3839
    > cpquery(net.rate, (A3 > 4.5), TRUE)
    [1] 0.3064333
    > 0.2479667 + 0.3839 + 0.3064333
    [1] 0.9383

    Сумма вероятностей сходится с предыдущим ответом с точностью до двух знаков после запятой. Отклонение объясняется спецификой модели расчетов (метод по умолчанию: logic sampling) — чем сложнее структура сети, тем больше может быть расхождение даже для идентичных запросов, сделанных друг за другом.

  5. Если студент получил больше 40 баллов за каждую из текущих аттестаций, каковы его шансы не получить на экзамене «отлично»?
  6. > cpquery(net.rate, (A3 < 4.5), (A1 > 40 & A2 > 40))
    [1] 0.015625
  7. Если студент получил меньше 20 баллов за каждую из текущих аттестаций, каковы его шансы получить на экзамене положительную оценку?
  8. > cpquery(net.rate, (A3 > 2.5), (A1 < 20 & A2 < 20))
    [1] 0.5664931

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

  9. А если студент получил меньше 20 баллов хотя бы за одну из текущих аттестаций?
  10. > cpquery(net.rate, (A3 > 2.5), (A1 < 20 | A2 < 20))
    [1] 0.7522488

    Шансы на положительную оценку в этом случае выше, чем в предыдущем.

Анализ причинности на основе обученной байесовой сети

Построение прогнозов — не единственный вариант использования обученной байесовой сети. Ниже приведены примеры диагностирования, построенные на ее основе.

  1. Студент получил на экзамене «неудовлетворительно». Какова вероятность того, что хотя бы на одной промежуточной аттестации он получил меньше 20 баллов?
  2. > cpquery(net.rate, (A1 < 20 | A2 < 20), (A3 > 1.5 & A3 < 2.5))
    [1] 0.8404692

  3. Тот же вопрос для студента, получившего на экзамене «хорошо».
  4. > cpquery(net.rate, (A1 < 20 | A2 < 20), (A3 > 3.5 & A3 < 4.5))
    [1] 0.1283003

  5. Студент получил на экзамене «удовлетворительно». Что вероятнее: у него есть аттестация хуже 30 баллов или лучше 30 баллов?
  6. > cpquery(net.rate, (A1 < 30 | A2 < 30), (A3 > 2.5 & A3 < 3.5))
    [1] 0.9836088
    > cpquery(net.rate, (A1 >= 30 | A2 >= 30), (A3 > 2.5 & A3 < 3.5))
    [1] 0.1065574

    Вероятность первого ответа — существенно выше.

Наконец, приведем варианты межпричинного анализа на основе байесовой сети.

  1. Результат первой аттестации студента ниже 30 баллов. Какова вероятность того, что он получит на второй аттестации результат лучше, чем на первой?
  2. > cpquery(net.rate, (A2 > A1), (A1 < 30))
    [1] 0.6594571
  3. Один студент во втором семестре учился лучше, чем в первом, другой — хуже. У кого вероятность результата второй аттестации выше 30 баллов больше?
  4. > cpquery(net.rate, (A2 > A1), (A2 > 30))
    [1] 0.3975462
    > cpquery(net.rate, (A2 < A1), (A2 > 30))
    [1] 0.6032461

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

Заключение

Нами рассмотрена работа с байесовой сетью, обученной на вещественных переменных. В случае с оценкой работы студентов лучше использовать переменные — факторы. Более того, пакет bnlearn позволяет использовать упорядоченные факторы.