第1题:数值稳定性
1.1大数据中提高精度是否值得
题意:题目要求权衡精度、存储、网络和吞吐,不接受“精度越高越好”的单向结论。
知识点:IEEE 754单精度浮点数 float 约有7位有效十进制数字;双精度浮点数 double 约有15–16位。更高精度可以降低累加、相消、病态分解和长迭代中的舍入误差。更高精度也会增加内存、磁盘和网络用量,并可能降低缓存、单指令多数据(SIMD)或图形处理器(GPU)的吞吐量。
解题步骤:
- 说明误差收益。敏感的归约和分解计算可以获得更可靠的结果。
- 说明系统代价。在IEEE 754格式下,
double 占64位,float 占32位,因此前者的单元素存储量是后者的两倍。
- 说明适用边界。高精度不能修复噪声数据、错误模型或不稳定算法。
- 根据条件数、误差预算和失败证据选择精度;若低精度计算达到吞吐目标但残差不达标,则用高精度执行残差校正。
1.2四种操作、100个随机1000×100矩阵
题面事实:分别累计测量 svd(X)、svd(X')、eig(X*X') 与 eig(X'*X)。
知识点:XXT 是1000×1000矩阵。XTX 是100×100矩阵。两者的非零特征值相同。X 与 XT 的非零奇异值也相同。库实现、完整或紧致计算模式以及工作区大小会影响计时。
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-范数条件数从 κ(X) 变为 κ(X)2。计算更快不表示数值更稳定。
常见错误:只生成一个矩阵;只测量一次;把本机运行时间写成算法定律;不说明完整或紧致计算模式;排除形成Gram矩阵的时间但不声明。
1.3 1000次随机扰动
题面事实:对给定的5×5非对称矩阵 X,分别研究 X+δX 的特征值和奇异值在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 抵消
知识点:非对称矩阵的特征值可能是复数。比较不同试验的结果之前,必须固定排序规则或匹配规则。奇异值非负,因此可以按降序匹配。奇异值满足扰动界 |σi(X+E)−σi(X)|≤‖E‖2。
常见错误:把确定性的逐元素 eps(X) 称为随机扰动;直接比较未匹配的特征值;累加带符号差值而使正负误差抵消;不说明扰动尺度。
1.4使用第4章解释实验
采用非正交基的特征分解 M=PDP−1,其局部扰动放大与 ‖P‖‖P−1‖ 有关。SVD的左右因子正交,因此对应的2-范数条件因子为1。SVD数值较稳定,不表示所有SVD计算方法都最快。通过Gram矩阵求SVD会损失一部分稳定性优势。
第2题:不用计算机求完整奇异值分解
题面矩阵:
X=[[1,2,3,4],[5,6,7,8],[9,0,1,2]]∈ℝ3×4。
题意:题目要求奇异值分解,不是只求奇异值。答案必须给出 U,Σ,VT。答案必须说明使用完整SVD还是紧致SVD。答案还必须写出计算步骤。
计算步骤:因为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 并归一化,以补齐完整的 V∈ℝ4×4。
下一节给出完整手算步骤和三个小矩阵例题。对于第5次作业中的矩阵,最后必须检查 UTU=I3、VTV=I4 和 UΣVT≈X。
第3题:Spark中的PCA
题面:两个没有表头的传感器CSV文件中,至少一个文件可能包含1001个电路传感器输出。最后一列 y 表示每小时用电量。需要说明PCA的作用。需要找出累计解释90% 方差的最小主成分数 n。需要使用前 n 个主成分建立 y 的模型。还需要判断 sensors2 是否属于同一类数据。
3.1 PCA如何帮助
PCA把强相关传感器列旋转为正交主方向,按方差排序。它可以揭示低维结构、减少后续回归维数,并帮助观察异常或分布差异。PCA不知道列的物理名称,也不能单独证明两个文件来自同一系统。
3.2解释90% 所需列数
先分离最后一列 y。只在特征矩阵上拟合缩放器和PCA。若解释方差比为 e1≥e2≥…,取满足下式的最小 n:
常见错误:把“每个主成分的解释方差比(EVR)大于0.01”当成累计90% 规则;把 y 输入PCA,造成标签泄漏。
3.3使用主成分得分进行回归
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)
处理流程:先切分数据。只使用训练集拟合缩放器、选择 n、拟合PCA和拟合回归模型。测试集只调用 transform。使用 test_predictions 计算留出测试集的决定系数(R²)和均方根误差(RMSE)。该流程不会把测试集分布泄漏到特征空间。
模型写为 y=β0+Σβipi+ε。题面给出的 ε∼Normal(0,1) 是模型假设。必须检查残差,不能把该假设当作已经证明的事实。报告留出测试集的R² 和RMSE。还要报告数据切分方式、随机种子和残差诊断结果。
3.4判断sensors2
对两份文件使用相同的预处理、数据切分和评价方法。比较累计方差谱、主成分得分回归模型在留出测试集上的表现、残差结构和基线结果。单个较高的R² 或相似的二维散点图不能证明两个文件来源相同。