题 4.1
使用位移反幂法。
取初始向量 x(0)=(1,1,1)T,位移量 μ=9.6。
令
A=123234345
B=A−μI=−8.6232−6.6434−4.6
迭代一次 y(1)=B−1x(0),也即方程组
⎩⎨⎧−8.6y1+2y2+3y3=12y1−6.6y2+4y3=13y1+4y2−4.6y3=1
解得:
y(1)=255402105
因为 λ≈μ+1/yj,j=argmaxi∣yi∣,所以特征值的估计为:
λ≈μ+yj1=9.6+1052=21202≈9.6190
对应单位特征向量的估计为:
x(1)=∥y(1)∥∞y(1)=211121161≈0.52380.76191.0000.
题 4.2
A(0)=422251216
取最大非对角元 a21(0)=2,则:
cotθ(1)tanθ(1)cosθ(1)sinθ(1):=τ(1)=2×24−5=−41:=t(1)=−∣τ(1)∣+1+(τ(1))2sign(τ(1))≈0.7808:=c(1)=1+(t(1))21≈0.7882:=s(1)=c(1)t(1)≈0.6154
从而旋转矩阵为:
J(1)=c(1)s(1)0−s(1)c(1)0001≈0.7882−0.615400.61540.78820001.
一次 Jordan 变换后:
A(1)=(J(1))⊤A(0)J(1)≈2.438400.961006.56162.01900.96102.01906
取最大非对角元 a32(1)≈2.0190,则:
cotθ(2)tanθ(2)cosθ(2)sinθ(2):=τ(2)≈0.1391:=t(2)=−∣τ(2)∣+1+(τ(2))2sign(τ(2))≈−0.8706:=c(2)=1+(t(2))21≈0.7542:=s(2)=c(2)t(2)≈−0.6566
从而旋转矩阵为:
J(2)=[100s(2)00c(2)c(2)−s(2)]≈10000.7542−0.656600.65660.7542.
两次 Jordan 变换后:
A(2)=(J(2))⊤A(1)J(2)≈2.438400.72480.63108.319200.724804.2423
特征值近似为:
λ1≈8.3192,λ2≈4.2423,λ3≈2.4384
使用了如下 python 代码帮助计算:
import numpy as np
np.set_printoptions(precision=4, suppress=True)
A = np.array([[4, 2, 2],
[2, 5, 1],
[2, 1, 6],], dtype=float)
k = 0
n = A.shape[0]
V = np.eye(n)
N = 1000
EPS = 1e-6
while k < N:
k += 1
print(f"===iteration {k} start===")
# 选最大非对角元
p, q = 0, 1
max_off = 0
for i in range(n):
for j in range(i + 1, n):
if abs(A[i, j]) > max_off:
max_off = abs(A[i, j])
p, q = i, j
print(f"A^({k-1})[{p}, {q}] = {A[p, q]:.4f}")
if max_off < EPS:
print("")
print("===all iteration done===")
break
# 计算旋转参数
tau = (A[p, p] - A[q, q]) / (2 * A[p, q])
if tau >= 0:
t = -1 / (tau + np.sqrt(1 + tau**2))
else:
t = 1 / (-tau + np.sqrt(1 + tau**2))
c = 1 / np.sqrt(1 + t**2)
s = c * t
print(f"cot2^({k}) = {tau:.4f}")
print(f"tan^({k}) = {t:.4f}")
print(f"cos^({k}) = {c:.4f}")
print(f"sin^({k}) = {s:.4f}")
# 更新 A
a_pp, a_qq, a_pq = A[p, p], A[q, q], A[p, q]
A[p, p] = c**2 * a_pp + s**2 * a_qq - 2*s*c*a_pq
A[q, q] = s**2 * a_pp + c**2 * a_qq + 2*s*c*a_pq
A[p, q] = A[q, p] = 0
for i in range(n):
if i != p and i != q:
a_ip, a_iq = A[i, p], A[i, q]
A[i, p] = A[p, i] = c*a_ip - s*a_iq
A[i, q] = A[q, i] = s*a_ip + c*a_iq
print(f"A^({k}) = {A}")
# 累积 V
for i in range(n):
v_ip, v_iq = V[i, p], V[i, q]
V[i, p] = c*v_ip - s*v_iq
V[i, q] = s*v_ip + c*v_iq
print(f"V^({k}) = {V}")
print("")
eigvals = np.diag(A)
idx = np.argsort(eigvals)[::-1] # 从大到小排序
eigvals = eigvals[idx]
eigvecs = V[:, idx]
print(f"eigvals:")
for i in range(n):
print(f" lambda_{i} = {eigvals[i]:.4f}")
题 4.3
令:
A(0)=−424−332−727,Q(0)=I3=100010001
第一次迭代:
x(0)=A(0)[0:3,0]=−424,∥x(0)∥2=6
y(0)=−sign(x1(0))⋅∥x(0)∥200=600
v(0)=x(0)−y(0)=−1024,∥v(0)∥2=230
w(0)=∥v(0)∥2v(0)=−305301302≈−0.91290.18260.3651
H(0)=I−2w(0)(w(0))T
A(1)[0:3,0:3]=A(0)[0:3,0:3]−2⋅w(0)⋅((w(0))TA(0)[0:3,0:3])=6004.33331.5333−0.933310−1.40.2
Q(1)[:,0:3]=Q(0)[:,0:3]−2⋅(Q(0)[:,0:3]w(0))⋅(w(0))T=−0.66670.33330.66670.33330.9333−0.13330.6667−0.13330.7333
第二次迭代:
x(1)=A(1)[1:3,1]=[1.5333−0.9333],∥x(1)∥2≈1.7951
y(1)=[−sign(x1(1))⋅∥x(1)∥20]=[−1.79510]
v(1)=x(1)−y(1)=[3.3284−0.9333],∥v(1)∥2≈3.4568
w(1)=∥v(1)∥2v(1)≈[0.9628−0.2700]
H(1)=I−2w(1)(w(1))T
A(2)[1:3,1:3]=A(1)[1:3,1:3]−2⋅w(1)⋅((w(1))TA(1)[1:3,1:3])=[−1.795101.2999−0.5571]
Q(2)[:,1:3]=Q(1)[:,1:3]−2⋅(Q(1)[:,1:3]w(1))⋅(w(1))T=0.0619−0.86660.49520.74280.37140.5571
最终分解:
Q=Q(2)=−0.66670.33330.66670.0619−0.86660.49520.74280.37140.5571
R=A(2)=6004.3333−1.79510101.2999−0.5571
使用了如下 python 代码帮助计算:
import numpy as np
np.set_printoptions(precision=4, suppress=True)
A = np.array([[-4, -3, -7],
[2, 3, 2],
[4, 2, 7],], dtype=float)
n = A.shape[0]
Q = np.eye(n)
for k in range(n - 1):
x = A[k:, k] # (n - k,)
norm_x = np.linalg.norm(x)
if norm_x < 1e-15: # 全 0
continue
y = np.zeros((n - k,)) # (n - k,)
y[0] = -np.sign(x[0]) * norm_x
w = (x - y) / np.linalg.norm(x - y) # (n - k,)
# H = np.eye(n) - 2 * np.outer(w, w)
sub_A = A[k:, k:] # (n - k, n - k)
sub_Q = Q[:, k:] # (n, n - k)
sub_A -= 2 * np.outer(w, w @ sub_A)
sub_Q -= 2 * np.outer(sub_Q @ w, w)
print("Q =")
print(f"{Q}")
print("R =")
print(f"{A}")
print("QR =")
print(f"{Q @ A}")
题 4.4
要求 1
记 n 阶矩阵 A 为 A(n),对应的特征多项式为 p(n)。
归纳证明 p(n) 满足题示形式。
当 n=2 时,A(2) 的特征多项式为:
p(2)(λ)=det(λI−A(2))=λ+c1−1c2λ=λ2+c1λ+c2
成立!
假设 n=k−1 时成立,下证 n=k 时也成立。
A(k) 的特征多项式为:
p(k)(λ)=det(λI−A(k))=λ+c1−100⋮00c2λ−10⋮00c30λ−1⋮00⋯⋯⋯⋯⋱⋯⋯ck−1000⋮λ−1ck000⋮0λ
行列式按最后一列展开得:
p(k)(λ)=det(λI−A(k))=λλ+c1−100⋮00c2λ−10⋮00c30λ−1⋮00⋯⋯⋯⋯⋱⋯⋯ck−2000⋮λ−1ck−1000⋮0λ+ck=λp(k−1)(λ)+ck=λ(λk−1+c1λk−2+⋯+ck−2λ+ck−1)+ck=λk+c1λk−1+⋯+ck−1λ+ck
也成立!
要求 2
整体算法:
- 初始化:令 p0(x)=p(x),次数为 n。
- 迭代求根:对 i=1,2,…,n−1,
- 构造 pi−1(x) 的伴随矩阵 Ai−1,用幂法求 Ai−1 的按模最大特征值,得到 pi−1(x) 按模最大根 xi;
- 对 pi−1(x) 做综合除法,除以 (x−xi) 得到降阶后的商式 pi(x)。
- 终止:当多项式降为 1 次时,pn−1(x)=x+c,直接得最后一个根 xn=−c。
综合除法:
设当前 m 次多项式为
pn−m(x)=xm+c1xm−1+c2xm−2+⋯+cm
设已求得近似根 x=xi,做带余除法:
pn−m(x)=(x−xi)q(x)+r,
其中商式 q(x) 为 m−1 次多项式,记为
q(x)=xm−1+d1xm−2+d2xm−3+⋯+dm−1
比较 (x−r)q(x) 与 pn−m(x) 的系数,得到系数递推关系:
d0dkr=1,=ck+xi⋅dk−1,k=1,2,…,m−1,=cm+xi⋅dm−1≈0
其中 r 约为 0,直接舍去即可。用这些新系数构造下一次迭代的伴随矩阵,继续求根。
题 4.5
系统总输入与总输出
总输入:
- 用户集合 U={u1,…,uN},共 N 位匿名用户
- 原始树洞帖子集合 P={p1,…,pL},每个帖子 pl 包含匿名用户 ID u(pl) 与文本内容
- 食堂菜品名称库 M={d1,…,dM}
总输出:
- 完整预测矩阵 A^∈RN×∣M′∣,其中 M′⊆M 为帖子中出现过的有效菜品集合
- 每位用户的 Top-K 推荐列表(从 M′ 中选取)
阶段一:NLP 文本量化系统
菜品筛选与用户-菜品帖子聚合
- 输入:原始树洞帖子集合 P;菜品名称库 M。
- 输出:
-
有效菜品集合 M′={dj∈M:∃p∈P,dj∈p},即至少被一个帖子提及的菜品子集。
-
对每个用户 ui 和菜品 dj∈M′,
聚合得到 ui 发布的所有提及 dj 的帖子文本集合 Dij=⋃p∈Pu(p)=ui,dj∈pp。
若 ui 从未提及 dj∈M′,则 Dij=∅。绝大多数 (i,j) 对满足 Dij=∅,导致后续口碑矩阵极度稀疏。
实现方式:
- 菜品筛选:遍历所有帖子,对菜品库 M 中每个名称做子串匹配,统计被至少一个帖子提及的菜品,构成有效菜品集合 M′。对未在帖子中出现的菜品,系统无法获得任何信息,故不纳入后续预测。
- 规则匹配:对 M′ 中每个 dj,在帖子文本中做子串匹配。
- 用户归属:按帖子附带的匿名用户ID,将匹配到的文本片段归入对应 Dij。
word2vec 语义空间构建
- 输入:所有帖子文本拼接成的长词序列。
- 输出:词向量矩阵 E∈R∣V∣×d,词表 V 中每个词 w 对应稠密向量 ew∈Rd。
算法实现:
使用 Skip-gram 进行训练。将高维稀疏的 one-hot 空间压缩到低维稠密语义空间。
对于中心词 wt,定义其上下文窗口为 C(wt)={wt−c,…,wt−1,wt+1,…,wt+c},其中 c 为窗口半径。
目标函数为:
L=t=1∑Tw∈C(wt)∑log∑v∈Vexp(ev′Tewt)exp(ew′Tewt)
实际训练中常采用负采样或层次 Softmax 加速优化。
情感语义聚类
- 输入:词向量矩阵 E;少量人工正面种子词 S+ 与负面种子词 S−。
- 输出:正面语义簇 V+、负面语义簇 V−;种子词向量集合 S+,S− 作为后续相似度计算基准。
算法实现:
V+=s∈S+⋃{w∈V:cos(ew,es)>θ},V−=s∈S−⋃{w∈V:cos(ew,es)>θ}
其中 θ 为相似度阈值。
用户-菜品语义特征提取
- 输入:用户-菜品聚合文本 Dij(dj∈M′);词向量矩阵 E;种子词集合 S+,S−.
- 输出:二维语义特征向量 xij=(xij+,xij−)T。若 Dij=∅,则特征缺失。
算法实现:
对 Dij 中每个词 w,计算其与正、负面种子词的最大余弦相似度作为情感权重,累加得到加权和特征:
xij+=w∈Dij∑s∈S+maxcos(ew,es),xij−=w∈Dij∑s∈S−maxcos(ew,es)
用户-菜品口碑量化
- 输入:语义特征 xij=(xij+,xij−)T(仅对 Dij=∅ 的项,且 dj∈M′)。
- 输出:稀疏口碑矩阵 A~=[a~ij]∈RN×∣M′∣,
其中 a~ij∈[1,5] 为用户 ui 对菜品 dj 的文本推断评分;若 Dij=∅,则 a~ij 缺失。
算法实现:
直接基于正面、负面情感权重的比例进行映射,并做拉普拉斯平滑避免除零:
a~ij=1+4⋅xij++xij−+2xij++1
阶段二:SVD 个性化推荐系统
稀疏口碑矩阵的 SVD 补全
- 输入:稀疏口碑矩阵 A~=[a~ij],由阶段一输出,尺寸 N×∣M′∣。
- 输出:
- 完整预测矩阵 A^∈RN×∣M′∣
- 每位用户的 Top-K 推荐列表(从 M′ 中选取)
算法实现:
记观测索引集 Ω={(i,j):Dij=∅}。首先计算全局均值、用户偏差与菜品偏差:
μαiβj=∣Ω∣1(i,j)∈Ω∑a~ij=∣Mi∣1j∈Mi∑a~ij−μ,Mi={j:(i,j)∈Ω}=∣Uj∣1i∈Uj∑a~ij−μ,Uj={i:(i,j)∈Ω}
构造去均值矩阵 B∈RN×∣M′∣:
- 若 (i,j)∈Ω,bij=a~ij−μ−αi−βj。
- 否则 bij=0。
对 B 做截断 SVD:
B≈UkΣkVkT.
最终预测公式为:
a^ij=μ+αi+βj+uiTΣkvj,
其中 uiT 与 vj 分别为 Uk 与 Vk 的第 i、j 行。
Top-K 推荐生成:
- 输入:完整预测矩阵 A^=[a^ij]∈RN×∣M′∣;用户-菜品聚合关系 Dij;有效菜品集合 M′。
- 输出:每位用户 ui 的 Top-K 推荐列表 Rec(ui)={dj1,…,djK}⊆M′。
算法实现:
对每位用户 ui,筛选其未产生过文本提及的有效菜品(即 dj∈M′ 且 Dij=∅ 的项),按预测评分 a^ij 降序排列,取前 K 个菜品构成个性化推荐列表:
Rec(ui)=Top-Kdj∈M′,Dij=∅a^ij
其中 Top-K 表示取前 K 个最大值的索引集合。