def L_dL_singleuser(arg): """ calculate log likelihood and gradient wrt couplings of mIRT model for single user """ couplings, state, options = arg abilities = state['abilities'].copy() correct = state['correct'] exercises_ind = state['exercises_ind'] # 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 exercise_couplings = couplings[exercises_ind, :] # calculate the probability of getting a question in this exercise correct Y = np.dot(exercise_couplings, abilities) Z = mirt_util.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 dL = np.dot(dLdY, abilities.T) dL /= np.log(2.) L = np.sum(np.log(pdata)) L /= np.log(2.) return -L, -dL, exercises_ind
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 = mirt_util.Parameters(theta.num_abilities, len(exercises_ind)) # 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 = mirt_util.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