了解每一层的 Keras 权重矩阵

Posted

技术标签:

【中文标题】了解每一层的 Keras 权重矩阵【英文标题】:Understanding Keras weight matrix of each layers 【发布时间】:2017-12-01 03:22:59 【问题描述】:

我正在尝试使用 Keras 中的全连接层架构进行二进制分类,这在 Keras 中称为 Dense 类。

这是我创建的神经网络架构的设计:

 from keras.models import Sequential
        from keras.layers import Dense, Dropout, Activation
        from keras.optimizers import SGD

        self.model = Sequential()
        # Dense(64) is a fully-connected layer with 64 hidden units.
        # in the first layer, you must specify the expected input data shape:
        # here, 20-dimensional vectors.
        self.model.add(Dense(32, activation='relu', input_dim=self.x_train_std.shape[1]))
        #self.model.add(Dropout(0.5))
        #self.model.add(Dense(64, activation='relu'))
        #self.model.add(Dropout(0.5))
        self.model.add(Dense(1, activation='sigmoid'))

所以我有一个 17000,2000 的输入矩阵,其中 17K 个样本具有 2k 个特征。

我只保留了一个隐藏层,其中包含 32 个单元或神经元。

我的输出层是一个具有 sigmoid 激活函数的神经元。

现在,当我尝试检查第一个隐藏层的权重时,我期望它的大小为 (2000,32),其中每一行用于每个输入,每列用于该层中的每个单元。

这是 Keras 架构设置的配置:

dl_1.model.get_config()
Out[70]:
['class_name': 'Dense',
  'config': 'activation': 'relu',
   'activity_regularizer': None,
   'batch_input_shape': (None, 2000),
   'bias_constraint': None,
   'bias_initializer': 'class_name': 'Zeros', 'config': ,
   'bias_regularizer': None,
   'dtype': 'float32',
   'kernel_constraint': None,
   'kernel_initializer': 'class_name': 'VarianceScaling',
    'config': 'distribution': 'uniform',
     'mode': 'fan_avg',
     'scale': 1.0,
     'seed': None,
   'kernel_regularizer': None,
   'name': 'dense_1',
   'trainable': True,
   'units': 32,
   'use_bias': True,
 'class_name': 'Dense',
  'config': 'activation': 'sigmoid',
   'activity_regularizer': None,
   'bias_constraint': None,
   'bias_initializer': 'class_name': 'Zeros', 'config': ,
   'bias_regularizer': None,
   'kernel_constraint': None,
   'kernel_initializer': 'class_name': 'VarianceScaling',
    'config': 'distribution': 'uniform',
     'mode': 'fan_avg',
     'scale': 1.0,
     'seed': None,
   'kernel_regularizer': None,
   'name': 'dense_2',
   'trainable': True,
   'units': 1,
   'use_bias': True]

查看第一个隐藏层的维度:

dl_1.model.get_layer(name="dense_1").input_shape

(None, 2000)

输出尺寸:

    dl_1.model.get_layer(name="dense_1").output_shape
Out[99]:
(None, 32)

所以它似乎确实给出了预期的 (2000,32)。

但是,当我尝试检查该层的权重矩阵时

dl_1.model.get_layer(name="dense_1").get_weights()[0]

它给了我一个 numpy 数组列表,列表长度为 2000,数组长度在 32 之内,如下所示:

array([[ 0.0484077 , -0.02401097, -0.03099879, -0.02864455, -0.01511723,
         0.01386002,  0.01127522,  0.00844895, -0.02420873,  0.04466306,
         0.02965425,  0.0410631 ,  0.02397312,  0.0038885 ,  0.04846045,
         0.00653989, -0.05288456, -0.00325713,  0.0445733 ,  0.04594839,
         0.02839083,  0.0445912 , -0.0140048 , -0.01198476,  0.05259909,
        -0.03752745, -0.01337494, -0.02162734, -0.01522341,  0.01208428,
         0.01122886,  0.01496441],
       [ 0.05225918,  0.04231448,  0.01388102, -0.03310467, -0.05293509,
         0.01130457,  0.03127011, -0.04250741, -0.04212657, -0.01595866,
        -0.002456  ,  0.01112743,  0.0150629 ,  0.03072598, -0.04061607,
        -0.01131565, -0.02259113,  0.00907649, -0.04728404, -0.00909081,
         0.03182121, -0.04608218, -0.04411709, -0.03561752,  0.04686243,
        -0.04555761,  0.04087613,  0.04380137,  0.02079088, -0.02390963,
        -0.0164928 , -0.01228274],

我不确定我是否理解这一点。它应该是 32 X2000 而不是 2000 X 32。所以我期待,因为我有 32 个单元,并且每个单元有 2000 个权重,所以列表将是 32 个元素长,每个元素应该是 2000 维 numpy 数组。但它是相反的。我不确定这是为什么?

权重与隐藏层相关联,而不是与输入层相关联,所以如果我认为它们为输入层显示它是没有意义的。

知道这是怎么回事吗?

【问题讨论】:

没什么,只是符号和约定的问题。 是的,我明白这一点。但这不是一个不方便的约定吗?想想看。当我说我想检查一个层的权重时,基本上意味着我想找出该层中每个单元的权重是多少。它还使我可以灵活地按单元 (1, 2, 3,,) 为层编制索引,然后找出该单元的所有权重。但是现在,Keras 的方式,是上一层的一个单元,这意味着 【参考方案1】:

您正在创建一个包含 32 个单元的 Dense() 层。 Dense 层是(正如您在代码中的注释所示)“全连接层”,这意味着数据中的每个特征都连接到每个层。您的数据元素中还有 2000 个特征。

因此,您得到的数组有 2000 个元素,每个要素一个,每个具有 32 个权重,每个隐藏层一个,因此您得到的形状。

从keras docs我们可以看到例子:

model = Sequential()
model.add(Dense(32, input_shape=(16,)))
# now the model will take as input arrays of shape (*, 16)
# and output arrays of shape (*, 32)

# after the first layer, you don't need to specify
# the size of the input anymore:
model.add(Dense(32))

在你的情况下,* 是 2000,所以你的输出权重应该是你得到的形状 (2000,32)。这似乎是 Keras 用于其输出的约定。无论哪种方式,您都可以将数据转换为其他形状,因为(N, M) 数组与(M, N) 数组具有相同数量的元素。

【讨论】:

这就是重点。权重不适用于特征。权重是为使用这些特征的神经元定义的。您所说的是,对于输入层,它给出了这个输出,而实际上它应该为隐藏层显示这个。每个隐藏层有 32 个单元,每个单元上都有 2000 个权重。所以理想情况下,它应该是每个神经元的 32 个元素的列表,每个元素是 2000 个数组,对应 2000 个特征。 "理想情况下应该是..." ...好吧,也许您是对的,它可能是 32x2000,但是请注意,无论哪种方式(32x2000 或 2000x32),即使它仍然拥有相同的信息有不同的形状。您甚至可以将其重塑为您的喜好之一。这肯定是开发人员决定使用的约定。 根据我之前的评论和一些文档进一步编辑了我的问题 当您说访问每一层的权重时,人们会想访问与该层的每个单元关联的权重是什么。这意味着从开发人员的角度来看,他想知道每个单元的权重是多少。因此,拥有 32 个 X2000 是有意义的,因为现在可以说每个单元我有 2000 个权重。 @Baktaawar 我同意你的观点,知道每个隐藏单元的权重很重要,特别是当你想更深入地了解你的模型和问题时(因为那些权重更大的单元给出了一些主成分的概念你的特点)。如果您想获得这种洞察力,您将必须转换数据并对每层的权重进行分组,所以是的,获取该数据并不简单。

以上是关于了解每一层的 Keras 权重矩阵的主要内容,如果未能解决你的问题,请参考以下文章

如何获得每一层的权重形状?

相同的权重,实现但不同的结果 n Keras 和 Pytorch

Keras:如何在损失函数中使用层的权重?

在不使用 Keras API 的情况下,提取 Keras 层的权重对于进行前向传递有啥意义

如何获得每一层的重量

如何在每一层和每个时期获得权重然后保存在文件中