【问题标题】:Tensorflow custom layer: Creating a sparse matrix with trainable parametersTensorflow 自定义层:创建具有可训练参数的稀疏矩阵
【发布时间】:2020-01-29 22:28:41
【问题描述】:

我正在研究的模型应该同时预测很多变量 (>1000)。因此,我想在每个输出的网络末端都有一个小型神经网络。

为了紧凑地做到这一点,我想找到一种方法,在 Tensorflow 框架内的神经网络的两层之间创建稀疏的可训练连接。

只有一小部分连接矩阵应该是可训练的:只有参数是块对角线的一部分。


例如:

连接矩阵如下:

可训练的参数应该在 1 的位置。

【问题讨论】:

  • 那么你具体想要什么?您想知道如何在 tensorflow 中创建稀疏矩阵,或者您正在努力解决什么问题?
  • @eugen 是的,我想创建一个稀疏的可训练矩阵,至少一个遵循上述模式
  • 好的,我已经发布了答案,看看
  • 我确信有更好的方法,但您可以创建一个密集的权重矩阵,并在激活函数之前将其乘以块对角矩阵。这样,与块诊断矩阵中位置 0 相关联的所有权重的梯度将被清零,并且权重不会改变。
  • @foglerit 这会使事情变得相当缓慢。 TF 在优化时仍然会考虑所有变量,对吧?

标签: python tensorflow machine-learning


【解决方案1】:

我写的正是这样一个层:

https://github.com/ArnovanHilten/GenNet/blob/master/GenNet_utils/LocallyDirectedConnected_tf2.py

它将稀疏矩阵作为输入,让您决定如何在层之间连接。该层使用稀疏张量和矩阵乘法。

【讨论】:

    【解决方案2】:

    编辑 所以评论是Is this a trainable object though?

    答案:不。您目前不能使用稀疏矩阵并使其可训练。相反,您可以使用掩码矩阵(见最后)

    但是如果你需要使用稀疏矩阵,你只需要使用tf.sparse.sparse_dense_matmul()tf.sparse_tensor_to_dense(),你的稀疏矩阵与密集矩阵交互。我从here 中获取了一个简单的 XOR 示例,并用稀疏矩阵替换了 dense:

    #Declaring necessary modules
    import tensorflow as tf
    import numpy as np
    """
    A simple numpy implementation of a XOR gate to understand the backpropagation
    algorithm
    """
    
    x = tf.placeholder(tf.float32,shape = [4,2],name = "x")
    #declaring a place holder for input x
    y = tf.placeholder(tf.float32,shape = [4,1],name = "y")
    #declaring a place holder for desired output y
    
    m = np.shape(x)[0]#number of training examples
    n = np.shape(x)[1]#number of features
    hidden_s = 2 #number of nodes in the hidden layer
    l_r = 1#learning rate initialization
    
    theta1 = tf.SparseTensor(indices=[[0, 0],[0, 1], [1, 1]], values=[0.1, 0.2, 0.1], dense_shape=[3, 2])
    #theta1 = tf.cast(tf.Variable(tf.random_normal([3,hidden_s]),name = "theta1"),tf.float64)
    theta2 = tf.cast(tf.Variable(tf.random_normal([hidden_s+1,1]),name = "theta2"),tf.float32)
    
    #conducting forward propagation
    a1 = tf.concat([np.c_[np.ones(x.shape[0])],x],1)
    #the weights of the first layer are multiplied by the input of the first layer
    
    #z1 = tf.sparse_tensor_dense_matmul(theta1, a1)
    
    z1 = tf.matmul(a1,tf.sparse_tensor_to_dense(theta1))
    #the input of the second layer is the output of the first layer, passed through the 
    
    a2 = tf.concat([np.c_[np.ones(x.shape[0])],tf.sigmoid(z1)],1)
    #the input of the second layer is multiplied by the weights
    
    z3 = tf.matmul(a2,theta2)
    #the output is passed through the activation function to obtain the final probability
    
    h3 = tf.sigmoid(z3)
    cost_func = -tf.reduce_sum(y*tf.log(h3)+(1-y)*tf.log(1-h3),axis = 1)
    
    #built in tensorflow optimizer that conducts gradient descent using specified 
    
    optimiser = tf.train.GradientDescentOptimizer(learning_rate = l_r).minimize(cost_func)
    
    #setting required X and Y values to perform XOR operation
    X = [[0,0],[0,1],[1,0],[1,1]]
    Y = [[0],[1],[1],[0]]
    
    #initializing all variables, creating a session and running a tensorflow session
    init = tf.global_variables_initializer()
    sess = tf.Session()
    sess.run(init)
    
    #running gradient descent for each iterati
    for i in range(200):
       sess.run(optimiser, feed_dict = {x:X,y:Y})#setting place holder values using feed_dict
       if i%100==0:
          print("Epoch:",i)
          print(sess.run(theta1))
    

    输出是:

    Epoch: 0
    SparseTensorValue(indices=array([[0, 0],
           [0, 1],
           [1, 1]]), values=array([0.1, 0.2, 0.1], dtype=float32), dense_shape=array([3, 2]))
    Epoch: 100
    SparseTensorValue(indices=array([[0, 0],
           [0, 1],
           [1, 1]]), values=array([0.1, 0.2, 0.1], dtype=float32), dense_shape=array([3, 2]))
    
    

    所以唯一的方法是使用掩码矩阵。您可以通过乘法或 tf.where 使用它

    1) 乘法:您可以创建所需形状的掩码矩阵并将其与权重矩阵相乘:

    mask = tf.Variable([[1,0,0],[0,1,0],[0,0,1]],name ='mask', trainable=False)
    weight = tf.cast(tf.Variable(tf.random_normal([3,3])),tf.float32)
    desired_tensor = tf.matmul(weight, mask)
    

    2) tf.where

    mask = tf.Variable([[1,0,0],[0,1,0],[0,0,1]],name ='mask', trainable=False)
    weight = tf.cast(tf.Variable(tf.random_normal([3,3])),tf.float32)
    desired_tensor = tf.where(mask > 0, tf.ones_like(weight), weight)
    

    希望对你有帮助


    你可以像这样使用稀疏张量来做到这一点:

    SparseTensor(indices=[[0, 0], [1, 2]], values=[1, 2], dense_shape=[3, 4])
    
    

    输出是:

    [[1, 0, 0, 0]
     [0, 0, 2, 0]
     [0, 0, 0, 0]]
    
    

    你可以在这里查看更多关于稀疏张量的文档:

    https://www.tensorflow.org/api_docs/python/tf/sparse/SparseTensor

    希望对你有帮助!

    【讨论】:

    • 这是一个可训练的对象吗?
    猜你喜欢
    • 2011-11-07
    • 1970-01-01
    • 2016-10-25
    • 2012-01-10
    • 2017-03-31
    • 1970-01-01
    • 2018-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多