Keras密集层输出形状

时间:2020-05-02 14:23:47

标签: python machine-learning keras deep-learning keras-layer

我无法理解获取第一个隐藏层的输出形状背后的逻辑。我采取了一些任意的例子,如下:

示例1:

model.add(Dense(units=4,activation='linear',input_shape=(784,)))  
model.add(Dense(units=10,activation='softmax'))
model.summary()

Model: "sequential_4"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_7 (Dense)              (None, 4)                 3140      
_________________________________________________________________
dense_8 (Dense)              (None, 10)                50        
=================================================================
Total params: 3,190
Trainable params: 3,190
Non-trainable params: 0

示例2:

model.add(Dense(units=4,activation='linear',input_shape=(784,1)))   
model.add(Dense(units=10,activation='softmax'))
model.summary()
Model: "sequential_6"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_11 (Dense)             (None, 784, 4)            8         
_________________________________________________________________
dense_12 (Dense)             (None, 784, 10)           50        
=================================================================
Total params: 58
Trainable params: 58
Non-trainable params: 0

示例3:

model.add(Dense(units=4,activation='linear',input_shape=(32,28)))    
model.add(Dense(units=10,activation='softmax'))
model.summary()
Model: "sequential_8"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_15 (Dense)             (None, 32, 4)             116       
_________________________________________________________________
dense_16 (Dense)             (None, 32, 10)            50        
=================================================================
Total params: 166
Trainable params: 166
Non-trainable params: 0

示例4:

model.add(Dense(units=4,activation='linear',input_shape=(32,28,1)))    
model.add(Dense(units=10,activation='softmax'))
model.summary()
Model: "sequential_9"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_17 (Dense)             (None, 32, 28, 4)         8         
_________________________________________________________________
dense_18 (Dense)             (None, 32, 28, 10)        50        
=================================================================
Total params: 58
Trainable params: 58
Non-trainable params: 0

请帮助我理解逻辑。

此外,我认为input_shape=(784,)input_shape=(784,1)的排名相同,那么为什么它们的Output Shape不同?

6 个答案:

答案 0 :(得分:2)

根据Keras的官方文档,对于密集层,当您将输入作为input_shape=(input_units,)时,将模态作为形状为(*, input_units)的输入数组,并输出形状为(*, output_units)的数组 [在您的情况下,input_shape=(784,)被视为input shape=(*, 784),输出为output_shape=(*,4)]

通常对于输入维度(batch_size, ..., input_dim),模态给出大小为(batch_size, ..., units)的输出。

因此,当您将输入作为input_shape=(784,)时,模态将作为形状为(*, 784)的输入数组,其中*是批处理大小,784作为input_dim,给出输出形状为(*, 4)

当输入为(784,1)时,模态将其作为(*, 784, 1),其中*是批处理大小,784...和{{1} }是input_dim => 1,输出为(batch_size, ..., input_dim) => (*, 784, 4)

(batch_size, ..., units)相同,给出输出input_shape=(32,28)=>(*,32,28),并输入(*,32,4),其中input_shape=(32,28,1)=>(*,32,28,1)也是batch_size,*是{{1} }和32,28是input_dim => ...

“无”代表什么,请检查What is the meaning of the "None" in model.summary of KERAS?

答案 1 :(得分:2)

逻辑非常简单:将密集层独立地应用于到上一层的最后一个维度。因此,通过具有(d1, ..., dn, d)个单位的密集层输入形状m会导致形状(d1, ..., dn, m)的输出,并且该层具有d*m+m个参数(m偏见)。

请注意,相同的权重是独立应用的,因此示例4的工作方式如下:

for i in range(32):
    for j in range(28):
        output[i, j, :] = input[i, j, :] @ layer.weights + layer.bias

@是矩阵乘法。 input[i, j]是形状为(1,)的向量,layer.weights的大小为(1,4)layer.bias是形状的向量(1,)

这也解释了为什么(784,)(784,1)给出不同的结果:它们的最后一个尺寸不同,分别为784和1。

答案 2 :(得分:1)

密集层需要输入的内容为(batch_size,input_size),大多数情况下,我们在训练过程中会跳过batch_size并对其进行定义。

如果输入形状是一维的,则在第一种情况下(784,),模型将作为形状(〜,784)的输入数组和形状(〜,4)的输出数组。默认情况下,它将添加偏差4(因为4个单位)。因此总参数将为

parameters -> 784*4 + 4 = 3140

如果输入形状为二维,则在第二种情况下(784,1),模型将作为形状(784,1)的输入数组和形状(None,784,4)的输出数组。{{1} }是批次维度。默认情况下,它将添加偏差4(因为4个单位)。因此总参数将为

None

答案 3 :(得分:1)

图层的输出形状取决于所使用图层的类型。例如,std::vector<reachability::values_t> v; std::list<reachability::values_t> l; std::pair<int,int> p; reachability::operator<<(cout, vals); // OK reachability::operator<<(cout, v); // OK reachability::operator<<(cout, l); // OK reachability::operator<<(cout, p); // Wrong, compile-time error, no match ... 层的输出形状基于该层中定义的Dense,其中units层的输出形状取决于Conv

要记住的另一件事是,默认情况下,任何输入的最后一个维度被视为通道数。在输出形状估计的过程中,通道数被层中定义的filters替换。对于units等一维输入,最后使用input_shape=(784,)很重要。

示例1(一维),示例2(2维,通道= 1),示例3(2维,通道= 28)和示例4(3维,通道= 1)。如上所述,最后一个维度被,层中定义的units取代。

在此Demo答案中非常清楚地提到了有关尺寸,轴,通道,input_dim等的更多详细信息。

答案 4 :(得分:1)

keras是一个高级api,它负责很多抽象。以下示例可以帮助您更好地理解。在您的问题中,这是与keras抽象最接近的原始tensorflow等效值:

import tensorflow as tf
from pprint import pprint


for shape in [(None,784,), (None, 784,1), (None, 32,28), (None, 32,28,1)]:
    shapes_list = []

    input_layer_1 = tf.compat.v1.placeholder(dtype=tf.float32, shape=shape, name=None)
    shapes_list.append(input_layer_1.shape)
    d1 = tf.compat.v1.layers.dense(
        inputs=input_layer_1, units=4, activation=None, use_bias=True, kernel_initializer=None,
        bias_initializer=tf.zeros_initializer(), kernel_regularizer=None,
        bias_regularizer=None, activity_regularizer=None, kernel_constraint=None,
        bias_constraint=None, trainable=True, name=None, reuse=None
    )
    shapes_list.append(d1.shape)
    d2 = tf.compat.v1.layers.dense(
        inputs=d1, units=10, activation=tf.compat.v1.nn.softmax, use_bias=True, kernel_initializer=None,
        bias_initializer=tf.zeros_initializer(), kernel_regularizer=None,
        bias_regularizer=None, activity_regularizer=None, kernel_constraint=None,
        bias_constraint=None, trainable=True, name=None, reuse=None
    )
    shapes_list.append(d2.shape)
    print('++++++++++++++++++++++++++')
    pprint(shapes_list)
    print('++++++++++++++++++++++++++')

Dense函数用于制作密集连接的层或Perceptron

按照您的代码片段,您似乎已经创建了一个多层感知器(具有线性激活函数f(x)= x),其中隐藏层1具有4个神经元,而输出层针对10个类/标签进行了自定义预料到的。

每层神经元的数量由 units 参数确定。并且 layer_L 中每个神经元的形状取决于前一个 layer_L-1 的输出。

如果输入到密集层的输入为(BATCH_SIZE, N, l),那么输出的形状将为(BATCH_SIZE, N, value_passed_to_argument_units_in_Dense)

如果输入为(BATCH_SIZE, N, M, l),则输出形状为(BATCH_SIZE, N, M, value_passed_to_argument_units_in_Dense),依此类推。

注意:

仅在Dense神经元的情况下会发生这种情况,因为它不会更改batch_size和last_channel之间的中间尺寸。

但是,在其他神经元(例如 Conv2D->(最大/平均)合并)的情况下,中间维度可能也会改变(取决于传递的参数),因为这些神经元也会对这些维度起作用。

答案 5 :(得分:1)

根据keras

Dense layer is applied on the last axis independently. [1]

https://github.com/keras-team/keras/issues/10736#issuecomment-406589140

第一个示例:

input_shape=(784,)
model.add(Dense(units=4,activation='linear',input_shape=(784,)))

它表示输入只有784行。模型的第一层有4个单位。密集层中的每个单元都连接到所有784行。

这就是为什么

Output shape=  (None, 4) 

没有代表这里不知道的batch_size。

第二个示例

在此处输入第2级张量

input_shape=(784,1)
Units = 4

因此,现在输入为784行和1行。 现在,密集层的每个单元都连接到总共784行中的每一行中的1个元素。 输出形状=(None,784,4)
批量大小无。

第三个示例

 input_shape=(32,28)

现在,每个密集层单元都连接到32行中每行的28个元素。所以

output_shape=(None,32,4)

最后一个例子

model.add(Dense(units=4,activation='linear',input_shape=(32,28,1)))   

再次在最后一个轴上应用了致密层,输出形状变为

Output Shape =(None,32,28,4)

注意

rank在(784,)处为1,逗号不代表其他维度。 在(784,1)处排名2

stackcoverflow中的图表可能会为您提供进一步的帮助。