IRT简介
IRT理论即项目反应理论(Item Response Theory, IRT)。F. Lord在1951年从普林斯顿大学毕业时的博士论文《A Theory of Test Scores》被认为是IRT理论的开端之作。IRT最早使用在心理学领域,目的是做能力评估。现在已广泛应用于教育行业,用于校准评估测试、潜在特征的评分等。
模型介绍
IRT模型是用于评估被试对某一项目或某一类项目的潜在特质。
IRT模型是建立在一定的假设之下:
- 单维性假设,即假设某个测验只测量被试的某一种能力。
- 立性假设,即假设被试在每一个项目上的作答反应是相互独立,互不影响的,作答反应只与被试自身的能力水平有关,与其他元素无关。
- 模型假设,即被试在项目上的正确反应概率与被试的能力水平有一定的函数关系。
IRT有一参数、两参数、三参数模型,三参数模型的数学公式如下:
其中相关参数的定义如下:
参数 |
定义 | 解释 |
d | 常数1.702 | |
ai | 项目区分度系数 | 表示项目或题目的区分度,在曲线中影响曲线中部的斜率,当斜率越小,那么就很难将被试的测试分数结果区分开 |
bi | 项目难度系数 | 表示项目或题目的难度,在曲线中代表曲线横轴方向的位移,难度系数越大,则被试想要获得比较高的分数就需要比较高的能力 |
ci | 项目猜测系数 | 表示即使被试对测试的项目一点先验知识都没有,靠蒙也能蒙对的概率,比如选择题有0.25的概率才对 |
被试的能力值 | 表示被试在项目或题目所要考核的知识点或能力方面的掌握程度 | |
被试做对该项目的概率 |
IRT简化的一参数模型Rasch模型:
在Rasch模型中,所有的曲线,其形状都是一样的。实际上,这是不合理的。比如,有两道难度相同(比如难度等于2)的题目,一道是判断题,一道是选择题(4个选项)。对于判断题,即使学渣完全不知道怎么做,也有大约有50%概率能答对,而学霸也是50%左右的概率能答对。对于选择题,学渣大约有25%概率能答对,而学霸仍然是50%左右。因此,选择题比判断题能够更好的区分学霸和学渣,我们称它的区分度(discrimination)更高。
本次实验的数据来自于学生oj题目数据,所有题目都属于同一种类型,因此不需要引入区分度来进行区别。与此同时,蒙对一道oj题目的概率较小,因此猜测系数在本次实验中也不考虑。因此采用Rasch模型进行学生oj做题情况预测。
参数估计
IRT模型的参数估计方法有很多,包括极大似然估计,EM算法,贝叶斯算法等,本文将简单介绍使用极大似然估计方法进行参数估计过程。
- 极大似然函数
- 似然函数求对数
- 求导数(注意这里用的Rasch模型,只有难度系数一个参数)
- 梯度下降更新
其中表示学习率,pi表示预测值,yi表示实际值。
实验部分
定义Rasch模型函数:
def sigmoid(x,b):return 1.0/(1+np.exp(1.702*(-x+b)))
画出三种难度下的模型函数,其中横坐标为掌握程度,纵坐标为答对的概率
import matplotlib.pyplot as plt
x = np.linspace(0,2*np.pi,500)
y1 = sigmoid(x,1)
y2 = sigmoid(x,2)
y3 = sigmoid(x,3)plt.plot(x,y1,color = 'r',label = 'level1') #label每个plot指定一个字符串标签
plt.plot(x,y2,'-.', color = 'b', label = 'level2')
plt.plot(x,y3,'--', color = 'g', label = 'level3')plt.legend(loc='best')
plt.show()
梯度更新
#传入dataRecord为做题记录,classLabels为题目难度
def gradAscent(dataRecord,classLabels):dataRecord = np.array(dataRecord)classLabels = np.array(classLabels).transpose()alpha = 0.01maxCycles = 500weights = np.array([1])#通过broadcastfor k in range(maxCycles):h = sigmoid(weights,classLabels)error = (dataRecord - h)weights = weights + alpha*np.dot(classLabels.transpose(),error)return weights
模拟学生数据
data = {"格式化输入输出":{"做题记录":[0,0,1,0,1,0,1,0,0,0,1,1],"题目难度":[1,1,1,1,1,2,2,2,2,2,2,2]},"基本数据类型":{"做题记录":[1,0,0,1,0,1,0,0,1,1],"题目难度":[1,1,1,1,2,2,2,2,2,2]}}
计算结果
dataMat = data["格式化输入输出"]["做题记录"]
classLabel = data["格式化输入输出"]["题目难度"]
gradAscent(dataMat,classLabel)array([1.54495735])
问题发现
1.对于oj数据,经常会出现的情况是学生尝试同一道题目多次才能做对。在多次试错的过程中掌握程度会变得很低,因此就很难预测他在多次试错中做对。也即是说,IRT模型无法体现学生从错误中学习经验,从而做对的特点。
2.一个模型只能对一个学生的一个知识点进行建模,无法反映学生之间、知识点之间的关联。