keras技巧——如何获取某一个网络层的输出

前言:keras默认提供了如何获取某一个层的某一个节点的输出,但是没有提供如何获取某一个层的输出的接口,所以有时候我们需要获取某一个层的输出,则需要自己编写代码,但是鉴于keras高层封装的特性,编写起来实际上很简单,本文提供两种常见的方法来实现,基于上一篇文章的模型和代码: keras自定义回调函数查看训练的loss和accuracy

一、模型加载以及各个层的信息查看

从前面的定义可知,参见上一篇文章,一共定义了8个网络层,定义如下:

 
  1. model.add(Convolution2D(filters=6, kernel_size=(5, 5), padding='valid', input_shape=(img_rows, img_cols, 1), activation='tanh'))

  2. model.add(MaxPooling2D(pool_size=(2, 2)))

  3. model.add(Convolution2D(filters=16, kernel_size=(5, 5), padding='valid', activation='tanh'))

  4. model.add(MaxPooling2D(pool_size=(2, 2)))

  5. model.add(Flatten())

  6. model.add(Dense(120, activation='tanh'))

  7. model.add(Dense(84, activation='tanh'))

  8. model.add(Dense(n_classes, activation='softmax'))

这里每一个层都没有起名字,实际上最好给每一个层取一个名字,所以这里就使用索引来访问层,如下:

 
  1. for index in range(8):

  2. layer=model.get_layer(index=index)

  3. # layer=model.layers[index] # 这样获取每一个层也是一样的

  4. print(model)

  5.  
  6. '''运行结果如下:

  7. <keras.engine.sequential.Sequential object at 0x0000012A4F232E10>

  8. <keras.engine.sequential.Sequential object at 0x0000012A4F232E10>

  9. <keras.engine.sequential.Sequential object at 0x0000012A4F232E10>

  10. <keras.engine.sequential.Sequential object at 0x0000012A4F232E10>

  11. <keras.engine.sequential.Sequential object at 0x0000012A4F232E10>

  12. <keras.engine.sequential.Sequential object at 0x0000012A4F232E10>

  13. <keras.engine.sequential.Sequential object at 0x0000012A4F232E10>

  14. <keras.engine.sequential.Sequential object at 0x0000012A4F232E10>

  15. '''

当然由于 model.laters是一个列表,所以可以一次性打印出所有的层信息,即

print(model.layers)  # 打印出所有的层

二、模型的加载

准备测试数据

 
  1. # 训练参数

  2. learning_rate = 0.001

  3. epochs = 10

  4. batch_size = 128

  5. n_classes = 10

  6.  
  7. # 定义图像维度reshape

  8. img_rows, img_cols = 28, 28

  9.  
  10.  
  11. # 加载keras中的mnist数据集 分为60,000个训练集,10,000个测试集

  12. (x_train, y_train), (x_test, y_test) = mnist.load_data()

  13.  
  14. # 将图片转化为(samples,width,height,channels)的格式

  15. x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)

  16. x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)

  17.  
  18. # 将X_train, X_test的数据格式转为float32

  19. x_train = x_train.astype('float32')

  20. x_test = x_test.astype('float32')

  21. # 将X_train, X_test归一化0-1

  22. x_train /= 255

  23. x_test /= 255

  24.  
  25. # 输出0-9转换为ont-hot形式

  26. y_train = np_utils.to_categorical(y_train, n_classes)

  27. y_test = np_utils.to_categorical(y_test, n_classes)

模型的加载

model=keras.models.load_model('./models/lenet5_weight.h5')

注意事项:

keras的每一个层有一个input和output属性,但是它是只针对单节点的层而言的哦,否则就不需要我们再自己编写输出函数了,

如果一个层具有单个节点 (i.e. 如果它不是共享层), 你可以得到它的输入张量、输出张量、输入尺寸和输出尺寸:

  • layer.input
  • layer.output
  • layer.input_shape
  • layer.output_shape

如果层有多个节点 (参见: 层节点和共享层的概念), 您可以使用以下函数:

  • layer.get_input_at(node_index)
  • layer.get_output_at(node_index)
  • layer.get_input_shape_at(node_index)
  • layer.get_output_shape_at(node_index)

三、获取某一个层的输出的方法定义

3.1 第一种实现方法

 
  1. def get_output_function(model,output_layer_index):

  2. '''

  3. model: 要保存的模型

  4. output_layer_index:要获取的那一个层的索引

  5. '''

  6. vector_funcrion=K.function([model.layers[0].input],[model.layers[output_layer_index].output])

  7. def inner(input_data):

  8. vector=vector_funcrion([input_data])[0]

  9. return vector

  10.  
  11. return inner

  12.  
  13. # 现在仅仅测试一张图片

  14. #选择一张图片,选择第一张

  15. x= np.expand_dims(x_test[1],axis=0) #[1,28,28,1] 的形状

  16.  
  17. get_feature=get_output_function(model,6) # 该函数的返回值依然是一个函数哦,获取第6层输出

  18.  
  19. feature=get_feature(x) # 相当于调用 定义在里面的inner函数

  20. print(feature)

  21. '''运行结果为

  22. [[-0.99986297 -0.9988328 -0.9273474 0.9101525 -0.9054705 -0.95798373

  23. 0.9911243 0.78576803 0.99676156 0.39356467 -0.9724135 -0.74534595

  24. 0.8527011 -0.9968267 -0.9420816 -0.32765102 -0.41667578 0.99942905

  25. 0.92333794 0.7565034 -0.38416263 -0.994241 0.3781617 0.9621943

  26. 0.9443946 0.9671554 -0.01000021 -0.9984282 -0.96650964 -0.9925837

  27. -0.48193568 -0.9749565 -0.79769516 0.9651831 0.9678705 -0.9444472

  28. 0.9405674 0.97538495 -0.12366439 -0.9973782 0.05803521 0.9159217

  29. -0.9627071 0.99898154 0.99429387 -0.985909 0.5787794 -0.9789403

  30. -0.94316894 0.9999644 0.9156823 0.46314353 -0.01582102 0.98359734

  31. 0.5586145 -0.97360635 0.99058044 0.9995654 -0.9800733 0.99942625

  32. 0.8786553 -0.9992093 0.99916387 -0.5141877 0.99970615 0.28427476

  33. 0.86589384 0.7649907 -0.9986046 0.9999706 -0.9892468 0.99854743

  34. -0.86872625 -0.9997323 0.98981035 -0.87805724 -0.9999373 -0.7842255

  35. -0.97456616 -0.97237325 -0.729563 0.98718935 0.9992022 -0.5294769 ]]

  36. '''

但是上面的实现方法似乎不是很简单,还有更加简单的方法,思想来源与keras中,可以将整个模型model也当成是层layer来处理,实现如下面。

3.2 第二种实现方法

 
  1. import keras

  2. import numpy as np

  3. from keras.datasets import mnist

  4. from keras.models import Model

  5.  
  6. model=keras.models.load_model('./models/lenet5_weight.h5')

  7.  
  8.  
  9. #选择一张图片,选择第一张

  10. x= np.expand_dims(x_test[1],axis=0) #[1,28,28,1] 的形状

  11.  
  12. # 将模型作为一个层,输出第7层的输出

  13. layer_model = Model(inputs=model.input, outputs=model.layers[6].output)

  14.  
  15. feature=layer_model.predict(x)

  16.  
  17. print(feature)

  18. '''运行结果为:

  19. [[-0.99986297 -0.9988328 -0.9273474 0.9101525 -0.9054705 -0.95798373

  20. 0.9911243 0.78576803 0.99676156 0.39356467 -0.9724135 -0.74534595

  21. 0.8527011 -0.9968267 -0.9420816 -0.32765102 -0.41667578 0.99942905

  22. 0.92333794 0.7565034 -0.38416263 -0.994241 0.3781617 0.9621943

  23. 0.9443946 0.9671554 -0.01000021 -0.9984282 -0.96650964 -0.9925837

  24. -0.48193568 -0.9749565 -0.79769516 0.9651831 0.9678705 -0.9444472

  25. 0.9405674 0.97538495 -0.12366439 -0.9973782 0.05803521 0.9159217

  26. -0.9627071 0.99898154 0.99429387 -0.985909 0.5787794 -0.9789403

  27. -0.94316894 0.9999644 0.9156823 0.46314353 -0.01582102 0.98359734

  28. 0.5586145 -0.97360635 0.99058044 0.9995654 -0.9800733 0.99942625

  29. 0.8786553 -0.9992093 0.99916387 -0.5141877 0.99970615 0.28427476

  30. 0.86589384 0.7649907 -0.9986046 0.9999706 -0.9892468 0.99854743

  31. -0.86872625 -0.9997323 0.98981035 -0.87805724 -0.9999373 -0.7842255

  32. -0.97456616 -0.97237325 -0.729563 0.98718935 0.9992022 -0.5294769 ]]

  33. '''

可见和上面的结果是一样的,

总结:由于keras的层与模型之间实际上的转化关系,所以提供了非常灵活的输出方法,推荐使用第二种方法获得某一个层的输出。总结为以下几个主要的步骤(四步走)

 
  1. import keras

  2. import numpy as np

  3. from keras.datasets import mnist

  4. from keras.models import Model

  5.  
  6. # 第一步:准备输入数据

  7. x= np.expand_dims(x_test[1],axis=0) #[1,28,28,1] 的形状

  8.  
  9. # 第二步:加载已经训练的模型

  10. model=keras.models.load_model('./models/lenet5_weight.h5')

  11.  
  12. # 第三步:将模型作为一个层,输出第7层的输出

  13. layer_model = Model(inputs=model.input, outputs=model.layers[6].output)

  14.  
  15. # 第四步:调用新建的“曾模型”的predict方法,得到模型的输出

  16. feature=layer_model.predict(x)

  17.  
  18. print(feature)

======================================================================

keras输出中间层结果的2种方法

哈哈进步 2017-09-14 17:20:40  38136  收藏 21

分类专栏: 机器学习 其他随笔

版权

1.使用函数模型API,新建一个model,将输入和输出定义为原来的model的输入和想要的那一层的输出,然后重新进行predict.

 

 
  1. #coding=utf-8

  2. import seaborn as sbn

  3. import pylab as plt

  4. import theano

  5. from keras.models import Sequential

  6. from keras.layers import Dense,Activation

  7.  
  8.  
  9. from keras.models import Model

  10.  
  11. model = Sequential()

  12. model.add(Dense(32, activation='relu', input_dim=100))

  13. model.add(Dense(16, activation='relu',name="Dense_1"))

  14. model.add(Dense(1, activation='sigmoid',name="Dense_2"))

  15. model.compile(optimizer='rmsprop',

  16. loss='binary_crossentropy',

  17. metrics=['accuracy'])

  18.  
  19. # Generate dummy data

  20. import numpy as np

  21. #假设训练和测试使用同一组数据

  22. data = np.random.random((1000, 100))

  23. labels = np.random.randint(2, size=(1000, 1))

  24.  
  25. # Train the model, iterating on the data in batches of 32 samples

  26. model.fit(data, labels, epochs=10, batch_size=32)

  27. #已有的model在load权重过后

  28. #取某一层的输出为输出新建为model,采用函数模型

  29. dense1_layer_model = Model(inputs=model.input,

  30. outputs=model.get_layer('Dense_1').output)

  31. #以这个model的预测值作为输出

  32. dense1_output = dense1_layer_model.predict(data)

  33.  
  34. print dense1_output.shape

  35. print dense1_output[0]

  • 6
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值