Vaadake ridade kaupa läbi veebi/lib/bkt.ts
Sukelduge põhjalikult teemasse web/lib/bkt.ts.
Eesmärk: avage fail ja tehke iga otsus ~10 minuti jooksul.
Import ja konstandid
Jaotis «Import ja konstandid»import { BktParams, DEFAULT_BKT, MicroSkill, MicroSkillId, StudentState, Task,} from "./microskills";„DEFAULT_BKT” koondab kirjanduse vaikeväärtused (P(L_0)=0,2, P(T)=0,1, P(S)=0,1, P(G)=0,2). Funktsioonid aktsepteerivad valikulisi parameetreid, nii et testid/vidinad kohandavad käitumist ilma allkirjade katkemiseta.
pSolve — ennustusvalem
Jaotis «pSolve — ennustusvalem»export function pSolve(pL: number, params: BktParams = DEFAULT_BKT): number { return pL * (1 - params.pSlip) + (1 - pL) * params.pGuess;}Üks rida – kogu P(lahendada) arvutus (peatükk 8). Numbriliselt taltsas (pole jaotust/logisid), mida nimetatakse tugevalt punktiarvestussilmusteks – hoidke pingul.
bktUpdate – Bayesi tuum
Jaotis «bktUpdate – Bayesi tuum»export function bktUpdate( pL: number, observedCorrect: boolean, params: BktParams = DEFAULT_BKT): number { const { pSlip, pGuess, pTransit } = params; const posterior = observedCorrect ? (pL * (1 - pSlip)) / (pL * (1 - pSlip) + (1 - pL) * pGuess) : (pL * pSlip) / (pL * pSlip + (1 - pL) * (1 - pGuess)); return posterior + (1 - posterior) * pTransit;}BKT süda. Ternaarne hoiab oksad tihedana; samaväärne “kui/muidu” oleks õhupall.
Arvuline ohutus: nimetajad jäävad , puhul positiivseks – 0/0 pole.
ensureMastery — laisk lähtestamine
Jaotis «ensureMastery — laisk lähtestamine»export function ensureMastery( state: StudentState, skillId: MicroSkillId, params: BktParams = DEFAULT_BKT): number { const cur = state.mastery[skillId]; if (cur === undefined) { state.mastery[skillId] = params.pInit; return params.pInit; } return cur;}Esimene kohtumine oskusega seemned pInit. Muteerib olek sihilikult – soojuskaardid/kasutajaliides vajavad konkreetseid numbreid, mitte defineerimata.
Alternatiivne muutumatu cur?? pInit lükkab raamatupidamise väljapoole – esimese puudutusega muteerumine jääb lihtsamaks.
applyAttempt — katsejärgne värskendus
Jaotis «applyAttempt — katsejärgne värskendus»export function applyAttempt( state: StudentState, task: Task, correct: boolean, perSkill?: Record<MicroSkillId, boolean>, params: BktParams = DEFAULT_BKT): StudentState { for (const skillId of task.microskills) { const observed = perSkill?.[skillId] ?? correct; const prior = ensureMastery(state, skillId, params); state.mastery[skillId] = bktUpdate(prior, observed, params); } state.history.push({ task_id: task.id, correct, per_skill: perSkill, ts: new Date().toISOString(), }); return state;}“perSkill” vastab:
Õpilane ei suutnud probleemi lahendada – millised mikrooskused ebaõnnestusid?
Sammutasandi jäädvustamine (tahvelarvuti töövoog / skanner) võimaldavad lahtris expand_brackets positiivseid tulemusi, karistades samas arith.signsi – palju teravamalt kui ühtsed +/- värskendused.
Varundus ilma perSkillita: ühtne signaal – MVP sans skanneri jaoks sobib.
history.push võimaldab navigeerimist, auditiloge ja kordusvastast heuristikat.
scoreTaskForStudent — valija tuum
Jaotis «scoreTaskForStudent — valija tuum»export function scoreTaskForStudent( state: StudentState, task: Task, opts: SelectorOptions = {}, params: BktParams = DEFAULT_BKT): ScoredTask { const target = opts.target ?? 0.7; const rareBonus = opts.rareSkillBonus ?? 0.15;
// Per-skill P(solve), then take the geometric mean as the joint — // a task fails if *any* required skill fails, so geo-mean penalises // missing one skill more than arithmetic mean. const perSkillPL: Record<MicroSkillId, number> = {}; let logSum = 0; for (const skillId of task.microskills) { const pL = state.mastery[skillId] ?? params.pInit; perSkillPL[skillId] = pL; logSum += Math.log(Math.max(1e-6, pSolve(pL, params))); } const pSolveJoint = Math.exp(logSum / task.microskills.length);
// Closeness to target — Gaussian-ish, peaks at target=0.7 const closeness = Math.exp(-Math.pow(pSolveJoint - target, 2) / 0.03);
// Rarity bonus: how many of this task's skills are below 0.4? const undertrained = task.microskills.filter( (s) => (state.mastery[s] ?? params.pInit) < 0.4 ).length; const rarity = undertrained / task.microskills.length;
const score = closeness + rareBonus * rarity;
return { task, pSolve: pSolveJoint, perSkillPL, score };}Tihe plokk — lahti pakkida sektsioonide kaupa.
sihtmärk = 0,7
Jaotis «sihtmärk = 0,7»ZPD bullseye (peatükk 8). Katsetamisel alistamine valiku „opts” kaudu.
`Math.max(1e-6, pSolve(pL, params))
Jaotis «`Math.max(1e-6, pSolve(pL, params))»Valvurid Math.log(0). Reaalsed jooksud jõuavad harva nulli tänu pGuess > 0le, kuid klamber on odav kindlustus.
Geomeetriline keskmine logide kaudu
Jaotis «Geomeetriline keskmine logide kaudu»logSum = Σ log(P_i)GM = exp(logSum / n)Eelised:
- väldib korrutavat allavoolu suurte n-de korral;
- vastab IRT laiendustest tuttavatele logi-keskmistele mõõdikutele.
Gaussi lähedus
Jaotis «Gaussi lähedus»closeness = exp(-(p - 0.7)^2 / 0.03)Width 0,03 arutelu — peatükk 8.
Alternatiivid:
1 - |p - 0,7|— lineaarne, nõrk kontrast sihtmärgi lähedal;- Lorentzian - pehmemad sabad.
Gaussi joon jääb adaptiivse testimise kirjanduses sujuvaks, sümmeetriliseks ja tavapäraseks.
Harulduse boonus — uurimine
Jaotis «Harulduse boonus — uurimine»rarity = (#skills with P(L) < 0.4) / (#skills required)score = closeness + rareBonus * rarityIlma selleta püsivad valijad mugavustsoonides.
„rareBonus = 0,15” tasakaalustab uurimise ja pettumuse (valija peatükk).
Tagastage kasulik koormus
Jaotis «Tagastage kasulik koormus»return { task, pSolve: pSolveJoint, perSkillPL, score };“perSkillPL” voogude selgitatavus koopia.
soovita — lõplik tellimine
Jaotis «soovita — lõplik tellimine»export function recommend( state: StudentState, pool: Task[], topN = 5, opts?: SelectorOptions, params?: BktParams): ScoredTask[] { const recentIds = new Set( state.history.slice(-5).map((h) => h.task_id) ); const scored = pool .filter((t) => !recentIds.has(t.id)) .map((t) => scoreTaskForStudent(state, t, opts, params)); scored.sort((a, b) => b.score - a.score); return scored.slice(0, topN);}Eemaldage viimased viis ülesande ID-d – kordumise vastane:
- identsete asjade kordamine tüütab õpilasi;
- viieastmeline aken tasakaalustab uudsuse ja katvuse.
Alternatiivne eksponentsiaalne lagunemine:
const recencyPenalty = recent.findIndex(h => h.task_id === t.id);score *= recencyPenalty < 0 ? 1 : Math.exp(-recencyPenalty / 3);Raskem seletada; MVP ei vaja seda.
Alumine rida
Jaotis «Alumine rida»~150 rida. Null raskekaalu deps (ainult jagatud tüübid). Selgesõnalised valemid – läbipaistmatud sklearn-virnad puuduvad.
See on tahtlik – iga otsus on õpetajate ja välise auditooriumi jaoks sõnaliselt kaitstav.