Keras/TensorFlow添加幺正性约束后损失返回数组问题求助
问题
在Keras(TensorFlow框架)中为自定义损失函数添加幺正性约束时遇到问题。
原损失函数代码:
self.__loss_fn = tf.reduce_mean( tf.square( self.__psiNNy - tf.matmul(self.__psiNNx, self.__K) ) )
添加幺正性约束($K^T K = I$)后,修改的损失函数代码:
self.__loss_fn = tf.reduce_mean( tf.square( self.__psiNNy - tf.matmul(self.__psiNNx, self.__K) ) ) + tf.multiply(alpha, tf.matmul(tf.transpose(self.__K),self.__K)-1))
其中alpha为惩罚系数,但运行后损失未返回标量值,而是输出数组:
Epoch - 0 Loss - [[-0.3633499 -1.2530719 -1.29390422 ... -0.90075779 -0.81838405 -0.94197399] [-1.2530719 14.31707269 14.78048348 ... -5.04269215 -5.24336678 -0.27613182] [-1.29390422 14.78048348 15.89136624 ... -5.83845412 -6.28395005 -0.08354599] ... [-0.90075779 -5.04269215 -5.83845412 ... 1.25852317 0.25653466 -0.60421091] [-0.81838405 -5.24336678 -6.28395005 ... 0.25653466 5.08378911 -4.45022781] [-0.94197399 -0.27613182 -0.08354599 ... -0.60421091 -4.45022781 2.03832155]] LR - 0.0001 Time - 1.472019910812378
解决方案
问题核心是幺正性约束部分的计算没有压缩为标量:
tf.matmul(tf.transpose(self.__K), self.__K) - 1得到的是一个方阵(与K同维度),直接和原损失(标量)相加后,整个损失会变成张量而非标量,导致输出数组。- 正确做法是将矩阵误差转化为标量,常用两种方式:
- 计算矩阵所有元素的平方损失均值:
self.__loss_fn = tf.reduce_mean(tf.square(self.__psiNNy - tf.matmul(self.__psiNNx, self.__K))) + alpha * tf.reduce_mean(tf.square(tf.matmul(tf.transpose(self.__K), self.__K) - tf.eye(tf.shape(self.__K)[1]))) - 计算矩阵的Frobenius范数(等价于所有元素平方和的平方根,也可直接用平方和):
self.__loss_fn = tf.reduce_mean(tf.square(self.__psiNNy - tf.matmul(self.__psiNNx, self.__K))) + alpha * tf.norm(tf.matmul(tf.transpose(self.__K), self.__K) - tf.eye(tf.shape(self.__K)[1]), ord='fro')
- 计算矩阵所有元素的平方损失均值:
注意事项:
- 用
tf.eye(tf.shape(self.__K)[1])代替1,因为我们需要的是与K^T K同维度的单位矩阵,直接用标量1会触发广播,不符合幺正性约束的数学定义。 - 必须将约束项的矩阵误差压缩为标量,才能和原损失(标量)相加得到合法的损失值。
内容的提问来源于stack exchange,提问作者Carlos
相关产品推荐
相关产品推荐

