AI Computer Institute
Expert-curated CS & AI curriculum aligned to CBSE standards. A bharath.ai initiative. About Us

Grade 11 AI & Computer Science Practice Questions — Set 4

20 questions from the Grade 11 bank, each with its answer and a full explanation. Set 4 of 11 · 221 questions in this grade.

Reading is revision; testing is practice. Take the same questions as a timed quiz →

Question 61 · GAN training dynamics · hard

In GAN training, the discriminator's sigmoid output satisfies D(G(z)) = σ(s), where s is the pre-activation logit, so dD(G(z))/ds = D(G(z))·(1 − D(G(z))). Suppose early in training the discriminator confidently rejects a batch of fake images, giving D(G(z)) = 0.02. Using the chain rule, what is the gradient of the generator's loss with respect to the logit s for the original minimax loss L = log(1 − D(G(z))) versus the non-saturating loss L' = −log(D(G(z))), and which one avoids the vanishing-gradient problem here?

  1. Applying the chain rule dL/ds = (dL/dD)·D(1−D) gives −D(G(z)) = −0.02 for the minimax loss and −(1−D(G(z))) = −0.98 for the non-saturating loss, so the non-saturating loss delivers a gradient roughly 49 times larger and drives generator learning far more effectively here.
  2. The same chain-rule computation instead yields −0.98 for the minimax loss and −0.02 for the non-saturating loss, meaning the original minimax formulation supplies the stronger gradient whenever the discriminator becomes confident about rejecting fakes.
  3. Because D(G(z))(1−D(G(z))) is a common factor in both derivatives, the two loss functions reduce to the identical expression dL/ds = −D(G(z))(1−D(G(z))), so both formulations produce exactly the same gradient magnitude of 0.0196 at this point.
  4. Differentiating each loss with respect to D(G(z)) rather than the logit s gives −1/(1−0.02) ≈ −1.02 for the minimax loss and −1/0.02 = −50 for the non-saturating loss, showing that the non-saturating loss produces the larger raw gradient at the discriminator's output layer.

Answer: A. Applying the chain rule dL/ds = (dL/dD)·D(1−D) gives −D(G(z)) = −0.02 for the minimax loss and −(1−D(G(z))) = −0.98 for the non-saturating loss, so the non-saturating loss delivers a gradient roughly 49 times larger and drives generator learning far more effectively here.

ExplanationThe discriminator's sigmoid gives dD(G(z))/ds = D(G(z))(1 − D(G(z))), the local derivative needed for the chain rule. For the minimax loss L = log(1 − D(G(z))), dL/dD(G(z)) = −1/(1 − D(G(z))); multiplying by the sigmoid's local derivative, dL/ds = [−1/(1−D(G(z)))]·[D(G(z))(1−D(G(z)))] = −D(G(z)) = −0.02. For the non-saturating loss L' = −log(D(G(z))), dL'/dD(G(z)) = −1/D(G(z)); multiplying by the same local derivative, dL'/ds = [−1/D(G(z))]·[D(G(z))(1−D(G(z)))] = −(1 − D(G(z))) = −0.98. Since |−0.98| is about 49 times |−0.02|, the non-saturating loss keeps the generator's gradient strong exactly when the minimax loss would vanish — this is why the original GAN paper recommends training the generator to maximize log(D(G(z))) rather than minimize log(1 − D(G(z))) once the discriminator becomes confident.

Question 62 · Optimization algorithms · hard

A neural network has exactly 2,000,000 trainable parameters, each stored as a 32-bit float (4 bytes), so the parameters themselves occupy 8 MB. One training run uses torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9), which keeps a single velocity buffer per parameter; a second run uses torch.optim.Adam(model.parameters(), lr=0.001), which keeps a first-moment estimate (m) and a second-moment estimate (v) per parameter and updates each parameter with θ -= lr · m̂ / (√v̂ + ε). How much extra optimizer-state memory does each method require beyond the 8 MB of parameters, and how does Adam's extra buffer make its effective step size adaptive per parameter?

  1. Neither optimizer needs extra memory beyond the 8 MB of parameters, because both the momentum term and the Adam moment estimates are recomputed from the current gradient at each step rather than stored between steps.
  2. Adam stores two per-parameter buffers (m and v), needing 2 × 8 MB = 16 MB extra memory — twice the 8 MB SGD-momentum needs for its single velocity buffer — because dividing each update by √v + ε automatically shrinks the effective step size for parameters with large, noisy gradients.
  3. SGD with momentum needs 16 MB extra because it stores separate buffers for the raw gradient, the velocity, and the previous parameter value, while Adam needs only 8 MB since m and v are packed into one combined tensor.
  4. Adam needs 32 MB extra because bias correction requires storing separate corrected and uncorrected copies of both m and v, giving four full buffers per parameter.

Answer: B. Adam stores two per-parameter buffers (m and v), needing 2 × 8 MB = 16 MB extra memory — twice the 8 MB SGD-momentum needs for its single velocity buffer — because dividing each update by √v + ε automatically shrinks the effective step size for parameters with large, noisy gradients.

ExplanationBoth optimizers keep state tensors that persist between steps, so nothing here is recomputed from scratch each iteration. Parameter memory is fixed at 2,000,000 × 4 bytes = 8,000,000 bytes = 8 MB. SGD with momentum needs exactly one velocity buffer, v_t = 0.9·v_{t-1} + g_t, the same size as the parameters — so its overhead is 8 MB, i.e. 1× the parameter memory. Adam needs two such buffers: the first-moment estimate m_t (an exponential moving average of the gradient) and the second-moment estimate v_t (an exponential moving average of the squared gradient), each 8 MB, giving a total overhead of 2 × 8 MB = 16 MB, i.e. 2× the parameter memory. That extra v_t buffer is exactly what makes Adam's step size adaptive per parameter: the update rule θ -= lr · m̂_t / (√v̂_t + ε) divides by the square root of the accumulated squared gradients, so a parameter whose gradients have consistently been large gets divided by a large number and takes a smaller effective step, while a parameter with small or sparse gradients takes a comparatively larger one. Bias correction (dividing m_t and v_t by 1 − β^t) is a cheap scalar operation applied at use-time, not an extra stored tensor, which is why the "four buffers" and "combined tensor" claims above are both wrong.

Question 63 · Optimization algorithms · hard

Given the optimizer: torch.optim.AdamW(model.parameters(), lr=0.0001, betas=(0.9, 0.999), eps=1e-8) for a model with 10M parameters, calculate the optimizer state memory overhead and analyze how the adaptive learning rate affects convergence?

  1. AdamW maintains 2 state tensors (m_t first moment, v_t second moment) per parameter, requiring 76.3 MB extra memory; the parameter update at each step scales lr by m_t/(sqrt(v_t) + eps), so dividing by sqrt(v_t) gives each parameter its own effective learning rate that shrinks as its gradient history grows larger
  2. AdamW requires no additional memory beyond model parameters because optimizer state is computed on-the-fly during each step and never stored between iterations
  3. The learning rate lr=0.0001 remains constant for all parameters throughout training because AdamW does not adapt per-parameter rates, applying the exact same scalar step size to every weight regardless of its gradient history
  4. AdamW doubles the model memory because it stores a complete copy of all parameters for momentum calculation, effectively duplicating the entire parameter tensor at every training step

Answer: A. AdamW maintains 2 state tensors (m_t first moment, v_t second moment) per parameter, requiring 76.3 MB extra memory; the parameter update at each step scales lr by m_t/(sqrt(v_t) + eps), so dividing by sqrt(v_t) gives each parameter its own effective learning rate that shrinks as its gradient history grows larger

ExplanationStep-by-step optimizer analysis: (1) Model has 10M = 10,000,000 parameters, each stored as float32 (4 bytes) = 38.1 MB. (2) AdamW state: two moment estimates per parameter: m_t (first moment, beta1=0.9) and v_t (second moment, beta2=0.999). Memory = 2 × 10,000,000 × 4 bytes = 76.3 MB. (3) Therefore, total optimizer memory = 76.3 MB, which is 2x the model parameter memory. (4) Adam update rule: m_t = 0.9*m_{t-1} + (1-0.9)*g_t; v_t = 0.999*v_{t-1} + (1-0.999)*g_t^2; param -= lr * m_t_hat / (sqrt(v_t_hat) + 1e-8). Here lr/(sqrt(v_t_hat) + 1e-8) is the effective per-parameter learning rate, and multiplying it by m_t_hat gives the actual parameter update. Because bias correction divides by (1 - beta^t), early iterations have larger effective learning rates, enabling faster initial convergence.

Question 64 · Optimization algorithms · hard

Given the optimizer: torch.optim.RMSprop(model.parameters(), lr=0.001, eps=1e-8) for a model with 2M parameters, calculate the optimizer state memory overhead and analyze how the adaptive learning rate affects convergence?

  1. RMSprop maintains 1 state tensor (running average of squared gradients) per parameter, requiring 7.6 MB extra memory; the effective learning rate for each parameter = lr / sqrt(v_t + eps), because adaptive methods scale updates inversely to gradient history magnitude
  2. RMSprop requires no additional memory beyond model parameters because optimizer state is computed on-the-fly during each step
  3. The learning rate lr=0.001 remains constant for every parameter throughout training because RMSprop uses a single global scalar rate with no per-parameter adaptation, ignoring the squared-gradient accumulator entirely
  4. RMSprop doubles the model memory because it stores both the current squared-gradient average and a separate full copy of the raw gradients for every parameter, requiring 15.2 MB instead of 7.6 MB

Answer: A. RMSprop maintains 1 state tensor (running average of squared gradients) per parameter, requiring 7.6 MB extra memory; the effective learning rate for each parameter = lr / sqrt(v_t + eps), because adaptive methods scale updates inversely to gradient history magnitude

ExplanationStep-by-step optimizer analysis: (1) The model has 2,000,000 parameters, each stored as float32 (4 bytes), so the parameter memory itself is 2,000,000 x 4 bytes = 8,000,000 bytes ~= 7.6 MB. (2) RMSprop keeps exactly one extra state tensor per parameter, the running average of squared gradients v_t = beta*v_{t-1} + (1-beta)*g_t^2, so the extra memory is also 2,000,000 x 4 bytes ~= 7.6 MB — a 1x overhead on top of the parameters, not 0x and not 2x. (3) At every step the effective per-parameter learning rate is lr / sqrt(v_t + eps): parameters whose gradients have historically been large get their updates shrunk (v_t is large, so the denominator is large), while parameters with small or sparse gradient history keep relatively larger updates. (4) This per-parameter rescaling is what lets RMSprop converge faster and more stably than plain SGD when different parameters see very different gradient magnitudes, since each parameter effectively gets its own adapted step size instead of one shared global rate.

Question 65 · Optimization algorithms · hard

Given the optimizer torch.optim.SGD(model.parameters(), lr=0.05, momentum=0.9) applied to a model with 2,500,000 float32 parameters, what is the optimizer's extra memory overhead beyond the parameters themselves, and does the momentum term make the learning rate adaptive per parameter?

  1. Momentum-based SGD keeps a single velocity buffer per parameter, adding 2,500,000 × 4 bytes = 10 MB of extra memory (matching the 10 MB used by the parameters); this velocity buffer applies the same learning rate, lr = 0.05, to every parameter throughout training, since momentum only smooths the direction of past gradients rather than rescaling updates by their magnitude history.
  2. No additional memory is required beyond the 10 MB parameter tensor, because the velocity term in SGD with momentum is recomputed from the current gradient at every step and discarded immediately afterward.
  3. Each parameter's effective learning rate shrinks over training in SGD with momentum, because the optimizer divides lr = 0.05 by an exponentially weighted average of that parameter's squared gradient history.
  4. Two separate buffers per parameter are stored by SGD with momentum — one tracking a first-moment estimate and one tracking a second-moment estimate — pushing total optimizer state to 20 MB, double the 10 MB held by the parameters.

Answer: A. Momentum-based SGD keeps a single velocity buffer per parameter, adding 2,500,000 × 4 bytes = 10 MB of extra memory (matching the 10 MB used by the parameters); this velocity buffer applies the same learning rate, lr = 0.05, to every parameter throughout training, since momentum only smooths the direction of past gradients rather than rescaling updates by their magnitude history.

ExplanationSGD with momentum keeps exactly one extra state tensor per parameter — a velocity buffer v, the same shape as model.parameters(). For 2,500,000 float32 parameters, that buffer costs 2,500,000 × 4 bytes = 10,000,000 bytes = 10 MB, identical to the 10 MB already used to store the parameters themselves (so total memory roughly doubles, but the extra overhead beyond the parameters is 10 MB). Each optimizer step computes v = momentum × v_prev + grad, then updates param -= lr × v. Because lr = 0.05 is a single scalar applied identically in that update for every parameter — never divided or rescaled by any per-parameter statistic — momentum changes the direction and effective speed of descent by smoothing noisy gradients across steps, but it does not make the learning rate itself adaptive. That is what separates plain SGD+momentum from optimizers such as Adam or RMSprop, which maintain a second buffer of squared-gradient history and divide lr by its square root, producing a genuinely per-parameter adaptive rate.

Question 66 · Object detection (YOLO) · hard

Given YOLO detection head with grid size 13×13, 5 anchor boxes per cell, 80 object classes, and input image 416×416: the output tensor shape is [batch, 13, 13, 425] where each anchor predicts (tx, ty, tw, th, objectness, class_probs). Calculate the total number of bounding box predictions and analyze how NMS filters them?

  1. Total predictions = 13×13×5 = 845 boxes; each box has 85 values (4 coords + 1 objectness + 80 class probs). NMS filters by sorting on objectness×max_class_prob, then removing boxes with IoU > 0.45 relative to higher-scored boxes, because overlapping detections of the same object should be merged
  2. Total predictions = 13×13 = 169 boxes because only one detection per grid cell is possible regardless of anchor count
  3. NMS removes all boxes with objectness < 0.5 without considering overlap, because confidence thresholding is sufficient for detection deduplication
  4. The output tensor has 80 channels because each channel corresponds to one class detection map without anchor box regression

Answer: A. Total predictions = 13×13×5 = 845 boxes; each box has 85 values (4 coords + 1 objectness + 80 class probs). NMS filters by sorting on objectness×max_class_prob, then removing boxes with IoU > 0.45 relative to higher-scored boxes, because overlapping detections of the same object should be merged

ExplanationStep-by-step YOLO analysis: (1) Grid: 13×13 = 169 cells, each cell covers 32.0×32.0 pixels. (2) Per cell: 5 anchors, each producing 5+80 = 85 predictions. (3) Total boxes: 13×13×5 = 845. Total output values: 845×85 = 71,825. (4) Box decoding: bx = sigmoid(tx) + cell_x, by = sigmoid(ty) + cell_y, bw = anchor_w × exp(tw), bh = anchor_h × exp(th). (5) NMS algorithm: sort 845 boxes by score, iterate: keep top box, remove all boxes with IoU > threshold (typically 0.45). Therefore, NMS reduces 845 predictions to typically 10-50 final detections.

Question 67 · Object detection (YOLO) · hard

Given YOLO detection head with grid size 52×52, 3 anchor boxes per cell, 80 object classes, and input image 416×416: the output tensor shape is [batch, 52, 52, 255] where each anchor predicts (tx, ty, tw, th, objectness, class_probs). Calculate the total number of bounding box predictions and analyze how NMS filters them?

  1. Total predictions = 52×52×3 = 8,112 boxes; each box has 85 values (4 coords + 1 objectness + 80 class probs). NMS filters by sorting on objectness×max_class_prob, then removing boxes with IoU > 0.45 relative to higher-scored boxes, because overlapping detections of the same object should be merged
  2. Only 2,704 bounding boxes are predicted (52×52), because YOLO outputs a single box per grid cell regardless of anchor count, discarding two of the three anchor predictions as redundant duplicates
  3. NMS removes all boxes with objectness < 0.5 without considering overlap, because confidence thresholding is assumed sufficient for deduplication, so two overlapping boxes on the same object that both score above 0.5 are kept as separate final detections
  4. The output tensor has 80 channels because each channel corresponds to one class detection map without anchor box regression

Answer: A. Total predictions = 52×52×3 = 8,112 boxes; each box has 85 values (4 coords + 1 objectness + 80 class probs). NMS filters by sorting on objectness×max_class_prob, then removing boxes with IoU > 0.45 relative to higher-scored boxes, because overlapping detections of the same object should be merged

ExplanationStep-by-step YOLO analysis: (1) Grid: 52×52 = 2704 cells, each cell covers 8.0×8.0 pixels. (2) Per cell: 3 anchors, each producing 5+80 = 85 predictions. (3) Total boxes: 52×52×3 = 8,112. Total output values: 8112×85 = 689,520. (4) Box decoding: bx = sigmoid(tx) + cell_x, by = sigmoid(ty) + cell_y, bw = anchor_w × exp(tw), bh = anchor_h × exp(th). (5) NMS algorithm: sort 8112 boxes by score, iterate: keep top box, remove all boxes with IoU > threshold (typically 0.45). Therefore, NMS reduces 8,112 predictions to typically 10-50 final detections.

Question 68 · Q-learning · hard

Given Q-learning with state space S=25, action space A=4, discount factor gamma=0.95, learning rate alpha=0.2: Q(s,a) <- Q(s,a) + alpha * (r + gamma * max_a' Q(s',a') - Q(s,a)). With Q-table size = 25×4 = 100 entries, analyze the convergence behavior over 500 episodes and predict the memory requirements?

  1. Q-table memory = 25×4×4 bytes = 0.4 KB; convergence requires visiting each state-action pair multiple times, therefore 500 episodes with epsilon-greedy exploration (epsilon decaying from 1.0 to 0.01) ensures coverage of the 100-entry table with high probability
  2. Q-learning converges in exactly 25 episodes because each state needs exactly one visit to compute the optimal Q-value, ignoring that each of the 4 actions per state requires its own separately-updated estimate that a single visit cannot provide
  3. The Q-table requires 20000 bytes because it stores a full 25×25 state-transition probability matrix for each of the 4 actions using 64-bit floats, confusing Q-learning's model-free Q-table with a model-based transition-probability representation it does not need
  4. Convergence is guaranteed in 1 episode because the Bellman equation can be solved analytically in closed form once gamma and alpha are fixed, treating the temporal-difference update as a one-shot linear solve rather than the iterative sampling process Q-learning actually performs

Answer: A. Q-table memory = 25×4×4 bytes = 0.4 KB; convergence requires visiting each state-action pair multiple times, therefore 500 episodes with epsilon-greedy exploration (epsilon decaying from 1.0 to 0.01) ensures coverage of the 100-entry table with high probability

ExplanationStep-by-step Q-learning analysis: (1) Q-table: 25 states × 4 actions = 100 entries, each float32 = 400 bytes = 0.4 KB. (2) Update rule: Q(s,a) += 0.2 × (r + 0.95 × max Q(s') - Q(s,a)). The TD error = r + 0.95 × max Q(s') - Q(s,a) drives learning. (3) Convergence: requires each (s,a) pair visited infinitely often in theory; practically, ~10-50 visits per pair suffices. With 100 pairs and 500 episodes averaging ~10 steps: total transitions ≈ 5000, so avg visits per (s,a) ≈ 50. This is well within the range needed for practical convergence, and the 0.4 KB table size confirms memory stays negligible regardless of episode count.

Question 69 · Q-learning · hard

Given Q-learning with state space S=400, action space A=8, discount factor gamma=0.99, learning rate alpha=0.05: Q(s,a) <- Q(s,a) + alpha * (r + gamma * max_a' Q(s',a') - Q(s,a)). With Q-table size = 400×8 = 3200 entries, analyze the convergence behavior over 5000 episodes and predict the memory requirements?

  1. Q-table memory = 400×8×4 bytes = 12.5 KB; convergence requires visiting each state-action pair multiple times, therefore 5000 episodes with epsilon-greedy exploration (epsilon decaying from 1.0 to 0.01) ensures coverage of the 3200-entry table with high probability
  2. Q-learning converges in exactly 400 episodes because each state needs exactly one visit to compute the optimal Q-value
  3. Memory usage totals 25.6 KB because the 3200 Q-values are stored as 8-byte doubles, and convergence is achieved within exactly 400 episodes since visiting every state once yields the optimal policy
  4. The Bellman optimality equation is solved in closed form after a single episode, requiring 0 additional iterations because gamma=0.99 makes the environment fully deterministic

Answer: A. Q-table memory = 400×8×4 bytes = 12.5 KB; convergence requires visiting each state-action pair multiple times, therefore 5000 episodes with epsilon-greedy exploration (epsilon decaying from 1.0 to 0.01) ensures coverage of the 3200-entry table with high probability

ExplanationThe Q-table has 400 states × 8 actions = 3200 entries. Stored as float32 (4 bytes each), total memory = 3200 × 4 = 12,800 bytes = 12.5 KB, matching a Q-table memory of 400×8×4 bytes = 12.5 KB. For convergence, Q-learning theory requires every state-action pair to be visited infinitely often, but in practice tens of visits per pair suffice in expectation. Assuming roughly 80 steps per episode, 5000 episodes yield about 400,000 transitions, or roughly 125 visits per state-action pair on average — enough for an epsilon-greedy schedule (epsilon decaying from 1.0 to 0.01) to give high-probability coverage of all 3200 entries. A single visit per state cannot produce the optimal Q-value, since Q-learning is a stochastic, incremental update rule rather than a one-shot analytical solver, so claims of exact convergence in one episode or in exactly 400 episodes are incorrect.

Question 70 · Q-learning · hard

Given Q-learning with state space S=1000, action space A=6, discount factor gamma=0.999, learning rate alpha=0.01: Q(s,a) <- Q(s,a) + alpha * (r + gamma * max_a' Q(s',a') - Q(s,a)). With Q-table size = 1000×6 = 6000 entries, analyze the convergence behavior over 10000 episodes and predict the memory requirements?

  1. Q-table memory = 1000×6×4 bytes = 23.4 KB; convergence requires visiting each state-action pair multiple times, therefore 10000 episodes with epsilon-greedy exploration (epsilon decaying from 1.0 to 0.01) ensures coverage of the 6000-entry table with high probability
  2. Q-learning converges in exactly 1000 episodes because each state needs exactly one visit to compute the optimal Q-value, treating the size of the state space alone as sufficient for convergence while disregarding the action space and the need for repeated exploration of each state-action pair
  3. The Q-table requires 49152000 bytes because each entry stores a 64-bit matrix of transition probabilities, confusing Q-learning's model-free value updates with a model-based approach that must explicitly store the full state-transition dynamics
  4. Convergence is guaranteed in 1 episode because the Bellman equation is solved analytically without iteration, mistaking the Bellman optimality equation's fixed-point definition for a closed-form solution that could be computed in a single pass

Answer: A. Q-table memory = 1000×6×4 bytes = 23.4 KB; convergence requires visiting each state-action pair multiple times, therefore 10000 episodes with epsilon-greedy exploration (epsilon decaying from 1.0 to 0.01) ensures coverage of the 6000-entry table with high probability

ExplanationStep-by-step Q-learning analysis: (1) Q-table: 1000 states × 6 actions = 6000 entries, each float32 = 24,000 bytes = 23.4 KB. (2) Update rule: Q(s,a) += 0.01 × (r + 0.999 × max Q(s') - Q(s,a)). The TD error = r + 0.999 × max Q(s') - Q(s,a) drives learning. (3) Convergence: requires each (s,a) pair visited infinitely often in theory; practically, ~10-50 visits per pair suffices. With 6000 pairs and 10000 episodes averaging ~200 steps: total transitions ≈ 2000000. Therefore, avg visits per (s,a) ≈ 333.3. (4) Because gamma=0.999, the effective planning horizon = 1/(1-0.999) = 1000 steps. Higher gamma means longer-horizon planning but slower convergence. With alpha=0.01: learning stability requires alpha < 1.0, and smaller alpha gives smoother but slower convergence.

Question 71 · Conv2d output shape · hard

Consider the following PyTorch layer applied to a batched image tensor: ```python import torch.nn as nn conv = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=5, stride=2, padding=2) x = torch.randn(8, 16, 64, 64) y = conv(x) ``` Given that Conv2d pads both sides of each spatial dimension by `padding` and includes a bias term by default, which statement correctly describes the shape of `y` and the number of learnable parameters in `conv`?

  1. The output tensor has shape [8, 32, 32, 32], since H_out = floor((64 + 2×2 − 5)/2) + 1 = 32, and the layer has 12,832 learnable parameters from params = 32×(16×5×5 + 1) including the bias term
  2. Spatial dimensions come out as [8, 32, 32, 32], matching the correct height and width, but the parameter count is only 12,800, because Conv2d layers have no bias term unless one is explicitly added with bias=True
  3. Applying padding to only one edge of each spatial axis, as PyTorch actually does, yields shape [8, 32, 31, 31] via H_out = floor((64 + 2 − 5)/2) + 1 = 31, while the parameter count of 12,832 stays unaffected by padding
  4. Rounding the fractional convolution ratio upward rather than downward gives shape [8, 32, 33, 33] via H_out = ceil((64 + 4 − 5)/2) + 1 = 33, with the parameter count unaffected at 12,832

Answer: A. The output tensor has shape [8, 32, 32, 32], since H_out = floor((64 + 2×2 − 5)/2) + 1 = 32, and the layer has 12,832 learnable parameters from params = 32×(16×5×5 + 1) including the bias term

ExplanationFor a Conv2d layer, the spatial output size follows H_out = floor((H_in + 2×padding − kernel_size)/stride) + 1, and PyTorch pads both sides of each spatial axis by the given padding value. Substituting H_in=64, padding=2, kernel_size=5, stride=2 gives H_out = floor((64+4−5)/2)+1 = floor(63/2)+1 = 31+1 = 32, so W_out is also 32 by symmetry, and the batch size (8) and out_channels (32) carry through directly, giving y.shape = [8, 32, 32, 32]. The parameter count for a Conv2d layer is out_channels × (in_channels × kernel_height × kernel_width + 1), where the +1 accounts for one bias value per output channel — PyTorch's nn.Conv2d uses bias=True by default. That gives 32 × (16×5×5 + 1) = 32 × 401 = 12,832 parameters. The claim that no bias term exists understates the count at 12,800 because it wrongly assumes bias is off by default. Treating padding as applied to only one edge instead of both undercounts the effective padded input size and produces an incorrect H_out of 31. Rounding the division result upward instead of applying the floor function overstates H_out as 33, which does not match how PyTorch actually computes convolution output sizes.

Question 72 · ResNet skip connection · hard

A residual block computes y = F(x) + x, where F is a small stack of convolution and batch-normalization layers. During backpropagation at a particular input, the upstream gradient arriving at the block's output is dL/dy = 0.5, and the local Jacobian of the residual branch at that point is dF/dx = -0.5. Using the chain rule dL/dx = dL/dy · (dF/dx + 1), what is dL/dx?

  1. The chain rule yields dL/dx = 0.25, since dL/dy · (dF/dx + 1) = 0.5 × (-0.5 + 1) = 0.5 × 0.5, with the skip connection's +1 added to the local Jacobian before multiplying by the upstream gradient.
  2. Multiplying dL/dy and dF/dx directly, as 0.5 × (-0.5), gives dL/dx = -0.25 but omits the constant contribution that the identity path adds to the local Jacobian.
  3. Adding dL/dy and dF/dx instead of multiplying, as 0.5 + (-0.5), gives dL/dx = 0 by mistaking the chain rule's multiplication for a sum.
  4. Treating the skip connection as passing the upstream gradient through completely unchanged gives dL/dx = 0.5, the same as dL/dy, ignoring the residual branch's contribution entirely.

Answer: A. The chain rule yields dL/dx = 0.25, since dL/dy · (dF/dx + 1) = 0.5 × (-0.5 + 1) = 0.5 × 0.5, with the skip connection's +1 added to the local Jacobian before multiplying by the upstream gradient.

ExplanationIn a residual block y = F(x) + x, backpropagation splits the upstream gradient across two paths: the identity path passes dL/dy straight through, and the residual path scales it by the local Jacobian dF/dx. The chain rule combines these as dL/dx = dL/dy · (dF/dx + 1). Substituting the given values, dF/dx + 1 = -0.5 + 1 = 0.5, so dL/dx = 0.5 × 0.5 = 0.25. This structure is precisely why deep residual networks resist vanishing gradients: even when the residual branch's local gradient shrinks toward zero, the +1 keeps the multiplier away from zero, so gradient magnitude never collapses purely from an unfavorable dF/dx. Multiplying dL/dy and dF/dx directly (0.5 × -0.5 = -0.25) drops the identity path's contribution. Adding dL/dy and dF/dx (0.5 + -0.5 = 0) confuses the chain rule's multiplication with a plain sum. Assuming the gradient passes through unchanged at dL/dy = 0.5 ignores that the residual branch also contributes to the total gradient whenever dF/dx is nonzero.

Question 73 · transfer learning freezing · hard

A pre-trained CNN backbone has 8,400,000 parameters in its convolutional base and an original classification head FC(1024, 1000) built for a 1000-class dataset. For a new 6-class skin-lesion classification task, the entire convolutional base is frozen (learning rate = 0) and the head is replaced with a new, randomly initialized FC(1024, 6) layer. This FC layer alone is trained with learning rate 1e-3 until validation loss plateaus (Phase 1). Training then enters Phase 2: only the last convolutional block, containing 1,200,000 of the 8,400,000 base parameters, is unfrozen and trained at learning rate 1e-5, the FC layer continues training at a reduced learning rate of 1e-4, and the remaining 7,200,000 base parameters stay frozen at learning rate 0. During Phase 2, how many parameters are actively updated by gradient descent, and why is the newly unfrozen convolutional block given a smaller learning rate than the FC layer?

  1. A total of 1,206,150 parameters change in Phase 2 (1,200,000 from the unfrozen convolutional block plus 6,150 from the FC layer), and the unfrozen block is given a smaller learning rate because its pre-trained weights already encode useful features that need only gentle adjustment, avoiding large updates that would erase this learned representation.
  2. All 8,406,150 parameters are updated in Phase 2, because a learning rate of 0 still produces a tiny nonzero weight update in practice, so the remaining 7,200,000 frozen base parameters change along with the unfrozen block and the FC layer.
  3. Only 1,200,000 parameters are updated in Phase 2, because the FC layer's validation loss already plateaued during Phase 1, and once a layer's loss plateaus it is automatically excluded from further gradient updates regardless of its assigned learning rate.
  4. During Phase 2, 1,206,150 parameters are updated in total (1,200,000 from the unfrozen block plus 6,150 from the FC layer), but the unfrozen block is given a smaller learning rate than the FC layer purely because it has far more parameters, and layers with more parameters must always use proportionally smaller learning rates to balance the total weight-update magnitude.

Answer: A. A total of 1,206,150 parameters change in Phase 2 (1,200,000 from the unfrozen convolutional block plus 6,150 from the FC layer), and the unfrozen block is given a smaller learning rate because its pre-trained weights already encode useful features that need only gentle adjustment, avoiding large updates that would erase this learned representation.

ExplanationOnly parameters with a nonzero learning rate receive gradient updates; a learning rate of exactly 0 means the layer's pre-trained weights are used to compute the forward pass but are never changed by backpropagation. In Phase 2, the unfrozen convolutional block contributes 1,200,000 trainable parameters and the FC(1024, 6) layer contributes 1024 × 6 + 6 = 6,150 trainable parameters, giving a total of 1,206,150 parameters actively updated by gradient descent, while the other 7,200,000 base parameters stay fixed at their pre-trained values because their learning rate is 0. The smaller learning rate (1e-5) assigned to the unfrozen block matters because its weights are already pre-trained and encode useful features refined over a large source dataset; large updates could overwrite that learned representation, a failure mode known as catastrophic forgetting. The FC layer, by contrast, was randomly initialized in Phase 1 and had no useful information to begin with, so it is given a comparatively larger learning rate (1e-4 in Phase 2) to keep learning meaningful weights quickly. The claim that all 8,406,150 parameters update mistakes a learning rate of 0 for a very small but nonzero value, when a true freeze means no gradient step is applied to those weights at all. The claim that only 1,200,000 parameters update assumes a layer becomes permanently frozen once its validation loss plateaus, but plateauing in Phase 1 only describes how training progressed — it does not change the FC layer's learning rate, which is explicitly still nonzero (1e-4) in Phase 2, so the FC layer keeps updating. The claim that the smaller learning rate follows from the unfrozen block having more parameters mistakes parameter count for the actual reason behind the choice, which is whether the weights start pre-trained (needing gentle fine-tuning) or randomly initialized (needing larger updates), not how many parameters a layer contains.

Question 74 · CycleGAN consistency loss · hard

In a CycleGAN trained to translate horse photographs into zebra photographs without any paired horse-zebra training images, the generator loss combines an adversarial term with a weighted cycle-consistency term: Loss = adversarial + λ_cycle × (||G_BA(G_AB(x_horse)) − x_horse||₁ + ||G_AB(G_BA(x_zebra)) − x_zebra||₁). For a given training batch, the adversarial loss is 0.5, the horse round-trip (horse→zebra→horse) L1 reconstruction error is 0.4, the zebra round-trip (zebra→horse→zebra) L1 reconstruction error is 0.2, and λ_cycle = 10. What is the total generator loss for this batch, and what role does the cycle-consistency term play in making CycleGAN training possible without paired images?

  1. Summing 0.5 with λ_cycle times both round-trip errors gives a total generator loss of 6.5; cycle consistency substitutes for missing paired horse-zebra images by forcing each translation to be reversible back to the original, constraining G_AB and G_BA even without direct pixel-level supervision.
  2. Adding the adversarial term to the two unweighted L1 reconstruction errors yields a total loss of 1.1, treating λ_cycle as if it modifies only the adversarial component rather than the combined cycle-consistency sum.
  3. Applying λ_cycle correctly to both cycle terms still gives a total loss of 6.5, but the reconstruction term's real purpose is to sharpen output resolution rather than to enforce a reversible mapping between the two image domains.
  4. Scaling only the horse round-trip error by λ_cycle while adding the zebra round-trip error directly produces a total loss of 4.7, treating the two translation directions asymmetrically instead of weighting their sum by a single shared coefficient.

Answer: A. Summing 0.5 with λ_cycle times both round-trip errors gives a total generator loss of 6.5; cycle consistency substitutes for missing paired horse-zebra images by forcing each translation to be reversible back to the original, constraining G_AB and G_BA even without direct pixel-level supervision.

ExplanationThe generator loss is Loss = adversarial + λ_cycle × (cycle_horse + cycle_zebra) = 0.5 + 10 × (0.4 + 0.2) = 0.5 + 10 × 0.6 = 0.5 + 6.0 = 6.5. Both round-trip terms — horse→zebra→horse and zebra→horse→zebra — sit inside the same λ_cycle-weighted sum, so the coefficient scales the combined cycle error, not just one direction and not the adversarial term. Conceptually, cycle consistency is what makes it possible to train CycleGAN from unpaired collections of horse and zebra images. Since no ground-truth zebra photo matches any particular horse photo, the model cannot be supervised pixel-by-pixel the way a paired translation network would be. Requiring that translating an image and translating it back reproduces the original constrains G_AB and G_BA to learn a semantically meaningful, approximately invertible mapping rather than one that discards or hallucinates content — this reversibility requirement is the actual substitute for paired supervision. One incorrect claim treats λ_cycle as modifying only the adversarial term and leaves both L1 errors unweighted, giving 1.1 — this misreads which term the coefficient multiplies. Another claim scales only the horse round-trip by λ_cycle while adding the zebra round-trip unweighted, giving 4.7 — this incorrectly treats the two cycle directions asymmetrically, when the loss applies one shared λ_cycle to their sum. A third claim reaches the correct total of 6.5 but misidentifies the purpose of cycle consistency as sharpening output resolution; resolution and visual sharpness are governed by the adversarial term and network architecture, while cycle consistency's specific job is enforcing reversibility so unpaired training stays well-constrained.

Question 75 · BatchNorm statistics · hard

A PyTorch nn.BatchNorm2d(64) layer trains with momentum = 0.1. For one channel, the running_mean before a training step is 5.0, and the batch mean computed over the batch and spatial dimensions during that step is 15.0. PyTorch updates running statistics using running_mean_new = (1 − momentum) × running_mean_old + momentum × batch_mean. Applying this update rule to the given values, what is the running_mean for that channel immediately after this training step?

  1. The updated running_mean is 6.0, because PyTorch's EMA update weights the old value by (1 − momentum) = 0.9 and the new batch mean by momentum = 0.1, giving 0.9×5.0 + 0.1×15.0 = 6.0.
  2. PyTorch overwrites running_mean entirely with the batch mean, so it becomes 15.0, discarding the previous running estimate at every training step.
  3. Since the update is a simple unweighted average of the old and new means, running_mean becomes 10.0.
  4. Swapping the weights so momentum multiplies the old running_mean and (1 − momentum) multiplies the batch mean yields running_mean = 14.0.

Answer: A. The updated running_mean is 6.0, because PyTorch's EMA update weights the old value by (1 − momentum) = 0.9 and the new batch mean by momentum = 0.1, giving 0.9×5.0 + 0.1×15.0 = 6.0.

ExplanationThe running_mean update in PyTorch's BatchNorm is an exponential moving average, not a simple average or an overwrite: running_mean_new = (1 − momentum) × running_mean_old + momentum × batch_mean. With momentum = 0.1, running_mean_old = 5.0, and batch_mean = 15.0, this gives (0.9 × 5.0) + (0.1 × 15.0) = 4.5 + 1.5 = 6.0. Overwriting the running mean with the batch mean confuses BatchNorm's running statistics with the batch statistics actually used to normalize activations during training — the running estimate is only used at inference time. Treating the update as a plain average of the two values ignores that momentum controls how much the old estimate persists, and with momentum = 0.1 the old value should dominate rather than contribute equally. Swapping which term gets weight (1 − momentum) versus momentum inverts the direction of the exponential decay, making the running estimate track the batch statistics too aggressively instead of smoothing them out slowly across many training steps.

Question 76 · depthwise separable convolution · hard

A standard 3x3 convolution with no bias maps 32 input channels to 64 output channels, giving params = 3x3x32x64 = 18,432. It is replaced by a depthwise separable convolution: a 3x3 depthwise stage (one filter per input channel) followed by a 1x1 pointwise stage (a full linear combination across channels). Which statement correctly reports the parameter counts for both stages, the total, and the resulting reduction factor versus the standard convolution?

  1. Because the depthwise stage applies one shared 3x3 kernel across all input channels, it needs only 9 parameters, giving a total of 2057 parameters and a reduction of about 8.96x compared to the standard convolution.
  2. The depthwise stage uses 3x3x32 = 288 parameters and the pointwise stage uses 32x64 = 2048 parameters, giving a total of 2336 versus 18,432 for the standard convolution — a reduction of about 7.89x.
  3. The pointwise 1x1 convolution operates on spatial neighborhoods rather than channels, so it contributes 3x3x64 = 576 parameters, making the total depthwise separable parameter count 864, an efficiency gain of about 21.3x over the standard convolution.
  4. Since the depthwise separable convolution still contains two convolutional layers, its total parameter count of 21,000 rounds up to nearly match the standard convolution's 18,432 parameters, so no meaningful reduction occurs.

Answer: B. The depthwise stage uses 3x3x32 = 288 parameters and the pointwise stage uses 32x64 = 2048 parameters, giving a total of 2336 versus 18,432 for the standard convolution — a reduction of about 7.89x.

ExplanationFor a standard 3x3 convolution mapping 32 input channels to 64 output channels, the parameter count is 3x3x32x64 = 18,432, since every output channel needs its own 3x3 kernel spanning all 32 input channels. A depthwise separable convolution splits this into two cheaper stages. The depthwise stage keeps a separate 3x3 kernel for each of the 32 input channels, with no mixing across channels, costing 3x3x32 = 288 parameters. The pointwise stage is a 1x1 convolution that mixes the 32 channels into 64 output channels, costing 1x1x32x64 = 2048 parameters. Together the depthwise separable convolution needs 288 + 2048 = 2336 parameters, versus 18,432 for the standard convolution — a reduction factor of 18432/2336, which is about 7.89x. The claim that the depthwise stage shares a single 3x3 kernel across all channels misreads what "depthwise" means: it actually keeps one kernel per channel, so treating it as 9 parameters undercounts that stage and manufactures an inflated reduction figure. The claim that the pointwise stage operates on spatial neighborhoods confuses the two stages' roles — a 1x1 kernel has zero spatial extent, so it can only combine information across channels, never across space, which makes a 3x3x64 parameter count for that stage incorrect. The claim that the total stays near 18,432 because there are two layers ignores that each stage is individually far smaller than the fused kernel: factorizing a 3x3x32x64 operation into a 3x3x32 stage plus a 32x64 stage is precisely what removes the multiplicative coupling between kernel area and channel count, which is the whole point of the factorization.

Question 77 · Conv2d output shape · hard

A CNN layer is defined as nn.Conv2d(in_channels=8, out_channels=16, kernel_size=4, stride=3, padding=1) and applied to a batched input tensor of shape [4, 8, 15, 15] (batch=4, channels=8, height=15, width=15). Using H_out = floor((H_in + 2·padding − kernel_size)/stride) + 1, what is the output shape produced by this layer?

  1. The output tensor has shape [4, 16, 5, 5], because floor((15+2-4)/3)+1 = floor(13/3)+1 = 4+1 = 5 for both spatial dimensions.
  2. This layer instead produces shape [4, 16, 6, 6], since rounding 13/3 up to the nearest whole number (5) and then adding 1 gives 6 for each spatial dimension.
  3. Applying the stride steps alone without the trailing +1 yields shape [4, 16, 4, 4], since floor(13/3) = 4 is mistaken for the full output size.
  4. No valid output shape can be computed for this layer, because stride=3 does not evenly divide 15+2(1)-4=13, leaving the convolution undefined.

Answer: A. The output tensor has shape [4, 16, 5, 5], because floor((15+2-4)/3)+1 = floor(13/3)+1 = 4+1 = 5 for both spatial dimensions.

ExplanationConvolution output size follows H_out = floor((H_in + 2·padding − kernel_size)/stride) + 1. Here H_in=15, padding=1, kernel_size=4, stride=3, so the numerator is 15 + 2(1) − 4 = 13, and 13/3 = 4.333…, which floors to 4. Adding the final +1 — which counts the kernel's starting position as the first valid output element, not just the number of stride steps taken afterward — gives H_out = W_out = 5. With out_channels=16 and the batch dimension of 4 preserved, the output tensor is [4, 16, 5, 5]. Rounding the division up instead of flooring it produces an incorrect 6×6 spatial size; dropping the +1 term and using only the stride-step count produces an incorrect 4×4 size; and assuming stride must evenly divide the padded, kernel-adjusted input size is not a requirement of the formula, since floor division handles non-exact cases without making the layer invalid.

Question 78 · attention score computation · hard

In scaled dot-product attention, Attention(Q, K, V) = softmax(QK^T / sqrt(d_k)) V, a batch of query vectors Q has shape (2, 5, 16) — batch size 2, 5 query tokens, key-dimension 16 — while the corresponding K has shape (2, 7, 16) and V has shape (2, 7, 32), so there are 7 key/value tokens but the value vectors carry 32 features instead of 16. After computing scores = QK^T / sqrt(16), applying softmax along the last axis, and multiplying the result by V, what is the shape of the final attention output?

  1. It comes out as shape (2, 5, 32), since multiplying the (2, 5, 7) attention-weight matrix by V's (2, 7, 32) shape contracts the shared dimension of 7 and retains V's own feature dimension of 32.
  2. Its shape becomes (2, 5, 16), because attention output always keeps the query/key dimension of 16 rather than adopting the value vectors' distinct feature dimension of 32.
  3. The result takes shape (2, 7, 32), because softmax renormalizes over query positions, which swaps the leading sequence length from 5 to the key count of 7 before multiplying by V.
  4. This computation stops at shape (2, 5, 7), since the softmax-normalized attention-weight matrix is itself treated as the final output rather than being multiplied by V.

Answer: A. It comes out as shape (2, 5, 32), since multiplying the (2, 5, 7) attention-weight matrix by V's (2, 7, 32) shape contracts the shared dimension of 7 and retains V's own feature dimension of 32.

ExplanationMatrix multiplication QK^T contracts the shared dimension of 16 (the key-dimension present in both Q and K), turning Q's (2, 5, 16) and K's (2, 7, 16) into a score tensor of shape (2, 5, 7) — batch 2, 5 queries each scored against 7 keys. Dividing by sqrt(16) = 4 and applying softmax along the last axis (length 7) changes only the values, not the shape, so the attention-weight matrix stays (2, 5, 7). The final matrix multiplication with V, shaped (2, 7, 32), contracts the shared dimension of 7 (the key/value token count) and carries forward V's own feature dimension of 32, leaving the batch size 2 and query count 5 untouched. The result is therefore shape (2, 5, 32) — proof that an attention output's feature width comes from V, not from Q or K, which is exactly why V is free to use a different width (32) than Q and K (16). Stopping right after softmax gives only the (2, 5, 7) weight matrix, a common mistake among students who forget that multiplying by V is part of the attention formula, not an optional extra step. Claiming the shape becomes (2, 7, 32) confuses which axis softmax operates over: softmax normalizes across the 7 key positions independently for each of the 5 fixed queries, so it never changes the query count into 7. Claiming the output keeps dimension 16 ignores that the last matrix multiplication is against V, whose feature dimension is 32, not against K again.

Question 79 · transfer learning freezing · hard

A team fine-tunes a pretrained CNN backbone in two phases. The network's forward order is: Input → ConvBlock1 → ConvBlock2 → ConvBlock3 → ConvBlock4 → ConvBlock5 → FC(new, 5 classes). In Phase 1, ConvBlock1–ConvBlock5 are frozen (requires_grad=False) and only FC is trainable. In Phase 2, ConvBlock4 and ConvBlock5 (the last two blocks) are also unfrozen, while ConvBlock1–ConvBlock3 stay frozen and FC remains trainable throughout. Backpropagation only needs to compute the gradient of the loss with respect to a layer's input when that gradient will be used to update some trainable parameter further upstream (i.e., earlier in the forward pass). Given this rule, in which phase, if any, does the backward pass actually need to compute gradients through ConvBlock1–ConvBlock3?

  1. In Phase 1, autograd must still compute gradients through ConvBlock1–ConvBlock3 because PyTorch computes a gradient for every layer touched during the forward pass, independent of each layer's requires_grad setting.
  2. In Phase 2, autograd must propagate gradients all the way back through ConvBlock1–ConvBlock3, because unfreezing ConvBlock4 and ConvBlock5 automatically re-enables gradient tracking for every block that precedes them in the forward pass.
  3. In neither phase does autograd need to compute gradients through ConvBlock1–ConvBlock3, since no trainable parameter ever precedes them — the backward pass can stop once it reaches the input of the earliest trainable block in each phase.
  4. In both phases, autograd must compute gradients through ConvBlock1–ConvBlock3 because the chain rule connects the loss to every layer between it and the network's input, regardless of which parameters are being updated.

Answer: C. In neither phase does autograd need to compute gradients through ConvBlock1–ConvBlock3, since no trainable parameter ever precedes them — the backward pass can stop once it reaches the input of the earliest trainable block in each phase.

ExplanationConvBlock1–ConvBlock3 sit at the very start of the network, before any layer that is ever trainable in either phase: in Phase 1 only FC is trainable, and in Phase 2 only FC, ConvBlock4, and ConvBlock5 are trainable — but ConvBlock1–ConvBlock3 still come before all of these in the forward order. Since backpropagation only needs a frozen layer's input-gradient when that gradient will be used to update a trainable parameter further upstream, and no trainable parameter ever exists before ConvBlock1, the backward pass can stop at the boundary of the earliest trainable block in both cases — at FC's input in Phase 1, and at ConvBlock4's input in Phase 2. This is exactly why frozen backbones are often used to precompute and cache fixed features once rather than rerunning backpropagation through them every step: whether a frozen layer needs its gradient computed depends on what is trainable upstream of it, not merely on whether that particular layer itself is frozen. The claim that PyTorch computes gradients for every layer regardless of requires_grad ignores how autograd actually skips gradient computation once no trainable parameter can use it. The claim that unfreezing later blocks re-enables gradient tracking for earlier frozen blocks confuses per-parameter freezing (explicit and local) with some automatic cascading rule that does not exist. The claim invoking the chain rule for every layer conflates mathematical connectivity between loss and input with computational necessity — being connected via the chain rule does not mean the gradient must actually be computed when nothing trainable will consume it.

Question 80 · PPO clipped objective · hard

In Proximal Policy Optimization (PPO), the clipped surrogate objective is L_t = min(r_t · A_t, clip(r_t, 1−ε, 1+ε) · A_t), where r_t = π_θ(a_t|s_t) / π_θ_old(a_t|s_t) is the probability ratio between the new and old policy, and A_t is the estimated advantage of the action taken. At a particular training step, r_t = 1.4, A_t = 5, and ε = 0.2, what is the value of L_t at this step, and is the clipping term active?

  1. Since r_t = 1.4 exceeds 1+ε = 1.2, clip(r_t, 0.8, 1.2) evaluates to 1.2, so min(1.4×5, 1.2×5) = min(7.0, 6.0) = 6.0, meaning the clipping term is active and caps the reward for driving this already-favoured action's probability still higher.
  2. Because the advantage A_t is positive, the min operator always returns the unclipped product r_t·A_t regardless of the ratio, giving L_t = 1.4×5 = 7.0 with clipping never engaging for good actions.
  3. Although the arithmetic still yields 6.0, the clipping term is not genuinely active here because clip(r_t, 1−ε, 1+ε) only restricts r_t when the ratio drops below zero or grows unboundedly large, not merely when it crosses 1+ε.
  4. The clip function caps r_t at its lower bound 0.8 whenever r_t exceeds 1, so clip(1.4, 0.8, 1.2)×A_t equals 0.8×5 = 4.0, and the min operator then negates this result to penalize the drift, giving L_t = −4.0.

Answer: A. Since r_t = 1.4 exceeds 1+ε = 1.2, clip(r_t, 0.8, 1.2) evaluates to 1.2, so min(1.4×5, 1.2×5) = min(7.0, 6.0) = 6.0, meaning the clipping term is active and caps the reward for driving this already-favoured action's probability still higher.

Explanationclip(r_t, 1−ε, 1+ε) clamps r_t into the band [0.8, 1.2]. Since r_t = 1.4 exceeds the upper bound 1.2, clip(1.4, 0.8, 1.2) = 1.2 — the function snaps to the nearer bound, not the lower one. The unclipped term is r_t·A_t = 1.4×5 = 7.0, and the clipped term is 1.2×5 = 6.0. Taking the minimum, L_t = min(7.0, 6.0) = 6.0. Because the minimum selects the clipped term rather than the unclipped one, clipping is active at this step: it removes the extra incentive the policy would otherwise get for pushing the probability of an already-favoured action beyond the trust region, which is exactly the mechanism PPO uses to prevent overly large policy updates. Claiming the min operator always returns the unclipped product whenever the advantage is positive ignores that clipping specifically engages when r_t drifts past 1+ε for good actions — that is the entire point of the clip term. Reaching the correct number 6.0 while denying that clipping is active misreads what clip(r_t, 1−ε, 1+ε) restricts: it engages the moment the ratio leaves the [1−ε, 1+ε] band, not only at extreme ratios near zero or infinity. Finally, there is no negation step anywhere in the PPO formula, and clip() does not default to the lower bound whenever r_t exceeds 1 — it picks whichever bound r_t actually crossed, which here is the upper bound 1.2, not 0.8.
← Set 3Set 5 →