QuizGenerator 0.4.3__py3-none-any.whl → 0.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- QuizGenerator/contentast.py +949 -80
- QuizGenerator/generate.py +44 -7
- QuizGenerator/misc.py +4 -554
- QuizGenerator/mixins.py +47 -25
- QuizGenerator/premade_questions/cst334/languages.py +139 -125
- QuizGenerator/premade_questions/cst334/math_questions.py +78 -66
- QuizGenerator/premade_questions/cst334/memory_questions.py +258 -144
- QuizGenerator/premade_questions/cst334/persistence_questions.py +71 -33
- QuizGenerator/premade_questions/cst334/process.py +51 -20
- QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py +32 -6
- QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py +59 -34
- QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py +27 -8
- QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py +53 -32
- QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py +228 -88
- QuizGenerator/premade_questions/cst463/models/attention.py +26 -10
- QuizGenerator/premade_questions/cst463/models/cnns.py +32 -19
- QuizGenerator/premade_questions/cst463/models/rnns.py +25 -12
- QuizGenerator/premade_questions/cst463/models/text.py +26 -11
- QuizGenerator/premade_questions/cst463/models/weight_counting.py +36 -22
- QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py +89 -109
- QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py +126 -53
- QuizGenerator/question.py +110 -15
- QuizGenerator/quiz.py +74 -23
- QuizGenerator/regenerate.py +98 -29
- {quizgenerator-0.4.3.dist-info → quizgenerator-0.5.0.dist-info}/METADATA +1 -1
- {quizgenerator-0.4.3.dist-info → quizgenerator-0.5.0.dist-info}/RECORD +29 -31
- QuizGenerator/README.md +0 -5
- QuizGenerator/logging.yaml +0 -55
- {quizgenerator-0.4.3.dist-info → quizgenerator-0.5.0.dist-info}/WHEEL +0 -0
- {quizgenerator-0.4.3.dist-info → quizgenerator-0.5.0.dist-info}/entry_points.txt +0 -0
- {quizgenerator-0.4.3.dist-info → quizgenerator-0.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -566,13 +566,15 @@ class ForwardPassQuestion(SimpleNeuralNetworkBase):
|
|
|
566
566
|
# Hidden layer activations
|
|
567
567
|
for i in range(self.num_hidden):
|
|
568
568
|
key = f"h{i+1}"
|
|
569
|
-
self.answers[key] = Answer.float_value(key, float(self.a1[i]))
|
|
569
|
+
self.answers[key] = Answer.float_value(key, float(self.a1[i]), label=f"h_{i+1}")
|
|
570
570
|
|
|
571
571
|
# Output
|
|
572
|
-
self.answers["y_pred"] = Answer.float_value("y_pred", float(self.a2[0]))
|
|
572
|
+
self.answers["y_pred"] = Answer.float_value("y_pred", float(self.a2[0]), label="ŷ")
|
|
573
573
|
|
|
574
|
-
def
|
|
574
|
+
def _get_body(self, **kwargs) -> Tuple[ContentAST.Section, List[Answer]]:
|
|
575
|
+
"""Build question body and collect answers."""
|
|
575
576
|
body = ContentAST.Section()
|
|
577
|
+
answers = []
|
|
576
578
|
|
|
577
579
|
# Question description
|
|
578
580
|
body.add_element(ContentAST.Paragraph([
|
|
@@ -597,28 +599,23 @@ class ForwardPassQuestion(SimpleNeuralNetworkBase):
|
|
|
597
599
|
f"**Hidden layer activation:** {self._get_activation_name()}"
|
|
598
600
|
]))
|
|
599
601
|
|
|
600
|
-
#
|
|
601
|
-
answers = []
|
|
602
|
+
# Collect answers
|
|
602
603
|
for i in range(self.num_hidden):
|
|
603
|
-
answers.append(
|
|
604
|
-
ContentAST.Answer(
|
|
605
|
-
answer=self.answers[f"h{i+1}"],
|
|
606
|
-
label=f"h_{i+1}"
|
|
607
|
-
)
|
|
608
|
-
)
|
|
604
|
+
answers.append(self.answers[f"h{i+1}"])
|
|
609
605
|
|
|
610
|
-
answers.append(
|
|
611
|
-
ContentAST.Answer(
|
|
612
|
-
answer=self.answers["y_pred"],
|
|
613
|
-
label="ŷ"
|
|
614
|
-
)
|
|
615
|
-
)
|
|
606
|
+
answers.append(self.answers["y_pred"])
|
|
616
607
|
|
|
617
608
|
body.add_element(ContentAST.AnswerBlock(answers))
|
|
618
609
|
|
|
610
|
+
return body, answers
|
|
611
|
+
|
|
612
|
+
def get_body(self, **kwargs) -> ContentAST.Section:
|
|
613
|
+
"""Build question body (backward compatible interface)."""
|
|
614
|
+
body, _ = self._get_body(**kwargs)
|
|
619
615
|
return body
|
|
620
616
|
|
|
621
|
-
def
|
|
617
|
+
def _get_explanation(self, **kwargs) -> Tuple[ContentAST.Section, List[Answer]]:
|
|
618
|
+
"""Build question explanation."""
|
|
622
619
|
explanation = ContentAST.Section()
|
|
623
620
|
|
|
624
621
|
explanation.add_element(ContentAST.Paragraph([
|
|
@@ -695,6 +692,11 @@ class ForwardPassQuestion(SimpleNeuralNetworkBase):
|
|
|
695
692
|
"so the output is between 0 and 1, representing the probability of class 1)"
|
|
696
693
|
]))
|
|
697
694
|
|
|
695
|
+
return explanation, []
|
|
696
|
+
|
|
697
|
+
def get_explanation(self, **kwargs) -> ContentAST.Section:
|
|
698
|
+
"""Build question explanation (backward compatible interface)."""
|
|
699
|
+
explanation, _ = self._get_explanation(**kwargs)
|
|
698
700
|
return explanation
|
|
699
701
|
|
|
700
702
|
|
|
@@ -741,15 +743,17 @@ class BackpropGradientQuestion(SimpleNeuralNetworkBase):
|
|
|
741
743
|
# Gradient for W2 (hidden to output)
|
|
742
744
|
for i in range(self.num_hidden):
|
|
743
745
|
key = f"dL_dw2_{i}"
|
|
744
|
-
self.answers[key] = Answer.auto_float(key, self._compute_gradient_W2(i))
|
|
746
|
+
self.answers[key] = Answer.auto_float(key, self._compute_gradient_W2(i), label=f"∂L/∂w_{i+3}")
|
|
745
747
|
|
|
746
748
|
# Gradient for W1 (input to hidden) - pick first hidden neuron
|
|
747
749
|
for j in range(self.num_inputs):
|
|
748
750
|
key = f"dL_dw1_0{j}"
|
|
749
|
-
self.answers[key] = Answer.auto_float(key, self._compute_gradient_W1(0, j))
|
|
751
|
+
self.answers[key] = Answer.auto_float(key, self._compute_gradient_W1(0, j), label=f"∂L/∂w_1{j+1}")
|
|
750
752
|
|
|
751
|
-
def
|
|
753
|
+
def _get_body(self, **kwargs) -> Tuple[ContentAST.Section, List[Answer]]:
|
|
754
|
+
"""Build question body and collect answers."""
|
|
752
755
|
body = ContentAST.Section()
|
|
756
|
+
answers = []
|
|
753
757
|
|
|
754
758
|
# Question description
|
|
755
759
|
body.add_element(ContentAST.Paragraph([
|
|
@@ -779,32 +783,25 @@ class BackpropGradientQuestion(SimpleNeuralNetworkBase):
|
|
|
779
783
|
"**Calculate the following gradients:**"
|
|
780
784
|
]))
|
|
781
785
|
|
|
782
|
-
#
|
|
783
|
-
answers = []
|
|
784
|
-
|
|
785
|
-
# W2 gradients
|
|
786
|
+
# Collect W2 gradient answers
|
|
786
787
|
for i in range(self.num_hidden):
|
|
787
|
-
answers.append(
|
|
788
|
-
ContentAST.Answer(
|
|
789
|
-
answer=self.answers[f"dL_dw2_{i}"],
|
|
790
|
-
label=f"∂L/∂w_{i+3}"
|
|
791
|
-
)
|
|
792
|
-
)
|
|
788
|
+
answers.append(self.answers[f"dL_dw2_{i}"])
|
|
793
789
|
|
|
794
|
-
# W1
|
|
790
|
+
# Collect W1 gradient answers (first hidden neuron)
|
|
795
791
|
for j in range(self.num_inputs):
|
|
796
|
-
answers.append(
|
|
797
|
-
ContentAST.Answer(
|
|
798
|
-
answer=self.answers[f"dL_dw1_0{j}"],
|
|
799
|
-
label=f"∂L/∂w_1{j+1}"
|
|
800
|
-
)
|
|
801
|
-
)
|
|
792
|
+
answers.append(self.answers[f"dL_dw1_0{j}"])
|
|
802
793
|
|
|
803
794
|
body.add_element(ContentAST.AnswerBlock(answers))
|
|
804
795
|
|
|
796
|
+
return body, answers
|
|
797
|
+
|
|
798
|
+
def get_body(self, **kwargs) -> ContentAST.Section:
|
|
799
|
+
"""Build question body (backward compatible interface)."""
|
|
800
|
+
body, _ = self._get_body(**kwargs)
|
|
805
801
|
return body
|
|
806
802
|
|
|
807
|
-
def
|
|
803
|
+
def _get_explanation(self, **kwargs) -> Tuple[ContentAST.Section, List[Answer]]:
|
|
804
|
+
"""Build question explanation."""
|
|
808
805
|
explanation = ContentAST.Section()
|
|
809
806
|
|
|
810
807
|
explanation.add_element(ContentAST.Paragraph([
|
|
@@ -875,6 +872,11 @@ class BackpropGradientQuestion(SimpleNeuralNetworkBase):
|
|
|
875
872
|
inline=False
|
|
876
873
|
))
|
|
877
874
|
|
|
875
|
+
return explanation, []
|
|
876
|
+
|
|
877
|
+
def get_explanation(self, **kwargs) -> ContentAST.Section:
|
|
878
|
+
"""Build question explanation (backward compatible interface)."""
|
|
879
|
+
explanation, _ = self._get_explanation(**kwargs)
|
|
878
880
|
return explanation
|
|
879
881
|
|
|
880
882
|
|
|
@@ -918,14 +920,16 @@ class EnsembleAveragingQuestion(Question):
|
|
|
918
920
|
|
|
919
921
|
# Mean prediction
|
|
920
922
|
mean_pred = np.mean(self.predictions)
|
|
921
|
-
self.answers["mean"] = Answer.float_value("mean", float(mean_pred))
|
|
923
|
+
self.answers["mean"] = Answer.float_value("mean", float(mean_pred), label="Mean (average)")
|
|
922
924
|
|
|
923
925
|
# Median (optional, but useful)
|
|
924
926
|
median_pred = np.median(self.predictions)
|
|
925
|
-
self.answers["median"] = Answer.float_value("median", float(median_pred))
|
|
927
|
+
self.answers["median"] = Answer.float_value("median", float(median_pred), label="Median")
|
|
926
928
|
|
|
927
|
-
def
|
|
929
|
+
def _get_body(self, **kwargs) -> Tuple[ContentAST.Section, List[Answer]]:
|
|
930
|
+
"""Build question body and collect answers."""
|
|
928
931
|
body = ContentAST.Section()
|
|
932
|
+
answers = []
|
|
929
933
|
|
|
930
934
|
# Question description
|
|
931
935
|
body.add_element(ContentAST.Paragraph([
|
|
@@ -944,26 +948,21 @@ class EnsembleAveragingQuestion(Question):
|
|
|
944
948
|
"To create an ensemble, calculate the combined prediction using the following methods:"
|
|
945
949
|
]))
|
|
946
950
|
|
|
947
|
-
#
|
|
948
|
-
answers
|
|
949
|
-
answers.append(
|
|
950
|
-
ContentAST.Answer(
|
|
951
|
-
answer=self.answers["mean"],
|
|
952
|
-
label="Mean (average)"
|
|
953
|
-
)
|
|
954
|
-
)
|
|
955
|
-
answers.append(
|
|
956
|
-
ContentAST.Answer(
|
|
957
|
-
answer=self.answers["median"],
|
|
958
|
-
label="Median"
|
|
959
|
-
)
|
|
960
|
-
)
|
|
951
|
+
# Collect answers
|
|
952
|
+
answers.append(self.answers["mean"])
|
|
953
|
+
answers.append(self.answers["median"])
|
|
961
954
|
|
|
962
955
|
body.add_element(ContentAST.AnswerBlock(answers))
|
|
963
956
|
|
|
957
|
+
return body, answers
|
|
958
|
+
|
|
959
|
+
def get_body(self, **kwargs) -> ContentAST.Section:
|
|
960
|
+
"""Build question body (backward compatible interface)."""
|
|
961
|
+
body, _ = self._get_body(**kwargs)
|
|
964
962
|
return body
|
|
965
963
|
|
|
966
|
-
def
|
|
964
|
+
def _get_explanation(self, **kwargs) -> Tuple[ContentAST.Section, List[Answer]]:
|
|
965
|
+
"""Build question explanation."""
|
|
967
966
|
explanation = ContentAST.Section()
|
|
968
967
|
|
|
969
968
|
explanation.add_element(ContentAST.Paragraph([
|
|
@@ -1009,6 +1008,11 @@ class EnsembleAveragingQuestion(Question):
|
|
|
1009
1008
|
f"({sorted_preds[mid_idx1]:.1f} + {sorted_preds[mid_idx2]:.1f}) / 2 = {median_val:.1f}"
|
|
1010
1009
|
]))
|
|
1011
1010
|
|
|
1011
|
+
return explanation, []
|
|
1012
|
+
|
|
1013
|
+
def get_explanation(self, **kwargs) -> ContentAST.Section:
|
|
1014
|
+
"""Build question explanation (backward compatible interface)."""
|
|
1015
|
+
explanation, _ = self._get_explanation(**kwargs)
|
|
1012
1016
|
return explanation
|
|
1013
1017
|
|
|
1014
1018
|
|
|
@@ -1079,21 +1083,23 @@ class EndToEndTrainingQuestion(SimpleNeuralNetworkBase):
|
|
|
1079
1083
|
self.answers = {}
|
|
1080
1084
|
|
|
1081
1085
|
# Forward pass answers
|
|
1082
|
-
self.answers["y_pred"] = Answer.float_value("y_pred", float(self.a2[0]))
|
|
1086
|
+
self.answers["y_pred"] = Answer.float_value("y_pred", float(self.a2[0]), label="1. Forward Pass - Network output ŷ")
|
|
1083
1087
|
|
|
1084
1088
|
# Loss answer
|
|
1085
|
-
self.answers["loss"] = Answer.float_value("loss", float(self.loss))
|
|
1089
|
+
self.answers["loss"] = Answer.float_value("loss", float(self.loss), label="2. Loss")
|
|
1086
1090
|
|
|
1087
1091
|
# Gradient answers (for key weights)
|
|
1088
|
-
self.answers["grad_w3"] = Answer.auto_float("grad_w3", self._compute_gradient_W2(0))
|
|
1089
|
-
self.answers["grad_w11"] = Answer.auto_float("grad_w11", self._compute_gradient_W1(0, 0))
|
|
1092
|
+
self.answers["grad_w3"] = Answer.auto_float("grad_w3", self._compute_gradient_W2(0), label="3. Gradient ∂L/∂w₃")
|
|
1093
|
+
self.answers["grad_w11"] = Answer.auto_float("grad_w11", self._compute_gradient_W1(0, 0), label="4. Gradient ∂L/∂w₁₁")
|
|
1090
1094
|
|
|
1091
1095
|
# Updated weight answers
|
|
1092
|
-
self.answers["new_w3"] = Answer.float_value("new_w3", float(self.new_W2[0, 0]))
|
|
1093
|
-
self.answers["new_w11"] = Answer.float_value("new_w11", float(self.new_W1[0, 0]))
|
|
1096
|
+
self.answers["new_w3"] = Answer.float_value("new_w3", float(self.new_W2[0, 0]), label="5. Updated w₃:")
|
|
1097
|
+
self.answers["new_w11"] = Answer.float_value("new_w11", float(self.new_W1[0, 0]), label="6. Updated w₁₁:")
|
|
1094
1098
|
|
|
1095
|
-
def
|
|
1099
|
+
def _get_body(self, **kwargs) -> Tuple[ContentAST.Section, List[Answer]]:
|
|
1100
|
+
"""Build question body and collect answers."""
|
|
1096
1101
|
body = ContentAST.Section()
|
|
1102
|
+
answers = []
|
|
1097
1103
|
|
|
1098
1104
|
# Question description
|
|
1099
1105
|
body.add_element(ContentAST.Paragraph([
|
|
@@ -1139,56 +1145,25 @@ class EndToEndTrainingQuestion(SimpleNeuralNetworkBase):
|
|
|
1139
1145
|
# Network parameters table
|
|
1140
1146
|
body.add_element(self._generate_parameter_table(include_activations=False))
|
|
1141
1147
|
|
|
1142
|
-
#
|
|
1143
|
-
answers
|
|
1144
|
-
|
|
1145
|
-
answers.append(
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
)
|
|
1150
|
-
)
|
|
1151
|
-
|
|
1152
|
-
answers.append(
|
|
1153
|
-
ContentAST.Answer(
|
|
1154
|
-
answer=self.answers["loss"],
|
|
1155
|
-
label="2. Loss"
|
|
1156
|
-
)
|
|
1157
|
-
)
|
|
1158
|
-
|
|
1159
|
-
answers.append(
|
|
1160
|
-
ContentAST.Answer(
|
|
1161
|
-
answer=self.answers["grad_w3"],
|
|
1162
|
-
label="3. Gradient ∂L/∂w₃"
|
|
1163
|
-
)
|
|
1164
|
-
)
|
|
1165
|
-
|
|
1166
|
-
answers.append(
|
|
1167
|
-
ContentAST.Answer(
|
|
1168
|
-
answer=self.answers["grad_w11"],
|
|
1169
|
-
label="4. Gradient ∂L/∂w₁₁"
|
|
1170
|
-
)
|
|
1171
|
-
)
|
|
1172
|
-
|
|
1173
|
-
answers.append(
|
|
1174
|
-
ContentAST.Answer(
|
|
1175
|
-
answer=self.answers["new_w3"],
|
|
1176
|
-
label="5. Updated w₃:"
|
|
1177
|
-
)
|
|
1178
|
-
)
|
|
1179
|
-
|
|
1180
|
-
answers.append(
|
|
1181
|
-
ContentAST.Answer(
|
|
1182
|
-
answer=self.answers["new_w11"],
|
|
1183
|
-
label="6. Updated w₁₁:"
|
|
1184
|
-
)
|
|
1185
|
-
)
|
|
1148
|
+
# Collect answers
|
|
1149
|
+
answers.append(self.answers["y_pred"])
|
|
1150
|
+
answers.append(self.answers["loss"])
|
|
1151
|
+
answers.append(self.answers["grad_w3"])
|
|
1152
|
+
answers.append(self.answers["grad_w11"])
|
|
1153
|
+
answers.append(self.answers["new_w3"])
|
|
1154
|
+
answers.append(self.answers["new_w11"])
|
|
1186
1155
|
|
|
1187
1156
|
body.add_element(ContentAST.AnswerBlock(answers))
|
|
1188
1157
|
|
|
1158
|
+
return body, answers
|
|
1159
|
+
|
|
1160
|
+
def get_body(self, **kwargs) -> ContentAST.Section:
|
|
1161
|
+
"""Build question body (backward compatible interface)."""
|
|
1162
|
+
body, _ = self._get_body(**kwargs)
|
|
1189
1163
|
return body
|
|
1190
1164
|
|
|
1191
|
-
def
|
|
1165
|
+
def _get_explanation(self, **kwargs) -> Tuple[ContentAST.Section, List[Answer]]:
|
|
1166
|
+
"""Build question explanation."""
|
|
1192
1167
|
explanation = ContentAST.Section()
|
|
1193
1168
|
|
|
1194
1169
|
explanation.add_element(ContentAST.Paragraph([
|
|
@@ -1311,4 +1286,9 @@ class EndToEndTrainingQuestion(SimpleNeuralNetworkBase):
|
|
|
1311
1286
|
"These updated weights would be used in the next training iteration."
|
|
1312
1287
|
]))
|
|
1313
1288
|
|
|
1289
|
+
return explanation, []
|
|
1290
|
+
|
|
1291
|
+
def get_explanation(self, **kwargs) -> ContentAST.Section:
|
|
1292
|
+
"""Build question explanation (backward compatible interface)."""
|
|
1293
|
+
explanation, _ = self._get_explanation(**kwargs)
|
|
1314
1294
|
return explanation
|