Ejemplo n.º 1
0
def conditional_probability_correct(abilities, ex_parameters, exercise_ind):
    """Predict the probabilities of getting questions correct for a set of
    exercise indices, given model parameters in couplings and the
    abilities vector for the user.

    Args:
        abilities: An ndarray with shape = (a, 1), where a = the
            number of abilities in the model (not including the bias)
        couplings: An ndarray with shape (n, a + 1), where n = the
            number of exercises known by the model.
        execises_ind: An ndarray of exercise indices in the coupling matrix.
            The argument specifies which exercises the caller would like
            conditional probabilities for.
            Should be 1-d with shape = (# of exercises queried for)

    Returns:
        An ndarray of floats with shape = (exercise_ind.size)
    """
    # Pad the abilities vector with a 1 to act as a bias.
    # The shape of abilities will become (a+1, 1).
    abilities = np.append(abilities.copy(), np.ones((1, 1)), axis=0)
    difficulties = ex_parameters.W_correct[exercise_ind, :]
    Z = sigmoid(np.dot(difficulties, abilities))
    Z = np.reshape(Z, Z.size)  # flatten to 1-d ndarray
    return Z
Ejemplo n.º 2
0
def conditional_probability_correct(abilities, ex_parameters, exercise_ind):
    """Predict the probabilities of getting questions correct for a set of
    exercise indices, given model parameters in couplings and the
    abilities vector for the user.

    Args:
        abilities: An ndarray with shape = (a, 1), where a = the
            number of abilities in the model (not including the bias)
        couplings: An ndarray with shape (n, a + 1), where n = the
            number of exercises known by the model.
        execises_ind: An ndarray of exercise indices in the coupling matrix.
            The argument specifies which exercises the caller would like
            conditional probabilities for.
            Should be 1-d with shape = (# of exercises queried for)

    Returns:
        An ndarray of floats with shape = (exercise_ind.size)
    """
    # Pad the abilities vector with a 1 to act as a bias.
    # The shape of abilities will become (a+1, 1).
    abilities = np.append(abilities.copy(), np.ones((1, 1)), axis=0)
    difficulties = ex_parameters.W_correct[exercise_ind, :]
    Z = sigmoid(np.dot(difficulties, abilities))
    Z = np.reshape(Z, Z.size)  # flatten to 1-d ndarray
    return Z
Ejemplo n.º 3
0
def L_dL_singleuser(arg):
    """Calculate log likelihood and gradient wrt couplings of mIRT model
       for single user """
    theta, state, options = arg

    abilities = state['abilities'].copy()
    correct = state['correct']
    exercises_ind = state['exercises_ind']

    dL = Parameters(theta.num_abilities, theta.num_exercises)

    # pad the abilities vector with a 1 to act as a bias
    abilities = np.append(abilities.copy(),
                          np.ones((1, abilities.shape[1])),
                          axis=0)
    # the abilities to exercise coupling parameters for this exercise
    W_correct = theta.W_correct[exercises_ind, :]

    # calculate the probability of getting a question in this exercise correct
    Y = np.dot(W_correct, abilities)
    Z = sigmoid(Y)  # predicted correctness value
    Zt = correct.reshape(Z.shape)  # true correctness value
    pdata = Zt * Z + (1. - Zt) * (1. - Z)  # = 2*Zt*Z - Z + const
    dLdY = ((2. * Zt - 1.) * Z * (1. - Z)) / pdata

    L = -np.sum(np.log(pdata))
    dL.W_correct = -np.dot(dLdY, abilities.T)

    if not options.correct_only:
        # calculate the probability of taking time response_time to answer
        log_time_taken = state['log_time_taken']
        # the abilities to time coupling parameters for this exercise
        W_time = theta.W_time[exercises_ind, :]
        sigma = theta.sigma_time[exercises_ind].reshape((-1, 1))
        Y = np.dot(W_time, abilities)
        err = (Y - log_time_taken.reshape((-1, 1)))
        L += np.sum(err**2 / sigma**2) / 2.
        dLdY = err / sigma**2

        dL.W_time = np.dot(dLdY, abilities.T)
        dL.sigma_time = (-err**2 / sigma**3).ravel()

        # normalization for the Gaussian
        L += np.sum(0.5 * np.log(sigma**2))
        dL.sigma_time += 1. / sigma.ravel()

    return L, dL, exercises_ind
Ejemplo n.º 4
0
def L_dL_singleuser(arg):
    """Calculate log likelihood and gradient wrt couplings of mIRT model
       for single user """
    theta, state, options = arg

    abilities = state['abilities'].copy()
    correct = state['correct']
    exercises_ind = state['exercises_ind']

    dL = Parameters(theta.num_abilities, theta.num_exercises)

    # pad the abilities vector with a 1 to act as a bias
    abilities = np.append(abilities.copy(),
                          np.ones((1, abilities.shape[1])),
                          axis=0)
    # the abilities to exercise coupling parameters for this exercise
    W_correct = theta.W_correct[exercises_ind, :]

    # calculate the probability of getting a question in this exercise correct
    Y = np.dot(W_correct, abilities)
    Z = sigmoid(Y)  # predicted correctness value
    Zt = correct.reshape(Z.shape)  # true correctness value
    pdata = Zt * Z + (1. - Zt) * (1. - Z)  # = 2*Zt*Z - Z + const
    dLdY = ((2. * Zt - 1.) * Z * (1. - Z)) / pdata

    L = -np.sum(np.log(pdata))
    dL.W_correct = -np.dot(dLdY, abilities.T)

    if not options.correct_only:
        # calculate the probability of taking time response_time to answer
        log_time_taken = state['log_time_taken']
        # the abilities to time coupling parameters for this exercise
        W_time = theta.W_time[exercises_ind, :]
        sigma = theta.sigma_time[exercises_ind].reshape((-1, 1))
        Y = np.dot(W_time, abilities)
        err = (Y - log_time_taken.reshape((-1, 1)))
        L += np.sum(err ** 2 / sigma ** 2) / 2.
        dLdY = err / sigma ** 2

        dL.W_time = np.dot(dLdY, abilities.T)
        dL.sigma_time = (-err ** 2 / sigma ** 3).ravel()

        # normalization for the Gaussian
        L += np.sum(0.5 * np.log(sigma ** 2))
        dL.sigma_time += 1. / sigma.ravel()

    return L, dL, exercises_ind