Ex.1 — Numerical stability
1.1 大数据中提高精度是否值得
题意:题目要求权衡精度、存储、网络和吞吐,不接受“精度越高越好”的单向结论。
知识点:float 通常约 7 位有效十进制数字;double 约 15–16 位。更高精度降低累计、相消、病态分解和长迭代中的舍入误差,但增加内存、磁盘与网络流量,并可能降低缓存、SIMD 或 GPU 吞吐。
解法结构:
- 先说误差收益:敏感 reduction 与 factorization 更可靠。
- 再说系统代价:double 的每元素容量通常约为 float 的两倍。
- 指出边界:高精度不能修复噪声数据、错误模型或不稳定算法。
- 给条件化结论:依据 condition number、误差预算与失败证据选择;可采用混合精度。
1.2 四种操作、100 个随机 1000×100 矩阵
题面事实:分别累计测量 svd(X)、svd(X')、eig(X*X') 与 eig(X'*X)。
知识点:XXT 是 1000×1000,XTX 是 100×100;两者的非零特征值相同。X 与 XT 的非零奇异值也相同,但库实现、full/economy 模式与 workspace 会影响计时。
rng(0);
trials = 100;
elapsed = zeros(trials, 4);
% 可先用一份矩阵 warm-up,避免把首次库初始化混入主计时
X = randn(1000, 100);
svd(X, "econ"); svd(X', "econ"); eig(X*X'); eig(X'*X);
for t = 1:trials
X = randn(1000, 100);
tic; svd(X, "econ"); elapsed(t,1) = toc;
tic; svd(X', "econ"); elapsed(t,2) = toc;
tic; eig(X*X'); elapsed(t,3) = toc;
tic; eig(X'*X); elapsed(t,4) = toc;
end
total = sum(elapsed, 1);
average = mean(elapsed, 1);
spread = std(elapsed, 0, 1);
结果解释框架:报告 MATLAB 版本、CPU/BLAS、随机种子、econ 约定、总时间、均值和离散度。小 Gram 通常更快,但显式形成 XTX 会令 2-norm condition number 从 κ(X) 变为 κ(X)2;速度不自动代表稳定。
常见扣分点:只生成一个矩阵;只测一次;把本机秒数写成算法定律;不说明 full/econ;把形成 Gram 的时间排除却不声明。
1.3 1000 次随机扰动
题面事实:对给定 5×5 非对称矩阵 X,分别研究 X+δX 的 eigenvalues 与 singular values 在 1000 次小随机扰动下的变化。题目提示可参考 MATLAB eps。
rng(0);
trials = 1000;
scale = eps(norm(X, "fro")) * norm(X, "fro");
baseEig = eig(X);
baseS = sort(svd(X), "descend");
eigSamples = complex(zeros(5, trials));
sSamples = zeros(5, trials);
for t = 1:trials
dX = scale * randn(size(X));
e = eig(X + dX);
[~, order] = sortrows([real(e), imag(e)], [1 2]);
eigSamples(:,t) = e(order);
sSamples(:,t) = sort(svd(X + dX), "descend");
end
% 报告 absolute error 的 median/std/quantiles,避免 signed error 抵消
知识点:非对称矩阵的 eigenvalues 可能为复数,跨 trial 比较前必须固定排序或匹配规则。singular values 非负且可降序匹配,并满足扰动界 |σi(X+E)−σi(X)|≤‖E‖2。
常见扣分点:把确定性的逐元素 eps(X) 称为随机扰动;直接比较未匹配 eigenvalues;累加 signed difference 使正负误差抵消;不写扰动尺度。
1.4 用 Chapter 4 解释实验
一般特征分解 M=PDP−1 的局部扰动放大与 ‖P‖‖P−1‖ 有关。SVD 的左右因子正交,因此对应 2-norm 条件因子为 1。答题时还必须说明:SVD 较稳不表示所有 SVD 路线都最快,且通过 Gram 求 SVD 会损失一部分稳定性优势。
Ex.2 — 不用计算机求完整 singular decomposition
题面矩阵:
X=[[1,2,3,4],[5,6,7,8],[9,0,1,2]]∈ℝ3×4。
题意:题面写的是 singular decomposition,不是只求 singular values。答案必须交出 U,Σ,VT,说明 full/thin 约定,并详写步骤。
最省算力路线:因为 3<4,先算 3×3 的 XXT:
XXT=[[30,70,20],[70,174,68],[20,68,86]]。
调研材料记录其正特征值约为 235.6958、53.5435、0.7607,因此奇异值约为 15.3524、7.3173、0.8722。先求对应的正交归一左特征向量 u1,u2,u3,再用 vi=XTui/σi 恢复前三个右奇异向量。最后解 Xv4=0 并归一,补出 full V∈ℝ4×4。
完整手算合同与三个可算尽的小例见下一专题。对 HW5 大矩阵,最终必须核验 UTU=I3、VTV=I4 与 UΣVT≈X。
Ex.3 — PCA in Spark
题面:两个无 header 的 sensor CSV 中至少一个可能包含 1001 个电路传感器输出,最后一列 y 是每小时用电量。需要解释 PCA 的帮助、找出解释 90% 数据的最小列数 n、用前 n 个 principal components 建模 y,并判断 sensors2 是否同类。
3.1 PCA 如何帮助
PCA 把强相关传感器列旋转为正交主方向,按方差排序。它可以揭示低维结构、减少后续回归维数,并帮助观察异常或分布差异。PCA 不知道列的物理名称,也不能单独证明两个文件来自同一系统。
3.2 解释 90% 所需列数
先把最后一列 y 分离。只在 feature matrix 上拟合 scaler/PCA。若解释方差比为 e1≥e2≥…,取最小 n 使:
常见扣分点:把“每个 component 的 EVR 大于 0.01”当成累计 90% 规则;把 y 放进 PCA,造成 label leakage。
3.3 用 principal-component scores 回归
import numpy as np
from pyspark.ml.feature import PCA, StandardScaler, VectorAssembler
from pyspark.ml.regression import LinearRegression
# 无 header CSV:最后一列是 y,其余列是传感器特征
raw = spark.read.option("inferSchema", True).csv(path)
feature_cols = raw.columns[:-1]
label_col = raw.columns[-1]
data = raw.withColumnRenamed(label_col, "label")
train_raw, test_raw = data.randomSplit([0.8, 0.2], seed=42)
assembler = VectorAssembler(
inputCols=feature_cols,
outputCol="features"
)
train_assembled = assembler.transform(train_raw)
test_assembled = assembler.transform(test_raw)
scaler = StandardScaler(
inputCol="features",
outputCol="scaled",
withMean=True,
withStd=True
).fit(train_assembled) # 只在训练集拟合
train_scaled = scaler.transform(train_assembled)
test_scaled = scaler.transform(test_assembled)
# 只用训练集方差谱选择累计解释方差达到 90% 的最小 n
full_pca = PCA(
k=len(feature_cols),
inputCol="scaled",
outputCol="all_pc_scores"
).fit(train_scaled)
cum_evr = np.cumsum(full_pca.explainedVariance.toArray())
n = int(np.searchsorted(cum_evr, 0.90) + 1)
pca_model = PCA(
k=n,
inputCol="scaled",
outputCol="pc_scores"
).fit(train_scaled) # 仍只在训练集拟合
train_scores = pca_model.transform(train_scaled)
test_scores = pca_model.transform(test_scaled)
model = LinearRegression(
featuresCol="pc_scores",
labelCol="label"
).fit(train_scores)
test_predictions = model.transform(test_scores)
管线合同:先切分,再由训练集拟合 scaler、选择 n、拟合 PCA 和回归;测试集只调用 transform。test_predictions 才用于 held-out R²/RMSE,因而不会把测试分布泄漏进特征空间。
模型写为 y=β0+Σβipi+ε。题面给 ε∼Normal(0,1) 是模型假设;应检查残差,而不能把它当作已证事实。报告 held-out R²/RMSE、split/seed 与 residual diagnostics。
3.4 判断 sensors2
对两份文件采用相同预处理、split 与评价口径,比较 cumulative spectrum、PC-score regression 的 held-out 表现、残差结构和基线。仅凭一个高 R² 或二维散点相似,不能证明来源相同。