Spaces:
Sleeping
Sleeping
work-sejal commited on
Commit ·
11c4b38
1
Parent(s): 2657667
Add artifacts/models to HF Space repo and fix ignore rules
Browse files- artifacts/models/answer_scorer/.gitkeep +0 -0
- artifacts/models/answer_scorer/metrics.json +45 -0
- artifacts/models/answer_scorer/model.joblib +3 -0
- artifacts/models/answer_scorer/model_card.md +51 -0
- artifacts/models/answer_scorer/training_config.json +26 -0
- artifacts/models/answer_scorer/vectorizer.joblib +3 -0
- artifacts/models/bloom_classifier/.gitkeep +0 -0
- artifacts/models/bloom_classifier/label_encoder.joblib +3 -0
- artifacts/models/bloom_classifier/metrics.json +204 -0
- artifacts/models/bloom_classifier/model.joblib +3 -0
- artifacts/models/bloom_classifier/model_card.md +47 -0
- artifacts/models/bloom_classifier/training_config.json +28 -0
- artifacts/models/bloom_classifier/vectorizer.joblib +3 -0
- artifacts/models/difficulty_model/encoder.joblib +3 -0
- artifacts/models/difficulty_model/feature_columns.json +6 -0
- artifacts/models/difficulty_model/metrics.json +38 -0
- artifacts/models/difficulty_model/model.joblib +3 -0
- artifacts/models/difficulty_model/model_card.md +50 -0
- artifacts/models/difficulty_model/training_config.json +33 -0
- artifacts/models/lo_tagger/.gitkeep +0 -0
- artifacts/models/lo_tagger/label_encoder.joblib +3 -0
- artifacts/models/lo_tagger/metrics.json +0 -0
- artifacts/models/lo_tagger/model.joblib +3 -0
- artifacts/models/lo_tagger/model_card.md +50 -0
- artifacts/models/lo_tagger/training_config.json +27 -0
- artifacts/models/lo_tagger/vectorizer.joblib +3 -0
- artifacts/models/mastery_model/.gitkeep +0 -0
- artifacts/models/mastery_model/feature_columns.json +11 -0
- artifacts/models/mastery_model/metrics.json +132 -0
- artifacts/models/mastery_model/model.joblib +3 -0
- artifacts/models/mastery_model/model_card.md +56 -0
- artifacts/models/mastery_model/training_config.json +35 -0
- artifacts/models/recommender/.gitkeep +0 -0
- artifacts/models/recommender/encoder.joblib +3 -0
- artifacts/models/recommender/feature_columns.json +7 -0
- artifacts/models/recommender/metrics.json +33 -0
- artifacts/models/recommender/model.joblib +3 -0
- artifacts/models/recommender/model_card.md +53 -0
- artifacts/models/recommender/training_config.json +39 -0
- artifacts/models/risk_model/.gitkeep +0 -0
- artifacts/models/risk_model/feature_columns.json +21 -0
- artifacts/models/risk_model/metrics.json +101 -0
- artifacts/models/risk_model/model.joblib +3 -0
- artifacts/models/risk_model/model_card.md +71 -0
- artifacts/models/risk_model/training_config.json +44 -0
artifacts/models/answer_scorer/.gitkeep
ADDED
|
File without changes
|
artifacts/models/answer_scorer/metrics.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_name": "answer_scorer",
|
| 3 |
+
"model_version": "answer_scorer_v2_baseline_001",
|
| 4 |
+
"dataset_version": "2.0.0",
|
| 5 |
+
"trained_at": "2026-05-22T05:33:11.363132+00:00",
|
| 6 |
+
"seed": 20260520,
|
| 7 |
+
"split_counts": {
|
| 8 |
+
"train": 8371,
|
| 9 |
+
"validation": 1820,
|
| 10 |
+
"test": 1809
|
| 11 |
+
},
|
| 12 |
+
"metrics": {
|
| 13 |
+
"validation": {
|
| 14 |
+
"mae": 0.4787,
|
| 15 |
+
"rmse": 0.773,
|
| 16 |
+
"r_squared": 0.718,
|
| 17 |
+
"distribution": {
|
| 18 |
+
"predicted_mean": 1.8303,
|
| 19 |
+
"predicted_std": 0.9736,
|
| 20 |
+
"actual_mean": 2.0455,
|
| 21 |
+
"actual_std": 1.4557
|
| 22 |
+
},
|
| 23 |
+
"pct_above_review_threshold": 16.87
|
| 24 |
+
},
|
| 25 |
+
"test": {
|
| 26 |
+
"mae": 0.5256,
|
| 27 |
+
"rmse": 0.8385,
|
| 28 |
+
"r_squared": 0.6791,
|
| 29 |
+
"distribution": {
|
| 30 |
+
"predicted_mean": 1.8985,
|
| 31 |
+
"predicted_std": 0.9581,
|
| 32 |
+
"actual_mean": 2.174,
|
| 33 |
+
"actual_std": 1.4803
|
| 34 |
+
},
|
| 35 |
+
"pct_above_review_threshold": 19.68
|
| 36 |
+
}
|
| 37 |
+
},
|
| 38 |
+
"limitations": [
|
| 39 |
+
"Trained on synthetic data only.",
|
| 40 |
+
"TF-IDF features do not capture deep semantic similarity.",
|
| 41 |
+
"Predictions clipped to [0, max_marks] range.",
|
| 42 |
+
"teacher_review_required is always True in V2 baseline.",
|
| 43 |
+
"MAE is the primary metric; individual predictions may deviate significantly."
|
| 44 |
+
]
|
| 45 |
+
}
|
artifacts/models/answer_scorer/model.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9f526fa2fd7fdd63a024d3c47d7259efbd85fd8133b0ea12cfc070dc0194109d
|
| 3 |
+
size 8524
|
artifacts/models/answer_scorer/model_card.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Model Card: Answer Scorer
|
| 2 |
+
|
| 3 |
+
## Model Details
|
| 4 |
+
|
| 5 |
+
- **Model Name:** answer_scorer
|
| 6 |
+
- **Model Version:** answer_scorer_v2_baseline_001
|
| 7 |
+
- **Algorithm:** TF-IDF + Ridge Regression
|
| 8 |
+
- **Framework:** scikit-learn
|
| 9 |
+
- **Trained At:** 2026-05-22T05:33:11.363132+00:00
|
| 10 |
+
- **Seed:** 20260520
|
| 11 |
+
|
| 12 |
+
## Intended Use
|
| 13 |
+
|
| 14 |
+
Score subjective student answers against a rubric and model answer.
|
| 15 |
+
Produces a predicted marks value clipped to [0, max_marks]. Always sets
|
| 16 |
+
teacher_review_required=True in V2 baseline — predictions are advisory only.
|
| 17 |
+
|
| 18 |
+
## Training Data
|
| 19 |
+
|
| 20 |
+
- **Source:** training_answer_scoring.csv (synthetic dataset v2)
|
| 21 |
+
- **Split Counts:** train=8371, validation=1820, test=1809
|
| 22 |
+
- **Features:** student_answer (TF-IDF, max_features=5000, ngram_range=(1,2)) + rubric_match_score + concept_coverage_score
|
| 23 |
+
- **Target:** teacher_marks (continuous)
|
| 24 |
+
|
| 25 |
+
## Metrics
|
| 26 |
+
|
| 27 |
+
### Validation Set
|
| 28 |
+
- MAE: 0.4787
|
| 29 |
+
- RMSE: 0.773
|
| 30 |
+
- R-squared: 0.718
|
| 31 |
+
- % Above Review Threshold (>1.0): 16.87%
|
| 32 |
+
|
| 33 |
+
### Test Set
|
| 34 |
+
- MAE: 0.5256
|
| 35 |
+
- RMSE: 0.8385
|
| 36 |
+
- R-squared: 0.6791
|
| 37 |
+
- % Above Review Threshold (>1.0): 19.68%
|
| 38 |
+
|
| 39 |
+
## Known Limitations
|
| 40 |
+
|
| 41 |
+
- Trained on synthetic data only — performance on real student answers is unknown.
|
| 42 |
+
- TF-IDF features do not capture deep semantic similarity or paraphrasing.
|
| 43 |
+
- Predictions are clipped to [0, max_marks]; the model may predict outside this range before clipping.
|
| 44 |
+
- teacher_review_required is always True in V2 baseline.
|
| 45 |
+
- MAE is the primary metric; individual predictions may deviate significantly from teacher marks.
|
| 46 |
+
|
| 47 |
+
## Fallback Behavior
|
| 48 |
+
|
| 49 |
+
When the model is not loaded or confidence is below threshold,
|
| 50 |
+
the system falls back to rubric keyword coverage + length heuristic,
|
| 51 |
+
always setting teacher_review_required=True.
|
artifacts/models/answer_scorer/training_config.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_name": "answer_scorer",
|
| 3 |
+
"model_version": "answer_scorer_v2_baseline_001",
|
| 4 |
+
"dataset_version": "2.0.0",
|
| 5 |
+
"seed": 20260520,
|
| 6 |
+
"split_counts": {
|
| 7 |
+
"train": 8371,
|
| 8 |
+
"validation": 1820,
|
| 9 |
+
"test": 1809
|
| 10 |
+
},
|
| 11 |
+
"hyperparameters": {
|
| 12 |
+
"tfidf_max_features": 5000,
|
| 13 |
+
"ngram_range": [
|
| 14 |
+
1,
|
| 15 |
+
2
|
| 16 |
+
],
|
| 17 |
+
"ridge_alpha": 1.0
|
| 18 |
+
},
|
| 19 |
+
"feature_columns": [
|
| 20 |
+
"student_answer (TF-IDF)",
|
| 21 |
+
"rubric_match_score",
|
| 22 |
+
"concept_coverage_score"
|
| 23 |
+
],
|
| 24 |
+
"target_column": "teacher_marks",
|
| 25 |
+
"algorithm": "TF-IDF + Ridge regression"
|
| 26 |
+
}
|
artifacts/models/answer_scorer/vectorizer.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a8210b922548969cb609cb8e7c93590e064bfd2208b10647c993f51482bc0442
|
| 3 |
+
size 26983
|
artifacts/models/bloom_classifier/.gitkeep
ADDED
|
File without changes
|
artifacts/models/bloom_classifier/label_encoder.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:49cd11f5861283c0d8da24d21a2f021791eb64ea0d971e21e6d76ce16c3f2b7f
|
| 3 |
+
size 439
|
artifacts/models/bloom_classifier/metrics.json
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_name": "bloom_classifier",
|
| 3 |
+
"model_version": "bloom_classifier_v2_baseline_001",
|
| 4 |
+
"dataset_version": "2.0.0",
|
| 5 |
+
"trained_at": "2026-05-22T05:33:07.050037+00:00",
|
| 6 |
+
"seed": 20260520,
|
| 7 |
+
"split_counts": {
|
| 8 |
+
"train": 3912,
|
| 9 |
+
"validation": 1033,
|
| 10 |
+
"test": 875
|
| 11 |
+
},
|
| 12 |
+
"metrics": {
|
| 13 |
+
"validation": {
|
| 14 |
+
"macro_f1": 0.6434,
|
| 15 |
+
"weighted_f1": 0.6634,
|
| 16 |
+
"per_class": {
|
| 17 |
+
"Analyze": {
|
| 18 |
+
"precision": 0.614,
|
| 19 |
+
"recall": 0.6774,
|
| 20 |
+
"f1": 0.6442,
|
| 21 |
+
"support": 155
|
| 22 |
+
},
|
| 23 |
+
"Apply": {
|
| 24 |
+
"precision": 0.65,
|
| 25 |
+
"recall": 0.5778,
|
| 26 |
+
"f1": 0.6118,
|
| 27 |
+
"support": 270
|
| 28 |
+
},
|
| 29 |
+
"Create": {
|
| 30 |
+
"precision": 0.8947,
|
| 31 |
+
"recall": 1.0,
|
| 32 |
+
"f1": 0.9444,
|
| 33 |
+
"support": 17
|
| 34 |
+
},
|
| 35 |
+
"Evaluate": {
|
| 36 |
+
"precision": 1.0,
|
| 37 |
+
"recall": 0.1522,
|
| 38 |
+
"f1": 0.2642,
|
| 39 |
+
"support": 46
|
| 40 |
+
},
|
| 41 |
+
"Remember": {
|
| 42 |
+
"precision": 0.7438,
|
| 43 |
+
"recall": 0.5732,
|
| 44 |
+
"f1": 0.6475,
|
| 45 |
+
"support": 157
|
| 46 |
+
},
|
| 47 |
+
"Understand": {
|
| 48 |
+
"precision": 0.68,
|
| 49 |
+
"recall": 0.8325,
|
| 50 |
+
"f1": 0.7486,
|
| 51 |
+
"support": 388
|
| 52 |
+
}
|
| 53 |
+
},
|
| 54 |
+
"confusion_matrix": [
|
| 55 |
+
[
|
| 56 |
+
105,
|
| 57 |
+
50,
|
| 58 |
+
0,
|
| 59 |
+
0,
|
| 60 |
+
0,
|
| 61 |
+
0
|
| 62 |
+
],
|
| 63 |
+
[
|
| 64 |
+
27,
|
| 65 |
+
156,
|
| 66 |
+
0,
|
| 67 |
+
0,
|
| 68 |
+
0,
|
| 69 |
+
87
|
| 70 |
+
],
|
| 71 |
+
[
|
| 72 |
+
0,
|
| 73 |
+
0,
|
| 74 |
+
17,
|
| 75 |
+
0,
|
| 76 |
+
0,
|
| 77 |
+
0
|
| 78 |
+
],
|
| 79 |
+
[
|
| 80 |
+
37,
|
| 81 |
+
0,
|
| 82 |
+
2,
|
| 83 |
+
7,
|
| 84 |
+
0,
|
| 85 |
+
0
|
| 86 |
+
],
|
| 87 |
+
[
|
| 88 |
+
0,
|
| 89 |
+
2,
|
| 90 |
+
0,
|
| 91 |
+
0,
|
| 92 |
+
90,
|
| 93 |
+
65
|
| 94 |
+
],
|
| 95 |
+
[
|
| 96 |
+
2,
|
| 97 |
+
32,
|
| 98 |
+
0,
|
| 99 |
+
0,
|
| 100 |
+
31,
|
| 101 |
+
323
|
| 102 |
+
]
|
| 103 |
+
]
|
| 104 |
+
},
|
| 105 |
+
"test": {
|
| 106 |
+
"macro_f1": 0.6178,
|
| 107 |
+
"weighted_f1": 0.6654,
|
| 108 |
+
"per_class": {
|
| 109 |
+
"Analyze": {
|
| 110 |
+
"precision": 0.7,
|
| 111 |
+
"recall": 0.6853,
|
| 112 |
+
"f1": 0.6926,
|
| 113 |
+
"support": 143
|
| 114 |
+
},
|
| 115 |
+
"Apply": {
|
| 116 |
+
"precision": 0.6411,
|
| 117 |
+
"recall": 0.5678,
|
| 118 |
+
"f1": 0.6022,
|
| 119 |
+
"support": 236
|
| 120 |
+
},
|
| 121 |
+
"Create": {
|
| 122 |
+
"precision": 0.8333,
|
| 123 |
+
"recall": 0.9375,
|
| 124 |
+
"f1": 0.8824,
|
| 125 |
+
"support": 16
|
| 126 |
+
},
|
| 127 |
+
"Evaluate": {
|
| 128 |
+
"precision": 0.6667,
|
| 129 |
+
"recall": 0.0588,
|
| 130 |
+
"f1": 0.1081,
|
| 131 |
+
"support": 34
|
| 132 |
+
},
|
| 133 |
+
"Remember": {
|
| 134 |
+
"precision": 0.7677,
|
| 135 |
+
"recall": 0.608,
|
| 136 |
+
"f1": 0.6786,
|
| 137 |
+
"support": 125
|
| 138 |
+
},
|
| 139 |
+
"Understand": {
|
| 140 |
+
"precision": 0.665,
|
| 141 |
+
"recall": 0.8411,
|
| 142 |
+
"f1": 0.7428,
|
| 143 |
+
"support": 321
|
| 144 |
+
}
|
| 145 |
+
},
|
| 146 |
+
"confusion_matrix": [
|
| 147 |
+
[
|
| 148 |
+
98,
|
| 149 |
+
45,
|
| 150 |
+
0,
|
| 151 |
+
0,
|
| 152 |
+
0,
|
| 153 |
+
0
|
| 154 |
+
],
|
| 155 |
+
[
|
| 156 |
+
13,
|
| 157 |
+
134,
|
| 158 |
+
0,
|
| 159 |
+
0,
|
| 160 |
+
0,
|
| 161 |
+
89
|
| 162 |
+
],
|
| 163 |
+
[
|
| 164 |
+
0,
|
| 165 |
+
0,
|
| 166 |
+
15,
|
| 167 |
+
1,
|
| 168 |
+
0,
|
| 169 |
+
0
|
| 170 |
+
],
|
| 171 |
+
[
|
| 172 |
+
29,
|
| 173 |
+
0,
|
| 174 |
+
3,
|
| 175 |
+
2,
|
| 176 |
+
0,
|
| 177 |
+
0
|
| 178 |
+
],
|
| 179 |
+
[
|
| 180 |
+
0,
|
| 181 |
+
2,
|
| 182 |
+
0,
|
| 183 |
+
0,
|
| 184 |
+
76,
|
| 185 |
+
47
|
| 186 |
+
],
|
| 187 |
+
[
|
| 188 |
+
0,
|
| 189 |
+
28,
|
| 190 |
+
0,
|
| 191 |
+
0,
|
| 192 |
+
23,
|
| 193 |
+
270
|
| 194 |
+
]
|
| 195 |
+
]
|
| 196 |
+
}
|
| 197 |
+
},
|
| 198 |
+
"limitations": [
|
| 199 |
+
"Trained on synthetic data only.",
|
| 200 |
+
"6 classes with imbalanced distribution \u2014 Create (~2%) and Evaluate (~4%) are rare.",
|
| 201 |
+
"Macro F1 is the primary metric; per-class recall may be low for rare classes.",
|
| 202 |
+
"TF-IDF features do not capture semantic similarity beyond n-gram overlap."
|
| 203 |
+
]
|
| 204 |
+
}
|
artifacts/models/bloom_classifier/model.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c536885f0c45c7cb0318e5a65db523761d0e02b1ce5798e82b1764e4f4dd2d3d
|
| 3 |
+
size 76782
|
artifacts/models/bloom_classifier/model_card.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Model Card: Bloom Classifier
|
| 2 |
+
|
| 3 |
+
## Model Details
|
| 4 |
+
|
| 5 |
+
- **Model Name:** bloom_classifier
|
| 6 |
+
- **Model Version:** bloom_classifier_v2_baseline_001
|
| 7 |
+
- **Algorithm:** TF-IDF + LogisticRegression (multinomial)
|
| 8 |
+
- **Framework:** scikit-learn
|
| 9 |
+
- **Trained At:** 2026-05-22T05:33:07.050037+00:00
|
| 10 |
+
- **Seed:** 20260520
|
| 11 |
+
|
| 12 |
+
## Intended Use
|
| 13 |
+
|
| 14 |
+
Automatically classify questions by Bloom's taxonomy cognitive level.
|
| 15 |
+
Used in the Bloom classification endpoint to predict one of 6 levels:
|
| 16 |
+
Remember, Understand, Apply, Analyze, Evaluate, Create.
|
| 17 |
+
|
| 18 |
+
## Training Data
|
| 19 |
+
|
| 20 |
+
- **Source:** training_bloom_classification.csv (synthetic dataset v2)
|
| 21 |
+
- **Split Counts:** train=3912, validation=1033, test=875
|
| 22 |
+
- **Feature:** question_text (TF-IDF vectorized, max_features=8000, ngram_range=(1,2))
|
| 23 |
+
- **Target:** bloom_level (6 classes)
|
| 24 |
+
|
| 25 |
+
## Metrics
|
| 26 |
+
|
| 27 |
+
### Validation Set
|
| 28 |
+
- Macro F1: 0.6434
|
| 29 |
+
- Weighted F1: 0.6634
|
| 30 |
+
|
| 31 |
+
### Test Set
|
| 32 |
+
- Macro F1: 0.6178
|
| 33 |
+
- Weighted F1: 0.6654
|
| 34 |
+
|
| 35 |
+
## Known Limitations
|
| 36 |
+
|
| 37 |
+
- Trained on synthetic data only — performance on real classroom questions is unknown.
|
| 38 |
+
- Class imbalance: Create (~2%) and Evaluate (~4%) are rare; recall on these classes may be low.
|
| 39 |
+
- TF-IDF features do not capture semantic similarity beyond n-gram overlap.
|
| 40 |
+
- Macro F1 is the primary metric; accuracy alone would mask poor performance on rare classes.
|
| 41 |
+
|
| 42 |
+
## Fallback Behavior
|
| 43 |
+
|
| 44 |
+
When the model is not loaded or confidence is below the threshold (0.55),
|
| 45 |
+
the system falls back to keyword heuristic classification:
|
| 46 |
+
define/list → Remember; explain → Understand; calculate/use → Apply;
|
| 47 |
+
compare/contrast → Analyze; justify → Evaluate; design → Create.
|
artifacts/models/bloom_classifier/training_config.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_name": "bloom_classifier",
|
| 3 |
+
"model_version": "bloom_classifier_v2_baseline_001",
|
| 4 |
+
"dataset_version": "2.0.0",
|
| 5 |
+
"seed": 20260520,
|
| 6 |
+
"split_counts": {
|
| 7 |
+
"train": 3912,
|
| 8 |
+
"validation": 1033,
|
| 9 |
+
"test": 875
|
| 10 |
+
},
|
| 11 |
+
"hyperparameters": {
|
| 12 |
+
"tfidf_max_features": 8000,
|
| 13 |
+
"ngram_range": [
|
| 14 |
+
1,
|
| 15 |
+
2
|
| 16 |
+
],
|
| 17 |
+
"sublinear_tf": true,
|
| 18 |
+
"logreg_C": 1.0,
|
| 19 |
+
"logreg_solver": "lbfgs",
|
| 20 |
+
"logreg_max_iter": 1000,
|
| 21 |
+
"logreg_multi_class": "multinomial"
|
| 22 |
+
},
|
| 23 |
+
"feature_columns": [
|
| 24 |
+
"question_text"
|
| 25 |
+
],
|
| 26 |
+
"target_column": "bloom_level",
|
| 27 |
+
"algorithm": "LogisticRegression(multinomial)"
|
| 28 |
+
}
|
artifacts/models/bloom_classifier/vectorizer.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a1aef70da6176b150f33ce072efdda54115a07b9e1dacc2b2bf25daad5670b49
|
| 3 |
+
size 31067
|
artifacts/models/difficulty_model/encoder.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:781bac207e91e216ba726703b113d6646eabe3f46567205b10088621e6404f47
|
| 3 |
+
size 704
|
artifacts/models/difficulty_model/feature_columns.json
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
"bloom_score",
|
| 3 |
+
"grade",
|
| 4 |
+
"subject",
|
| 5 |
+
"question_type"
|
| 6 |
+
]
|
artifacts/models/difficulty_model/metrics.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_name": "difficulty_model",
|
| 3 |
+
"model_version": "difficulty_model_v2_baseline_001",
|
| 4 |
+
"dataset_version": "2.0.0",
|
| 5 |
+
"trained_at": "2026-05-22T05:33:07.506348+00:00",
|
| 6 |
+
"seed": 20260520,
|
| 7 |
+
"split_counts": {
|
| 8 |
+
"train": 3912,
|
| 9 |
+
"validation": 1033,
|
| 10 |
+
"test": 875
|
| 11 |
+
},
|
| 12 |
+
"metrics": {
|
| 13 |
+
"validation": {
|
| 14 |
+
"mae": 0.3477,
|
| 15 |
+
"r_squared": 0.5007,
|
| 16 |
+
"per_bucket_mae": {
|
| 17 |
+
"easy": 0.3051,
|
| 18 |
+
"medium": 0.2958,
|
| 19 |
+
"hard": 0.6525
|
| 20 |
+
}
|
| 21 |
+
},
|
| 22 |
+
"test": {
|
| 23 |
+
"mae": 0.3514,
|
| 24 |
+
"r_squared": 0.4693,
|
| 25 |
+
"per_bucket_mae": {
|
| 26 |
+
"easy": 0.3241,
|
| 27 |
+
"medium": 0.2903,
|
| 28 |
+
"hard": 0.6728
|
| 29 |
+
}
|
| 30 |
+
}
|
| 31 |
+
},
|
| 32 |
+
"limitations": [
|
| 33 |
+
"Trained on synthetic data only.",
|
| 34 |
+
"difficulty_score distribution may not reflect real-world difficulty.",
|
| 35 |
+
"OrdinalEncoder assumes an ordering that may not be meaningful for subject/question_type.",
|
| 36 |
+
"Per-bucket MAE depends on the quality of the difficulty string labels."
|
| 37 |
+
]
|
| 38 |
+
}
|
artifacts/models/difficulty_model/model.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:87924be76fe290bfce10dec3bbbe137fd942314538029843c12798f3da975e98
|
| 3 |
+
size 735477
|
artifacts/models/difficulty_model/model_card.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Model Card: Difficulty Model
|
| 2 |
+
|
| 3 |
+
## Model Details
|
| 4 |
+
|
| 5 |
+
- **Model Name:** difficulty_model
|
| 6 |
+
- **Model Version:** difficulty_model_v2_baseline_001
|
| 7 |
+
- **Algorithm:** RandomForestRegressor
|
| 8 |
+
- **Framework:** scikit-learn
|
| 9 |
+
- **Trained At:** 2026-05-22T05:33:07.506348+00:00
|
| 10 |
+
- **Seed:** 20260520
|
| 11 |
+
|
| 12 |
+
## Intended Use
|
| 13 |
+
|
| 14 |
+
Estimate question difficulty as a continuous score in [0, 1] based on
|
| 15 |
+
question features (bloom_score, grade, subject, question_type). Used in
|
| 16 |
+
the difficulty estimation endpoint to predict how hard a question is for
|
| 17 |
+
a given grade level.
|
| 18 |
+
|
| 19 |
+
## Training Data
|
| 20 |
+
|
| 21 |
+
- **Source:** training_lo_tagging.csv + questions.csv (for question_type)
|
| 22 |
+
- **Split Counts:** train=3912, validation=1033, test=875
|
| 23 |
+
- **Features:** bloom_score (numeric), grade (numeric), subject (OrdinalEncoded), question_type (OrdinalEncoded)
|
| 24 |
+
- **Target:** difficulty_score (continuous [0, 1])
|
| 25 |
+
|
| 26 |
+
## Metrics
|
| 27 |
+
|
| 28 |
+
### Validation Set
|
| 29 |
+
- MAE: 0.3477
|
| 30 |
+
- R-squared: 0.5007
|
| 31 |
+
- Per-bucket MAE: {'easy': 0.3051, 'medium': 0.2958, 'hard': 0.6525}
|
| 32 |
+
|
| 33 |
+
### Test Set
|
| 34 |
+
- MAE: 0.3514
|
| 35 |
+
- R-squared: 0.4693
|
| 36 |
+
- Per-bucket MAE: {'easy': 0.3241, 'medium': 0.2903, 'hard': 0.6728}
|
| 37 |
+
|
| 38 |
+
## Known Limitations
|
| 39 |
+
|
| 40 |
+
- Trained on synthetic data only — performance on real questions is unknown.
|
| 41 |
+
- difficulty_score distribution may not reflect real-world difficulty.
|
| 42 |
+
- OrdinalEncoder assumes an ordering that may not be meaningful for subject/question_type.
|
| 43 |
+
- Per-bucket MAE depends on the quality of the difficulty string labels.
|
| 44 |
+
- Limited feature set (4 features); text-based features could improve performance.
|
| 45 |
+
|
| 46 |
+
## Fallback Behavior
|
| 47 |
+
|
| 48 |
+
When the model is not loaded or confidence is below threshold, the system
|
| 49 |
+
falls back to a rule-based difficulty estimation using bloom_score and
|
| 50 |
+
grade-level heuristics.
|
artifacts/models/difficulty_model/training_config.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_name": "difficulty_model",
|
| 3 |
+
"model_version": "difficulty_model_v2_baseline_001",
|
| 4 |
+
"dataset_version": "2.0.0",
|
| 5 |
+
"seed": 20260520,
|
| 6 |
+
"split_counts": {
|
| 7 |
+
"train": 3912,
|
| 8 |
+
"validation": 1033,
|
| 9 |
+
"test": 875
|
| 10 |
+
},
|
| 11 |
+
"hyperparameters": {
|
| 12 |
+
"n_estimators": 100,
|
| 13 |
+
"random_state": 20260520,
|
| 14 |
+
"algorithm": "RandomForestRegressor",
|
| 15 |
+
"encoder": "OrdinalEncoder"
|
| 16 |
+
},
|
| 17 |
+
"feature_columns": [
|
| 18 |
+
"bloom_score",
|
| 19 |
+
"grade",
|
| 20 |
+
"subject",
|
| 21 |
+
"question_type"
|
| 22 |
+
],
|
| 23 |
+
"categorical_columns": [
|
| 24 |
+
"subject",
|
| 25 |
+
"question_type"
|
| 26 |
+
],
|
| 27 |
+
"numeric_columns": [
|
| 28 |
+
"bloom_score",
|
| 29 |
+
"grade"
|
| 30 |
+
],
|
| 31 |
+
"target_column": "difficulty_score",
|
| 32 |
+
"algorithm": "RandomForestRegressor"
|
| 33 |
+
}
|
artifacts/models/lo_tagger/.gitkeep
ADDED
|
File without changes
|
artifacts/models/lo_tagger/label_encoder.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:42e9faea136d20cf19963170fc609d0f3a02b28b6d2e3e376b79739b3f043e43
|
| 3 |
+
size 1147
|
artifacts/models/lo_tagger/metrics.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
artifacts/models/lo_tagger/model.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1178f614787d62a4f6a96764052381a23df9018505e1f8979110d22ea6db925a
|
| 3 |
+
size 7427598
|
artifacts/models/lo_tagger/model_card.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Model Card: LO Tagger
|
| 2 |
+
|
| 3 |
+
## Model Details
|
| 4 |
+
|
| 5 |
+
- **Model Name:** lo_tagger
|
| 6 |
+
- **Model Version:** lo_tagger_v2_baseline_001
|
| 7 |
+
- **Algorithm:** TF-IDF + CalibratedClassifierCV(LinearSVC)
|
| 8 |
+
- **Framework:** scikit-learn
|
| 9 |
+
- **Trained At:** 2026-05-22T05:33:05.850313+00:00
|
| 10 |
+
- **Seed:** 20260520
|
| 11 |
+
|
| 12 |
+
## Intended Use
|
| 13 |
+
|
| 14 |
+
Automatically tag questions to their most relevant Learning Outcome (LO).
|
| 15 |
+
Used in the LO tagging endpoint to classify question text into one of 194
|
| 16 |
+
learning outcome categories.
|
| 17 |
+
|
| 18 |
+
## Training Data
|
| 19 |
+
|
| 20 |
+
- **Source:** training_lo_tagging.csv (synthetic dataset v2)
|
| 21 |
+
- **Split Counts:** train=3912, validation=1033, test=875
|
| 22 |
+
- **Feature:** question_text (TF-IDF vectorized, max_features=10000, ngram_range=(1,2))
|
| 23 |
+
- **Target:** lo_id (194 classes)
|
| 24 |
+
|
| 25 |
+
## Metrics
|
| 26 |
+
|
| 27 |
+
### Validation Set
|
| 28 |
+
- Top-1 Accuracy: 0.9245
|
| 29 |
+
- Top-3 Accuracy: 1.0
|
| 30 |
+
- Macro F1: 0.9042
|
| 31 |
+
- Weighted F1: 0.9249
|
| 32 |
+
|
| 33 |
+
### Test Set
|
| 34 |
+
- Top-1 Accuracy: 0.9097
|
| 35 |
+
- Top-3 Accuracy: 1.0
|
| 36 |
+
- Macro F1: 0.8861
|
| 37 |
+
- Weighted F1: 0.9115
|
| 38 |
+
|
| 39 |
+
## Known Limitations
|
| 40 |
+
|
| 41 |
+
- Trained on synthetic data only — performance on real classroom questions is unknown.
|
| 42 |
+
- 194 classes with imbalanced distribution; rare LOs may have low recall.
|
| 43 |
+
- TF-IDF features do not capture semantic similarity beyond n-gram overlap.
|
| 44 |
+
- Top-3 accuracy is the primary metric; top-1 may be low for ambiguous questions.
|
| 45 |
+
|
| 46 |
+
## Fallback Behavior
|
| 47 |
+
|
| 48 |
+
When the model is not loaded or confidence is below the threshold (0.55),
|
| 49 |
+
the system falls back to keyword/embedding match against learning_outcomes.embedding_text
|
| 50 |
+
filtered by grade and subject, returning top-3 with rule-based confidence.
|
artifacts/models/lo_tagger/training_config.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_name": "lo_tagger",
|
| 3 |
+
"model_version": "lo_tagger_v2_baseline_001",
|
| 4 |
+
"dataset_version": "2.0.0",
|
| 5 |
+
"seed": 20260520,
|
| 6 |
+
"split_counts": {
|
| 7 |
+
"train": 3912,
|
| 8 |
+
"validation": 1033,
|
| 9 |
+
"test": 875
|
| 10 |
+
},
|
| 11 |
+
"hyperparameters": {
|
| 12 |
+
"tfidf_max_features": 10000,
|
| 13 |
+
"ngram_range": [
|
| 14 |
+
1,
|
| 15 |
+
2
|
| 16 |
+
],
|
| 17 |
+
"sublinear_tf": true,
|
| 18 |
+
"svc_max_iter": 5000,
|
| 19 |
+
"calibration_cv": 3,
|
| 20 |
+
"calibration_method": "sigmoid"
|
| 21 |
+
},
|
| 22 |
+
"feature_columns": [
|
| 23 |
+
"question_text"
|
| 24 |
+
],
|
| 25 |
+
"target_column": "lo_id",
|
| 26 |
+
"algorithm": "CalibratedClassifierCV(LinearSVC)"
|
| 27 |
+
}
|
artifacts/models/lo_tagger/vectorizer.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f40dd0d2353b0d608565093d96e288a624498f2acbfcd007dc993e5f47422606
|
| 3 |
+
size 31068
|
artifacts/models/mastery_model/.gitkeep
ADDED
|
File without changes
|
artifacts/models/mastery_model/feature_columns.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
"attempt_count",
|
| 3 |
+
"accuracy",
|
| 4 |
+
"average_marks_ratio",
|
| 5 |
+
"average_time_seconds",
|
| 6 |
+
"hint_usage_rate",
|
| 7 |
+
"attendance_percentage",
|
| 8 |
+
"assignment_completion_rate",
|
| 9 |
+
"average_login_per_week",
|
| 10 |
+
"inactive_days_last_14"
|
| 11 |
+
]
|
artifacts/models/mastery_model/metrics.json
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_name": "mastery_model",
|
| 3 |
+
"model_version": "mastery_model_v2_baseline_001",
|
| 4 |
+
"dataset_version": "2.0.0",
|
| 5 |
+
"trained_at": "2026-05-22T05:33:10.125086+00:00",
|
| 6 |
+
"seed": 20260520,
|
| 7 |
+
"split_counts": {
|
| 8 |
+
"train": 24515,
|
| 9 |
+
"validation": 5218,
|
| 10 |
+
"test": 5187
|
| 11 |
+
},
|
| 12 |
+
"metrics": {
|
| 13 |
+
"validation": {
|
| 14 |
+
"macro_f1": 0.8661,
|
| 15 |
+
"weighted_f1": 0.8967,
|
| 16 |
+
"per_class": {
|
| 17 |
+
"weak": {
|
| 18 |
+
"precision": 0.9678,
|
| 19 |
+
"recall": 0.964,
|
| 20 |
+
"f1": 0.9659,
|
| 21 |
+
"support": 2247
|
| 22 |
+
},
|
| 23 |
+
"developing": {
|
| 24 |
+
"precision": 0.8908,
|
| 25 |
+
"recall": 0.9095,
|
| 26 |
+
"f1": 0.9001,
|
| 27 |
+
"support": 1337
|
| 28 |
+
},
|
| 29 |
+
"proficient": {
|
| 30 |
+
"precision": 0.7819,
|
| 31 |
+
"recall": 0.7421,
|
| 32 |
+
"f1": 0.7615,
|
| 33 |
+
"support": 826
|
| 34 |
+
},
|
| 35 |
+
"mastered": {
|
| 36 |
+
"precision": 0.8255,
|
| 37 |
+
"recall": 0.849,
|
| 38 |
+
"f1": 0.8371,
|
| 39 |
+
"support": 808
|
| 40 |
+
}
|
| 41 |
+
},
|
| 42 |
+
"confusion_matrix": [
|
| 43 |
+
[
|
| 44 |
+
2166,
|
| 45 |
+
81,
|
| 46 |
+
0,
|
| 47 |
+
0
|
| 48 |
+
],
|
| 49 |
+
[
|
| 50 |
+
72,
|
| 51 |
+
1216,
|
| 52 |
+
49,
|
| 53 |
+
0
|
| 54 |
+
],
|
| 55 |
+
[
|
| 56 |
+
0,
|
| 57 |
+
68,
|
| 58 |
+
613,
|
| 59 |
+
145
|
| 60 |
+
],
|
| 61 |
+
[
|
| 62 |
+
0,
|
| 63 |
+
0,
|
| 64 |
+
122,
|
| 65 |
+
686
|
| 66 |
+
]
|
| 67 |
+
]
|
| 68 |
+
},
|
| 69 |
+
"test": {
|
| 70 |
+
"macro_f1": 0.8763,
|
| 71 |
+
"weighted_f1": 0.9034,
|
| 72 |
+
"per_class": {
|
| 73 |
+
"weak": {
|
| 74 |
+
"precision": 0.9653,
|
| 75 |
+
"recall": 0.9722,
|
| 76 |
+
"f1": 0.9687,
|
| 77 |
+
"support": 2120
|
| 78 |
+
},
|
| 79 |
+
"developing": {
|
| 80 |
+
"precision": 0.9179,
|
| 81 |
+
"recall": 0.9067,
|
| 82 |
+
"f1": 0.9123,
|
| 83 |
+
"support": 1394
|
| 84 |
+
},
|
| 85 |
+
"proficient": {
|
| 86 |
+
"precision": 0.7887,
|
| 87 |
+
"recall": 0.7518,
|
| 88 |
+
"f1": 0.7698,
|
| 89 |
+
"support": 814
|
| 90 |
+
},
|
| 91 |
+
"mastered": {
|
| 92 |
+
"precision": 0.8354,
|
| 93 |
+
"recall": 0.8743,
|
| 94 |
+
"f1": 0.8544,
|
| 95 |
+
"support": 859
|
| 96 |
+
}
|
| 97 |
+
},
|
| 98 |
+
"confusion_matrix": [
|
| 99 |
+
[
|
| 100 |
+
2061,
|
| 101 |
+
59,
|
| 102 |
+
0,
|
| 103 |
+
0
|
| 104 |
+
],
|
| 105 |
+
[
|
| 106 |
+
74,
|
| 107 |
+
1264,
|
| 108 |
+
56,
|
| 109 |
+
0
|
| 110 |
+
],
|
| 111 |
+
[
|
| 112 |
+
0,
|
| 113 |
+
54,
|
| 114 |
+
612,
|
| 115 |
+
148
|
| 116 |
+
],
|
| 117 |
+
[
|
| 118 |
+
0,
|
| 119 |
+
0,
|
| 120 |
+
108,
|
| 121 |
+
751
|
| 122 |
+
]
|
| 123 |
+
]
|
| 124 |
+
}
|
| 125 |
+
},
|
| 126 |
+
"limitations": [
|
| 127 |
+
"Trained on synthetic data only.",
|
| 128 |
+
"4-class mastery labels derived from synthetic mastery_score thresholds.",
|
| 129 |
+
"All features are numeric; no text or contextual features used.",
|
| 130 |
+
"Class distribution may not reflect real-world mastery patterns."
|
| 131 |
+
]
|
| 132 |
+
}
|
artifacts/models/mastery_model/model.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:36c2dffc14d2708ee128a0859f3f13453a61400f725ce0b56dcbb488043e1090
|
| 3 |
+
size 6881288
|
artifacts/models/mastery_model/model_card.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Model Card: Mastery Model
|
| 2 |
+
|
| 3 |
+
## Model Details
|
| 4 |
+
|
| 5 |
+
- **Model Name:** mastery_model
|
| 6 |
+
- **Model Version:** mastery_model_v2_baseline_001
|
| 7 |
+
- **Algorithm:** RandomForestClassifier
|
| 8 |
+
- **Framework:** scikit-learn
|
| 9 |
+
- **Trained At:** 2026-05-22T05:33:10.125086+00:00
|
| 10 |
+
- **Seed:** 20260520
|
| 11 |
+
|
| 12 |
+
## Intended Use
|
| 13 |
+
|
| 14 |
+
Predict per-student per-LO mastery label (weak, developing, proficient, mastered)
|
| 15 |
+
based on behavioral and performance features. Used in the mastery prediction
|
| 16 |
+
endpoint to classify student mastery level for a given learning outcome.
|
| 17 |
+
|
| 18 |
+
## Training Data
|
| 19 |
+
|
| 20 |
+
- **Source:** training_mastery_prediction.csv (synthetic dataset v2)
|
| 21 |
+
- **Split Counts:** train=24515, validation=5218, test=5187
|
| 22 |
+
- **Features:** attempt_count, accuracy, average_marks_ratio, average_time_seconds, hint_usage_rate, attendance_percentage, assignment_completion_rate, average_login_per_week, inactive_days_last_14 (all numeric)
|
| 23 |
+
- **Target:** mastery_label (integer 0-3, mapped to weak/developing/proficient/mastered)
|
| 24 |
+
|
| 25 |
+
## Metrics
|
| 26 |
+
|
| 27 |
+
### Validation Set
|
| 28 |
+
- Macro F1: 0.8661
|
| 29 |
+
- Weighted F1: 0.8967
|
| 30 |
+
|
| 31 |
+
### Test Set
|
| 32 |
+
- Macro F1: 0.8763
|
| 33 |
+
- Weighted F1: 0.9034
|
| 34 |
+
|
| 35 |
+
## Per-Class Performance (Test Set)
|
| 36 |
+
|
| 37 |
+
| Class | Precision | Recall | F1 | Support |
|
| 38 |
+
|-------|-----------|--------|-----|---------|
|
| 39 |
+
| weak | 0.9653 | 0.9722 | 0.9687 | 2120 |
|
| 40 |
+
| developing | 0.9179 | 0.9067 | 0.9123 | 1394 |
|
| 41 |
+
| proficient | 0.7887 | 0.7518 | 0.7698 | 814 |
|
| 42 |
+
| mastered | 0.8354 | 0.8743 | 0.8544 | 859 |
|
| 43 |
+
|
| 44 |
+
## Known Limitations
|
| 45 |
+
|
| 46 |
+
- Trained on synthetic data only — performance on real student data is unknown.
|
| 47 |
+
- 4-class mastery labels derived from synthetic mastery_score thresholds.
|
| 48 |
+
- All features are numeric; no text or contextual features used.
|
| 49 |
+
- Class distribution may not reflect real-world mastery patterns.
|
| 50 |
+
- No encoding needed since all features are already numeric.
|
| 51 |
+
|
| 52 |
+
## Fallback Behavior
|
| 53 |
+
|
| 54 |
+
When the model is not loaded or confidence is below the threshold (0.55),
|
| 55 |
+
the system falls back to rule-based mastery estimation using mastery_score
|
| 56 |
+
thresholds: <0.4 weak, <0.6 developing, <0.8 proficient, else mastered.
|
artifacts/models/mastery_model/training_config.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_name": "mastery_model",
|
| 3 |
+
"model_version": "mastery_model_v2_baseline_001",
|
| 4 |
+
"dataset_version": "2.0.0",
|
| 5 |
+
"seed": 20260520,
|
| 6 |
+
"split_counts": {
|
| 7 |
+
"train": 24515,
|
| 8 |
+
"validation": 5218,
|
| 9 |
+
"test": 5187
|
| 10 |
+
},
|
| 11 |
+
"hyperparameters": {
|
| 12 |
+
"n_estimators": 100,
|
| 13 |
+
"random_state": 20260520,
|
| 14 |
+
"algorithm": "RandomForestClassifier"
|
| 15 |
+
},
|
| 16 |
+
"feature_columns": [
|
| 17 |
+
"attempt_count",
|
| 18 |
+
"accuracy",
|
| 19 |
+
"average_marks_ratio",
|
| 20 |
+
"average_time_seconds",
|
| 21 |
+
"hint_usage_rate",
|
| 22 |
+
"attendance_percentage",
|
| 23 |
+
"assignment_completion_rate",
|
| 24 |
+
"average_login_per_week",
|
| 25 |
+
"inactive_days_last_14"
|
| 26 |
+
],
|
| 27 |
+
"target_column": "mastery_label",
|
| 28 |
+
"label_map": {
|
| 29 |
+
"0": "weak",
|
| 30 |
+
"1": "developing",
|
| 31 |
+
"2": "proficient",
|
| 32 |
+
"3": "mastered"
|
| 33 |
+
},
|
| 34 |
+
"algorithm": "RandomForestClassifier"
|
| 35 |
+
}
|
artifacts/models/recommender/.gitkeep
ADDED
|
File without changes
|
artifacts/models/recommender/encoder.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:417a9e093b8090b171f8383bc3772bfca90127b02d17a5b543ec3f5517200d2d
|
| 3 |
+
size 699
|
artifacts/models/recommender/feature_columns.json
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
"priority",
|
| 3 |
+
"ai_confidence",
|
| 4 |
+
"recommendation_type",
|
| 5 |
+
"grade",
|
| 6 |
+
"subject"
|
| 7 |
+
]
|
artifacts/models/recommender/metrics.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_name": "recommender",
|
| 3 |
+
"model_version": "recommender_v2_baseline_001",
|
| 4 |
+
"dataset_version": "2.0.0",
|
| 5 |
+
"trained_at": "2026-05-22T05:33:12.270778+00:00",
|
| 6 |
+
"seed": 20260520,
|
| 7 |
+
"split_counts": {
|
| 8 |
+
"train": 5671,
|
| 9 |
+
"validation": 1214,
|
| 10 |
+
"test": 1215
|
| 11 |
+
},
|
| 12 |
+
"metrics": {
|
| 13 |
+
"validation": {
|
| 14 |
+
"roc_auc_clicked": 0.544,
|
| 15 |
+
"lift_at_10_clicked": 1.1392,
|
| 16 |
+
"roc_auc_is_completed": 0.5299,
|
| 17 |
+
"lift_at_10_is_completed": 1.1056
|
| 18 |
+
},
|
| 19 |
+
"test": {
|
| 20 |
+
"roc_auc_clicked": 0.5486,
|
| 21 |
+
"lift_at_10_clicked": 1.0471,
|
| 22 |
+
"roc_auc_is_completed": 0.5424,
|
| 23 |
+
"lift_at_10_is_completed": 1.0366
|
| 24 |
+
}
|
| 25 |
+
},
|
| 26 |
+
"limitations": [
|
| 27 |
+
"Trained on synthetic data only.",
|
| 28 |
+
"Two separate GBC models \u2014 no joint optimization of clicked + is_completed.",
|
| 29 |
+
"OrdinalEncoder assumes an ordering for priority/recommendation_type/subject.",
|
| 30 |
+
"Lift@10 depends on the distribution of positive labels in the dataset.",
|
| 31 |
+
"No user-level features (e.g., engagement history) included in baseline."
|
| 32 |
+
]
|
| 33 |
+
}
|
artifacts/models/recommender/model.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:27c6e41ce34d625c1fd10f05537051daf7f4ae871ecf147746eeff7203e83d3d
|
| 3 |
+
size 201527
|
artifacts/models/recommender/model_card.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Model Card: Recommender
|
| 2 |
+
|
| 3 |
+
## Model Details
|
| 4 |
+
|
| 5 |
+
- **Model Name:** recommender
|
| 6 |
+
- **Model Version:** recommender_v2_baseline_001
|
| 7 |
+
- **Algorithm:** GradientBoostingClassifier (two models: clicked, is_completed)
|
| 8 |
+
- **Framework:** scikit-learn
|
| 9 |
+
- **Trained At:** 2026-05-22T05:33:12.270778+00:00
|
| 10 |
+
- **Seed:** 20260520
|
| 11 |
+
|
| 12 |
+
## Intended Use
|
| 13 |
+
|
| 14 |
+
Predict whether a student will click on a recommendation and whether they will
|
| 15 |
+
complete the recommended content. Used in the recommendation engine to rank
|
| 16 |
+
content by predicted engagement. Two separate binary classifiers are trained:
|
| 17 |
+
one for `clicked` and one for `is_completed`.
|
| 18 |
+
|
| 19 |
+
## Training Data
|
| 20 |
+
|
| 21 |
+
- **Source:** training_recommendation_outcomes.csv (synthetic dataset v2)
|
| 22 |
+
- **Split Counts:** train=5671, validation=1214, test=1215
|
| 23 |
+
- **Features:** priority (OrdinalEncoded), ai_confidence (numeric), recommendation_type (OrdinalEncoded), grade (numeric), subject (OrdinalEncoded)
|
| 24 |
+
- **Targets:** clicked (binary), is_completed (binary)
|
| 25 |
+
|
| 26 |
+
## Metrics
|
| 27 |
+
|
| 28 |
+
### Validation Set
|
| 29 |
+
- ROC-AUC (clicked): 0.544
|
| 30 |
+
- ROC-AUC (is_completed): 0.5299
|
| 31 |
+
- Lift@10 (clicked): 1.1392
|
| 32 |
+
- Lift@10 (is_completed): 1.1056
|
| 33 |
+
|
| 34 |
+
### Test Set
|
| 35 |
+
- ROC-AUC (clicked): 0.5486
|
| 36 |
+
- ROC-AUC (is_completed): 0.5424
|
| 37 |
+
- Lift@10 (clicked): 1.0471
|
| 38 |
+
- Lift@10 (is_completed): 1.0366
|
| 39 |
+
|
| 40 |
+
## Known Limitations
|
| 41 |
+
|
| 42 |
+
- Trained on synthetic data only — performance on real recommendation data is unknown.
|
| 43 |
+
- Two separate GBC models — no joint optimization of clicked + is_completed.
|
| 44 |
+
- OrdinalEncoder assumes an ordering for priority/recommendation_type/subject.
|
| 45 |
+
- Lift@10 depends on the distribution of positive labels in the dataset.
|
| 46 |
+
- No user-level features (e.g., engagement history) included in baseline.
|
| 47 |
+
- Limited feature set (5 features); adding student history could improve performance.
|
| 48 |
+
|
| 49 |
+
## Fallback Behavior
|
| 50 |
+
|
| 51 |
+
When the model is not loaded or confidence is below threshold, the system
|
| 52 |
+
falls back to knowledge-graph weakest-prerequisite + content_catalog filtered
|
| 53 |
+
by LO + difficulty, ranked by estimated_mastery_gain.
|
artifacts/models/recommender/training_config.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_name": "recommender",
|
| 3 |
+
"model_version": "recommender_v2_baseline_001",
|
| 4 |
+
"dataset_version": "2.0.0",
|
| 5 |
+
"seed": 20260520,
|
| 6 |
+
"split_counts": {
|
| 7 |
+
"train": 5671,
|
| 8 |
+
"validation": 1214,
|
| 9 |
+
"test": 1215
|
| 10 |
+
},
|
| 11 |
+
"hyperparameters": {
|
| 12 |
+
"n_estimators": 100,
|
| 13 |
+
"max_depth": 4,
|
| 14 |
+
"random_state": 20260520,
|
| 15 |
+
"algorithm": "GradientBoostingClassifier",
|
| 16 |
+
"encoder": "OrdinalEncoder"
|
| 17 |
+
},
|
| 18 |
+
"feature_columns": [
|
| 19 |
+
"priority",
|
| 20 |
+
"ai_confidence",
|
| 21 |
+
"recommendation_type",
|
| 22 |
+
"grade",
|
| 23 |
+
"subject"
|
| 24 |
+
],
|
| 25 |
+
"categorical_columns": [
|
| 26 |
+
"priority",
|
| 27 |
+
"recommendation_type",
|
| 28 |
+
"subject"
|
| 29 |
+
],
|
| 30 |
+
"numeric_columns": [
|
| 31 |
+
"ai_confidence",
|
| 32 |
+
"grade"
|
| 33 |
+
],
|
| 34 |
+
"target_columns": [
|
| 35 |
+
"clicked",
|
| 36 |
+
"is_completed"
|
| 37 |
+
],
|
| 38 |
+
"algorithm": "GradientBoostingClassifier"
|
| 39 |
+
}
|
artifacts/models/risk_model/.gitkeep
ADDED
|
File without changes
|
artifacts/models/risk_model/feature_columns.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
"avg_mastery_score",
|
| 3 |
+
"weak_lo_count",
|
| 4 |
+
"developing_lo_count",
|
| 5 |
+
"mastered_lo_count",
|
| 6 |
+
"avg_confidence",
|
| 7 |
+
"avg_accuracy",
|
| 8 |
+
"avg_marks_ratio",
|
| 9 |
+
"avg_time_seconds",
|
| 10 |
+
"hint_usage_rate",
|
| 11 |
+
"total_attempts",
|
| 12 |
+
"attendance_percentage",
|
| 13 |
+
"assignment_completion_rate",
|
| 14 |
+
"average_login_per_week",
|
| 15 |
+
"inactive_days_last_14",
|
| 16 |
+
"avg_active_minutes",
|
| 17 |
+
"total_logins",
|
| 18 |
+
"avg_video_watch_ratio",
|
| 19 |
+
"total_content_completed",
|
| 20 |
+
"total_quiz_attempts"
|
| 21 |
+
]
|
artifacts/models/risk_model/metrics.json
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_name": "risk_model",
|
| 3 |
+
"model_version": "risk_model_v2_baseline_001",
|
| 4 |
+
"dataset_version": "2.0.0",
|
| 5 |
+
"trained_at": "2026-05-22T05:33:10.882126+00:00",
|
| 6 |
+
"seed": 20260520,
|
| 7 |
+
"split_counts": {
|
| 8 |
+
"train": 1133,
|
| 9 |
+
"validation": 243,
|
| 10 |
+
"test": 244
|
| 11 |
+
},
|
| 12 |
+
"metrics": {
|
| 13 |
+
"validation": {
|
| 14 |
+
"recall_positive": 0.8571,
|
| 15 |
+
"precision_positive": 0.9231,
|
| 16 |
+
"f1_positive": 0.8889,
|
| 17 |
+
"roc_auc": 0.9915,
|
| 18 |
+
"per_class": {
|
| 19 |
+
"not_at_risk": {
|
| 20 |
+
"precision": 0.9706,
|
| 21 |
+
"recall": 0.9851,
|
| 22 |
+
"f1": 0.9778,
|
| 23 |
+
"support": 201
|
| 24 |
+
},
|
| 25 |
+
"at_risk": {
|
| 26 |
+
"precision": 0.9231,
|
| 27 |
+
"recall": 0.8571,
|
| 28 |
+
"f1": 0.8889,
|
| 29 |
+
"support": 42
|
| 30 |
+
}
|
| 31 |
+
},
|
| 32 |
+
"confusion_matrix": [
|
| 33 |
+
[
|
| 34 |
+
198,
|
| 35 |
+
3
|
| 36 |
+
],
|
| 37 |
+
[
|
| 38 |
+
6,
|
| 39 |
+
36
|
| 40 |
+
]
|
| 41 |
+
],
|
| 42 |
+
"risk_level_recall": {
|
| 43 |
+
"high": {
|
| 44 |
+
"recall": 0.8421,
|
| 45 |
+
"support": 38
|
| 46 |
+
},
|
| 47 |
+
"critical": {
|
| 48 |
+
"recall": 1.0,
|
| 49 |
+
"support": 4
|
| 50 |
+
}
|
| 51 |
+
}
|
| 52 |
+
},
|
| 53 |
+
"test": {
|
| 54 |
+
"recall_positive": 0.8125,
|
| 55 |
+
"precision_positive": 0.8966,
|
| 56 |
+
"f1_positive": 0.8525,
|
| 57 |
+
"roc_auc": 0.9899,
|
| 58 |
+
"per_class": {
|
| 59 |
+
"not_at_risk": {
|
| 60 |
+
"precision": 0.9721,
|
| 61 |
+
"recall": 0.9858,
|
| 62 |
+
"f1": 0.9789,
|
| 63 |
+
"support": 212
|
| 64 |
+
},
|
| 65 |
+
"at_risk": {
|
| 66 |
+
"precision": 0.8966,
|
| 67 |
+
"recall": 0.8125,
|
| 68 |
+
"f1": 0.8525,
|
| 69 |
+
"support": 32
|
| 70 |
+
}
|
| 71 |
+
},
|
| 72 |
+
"confusion_matrix": [
|
| 73 |
+
[
|
| 74 |
+
209,
|
| 75 |
+
3
|
| 76 |
+
],
|
| 77 |
+
[
|
| 78 |
+
6,
|
| 79 |
+
26
|
| 80 |
+
]
|
| 81 |
+
],
|
| 82 |
+
"risk_level_recall": {
|
| 83 |
+
"high": {
|
| 84 |
+
"recall": 0.7778,
|
| 85 |
+
"support": 27
|
| 86 |
+
},
|
| 87 |
+
"critical": {
|
| 88 |
+
"recall": 1.0,
|
| 89 |
+
"support": 5
|
| 90 |
+
}
|
| 91 |
+
}
|
| 92 |
+
}
|
| 93 |
+
},
|
| 94 |
+
"limitations": [
|
| 95 |
+
"Trained on synthetic data only.",
|
| 96 |
+
"Binary risk_label derived from synthetic risk_score thresholds.",
|
| 97 |
+
"All features are numeric; no text or contextual features used.",
|
| 98 |
+
"Class imbalance (~16% positive) addressed via class_weight='balanced'.",
|
| 99 |
+
"Critical class (~2%) recall should be monitored separately."
|
| 100 |
+
]
|
| 101 |
+
}
|
artifacts/models/risk_model/model.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d10e1aed1d17c9b2973771c900a258d13393df793c0b766667546904a0af505a
|
| 3 |
+
size 151205
|
artifacts/models/risk_model/model_card.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Model Card: Risk Model
|
| 2 |
+
|
| 3 |
+
## Model Details
|
| 4 |
+
|
| 5 |
+
- **Model Name:** risk_model
|
| 6 |
+
- **Model Version:** risk_model_v2_baseline_001
|
| 7 |
+
- **Algorithm:** RandomForestClassifier (class_weight="balanced")
|
| 8 |
+
- **Framework:** scikit-learn
|
| 9 |
+
- **Trained At:** 2026-05-22T05:33:10.882126+00:00
|
| 10 |
+
- **Seed:** 20260520
|
| 11 |
+
|
| 12 |
+
## Intended Use
|
| 13 |
+
|
| 14 |
+
Predict whether a student is at-risk (binary: 0=not at-risk, 1=at-risk) based on
|
| 15 |
+
mastery, performance, and engagement features. Used in the risk prediction endpoint
|
| 16 |
+
to identify students who may need intervention. Primary optimization target is
|
| 17 |
+
recall on the positive class to minimize missed at-risk students.
|
| 18 |
+
|
| 19 |
+
## Training Data
|
| 20 |
+
|
| 21 |
+
- **Source:** training_risk_prediction.csv (synthetic dataset v2)
|
| 22 |
+
- **Split Counts:** train=1133, validation=243, test=244
|
| 23 |
+
- **Features:** avg_mastery_score, weak_lo_count, developing_lo_count, mastered_lo_count, avg_confidence, avg_accuracy, avg_marks_ratio, avg_time_seconds, hint_usage_rate, total_attempts, attendance_percentage, assignment_completion_rate, average_login_per_week, inactive_days_last_14, avg_active_minutes, total_logins, avg_video_watch_ratio, total_content_completed, total_quiz_attempts (all numeric, 19 features)
|
| 24 |
+
- **Target:** risk_label (binary 0/1)
|
| 25 |
+
- **Class Imbalance:** ~16% positive class, addressed via class_weight="balanced"
|
| 26 |
+
|
| 27 |
+
## Metrics
|
| 28 |
+
|
| 29 |
+
### Validation Set
|
| 30 |
+
- Recall (positive): 0.8571
|
| 31 |
+
- Precision (positive): 0.9231
|
| 32 |
+
- F1 (positive): 0.8889
|
| 33 |
+
- ROC-AUC: 0.9915
|
| 34 |
+
|
| 35 |
+
### Test Set
|
| 36 |
+
- Recall (positive): 0.8125
|
| 37 |
+
- Precision (positive): 0.8966
|
| 38 |
+
- F1 (positive): 0.8525
|
| 39 |
+
- ROC-AUC: 0.9899
|
| 40 |
+
|
| 41 |
+
## Per-Class Performance (Test Set)
|
| 42 |
+
|
| 43 |
+
| Class | Precision | Recall | F1 | Support |
|
| 44 |
+
|-------|-----------|--------|-----|---------|
|
| 45 |
+
| not_at_risk | 0.9721 | 0.9858 | 0.9789 | 212 |
|
| 46 |
+
| at_risk | 0.8966 | 0.8125 | 0.8525 | 32 |
|
| 47 |
+
|
| 48 |
+
## Risk Level Recall (Test Set)
|
| 49 |
+
|
| 50 |
+
| Risk Level | Recall | Support |
|
| 51 |
+
|------------|--------|---------|
|
| 52 |
+
| high | 0.7778 | 27 |
|
| 53 |
+
| critical | 1.0 | 5 |
|
| 54 |
+
|
| 55 |
+
## Known Limitations
|
| 56 |
+
|
| 57 |
+
- Trained on synthetic data only — performance on real student data is unknown.
|
| 58 |
+
- Binary risk_label derived from synthetic risk_score thresholds.
|
| 59 |
+
- All features are numeric; no text or contextual features used.
|
| 60 |
+
- Class imbalance (~16% positive) addressed via class_weight="balanced".
|
| 61 |
+
- Critical class (~2%) is very rare; recall on critical should be monitored.
|
| 62 |
+
- No temporal features (trend over time) included in this baseline.
|
| 63 |
+
|
| 64 |
+
## Fallback Behavior
|
| 65 |
+
|
| 66 |
+
When the model is not loaded or confidence is below the threshold (0.55),
|
| 67 |
+
the system falls back to rule-based risk estimation using:
|
| 68 |
+
- inactive_days_last_14 > 7 → high risk
|
| 69 |
+
- attendance_percentage < 60% → high risk
|
| 70 |
+
- avg_mastery_score < 0.4 → medium risk
|
| 71 |
+
- Otherwise → low risk
|
artifacts/models/risk_model/training_config.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model_name": "risk_model",
|
| 3 |
+
"model_version": "risk_model_v2_baseline_001",
|
| 4 |
+
"dataset_version": "2.0.0",
|
| 5 |
+
"seed": 20260520,
|
| 6 |
+
"split_counts": {
|
| 7 |
+
"train": 1133,
|
| 8 |
+
"validation": 243,
|
| 9 |
+
"test": 244
|
| 10 |
+
},
|
| 11 |
+
"hyperparameters": {
|
| 12 |
+
"n_estimators": 100,
|
| 13 |
+
"class_weight": "balanced",
|
| 14 |
+
"random_state": 20260520,
|
| 15 |
+
"algorithm": "RandomForestClassifier"
|
| 16 |
+
},
|
| 17 |
+
"feature_columns": [
|
| 18 |
+
"avg_mastery_score",
|
| 19 |
+
"weak_lo_count",
|
| 20 |
+
"developing_lo_count",
|
| 21 |
+
"mastered_lo_count",
|
| 22 |
+
"avg_confidence",
|
| 23 |
+
"avg_accuracy",
|
| 24 |
+
"avg_marks_ratio",
|
| 25 |
+
"avg_time_seconds",
|
| 26 |
+
"hint_usage_rate",
|
| 27 |
+
"total_attempts",
|
| 28 |
+
"attendance_percentage",
|
| 29 |
+
"assignment_completion_rate",
|
| 30 |
+
"average_login_per_week",
|
| 31 |
+
"inactive_days_last_14",
|
| 32 |
+
"avg_active_minutes",
|
| 33 |
+
"total_logins",
|
| 34 |
+
"avg_video_watch_ratio",
|
| 35 |
+
"total_content_completed",
|
| 36 |
+
"total_quiz_attempts"
|
| 37 |
+
],
|
| 38 |
+
"target_column": "risk_label",
|
| 39 |
+
"label_map": {
|
| 40 |
+
"0": "not_at_risk",
|
| 41 |
+
"1": "at_risk"
|
| 42 |
+
},
|
| 43 |
+
"algorithm": "RandomForestClassifier"
|
| 44 |
+
}
|