RNN模型将估计矩阵用作MVN协方差时如何避免输入矩阵不可逆报错
报错原因
触发Input matrix is not invertible错误的核心是你构造的协方差矩阵为奇异/半正定矩阵,不符合tf.linalg.cholesky要求的严格正定可逆的输入条件。通常是参数训练过程中的波动、数值精度误差,加上当前的矩阵构造逻辑冗余导致的。
修复方案
- 方案1:直接构造合法的下三角缩放矩阵(最优方案,从根源规避问题)
你当前的逻辑完全冗余,MultivariateNormalTriL本身就接受下三角的scale_tril参数,无需先生成协方差再做Cholesky分解。你可以直接对估计的三角参数做如下处理:
X_list=list of triangular matrix components like 6 numbers for a 3*3 matrix (for n*n matrix, n(n+1)/2 ) mean=list of n numbers for n*n MVN distribution # 直接生成下三角矩阵 X_tril = tfp.math.fill_triangular(X_list, upper=False) # 给对角线加Softplus激活,保证对角线元素严格为正,这样scale_tril必然可逆 X_tril = tf.linalg.set_diag(X_tril, tf.nn.softplus(tf.linalg.diag_part(X_tril))) # 直接传入合法的scale_tril,无需计算协方差和Cholesky分解 dist = tfp.distributions.MultivariateNormalTriL(loc=mean, scale_tril=X_tril) return tf.reduce_mean(-dist.log_prob(sample))
- 方案2:如果业务需要保留协方差矩阵的计算逻辑,给协方差加对角抖动
如果你的场景必须先得到协方差矩阵,可以在做Cholesky分解前给协方差的对角线加一个极小的正数值(通常取1e-6~1e-4即可),保证矩阵严格正定:
X_list=list of triangular matrix components like 6 numbers for a 3*3 matrix (for n*n matrix, n(n+1)/2 ) mean=list of n numbers for n*n MVN distribution X_upper = tfp.math.fill_triangular(X_list, upper=True) X_symm = 0.5 * (X_upper + tf.transpose(X_upper, perm=[0,2,1])) cov=tf.matmul(X_symm, tf.transpose(X_symm, perm=[0,2,1])) # 加对角抖动 jitter = 1e-6 * tf.eye(cov.shape[-1], batch_shape=cov.shape[:-2]) cov = cov + jitter dist = tfp.distributions.MultivariateNormalTriL(loc=mean, scale_tril=tf.linalg.cholesky(cov)) return tf.reduce_mean(-dist.log_prob(sample))
- 额外优化点:训练初始化时将三角矩阵的对角线参数初始化为1左右的正值,避免训练初期就出现对角线为0/负的情况,减少初期报错概率。
内容的提问来源于stack exchange,提问作者Tanzin Farhat
相关产品推荐
相关产品推荐

