def get_guess(card_parameters): """ Gets the guess value for the card. """ guess_distribution = get_distribution(card_parameters, 'guess') return get_guess_pmf_value(guess_distribution)
def update(score, time_delta, learned, guess_distribution, slip_distribution): """ Given a learner and a card, update both statistics. Input: - Score - What what the score (0 - wrong or 1 - correct)? - Time - When did the score come in (in seconds)? - Prev Time [Previous Card] - When was the last time we saw a learner response for this skill? - * * * - Learned [Learner] - Before seeing the response, how likely did we already believe the learner knew the skill? - Guess [Card] - Before the response, how likely would a learner who didn't know the skill still get the right answer? - Slip [Card] - Before the response, how likely woud a learner who did know the skill still get a wrong answer? - Weight [Card] - How much should we consider previous examples? - Transit [Card] - Before seeing the data, how likely did we think the learner would learn the skill by seeing the card? Output: - Correct - Before seeing the score, how likely was the learner to answer the card well? (doesn't update anything) - Learned [Learner] - How likely is it that the learner knows the skill? (main calculation) - Guess [Card] - If the learner doesn't know the skill, how likely are they to get the answer right anyways? (should come before learned) - Slip [Card] - If the learner knows the skill, how likely are they to still answer incorrectly? (should come before learned) - Weight [Card] - How much should we consider previous examples? (scale before guess, slip, transit, update after) - Transit [Card (Prior)] - How likely is it the learner learned the skill as the result of seeing that card? (after learned) """ guess = get_guess_pmf_value(guess_distribution) slip = get_slip_pmf_value(slip_distribution) transit = init_transit learned2 = update_learned(score, learned, guess, slip, transit, time_delta) guess_distribution = update_pmf(guess_distribution, { 'score': score, 'learned': learned, 'guess': guess, 'slip': slip, }, get_guess_pmf_likelihood) slip_distribution = update_pmf(slip_distribution, { 'score': score, 'learned': learned, 'guess': guess, 'slip': slip, }, get_slip_pmf_likelihood) return { 'learned': learned2, 'guess_distribution': guess_distribution, 'slip_distribution': slip_distribution, }
def main(num_learners=1000, num_cards=50): d = create_responses(num_learners, num_cards) responses, learners, cards = d['responses'], d['learners'], d['cards'] precision = 20 my_cards = [{ 'name': card['name'], 'guess_distribution': init_pmf({ h: 1 - (init_guess - h) ** 2 for h in [h / precision for h in range(1, precision)]}), 'slip_distribution': init_pmf({ h: 1 - (init_slip - h) ** 2 for h in [h / precision for h in range(1, precision)]}), 'transit': init_transit, } for card in cards] my_learners = [{ 'name': learner['name'], 'learned': init_learned, } for learner in learners] latest_response_per_learner = {} for i, response in enumerate(responses): # response keys: learner, card, time, score if response['learner'] in latest_response_per_learner: prev_response = latest_response_per_learner[response['learner']] else: prev_response = { 'time': response['time'], 'prev_learned': init_learned, } my_learner = get_learner(response['learner'], my_learners) my_card = get_card(response['card'], my_cards) response['prev_learned'] = my_learner['learned'] c = update(learned=my_learner['learned'], guess_distribution=my_card['guess_distribution'], slip_distribution=my_card['slip_distribution'], score=response['score'], time_delta=response['time'] - prev_response['time']) my_learner['learned'] = c['learned'] my_card['guess_distribution'] = c['guess_distribution'] my_card['slip_distribution'] = c['slip_distribution'] latest_response_per_learner[response['learner']] = response # Compute the error rates. # Error should sqrt(sum( (o - x)^2 for o in list )) guess_error, slip_error, transit_error = 0, 0, 0 for card in cards: my_card = get_card(card['name'], my_cards) my_card['guess'] = get_guess_pmf_value(my_card['guess_distribution']) my_card['slip'] = get_slip_pmf_value(my_card['slip_distribution']) guess_error += (my_card['guess'] - card['guess']) ** 2 slip_error += (my_card['slip'] - card['slip']) ** 2 transit_error += (my_card['transit'] - card['transit']) ** 2 print('guess_error', sqrt(guess_error / len(my_cards))) print('slip_error', sqrt(slip_error / len(my_cards))) print('transit_error', sqrt(transit_error / len(my_cards))) guess_error, slip_error, transit_error = 0, 0, 0 for card in cards: guess_error += (init_guess - card['guess']) ** 2 slip_error += (init_slip - card['slip']) ** 2 transit_error += (init_transit - card['transit']) ** 2 print('CONTROL guess_error', sqrt(guess_error / len(my_cards))) print('CONTROL slip_error', sqrt(slip_error / len(my_cards))) print('CONTROL transit_error', sqrt(transit_error / len(my_cards)))