如何横向合并分类模型
how to merge classification models horizontally
我已经训练了许多模型,每个模型都回答一个简单的 yes/no 问题。伪代码:
model_dog = keras.load('is_dog')
model_cat = keras.load('is_cat')
model_rat = keras.load('is_rat')
image = load_photo_as_numpy_array('photo.jpg')
multi_class = [ m.predict(image) for m in (model_dog,model_cat,model_rat) ]
这很好用,但是它 a> 很慢,因为推理是按顺序而不是并行进行的(我有数百个这样的模型,而不仅仅是 3 个),而且 b> 使用起来比我有复杂得多一个进行多分类的模型。
我想要的是:
model = keras.concat_horizontal([ model_dog, model_cat, model_rat ])
model.save('combined_model')
那么每当我想使用组合模型时,就这么简单:
model = keras.load('combined_model')
multi_class = m.predict(image)
这样,我可以通过训练一个简单的模型(例如识别鱼)向组合模型添加新的分类。
正如我在评论中所建议的,您可以将多个模型合并到一个新模型中并使用这个新模型进行预测。
首先,我编写了一个合并模型的函数和return一个新的组合模型。这就是你想要的:
def concat_horizontal(models, input_shape):
models_count = len(models)
hidden = []
input = tf.keras.layers.Input(shape=input_shape)
for i in range(models_count):
hidden.append(models[i](input))
output = tf.keras.layers.concatenate(hidden)
model = tf.keras.Model(inputs=input, outputs=output)
return model
我们来看一个例子。假设我们想要像这样合并两个顺序模型:
def model_1():
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28,28,1)),
tf.keras.layers.Dense(150, activation='relu'),
tf.keras.layers.Dense(200, activation='relu'),
tf.keras.layers.Dense(150, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')], name="model1")
model.compile(optimizer=tf.keras.optimizers.Adam(), loss=tf.keras.losses.sparse_categorical_crossentropy, metrics=['accuracy'])
return model
def model_2():
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28,28,1)),
tf.keras.layers.Dense(150, activation='relu'),
tf.keras.layers.Dense(150, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')], name="model2")
model.compile(optimizer=tf.keras.optimizers.Adam(), loss=tf.keras.losses.sparse_categorical_crossentropy, metrics=['accuracy'])
return model
model1 = model_1()
model2 = model_2()
让我们使用 MNIST 作为我们两个模型的训练数据集:
import tensorflow_datasets as tfds
ds_1 = tfds.load('mnist', split='train', as_supervised=True)
ds_2 = tfds.load('mnist', split='test', as_supervised=True)
def map_fn(image, label):
image = image / 255
return image, label
ds_1 = ds_1.map(map_fn).shuffle(1024).batch(32)
ds_2 = ds_2.map(map_fn).shuffle(1024).batch(32)
现在,我们可以训练模型,保存它们,然后像这样加载它们:
model1.fit(ds_1, epochs=2, validation_data=ds_1)
model2.fit(ds_2, epochs=2, validation_data=ds_2)
model1.save('model1.h5')
model2.save('model2.h5')
model3 = tf.keras.models.load_model('model1.h5')
model4 = tf.keras.models.load_model('model2.h5')
所以我们有 2 个独立的模型 (model3
,model4
) 并且想将它们合并为一个新模型。将它们沿输入形状(在本例中为 MNIST 数据形状)传递给我们上面编写的函数:
new_model = concat_horizontal([model3,model4],(28,28,1))
现在,如果我们绘制这个新模型:
tf.keras.utils.plot_model(new_model)
是时候获取模型预测了:
sample = ds_1.unbatch().take(1)
for i,j in sample:
img = i
lbl = j
img = tf.expand_dims(img,axis=0)
pred = new_model.predict(img)
pred = np.reshape(pred,(2,10))
results = np.argmax(pred,axis=1)
print(results)
import matplotlib.pyplot as plt
plt.imshow(np.array(img).squeeze())
plt.show
在我的例子中,我得到的两个预测都被分类为 4:
输出:
我已经训练了许多模型,每个模型都回答一个简单的 yes/no 问题。伪代码:
model_dog = keras.load('is_dog')
model_cat = keras.load('is_cat')
model_rat = keras.load('is_rat')
image = load_photo_as_numpy_array('photo.jpg')
multi_class = [ m.predict(image) for m in (model_dog,model_cat,model_rat) ]
这很好用,但是它 a> 很慢,因为推理是按顺序而不是并行进行的(我有数百个这样的模型,而不仅仅是 3 个),而且 b> 使用起来比我有复杂得多一个进行多分类的模型。
我想要的是:
model = keras.concat_horizontal([ model_dog, model_cat, model_rat ])
model.save('combined_model')
那么每当我想使用组合模型时,就这么简单:
model = keras.load('combined_model')
multi_class = m.predict(image)
这样,我可以通过训练一个简单的模型(例如识别鱼)向组合模型添加新的分类。
正如我在评论中所建议的,您可以将多个模型合并到一个新模型中并使用这个新模型进行预测。
首先,我编写了一个合并模型的函数和return一个新的组合模型。这就是你想要的:
def concat_horizontal(models, input_shape):
models_count = len(models)
hidden = []
input = tf.keras.layers.Input(shape=input_shape)
for i in range(models_count):
hidden.append(models[i](input))
output = tf.keras.layers.concatenate(hidden)
model = tf.keras.Model(inputs=input, outputs=output)
return model
我们来看一个例子。假设我们想要像这样合并两个顺序模型:
def model_1():
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28,28,1)),
tf.keras.layers.Dense(150, activation='relu'),
tf.keras.layers.Dense(200, activation='relu'),
tf.keras.layers.Dense(150, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')], name="model1")
model.compile(optimizer=tf.keras.optimizers.Adam(), loss=tf.keras.losses.sparse_categorical_crossentropy, metrics=['accuracy'])
return model
def model_2():
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28,28,1)),
tf.keras.layers.Dense(150, activation='relu'),
tf.keras.layers.Dense(150, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')], name="model2")
model.compile(optimizer=tf.keras.optimizers.Adam(), loss=tf.keras.losses.sparse_categorical_crossentropy, metrics=['accuracy'])
return model
model1 = model_1()
model2 = model_2()
让我们使用 MNIST 作为我们两个模型的训练数据集:
import tensorflow_datasets as tfds
ds_1 = tfds.load('mnist', split='train', as_supervised=True)
ds_2 = tfds.load('mnist', split='test', as_supervised=True)
def map_fn(image, label):
image = image / 255
return image, label
ds_1 = ds_1.map(map_fn).shuffle(1024).batch(32)
ds_2 = ds_2.map(map_fn).shuffle(1024).batch(32)
现在,我们可以训练模型,保存它们,然后像这样加载它们:
model1.fit(ds_1, epochs=2, validation_data=ds_1)
model2.fit(ds_2, epochs=2, validation_data=ds_2)
model1.save('model1.h5')
model2.save('model2.h5')
model3 = tf.keras.models.load_model('model1.h5')
model4 = tf.keras.models.load_model('model2.h5')
所以我们有 2 个独立的模型 (model3
,model4
) 并且想将它们合并为一个新模型。将它们沿输入形状(在本例中为 MNIST 数据形状)传递给我们上面编写的函数:
new_model = concat_horizontal([model3,model4],(28,28,1))
现在,如果我们绘制这个新模型:
tf.keras.utils.plot_model(new_model)
是时候获取模型预测了:
sample = ds_1.unbatch().take(1)
for i,j in sample:
img = i
lbl = j
img = tf.expand_dims(img,axis=0)
pred = new_model.predict(img)
pred = np.reshape(pred,(2,10))
results = np.argmax(pred,axis=1)
print(results)
import matplotlib.pyplot as plt
plt.imshow(np.array(img).squeeze())
plt.show
在我的例子中,我得到的两个预测都被分类为 4:
输出: