문항특성의 불변성
문항반응이론: 문항특성의 불변성
다음은 “예비교사를 위한 교육평가"의 일부(p.168)를 발췌한 내용이다.[1]
"문항반응이론은 능력이 낮은 피험자 집단에 검사를 실시해도 능력이 높은 피험자 집단에 검사를 실시해도 문항난이도, 문항변별도, 문항추측도를 추정하였을 때 값이 같다는 것이다.”
[1]: 비단 이 책만 아니고 내가 찾아본 거의 모든 교육 평가 책에는 동일한 내용이 동일하게 (뒤에서 살펴보겠지만) 부실한 설명으로 적혀 있었다. Christine DeMars가 설명한 내용을 발췌해보자. “In IRT, the item difficulty, \(b\) , is the same(invariant) across samples, up to linear transofrmation.”
이 내용만 봐서는 오해의 소지가 다분한 듯 하다.
IRT에서 모집단의 능력 분포인 표준 정규 분포( \(\mathcal{N}(0,1)\) )은 임의적인 설정이다. 따라서 피험자 집단에 따라 문항난이도와 문항변별도는 다르게 추정된다.
다음은 모집단의 능력 평균이 0인 경우와 1인 경우에 문항 난이도 추정치가 어떻게 달라지는지를 보여준다.
library(mirt)
library(tibble)
library(dplyr)
library(ggplot2)
a = rep(1,10)
d = rnorm(10)
thA = matrix(rnorm(1000, mean=0), 1000, 1)
thB = matrix(rnorm(1000, mean=1), 1000, 1)
YA <- simdata(a=a, d=d, itemtype='2PL', Theta=thA)
YB <- simdata(a=a, d=d, itemtype='2PL', Theta=thB)
fitA <- mirt(YA, itemtype='2PL', model=1, SE=TRUE)
fitB <- mirt(YB, itemtype='2PL', model=1, SE=TRUE)
cfA <- coef(fitA, as.data.frame=TRUE)
cfB <- coef(fitB, as.data.frame=TRUE)
dat <- rbind(
cfA[grepl('d', rownames(cfA)), ,drop=FALSE] %>%
as_tibble %>%
rownames_to_column(var='item') %>%
mutate(group='A'),
cfB[grepl('d', rownames(cfB)), ,drop=FALSE] %>%
as_tibble %>%
rownames_to_column(var='item') %>%
mutate(group='B')
) %>%
mutate(item = factor(item, levels=1:10))
## Iteration: 1, Log-Lik: -5468.804, Max-Change: 0.19976 Iteration: 2, Log-Lik: -5449.417, Max-Change: 0.11241 Iteration: 3, Log-Lik: -5443.917, Max-Change: 0.06594 Iteration: 4, Log-Lik: -5442.263, Max-Change: 0.03871 Iteration: 5, Log-Lik: -5441.773, Max-Change: 0.02261 Iteration: 6, Log-Lik: -5441.625, Max-Change: 0.01267 Iteration: 7, Log-Lik: -5441.574, Max-Change: 0.00699 Iteration: 8, Log-Lik: -5441.563, Max-Change: 0.00401 Iteration: 9, Log-Lik: -5441.559, Max-Change: 0.00237 Iteration: 10, Log-Lik: -5441.558, Max-Change: 0.00129 Iteration: 11, Log-Lik: -5441.558, Max-Change: 0.00052 Iteration: 12, Log-Lik: -5441.558, Max-Change: 0.00034 Iteration: 13, Log-Lik: -5441.558, Max-Change: 0.00021 Iteration: 14, Log-Lik: -5441.558, Max-Change: 0.00014 Iteration: 15, Log-Lik: -5441.558, Max-Change: 0.00009 ## ## ## Calculating information matrix... ## Iteration: 1, Log-Lik: -5562.617, Max-Change: 0.16846 Iteration: 2, Log-Lik: -5552.706, Max-Change: 0.10277 Iteration: 3, Log-Lik: -5549.896, Max-Change: 0.06307 Iteration: 4, Log-Lik: -5548.948, Max-Change: 0.03148 Iteration: 5, Log-Lik: -5548.764, Max-Change: 0.01779 Iteration: 6, Log-Lik: -5548.709, Max-Change: 0.01030 Iteration: 7, Log-Lik: -5548.688, Max-Change: 0.00534 Iteration: 8, Log-Lik: -5548.684, Max-Change: 0.00353 Iteration: 9, Log-Lik: -5548.683, Max-Change: 0.00192 Iteration: 10, Log-Lik: -5548.682, Max-Change: 0.00063 Iteration: 11, Log-Lik: -5548.682, Max-Change: 0.00039 Iteration: 12, Log-Lik: -5548.682, Max-Change: 0.00024 Iteration: 13, Log-Lik: -5548.682, Max-Change: 0.00015 Iteration: 14, Log-Lik: -5548.682, Max-Change: 0.00009 ## ## ## Calculating information matrix...
pd = position_dodge(0.1)
dat %>% ggplot(aes(x=item, y=par, ymin=CI_2.5, ymax=CI_97.5, col=group)) +
geom_point(position=pd) + geom_errorbar(width=0.1, position=pd) +
labs(y='Estimated difficulty') +
labs(x='Items')
이것은 모집단의 능력 평균을 모두 0으로 지정했기 때문에 발생하는 현상이다. (하지만 우리는 모집단의 능력 평균을 미리 알 수 없기 때문에 다른 방도가 없다!)
따라서 능력이 낮은 피험자 집단에 검사를 실시해도 능력이 높은 피험자 집단에 검사를 실시해도 문항난이도, 문항변별도, 문항추측도를 추정하였을 때 값이 같다는 문장은 오해의 소지가 다분하다. (이렇게 집단 평균이 다른 경우 뿐 아니라, 차별문항기능(Differential Item Functioning; DIF)이라는 현상을 생각해봐도 된다. 차별문항기능이란 문항의 난이도나 변별도가 집단에 따라 달라지는 현상을 의미한다.)
문항 난이도 불변성
IRT의 진짜 장점은 사람의 능력과 문항의 난이도를 하나의 직선 위에 위치시킨다는 것이다.
이렇게 생각해보자. IRT를 포함한 검사를 분석할 때 우리가 관심을 가지는 것은 다음의 세 가지로 분류해 볼 수 있다.
- 검사 자체의 특성
- 문항의 특성
- 수험자의 특성
3번 수험자의 특성이란, 수험자의 능력을 의미하는 것이고, 2번 문항의 특성이란 문항의 난이도, 변별도 등을 의미한다. 1번 검사 자체의 특성이란 문항들이 모여서 우리가 측정하려는 대상(능력, 성향, 적성 등)을 얼마나 정확하게 그리고 신빙성 있게 측정하느냐는 것이다.
이때 수험자의 특성은 눈에 보이지 않고, 직접 측정할 수도 없는 것이다. 만약 집단마다 분포가 다르다고 해도 우리가 이를 확실히 눈으로 볼 수 없다. 반면 문항이란 같은 문항은 어떤 집단에게 제시되었던 간에 같다라고 우선 가정한다. (여기서 가정한다고 하는 것은 차별문항기능에서 보듯이 다를 수도 있기 때문이다. 예를 들어 “두 개의 에머랄드와 한 개의 에머랄드를 합치면 몇 개인가?"라는 질문은 에머랄드를 너무나 잘 알고 있고, 항상 몇 개씩 가지고 다니는 아이들과 에머랄드란 단어 자체를 모르는 아이들에게 같다고 생각할 수 없기 때문이다.)
다음은 앞의 평균이 다른 두 집단에 대한 2PL 분석 결과로 얻어진 문항 난이도과 수험자의 능력치 추정값을 하나의 그림에 나타낸 것이다.
library(WrightMap)
diffA <- cfA[grepl('d', rownames(cfA)), "par"]
names(diffA) <- 1:10
diffB <- cfB[grepl('d', rownames(cfB)), "par"]
names(diffB) <- 1:10
wrightMap(fscores(fitA), diffA)
## [,1] ## 1 -1.4254750 ## 2 -0.7849791 ## 3 0.6550960 ## 4 0.1246907 ## 5 -1.6476004 ## 6 -2.7422941 ## 7 0.7555924 ## 8 1.5507982 ## 9 -1.3510807 ## 10 -0.3372793
wrightMap(fscores(fitB), diffB)
## [,1] ## 1 -0.1325570 ## 2 0.1415064 ## 3 1.4158933 ## 4 1.1563284 ## 5 -0.6001822 ## 6 -1.6807807 ## 7 1.6392685 ## 8 2.4272736 ## 9 -0.4676746 ## 10 0.6706505
여기서 우리는 문항 난이도는 달라졌지만, 문항 사이의 거리는 일정하게 유지됨을 알 수 있다. 그리고 문항을 기준으로 사람의 능력 평균을 보면 그 차이는 실제 차이와 비슷한 1이다.
문항 변별도 불변성
변별도의 경우도 마찬가지이다. 만약 표본 집단의 능력 분산이 다르다면 문항의 변별도는 다르게 추정될 것이다. 하지만 문항 간의 난이도 차이를 고려해볼 때, 문항의 변별도의 의미는 동일하게 유지된다. 예를 들어 문항 간의 난이도 차이가 증가되면 변별도도 감소하고, 문항 간의 난이도 차이가 줄어들면 변별도는 증가하게 된다.
d = rnorm(10)
thA = matrix(rnorm(1000, mean=0, sd=0.7), 1000, 1)
thB = matrix(rnorm(1000, mean=0, sd=1.4), 1000, 1)
YA <- simdata(a=a, d=d, itemtype='2PL', Theta=thA)
YB <- simdata(a=a, d=d, itemtype='2PL', Theta=thB)
fitA <- mirt(YA, itemtype='2PL', model=1, SE=TRUE)
fitB <- mirt(YB, itemtype='2PL', model=1, SE=TRUE)
cfA <- coef(fitA, as.data.frame=TRUE)
cfB <- coef(fitB, as.data.frame=TRUE)
dat <- rbind(
cfA[grepl('[.]a', rownames(cfA)), ,drop=FALSE] %>%
as_tibble %>%
rownames_to_column(var='item') %>%
mutate(group='A'),
cfB[grepl('[.]a', rownames(cfB)), ,drop=FALSE] %>%
as_tibble %>%
rownames_to_column(var='item') %>%
mutate(group='B')
) %>%
mutate(item = factor(item, levels=1:10))
## Iteration: 1, Log-Lik: -5909.715, Max-Change: 0.17443 Iteration: 2, Log-Lik: -5899.020, Max-Change: 0.08096 Iteration: 3, Log-Lik: -5897.047, Max-Change: 0.04394 Iteration: 4, Log-Lik: -5896.413, Max-Change: 0.02336 Iteration: 5, Log-Lik: -5896.251, Max-Change: 0.01254 Iteration: 6, Log-Lik: -5896.205, Max-Change: 0.00747 Iteration: 7, Log-Lik: -5896.187, Max-Change: 0.00319 Iteration: 8, Log-Lik: -5896.183, Max-Change: 0.00241 Iteration: 9, Log-Lik: -5896.182, Max-Change: 0.00132 Iteration: 10, Log-Lik: -5896.181, Max-Change: 0.00057 Iteration: 11, Log-Lik: -5896.181, Max-Change: 0.00028 Iteration: 12, Log-Lik: -5896.181, Max-Change: 0.00023 Iteration: 13, Log-Lik: -5896.181, Max-Change: 0.00012 Iteration: 14, Log-Lik: -5896.181, Max-Change: 0.00010 ## ## ## Calculating information matrix... ## Iteration: 1, Log-Lik: -5689.507, Max-Change: 0.30165 Iteration: 2, Log-Lik: -5617.278, Max-Change: 0.16612 Iteration: 3, Log-Lik: -5599.240, Max-Change: 0.08868 Iteration: 4, Log-Lik: -5594.195, Max-Change: 0.04930 Iteration: 5, Log-Lik: -5592.647, Max-Change: 0.02773 Iteration: 6, Log-Lik: -5592.161, Max-Change: 0.01620 Iteration: 7, Log-Lik: -5591.955, Max-Change: 0.00689 Iteration: 8, Log-Lik: -5591.924, Max-Change: 0.00416 Iteration: 9, Log-Lik: -5591.913, Max-Change: 0.00239 Iteration: 10, Log-Lik: -5591.908, Max-Change: 0.00121 Iteration: 11, Log-Lik: -5591.907, Max-Change: 0.00067 Iteration: 12, Log-Lik: -5591.907, Max-Change: 0.00039 Iteration: 13, Log-Lik: -5591.907, Max-Change: 0.00022 Iteration: 14, Log-Lik: -5591.907, Max-Change: 0.00014 Iteration: 15, Log-Lik: -5591.907, Max-Change: 0.00011 Iteration: 16, Log-Lik: -5591.907, Max-Change: 0.00006 ## ## ## Calculating information matrix...
pd = position_dodge(0.1)
dat %>% ggplot(aes(x=item, y=par, ymin=CI_2.5, ymax=CI_97.5, col=group)) +
geom_point(position=pd) + geom_errorbar(width=0.1, position=pd) +
labs(y='Estimated discrimination') +
labs(x='Items')
마무리
IRT를 통해 눈에 보이지 않는 잠재변수(예. 사람의 능력)를 구체적인 문항을 기준으로 표시할 수 있다. 조카의 연산 능력은 +1(모집단에서 1표준편차 위)라고 말하는 것과 11+12는 풀 확률이 50%이고 101+102를 풀 확률은 30%라고 말하는 것의 차이를 생각해보자.
Leave a comment