机器学习实战--对亚马逊森林卫星照片进行分类(3)

2019-07-02 17:34:27 浏览数 (1)

如何运用迁移学习 迁移学习涉及到使用一个在相关任务上训练过的模型的全部或部分。

Keras提供了一系列预先训练的模型,可以通过Keras应用程序API全部或部分地加载和使用这些模型。 一个有用的迁移学习模型是VGG模型之一,例如VGG-16,它有16层,在开发时在ImageNet照片分类挑战中取得了最好的成绩。 该模型由两个主要部分组成:模型的特征提取器部分由VGG块组成,模型的分类器部分由全连通层层和输出层组成。

我们可以使用模型的特征提取部分,并在模型中添加一个新的分类器部分,该分类器部分是针对行星数据集量身定制的。具体来说,我们可以在训练中保持所有卷积层的权重不变,只训练新的全连通层,这些全连通层将学习如何解释从模型中提取的特征,并进行一套二进制分类。

这可以通过加载VGG-16模型,从模型的输出端移除全连接层,然后添加新的全连接层来解释模型输出并做出预测来实现。通过将“include_top”参数设置为“False”,可以自动删除模型的分类器部分,这也要求为模型指定输入的形状,在本例中为(128,128,3)。这意味着加载的模型在最后一个最大池化层结束,之后我们可以手动添加Flatten图层和新分类器完全连接的图层。

下面的define_model()函数实现了这一点,并返回一个准备好进行培训的新模型。

代码语言:javascript复制
 1# define cnn model
 2def define_model(in_shape=(128, 128, 3), out_shape=17):
 3    # load model
 4    model = VGG16(include_top=False, input_shape=in_shape)
 5    # mark loaded layers as not trainable
 6    for layer in model.layers:
 7        layer.trainable = False
 8    # add new classifier layers
 9    flat1 = Flatten()(model.layers[-1].output)
10    class1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)
11    output = Dense(out_shape, activation='sigmoid')(class1)
12    # define new model
13    model = Model(inputs=model.inputs, outputs=output)
14    # compile model
15    opt = SGD(lr=0.01, momentum=0.9)
16    model.compile(optimizer=opt, loss='binary_crossentropy', metrics=[fbeta])
17    return model

一旦创建,我们就可以像以前一样在训练数据集中训练模型。

在这种情况下,不需要进行大量的训练,因为只有新的完全连接和输出层具有可训练的权重。因此,我们将训练时期的数量固定为10。

VGG16模型在特定的ImageNet挑战数据集上进行了训练。因此,模型期望图像居中。也就是说,从输入中减去ImageNet训练数据集上计算的每个通道(红色,绿色和蓝色)的平均像素值。

Keras提供了通过preprocess_input()函数为单个照片执行此准备的功能。尽管如此,我们可以通过将“ featurewise_center ”参数设置为“ True ”并手动指定在以ImageNet训练数据集为中心时使用的平均像素值来实现与图像数据生成器相同的效果:[123.68,116.779 ,103.939]。

代码语言:javascript复制
1# create data generator
2datagen = ImageDataGenerator(featurewise_center=True)
3# specify imagenet mean values for centering
4datagen.mean = [123.68, 116.779, 103.939]
5    return model

下面列出了用于行星数据集上的转移学习的VGG-16模型的完整代码清单。

代码语言:javascript复制
 1# vgg16 transfer learning on the planet dataset
 2import sys
 3from numpy import load
 4from matplotlib import pyplot
 5from sklearn.model_selection import train_test_split
 6from keras import backend
 7from keras.layers import Dense
 8from keras.layers import Flatten
 9from keras.optimizers import SGD
10from keras.applications.vgg16 import VGG16
11from keras.models import Model
12from keras.preprocessing.image import ImageDataGenerator
13
14# load train and test dataset
15def load_dataset():
16    # load dataset
17    data = load('planet_data.npz')
18    X, y = data['arr_0'], data['arr_1']
19    # separate into train and test datasets
20    trainX, testX, trainY, testY = train_test_split(X, y, test_size=0.3, random_state=1)
21    print(trainX.shape, trainY.shape, testX.shape, testY.shape)
22    return trainX, trainY, testX, testY
23
24# calculate fbeta score for multi-class/label classification
25def fbeta(y_true, y_pred, beta=2):
26    # clip predictions
27    y_pred = backend.clip(y_pred, 0, 1)
28    # calculate elements
29    tp = backend.sum(backend.round(backend.clip(y_true * y_pred, 0, 1)), axis=1)
30    fp = backend.sum(backend.round(backend.clip(y_pred - y_true, 0, 1)), axis=1)
31    fn = backend.sum(backend.round(backend.clip(y_true - y_pred, 0, 1)), axis=1)
32    # calculate precision
33    p = tp / (tp   fp   backend.epsilon())
34    # calculate recall
35    r = tp / (tp   fn   backend.epsilon())
36    # calculate fbeta, averaged across each class
37    bb = beta ** 2
38    fbeta_score = backend.mean((1   bb) * (p * r) / (bb * p   r   backend.epsilon()))
39    return fbeta_score
40
41# define cnn model
42def define_model(in_shape=(128, 128, 3), out_shape=17):
43    # load model
44    model = VGG16(include_top=False, input_shape=in_shape)
45    # mark loaded layers as not trainable
46    for layer in model.layers:
47        layer.trainable = False
48    # add new classifier layers
49    flat1 = Flatten()(model.layers[-1].output)
50    class1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)
51    output = Dense(out_shape, activation='sigmoid')(class1)
52    # define new model
53    model = Model(inputs=model.inputs, outputs=output)
54    # compile model
55    opt = SGD(lr=0.01, momentum=0.9)
56    model.compile(optimizer=opt, loss='binary_crossentropy', metrics=[fbeta])
57    return model
58
59# plot diagnostic learning curves
60def summarize_diagnostics(history):
61    # plot loss
62    pyplot.subplot(211)
63    pyplot.title('Cross Entropy Loss')
64    pyplot.plot(history.history['loss'], color='blue', label='train')
65    pyplot.plot(history.history['val_loss'], color='orange', label='test')
66    # plot accuracy
67    pyplot.subplot(212)
68    pyplot.title('Fbeta')
69    pyplot.plot(history.history['fbeta'], color='blue', label='train')
70    pyplot.plot(history.history['val_fbeta'], color='orange', label='test')
71    # save plot to file
72    filename = sys.argv[0].split('/')[-1]
73    pyplot.savefig(filename   '_plot.png')
74    pyplot.close()
75
76# run the test harness for evaluating a model
77def run_test_harness():
78    # load dataset
79    trainX, trainY, testX, testY = load_dataset()
80    # create data generator
81    datagen = ImageDataGenerator(featurewise_center=True)
82    # specify imagenet mean values for centering
83    datagen.mean = [123.68, 116.779, 103.939]
84    # prepare iterators
85    train_it = datagen.flow(trainX, trainY, batch_size=128)
86    test_it = datagen.flow(testX, testY, batch_size=128)
87    # define model
88    model = define_model()
89    # fit model
90    history = model.fit_generator(train_it, steps_per_epoch=len(train_it),
91        validation_data=test_it, validation_steps=len(test_it), epochs=20, verbose=0)
92    # evaluate model
93    loss, fbeta = model.evaluate_generator(test_it, steps=len(test_it), verbose=0)
94    print('> loss=%.3f, fbeta=%.3f' % (loss, fbeta))
95    # learning curves
96    summarize_diagnostics(history)
97
98# entry point, run the test harness
99run_test_harness()

首先运行示例适合模型,然后在保持测试数据集上报告模型性能。 鉴于学习算法的随机性,您的具体结果可能会有所不同。 在这种情况下,我们可以看到模型的F-beta得分约为0.860,优于基准模型,但不如图像数据增加的基模准型好。

回顾学习曲线,我们可以看到该模型对数据集的拟合速度很快,仅在几个训练阶段就显示出很强的过拟合。 结果表明,该模型可以通过正则化来解决过度拟合问题,或者通过模型的其他变化或学习过程来减缓改进的速度。

VGG-16模型的设计目的是将物体的照片分为1000个类别之一。因此,它被设计用来挑选对象的细粒度特性。我们可以猜测,更深层次的模型学习到的特征将代表ImageNet数据集中看到的更高阶的特征,这些特征可能与亚马逊雨林卫星照片的分类没有直接关系。 为了解决这个问题,我们可以重新拟合VGG-16模型,并允许训练算法对模型中某些层的权重进行微调。在本例中,我们将使三个卷积层(以及一致性池化层)成为可训练的。下面列出了define_model()函数的更新版本。

代码语言:javascript复制
 1# define cnn model
 2def define_model(in_shape=(128, 128, 3), out_shape=17):
 3    # load model
 4    model = VGG16(include_top=False, input_shape=in_shape)
 5    # mark loaded layers as not trainable
 6    for layer in model.layers:
 7        layer.trainable = False
 8    # allow last vgg block to be trainable
 9    model.get_layer('block5_conv1').trainable = True
10    model.get_layer('block5_conv2').trainable = True
11    model.get_layer('block5_conv3').trainable = True
12    model.get_layer('block5_pool').trainable = True
13    # add new classifier layers
14    flat1 = Flatten()(model.layers[-1].output)
15    class1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)
16    output = Dense(out_shape, activation='sigmoid')(class1)
17    # define new model
18    model = Model(inputs=model.inputs, outputs=output)
19    # compile model
20    opt = SGD(lr=0.01, momentum=0.9)
21    model.compile(optimizer=opt, loss='binary_crossentropy', metrics=[fbeta])

然后可以使用此修改重新运行在行星数据集上使用VGG-16进行传递学习的示例。 鉴于学习算法的随机性,您的具体结果可能会有所不同。 在这种情况下,与VGG-16模型特征提取模型相比,我们看到模型性能有所提升,因为正在将F-β评分从大约0.860提高到大约0.879。该分数接近于基准模型所见的F-beta分数,并增加了图像数据增强。

回顾学习曲线,我们可以看到模型在运行中相对早期仍显示过度拟合训练数据集的迹象。结果表明,该模型可能会受益于使用dropout和/或其他正规化方法。

鉴于我们在基准模型上使用数据增强看到了很大的改进,看看数据增强是否可用于通过微调来改善VGG-16模型的性能可能会很有趣。 在本例中,可以使用相同的define_model()函数,但在本例中,可以像上一节中执行的那样,更新run_test_harness(),以使用图像数据增强。我们期望增加的数据会减慢改进的速度。因此,我们将把训练周期从20个增加到50个,以给模型更多的时间来收敛。 下面列出了带有微调和数据增强功能的完整VGG-16示例。

代码语言:javascript复制
  1# vgg with fine-tuning and data augmentation for the planet dataset
  2import sys
  3from numpy import load
  4from matplotlib import pyplot
  5from sklearn.model_selection import train_test_split
  6from keras import backend
  7from keras.layers import Dense
  8from keras.layers import Flatten
  9from keras.optimizers import SGD
 10from keras.applications.vgg16 import VGG16
 11from keras.models import Model
 12from keras.preprocessing.image import ImageDataGenerator
 13
 14# load train and test dataset
 15def load_dataset():
 16    # load dataset
 17    data = load('planet_data.npz')
 18    X, y = data['arr_0'], data['arr_1']
 19    # separate into train and test datasets
 20    trainX, testX, trainY, testY = train_test_split(X, y, test_size=0.3, random_state=1)
 21    print(trainX.shape, trainY.shape, testX.shape, testY.shape)
 22    return trainX, trainY, testX, testY
 23
 24# calculate fbeta score for multi-class/label classification
 25def fbeta(y_true, y_pred, beta=2):
 26    # clip predictions
 27    y_pred = backend.clip(y_pred, 0, 1)
 28    # calculate elements
 29    tp = backend.sum(backend.round(backend.clip(y_true * y_pred, 0, 1)), axis=1)
 30    fp = backend.sum(backend.round(backend.clip(y_pred - y_true, 0, 1)), axis=1)
 31    fn = backend.sum(backend.round(backend.clip(y_true - y_pred, 0, 1)), axis=1)
 32    # calculate precision
 33    p = tp / (tp   fp   backend.epsilon())
 34    # calculate recall
 35    r = tp / (tp   fn   backend.epsilon())
 36    # calculate fbeta, averaged across each class
 37    bb = beta ** 2
 38    fbeta_score = backend.mean((1   bb) * (p * r) / (bb * p   r   backend.epsilon()))
 39    return fbeta_score
 40
 41# define cnn model
 42def define_model(in_shape=(128, 128, 3), out_shape=17):
 43    # load model
 44    model = VGG16(include_top=False, input_shape=in_shape)
 45    # mark loaded layers as not trainable
 46    for layer in model.layers:
 47        layer.trainable = False
 48    # allow last vgg block to be trainable
 49    model.get_layer('block5_conv1').trainable = True
 50    model.get_layer('block5_conv2').trainable = True
 51    model.get_layer('block5_conv3').trainable = True
 52    model.get_layer('block5_pool').trainable = True
 53    # add new classifier layers
 54    flat1 = Flatten()(model.layers[-1].output)
 55    class1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)
 56    output = Dense(out_shape, activation='sigmoid')(class1)
 57    # define new model
 58    model = Model(inputs=model.inputs, outputs=output)
 59    # compile model
 60    opt = SGD(lr=0.01, momentum=0.9)
 61    model.compile(optimizer=opt, loss='binary_crossentropy', metrics=[fbeta])
 62    return model
 63
 64# plot diagnostic learning curves
 65def summarize_diagnostics(history):
 66    # plot loss
 67    pyplot.subplot(211)
 68    pyplot.title('Cross Entropy Loss')
 69    pyplot.plot(history.history['loss'], color='blue', label='train')
 70    pyplot.plot(history.history['val_loss'], color='orange', label='test')
 71    # plot accuracy
 72    pyplot.subplot(212)
 73    pyplot.title('Fbeta')
 74    pyplot.plot(history.history['fbeta'], color='blue', label='train')
 75    pyplot.plot(history.history['val_fbeta'], color='orange', label='test')
 76    # save plot to file
 77    filename = sys.argv[0].split('/')[-1]
 78    pyplot.savefig(filename   '_plot.png')
 79    pyplot.close()
 80
 81# run the test harness for evaluating a model
 82def run_test_harness():
 83    # load dataset
 84    trainX, trainY, testX, testY = load_dataset()
 85    # create data generator
 86    train_datagen = ImageDataGenerator(featurewise_center=True, horizontal_flip=True, vertical_flip=True, rotation_range=90)
 87    test_datagen = ImageDataGenerator(featurewise_center=True)
 88    # specify imagenet mean values for centering
 89    train_datagen.mean = [123.68, 116.779, 103.939]
 90    test_datagen.mean = [123.68, 116.779, 103.939]
 91    # prepare iterators
 92    train_it = train_datagen.flow(trainX, trainY, batch_size=128)
 93    test_it = test_datagen.flow(testX, testY, batch_size=128)
 94    # define model
 95    model = define_model()
 96    # fit model
 97    history = model.fit_generator(train_it, steps_per_epoch=len(train_it),
 98        validation_data=test_it, validation_steps=len(test_it), epochs=50, verbose=0)
 99    # evaluate model
100    loss, fbeta = model.evaluate_generator(test_it, steps=len(test_it), verbose=0)
101    print('> loss=%.3f, fbeta=%.3f' % (loss, fbeta))
102    # learning curves
103    summarize_diagnostics(history)
104
105# entry point, run the test harness
106run_test_harness()

首先运行示例适合模型,然后在保持测试数据集上报告模型性能。

鉴于学习算法的随机性,您的具体结果可能会有所不同。

在这种情况下,我们可以看到模型性能进一步提高,从F-beta评分约0.879提高到F-beta评分约0.891。

回顾学习曲线,我们可以看到数据的增加再次对模型的过拟合产生了很大的影响,在这种情况下稳定了学习,并可能将过拟合延迟到20 epoch。

讨论 在本节中,我们探讨了三种不同的迁移学习案例。 结果总结如下,尽管我们必须假设学习算法的随机性质,这些结果有一些差异:

  • VGG-16模型:0.860。
  • VGG-16模型 微调:0.879。
  • VGG-16模型 微调 数据扩充:0.891。

VGG-16模型的选择有些武断,因为它是一个较小的、易于理解的模型。其他模型可以作为转移学习的基础,例如ResNet,它可以获得更好的性能。

此外,更多的微调也可能导致更好的性能。这可能包括调整更多特征提取器层的权重,可能会降低学习速度。这还可能包括修改模型以添加正则化,例如dropout。

如何确定模型并做出预测

只要我们有想法,有时间和资源去测试它们,模型改进的过程就会持续下去。

在某些时候,必须选择并采用最终的模型配置。在本例中,我们将保持简单,并使用VGG-16转移学习,微调和数据增强作为最终模型。

首先,我们将通过在整个训练数据集上拟合模型并将模型保存到文件以供以后使用来完成我们的模型。然后,我们将加载已保存的模型并使用它来对单个图像进行预测。

保存最终模型

第一步是在整个训练数据集上拟合最终模型。 所述load_dataset()函数可以被更新到加载的数据集不再分成训练集和测试集。

代码语言:javascript复制
1# load train and test dataset
2def load_dataset():
3    # load dataset
4    data = load('planet_data.npz')
5    X, y = data['arr_0'], data['arr_1']
6    return X, y

所述define_model()函数可以被用作前一节与微调和数据扩张中VGG-16模型中被定义。

代码语言:javascript复制
 1# define cnn model
 2def define_model(in_shape=(128, 128, 3), out_shape=17):
 3    # load model
 4    model = VGG16(include_top=False, input_shape=in_shape)
 5    # mark loaded layers as not trainable
 6    for layer in model.layers:
 7        layer.trainable = False
 8    # allow last vgg block to be trainable
 9    model.get_layer('block5_conv1').trainable = True
10    model.get_layer('block5_conv2').trainable = True
11    model.get_layer('block5_conv3').trainable = True
12    model.get_layer('block5_pool').trainable = True
13    # add new classifier layers
14    flat1 = Flatten()(model.layers[-1].output)
15    class1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)
16    output = Dense(out_shape, activation='sigmoid')(class1)
17    # define new model
18    model = Model(inputs=model.inputs, outputs=output)
19    # compile model
20    opt = SGD(lr=0.01, momentum=0.9)
21    model.compile(optimizer=opt, loss='binary_crossentropy')
22    return model

最后,对于训练数据集,我们只需要一个数据生成器和一个迭代器。

代码语言:javascript复制
1# create data generator
2datagen = ImageDataGenerator(featurewise_center=True, horizontal_flip=True, vertical_flip=True, rotation_range=90)
3# specify imagenet mean values for centering
4datagen.mean = [123.68, 116.779, 103.939]
5# prepare iterator
6train_it = datagen.flow(X, y, batch_size=128)

该模型将适用于50个epoch,之后通过调用模型上的save()函数将其保存到H5文件中

代码语言:javascript复制
1# fit model
2model.fit_generator(train_it, steps_per_epoch=len(train_it), epochs=50, verbose=0)
3# save model
4model.save('final_model.h5')

注意:保存和加载Keras模型需要在工作站上安装h5py库。 下面列出了将最终模型拟合到训练数据集并将其保存到文件的完整示例。

代码语言:javascript复制
 1# save the final model to file
 2from numpy import load
 3from keras.preprocessing.image import ImageDataGenerator
 4from keras.applications.vgg16 import VGG16
 5from keras.models import Model
 6from keras.layers import Dense
 7from keras.layers import Flatten
 8from keras.optimizers import SGD
 9
10# load train and test dataset
11def load_dataset():
12    # load dataset
13    data = load('planet_data.npz')
14    X, y = data['arr_0'], data['arr_1']
15    return X, y
16
17# define cnn model
18def define_model(in_shape=(128, 128, 3), out_shape=17):
19    # load model
20    model = VGG16(include_top=False, input_shape=in_shape)
21    # mark loaded layers as not trainable
22    for layer in model.layers:
23        layer.trainable = False
24    # allow last vgg block to be trainable
25    model.get_layer('block5_conv1').trainable = True
26    model.get_layer('block5_conv2').trainable = True
27    model.get_layer('block5_conv3').trainable = True
28    model.get_layer('block5_pool').trainable = True
29    # add new classifier layers
30    flat1 = Flatten()(model.layers[-1].output)
31    class1 = Dense(128, activation='relu', kernel_initializer='he_uniform')(flat1)
32    output = Dense(out_shape, activation='sigmoid')(class1)
33    # define new model
34    model = Model(inputs=model.inputs, outputs=output)
35    # compile model
36    opt = SGD(lr=0.01, momentum=0.9)
37    model.compile(optimizer=opt, loss='binary_crossentropy')
38    return model
39
40# run the test harness for evaluating a model
41def run_test_harness():
42    # load dataset
43    X, y = load_dataset()
44    # create data generator
45    datagen = ImageDataGenerator(featurewise_center=True, horizontal_flip=True, vertical_flip=True, rotation_range=90)
46    # specify imagenet mean values for centering
47    datagen.mean = [123.68, 116.779, 103.939]
48    # prepare iterator
49    train_it = datagen.flow(X, y, batch_size=128)
50    # define model
51    model = define_model()
52    # fit model
53    model.fit_generator(train_it, steps_per_epoch=len(train_it), epochs=50, verbose=0)
54    # save model
55    model.save('final_model.h5')
56
57# entry point, run the test harness
58run_test_harness()

运行此示例后,您将在当前工作目录中将拥有一个91兆字节的大文件,名为final_model。

做一个预测

我们可以使用我们保存的模型对新图像进行预测。 该模型假设新图像是彩色的,并且它们已被分割成大小为256×256的正方形。 下面是从训练数据集中提取的图像。

将其从训练数据目录复制到名为“ sample_image.jpg ” 的当前工作目录,例如:

根据训练数据集的映射文件,该文件具有标记(没有特定的顺序):

  • 农业

我们将假装这是一个全新的,看不见的图像,以所需的方式准备,并看看我们如何使用我们保存的模型来预测图像所代表的标签。

首先,我们可以加载图像并将其强制为128×128像素。然后可以调整加载的图像的大小以在数据集中具有单个样本。像素值也必须居中以匹配在模型训练期间准备数据的方式。

该load_image()函数实现这一点,将返回加载图像准备进行分类。

代码语言:javascript复制
 1# load and prepare the image
 2def load_image(filename):
 3    # load the image
 4    img = load_img(filename, target_size=(128, 128))
 5    # convert to array
 6    img = img_to_array(img)
 7    # reshape into a single sample with 3 channels
 8    img = img.reshape(1, 128, 128, 3)
 9    # center pixel data
10    img = img.astype('float32')
11    img = img - [123.68, 116.779, 103.939]
12    return img

接下来,我们可以像上一节一样加载模型,并调用predict()函数来预测图像中的内容。

代码语言:javascript复制
1# predict the class
2result = model.predict(img)

这将返回一个包含17个元素的向量,其浮点值介于0和1之间,可以将其解释为模型确信照片可以用每个已知标记标记的概率。 我们可以将这些概率舍入为0或1,然后使用我们在create_tag_mapping()函数的第一部分中准备的反向映射,将具有“ 1 ”值的矢量索引转换为图像的标记。

下面的prediction_to_tags()函数实现了这一点,将整数映射到标签和照片模型预测的向量,并返回预测的标签列表。

代码语言:javascript复制
1# convert a prediction to tags
2def prediction_to_tags(inv_mapping, prediction):
3    # round probabilities to {0, 1}
4    values = prediction.round()
5    # collect all predicted tags
6    tags = [inv_mapping[i] for i in range(len(values)) if values[i] == 1.0]
7    return tags

我们可以将所有这些结合在一起并对新照片进行预测。下面列出了完整的示例。

代码语言:javascript复制
 1# make a prediction for a new image
 2from pandas import read_csv
 3from keras.preprocessing.image import load_img
 4from keras.preprocessing.image import img_to_array
 5from keras.models import load_model
 6
 7# create a mapping of tags to integers given the loaded mapping file
 8def create_tag_mapping(mapping_csv):
 9    # create a set of all known tags
10    labels = set()
11    for i in range(len(mapping_csv)):
12        # convert spaced separated tags into an array of tags
13        tags = mapping_csv['tags'][i].split(' ')
14        # add tags to the set of known labels
15        labels.update(tags)
16    # convert set of labels to a list to list
17    labels = list(labels)
18    # order set alphabetically
19    labels.sort()
20    # dict that maps labels to integers, and the reverse
21    labels_map = {labels[i]:i for i in range(len(labels))}
22    inv_labels_map = {i:labels[i] for i in range(len(labels))}
23    return labels_map, inv_labels_map
24
25# convert a prediction to tags
26def prediction_to_tags(inv_mapping, prediction):
27    # round probabilities to {0, 1}
28    values = prediction.round()
29    # collect all predicted tags
30    tags = [inv_mapping[i] for i in range(len(values)) if values[i] == 1.0]
31    return tags
32
33# load and prepare the image
34def load_image(filename):
35    # load the image
36    img = load_img(filename, target_size=(128, 128))
37    # convert to array
38    img = img_to_array(img)
39    # reshape into a single sample with 3 channels
40    img = img.reshape(1, 128, 128, 3)
41    # center pixel data
42    img = img.astype('float32')
43    img = img - [123.68, 116.779, 103.939]
44    return img
45
46# load an image and predict the class
47def run_example(inv_mapping):
48    # load the image
49    img = load_image('sample_image.jpg')
50    # load model
51    model = load_model('final_model.h5')
52    # predict the class
53    result = model.predict(img)
54    print(result[0])
55    # map prediction to tags
56    tags = prediction_to_tags(inv_mapping, result[0])
57    print(tags)
58
59# load the mapping file
60filename = 'train_v2.csv'
61mapping_csv = read_csv(filename)
62# create a mapping of tags to integers
63_, inv_mapping = create_tag_mapping(mapping_csv)
64# entry point, run the example
65run_example(inv_mapping)

运行示例首先加载并准备图像,加载模型,然后进行预测。 首先,打印原始17元素预测向量。如果我们愿意,我们可以漂亮地打印这个矢量并总结出照片将被分配到每个标签的预期置信度。

接下来,对预测进行舍入,并将包含1值的向量索引反向映射到其标记字符串值。然后打印预测的标签。我们可以看到模型已正确预测所提供照片的已知标签。

在您已经手动建议标签后,使用全新照片(例如测试数据集中的照片)重复此测试可能会很有趣。

扩展

本节列出了一些扩展您可能希望探索的教程的想法。

  • 调整学习速率。探索用于训练基准模型的学习算法的更改,如替代学习速率、学习率调度或自适应学习率算法(如Adam)。
  • 规范迁移学习模型。探索在迁移学习中添加更多的正则化技术,如early topping、dropout、weight decay等,并比较结果。
  • 自动化测试时间。更新模型以使用测试时间预测,例如flips, rotations, and/or crops,以查看测试数据集上的预测性能是否可以进一步提高。

写在最后:

文章终于翻译完了,这两个周只要有时间就会翻译文章,自己水平有限,文章中可能会存在很多问题,欢迎您在留言区跟我交流,如果翻译的文章对您有用,我以后还会继续翻译文章。翻译这篇文章被老外的思维所折服,以后写此类文章会加以学习。

原文传送门:

https://machinelearningmastery.com/how-to-develop-a-convolutional-neural-network-to-classify-satellite-photos-of-the-amazon-rainforest/

在看和转发

都是一种支持

0 人点赞