QuizGenerator 0.4.4__py3-none-any.whl → 0.5.1__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 +952 -82
- QuizGenerator/generate.py +45 -9
- 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 +554 -64
- 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 +117 -51
- QuizGenerator/question.py +110 -15
- QuizGenerator/quiz.py +81 -24
- QuizGenerator/regenerate.py +98 -29
- {quizgenerator-0.4.4.dist-info → quizgenerator-0.5.1.dist-info}/METADATA +1 -1
- {quizgenerator-0.4.4.dist-info → quizgenerator-0.5.1.dist-info}/RECORD +29 -31
- QuizGenerator/README.md +0 -5
- QuizGenerator/logging.yaml +0 -55
- {quizgenerator-0.4.4.dist-info → quizgenerator-0.5.1.dist-info}/WHEEL +0 -0
- {quizgenerator-0.4.4.dist-info → quizgenerator-0.5.1.dist-info}/entry_points.txt +0 -0
- {quizgenerator-0.4.4.dist-info → quizgenerator-0.5.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -3,9 +3,10 @@ import logging
|
|
|
3
3
|
import math
|
|
4
4
|
import keras
|
|
5
5
|
import numpy as np
|
|
6
|
+
from typing import List, Tuple
|
|
6
7
|
|
|
7
|
-
from QuizGenerator.question import Question, QuestionRegistry
|
|
8
|
-
from QuizGenerator.misc import
|
|
8
|
+
from QuizGenerator.question import Question, QuestionRegistry, Answer
|
|
9
|
+
from QuizGenerator.misc import MatrixAnswer
|
|
9
10
|
from QuizGenerator.contentast import ContentAST
|
|
10
11
|
from QuizGenerator.constants import MathRanges
|
|
11
12
|
from .matrices import MatrixQuestion
|
|
@@ -65,22 +66,24 @@ class ConvolutionCalculation(MatrixQuestion):
|
|
|
65
66
|
self.result = self.conv2d_multi_channel(self.image, self.kernel, stride=self.stride, padding=self.padding)
|
|
66
67
|
|
|
67
68
|
self.answers = {
|
|
68
|
-
f"result_{i}" : MatrixAnswer(f"result_{i}", self.result[:,:,i])
|
|
69
|
+
f"result_{i}" : MatrixAnswer(f"result_{i}", self.result[:,:,i], label=f"Result of filter {i}")
|
|
69
70
|
for i in range(self.result.shape[-1])
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
return True
|
|
73
74
|
|
|
74
|
-
def
|
|
75
|
+
def _get_body(self, **kwargs) -> Tuple[ContentAST.Section, List[Answer]]:
|
|
76
|
+
"""Build question body and collect answers."""
|
|
75
77
|
body = ContentAST.Section()
|
|
76
|
-
|
|
78
|
+
answers = []
|
|
79
|
+
|
|
77
80
|
body.add_elements(
|
|
78
81
|
[
|
|
79
82
|
ContentAST.Text("Given image represented as matrix: "),
|
|
80
83
|
ContentAST.Matrix(self.image, name="image")
|
|
81
84
|
]
|
|
82
85
|
)
|
|
83
|
-
|
|
86
|
+
|
|
84
87
|
body.add_elements(
|
|
85
88
|
[
|
|
86
89
|
ContentAST.Text("And convolution filters: "),
|
|
@@ -89,7 +92,7 @@ class ConvolutionCalculation(MatrixQuestion):
|
|
|
89
92
|
for i in range(self.kernel.shape[-1])
|
|
90
93
|
]
|
|
91
94
|
)
|
|
92
|
-
|
|
95
|
+
|
|
93
96
|
body.add_element(
|
|
94
97
|
ContentAST.Paragraph(
|
|
95
98
|
[
|
|
@@ -97,22 +100,27 @@ class ConvolutionCalculation(MatrixQuestion):
|
|
|
97
100
|
]
|
|
98
101
|
)
|
|
99
102
|
)
|
|
100
|
-
|
|
103
|
+
|
|
101
104
|
body.add_element(ContentAST.LineBreak())
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
ContentAST.
|
|
105
|
+
|
|
106
|
+
for i in range(self.result.shape[-1]):
|
|
107
|
+
answers.append(self.answers[f"result_{i}"])
|
|
108
|
+
body.add_elements([
|
|
109
|
+
ContentAST.Container([
|
|
110
|
+
self.answers[f"result_{i}"],
|
|
111
|
+
ContentAST.LineBreak()
|
|
112
|
+
])
|
|
107
113
|
])
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
114
|
+
|
|
115
|
+
return body, answers
|
|
116
|
+
|
|
117
|
+
def get_body(self, **kwargs) -> ContentAST.Section:
|
|
118
|
+
"""Build question body (backward compatible interface)."""
|
|
119
|
+
body, _ = self._get_body(**kwargs)
|
|
113
120
|
return body
|
|
114
121
|
|
|
115
|
-
def
|
|
122
|
+
def _get_explanation(self, **kwargs) -> Tuple[ContentAST.Section, List[Answer]]:
|
|
123
|
+
"""Build question explanation."""
|
|
116
124
|
explanation = ContentAST.Section()
|
|
117
125
|
digits = Answer.DEFAULT_ROUNDING_DIGITS
|
|
118
126
|
|
|
@@ -183,4 +191,9 @@ class ConvolutionCalculation(MatrixQuestion):
|
|
|
183
191
|
ContentAST.Matrix(np.round(self.result[:, :, f_idx], digits))
|
|
184
192
|
)
|
|
185
193
|
|
|
194
|
+
return explanation, []
|
|
195
|
+
|
|
196
|
+
def get_explanation(self, **kwargs) -> ContentAST.Section:
|
|
197
|
+
"""Build question explanation (backward compatible interface)."""
|
|
198
|
+
explanation, _ = self._get_explanation(**kwargs)
|
|
186
199
|
return explanation
|
|
@@ -3,6 +3,7 @@ import logging
|
|
|
3
3
|
import math
|
|
4
4
|
import keras
|
|
5
5
|
import numpy as np
|
|
6
|
+
from typing import List, Tuple
|
|
6
7
|
|
|
7
8
|
from .matrices import MatrixQuestion
|
|
8
9
|
from QuizGenerator.question import Question, QuestionRegistry, Answer
|
|
@@ -63,13 +64,15 @@ class RNNForwardPass(MatrixQuestion, TableQuestionMixin):
|
|
|
63
64
|
## Answers:
|
|
64
65
|
# x_seq, W_xh, W_hh, b_h, h_0, h_states
|
|
65
66
|
|
|
66
|
-
self.answers["output_sequence"] = Answer.matrix(key="output_sequence", value=self.h_states)
|
|
67
|
+
self.answers["output_sequence"] = Answer.matrix(key="output_sequence", value=self.h_states, label="Hidden states")
|
|
67
68
|
|
|
68
69
|
return True
|
|
69
70
|
|
|
70
|
-
def
|
|
71
|
+
def _get_body(self, **kwargs) -> Tuple[ContentAST.Section, List[Answer]]:
|
|
72
|
+
"""Build question body and collect answers."""
|
|
71
73
|
body = ContentAST.Section()
|
|
72
|
-
|
|
74
|
+
answers = []
|
|
75
|
+
|
|
73
76
|
body.add_element(
|
|
74
77
|
ContentAST.Paragraph([
|
|
75
78
|
ContentAST.Text("Given the below information about an RNN, please calculate the output sequence."),
|
|
@@ -87,22 +90,27 @@ class RNNForwardPass(MatrixQuestion, TableQuestionMixin):
|
|
|
87
90
|
}
|
|
88
91
|
)
|
|
89
92
|
)
|
|
90
|
-
|
|
93
|
+
|
|
91
94
|
body.add_element(ContentAST.LineBreak())
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
|
|
96
|
+
answers.append(self.answers["output_sequence"])
|
|
97
|
+
body.add_element(self.answers["output_sequence"])
|
|
98
|
+
|
|
99
|
+
return body, answers
|
|
100
|
+
|
|
101
|
+
def get_body(self, **kwargs) -> ContentAST.Section:
|
|
102
|
+
"""Build question body (backward compatible interface)."""
|
|
103
|
+
body, _ = self._get_body(**kwargs)
|
|
97
104
|
return body
|
|
98
105
|
|
|
99
|
-
def
|
|
106
|
+
def _get_explanation(self, **kwargs) -> Tuple[ContentAST.Section, List[Answer]]:
|
|
107
|
+
"""Build question explanation."""
|
|
100
108
|
explanation = ContentAST.Section()
|
|
101
109
|
digits = Answer.DEFAULT_ROUNDING_DIGITS
|
|
102
110
|
|
|
103
111
|
explanation.add_element(
|
|
104
112
|
ContentAST.Paragraph([
|
|
105
|
-
|
|
113
|
+
"For an RNN forward pass, we compute the hidden state at each time step using:"
|
|
106
114
|
])
|
|
107
115
|
)
|
|
108
116
|
|
|
@@ -128,7 +136,7 @@ class RNNForwardPass(MatrixQuestion, TableQuestionMixin):
|
|
|
128
136
|
# Show detailed examples for first 2 timesteps (or just 1 if seq_len == 1)
|
|
129
137
|
seq_len = len(self.x_seq)
|
|
130
138
|
num_examples = min(2, seq_len)
|
|
131
|
-
|
|
139
|
+
|
|
132
140
|
explanation.add_element(ContentAST.Paragraph([""]))
|
|
133
141
|
|
|
134
142
|
for t in range(num_examples):
|
|
@@ -198,5 +206,10 @@ class RNNForwardPass(MatrixQuestion, TableQuestionMixin):
|
|
|
198
206
|
ContentAST.Matrix(np.round(self.h_states, digits))
|
|
199
207
|
)
|
|
200
208
|
|
|
209
|
+
return explanation, []
|
|
210
|
+
|
|
211
|
+
def get_explanation(self, **kwargs) -> ContentAST.Section:
|
|
212
|
+
"""Build question explanation (backward compatible interface)."""
|
|
213
|
+
explanation, _ = self._get_explanation(**kwargs)
|
|
201
214
|
return explanation
|
|
202
215
|
|
|
@@ -3,6 +3,7 @@ import logging
|
|
|
3
3
|
import math
|
|
4
4
|
import keras
|
|
5
5
|
import numpy as np
|
|
6
|
+
from typing import List, Tuple
|
|
6
7
|
|
|
7
8
|
from QuizGenerator.misc import MatrixAnswer
|
|
8
9
|
from QuizGenerator.premade_questions.cst463.models.matrices import MatrixQuestion
|
|
@@ -59,17 +60,19 @@ class word2vec__skipgram(MatrixQuestion, TableQuestionMixin):
|
|
|
59
60
|
|
|
60
61
|
## Answers:
|
|
61
62
|
# center_word, center_emb, context_words, context_embs, logits, probs
|
|
62
|
-
self.answers["logits"] = Answer.vector_value(key="logits", value=self.logits)
|
|
63
|
+
self.answers["logits"] = Answer.vector_value(key="logits", value=self.logits, label="Logits")
|
|
63
64
|
most_likely_idx = np.argmax(self.probs)
|
|
64
65
|
most_likely_word = self.context_words[most_likely_idx]
|
|
65
|
-
self.answers["center_word"] = Answer.string(key="center_word", value=most_likely_word)
|
|
66
|
+
self.answers["center_word"] = Answer.string(key="center_word", value=most_likely_word, label="Most likely context word")
|
|
66
67
|
|
|
67
68
|
|
|
68
69
|
return True
|
|
69
70
|
|
|
70
|
-
def
|
|
71
|
+
def _get_body(self, **kwargs) -> Tuple[ContentAST.Section, List[Answer]]:
|
|
72
|
+
"""Build question body and collect answers."""
|
|
71
73
|
body = ContentAST.Section()
|
|
72
|
-
|
|
74
|
+
answers = []
|
|
75
|
+
|
|
73
76
|
body.add_element(
|
|
74
77
|
ContentAST.Paragraph([
|
|
75
78
|
f"Given center word: `{self.center_word}` with embedding {self.center_emb}, compute the skip-gram probabilities for each context word and identify the most likely one."
|
|
@@ -78,21 +81,28 @@ class word2vec__skipgram(MatrixQuestion, TableQuestionMixin):
|
|
|
78
81
|
body.add_elements([
|
|
79
82
|
ContentAST.Paragraph([ContentAST.Text(f"`{w}` : "), str(e)]) for w, e in zip(self.context_words, self.context_embs)
|
|
80
83
|
])
|
|
81
|
-
|
|
84
|
+
|
|
85
|
+
answers.append(self.answers["logits"])
|
|
86
|
+
answers.append(self.answers["center_word"])
|
|
82
87
|
body.add_elements([
|
|
83
88
|
ContentAST.LineBreak(),
|
|
84
|
-
self.answers["logits"]
|
|
89
|
+
self.answers["logits"],
|
|
85
90
|
ContentAST.LineBreak(),
|
|
86
|
-
self.answers["center_word"]
|
|
91
|
+
self.answers["center_word"]
|
|
87
92
|
])
|
|
88
|
-
|
|
89
|
-
|
|
93
|
+
|
|
90
94
|
log.debug(f"output: {self.logits}")
|
|
91
95
|
log.debug(f"weights: {self.probs}")
|
|
92
|
-
|
|
96
|
+
|
|
97
|
+
return body, answers
|
|
98
|
+
|
|
99
|
+
def get_body(self, **kwargs) -> ContentAST.Section:
|
|
100
|
+
"""Build question body (backward compatible interface)."""
|
|
101
|
+
body, _ = self._get_body(**kwargs)
|
|
93
102
|
return body
|
|
94
103
|
|
|
95
|
-
def
|
|
104
|
+
def _get_explanation(self, **kwargs) -> Tuple[ContentAST.Section, List[Answer]]:
|
|
105
|
+
"""Build question explanation."""
|
|
96
106
|
explanation = ContentAST.Section()
|
|
97
107
|
digits = Answer.DEFAULT_ROUNDING_DIGITS
|
|
98
108
|
|
|
@@ -199,5 +209,10 @@ class word2vec__skipgram(MatrixQuestion, TableQuestionMixin):
|
|
|
199
209
|
])
|
|
200
210
|
)
|
|
201
211
|
|
|
212
|
+
return explanation, []
|
|
213
|
+
|
|
214
|
+
def get_explanation(self, **kwargs) -> ContentAST.Section:
|
|
215
|
+
"""Build question explanation (backward compatible interface)."""
|
|
216
|
+
explanation, _ = self._get_explanation(**kwargs)
|
|
202
217
|
return explanation
|
|
203
218
|
|
|
@@ -3,6 +3,7 @@ import logging
|
|
|
3
3
|
import math
|
|
4
4
|
import keras
|
|
5
5
|
import numpy as np
|
|
6
|
+
from typing import List, Tuple
|
|
6
7
|
|
|
7
8
|
from QuizGenerator.question import Question, QuestionRegistry, Answer
|
|
8
9
|
from QuizGenerator.contentast import ContentAST
|
|
@@ -86,14 +87,17 @@ class WeightCounting(Question, abc.ABC):
|
|
|
86
87
|
self.num_parameters = self.model.count_params()
|
|
87
88
|
self.answers["num_parameters"] = Answer.integer(
|
|
88
89
|
"num_parameters",
|
|
89
|
-
self.num_parameters
|
|
90
|
+
self.num_parameters,
|
|
91
|
+
label="Number of Parameters"
|
|
90
92
|
)
|
|
91
93
|
|
|
92
94
|
return True
|
|
93
95
|
|
|
94
|
-
def
|
|
96
|
+
def _get_body(self, **kwargs) -> Tuple[ContentAST.Section, List[Answer]]:
|
|
97
|
+
"""Build question body and collect answers."""
|
|
95
98
|
body = ContentAST.Section()
|
|
96
|
-
|
|
99
|
+
answers = []
|
|
100
|
+
|
|
97
101
|
body.add_element(
|
|
98
102
|
ContentAST.Paragraph(
|
|
99
103
|
[
|
|
@@ -101,7 +105,7 @@ class WeightCounting(Question, abc.ABC):
|
|
|
101
105
|
]
|
|
102
106
|
)
|
|
103
107
|
)
|
|
104
|
-
|
|
108
|
+
|
|
105
109
|
body.add_element(
|
|
106
110
|
ContentAST.Code(
|
|
107
111
|
self.model_to_python(
|
|
@@ -110,18 +114,23 @@ class WeightCounting(Question, abc.ABC):
|
|
|
110
114
|
)
|
|
111
115
|
)
|
|
112
116
|
)
|
|
113
|
-
|
|
117
|
+
|
|
114
118
|
body.add_element(ContentAST.LineBreak())
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
119
|
+
|
|
120
|
+
answers.append(self.answers["num_parameters"])
|
|
121
|
+
body.add_element(self.answers["num_parameters"])
|
|
122
|
+
|
|
123
|
+
return body, answers
|
|
124
|
+
|
|
125
|
+
def get_body(self, **kwargs) -> ContentAST.Section:
|
|
126
|
+
"""Build question body (backward compatible interface)."""
|
|
127
|
+
body, _ = self._get_body(**kwargs)
|
|
120
128
|
return body
|
|
121
129
|
|
|
122
|
-
def
|
|
130
|
+
def _get_explanation(self, **kwargs) -> Tuple[ContentAST.Section, List[Answer]]:
|
|
131
|
+
"""Build question explanation."""
|
|
123
132
|
explanation = ContentAST.Section()
|
|
124
|
-
|
|
133
|
+
|
|
125
134
|
def markdown_summary(model) -> ContentAST.Table:
|
|
126
135
|
# Ensure the model is built by running build() or calling it once
|
|
127
136
|
if not model.built:
|
|
@@ -129,37 +138,42 @@ class WeightCounting(Question, abc.ABC):
|
|
|
129
138
|
model.build(model.input_shape)
|
|
130
139
|
except:
|
|
131
140
|
pass # Some subclassed models need real data to build
|
|
132
|
-
|
|
141
|
+
|
|
133
142
|
data = []
|
|
134
|
-
|
|
143
|
+
|
|
135
144
|
total_params = 0
|
|
136
|
-
|
|
145
|
+
|
|
137
146
|
for layer in model.layers:
|
|
138
147
|
name = layer.name
|
|
139
148
|
ltype = layer.__class__.__name__
|
|
140
|
-
|
|
149
|
+
|
|
141
150
|
# Try to extract output shape
|
|
142
151
|
try:
|
|
143
152
|
outshape = tuple(layer.output.shape)
|
|
144
153
|
except:
|
|
145
154
|
outshape = "?"
|
|
146
|
-
|
|
155
|
+
|
|
147
156
|
params = layer.count_params()
|
|
148
157
|
total_params += params
|
|
149
|
-
|
|
158
|
+
|
|
150
159
|
data.append([name, ltype, outshape, params])
|
|
151
|
-
|
|
160
|
+
|
|
152
161
|
data.append(["**Total**", "", "", f"**{total_params}**"])
|
|
153
162
|
return ContentAST.Table(data=data, headers=["Layer", "Type", "Output Shape", "Params"])
|
|
154
|
-
|
|
155
|
-
|
|
163
|
+
|
|
164
|
+
|
|
156
165
|
summary_lines = []
|
|
157
166
|
self.model.summary(print_fn=lambda x: summary_lines.append(x))
|
|
158
167
|
explanation.add_element(
|
|
159
168
|
# ContentAST.Text('\n'.join(summary_lines))
|
|
160
169
|
markdown_summary(self.model)
|
|
161
170
|
)
|
|
162
|
-
|
|
171
|
+
|
|
172
|
+
return explanation, []
|
|
173
|
+
|
|
174
|
+
def get_explanation(self, **kwargs) -> ContentAST.Section:
|
|
175
|
+
"""Build question explanation (backward compatible interface)."""
|
|
176
|
+
explanation, _ = self._get_explanation(**kwargs)
|
|
163
177
|
return explanation
|
|
164
178
|
|
|
165
179
|
|