Julia与Zygote:QR分解时伴随算子错误的解决求助
解决Zygote求导时QRCompactWYQ构造器无伴随的问题
问题背景
我实现了GEKPLS代理函数,尝试用Zygote计算梯度以寻找最优theta参数,运行以下代码时触发错误:
function min_rlfv(theta) g = GEKPLS(X, y, grads, n_comp, delta_x, xlimits, extra_points, theta) return -g.reduced_likelihood_function_value end Zygote.gradient(min_rlfv, [0.01, 0.1])
错误信息:
ERROR: Need an adjoint for constructor LinearAlgebra.QRCompactWYQ{Float64, Matrix{Float64}}. Gradient is of type LinearAlgebra.Transpose{Float64, Matrix{Float64}}
堆栈追踪指向_reduced_likelihood_function函数中的Q, G = qr(Ft)行。
解决思路
1. 直接替换为最小二乘运算符(最优方案)
观察代码中QR分解的用途:通过Q和G计算beta = G \ [(transpose(Q) ⋅ Yt)],这本质是求解线性最小二乘问题Ft * beta ≈ Yt。Julia的反斜杠运算符\已经封装了稳定的最小二乘求解逻辑,且Zygote对其有完善的梯度支持。直接替换这部分代码即可:
# 替换原代码中从QR到beta的部分 # Q, G = qr(Ft) # Q = Array(Q) # Yt = C \ y_norma # beta = G \ [(transpose(Q) ⋅ Yt)] Yt = C \ y_norma beta = Ft \ Yt # 直接用最小二乘替代QR分解逻辑
这种方式既简化了代码,又彻底避开了Zygote不支持的QRCompactWYQ类型问题,同时保留了数值稳定性。
2. 手动定义QRCompactWYQ的伴随函数
如果必须保留QR分解逻辑,可以手动为QRCompactWYQ构造器添加Zygote伴随函数,解决梯度传递问题:
using Zygote Zygote.@adjoint function LinearAlgebra.QRCompactWYQ(Q::AbstractMatrix) # 构造原对象,反向传播时将梯度转为矩阵类型 QRCompactWYQ(Q), Δ -> (Matrix(Δ),) end
注意:需要验证该伴随函数的梯度正确性,确保不会引入计算偏差。
3. 改用显式矩阵形式获取Q
将QR分解的结果直接转换为矩阵类型,跳过中间的QRCompactWYQ包装:
# 替换原Q, G = qr(Ft) qr_result = qr(Ft) Q = Matrix(qr_result.Q) G = qr_result.R # 注意原代码中G对应QR分解的R因子
这种方式能避免直接接触QRCompactWYQ类型,可能让Zygote正常处理梯度,但本质还是依赖QR分解的梯度支持,不如第一种方案可靠。
内容的提问来源于stack exchange,提问作者vikram-s-narayan
相关产品推荐
相关产品推荐

