Skip to content

Latest commit

 

History

21 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LBKT-Reading-Proficiency Banner

Table of Contents

  1. Overview
  2. Architecture
  3. Model Components
  4. Technical Specifications
  5. Data Format
  6. Installation
  7. Dependencies
  8. Quick Start
  9. Usage

1. Overview

The LBKT (Learning Behavior-aware Knowledge Tracing) model is designed to track learners' knowledge states by capturing the complex effects of multiple learning behaviors on the learning and forgetting process. The model focuses on three key learning behaviors:

  • Speed: How quickly learners respond to questions (quantified via time factors)
  • Attempts: Number of attempts made before success (quantified via attempts factors)
  • Hints: Usage of hints during learning (quantified via hints factors)

The model investigates how these behaviors individually and collectively affect knowledge acquisition and forgetting, providing a more nuanced understanding of learner proficiency through a sophisticated recurrent neural network architecture.

Folder PATH listing
+---assets                          <-- Contains static assets and images
│       banner.png                  <-- Project banner image
│
+---data                            <-- Contains datasets and data files
│       attempts_factor.json        <-- Attempts behavior factor data
│       hints_factor.json           <-- Hints behavior factor data
│       kc2index.json               <-- Knowledge component to index mapping
│       new_records.json            <-- New records data file
│       new_test_data.json          <-- Test dataset
│       new_train_data.json         <-- Training dataset
│       new_valid_data.json         <-- Validation dataset
│       q_matrix.json               <-- Q-matrix for topic-KC relationships
│       README.md                   <-- Documentation for data directory
│       time_factor.json            <-- Time behavior factor data
│       topic_attempts_para.json    <-- Topic attempts parameters
│       topic_count.json            <-- Topic count statistics
│       topic_hints_para.json       <-- Topic hints parameters
│       topic_time_para.json        <-- Topic time parameters
│       topic2index.json            <-- Topic to index mapping
│
+---data_processing                 <-- Contains data preprocessing scripts
│       data_preprocesing.ipynb     <-- Data preprocessing notebook
│       README.md                   <-- Documentation for data processing
│
+---src                             <-- Contains source code files
│       cell.py                     <-- LBKTcell implementation
│       data_helper.py              <-- Data loading and processing utilities
│       layer.py                    <-- Layer1 gated mechanism implementation
│       model.py                    <-- Recurrent model implementation
│       README.md                   <-- Documentation for source code
│       train.py                    <-- Training script
│
        .gitignore                  <-- Git exclusions
        LICENSE                     <-- License information
        README.md                   <-- Project overview and documentation
        requirements.txt            <-- Python dependencies

2. Architecture

The LBKT model implements a recurrent neural network architecture that processes sequences of learning interactions. The model consists of several key components working together to track knowledge states while accounting for learning behaviors.

2.1 High-Level Architecture

flowchart TD
    A[Input Data] --> B[Data Processing]
    B --> C["Topics Array<br/>Shape: batch_size × seq_len"]
    B --> D["Resps Array<br/>Shape: batch_size × seq_len"]
    B --> E["Time Factors<br/>Shape: batch_size × seq_len"]
    B --> F["Attempts Factors<br/>Shape: batch_size × seq_len"]
    B --> G["Hints Factors<br/>Shape: batch_size × seq_len"]
    B --> H["Masks Array<br/>Shape: batch_size × seq_len"]
    
    C --> I[Recurrent Model]
    D --> I
    E --> I
    F --> I
    G --> I
    H --> I
    
    I --> J["Topic Embedding<br/>dim_tp=128"]
    I --> K["Response Embedding<br/>dim_hidden=50"]
    J --> L["Interaction Embedding<br/>num_units=128"]
    K --> L
    
    L --> M[RNN with LBKTcell]
    E --> M
    F --> M
    G --> M
    I --> N["Q-Matrix Lookup<br/>Shape: batch_size × seq_len × memory_size"]
    N --> M
    
    M --> O["Knowledge State<br/>Shape: batch_size × seq_len × memory_size × num_units"]
    M --> P["Predictions<br/>Shape: batch_size × (seq_len-1) × 1<br/>(sliced from step 1 onwards)"]
    M --> Q["Improvements<br/>Shape: batch_size × seq_len × 1<br/>(includes initial state)"]
    
    style A fill:#e1f5ff
    style I fill:#fff4e1
    style M fill:#ffe1f5
    style P fill:#e1ffe1
    style Q fill:#e1ffe1
Loading

2.2 Core Architectural Modules

The LBKT architecture integrates three core modules that work together to model the complex dynamics of knowledge acquisition and retention:

2.2.1 Differentiated Behavior Effect Quantifying Module

This module isolates and quantifies the individual impact of each learning behavior (response speed, number of attempts, and hint usage) on knowledge acquisition. By processing each behavior type separately through specialized gated mechanisms, the model captures how different learning strategies affect knowledge gain independently before considering their interactions.

2.2.2 Fused Behavior Effect Measuring Module

This module models the synergistic and interactive effects of multiple behaviors working together. Rather than treating behaviors as independent, this module captures how combinations of behaviors (e.g., fast response with multiple attempts) create compound effects on learning that differ from the sum of individual effects. The fusion mechanism learns to weight and combine these interactions adaptively.

2.2.3 Knowledge State Update Module

This module integrates both learning (from behavior-affected knowledge acquisition) and forgetting (from time and interaction patterns) to update the learner's knowledge state. The forget gate dynamically balances retention of previous knowledge with incorporation of new learning gains, enabling the model to track knowledge evolution over extended learning sequences.

Module Integration: These three modules operate sequentially within each time step: (1) individual behavior effects are quantified, (2) they are fused to compute a unified learning gain, and (3) the knowledge state is updated by combining this gain with a forget gate that modulates retention of prior knowledge. This design allows the model to capture both immediate learning effects and long-term knowledge dynamics. For detailed implementation, see Section 3: Model Components.

3. Model Components

This section provides detailed implementation specifications for each component of the LBKT model. For a high-level overview of how these components work together, see Section 2.2: Core Architectural Modules.

3.1 Recurrent Model (model.py)

The Recurrent class is the main model wrapper that processes sequences of learning interactions. It orchestrates the embedding layers, input processing, and recurrent computation that form the foundation of the LBKT architecture.

Key Components:

  • Topic Embedding Layer: Embeds topic indices into dim_tp=128 dimensional vectors using GlorotNormal initialization
  • Response Embedding Layer: Embeds response values (0/1) into dim_hidden=50 dimensional vectors
  • Input Processing Layer: Dense layer with ReLU activation transforming concatenated embeddings to num_units=128
  • RNN Layer: Wraps LBKTcell with return_sequences=True for sequence processing
  • Initial Knowledge State: Learnable parameter init_h with shape (memory_size, num_units)

Forward Pass:

  1. Embed topics and responses: topic_emb (batch_size, seq_len, dim_tp), resps_emb (batch_size, seq_len, dim_hidden)
  2. Lookup Q-matrix correlation weights: correlation_weight (batch_size, seq_len, memory_size)
  3. Compute interaction embeddings: acts_emb = Dense(concat([topic_emb, resps_emb])) → (batch_size, seq_len, num_units)
  4. Expand behavior factors to (batch_size, seq_len, 1)
  5. Concatenate inputs: [acts_emb, correlation_weight, topic_emb, time_factor, attempt_factor, hint_factor]
  6. Process through RNN with initial state h_init (batch_size, memory_size, num_units)
  7. Split RNN output into predictions and improvements
  8. Return predictions starting from step 1 (skip initial state): preds[:, 1:] and improve (full sequence)

3.2 LBKTcell (cell.py)

The LBKTcell is the core recurrent cell that implements the three architectural modules described in Section 2.2. It processes learning behaviors and updates knowledge states through the differentiated behavior quantification, fused behavior measurement, and knowledge state update mechanisms.

Key Components:

  • Three Behavior Gain Layers: time_gain, attempt_gain, hint_gain (each Layer1 with num_units=128)
  • Fusion Weights: Three weight tensors with shape (r=4, num_units+1=129, num_units=128) for each behavior
  • Fusion Bias: Shape (1, num_units=128)
  • Fusion Matrix: Wf with shape (1, r=4)
  • Forget Gate: Dense layer with sigmoid activation
  • Output Layer: Dense layer with sigmoid activation for predictions
  • Dropout Layer: Applied to learning gain with rate dropout=0.2

Internal Architecture:

flowchart TD
    A["Input Concatenation"] --> B["Split Inputs"]
    B --> C["interact_emb<br/>Shape: batch × num_units"]
    B --> D["correlation_weight<br/>Shape: batch × memory_size"]
    B --> E["topic_emb<br/>Shape: batch × dim_tp"]
    B --> F["time_factor<br/>Shape: batch × 1"]
    B --> G["attempt_factor<br/>Shape: batch × 1"]
    B --> H["hint_factor<br/>Shape: batch × 1"]
    
    I["h_pre: Previous State<br/>Shape: batch × memory_size × num_units"] --> J["Weighted Knowledge State<br/>h_pre_tilde<br/>Shape: batch × num_units"]
    
    J --> K["Prediction Before Learning<br/>preds<br/>Shape: batch × 1"]
    
    C --> L["Time Gain Layer<br/>Layer1"]
    F --> L
    J --> L
    
    C --> M["Attempt Gain Layer<br/>Layer1"]
    G --> M
    J --> M
    
    C --> N["Hint Gain Layer<br/>Layer1"]
    H --> N
    J --> N
    
    L --> O["Fusion Time<br/>Shape: batch × r × num_units"]
    M --> P["Fusion Attempt<br/>Shape: batch × r × num_units"]
    N --> Q["Fusion Hint<br/>Shape: batch × r × num_units"]
    
    O --> R["Element-wise Multiply<br/>fusion_all<br/>Shape: batch × r × num_units"]
    P --> R
    Q --> R
    
    R --> S["Fusion Reduction<br/>Shape: batch × num_units"]
    
    S --> T["Learning Gain<br/>ReLU activation<br/>Shape: batch × num_units"]
    
    T --> U["Distribute to KCs<br/>LG<br/>Shape: batch × memory_size × num_units"]
    
    I --> V["Forget Gate<br/>sigmoid activation<br/>Shape: batch × memory_size × num_units"]
    C --> V
    F --> V
    G --> V
    H --> V
    
    U --> W["Apply Dropout<br/>rate = 0.2"]
    V --> X["Update Knowledge State<br/>h = h_pre × forget_gate + LG<br/>Shape: batch × memory_size × num_units"]
    W --> X
    
    X --> Y["Weighted New State<br/>h_tilde<br/>Shape: batch × num_units"]
    
    Y --> Z["Prediction After Learning<br/>after_preds<br/>Shape: batch × 1"]
    
    K --> AA["Improvement<br/>improve = (after_preds - preds) / (1 - preds)<br/>Shape: batch × 1"]
    Z --> AA
    
    K --> BB["Output<br/>preds, improve<br/>Shape: batch × 2"]
    AA --> BB
    
    style A fill:#e1f5ff
    style I fill:#fff4e1
    style T fill:#ffe1f5
    style X fill:#e1ffe1
    style BB fill:#e1ffe1
Loading

Mathematical Formulations:

  1. Weighted Knowledge State:

    $$\tilde{h}{pre} = \sum{i=1}^{memory_size} correlation_weight_i \cdot h_{pre,i}$$

    where $correlation_weight \in \mathbb{R}^{memory_size}$ is the Q-matrix correlation weight for the current topic (extracted from the Q-matrix based on the topic), $h_{pre} \in \mathbb{R}^{memory_size \times num_units}$ is the previous knowledge state, and the output shape is $(batch_size, num_units)$. This operation computes a weighted sum of knowledge components, where weights indicate the relevance of each knowledge component to the current topic.

  2. Prediction Before Learning:

    $$b_{out} = [\tilde{h}{pre}, e{topic}]$$

    $$preds = \frac{1}{num_units} \sum_{i=1}^{num_units} \sigma(W_{out} \cdot b_{out} + bias_{out})$$

    where $\sigma$ is the sigmoid activation, and the output shape is $(batch_size, 1)$.

  3. Behavior Gain (from Layer1):

    $$gate = k + \frac{1-k}{1 + e^{-d \cdot (factor - b)}}$$

    where $k=0.3$, $d=10$, $b=0.3$ are hyperparameters.

    $$w = \sigma\left(\left(W \cdot [h, e_{interact}] + b\right) \odot gate\right)$$

    where $\odot$ denotes element-wise multiplication, and the output shape is $(batch_size, num_units)$.

  4. Fusion Mechanism:

    $$gain_{time}^* = [gain_{time}, \mathbf{1}] \in \mathbb{R}^{num_units+1}$$

    $$fusion_{time} = gain_{time}^* \cdot W_{time} \in \mathbb{R}^{r \times num_units}$$

    $$fusion_{all} = fusion_{time} \odot fusion_{attempt} \odot fusion_{hint}$$

    $$learning_gain = ReLU\left(W_f \cdot transpose(fusion_{all}) + b_{fusion}\right)$$

    where $transpose(fusion_{all})$ transposes dimensions from $(batch_size, r, num_units)$ to $(r, batch_size, num_units)$ for matrix multiplication with $W_f \in \mathbb{R}^{1 \times r}$, $r=4$ is the fusion rank, and the output shape is $(batch_size, num_units)$.

  5. Knowledge State Update:

    $$LG_{i,j} = correlation_weight_i \cdot learning_gain_j$$

    where $i$ indexes knowledge components and $j$ indexes hidden units, resulting in shape $(batch_size, memory_size, num_units)$.

    $$forget_gate = \sigma\left(W_{forget} \cdot [h_{pre}, e_{interact}, \text{tile}(time_factor), \text{tile}(attempt_factor), \text{tile}(hint_factor)] + b_{forget}\right)$$

    where the input to the forget gate Dense layer is the concatenation of:

    • $h_{pre} \in \mathbb{R}^{memory_size \times num_units}$ (previous knowledge state)
    • $e_{interact}$ tiled to $\mathbb{R}^{memory_size \times num_units}$ (interaction embedding)
    • Behavior factors tiled to $\mathbb{R}^{memory_size \times dim_hidden}$ (where $dim_hidden=50$)

    The total input dimension is $(2 \cdot num_units + 3 \cdot dim_hidden)$, and the output shape is $(batch_size, memory_size, num_units)$.

    $$h = h_{pre} \odot forget_gate + Dropout(LG)$$

    where the output shape is $(batch_size, memory_size, num_units)$.

  6. Improvement Metric:

    $$improve = \frac{preds_{after} - preds_{before}}{1 - preds_{before}}$$

    where the output shape is $(batch_size, 1)$.

3.3 Layer1 (layer.py)

The Layer1 class implements the gated mechanism for the Differentiated Behavior Effect Quantifying Module. It processes individual behavior factors (time, attempts, hints) to compute behavior-specific learning gains that are subsequently fused in the LBKTcell.

Parameters:

  • num_units: Number of hidden units (default: 128)
  • d: Steepness parameter for sigmoid gate (default: 10)
  • k: Minimum gate value (default: 0.3)
  • b: Bias parameter for sigmoid gate (default: 0.3)

Architecture:

  • Weight Matrix: Shape (2 * num_units, num_units) with GlorotNormal initialization and L2 regularization

  • Bias Vector: Shape (1, num_units) with GlorotNormal initialization and L2 regularization

  • Gate Formula:

    $$gate = k + \frac{1-k}{1 + e^{-d \cdot (factor - b)}}$$

    where $k=0.3$, $d=10$, and $b=0.3$ are hyperparameters.

  • Activation: Sigmoid applied to the gated linear transformation:

    $$w = \sigma\left(\left(W \cdot [h, e_{interact}] + b\right) \odot gate\right)$$

    where $\sigma$ is the sigmoid function and $\odot$ denotes element-wise multiplication.

Forward Pass:

  1. Compute sigmoid gate based on behavior factor
  2. Concatenate previous knowledge state h and interaction embedding interact_emb
  3. Apply linear transformation: w = concat([h, interact_emb]) @ weight + bias
  4. Modulate with gate: w = sigmoid(w * gate)
  5. Return gated output

4. Technical Specifications

4.1 Code Workflow

The codebase follows this modular structure:

flowchart TD
    A[train.py] --> B[LBKT Class]
    A --> C[Data Loading Functions]
    
    C --> D["form_data<br/>data_helper.py"]
    C --> E["fit_batch<br/>data_helper.py"]
    
    B --> F["Recurrent Model<br/>model.py"]
    
    F --> G["Embedding Layers<br/>Topic: dim_tp=128<br/>Response: dim_hidden=50"]
    F --> H["Input Processing Layer<br/>Dense: num_units=128"]
    F --> I["RNN Layer<br/>LBKTcell"]
    
    I --> J["LBKTcell<br/>cell.py"]
    
    J --> K["Layer1: time_gain<br/>layer.py"]
    J --> L["Layer1: attempt_gain<br/>layer.py"]
    J --> M["Layer1: hint_gain<br/>layer.py"]
    
    J --> N["Fusion Mechanism<br/>Rank r=4"]
    J --> O["Forget Gate<br/>Dense + Sigmoid"]
    J --> P["Output Layer<br/>Dense + Sigmoid"]
    
    B --> Q["Training Loop<br/>train_one_epoch"]
    B --> R["Validation Loop<br/>test_one_epoch"]
    
    Q --> S["Loss Computation<br/>BinaryCrossentropy"]
    Q --> T["Optimizer<br/>Adam + InverseTimeDecay"]
    
    R --> U["Metrics Computation<br/>AUC, Accuracy, RMSE"]
    
    style A fill:#e1f5ff
    style F fill:#fff4e1
    style J fill:#ffe1f5
    style K fill:#e1ffe1
    style L fill:#e1ffe1
    style M fill:#e1ffe1
Loading

4.2 Tensor Shapes

Input Shapes:

  • Topics: (batch_size, seq_len) where seq_len=100 (pad_len)
  • Resps: (batch_size, seq_len)
  • Masks: (batch_size, seq_len)
  • time_factor: (batch_size, seq_len)
  • attempts_factor: (batch_size, seq_len)
  • hints_factor: (batch_size, seq_len)

Embedding Shapes:

  • topic_emb: (batch_size, seq_len, dim_tp=128)
  • resps_emb: (batch_size, seq_len, dim_hidden=50)
  • acts_emb: (batch_size, seq_len, num_units=128)
  • correlation_weight: (batch_size, seq_len, memory_size)

State Shapes:

  • h_init: (batch_size, memory_size, num_units=128)
  • h_pre: (batch_size, memory_size, num_units=128)
  • h: (batch_size, memory_size, num_units=128)
  • h_pre_tilde: (batch_size, num_units=128)

Output Shapes:

  • preds: (batch_size, seq_len-1, 1) (sliced from step 1 onwards, skipping initial state)
  • improve: (batch_size, seq_len, 1) (includes all time steps including initial state)
  • RNN internal output: (batch_size, seq_len, 2) (concatenated preds and improve before slicing)

4.3 Hyperparameters Summary

Category Parameter Value Location
Model Architecture num_units 128 train.py, cell.py
dim_tp 128 train.py, model.py
dim_hidden 50 train.py, model.py
memory_size Variable (from kc2index) train.py
num_resps 2 train.py
dropout 0.2 train.py, cell.py
Sequence Processing pad_len 100 train.py, data_helper.py
BATCH_SIZE 16 (default) train.py
Training EPOCHS 100 train.py
lr 0.005 (default) train.py
q_factor 0.01 (default) train.py
patience 5 train.py
min_delta 0.000001 train.py
decay_rate 0.5 train.py
Layer1 Parameters d 10 layer.py
k 0.3 layer.py
b 0.3 layer.py
Fusion Mechanism r (rank) 4 cell.py

4.4 Key Formulas

  1. Q-Matrix Smoothing:

    $$Q = (1 - \alpha) \cdot Q_{original} + \alpha \cdot \mathbf{1}$$

    where $\alpha = q_factor$ (default: 0.01) is the smoothing factor, and $\mathbf{1}$ is a matrix of ones with the same shape as $Q_{original}$.

  2. Sigmoid Gate (Layer1):

    $$gate = k + \frac{1-k}{1 + e^{-d \cdot (factor - b)}}$$

    where $k=0.3$, $d=10$, and $b=0.3$ are hyperparameters controlling the gate's behavior.

  3. Prediction:

    $$preds = \frac{1}{num_units} \sum_{i=1}^{num_units} \sigma\left(W_{out} \cdot [\tilde{h}, e_{topic}] + b_{out}\right)$$

    where $\sigma$ is the sigmoid activation function, $\tilde{h}$ is the weighted knowledge state, and $e_{topic}$ is the topic embedding.

  4. Improvement:

    $$improve = \frac{preds_{after} - preds_{before}}{1 - preds_{before}}$$

    This metric quantifies the relative improvement in prediction after learning compared to before learning.

  5. Knowledge State Update:

    $$h^{(t)} = h^{(t-1)} \odot f_{gate} + Dropout(LG^{(t)})$$

    where $f_{gate}$ is the forget gate, $LG^{(t)}$ is the distributed learning gain, and $\odot$ denotes element-wise multiplication.

  6. Learning Rate Schedule:

    $$lr(t) = \frac{lr_0}{1 + \rho \cdot \frac{t}{decay_steps}}$$

    where $\rho = 0.5$ is the decay rate, $t$ is the current training step, and $decay_steps$ is the number of steps per epoch.

5. Data Format

5.1 Input Data Structure

The model expects JSON files with the following structure:

Training/Validation/Test Data (new_train_data.json, new_valid_data.json, new_test_data.json):

{
  "user_id_1": [
    [topic_id, response, correctness, timestamp, answer_time, attempts, hints],
    [topic_id, response, correctness, timestamp, answer_time, attempts, hints],
    ...
  ],
  "user_id_2": [...],
  ...
}

Field Descriptions:

  • topic_id: Identifier for the topic/exercise (integer)
  • response: Response value (typically 0 or 1, integer)
  • correctness: Whether the answer was correct (integer, 0 or 1)
  • timestamp: When the interaction occurred (numeric)
  • answer_time: Time taken to answer (numeric)
  • attempts: Number of attempts made (integer)
  • hints: Number of hints used (integer)

Behavior Factor Files (time_factor.json, attempts_factor.json, hints_factor.json):

{
  "user_id_1": [factor_value_1, factor_value_2, ...],
  "user_id_2": [factor_value_1, factor_value_2, ...],
  ...
}

Factor values are normalized and represent the behavior's effect on learning. The length of each factor array must match the number of interactions for that user.

Mapping Files:

  • topic2index.json: Maps topic IDs (as strings) to numerical indices
    {
      "topic_id_1": 0,
      "topic_id_2": 1,
      ...
    }
  • kc2index.json: Maps knowledge component IDs to numerical indices
    {
      "kc_id_1": 0,
      "kc_id_2": 1,
      ...
    }
  • q_matrix.json: Q-matrix representing topic-KC relationships (2D array)
    [
      [1, 0, 1, ...],  // Topic 0 requires KCs 0 and 2
      [0, 1, 1, ...],  // Topic 1 requires KCs 1 and 2
      ...
    ]
    Shape: (num_topics, num_kcs), values typically 0 or 1 (or probabilities)

5.2 Data Processing Pipeline

The data processing follows this workflow:

flowchart TD
    A[Load JSON Files] --> B[Read User Records]
    B --> C[Extract Sequences per User]
    
    C --> D["Map Topic IDs to Indices<br/>topic2index"]
    C --> E["Extract Fields<br/>topics, resps, atime, attempts, hints"]
    C --> F["Load Behavior Factors<br/>time_factor, attempts_factor, hints_factor"]
    
    D --> G{"Sequence Length > pad_len?"}
    E --> G
    F --> G
    
    G -->|Yes| H["Split into Multiple Sequences<br/>Each of length pad_len"]
    G -->|No| I{"Remaining Length >= 10?"}
    
    H --> J["Create Full Sequences<br/>Masks = all 1s"]
    H --> K[Update Remaining Length]
    K --> I
    
    I -->|Yes| L["Pad Remaining Sequence<br/>Add zeros to reach pad_len"]
    I -->|No| M[Discard Sequence]
    
    L --> N["Create Mask<br/>1s for valid, 0s for padding"]
    
    J --> O[Convert to NumPy Arrays]
    N --> O
    
    O --> P["Topics: int32<br/>Shape: n_sequences × pad_len"]
    O --> Q["Resps: int32<br/>Shape: n_sequences × pad_len"]
    O --> R["AnswerTime: float<br/>Shape: n_sequences × pad_len"]
    O --> S["Attempts: int32<br/>Shape: n_sequences × pad_len"]
    O --> T["Hints: int32<br/>Shape: n_sequences × pad_len"]
    O --> U["Masks: int32<br/>Shape: n_sequences × pad_len"]
    O --> V["Time_Factor: float<br/>Shape: n_sequences × pad_len"]
    O --> W["Attempts_Factor: float<br/>Shape: n_sequences × pad_len"]
    O --> X["Hints_Factor: float<br/>Shape: n_sequences × pad_len"]
    
    P --> Y["fit_batch: Ensure Batch Divisibility"]
    Q --> Y
    R --> Y
    S --> Y
    T --> Y
    U --> Y
    V --> Y
    W --> Y
    X --> Y
    
    Y --> Z["Add Zero-Padded Sequences<br/>Until len % batch_size == 0"]
    Z --> AA[Return Processed Data]
    
    style A fill:#e1f5ff
    style G fill:#fff4e1
    style O fill:#ffe1f5
    style Y fill:#e1ffe1
Loading

Processing Details:

  1. Sequence Splitting: Sequences longer than pad_len=100 are split into multiple sequences of length 100
  2. Padding: Remaining sequences shorter than pad_len are padded with zeros to reach pad_len
  3. Filtering: Sequences with remaining length < 10 after splitting are discarded
  4. Masking: Masks indicate valid positions (1) vs padding (0)
  5. Batch Fitting: Additional zero-padded sequences are added to ensure dataset size is divisible by batch size

For detailed data format specifications, see data/README.md.

6. Installation

6.1 Prerequisites

  • Python 3.7 or higher
  • pip package manager

6.2 Setup

  1. Clone the repository:
git clone <repository-url>
cd Reading-Proficiency-LBKT
  1. Create a virtual environment (recommended):
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
  1. Install dependencies:
pip install -r requirements.txt
  1. Install EduData (if needed for data preprocessing):
pip install EduData

Note: For more information about EduData, visit: https://github.com/bigdata-ustc/EduData

7. Dependencies

Core dependencies (see requirements.txt for versions):

  • TensorFlow (>=2.10.0, <3.0.0): Deep learning framework
  • NumPy (>=1.21.0): Numerical computing
  • SciPy (>=1.7.0): Scientific computing
  • scikit-learn (>=1.0.0): Machine learning utilities (metrics)
  • pandas (>=1.3.0): Data manipulation
  • tqdm (>=4.62.0): Progress bars
  • Jupyter (>=1.0.0): Notebook support
  • ipykernel (>=6.0.0): Jupyter kernel support

Note: EduData package may need to be installed separately for data preprocessing. Refer to: https://github.com/bigdata-ustc/EduData

8. Quick Start

  1. Ensure your data is preprocessed and placed in the data/ directory (see Data Format)

  2. Run training:

cd src
python train.py --batch_size 16 --lrate 0.005 --q_factor 0.01
  1. The model will automatically:
    • Train on the training set
    • Validate on the validation set (with early stopping)
    • Evaluate on the test set
    • Save the best model checkpoint to data/checkpoints/LBKT_assist2009/

9. Usage

9.1 Training Parameters

The training script accepts the following command-line arguments:

  • --batch_size or -bs: Batch size for training (default: 16)
  • --lrate or -lr: Learning rate (default: 0.005)
  • --q_factor or -qf: Q-matrix factor for smoothing (default: 0.01)

9.2 Example Commands

Basic training with default parameters:

python train.py

Custom parameters:

python train.py --batch_size 32 --lrate 0.01 --q_factor 0.02

9.3 Model Configuration

Key hyperparameters defined in train.py:

Parameter Default Value Description
pad_len 100 Maximum sequence length for padding/truncation
dim_tp 128 Topic embedding dimension
num_resps 2 Number of response types (correct/incorrect)
num_units 128 Number of hidden units in RNN cell
dropout 0.2 Dropout rate for regularization
dim_hidden 50 Response embedding dimension
EPOCHS 100 Maximum number of training epochs
BATCH_SIZE 16 Batch size (configurable via CLI)
lr 0.005 Learning rate (configurable via CLI)
q_factor 0.01 Q-matrix smoothing factor (configurable via CLI)

9.4 Training Process

The training process follows this workflow:

flowchart TD
    A[Start Training] --> B[Load Data Files]
    B --> C["form_data: Process Sequences"]
    C --> D["Split Long Sequences<br/>pad_len=100"]
    C --> E["Pad Short Sequences<br/>Discard if length < 10"]
    D --> F["fit_batch: Ensure Batch Divisibility"]
    E --> F
    
    F --> G[Initialize Model]
    G --> H[Load Q-Matrix]
    H --> I["Apply Q-Matrix Smoothing<br/>Q = (1-α)Q + α·1"]
    
    I --> J[Create LBKT Model Instance]
    J --> K["Initialize Optimizer<br/>Adam with InverseTimeDecay<br/>decay_rate=0.5"]
    
    K --> L["Training Loop: Epoch 0 to EPOCHS-1"]
    
    L --> M[Shuffle Training Data]
    M --> N[Batch Iteration]
    
    N --> O["Forward Pass<br/>recurrent.call"]
    O --> P["Compute Loss<br/>BinaryCrossentropy with sample weights"]
    P --> Q[Backward Pass<br/>Compute Gradients]
    Q --> R["Update Parameters<br/>optimizer.apply_gradients"]
    
    R --> S{More Batches?}
    S -->|Yes| N
    S -->|No| T["Compute Training Metrics<br/>Loss, AUC, Accuracy"]
    
    T --> U[Validation Loop]
    U --> V[Forward Pass on Validation Set]
    V --> W["Compute Validation Metrics<br/>Loss, AUC, Accuracy, RMSE"]
    
    W --> X{Validation AUC Improved?}
    X -->|Yes| Y["Save Model Checkpoint<br/>best_test_auc = valid_auc<br/>count = 0"]
    X -->|No| Z{"Check Early Stopping<br/>valid_auc - best_test_auc < min_delta?"}
    
    Z -->|Yes| AA[Increment Count]
    Z -->|No| AB[Reset Count to 0]
    
    AA --> AC{"Count >= Patience=5?"}
    AC -->|Yes| AD["Early Stopping<br/>Break Training Loop"]
    AC -->|No| AE{More Epochs?}
    
    AB --> AE
    Y --> AE
    
    AE -->|Yes| L
    AE -->|No| AF[Load Best Checkpoint]
    AD --> AF
    
    AF --> AG[Test Evaluation]
    AG --> AH[Forward Pass on Test Set]
    AH --> AI["Compute Test Metrics<br/>Loss, AUC, Accuracy, RMSE"]
    
    AI --> AJ[Print Results]
    AJ --> AK[End]
    
    style A fill:#e1f5ff
    style J fill:#fff4e1
    style L fill:#ffe1f5
    style Y fill:#e1ffe1
    style AD fill:#ffe1e1
    style AI fill:#e1ffe1
Loading

Training Details:

  1. Loss Function: Binary Cross-Entropy with reduction='sum' and sample weights from masks

    $$L_{total} = \sum_{i=1}^{N} mask_i \cdot \left[y_i \log(\hat{y}_i) + (1-y_i) \log(1-\hat{y}_i)\right]$$

    $$L_{batch} = \frac{L_{total}}{N_{valid}}$$

    where $N_{valid}$ is the number of valid (non-padded) samples in the batch.

  2. Optimizer: Adam with Inverse Time Decay learning rate schedule

    $$lr(t) = \frac{lr_0}{1 + \rho \cdot \frac{t}{decay_steps}}$$

    where $\rho = 0.5$ is the decay rate, $t$ is the current step, and $decay_steps$ is the number of steps per epoch.

  3. Early Stopping:

    • Patience: 5 epochs
    • Minimum delta: 0.000001
    • Monitors validation AUC
    • Saves best model based on validation AUC
  4. Evaluation Metrics:

    • AUC: Area Under ROC Curve using sklearn.metrics.roc_auc_score
    • Accuracy: Binary classification accuracy with threshold at 0.5
    • RMSE: Root Mean Squared Error using sklearn.metrics.mean_squared_error with squared=False
    • Loss: Binary Cross-Entropy computed as target * log(pred) + (1-target) * log(1-pred)

9.5 Output

The model outputs:

  • Training loss (Binary Cross-Entropy) per epoch
  • Validation metrics per epoch: AUC, Accuracy, RMSE
  • Test metrics (final): Loss, AUC, Accuracy, RMSE
  • Model checkpoints saved in data/checkpoints/LBKT_assist2009/

About

TensorFlow implementation of Learning Behavior-aware Knowledge Tracing for modeling reading proficiency using response time, attempts, and hint behavior.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Used by

Contributors

Languages