twopl_full
def twopl_full(dataset, options=None)Estimates parameters in a 2PL IRT model.
Please use twopl_mml instead.
Args
dataset- [items x participants] matrix of True/False Values
options- dictionary with updates to default options
Returns
discrimination- (1d array) estimates of item discrimination
difficulty- (1d array) estimates of item difficulties
Options
- max_iteration: int
- distribution: callable
- quadrature_bounds: (float, float)
- quadrature_n: int
Expand source code
def twopl_full(dataset, options=None): """ Estimates parameters in a 2PL IRT model. Please use twopl_mml instead. Args: dataset: [items x participants] matrix of True/False Values options: dictionary with updates to default options Returns: discrimination: (1d array) estimates of item discrimination difficulty: (1d array) estimates of item difficulties Options: * max_iteration: int * distribution: callable * quadrature_bounds: (float, float) * quadrature_n: int """ options = validate_estimation_options(options) quad_start, quad_stop = options['quadrature_bounds'] quad_n = options['quadrature_n'] n_items = dataset.shape[0] unique_sets, counts = np.unique(dataset, axis=1, return_counts=True) the_sign = convert_responses_to_kernel_sign(unique_sets) theta = _get_quadrature_points(quad_n, quad_start, quad_stop) distribution = options['distribution'](theta) discrimination = np.ones((n_items,)) difficulty = np.zeros((n_items,)) for iteration in range(options['max_iteration']): previous_discrimination = discrimination.copy() # Quadrature evaluation for values that do not change partial_int = _compute_partial_integral(theta, difficulty, discrimination, the_sign) partial_int *= distribution for item_ndx in range(n_items): # pylint: disable=cell-var-from-loop local_int = _compute_partial_integral(theta, difficulty[item_ndx, None], discrimination[item_ndx, None], the_sign[item_ndx, None]) partial_int /= local_int def min_func_local(estimate): discrimination[item_ndx] = estimate[0] difficulty[item_ndx] = estimate[1] estimate_int = _compute_partial_integral(theta, difficulty[item_ndx, None], discrimination[item_ndx, None], the_sign[item_ndx, None]) estimate_int *= partial_int otpt = integrate.fixed_quad( lambda x: estimate_int, quad_start, quad_stop, n=quad_n)[0] return -np.log(otpt).dot(counts) # Two parameter solver that doesn't need derivatives initial_guess = np.concatenate((discrimination[item_ndx, None], difficulty[item_ndx, None])) fmin_slsqp(min_func_local, initial_guess, disp=False, bounds=[(0.25, 4), (-4, 4)]) # Update the partial integral based on the new found values estimate_int = _compute_partial_integral(theta, difficulty[item_ndx, None], discrimination[item_ndx, None], the_sign[item_ndx, None]) # update partial integral partial_int *= estimate_int if(np.abs(discrimination - previous_discrimination).max() < 1e-3): break return discrimination, difficulty
Last modified April 7, 2020: Updating documentation. (3da0254)