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

 参考书目:陈允杰.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')


使用Functional API进行搭建

以前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()   # 显示模型摘要信息

 mnist案例

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

多输入

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

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") 
    

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

  • 10
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
好的,以下是使用Keras构建情感分析模型的代码示例: 首先,需要导入需要的库: ```python import pandas as pd import numpy as np from keras.preprocessing.text import Tokenizer from keras.preprocessing.sequence import pad_sequences from keras.models import Sequential from keras.layers import Embedding, Conv1D, GlobalMaxPooling1D, Dense ``` 接着,读取数据集并进行预处理: ```python # 读取数据集 data = pd.read_csv('sentiment_analysis.csv') # 将文本转换为小写 texts = data['text'].apply(lambda x: x.lower()) # 将标签转换为数字:0表示负面情感,1表示正面情感 labels = np.array([0 if label == 'negative' else 1 for label in data['label']]) ``` 然后,进行单词向量化: ```python # 将文本转换为单词序列 tokenizer = Tokenizer(num_words=5000) tokenizer.fit_on_texts(texts) sequences = tokenizer.texts_to_sequences(texts) # 对单词序列进行填充,使其长度相同 padded_sequences = pad_sequences(sequences, maxlen=100) ``` 接下来,构建模型: ```python model = Sequential() # 添加嵌入层 model.add(Embedding(input_dim=5000, output_dim=100, input_length=100)) # 添加1D卷积层 model.add(Conv1D(filters=32, kernel_size=3, padding='same', activation='relu')) # 添加全局最大池化层 model.add(GlobalMaxPooling1D()) # 添加全连接层 model.add(Dense(units=64, activation='relu')) # 添加输出层 model.add(Dense(units=1, activation='sigmoid')) # 编译模型 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) ``` 最后,训练模型并进行评估: ```python # 划分训练集和测试集 indices = np.arange(padded_sequences.shape[0]) np.random.shuffle(indices) padded_sequences = padded_sequences[indices] labels = labels[indices] train_size = int(0.8 * padded_sequences.shape[0]) train_X, test_X = padded_sequences[:train_size], padded_sequences[train_size:] train_y, test_y = labels[:train_size], labels[train_size:] # 训练模型 model.fit(train_X, train_y, epochs=10, batch_size=64) # 评估模型 loss, accuracy = model.evaluate(test_X, test_y) print('Test accuracy:', accuracy) ``` 完整的代码示例如下: ```python import pandas as pd import numpy as np from keras.preprocessing.text import Tokenizer from keras.preprocessing.sequence import pad_sequences from keras.models import Sequential from keras.layers import Embedding, Conv1D, GlobalMaxPooling1D, Dense # 读取数据集 data = pd.read_csv('sentiment_analysis.csv') # 将文本转换为小写 texts = data['text'].apply(lambda x: x.lower()) # 将标签转换为数字:0表示负面情感,1表示正面情感 labels = np.array([0 if label == 'negative' else 1 for label in data['label']]) # 将文本转换为单词序列 tokenizer = Tokenizer(num_words=5000) tokenizer.fit_on_texts(texts) sequences = tokenizer.texts_to_sequences(texts) # 对单词序列进行填充,使其长度相同 padded_sequences = pad_sequences(sequences, maxlen=100) # 构建模型 model = Sequential() # 添加嵌入层 model.add(Embedding(input_dim=5000, output_dim=100, input_length=100)) # 添加1D卷积层 model.add(Conv1D(filters=32, kernel_size=3, padding='same', activation='relu')) # 添加全局最大池化层 model.add(GlobalMaxPooling1D()) # 添加全连接层 model.add(Dense(units=64, activation='relu')) # 添加输出层 model.add(Dense(units=1, activation='sigmoid')) # 编译模型 model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) # 划分训练集和测试集 indices = np.arange(padded_sequences.shape[0]) np.random.shuffle(indices) padded_sequences = padded_sequences[indices] labels = labels[indices] train_size = int(0.8 * padded_sequences.shape[0]) train_X, test_X = padded_sequences[:train_size], padded_sequences[train_size:] train_y, test_y = labels[:train_size], labels[train_size:] # 训练模型 model.fit(train_X, train_y, epochs=10, batch_size=64) # 评估模型 loss, accuracy = model.evaluate(test_X, test_y) print('Test accuracy:', accuracy) ```
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阡之尘埃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值