Вступление
Здравствуй, Хабр! Я всегда мечтал создать идеальное приложение для обучения и запоминания информации, пытался понять как в целом работает память, насколько хорошо она может работать, от чего и как это зависит, в этой статье мы посмотрим что на данном этапе я достиг, или быть может я ничего такого и не сделал. Буду рад критике, и коль проект опенсоурс буду рад пул реквестам/предложениям.
С чего всё началось?
В 2020 году я загорелся идеей изучать языки, их так много, что аж глаза разбегаются, хочется выучить и тот и этот. Позже я конечно выбрал испанский и английский как приоритет, ещё чуть позже понял на какой уровень я их хочу - английский (B1/B2), испанский A2. И конечно же я использовал приложения для выучивания лексики и фраз. В таких приложениях довольно часто мелькают "Слабые", "Средние" и "Сильные" карточки. И вот сижу я в приложении, вроде как отвечаю на слова, уже хорошо так, а они как-то не по понятному алгоритму перемещаются между состояниями. Скорее там что-то примитивное, похожее на количество ответов и не ответов, меня не устраивала такая оценочная система. В итоге, попробовав различные приложения, основываясь на начитанности о принципах обучения и работе мозга я выловил себя на мысли: В одном приложении одно хорошо, в другом - другое, есть вещи которых нет ни в одном, и как же круто было бы собрать эти все фишки в одном месте и согласовать между собой.
Как говорится:
Критикуешь - предлагай!
А вот и предложим.
Первый прототип, предок MindVault
Первый прототип MindVault назывался GreekMemo и работал по принципу брутфорса, там уже была кое-какая слабенькая оценочная система, и количество необходимых оценок чтоб слово считалось выученным, и в целом, было это всё неплохо, однако - всё равно шляпа по сравнению с моими Напалеоновскими планами. Я ещё долго мучился с GUI интерфейсом и прочим
Кстати, GreekMemo примерно выглядел так:
import os
import random
import difflib
def check_ratio(s1, s2):
s = difflib.SequenceMatcher(None, s1, s2)
return round(s.ratio(), 2)
DELIMITER = input('Delimiter: ')
AMOUNT_PER_SESSION = int(input('Amount: '))
INPUT_FILE = input('File: ')
cards = dict()
answers_data = dict()
with open(INPUT_FILE, 'r', encoding='utf-8') as f:
for line in f.readlines():
question, answer = line.split(DELIMITER)
cards[question.strip()] = answer.strip()
questions = list(cards.keys())
random.shuffle(questions)
attemps = 0
while True:
question = random.choice(questions[:AMOUNT_PER_SESSION])
answer = input(f'{question}: ')
answer_ratio = check_ratio(cards[question], answer)
if not question in answers_data:
answers_data[question] = 0
if answer_ratio >= 0.9 and answers_data[question] > 2:
questions.remove(question)
del answers_data[question]
del cards[question]
message = 'Learned!'
elif answer_ratio >= 0.8:
answers_data[question] += 1
message = 'Right!'
else:
message = f'Wrong! ({cards[question]})'
attemps += 1
if attemps > 2:
attemps = 0
os.system('cls')
print(message)
Первое ядро MindVault, оно же CogniVersa
Полгода назад я таки поборол свою прокрастинацию, да и в принципе не помню как это было, но собрал, структурировал в своей голове всё, что хотел сделать и получилось ядро CogniVersa на языке NodeJS, хотя, от самого нода там не так много, можно считать сделано оно на JavaScript'е. Не так давно оно было удалено, а поскольку его бекапов нет показать я его не смогу, оно было похоже на нынешнее, только с некоторыми огрехами в логике, подсчётах оценки и чего-то ещё, которые потом унаследовал и сам MindVault, которые были исправлены позже.
Долгожданный релиз, всё работает, и даже почти как надо
Две недели назад был выпущен первый полноценный релиз этого чуда, но периодически возникали всякие недочёты в работе с GUI меню (я использую Swing с FlatLaf темами чтобы была поддержка Java 8+), недочёты в логике, что-то не обновляется, местами фигня интерфейс, но затем спустя несколько обновлений, переосмыслений логики и прочего я пришёл к этому:
Чем же всё-таки отличается MindVault? О его фишках и киллерфичах
Пять состояний карточек: Повторение, Слабые, Средние, Сильные, Не изученные
они расположены, кстати по их приоритету, об этом чуть позже
Система оценивания: При создании сессии, приложение просит ввести слово/фразу или что-нибудь чтобы рассчитать комфортную скорость с которой вы печатаете, это нужно для того, чтобы затем понимать долго ли вы думали над ответом или нет, то есть скорость ответа тоже входит в оценивание
В оценку скорости входит не только скорость печати, но и обдумывания, которая зависит от текущей средней оценки, если они очень хороши вам дают на обдумывание 3.5 секунд плюс ваша скорость печати плюс ещё половина от вашей скорости печати, так сказать штрафные, мало ли что
Далее, оценка аккуратности ответа, тут всё просто: если написать "стучт" вместо "стучать" это будет где-то 80% аккуратно из 100% и программа конечно же сообщит, что было почти верно и стоит написать это так (на всякий случай)
В итоге, оценка за ответ на карточку это: медиана от скорости + аккуратности
Потом они собираются в массив и там ещё рассчитывается общая оценка среди этих всех, это оценка за сессию
Коротко про оценку за сессию: В самом конфиге есть штука - perSessionCards, это число карточек, которые выучивается за раз. Тут в основу входит такая штука, что человек может за раз в кратковременной памяти удерживать максимум 10-11 единиц, в среднем, конечно 7-9. На это оценка и влияет, она регулирует сколько за сессию вы сейчас учите от 5 до 10 карточек за раз, на основе оценок, которые вы получаете.
Как происходит переход между состояниями: Изначально, когда вы добавляете карточки они все в состоянии LEARN (не выученные), после выучивания все карточки попадают в WEAK (слабые) вне зависимости от оценки, так как мозг запоминает последние 3-5 действий, нужно обязательно чтобы карточка ещё повстречалась. Далее зависит от ответов: если оценка низкая, остаёмся в WEAK, ответили средне/хорошо, идём из WEAK в MIDDLE. И так далее пока карточка не попадёт в STRONG (сильные) - эти карточки считаются выученными + проработанными.
Категория REVISE, интервальные повторения Эббингауза:
При очередной загрузке конфига сессии, приложение обновляет карточки, проверяет на каком интервале вы находитесь сейчас и не нарушен ли он. При нарушении интервала карточка считается забытой (конечно это не факт, особенно если интервал уже по счёту большой или слово ходовое и используется, и в дальнейшем логика программы всё же будет поправляться и улучшаться) и перемещается в LEARN. Нарушение интервала это: текущий интервал + треть с половиной от этого интервала
Интервалы (дни с последнего повторения): 1, 3, 7, 14, 30, 60, 120, 240
Переходы между состояниями из REVISE отличаются от LEARN, тут куда попадёт слово в WEAK, MIDDLE или сразу в STRONG напрямую зависит от оценки, ибо если слово спустя время хорошо и легко вспомнилось, то и проработки оно не требует.
Приоритеты: Первым по приоритету считается REVISE, ибо если есть что повторять надо сначала это повторить, затем идут WEAK, MIDDLE на проработку, и только потом мы можем учить что-то новое.
Некоторые ограничения, выставленные программой и в будущем могут быть настраиваемыми параметрами (а некоторые нет): Выучить новых карточек в день можно максимум 100, возможно это будет потом настраиваться. Помодоро таймер для умственных задач, схема 20-5-20-5-20-15 (то есть 20 минут работаем, 5 отдыхаем, большой перерыв 15 минут) при этом таких тренировочных блоков максимум в день можно сделать 3 штуки, это будет защищать от каши в голове, по крайней мере должно.
Где пощупать? Какие принципы вошли в основу?
Принципы обучения и работы мозга, которые вошли в основу создания приложения:
Интервальные повторения (spaced repetition) - это техника повторения информации через увеличивающиеся промежутки времени. Она основана на кривой забывания Эббингауза. Повторяя материал по оптимальному графику, можно эффективно перемещать знания из кратковременной в долговременную память. MindVault использует интервалы в 1, 3, 7, 14, 30, 60, 120, 240 дней для оптимального запоминания.
Интенсивность (intensity) - принцип работы над задачей максимально сфокусированно, не отвлекаясь. Помодоро-таймер в MindVault помогает поддерживать высокую концентрацию внимания, чередуя периоды интенсивной работы по 20 минут и короткие перерывы по 5 минут. Это позволяет избегать умственного истощения.
Ограничение объема (chunking) - за один подход оптимально учить ограниченное количество новой информации, около 5-10 элементов. Человеческий мозг способен удерживать в рабочей памяти 7±2 единицы. MindVault подстраивает число карточек за сессию от 5 до 10 в зависимости от ваших результатов.
Многоэтапное запоминание (multi-stage memorization) - для надежного усвоения недостаточно один раз вспомнить факт. Необходимо несколько повторений, чтобы перевести знание из кратковременной в долговременную память. В MindVault карточки проходят через 5 стадий - Не изученные, Слабые, Средние, Сильные, Повторение. Это обеспечивает постепенную проработку материала.
Приоритезация (prioritization) - в первую очередь нужно повторять то, что уже было выучено ранее, и только потом переходить к новому материалу. MindVault отдает приоритет карточкам для Повторения, затем Слабым и Средним. И лишь после их исчерпания предлагает учить новые карточки из категории Не изученные. Это помогает не забывать уже освоенное.
Приложение является полностью открытым, как можно понять и из самого вступления, она кстати на Java.
Git: https://github.com/DedInc/MindVault
Код далеко не идеален, я так себе умею на джаве, просто хотелось кросс-платформ да и затем на андроид реализовать, если понравилось - можете пользоваться, и ещё раз: буду рад вашим наработкам и советам.
Удачи всему Хабру :)