《deep learning for cv with python practical bundle》 第六章读书笔记

这一章主要讲的是:模型融合

模型融合的概念是:每一次迭代产生一个model,最终结果是对于这些model取平均值,因为每次迭代产生的模型对于特征提取的侧重点不同,因此平均的model的结果会有一些提升

主要涉及到两部分代码

1)5个epoch,产生5个model,并对于这5个model进行单个测试

2)对于这5个model进行融合,并且测试融合之后的效果

part1:train_models.py

# -*- coding:utf-8 -*- 
__author__ = 'xuy'
"""
在每次循环结束的时候保存模型
进行模型融合,每个模型epoch40次
一共融合5个模型,一共需要epoch200次
"""
import matplotlib
matplotlib.use("Agg")

from sklearn.preprocessing import LabelBinarizer
from sklearn.metrics import classification_report
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import SGD
from keras.datasets import cifar10
from pyimagesearch.nn.conv.minivggnet import MiniVGGNet
import matplotlib.pyplot as plt
import numpy as np
import argparse
import os

# Constrcut the argument parse and parse arguments.
ap = argparse.ArgumentParser()
ap.add_argument("-o", "--output", required=True, help="path to output figures directory")
ap.add_argument("-m", "--model", required=True, help="path to output models directory")
ap.add_argument("-n", "--num_models", type=int, default=5, help="# of models to train")
args = vars(ap.parse_args())

# Load the training and testing data, then scale it into the range [0, 1].
((trainX, trainY), (testX, testY)) = cifar10.load_data()
"""
将trainX 和testX进行归一化,方便后面利用交叉验证来计算我们的损失函数
"""
trainX = trainX.astype("float") / 255.0
testX = testX.astype("float") / 255.0
# Convert the labels from integers to vectors.
lb = LabelBinarizer()
trainY = lb.fit_transform(trainY)
testY  = lb.fit_transform(testY)

# Initialize the label names for the CIFAR-10 dataset,cifar-10的label
labelNames = ["airplane",
              "automobile",
              "bird",
              "cat",
              "deer",
              "dog",
              "frog",
              "horse",
              "ship",
              "truck"]

# Construct the image generator for data augmentation.
aug = ImageDataGenerator(rotation_range=10,             # Randomly rotated +/- 30 degrees; "typical[10, 30]"
                         width_shift_range=0.1,             # Horizontally shifted by a factor of 0.1; "typical[0.1, 0.2]"
                         height_shift_range=0.1,            # Vertically shifted by a factor of 0.1; "typical[0.1, 0.2]"
                         horizontal_flip=True,              # Randomly horizontally flipped, Unless flipping your image changes the class label,
                         fill_mode="nearest")               #You should always include horizontal flipping as well.

# Loop over the number of models to train.
for i in np.arange(0, args["num_models"]):
    # Initialize the optimizer and model.
    print("[INFO] training model {}/{}".format(i+1, args["num_models"]))
    opt = SGD(lr=0.01, decay=0.01/40, momentum=0.9, nesterov=True)#采用SGD的优化方式

    # Initialize model architecture.
    model = MiniVGGNet.build(width=32, height=32, depth=3, classes=len(labelNames))
    # Build model.
    model.compile(loss="categorical_crossentropy", optimizer=opt, metrics=["accuracy"])
    # Train model.
    History = model.fit_generator(aug.flow(trainX, trainY, batch_size=64),
                                  validation_data=(testX, testY), epochs=40,
                                  steps_per_epoch=len(trainX)//64, verbose=1)

    # Serialize model.
    path = [args["model"], "vgg16_cifar10_model_{}.model".format(i)]
    model.save(os.path.sep.join(path))#每进行一次epoch保存一次模型

    # Evaluate model.
    predictions = model.predict(testX, batch_size=64, verbose=1)
    report = classification_report(testY.argmax(axis=1),
                                   predictions.argmax(axis=1),
                                   target_names=labelNames)

    # Serialize report.
    path = [args["output"], "vgg16_cifar10_model_{}.txt".format(i)]#保存txt的训练结果
    f = open(os.path.sep.join(path), "w")
    f.write(report)
    f.close()

    # Plot the training loss, training accuracy, validation loss, validation accuracy over time.
    plt.style.use("ggplot")
    plt.figure()
    plt.plot(np.arange(0, 40), History.history["loss"], label="train_loss")
    plt.plot(np.arange(0, 40), History.history["val_loss"], label="val_loss")
    plt.plot(np.arange(0, 40), History.history["acc"], label="train_acc")
    plt.plot(np.arange(0, 40), History.history["val_acc"], label="val_acc")
    plt.title("Training Loss and Accuracy for model {}".format(i))
    plt.xlabel("Epoch #")
    plt.ylabel("Loss/Accuracy")
    plt.legend()

    # Serialize plot.
    path = [args["output"], "vgg16_cifar10_model_{}.png".format(i)]
    plt.savefig(os.path.sep.join(path))#保存train-loss图片
    plt.close()

part2: test_ensemble.py

# -*- coding:utf-8 -*- 
__author__ = 'xuy'


from sklearn.preprocessing import LabelBinarizer
from sklearn.metrics import classification_report
from keras.models import load_model
from keras.datasets import cifar10
import numpy as np
import argparse
import glob
import os

# Construct the argument parse and parse arguments.
ap = argparse.ArgumentParser()
ap.add_argument("-m", "--models", required=True, help="path to models directory")
args = vars(ap.parse_args())

# Load the testing data, then scale it into the range [0, 1].
# ((trainX, trainY), (testX, testY)) = cifar10.load_data()#载入全部数据集
(testX, testY) = cifar10.load_data()[1]#载入test set
testX = testX.astype("float") / 255.0

# Convert the labels from integers to vectors.
lb = LabelBinarizer()
testY  = lb.fit_transform(testY)

# Initialize the label names for the CIFAR-10 dataset
labelNames = ["airplane",
              "automobile",
              "bird",
              "cat",
              "deer",
              "dog",
              "frog",
              "horse",
              "ship",
              "truck"]

# Construct the path used to collect the models then initialize the models list.
modelPaths = os.path.sep.join([args["models"], "*.model"])
modelPaths = list(glob.glob(modelPaths))#将之前训练好的*.model文件保存到list当中
# print("modelPath的路径",modelPaths)
models = []

#开始进行模型融合
# Loop over the model paths, loading the model, and adding it to the list of models.
for (i, modelPath) in enumerate(modelPaths):
	print("[INFO] loading model {}/{}".format(i+1, len(modelPaths)))
	models.append(load_model(modelPath))

# Initialize the list of predictions.
print("[INFO] evaluating ensemble...")
predictions = []

# Loop over the models.
for model in models:
	# Use the current model to make predictions on the testing data then store these predictions in the aggregate predictions list.
    prediction=model.predict(testX, batch_size=64)#的行表示picture_number,列表示种类的label,是10000*10的二维矩阵#因此:predictions表示(5,10000,10)的维度
    predictions.append(prediction)

# print(np.shape(prediction))#(10000, 10)
# print(np.shape(predictions))#(5, 10000, 10),5表示模型数量,10000表示总的数据集,10表示最终的分类类别
# print("预测的结果:",predictions)
# Average the probabilities across all model predictions, then show a classification report.
# (5, 10000, 10) --avg--> (1000, 10).
ensembledPredictions = np.average(predictions, axis=0)#计算平均值,axis=0表示计算第一维度的平均值,predictions表示(5,10000,10)的维度,变为了(10000,10)
print(classification_report(testY.argmax(axis=1),#纵坐标
                            ensembledPredictions.argmax(axis=1),
target_names=labelNames))#输出模型融合之后的结果

'''
使用单个模型的结果:
             precision    recall  f1-score   support

   airplane       0.87      0.81      0.84      1000
 automobile       0.90      0.94      0.92      1000
       bird       0.77      0.73      0.75      1000
        cat       0.70      0.61      0.65      1000
       deer       0.81      0.81      0.81      1000
        dog       0.72      0.80      0.76      1000
       frog       0.80      0.92      0.85      1000
      horse       0.91      0.85      0.88      1000
       ship       0.91      0.91      0.91      1000
      truck       0.89      0.91      0.90      1000

avg / total       0.83      0.83      0.83     10000

使用模型融合的结果
             precision    recall  f1-score   support

   airplane       0.89      0.81      0.85      1000
 automobile       0.92      0.95      0.93      1000
       bird       0.81      0.75      0.78      1000
        cat       0.74      0.67      0.71      1000
       deer       0.82      0.84      0.83      1000
        dog       0.77      0.79      0.78      1000
       frog       0.85      0.92      0.88      1000
      horse       0.90      0.88      0.89      1000
       ship       0.89      0.94      0.91      1000
      truck       0.88      0.93      0.90      1000

avg / total       0.85      0.85      0.85     10000
我们会发现,acc会有一小部分提升,大概1%~5%左右,因为每次epoch训练的侧重点不同
'''

猜你喜欢

转载自blog.csdn.net/mdjxy63/article/details/81070811