Python keras层中的线性代数

Python keras层中的线性代数,python,numpy,tensorflow,keras,scipy,Python,Numpy,Tensorflow,Keras,Scipy,我试图在keras中将scipy.lingalg.null\u空间模块实现为Lambda层。 我的输入是成批的numpy形状数组(5,5),但是一个简单的 def ns(x_array): x_array = np.array(x_array) return null_space(x_array) null = keras.layers.Lambda(lambda x: ns(x) )(input) 生成错误消息: ~/miniconda3/lib/python3.7/si

我试图在
keras
中将
scipy.lingalg.null\u空间
模块实现为Lambda层。 我的输入是成批的
numpy
形状数组
(5,5)
,但是一个简单的

def ns(x_array):
    x_array = np.array(x_array)
    return null_space(x_array)

null = keras.layers.Lambda(lambda x: ns(x) )(input)
生成错误消息:


~/miniconda3/lib/python3.7/site-packages/scipy/linalg/decomp_svd.py in null_space(A, rcond)
    382 
    383     """
--> 384     u, s, vh = svd(A, full_matrices=True)
    385     M, N = u.shape[0], vh.shape[1]
    386     if rcond is None:

~/miniconda3/lib/python3.7/site-packages/scipy/linalg/decomp_svd.py in svd(a, full_matrices, compute_uv, overwrite_a, check_finite, lapack_driver)
    107 
    108     """
--> 109     a1 = _asarray_validated(a, check_finite=check_finite)
    110     if len(a1.shape) != 2:
    111         raise ValueError('expected matrix')

~/miniconda3/lib/python3.7/site-packages/scipy/_lib/_util.py in _asarray_validated(a, check_finite, sparse_ok, objects_ok, mask_ok, as_inexact)
    240     if not objects_ok:
    241         if a.dtype is np.dtype('O'):
--> 242             raise ValueError('object arrays are not supported')
    243     if as_inexact:
    244         if not np.issubdtype(a.dtype, np.inexact):

ValueError: object arrays are not supported

我想我必须将
null_space
的输入强制为二维数组(而不是每个批次的三维形状),但我不确定如何做到这一点

您可以使用keras/tensorflow重新实现
null\u空间。请参阅scipy源代码

实现看起来很简单。不过,您必须使用svd,这样才能使用


编辑:我通常不这样做,但我很好奇,所以这里有一个
null\u space
的tensorflow实现。输出接近但不完全等于scipy的输出

将numpy导入为np
导入tensorflow作为tf
float32_eps=np.finfo(np.float32.eps)
def tf_null_空间(A,rcond=None):
s、 u,vh=tf.linalg.svd(A,完整矩阵=True)
vh=tf.转置(vh)
M、 N=u形[0],vh形[1]
如果rcond为None:
rcond=浮动32_每股收益*最大值(M,N)
tol=tf.减少最大值*rcond
num=tf.reduce_sum(tf.cast(s>tol,tf.int32))
Q=tf.math.conj(tf.transpose(vh[num:,:]))
返回Q

如果您将其用作神经网络的一部分,则不能在Lambda层中使用numpy,因为您无法通过使用keras/tensorflow的numpy进行区分。我认为您的意思是复制
null\u空间
定义,并基本上用
tf
替换
np
?听起来多少有道理。但是您必须弄清楚如何处理
np.finfo
调用。您可以假设输入数据类型,如float32,并将其eps存储为常量。回到这里,我现在的问题是计算小于公差的奇异值的数量,并使用此数字提取由
tf.linalg.svd
…@非宗教提供的
v
的正确列-请参阅我更新的答案。它应该能回答你的问题,非常感谢@jakub,但我仍然在这方面发现了一些错误(我之前也尝试过类似的方法)-首先
rcond
定义错误(通过移除max(m,N)来修复):
在tf_null_空间(a,rcond)28 m,N=u.shape[0],vh.shape[1]29如果rcond为None:-->30 rcond=float32\u eps*max(M,N)31 tol=tf.reduce\u max(s)*rcond 32 num=tf.reduce\u sum(tf.cast(s>tol,tf.int32))。。。411 412 def\uu floordiv\uuu(self,other):类型错误:不支持*的操作数类型:'Dimension'和'float'