纸上的 Python
这场 final 是 paper-based,题型里有 Python comprehension 和 Python code,代码在卷面上跑不了,输出和矩阵的样子只能手推。两份往年卷和 practice exam 这三份卷子里,读代码的部分要把代码还原成矩阵和公式,写代码的部分要把一个定义写成函数。这两大题在三份卷子里都是合计 26 分,本期分值要等学校通知。
读代码的小题在问矩阵长什么样
分段拟合这道题是一份往年卷的 Q4。x ≤ 2 和 x > 2 各有 5 个数据点,A1 和 A2 都是 5×2,左列全 1,右列是 x。然后是这几行:
top_row = np.concatenate(
(A1, np.zeros((n1, 2))), axis=1)
bottom_row = np.concatenate(
(np.zeros((n2, 2)), A2), axis=1)
A = np.concatenate((top_row, bottom_row), axis=0)
axis=1 是横着拼,所以 top_row 的左两列是 A1,右两列是 0,bottom_row 正好反过来。axis=0 再竖着摞,A 就是 10×4,题目要求把这个 A 完整写出来。
A 写出来以后,模型也能读出来。左两列只作用于 x ≤ 2 的数据,配 θ₁、θ₂;右两列只作用于 x > 2 的数据,配 θ₃、θ₄。所以模型是两条直线:p(x) = θ₁ + θ₂x 和 q(x) = θ₃ + θ₄x。
约束也要一行行写成等式:
C = np.array([[1, 2, -1, -2], [1, 0, 0, 0]])
d = np.array([[0], [4]])
上面一行是 θ₁ + 2θ₂ − θ₃ − 2θ₄ = 0,移项后就是 p(2) = q(2),两条直线在 x = 2 接上。下面一行是 θ₁ = 4,p(x) 在 x = 0 处的值固定为 4。
这道题的结尾问为什么要写 theta_hat_z_hat[:4]。代码解的是 Week 12 的 KKT 方程组,解出来的向量同时装着参数 theta_hat 和 Lagrange 乘子 z_hat。这里有 4 个参数、2 条约束,向量长度是 6,前 4 个才是参数。
另外两份卷子读的是什么
Gram-Schmidt 那段代码在另一份往年卷的 Q4,变量名换成了 x、y、z、w,要求对回算法记号并写理由。z[i] = w/np.linalg.norm(w) 在做归一化,所以 z 存的是归一化以后的 q。内层循环逐项减掉投影,循环结束时 w 还没有归一化,它对应带波浪的 q̃,写成 q 就混淆了归一化前后的两个向量。
Practice exam 的 Q4 写的是 A_reg = np.sqrt(lamb)*np.eye(degree+1),其中 degree = 8,lamb = 4。print 出来是一个 9×9 的矩阵,对角线全是 2。接着要判断它和 ‖θ₂:ₚ‖² 对应的 A₂ 是否相同。A₂ 的尺寸是 8×9,左列全 0,不惩罚 θ₁;A_reg 是完整的 9×9,θ₁ 也被惩罚,所以两者不同,删掉 A_reg 的首行才一样。
准备这部分时,可以把 Gram-Schmidt、正则化堆叠和 KKT 这三段代码各过一遍,在每行旁边写出变量的 shape 和对应的数学符号。






