当前位置:   article > 正文

Python深度学习11——Keras实现共享层模型(多输入多输出)_keras共享权重

keras共享权重

 参考书目:陈允杰.TensorFlow与Keras——Python深度学习应用实战.北京:中国水利水电出版社,2021

本系列基本不讲数学原理,只从代码角度去让读者们利用最简洁的Python代码实现深度学习方法。


Keras框架虽然很简单,但是封装得太好了,自定义的自由度不够高,其搭建神经网络像搭建积木一样容易,却难以更改自己想要的积木的形状和位置。好在其神经网络层可以当成函数调用,这就保证了Keras还是具有一定的自定义能力,可以面向对象编程,下面进行一定的神经网络中间层的张量形状的获取,还有怎么实现共享模型,做到多输入和输出。


取得神经网络层的信息

定义好模型后,我们可以显示神经网络每层的名称和输出张量。如果训练完了还可以显示神经网络的权重。

先导入包

  1. from keras.models import Sequential
  2. from keras.layers import Dense
  3. from keras.layers import Flatten
  4. from keras.layers import Conv2D
  5. from keras.layers import MaxPooling2D
  6. from keras.layers import Dropout

定义模型

  1. # 定义模型
  2. model = Sequential()
  3. model.add(Conv2D(16, kernel_size=(5, 5), padding="same",input_shape=(28, 28, 1), activation="relu"))
  4. model.add(MaxPooling2D(pool_size=(2, 2)))
  5. model.add(Conv2D(32, kernel_size=(5, 5), padding="same",activation="relu"))
  6. model.add(MaxPooling2D(pool_size=(2, 2)))
  7. model.add(Dropout(0.5))
  8. model.add(Flatten())
  9. model.add(Dense(128, activation="relu"))
  10. model.add(Dropout(0.5))
  11. model.add(Dense(10, activation="softmax"))
  12. model.summary() # 显示模型摘要信息

 查看有多少层

  1. # 显示各神经层
  2. print("神经层数: ", len(model.layers))
  3. for i in range(len(model.layers)):
  4. print(i, model.layers[i].name)

 

  1. print("每一层的输入张量 ")
  2. for i in range(len(model.layers)):
  3. print(i, model.layers[i].input)

 

  1. print("每一层的输出张量: ")
  2. for i in range(len(model.layers)):
  3. print(i, model.layers[i].output)

  1. #显示各层的权重形状
  2. for i in range(len(model.layers)):
  3. print(i, model.layers[i].name, ":")
  4. weights = model.layers[i].get_weights()
  5. for j in range(len(weights)):
  6. print("==>", j, weights[j].shape)

可以读取的模型,查看其训练的权重

  1. model = Sequential()
  2. model = load_model("imdb_gru.h5")
  3. model.summary() # 显示模型摘要信息
  4. # 编译模型
  5. model.compile(loss="binary_crossentropy", optimizer="rmsprop", metrics=["accuracy"])
  6. # 显示GRU层的权重形状
  7. print(2, model.layers[2].name, ":")
  8. weights = model.layers[2].get_weights()
  9. for i in range(len(weights)):
  10. print("==>", i,weights[i].shape)

 

  1. for i in range(len(model.layers)):
  2. print(i, model.layers[i].name)
  3. print(i, model.layers[i].input)
  4. print(i, model.layers[i].output)
  5. print('\n')


使用Functional API进行搭建

以前Kears搭建模型都是上面那种,类似搭积木,下面使用函数的形式去搭建。

搭建这样一个网络

  1. # 定义模型
  2. mnist_input = Input(shape=(28, 28, 1),
  3. name="input")
  4. conv1 = Conv2D(16, kernel_size=(5, 5), padding="same",
  5. activation="relu", name="conv1")(mnist_input)
  6. pool1 = MaxPooling2D(pool_size=(2, 2),
  7. name="pool1")(conv1)
  8. conv2 = Conv2D(32, kernel_size=(5, 5), padding="same",
  9. activation="relu", name="conv2")(pool1)
  10. pool2 = MaxPooling2D(pool_size=(2, 2),
  11. name="pool2")(conv2)
  12. drop1 = Dropout(0.5, name="drop1")(pool2)
  13. flat = Flatten(name="flat")(drop1)
  14. hidden1 = Dense(128, activation="relu", name="hidden1")(flat)
  15. drop2 = Dropout(0.5, name="drop2")(hidden1)
  16. output = Dense(10, activation="softmax",
  17. name="output")(drop2)
  18. model = Model(inputs=mnist_input, outputs=output)
  19. model.summary() # 显示模型摘要信息

或者搭建这样一个LSTM网络

  1. # 定义模型
  2. imdb_input = Input(shape=(100,), dtype="int32",
  3. name="imdb_input")
  4. embed = Embedding(top_words, 32, input_length=max_words,
  5. name="embed")(imdb_input)
  6. drop1 = Dropout(0.25, name="drop1")(embed)
  7. lstm = LSTM(32, name="lstm")(drop1)
  8. drop2 = Dropout(0.25, name="drop2")(lstm)
  9. output = Dense(1, activation="sigmoid",
  10. name="output")(drop2)
  11. model = Model(inputs=imdb_input, outputs=output)
  12. model.summary() #显示模型摘要信息

共享层模型

前面的模型都是序列模型,即一层一层的搭建,但是有的网络可以多层一起搭建,例如下面这个模型,然后代码如下:

  1. from keras.models import Model
  2. from keras.layers import Input, Dense, Flatten, Conv2D, MaxPooling2D
  3. from keras.layers.merge import concatenate
  4. #定义模型
  5. shared_input = Input(shape=(64, 64, 1))
  6. # 第1个共享输入层的卷积和池化层
  7. conv1 = Conv2D(32, kernel_size=3, activation="relu")(shared_input)
  8. pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
  9. flat1 = Flatten()(pool1)
  10. # 第2个共享输入层的卷积和池化层
  11. conv2 = Conv2D(16, kernel_size=5, activation="relu")(shared_input)
  12. pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
  13. flat2 = Flatten()(pool2)
  14. #合并 2 个共享输入层的卷积和池化层
  15. merge = concatenate([flat1, flat2])
  16. hidden1 = Dense(10, activation="relu")(merge)
  17. output = Dense(1, activation="sigmoid")(hidden1)
  18. model = Model(inputs=shared_input, outputs=output)
  19. model.summary() # 显示模型摘要信息
  20. from keras.utils import plot_model
  21. plot_model(model, to_file="Ch16_4_1.png", show_shapes=True)

也可以不对称,两边随便弄几层,例如这样的

  1. from keras.models import Model
  2. from keras.layers import Input, Dense, LSTM
  3. from keras.layers.merge import concatenate
  4. #定义模型
  5. model_input = Input(shape=(100, 1))
  6. lstm = LSTM(32)(model_input)
  7. # 第 1 个共享特征提取层的解释层
  8. extract1 = Dense(16, activation="relu")(lstm)
  9. # 第 2 个共享特征提取层的解释层
  10. dense1 = Dense(16, activation="relu")(lstm)
  11. dense2 = Dense(32, activation="relu")(dense1)
  12. extract2 = Dense(16, activation='relu')(dense2)
  13. # 合并 2 个共享特征提取层的解释层
  14. merge = concatenate([extract1, extract2])
  15. output = Dense(1, activation="sigmoid")(merge)
  16. model = Model(inputs=model_input, outputs=output)
  17. model.summary() #显示模型摘要信息


多输入和输出模型

更加复杂的模型,有多对输入数据,例如图片有彩色和灰白,销售量有季节、温度、折扣、成本等很多因素影响。这就涉及到需要多输入和输出了。下面构建一个对彩色和灰白图片一起输入的模型:

多输入模型为

  1. from keras.models import Model
  2. from keras.layers import Input, Dense, Flatten, Conv2D, MaxPooling2D
  3. from keras.layers.merge import concatenate
  4. # 定义模型
  5. # 第 1 个灰度图片输入
  6. input1 = Input(shape=(28, 28, 1))
  7. conv11 = Conv2D(16, (3,3), activation="relu")(input1)
  8. pool11 = MaxPooling2D(pool_size=(2,2))(conv11)
  9. conv12 = Conv2D(32, (3,3), activation="relu")(pool11)
  10. pool12 = MaxPooling2D(pool_size=(2,2))(conv12)
  11. flat1 = Flatten()(pool12)
  12. # 第 2 个彩色图片输入
  13. input2 = Input(shape=(28, 28, 3))
  14. conv21 = Conv2D(16, (3,3), activation="relu")(input2)
  15. pool21 = MaxPooling2D(pool_size=(2,2))(conv21)
  16. conv22 = Conv2D(32, (3,3), activation="relu")(pool21)
  17. pool22 = MaxPooling2D(pool_size=(2,2))(conv22)
  18. flat2 = Flatten()(pool22)
  19. # 合并 2 个输入
  20. merge = concatenate([flat1, flat2])
  21. dense1 = Dense(512, activation="relu")(merge)
  22. dense2 = Dense(128, activation="relu")(dense1)
  23. dense3 = Dense(32, activation="relu")(dense2)
  24. output = Dense(10, activation="softmax")(dense3)
  25. # 定义多输入模型
  26. model = Model(inputs=[input1, input2], outputs=output)
  27. model.summary() # 显示模型摘要信息

 多输出模型为:

  1. from keras.models import Model
  2. from keras.layers import Dense, Input
  3. # 定义模型
  4. model_input = Input(shape = (784,))
  5. dense1 = Dense(512, activation="relu")(model_input)
  6. dense2 = Dense(128, activation="relu")(dense1)
  7. dense3 = Dense(32, activation ="relu")(dense2)
  8. # 第 1 个分类输出
  9. output = Dense(10, activation="softmax")(dense3)
  10. # 第 2 个自编码器输出
  11. up_dense1 = Dense(128, activation="relu")(dense3)
  12. up_dense2 = Dense(512, activation="relu")(up_dense1)
  13. decoded_outputs = Dense(784)(up_dense2)
  14. # 定义多输出模型
  15. model = Model(model_input, [output, decoded_outputs])
  16. model.summary() # 显示模型摘要信息

 mnist案例

使用手写数字数据集做上面两个模型的案例。

多输入

由于手写数字集没有彩色,那就改为两个黑白输入(这个案例里面这样做对精度没啥提升作用....只是演示)

  1. from keras.models import Model
  2. from keras.layers import Input, Dense, Flatten, Conv2D, MaxPooling2D
  3. from keras.layers.merge import concatenate
  4. from keras.datasets import mnist
  5. from tensorflow.keras.utils import to_categorical
  6. # 定义模型
  7. # 第 1 个灰度图片输入
  8. input1 = Input(shape=(28, 28, 1))
  9. conv11 = Conv2D(16, (3,3), activation="relu")(input1)
  10. pool11 = MaxPooling2D(pool_size=(2,2))(conv11)
  11. conv12 = Conv2D(32, (3,3), activation="relu")(pool11)
  12. pool12 = MaxPooling2D(pool_size=(2,2))(conv12)
  13. flat1 = Flatten()(pool12)
  14. # 第 2 个彩色图片输入
  15. input2 = Input(shape=(28, 28, 1))
  16. conv21 = Conv2D(16, (3,3), activation="relu")(input2)
  17. pool21 = MaxPooling2D(pool_size=(2,2))(conv21)
  18. conv22 = Conv2D(32, (3,3), activation="relu")(pool21)
  19. pool22 = MaxPooling2D(pool_size=(2,2))(conv22)
  20. flat2 = Flatten()(pool22)
  21. # 合并 2 个输入
  22. merge = concatenate([flat1, flat2])
  23. dense1 = Dense(512, activation="relu")(merge)
  24. dense2 = Dense(128, activation="relu")(dense1)
  25. dense3 = Dense(32, activation="relu")(dense2)
  26. output = Dense(10, activation="softmax")(dense3)
  27. # 定义多输入模型
  28. model = Model(inputs=[input1, input2], outputs=output)
  29. model.summary() # 显示模型摘要信息

  1. import numpy as np
  2. # 指定乱数种子
  3. seed = 7
  4. np.random.seed(seed)
  5. # 载入数据集
  6. (X_train, Y_train), (X_test, Y_test) = mnist.load_data()
  7. # 将图片转换成 4D 张量
  8. X_train = X_train.reshape(X_train.shape[0], 28, 28, 1).astype("float32")
  9. X_test = X_test.reshape(X_test.shape[0], 28, 28, 1).astype("float32")
  10. # 因为是固定范围, 所以执行正规化, 从 0-255 至 0-1
  11. X_train = X_train / 255
  12. X_test = X_test / 255
  13. # One-hot编码
  14. Y_train = to_categorical(Y_train)
  15. Y_test = to_categorical(Y_test)
  16. #编译模型
  17. model.compile(loss="categorical_crossentropy", optimizer="adam",metrics=["accuracy"])
  18. # 训练模型
  19. history = model.fit([X_train,X_train], Y_train,validation_split=0.2,
  20. epochs=10, batch_size=128, verbose=2)
  21. model.evaluate([X_test,X_test],Y_test)

 

多输出

  1. from keras.models import Sequential
  2. from keras.models import load_model
  3. # 建立Keras的Sequential模型
  4. model = Sequential()
  5. model = load_model("mnist.h5")
  6. model.summary() # 显示模型摘要信息
  7. # 编译模型
  8. model.compile(loss="categorical_crossentropy", optimizer="adam",metrics=["accuracy"])
  9. # 使用 Model 建立 前4层的 Conv2D 和 MaxPooling 层
  10. # 此模型是 1 个输入, 和 4 个输出
  11. layer_outputs = [layer.output for layer in model.layers[:4]]
  12. model_test = Model(inputs=model.input, outputs=layer_outputs)
  13. outputs = model_test.predict(X_train[1].reshape(1,28,28,1))
  14. # 取得第1个 Conv2D 的输出
  15. output = outputs[0]
  16. output.shape

  1. import matplotlib.pyplot as plt
  2. #绘出第1个 Conv2D 层的输出
  3. plt.figure(figsize=(10,8))
  4. for i in range(0,16):
  5. plt.subplot(4,4,i+1)
  6. plt.imshow(output[0,:,:,i], cmap="gray")
  7. plt.axis("off")

 

  1. # 取得第1个 MaxPooling 的输出
  2. output = outputs[1]
  3. # 绘出第1个 MaxPooling 层的输出
  4. plt.figure(figsize=(10,8))
  5. for i in range(0,16):
  6. plt.subplot(4,4,i+1)
  7. plt.imshow(output[0,:,:,i], cmap="gray")
  8. plt.axis("off")

 

  1. # 取得第2个 Conv2D 的输出
  2. output = outputs[2]
  3. # 绘出第2个 Conv2D 层的输出
  4. plt.figure(figsize=(10,8))
  5. for i in range(0,32):
  6. plt.subplot(6,6,i+1)
  7. plt.imshow(output[0,:,:,i], cmap="gray")
  8. plt.axis("off")

 

  1. # 取得第2个 MaxPooling 的输出
  2. output = outputs[3]
  3. # 绘出第2个 MaxPooling 层的输出
  4. plt.figure(figsize=(10,8))
  5. for i in range(0,32):
  6. plt.subplot(6,6,i+1)
  7. plt.imshow(output[0,:,:,i], cmap="gray")
  8. plt.axis("off")

 这个多输出模型是将每一步的中间层都输出了,可以查看模型学到了什么。算是模型中间层的可视化

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/978616
推荐阅读
相关标签
  

闽ICP备14008679号