Kears-4-深度学习用于计算机视觉-使用预训练的卷积网络

news2024/9/23 13:22:57

0. 说明:

本篇学习记录主要包括:《Python深度学习》的第5章(深度学习用于计算机视觉)的第3节(使用预训练的卷积神经网络)内容。

相关知识点:

  1. 预训练模型的复用方法;
  2. 预训练网络 (pretrained network) 是一个保存好的网络,之前已经在大型数据集上完成训练。理论上数据集足够大,那么该预训练网络就可以学到足够的特征,模型的可移植性就更好。
  3. 预训练模型的使用方法:特征提取 (feature extraction) 和 微调模型 (fine-tuning)。

示例前提: 本例中,假设有一个在 ImageNet 数据集上训练好的大型卷积网络 (ImageNet上有很多中动物的图片,包括猫和狗,所以可以认为该网络在猫狗分类问题上也能有良好的效果)。

本例中使用 VGG16 架构 (由 Karen Simonyan 和 Andrew Zisserman 于2014年开发)。

1. 使用预训练的卷积神经网络:

用法1: 特征提取

用之前网络学到的表示来从新样本中提取特征,再将这些特征输入一个新的分类器,从头开始训练。

用于图像分类的卷积神经网络包含两部分:

1). 一系列卷积层和汇聚层 (这部分被称为模型的卷积基 convolutional base);

2). 一个密集链接分类器;

对于卷积网络而言,卷积层提取到的表示的通用性取决于该层在模型中的深度。越靠近输入层的的层提取到的是局部的、高度通用的特征 (比如视觉边缘、颜色、纹理等);越靠近输出层中的层,提取到的特征是更加抽象的概念 (比如“猫耳朵”、”狗眼睛“)。所以对于用预训练模型而言,应该使用模型的前几层来提取特征,而不是用整个卷积基。

思路:使用在 ImageNet 上训练的 VGG16 网络的卷积基,从猫狗图像中提取有用的特征,然后在这些特征上训练一个猫狗分类器。

VGG16 等模型内置于 Keras 中,可以直接从 keras.applications 模块中导入。

keras.applications 模块中还包含其他的图形分类模型 (都是用 ImageNet 数据集训练得到的):

Xception

Inception V3

ResNet50

VGG16

VGG19

MobileNet

1. 将 VGG16 卷积基实例化:

from keras.applications import VGG16

conv_base = VGG16(weights="imagenet",  ## 指定模型初始化的权重检查点
                  include_top=False,   ## 指定模型最后是否包含密集分类器 (默认情况下分类器对应于ImageNet的1000个类别)
                  input_shape=(150, 150, 3)) ## 输入到网络中的图像张量的形状 (该参数可选,如果不传入该参数,那么该网络可以处理任意形状的输入)

Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/vgg16/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5
58889256/58889256 [==============================] - 10s 0us/step
conv_base.summary()
Model: "vgg16"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_1 (InputLayer)        [(None, 150, 150, 3)]     0         
                                                                 
 block1_conv1 (Conv2D)       (None, 150, 150, 64)      1792      
                                                                 
 block1_conv2 (Conv2D)       (None, 150, 150, 64)      36928     
                                                                 
 block1_pool (MaxPooling2D)  (None, 75, 75, 64)        0         
                                                                 
 block2_conv1 (Conv2D)       (None, 75, 75, 128)       73856     
                                                                 
 block2_conv2 (Conv2D)       (None, 75, 75, 128)       147584    
                                                                 
 block2_pool (MaxPooling2D)  (None, 37, 37, 128)       0         
                                                                 
 block3_conv1 (Conv2D)       (None, 37, 37, 256)       295168    
                                                                 
 block3_conv2 (Conv2D)       (None, 37, 37, 256)       590080    
                                                                 
 block3_conv3 (Conv2D)       (None, 37, 37, 256)       590080    
                                                                 
 block3_pool (MaxPooling2D)  (None, 18, 18, 256)       0         
                                                                 
 block4_conv1 (Conv2D)       (None, 18, 18, 512)       1180160   
                                                                 
 block4_conv2 (Conv2D)       (None, 18, 18, 512)       2359808   
                                                                 
 block4_conv3 (Conv2D)       (None, 18, 18, 512)       2359808   
                                                                 
 block4_pool (MaxPooling2D)  (None, 9, 9, 512)         0         
                                                                 
 block5_conv1 (Conv2D)       (None, 9, 9, 512)         2359808   
                                                                 
 block5_conv2 (Conv2D)       (None, 9, 9, 512)         2359808   
                                                                 
 block5_conv3 (Conv2D)       (None, 9, 9, 512)         2359808   
                                                                 
 block5_pool (MaxPooling2D)  (None, 4, 4, 512)         0         
                                                                 
=================================================================
Total params: 14,714,688
Trainable params: 14,714,688
Non-trainable params: 0
_________________________________________________________________

可以看出上面 conv_base 最后的特征形状为 (4, 4, 512),在该特征基础上加上一个密集连接分类器。

可以从以下两方面进行处理:

  1. 在自己的数据集上直接运行卷积基,将输出保存为 Numpy 数组,再将这个数组输入到 密集连接分类器中 (该方法:速度快,计算代价低,但是不能使用数据增强)。

  2. 在顶部添加 Dense 层扩展卷积基,再在输入数据上运行整个模型 (该方法:可以使用数据增强,但是计算代价高)。

2. 直接运行卷积基提取特征,再将特征输入密集链接分类器中 (不使用数据增强):

conv_base 提取特征:

import numpy as np
from keras.preprocessing.image import ImageDataGenerator ## 可以将硬盘上的图像文件自动转换为预处理好的张量批量

train_dir = "./dogs-vs-cats/small_dt/train/"
validation_dir = "./dogs-vs-cats/small_dt/validation/"
test_dir = "./dogs-vs-cats/small_dt/test/"

datagen = ImageDataGenerator(rescale=1./255)
batch_size = 20

## 基于 conv_base 提取图像特征
def extract_features(directory, sample_count):
    features = np.zeros(shape=(sample_count, 4, 4, 512)) ## 初始化一个形状为 (sample_count, 4, 4, 512)的特征
    labels = np.zeros(shape=(sample_count)) ## 初始化一个与特征对应的标签,形状为 (sample)
    ## 创建批量张量
    generator = datagen.flow_from_directory(
        directory=directory,
        target_size=(150, 150),
        batch_size=batch_size,
        class_mode="binary"
    )
    i = 0
    for inputs_batch, labels_batch in generator:
        features_batch = conv_base.predict(inputs_batch)
        features[i * batch_size : (i+1) * batch_size] = features_batch ## 将初始化的特征的第0维的 i*batch_size 到 (i+1)*batch_size 用 conv_base 提取到的特征进行填充。目的就是用 conv_base 提取的特征填充到初始化的矩阵中.
        labels[i * batch_size : (i+1) * batch_size] = labels_batch ## 对应的位置的标签的填充
        i += 1
        if i * batch_size >= sample_count:
            break
    return features, labels

train_features, train_labels = extract_features(train_dir, 2000) ## 2000张图片作为训练集,得到的特征形状为 (2000, 4, 4, 512)
validation_features, validation_labels = extract_features(validation_dir, 1000) ## 1000张作验证
test_features, test_labels = extract_features(test_dir, 1000) ## 1000张做测试

## 将得到的特征展开 (samples, 4, 4, 512) => (samples, 8192)
train_features = np.reshape(train_features, (2000, 4*4*512))
validation_features = np.reshape(validation_features, (1000, 4*4*512))
test_features = np.reshape(test_features, (1000, 4*4*512))
Found 2000 images belonging to 2 classes.
1/1 [==============================] - 1s 649ms/step
1/1 [==============================] - 0s 17ms/step

1/1 [==============================] - 0s 16ms/step
Found 1000 images belonging to 2 classes.
1/1 [==============================] - 0s 14ms/step
1/1 [==============================] - 0s 16ms/step

1/1 [==============================] - 0s 16ms/step
Found 1000 images belonging to 2 classes.
1/1 [==============================] - 0s 13ms/step
1/1 [==============================] - 0s 14ms/step

1/1 [==============================] - 0s 14ms/step
1/1 [==============================] - 0s 15ms/step

定义并训练密集链接分类器:

from keras import models
from keras import layers
from keras import optimizers

model = models.Sequential()
model.add(layers.Dense(256, activation="relu", input_dim=4*4*512))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(1, activation="sigmoid"))

model.compile(optimizer=optimizers.RMSprop(learning_rate=2e-5),
              loss="binary_crossentropy",
              metrics=["acc"])

history = model.fit(train_features, train_labels,
                    epochs=30,
                    batch_size=20,
                    validation_data=(validation_features, validation_labels))
Epoch 1/30
100/100 [==============================] - 2s 14ms/step - loss: 0.5930 - acc: 0.6755 - val_loss: 0.4406 - val_acc: 0.8440
Epoch 2/30
100/100 [==============================] - 1s 10ms/step - loss: 0.3957 - acc: 0.8385 - val_loss: 0.3564 - val_acc: 0.8740

Epoch 30/30
100/100 [==============================] - 1s 10ms/step - loss: 0.0735 - acc: 0.9820 - val_loss: 0.2407 - val_acc: 0.9020

可视化损失和精度:

import matplotlib.pyplot as plt
history_dict = history.history

loss_values = history_dict["loss"]
val_loss_values = history_dict["val_loss"]
epochs = range(1, len(loss_values)+1)

plt.plot(epochs, loss_values, "bo", label="Training loss") ## "bo" 表示蓝色圆点
plt.plot(epochs, val_loss_values, "b", label="Validation loss") ## "bo" 表示蓝色实线
plt.title("Training and validation loss")
plt.xlabel("Epochs")
plt.ylabel("Loss")
plt.legend()

plt.show()

在这里插入图片描述

## 训练精度和验证精度
import matplotlib.pyplot as plt
history_dict = history.history

acc_values = history_dict["acc"]
val_acc_values = history_dict["val_acc"]
epochs = range(1, len(acc_values)+1)

plt.plot(epochs, acc_values, "bo", label="Training accuracy") ## "bo" 表示蓝色圆点
plt.plot(epochs, val_acc_values, "b", label="Validation accuracy") ## "bo" 表示蓝色实线
plt.title("Training and validation accuracy")
plt.xlabel("Epochs")
plt.ylabel("Accuracy")
plt.legend()

plt.show()

在这里插入图片描述

该结果与之前 “从头开始训练的小模型” 的结果相比要好很多,尽管 dropout 比率较大,但是模型经过几次(大概epoch=5左右)训练基本就出现了过拟合的情况。

下面看一下使用数据增强的方法对应的结果如何?

3. 使用数据增强提取特征:

扩展 conv_base 模型,再将数据输入到模型中。

(ps. 书中说,该方法的计算代价很高,必须在GPU上运行。所以该部分的代码都在 Mac M1 上运行)

conv_base 上添加一个密集连接分类器:

from keras import models
from keras import layers

model = models.Sequential()
model.add(conv_base)
model.add(layers.Flatten())
model.add(layers.Dense(256, activation="relu"))
model.add(layers.Dense(1, activation="sigmoid"))
model.summary()
Model: "sequential_3"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 vgg16 (Functional)          (None, 4, 4, 512)         14714688  
                                                                 
 flatten_2 (Flatten)         (None, 8192)              0         
                                                                 
 dense_6 (Dense)             (None, 256)               2097408   
                                                                 
 dense_7 (Dense)             (None, 1)                 257       
                                                                 
=================================================================
Total params: 16,812,353
Trainable params: 16,812,353
Non-trainable params: 0
_________________________________________________________________

“冻结” 卷积基:

冻结 (freeze) 一个或多个层指的是在训练过程中保持其权重不变。如果不冻结,那么卷积基之前学到的表示将会在训练过程中被修改。

keras 中冻结网络的方法是将 trainable 属性设置为 False (注意:需要在编译模型compile之前冻结网络,否则将不起作用)。

print("冻结网络之前,训练权重的数目: ", len(model.trainable_weights))

conv_base.trainable = False ## 冻结网络

print("冻结网络之后,训练权重的数目: ", len(model.trainable_weights))
冻结网络之前,训练权重的数目:  30
冻结网络之后,训练权重的数目:  4

经过 “冻结网络” 的设置之后,只有添加的那两个Dense层的权重需要训练,conv_base的权重不需要训练,所以总共有4个权重张量。

利用 “冻结” 的卷积基端到端地训练模型:

from keras.preprocessing.image import ImageDataGenerator
from keras import optimizers

## 训练图像进行数据增强
train_datagen = ImageDataGenerator(
    rescale=1./255,
    rotation_range=40,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
    fill_mode="nearest"
)

## 验证数据不可以增强
test_datagen = ImageDataGenerator(rescale=1./255)

## 创建张量
train_generator = train_datagen.flow_from_directory(
    train_dir,
    target_size=(150, 150), ## 所有训练图像的大小调整为 150x150
    batch_size=20,
    class_mode="binary"
)

validation_generator = test_datagen.flow_from_directory(
    validation_dir,
    target_size=(150, 150),
    batch_size=20,
    class_mode="binary"
)

## 编译模型
model.compile(loss="binary_crossentropy",
              optimizer=optimizers.RMSprop(learning_rate=2e-5),
              metrics=["acc"])

history = model.fit_generator(
    train_generator,
    steps_per_epoch=100, ## 一共2000个训练样本,批量大小为20,需要加载100次
    epochs=30,
    validation_data=validation_generator,
    validation_steps=50 ## 一共1000个验证样本,批量大小为20,需要加载50次
)
Found 2000 images belonging to 2 classes.
Found 1000 images belonging to 2 classes.
Epoch 1/30


/var/folders/0w/m6x2g_g94sqfmg3k8dldpwgm0000gn/T/ipykernel_32812/1274639931.py:39: UserWarning: `Model.fit_generator` is deprecated and will be removed in a future version. Please use `Model.fit`, which supports generators.
  history = model.fit_generator(


100/100 [==============================] - 27s 267ms/step - loss: 0.5966 - acc: 0.6880 - val_loss: 0.4588 - val_acc: 0.8160
Epoch 2/30
100/100 [==============================] - 27s 270ms/step - loss: 0.4856 - acc: 0.7865 - val_loss: 0.3761 - val_acc: 0.8560
Epoch 3/30
100/100 [==============================] - 27s 269ms/step - loss: 0.4422 - acc: 0.7970 - val_loss: 0.3432 - val_acc: 0.8610

Epoch 30/30
100/100 [==============================] - 34s 341ms/step - loss: 0.2724 - acc: 0.8890 - val_loss: 0.2406 - val_acc: 0.9020

可视化损失和精度:

import matplotlib.pyplot as plt
history_dict = history.history

loss_values = history_dict["loss"]
val_loss_values = history_dict["val_loss"]
epochs = range(1, len(loss_values)+1)

plt.plot(epochs, loss_values, "bo", label="Training loss") ## "bo" 表示蓝色圆点
plt.plot(epochs, val_loss_values, "b", label="Validation loss") ## "bo" 表示蓝色实线
plt.title("Training and validation loss")
plt.xlabel("Epochs")
plt.ylabel("Loss")
plt.legend()

plt.show()

在这里插入图片描述

## 训练精度和验证精度
import matplotlib.pyplot as plt
history_dict = history.history

acc_values = history_dict["acc"]
val_acc_values = history_dict["val_acc"]
epochs = range(1, len(acc_values)+1)

plt.plot(epochs, acc_values, "bo", label="Training accuracy") ## "bo" 表示蓝色圆点
plt.plot(epochs, val_acc_values, "b", label="Validation accuracy") ## "bo" 表示蓝色实线
plt.title("Training and validation accuracy")
plt.xlabel("Epochs")
plt.ylabel("Accuracy")
plt.legend()

plt.show()

在这里插入图片描述

使用数据增强的方法得到的结果和不使用数据增强的方法得到的结果相比,验证精度基本一样,但是可以明显看出,使用数据增强的方法,模型的过拟合情况得到了明显的改善。

用法2: 模型微调

模型复用的另一种方法是 模型微调 (fine-tuning),它与特征提取互为补充。

关于模型微调的理解:

对于特征提取中被冻结的模型基,微调指的是将其顶部几层进行 “解冻”,并将 “解冻” 的层与新加部分进行联合训练。

之所以叫 “微调”,是因为该方法只是略微调整了所复用的模型,以便该模型学到的表示与实际问题更加相关。

1. 模型微调的步骤:

  1. 在已经训练好的基网络(base network)上添加自定义网络;
  2. 冻结基网络;
  3. 训练所添加的部分;
  4. 解冻基网络的一些层;
  5. 联合训练解冻的这些层和添加的部分;

(ps. 由于在前面特征提取时已经完成了前3个步骤,所以继续完成后2步)

conv_base.summary()
Model: "vgg16"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_1 (InputLayer)        [(None, 150, 150, 3)]     0         
                                                                 
 block1_conv1 (Conv2D)       (None, 150, 150, 64)      1792      
                                                                 
 block1_conv2 (Conv2D)       (None, 150, 150, 64)      36928     
                                                                 
 block1_pool (MaxPooling2D)  (None, 75, 75, 64)        0         
                                                                 
 block2_conv1 (Conv2D)       (None, 75, 75, 128)       73856     
                                                                 
 block2_conv2 (Conv2D)       (None, 75, 75, 128)       147584    
                                                                 
 block2_pool (MaxPooling2D)  (None, 37, 37, 128)       0         
                                                                 
 block3_conv1 (Conv2D)       (None, 37, 37, 256)       295168    
                                                                 
 block3_conv2 (Conv2D)       (None, 37, 37, 256)       590080    
                                                                 
 block3_conv3 (Conv2D)       (None, 37, 37, 256)       590080    
                                                                 
 block3_pool (MaxPooling2D)  (None, 18, 18, 256)       0         
                                                                 
 block4_conv1 (Conv2D)       (None, 18, 18, 512)       1180160   
                                                                 
 block4_conv2 (Conv2D)       (None, 18, 18, 512)       2359808   
                                                                 
 block4_conv3 (Conv2D)       (None, 18, 18, 512)       2359808   
                                                                 
 block4_pool (MaxPooling2D)  (None, 9, 9, 512)         0         
                                                                 
 block5_conv1 (Conv2D)       (None, 9, 9, 512)         2359808   
                                                                 
 block5_conv2 (Conv2D)       (None, 9, 9, 512)         2359808   
                                                                 
 block5_conv3 (Conv2D)       (None, 9, 9, 512)         2359808   
                                                                 
 block5_pool (MaxPooling2D)  (None, 4, 4, 512)         0         
                                                                 
=================================================================
Total params: 14,714,688
Trainable params: 0
Non-trainable params: 14,714,688
_________________________________________________________________

卷积基的架构如上所示,这里微调最后三个卷积层,即 从 input_1 一直到 block4_pool 都要冻结,block5_conv1, block5_conv2block5_conv3 要被训练。

2. 关于微调中目标层的选择:

  1. 选择比较靠输出的层,因为这些层编码的特征更专业化,微调这些更专业化的特征更有助于应对特定的问题;

  2. 微调的层数不要太多,一般是基网络的最后2-3层;

## 在上面 “使用数据增强提取特征” 的基础上微调模型

## 解冻基网络
conv_base.trainable = True

## 冻结 input_1 到 block4_pool 层
set_trainable = False
for layer in conv_base.layers:
    if layer.name == "block5_conv1":
        set_trainable = True
    if set_trainable:
        layer.trainable = True ## blcok5_conv1及后面的层仍旧保持解冻状态
    else:
        layer.trainable = False ## block5_conv1 之前的层都由解冻状态转变为冻结状态
## 微调模型
model.compile(loss="binary_crossentropy",
              optimizer=optimizers.RMSprop(learning_rate=1e-5),
              metrics=["acc"])

history = model.fit_generator(
    train_generator,
    steps_per_epoch=100,
    epochs=100,
    validation_data=validation_generator,
    validation_steps=50
)
Epoch 1/100


/var/folders/0w/m6x2g_g94sqfmg3k8dldpwgm0000gn/T/ipykernel_32812/3508158211.py:6: UserWarning: `Model.fit_generator` is deprecated and will be removed in a future version. Please use `Model.fit`, which supports generators.
  history = model.fit_generator(


100/100 [==============================] - 31s 302ms/step - loss: 0.2867 - acc: 0.8755 - val_loss: 0.2337 - val_acc: 0.9060
Epoch 2/100
100/100 [==============================] - 30s 299ms/step - loss: 0.2673 - acc: 0.8870 - val_loss: 0.2094 - val_acc: 0.9160

Epoch 100/100
100/100 [==============================] - 37s 366ms/step - loss: 0.0218 - acc: 0.9925 - val_loss: 0.3191 - val_acc: 0.9300

3. 可视化损失和精度:

import matplotlib.pyplot as plt
history_dict = history.history

loss_values = history_dict["loss"]
val_loss_values = history_dict["val_loss"]
epochs = range(1, len(loss_values)+1)

plt.plot(epochs, loss_values, "bo", label="Training loss") ## "bo" 表示蓝色圆点
plt.plot(epochs, val_loss_values, "b", label="Validation loss") ## "bo" 表示蓝色实线
plt.title("Training and validation loss")
plt.xlabel("Epochs")
plt.ylabel("Loss")
plt.legend()

plt.show()

在这里插入图片描述

## 训练精度和验证精度
import matplotlib.pyplot as plt
history_dict = history.history

acc_values = history_dict["acc"]
val_acc_values = history_dict["val_acc"]
epochs = range(1, len(acc_values)+1)

plt.plot(epochs, acc_values, "bo", label="Training accuracy") ## "bo" 表示蓝色圆点
plt.plot(epochs, val_acc_values, "b", label="Validation accuracy") ## "bo" 表示蓝色实线
plt.title("Training and validation accuracy")
plt.xlabel("Epochs")
plt.ylabel("Accuracy")
plt.legend()

plt.show()

在这里插入图片描述

曲线光滑化处理结果:

## 将曲线做平滑化处理 (将每个损失和精度都转化为指数移动平均值)
def smooth_curve(points, factor=0.8):
    smoothed_points = []
    for point in points:
        if smoothed_points:
            previous = smoothed_points[-1]
            smoothed_points.append(previous * factor + point * (1-factor))
        else:
            smoothed_points.append(point)
    return smoothed_points
import matplotlib.pyplot as plt
history_dict = history.history

loss_values = history_dict["loss"]
val_loss_values = history_dict["val_loss"]
epochs = range(1, len(loss_values)+1)

plt.plot(epochs, smooth_curve(loss_values), "bo", label="Training loss") ## "bo" 表示蓝色圆点
plt.plot(epochs, smooth_curve(val_loss_values), "b", label="Validation loss") ## "bo" 表示蓝色实线
plt.title("Training and validation loss")
plt.xlabel("Epochs")
plt.ylabel("Loss")
plt.legend()

plt.show()

在这里插入图片描述

## 训练精度和验证精度
import matplotlib.pyplot as plt
history_dict = history.history

acc_values = history_dict["acc"]
val_acc_values = history_dict["val_acc"]
epochs = range(1, len(acc_values)+1)

plt.plot(epochs, smooth_curve(acc_values), "bo", label="Training accuracy") ## "bo" 表示蓝色圆点
plt.plot(epochs, smooth_curve(val_acc_values), "b", label="Validation accuracy") ## "bo" 表示蓝色实线
plt.title("Training and validation accuracy")
plt.xlabel("Epochs")
plt.ylabel("Accuracy")
plt.legend()

plt.show()

在这里插入图片描述

可以看出,与使用数据增强提取特征的方法相比,通过模型微调的方法,其验证精度可以从 90% 左右上升到 94% 左右。

4. 模型在测试数据上的评估结果:

根据上图可以发现 epoch=20 左右的时候,模型验证损失达到最小,所以将epoch设为20重新训练模型,并在测试集上进行测试。

## 将epoch设为20,重新训练模型
model.compile(loss="binary_crossentropy",
              optimizer=optimizers.RMSprop(learning_rate=1e-5),
              metrics=["acc"])

history = model.fit_generator(
    train_generator,
    steps_per_epoch=100,
    epochs=20,
    validation_data=validation_generator,
    validation_steps=50
)
Epoch 1/20


/var/folders/0w/m6x2g_g94sqfmg3k8dldpwgm0000gn/T/ipykernel_32812/71092168.py:6: UserWarning: `Model.fit_generator` is deprecated and will be removed in a future version. Please use `Model.fit`, which supports generators.
  history = model.fit_generator(


100/100 [==============================] - 31s 302ms/step - loss: 0.0239 - acc: 0.9900 - val_loss: 0.3687 - val_acc: 0.9280
Epoch 2/20
100/100 [==============================] - 30s 300ms/step - loss: 0.0141 - acc: 0.9940 - val_loss: 0.2587 - val_acc: 0.9420
Epoch 3/20
100/100 [==============================] - 30s 300ms/step - loss: 0.0181 - acc: 0.9935 - val_loss: 0.3359 - val_acc: 0.9350

Epoch 20/20
100/100 [==============================] - 36s 364ms/step - loss: 0.0150 - acc: 0.9935 - val_loss: 0.3387 - val_acc: 0.9390
test_geneartor = test_datagen.flow_from_directory(
    test_dir,
    target_size=(150, 150),
    batch_size=20,
    class_mode="binary"
)

test_loss, test_acc = model.evaluate_generator(test_geneartor, steps=50)
print('test_acc: ', test_acc)
Found 1000 images belonging to 2 classes.


/var/folders/0w/m6x2g_g94sqfmg3k8dldpwgm0000gn/T/ipykernel_32812/2442981357.py:8: UserWarning: `Model.evaluate_generator` is deprecated and will be removed in a future version. Please use `Model.evaluate`, which supports generators.
  test_loss, test_acc = model.evaluate_generator(test_geneartor, steps=50)


test_acc:  0.9320000410079956

当epoch=20时,根据训练集重新训练的模型在测试集上的精度达到93.2%

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/689915.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ResNet网络结构

Deep Residual Learning for Image Recognition 论文:https://arxiv.org/abs/1512.03385 代码:ResNet网络详解及Pytorch代码实现(超详细帮助你掌握ResNet原理及实现)_basic block结构图_武晨的博客-CSDN博客 【DL系列】ResNet网…

前端Vue自定义签到积分获取弹框抽取红包弹框 自定义弹框内容 弹框顶部logo

前端Vue自定义签到积分获取弹框抽取红包弹框 自定义弹框内容 弹框顶部logo&#xff0c; 下载完整代码请访问uni-app插件市场地址&#xff1a;https://ext.dcloud.net.cn/plugin?id13204 效果图如下&#xff1a; # cc-downloadDialog #### 使用方法 使用方法 <!-- show&…

用VSCode开发的Vue项目请求HBuilder项目的JSON数据

在学Vue之前采用HBuilder学习了HTML,CSS.JavaScript&#xff0c;jQuery&#xff0c;AJAX&#xff0c;最方便的就是可以请求项目中的JSON数据&#xff0c;当然也可以请求【聚合数据】的数据。 现在用VSCode开发&#xff0c;去访问HBuilder发布的项目中的json数据&#xff0c;因…

chatgpt赋能python:Python计算器程序代码:一种简单却强大的工具

Python计算器程序代码&#xff1a;一种简单却强大的工具 如果你是一名计算机编程爱好者&#xff0c;那你一定不会陌生于Python编程语言。Python是如今最受欢迎的编程语言之一&#xff0c;它简单易学、功能强大&#xff0c;也有着庞大的社区支持&#xff0c;使得它成为了很多人…

嵌入式ppt

第二章 第五章 第六章 第七章 第八章 第九章 第十章 考点 条件编译 volatile、static、 union、 struct、 const指针 堆与栈的不同点 3.功能模块应用题 (1) GPIO 的应用:流水灯的电路及软件编码、驱动数码管的电路及编码。 (2)外部中断的应用:电路及回调函数编码。 (3) …

云原生安全取决于开源

本文首发微信公众号网络研究院&#xff0c;关注获取更多。 Kubernetes 和 K3S 等技术是云原生计算的成功和开源力量的代名词。他们在竞争中大获全胜绝非偶然。当企业寻求安全的云原生环境时&#xff0c;开源是难题中的关键部分。 工具法则是众所周知的认知偏差。当你只有一把…

openeuler22.03系统salt-minion启动报“Invalid version: ‘cpython‘“错的问题处理

某日&#xff0c;检查发现一台openeuler22.03 SP1系统的服务器上之前正常运行的saltstack客户端minion未运行&#xff0c;查看服务状态&#xff0c;报"Invalid version: cpython"错&#xff0c;无法正常运行&#xff0c;本文记录问题处理过程。 一、检查salt-minion…

【Nginx】第三章 Nginx常用的命令和配置文件

第3章 Nginx常用的命令和配置文件 3.1 nginx常用的命令 &#xff08;1&#xff09;启动命令 在/usr/local/nginx/sbin目录下执行 ./nginx &#xff08;2&#xff09;关闭命令 在/usr/local/nginx/sbin目录下执行 ./nginx -s stop &#xff08;3&#xff09;重新加载命令…

docker报错 driver failed programming external connectivity on e

Error response from daemon: driver failed programming external connectivity on e ndpoint mj 原因&#xff1a;在我们启动了Docker后&#xff0c;我们再对防火墙firewalld进行操作&#xff0c;就会发生上述报错&#xff0c; 详细原因&#xff1a;docker服务启动时定义的…

分别用最小二乘法和梯度下降法实现线性回归

下面代码中包含了两种方法 import numpy as npnp.random.seed(1234)x np.random.rand(500, 3) # x为数据&#xff0c;500个样本&#xff0c;每个样本三个自变量 y x.dot(np.array([4.2, 5.7, 10.8])) # y为标签&#xff0c;每个样本对应一个y值# 最小二乘法 class LR_LS():d…

LENOVO联想笔记本拯救者Legion R7000P APH8 2023款(82Y9)原厂Windows11系统原装出厂状态预装系统

lenovo联想笔记本电脑&#xff0c;拯救者Legion R7000P APH8(2023款)(82Y9)原装出厂Windows11系统安装&#xff0c;预装系统重装镜像&#xff0c;恢复出厂状态 系统自带所有驱动、出厂主题壁纸LOGO、Office办公软件、联想电脑管家等预装程序 所需要工具&#xff1a;16G或以上…

element ui - el-select 手动设置高度

el-select 手动设置高度 场景代码 场景 当我们的页面想要手动设置 element ui 中 el-select 的高度时&#xff0c;如果只是通过设置 el-select 的 height 属性时&#xff0c;会发现调整无效。 继续对 el-select 中的 input 元素 .el-input__inner 设置。会发现高度生效了&…

机器视觉硬件选型-机器视觉三大技术之一打光(图像采集技术)

机器视觉halcon-胶水轮廓检测 针对被测物的不同特征,要用不同打光方式,才可以突出被测物,便于图像处技术进一步处理。 机器视觉作为当前的热门行业,是计算机视觉的延伸,集结了光学、机械、电子、计算机软硬件等各方面技术,旨在于将所需求的图像特征提取出来,以方便视觉系…

读发布!设计与部署稳定的分布式系统(第2版)笔记13_断路器与舱壁

1. 电路保险丝 1.1. 保险丝通过自身率先失效&#xff0c;控制整体的系统失效方式 1.2. 当遇到电阻时&#xff0c;电流产生的热量与电流强度的平方和电阻的乘积&#xff08;I^2R&#xff09;成正比 1.3. 在房子着火前先行熔断&#xff0c;切断电路并避免火灾 1.4. 民用保险丝…

HOT22-相交链表

leetcode原题链接&#xff1a;相交链表 题目描述 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结…

可视化低代码编程平台项目

后端Spring BootMySQL 前端Vue 同学通过这个项目练手&#xff0c;简历上写出来也蛮有亮点的。 技术栈比较全面&#xff0c; 项目可以提高公司的开发效率&#xff0c;特别是方便产品经理或者业务线人员直接可视化生成UI

java之路——带你了解springboot框架与其基本使用

文章目录 一、springboot的发展背景二、什么是springboot三、springboot的地位四、开发步骤 一、springboot的发展背景 要了解springboot&#xff0c;我们先要了解Spring Boot的发展背景。 Spring Boot的发展背景可以追溯到Spring Framework的诞生和演进过程。 首先&#xff…

Linux常用命令——free命令

在线Linux命令查询工具 free 显示内存的使用情况 补充说明 free命令可以显示当前系统未使用的和已使用的内存数目&#xff0c;还可以显示被内核使用的内存缓冲区。 语法 free(选项)选项 -b # 以Byte为单位显示内存使用情况&#xff1b; -k # 以KB为单位显示内存使用情况…

【Docker】Exited 139解决Window下docker启动oracle11g失败Exited 139

前几天&#xff0c;在docker安装了oracle11&#xff0c;安装非常简单&#xff0c;但是启动的时候启动不起来&#xff0c;且没有任何log日志输出&#xff01; docker 拉取安装oracle11 docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g安装完成后启动oracle …

Nature Biomedical Engineering --利用白细胞“吃掉”实体瘤

癌症仍然是美国死亡率最高的疾病之一&#xff0c;每年导致的死亡人数超过60万人。形成实体肿瘤的癌症&#xff0c;如乳房、大脑或皮肤肿瘤&#xff0c;尤其难以治疗。外科手术通常是对抗实体肿瘤的第一道防线。但是&#xff0c;手术可能无法完全清除癌细胞&#xff0c;残留的细…