# coding=utf-8
import numpy as np
def _gen_item_dt(items):
"""
生成试题字典,key为试题顺序,value为试题所在维度
:param items: list(int), 试题维度排列列表
:return: dict(int: int) 试题字典
"""
item_dt = {}
for i, item in enumerate(items):
item_dt[i] = item
return item_dt
[docs]def gen_item_bank(trait_size, item_size, block_size=3, lower=1, upper=4, avg=0, std=1):
"""
生成用于自适应测验的题库
:param trait_size: int
:param item_size: int
:param block_size: int
:param lower: int|float
:param upper: int|float
:param avg: int|float
:param std: int|float
:return:
"""
if not isinstance(trait_size, int):
raise ValueError('trait_size must be int')
if not isinstance(item_size, int):
raise ValueError('trait_size must be int')
if block_size not in (2, 3):
raise ValueError('block_size must be 2 or 3')
if not isinstance(lower, (int, float)):
raise ValueError('lower must be int or float')
if not isinstance(upper, (int, float)):
raise ValueError('upper must be int or float')
if not isinstance(avg, (int, float)):
raise ValueError('avg must be int or float')
if not isinstance(std, (int, float)):
raise ValueError('std must be int or float')
trait_list = range(trait_size)
item_bank = []
for i in range(item_size):
_item_list = np.random.choice(trait_list, block_size, False)
_item_dt = _gen_item_dt(_item_list)
params = random_params(_item_dt, trait_size, block_size=block_size, lower=lower, upper=upper, avg=avg, std=std)
item_bank.append({'dim': _item_list, 'params': params})
return np.array(item_bank)
def _pair_random_params(item_dt, trait_size, lower=1, upper=4, avg=0, std=1):
"""
生成block_size为2的多维随机斜率(区分度),和一维阈值(通俗度)
:param std: 多维正态分布的标准差
:param avg: 多维正态分布的期望值
:param item_dt: dict(int:int), 试题字典
:param trait_size: int,特质数量
:param lower: int(>0), uniform分布的下界
:param upper: int(>lower), uniform分布的上界
:return: tuple(ndarray, ndarray), 斜率和阈值
"""
keys = item_dt.keys()
pair_nums = len(keys) / 2
keys.sort()
a = np.zeros((pair_nums, trait_size))
a1 = np.random.uniform(lower, upper, pair_nums * 2)
a2 = np.random.uniform(lower, upper, pair_nums * 2)
for i in range(pair_nums):
i1 = item_dt[2 * i]
i2 = item_dt[2 * i + 1]
a[i][i1] = a1[i]
a[i][i2] = a2[2 * i] * -1
b = np.random.normal(avg, std, pair_nums)
return a, b
def _triplet_random_params(item_dt, trait_size, lower=1, upper=4, avg=0, std=1):
"""
生成block_size为3的多维随机斜率(区分度),和一维阈值(通俗度)
:param std: 多维正态分布的标准差
:param avg: 多维正态分布的期望值
:param item_dt: dict(int:int), 试题字典
:param trait_size: int,特质数量
:param lower: int(>0), uniform分布的下界
:param upper: int(>lower), uniform分布的上界
:return: tuple(ndarray, ndarray), 斜率和阈值
"""
keys = list(item_dt.keys())
pair_nums = len(keys)
keys.sort()
a = np.zeros((pair_nums, trait_size))
a1 = np.random.uniform(lower, upper, pair_nums)
a2 = np.random.uniform(lower, upper, pair_nums)
for i in range(int(len(keys) / 3)):
i1 = item_dt[3 * i]
i2 = item_dt[3 * i + 1]
i3 = item_dt[3 * i + 2]
a[3 * i][i1] = a1[3 * i]
a[3 * i][i2] = a2[3 * i] * -1
a[3 * i + 1][i1] = a1[3 * i + 1]
a[3 * i + 1][i3] = a2[3 * i + 1] * -1
a[3 * i + 2][i2] = a1[3 * i + 2]
a[3 * i + 2][i3] = a2[3 * i + 2] * -1
b = np.random.normal(avg, std, pair_nums)
return a, b
[docs]def random_params(item_dt, trait_size, block_size=3, lower=1, upper=4, avg=0, std=1):
"""
生成随机参数
:param item_dt: dict,试题字典,例如题块为3的0:1,1:0,2:2}代表第1题的第一个陈述测的是特质1,
第二个陈述测的是特质0,第三个陈述测的是特质2
:param trait_size: int
:param block_size: int
:param lower: int|float
:param upper: int|float
:param avg: int|float
:param std: int|float
:return:
"""
if not isinstance(item_dt, dict):
raise ValueError('item_dt must be dict')
if not isinstance(trait_size, int):
raise ValueError('trait_size must be int')
if block_size not in (2, 3):
raise ValueError('block_size must be 2 or 3')
if not isinstance(lower, (int, float)):
raise ValueError('lower must be int or float')
if not isinstance(upper, (int, float)):
raise ValueError('upper must be int or float')
if not isinstance(avg, (int, float)):
raise ValueError('avg must be int or float')
if not isinstance(std, (int, float)):
raise ValueError('std must be int or float')
if block_size == 3:
return _triplet_random_params(item_dt, trait_size, lower=lower, upper=upper, avg=avg, std=std)
elif block_size == 2:
return _pair_random_params(item_dt, trait_size, lower=lower, upper=upper, avg=avg, std=std)