18 Stimmen

Abgestufte Wiederholung (SRS) für das Lernen

Ein Kunde hat mich gebeten, einen einfachen Wiederholungsalgorithmus (SRS) für eine online-basierte Lernsite hinzuzufügen. Doch bevor ich mich in die Arbeit stürze, möchte ich es mit der Gemeinschaft diskutieren.

Im Grunde stellt die Website dem Benutzer eine Reihe von Fragen (indem sie automatisch etwa 10 von insgesamt 100 Fragen aus einer Datenbank auswählt), und der Benutzer gibt entweder eine richtige oder eine falsche Antwort. Die Ergebnisse des Nutzers werden dann z. B. in einer Datenbank gespeichert:

userid  questionid  correctlyanswered  dateanswered
1       123         0 (no)             2010-01-01 10:00
1       124         1 (yes)            2010-01-01 11:00
1       125         1 (yes)            2010-01-01 12:00    

Um die Fähigkeit eines Benutzers, alle Antworten zu lernen, zu maximieren, sollte ich einen SRS-Algorithmus anwenden können, so dass ein Benutzer beim nächsten Mal, wenn er das Quiz absolviert, häufiger falsch beantwortete Fragen erhält, als richtig beantwortete Fragen. Außerdem sollten Fragen, die zuvor falsch, aber in letzter Zeit oft richtig beantwortet wurden, seltener vorkommen.

Hat jemand so etwas schon einmal umgesetzt? Hat jemand Tipps oder Vorschläge?

Das sind die besten Links, die ich gefunden habe:

8voto

gimel Punkte 78080

Anki ist ein quelloffenes Programm, das die abstandsbasierte Wiederholung implementiert. Da es quelloffen ist, können Sie den Quellcode für libanki eine Bibliothek mit Wiederholungsabständen für Anki. Seit Januar 2013 können die Quellen von Anki Version 2 durchsucht werden これ .

Die Quellen sind in Python は、その ausführbarer Pseudocode Sprache. Das Lesen des Quelltextes, um den Algorithmus zu verstehen, kann durchaus möglich sein. Das Datenmodell wird definiert durch sqlalechmey , das Python SQL Toolkit und Object Relational Mapper, das Anwendungsentwicklern die volle Leistungsfähigkeit und Flexibilität von SQL bietet.

8voto

Thomas Ahle Punkte 29242

Was Sie tun wollen, ist, eine Zahl zu haben X_i für alle Fragen i . Man kann diese Zahlen normalisieren (ihre Summe auf 1 setzen) und eine zufällig mit der entsprechenden Wahrscheinlichkeit auswählen.

Wenn N ist die Anzahl der verschiedenen Fragen und M die durchschnittliche Anzahl der Antworten auf die einzelnen Fragen ist, dann könnte man Folgendes herausfinden X in M*N Zeit wie diese:

  • Erstellen Sie das Array X[N] auf 0 gesetzt.
  • Gehen Sie die Daten durch, und jedes Mal, wenn Sie die Frage i falsch beantwortet, erhöhen N[i]f(t) wobei t ist die Antwortzeit und f ist eine steigende Funktion.

Denn f zunimmt, hat eine vor langer Zeit falsch beantwortete Frage weniger Auswirkungen als eine gestern falsch beantwortete. Sie können mit verschiedenen f um ein gutes Verhalten zu erreichen.

Der klügere Weg Ein schnellerer Weg ist es, nicht zu erzeugen X[] jedes Mal, wenn Sie Fragen auswählen, sondern speichern sie in einer Datenbanktabelle. Sie werden nicht in der Lage sein, die f mit dieser Lösung. Addieren Sie stattdessen einfach jedes Mal 1, wenn die Frage falsch beantwortet wird, und gehen Sie die Tabelle regelmäßig durch - beispielsweise um Mitternacht - und multiplizieren Sie alle X[i] durch eine Konstante - sagen wir 0.9 .

Update : Eigentlich sollten Sie Ihre Daten auf der Grundlage von Richtigstellungen und nicht von Falschmeldungen machen. Andernfalls haben Fragen, die lange Zeit weder richtig noch falsch beantwortet wurden, eine geringere Chance, ge

1voto

Jakobovski Punkte 2808

H

F

  • I
  • I
  • E
  • C

h .

D

import random
import datetime

# The number of times needed for the user to get the card correct(EASY) consecutively before removing the card from
# the current sub_deck.
CONSECUTIVE_CORRECT_TO_REMOVE_FROM_SUBDECK_WHEN_KNOWN = 2
CONSECUTIVE_CORRECT_TO_REMOVE_FROM_SUBDECK_WHEN_WILL_FORGET = 3

# The number of cards in the sub-deck
SUBDECK_SIZE = 15
REMINDER_RATE = 1.6

class Deck(object):

    def __init__(self):
        self.cards = []

        # Used to make sure we don't display the same card twice
        self.last_card = None

    def add_card(self, card):
        self.cards.append(card)

    def get_next_card(self):
        self.cards = sorted(self.cards)  # Sorted by next_practice_time
        sub_deck = self.cards[0:min(SUBDECK_SIZE, len(self.cards))]
        card = random.choice(sub_deck)

        # In case card == last card lets select again. We don't want to show the same card two times in a row.
        while card == self.last_card:
            card = random.choice(sub_deck)

        self.last_card = card
        return card

class Card(object):

    def __init__(self, front, back):
        self.front = front
        self.back = back

        self.next_practice_time = datetime.utc.now()
        self.consecutive_correct_answer = 0
        self.last_time_easy = datetime.utc.now()

    def update(self, performance_str):
        """ Updates the card after the user has seen it and answered how difficult it was. The user can provide one of
        three options: [I_KNOW, KNOW_BUT_WILL_FORGET, DONT_KNOW].
        """

        if performance_str == "KNOW_IT":
            self.consecutive_correct_answer += 1

            if self.consecutive_correct_answer >= CONSECUTIVE_CORRECT_TO_REMOVE_FROM_SUBDECK_WHEN_KNOWN:
                days_since_last_easy = (datetime.utc.now() - self.last_time_easy).days
                days_to_next_review = (days_since_last_easy + 2) * REMINDER_RATE
                self.next_practice_time = datetime.utc.now() + datetime.time(days=days_to_next_review)
                self.last_time_easy = datetime.utc.now()
            else:
                self.next_practice_time = datetime.utc.now()

        elif performance_str == "KNOW_BUT_WILL_FORGET":
            self.consecutive_correct_answer += 1

            if self.consecutive_correct_answer >= CONSECUTIVE_CORRECT_TO_REMOVE_FROM_SUBDECK_WHEN_WILL_FORGET:
                self.next_practice_time = datetime.utc.now() + datetime.time(days=1)
            else:
                self.next_practice_time = datetime.utc.now()

        elif performance_str == "DONT_KNOW":
            self.consecutive_correct_answer = 0
            self.next_practice_time = datetime.utc.now()

    def __cmp__(self, other):
        """Comparator or sorting cards by next_practice_time"""
        if hasattr(other, 'next_practice_time'):
            return self.number.__cmp__(other.next_practice_time)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X