-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Adding partial credit model. * Added multidimensional pcm model to the main class. * Unittested partial credit model.
- Loading branch information
Showing
16 changed files
with
274 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from .rayleigh import * | ||
from .partial_credit import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import numpy as np | ||
import theano.tensor as tt | ||
|
||
from theano.tensor.nnet import softmax | ||
from theano.tensor.extra_ops import cumsum | ||
from pymc3.theanof import floatX | ||
|
||
from pymc3.distributions.discrete import Categorical | ||
|
||
|
||
__all__ = ['PartialCredit'] | ||
|
||
|
||
class PartialCredit(Categorical): | ||
"""Computed the probability for the partial credit model given a set of | ||
cutpoints and observations. | ||
""" | ||
|
||
def __init__(self, eta, cutpoints, *args, **kwargs): | ||
eta = tt.as_tensor_variable(floatX(eta)) | ||
cutpoints = tt.concatenate( | ||
[ | ||
tt.as_tensor_variable([0.0]), | ||
tt.as_tensor_variable(cutpoints) | ||
]) | ||
cutpoints = tt.shape_padaxis(cutpoints, 0) | ||
eta = tt.shape_padaxis(eta, 1) | ||
|
||
p = softmax(cumsum(eta - cutpoints, axis=1)) | ||
|
||
super().__init__(p=p, *args, **kwargs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
from .graded_response_model import * | ||
from .multidimensional_grm import * | ||
from .multidimensional_grm import * | ||
from .partial_credit_model import * | ||
from .multidimensional_pcm import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import pymc3 as pm | ||
from numpy import linspace, zeros, unique | ||
|
||
import theano | ||
from theano import tensor as tt | ||
|
||
from girth.multidimensional import initial_guess_md | ||
from girth_mcmc.utils import get_discrimination_indices | ||
from girth_mcmc.distributions import PartialCredit | ||
|
||
|
||
__all__= ["multidimensional_credit_model"] | ||
|
||
|
||
def multidimensional_credit_model(dataset, n_categories, n_factors): | ||
"""Defines the mcmc model for the multidimensional partial credit model. | ||
Args: | ||
dataset: [n_items, n_participants] 2d array of measured responses | ||
n_categories: (int) number of polytomous values (i.e. Number of Likert Levels) | ||
n_factors: (int) number of factors to extract | ||
Returns: | ||
model: PyMC3 model to run | ||
""" | ||
if n_factors < 2: | ||
raise AssertionError(f"Multidimensional GRM model requires " | ||
f"two or more factors specified!") | ||
|
||
n_items, n_people = dataset.shape | ||
n_levels = n_categories - 1 | ||
|
||
# Need small deviation in offset to | ||
# fit into pymc framework | ||
mu_value = linspace(-0.05, 0.05, n_levels) | ||
|
||
# Run through 0, K - 1 | ||
observed = dataset - dataset.min() | ||
|
||
diagonal_indices, lower_indices = get_discrimination_indices(n_items, n_factors) | ||
lower_length = lower_indices[0].shape[0] | ||
|
||
graded_mcmc_model = pm.Model() | ||
|
||
with graded_mcmc_model: | ||
# Ability Parameters | ||
ability = pm.Normal("Ability", mu=0, sigma=1, shape=(n_factors, n_people)) | ||
|
||
# Multidimensional Discrimination | ||
discrimination = tt.zeros((n_items, n_factors), dtype=theano.config.floatX) | ||
diagonal_discrimination = pm.Lognormal('Diagonal Discrimination', mu=0, | ||
sigma=0.25, shape=n_factors) | ||
lower_discrimination = pm.Normal('Lower Discrimination', sigma=1, | ||
shape=lower_length) | ||
discrimination = tt.set_subtensor(discrimination[diagonal_indices], | ||
diagonal_discrimination) | ||
|
||
discrimination = tt.set_subtensor(discrimination[lower_indices], | ||
lower_discrimination) | ||
|
||
# Threshold multilevel prior | ||
sigma_difficulty = pm.HalfNormal('Difficulty_SD', sigma=1, shape=1) | ||
for ndx in range(n_items): | ||
thresholds = pm.Normal(f"Thresholds{ndx}", mu=mu_value, | ||
sigma=sigma_difficulty, shape=n_levels) | ||
|
||
# Compute the log likelihood | ||
kernel = pm.math.dot(discrimination[ndx], ability) | ||
probabilities = PartialCredit(f'Log_Likelihood{ndx}', cutpoints=thresholds, | ||
eta=kernel, observed=observed[ndx]) | ||
|
||
return graded_mcmc_model |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import pymc3 as pm | ||
from numpy import linspace, zeros, unique | ||
|
||
from girth_mcmc.distributions import PartialCredit, Rayleigh | ||
|
||
|
||
__all__ = ["partial_credit_model"] | ||
|
||
|
||
def partial_credit_model(dataset, n_categories): | ||
"""Defines the mcmc model for the partial credit model. | ||
Args: | ||
dataset: [n_items, n_participants] 2d array of measured responses | ||
n_categories: number of polytomous values (i.e. Number of Likert Levels) | ||
Returns: | ||
model: PyMC3 model to run | ||
""" | ||
n_items, n_people = dataset.shape | ||
n_levels = n_categories - 1 | ||
|
||
# Need small dither in offset to | ||
# fit into pymc framework | ||
mu_value = linspace(-0.05, 0.05, n_levels) | ||
|
||
# Run through 0, K - 1 | ||
observed = dataset - dataset.min() | ||
|
||
partial_mcmc_model = pm.Model() | ||
|
||
with partial_mcmc_model: | ||
# Ability Parameters | ||
ability = pm.Normal("Ability", mu=0, sigma=1, shape=n_people) | ||
|
||
# Discrimination multilevel prior | ||
rayleigh_scale = pm.Lognormal("Rayleigh_Scale", mu=0, sigma=1/4, shape=1) | ||
discrimination = pm.Bound(Rayleigh, lower=0.25)(name='Discrimination', | ||
beta=rayleigh_scale, offset=0.25, shape=n_items) | ||
|
||
# Threshold multilevel prior | ||
sigma_difficulty = pm.HalfNormal('Difficulty_SD', sigma=1, shape=1) | ||
|
||
# Possible Unorderd Categories | ||
for ndx in range(n_items): | ||
thresholds = pm.Normal(f"Thresholds{ndx}", mu=mu_value, | ||
sigma=sigma_difficulty, shape=n_levels) | ||
|
||
# Compute the log likelihood | ||
kernel = discrimination[ndx] * ability | ||
probabilities = PartialCredit(f'Log_Likelihood{ndx}', cutpoints=thresholds, | ||
eta=kernel, observed=observed[ndx]) | ||
|
||
return partial_mcmc_model |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
from .options import * | ||
from .multidimensional_utils import * | ||
from .missing_data import * | ||
from .rayleigh import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
numpy>=1.18.2 | ||
scipy>=1.4.1 | ||
pymc3>=3.10.0 | ||
girth>=0.5.0 | ||
girth>=0.7.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.