代码之家  ›  专栏  ›  技术社区  ›  The Rhyno

用张量流中的线性代数帮助新手(3阶张量)

  •  2
  • The Rhyno  · 技术社区  · 6 年前

    我怀疑这已经被问到了,尽管在我的搜索中,许多其他问题都有特定的独特问题,似乎不适用于我的情况(或者解决方案超出了我的想象)。

    我在TensorFlow中有一个标准的前馈神经网络,它的行为与rank2大小的输入张量是正确的。 [None, n_features] ,重量 [n_features, n_neurons] 从而形成一个 tf.matmul(inputs, weight) = [None, n_neurons] .

    但是,我希望在输入和输出中将维度扩展一个维度。例如,我想

    inputs = tf.placeholder("float", shape=[None, n_type, n_features])
    weight= tf.Variable(FNN_weight_initializer([n_type, n_features, n_neurons]))
    Hidden1 = tf.matmul(inputs, weight)
    

    我的最终目标是 Hidden1 = [None, n_type, n_neurons] .

    然而,我没有生成所需的张量形状,而是得到了形状的张量。 [n_type, n_type, n_neurons] . 我不是线性代数专家,我尝试过几次维数顺序的组合,但都没有成功。甚至可以用rank3张量乘以 tf.matmul ?我应该在这里做整形或转位手术吗?

    1 回复  |  直到 5 年前
        1
  •  2
  •   syltruong    6 年前

    根据操作员的意见进行编辑

    可以将输入的特征向量展平为形状 [-1, n_type * n_features] ,应用精心选择的矩阵乘法,并从 [-1, n_type * n_neurons] [-1, n_type, n_neurons]

    运算张量是块对角线 [n_type * n_features, n_type * n_neurons] 一个,每个块是 n_type 张量 weights .

    为了构建一个块对角矩阵,我使用了另一个答案(来自 here )

    这个看起来像

    inputs = tf.placeholder("float", shape=[None, n_type, n_features])
    inputs = tf.reshape(inputs, shape=[-1, n_type * n_features])
    
    weights = tf.Variable(FNN_weight_initializer([n_type, n_features, n_neurons]))
    
    split_weights = tf.split(weights, num_or_size_splits=n_type, axis=1)
    # each element of split_weights is a tensor of shape : [1, n_features, n_neurons] -> need to squeeze
    split_weights = tf.map_fn(lambda elt : tf.squeeze(elt, axis=0), split_weights)
    
    block_matrix = block_diagonal(split_weights) # from the abovementioned reference
    
    Hidden1 = tf.matmul(inputs, block_matrix)
    # shape : [None, n_type * n_neurons]
    
    Hidden1 = tf.reshape(Hidden1, [-1, n_type, n_neurons])
    # shape : [None, n_type, n_neurons]
    

    原始答案

    根据文件 tf.matmul ( reference )你要乘的张量必须是同一个等级。

    当等级是 >2 只有最后两个维度需要矩阵乘法兼容,第一个其他维度需要完全匹配。

    那么,对于这个问题,“能不能用tf.matmul把rank3张量相乘?”答案是“是的,这是可能的,但从概念上讲,它仍然是第二级乘法”。

    因此,需要进行一些整形:

    inputs = tf.placeholder("float", shape=[None, n_type, n_features])
    
    inputs = tf.reshape(inputs, shape=[-1, n_type, 1, n_features])
    
    weights = tf.Variable(FNN_weight_initializer([n_type, n_features, n_neurons]))
    
    weights = tf.expand_dims(weights, 0)
    # shape : [1, n_type, n_features, n_neurons]
    
    weights = tf.tile(weights, [tf.shape(inputs)[0], 1, 1, 1])
    # shape : [None, n_type, n_features, n_neurons]
    
    Hidden1 = tf.matmul(inputs, weights)
    # shape : [None, n_type, 1, n_neurons]
    
    Hidden1 = tf.reshape(Hidden1, [-1, n_type, n_neurons])
    # shape : [None, n_type, n_neurons]