赞
踩
参考书目:陈允杰.TensorFlow与Keras——Python深度学习应用实战.北京:中国水利水电出版社,2021
本系列基本不讲数学原理,只从代码角度去让读者们利用最简洁的Python代码实现深度学习方法。
Keras框架虽然很简单,但是封装得太好了,自定义的自由度不够高,其搭建神经网络像搭建积木一样容易,却难以更改自己想要的积木的形状和位置。好在其神经网络层可以当成函数调用,这就保证了Keras还是具有一定的自定义能力,可以面向对象编程,下面进行一定的神经网络中间层的张量形状的获取,还有怎么实现共享模型,做到多输入和输出。
定义好模型后,我们可以显示神经网络每层的名称和输出张量。如果训练完了还可以显示神经网络的权重。
先导入包
- from keras.models import Sequential
- from keras.layers import Dense
- from keras.layers import Flatten
- from keras.layers import Conv2D
- from keras.layers import MaxPooling2D
- from keras.layers import Dropout
定义模型
- # 定义模型
- model = Sequential()
- model.add(Conv2D(16, kernel_size=(5, 5), padding="same",input_shape=(28, 28, 1), activation="relu"))
- model.add(MaxPooling2D(pool_size=(2, 2)))
- model.add(Conv2D(32, kernel_size=(5, 5), padding="same",activation="relu"))
- model.add(MaxPooling2D(pool_size=(2, 2)))
- model.add(Dropout(0.5))
- model.add(Flatten())
- model.add(Dense(128, activation="relu"))
- model.add(Dropout(0.5))
- model.add(Dense(10, activation="softmax"))
- model.summary() # 显示模型摘要信息
查看有多少层
- # 显示各神经层
- print("神经层数: ", len(model.layers))
- for i in range(len(model.layers)):
- print(i, model.layers[i].name)
- print("每一层的输入张量 ")
- for i in range(len(model.layers)):
- print(i, model.layers[i].input)
- print("每一层的输出张量: ")
- for i in range(len(model.layers)):
- print(i, model.layers[i].output)
- #显示各层的权重形状
- for i in range(len(model.layers)):
- print(i, model.layers[i].name, ":")
- weights = model.layers[i].get_weights()
- for j in range(len(weights)):
- print("==>", j, weights[j].shape)
可以读取的模型,查看其训练的权重
- model = Sequential()
- model = load_model("imdb_gru.h5")
- model.summary() # 显示模型摘要信息
- # 编译模型
- model.compile(loss="binary_crossentropy", optimizer="rmsprop", metrics=["accuracy"])
- # 显示GRU层的权重形状
- print(2, model.layers[2].name, ":")
- weights = model.layers[2].get_weights()
- for i in range(len(weights)):
- print("==>", i,weights[i].shape)
- for i in range(len(model.layers)):
- print(i, model.layers[i].name)
- print(i, model.layers[i].input)
- print(i, model.layers[i].output)
- print('\n')
以前Kears搭建模型都是上面那种,类似搭积木,下面使用函数的形式去搭建。
搭建这样一个网络
- # 定义模型
- mnist_input = Input(shape=(28, 28, 1),
- name="input")
- conv1 = Conv2D(16, kernel_size=(5, 5), padding="same",
- activation="relu", name="conv1")(mnist_input)
- pool1 = MaxPooling2D(pool_size=(2, 2),
- name="pool1")(conv1)
- conv2 = Conv2D(32, kernel_size=(5, 5), padding="same",
- activation="relu", name="conv2")(pool1)
- pool2 = MaxPooling2D(pool_size=(2, 2),
- name="pool2")(conv2)
- drop1 = Dropout(0.5, name="drop1")(pool2)
- flat = Flatten(name="flat")(drop1)
- hidden1 = Dense(128, activation="relu", name="hidden1")(flat)
- drop2 = Dropout(0.5, name="drop2")(hidden1)
- output = Dense(10, activation="softmax",
- name="output")(drop2)
- model = Model(inputs=mnist_input, outputs=output)
- model.summary() # 显示模型摘要信息
或者搭建这样一个LSTM网络
- # 定义模型
- imdb_input = Input(shape=(100,), dtype="int32",
- name="imdb_input")
- embed = Embedding(top_words, 32, input_length=max_words,
- name="embed")(imdb_input)
- drop1 = Dropout(0.25, name="drop1")(embed)
- lstm = LSTM(32, name="lstm")(drop1)
- drop2 = Dropout(0.25, name="drop2")(lstm)
- output = Dense(1, activation="sigmoid",
- name="output")(drop2)
- model = Model(inputs=imdb_input, outputs=output)
- model.summary() #显示模型摘要信息
前面的模型都是序列模型,即一层一层的搭建,但是有的网络可以多层一起搭建,例如下面这个模型,然后代码如下:
- from keras.models import Model
- from keras.layers import Input, Dense, Flatten, Conv2D, MaxPooling2D
- from keras.layers.merge import concatenate
-
- #定义模型
- shared_input = Input(shape=(64, 64, 1))
- # 第1个共享输入层的卷积和池化层
- conv1 = Conv2D(32, kernel_size=3, activation="relu")(shared_input)
- pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
- flat1 = Flatten()(pool1)
- # 第2个共享输入层的卷积和池化层
- conv2 = Conv2D(16, kernel_size=5, activation="relu")(shared_input)
- pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
- flat2 = Flatten()(pool2)
- #合并 2 个共享输入层的卷积和池化层
- merge = concatenate([flat1, flat2])
- hidden1 = Dense(10, activation="relu")(merge)
- output = Dense(1, activation="sigmoid")(hidden1)
- model = Model(inputs=shared_input, outputs=output)
- model.summary() # 显示模型摘要信息
- from keras.utils import plot_model
-
- plot_model(model, to_file="Ch16_4_1.png", show_shapes=True)
也可以不对称,两边随便弄几层,例如这样的
- from keras.models import Model
- from keras.layers import Input, Dense, LSTM
- from keras.layers.merge import concatenate
-
- #定义模型
- model_input = Input(shape=(100, 1))
- lstm = LSTM(32)(model_input)
- # 第 1 个共享特征提取层的解释层
- extract1 = Dense(16, activation="relu")(lstm)
- # 第 2 个共享特征提取层的解释层
- dense1 = Dense(16, activation="relu")(lstm)
- dense2 = Dense(32, activation="relu")(dense1)
- extract2 = Dense(16, activation='relu')(dense2)
- # 合并 2 个共享特征提取层的解释层
- merge = concatenate([extract1, extract2])
- output = Dense(1, activation="sigmoid")(merge)
- model = Model(inputs=model_input, outputs=output)
- model.summary() #显示模型摘要信息
更加复杂的模型,有多对输入数据,例如图片有彩色和灰白,销售量有季节、温度、折扣、成本等很多因素影响。这就涉及到需要多输入和输出了。下面构建一个对彩色和灰白图片一起输入的模型:
多输入模型为
- from keras.models import Model
- from keras.layers import Input, Dense, Flatten, Conv2D, MaxPooling2D
- from keras.layers.merge import concatenate
-
- # 定义模型
- # 第 1 个灰度图片输入
- input1 = Input(shape=(28, 28, 1))
- conv11 = Conv2D(16, (3,3), activation="relu")(input1)
- pool11 = MaxPooling2D(pool_size=(2,2))(conv11)
- conv12 = Conv2D(32, (3,3), activation="relu")(pool11)
- pool12 = MaxPooling2D(pool_size=(2,2))(conv12)
- flat1 = Flatten()(pool12)
- # 第 2 个彩色图片输入
- input2 = Input(shape=(28, 28, 3))
- conv21 = Conv2D(16, (3,3), activation="relu")(input2)
- pool21 = MaxPooling2D(pool_size=(2,2))(conv21)
- conv22 = Conv2D(32, (3,3), activation="relu")(pool21)
- pool22 = MaxPooling2D(pool_size=(2,2))(conv22)
- flat2 = Flatten()(pool22)
- # 合并 2 个输入
- merge = concatenate([flat1, flat2])
- dense1 = Dense(512, activation="relu")(merge)
- dense2 = Dense(128, activation="relu")(dense1)
- dense3 = Dense(32, activation="relu")(dense2)
- output = Dense(10, activation="softmax")(dense3)
- # 定义多输入模型
- model = Model(inputs=[input1, input2], outputs=output)
- model.summary() # 显示模型摘要信息
多输出模型为:
- from keras.models import Model
- from keras.layers import Dense, Input
-
- # 定义模型
- model_input = Input(shape = (784,))
- dense1 = Dense(512, activation="relu")(model_input)
- dense2 = Dense(128, activation="relu")(dense1)
- dense3 = Dense(32, activation ="relu")(dense2)
- # 第 1 个分类输出
- output = Dense(10, activation="softmax")(dense3)
- # 第 2 个自编码器输出
- up_dense1 = Dense(128, activation="relu")(dense3)
- up_dense2 = Dense(512, activation="relu")(up_dense1)
- decoded_outputs = Dense(784)(up_dense2)
- # 定义多输出模型
- model = Model(model_input, [output, decoded_outputs])
- model.summary() # 显示模型摘要信息
使用手写数字数据集做上面两个模型的案例。
多输入
由于手写数字集没有彩色,那就改为两个黑白输入(这个案例里面这样做对精度没啥提升作用....只是演示)
- from keras.models import Model
- from keras.layers import Input, Dense, Flatten, Conv2D, MaxPooling2D
- from keras.layers.merge import concatenate
- from keras.datasets import mnist
- from tensorflow.keras.utils import to_categorical
-
- # 定义模型
- # 第 1 个灰度图片输入
- input1 = Input(shape=(28, 28, 1))
- conv11 = Conv2D(16, (3,3), activation="relu")(input1)
- pool11 = MaxPooling2D(pool_size=(2,2))(conv11)
- conv12 = Conv2D(32, (3,3), activation="relu")(pool11)
- pool12 = MaxPooling2D(pool_size=(2,2))(conv12)
- flat1 = Flatten()(pool12)
- # 第 2 个彩色图片输入
- input2 = Input(shape=(28, 28, 1))
- conv21 = Conv2D(16, (3,3), activation="relu")(input2)
- pool21 = MaxPooling2D(pool_size=(2,2))(conv21)
- conv22 = Conv2D(32, (3,3), activation="relu")(pool21)
- pool22 = MaxPooling2D(pool_size=(2,2))(conv22)
- flat2 = Flatten()(pool22)
- # 合并 2 个输入
- merge = concatenate([flat1, flat2])
- dense1 = Dense(512, activation="relu")(merge)
- dense2 = Dense(128, activation="relu")(dense1)
- dense3 = Dense(32, activation="relu")(dense2)
- output = Dense(10, activation="softmax")(dense3)
- # 定义多输入模型
- model = Model(inputs=[input1, input2], outputs=output)
- model.summary() # 显示模型摘要信息
- import numpy as np
- # 指定乱数种子
- seed = 7
- np.random.seed(seed)
- # 载入数据集
- (X_train, Y_train), (X_test, Y_test) = mnist.load_data()
- # 将图片转换成 4D 张量
- X_train = X_train.reshape(X_train.shape[0], 28, 28, 1).astype("float32")
- X_test = X_test.reshape(X_test.shape[0], 28, 28, 1).astype("float32")
- # 因为是固定范围, 所以执行正规化, 从 0-255 至 0-1
- X_train = X_train / 255
- X_test = X_test / 255
- # One-hot编码
- Y_train = to_categorical(Y_train)
- Y_test = to_categorical(Y_test)
-
- #编译模型
- model.compile(loss="categorical_crossentropy", optimizer="adam",metrics=["accuracy"])
-
- # 训练模型
- history = model.fit([X_train,X_train], Y_train,validation_split=0.2,
- epochs=10, batch_size=128, verbose=2)
-
- model.evaluate([X_test,X_test],Y_test)
多输出
- from keras.models import Sequential
- from keras.models import load_model
- # 建立Keras的Sequential模型
- model = Sequential()
- model = load_model("mnist.h5")
- model.summary() # 显示模型摘要信息
- # 编译模型
- model.compile(loss="categorical_crossentropy", optimizer="adam",metrics=["accuracy"])
-
- # 使用 Model 建立 前4层的 Conv2D 和 MaxPooling 层
- # 此模型是 1 个输入, 和 4 个输出
- layer_outputs = [layer.output for layer in model.layers[:4]]
- model_test = Model(inputs=model.input, outputs=layer_outputs)
-
- outputs = model_test.predict(X_train[1].reshape(1,28,28,1))
- # 取得第1个 Conv2D 的输出
- output = outputs[0]
- output.shape
- import matplotlib.pyplot as plt
- #绘出第1个 Conv2D 层的输出
- plt.figure(figsize=(10,8))
- for i in range(0,16):
- plt.subplot(4,4,i+1)
- plt.imshow(output[0,:,:,i], cmap="gray")
- plt.axis("off")
- # 取得第1个 MaxPooling 的输出
- output = outputs[1]
- # 绘出第1个 MaxPooling 层的输出
- plt.figure(figsize=(10,8))
- for i in range(0,16):
- plt.subplot(4,4,i+1)
- plt.imshow(output[0,:,:,i], cmap="gray")
- plt.axis("off")
- # 取得第2个 Conv2D 的输出
- output = outputs[2]
- # 绘出第2个 Conv2D 层的输出
- plt.figure(figsize=(10,8))
- for i in range(0,32):
- plt.subplot(6,6,i+1)
- plt.imshow(output[0,:,:,i], cmap="gray")
- plt.axis("off")
- # 取得第2个 MaxPooling 的输出
- output = outputs[3]
- # 绘出第2个 MaxPooling 层的输出
- plt.figure(figsize=(10,8))
- for i in range(0,32):
- plt.subplot(6,6,i+1)
- plt.imshow(output[0,:,:,i], cmap="gray")
- plt.axis("off")
这个多输出模型是将每一步的中间层都输出了,可以查看模型学到了什么。算是模型中间层的可视化
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。