利用VGG16做花数据集的识别

前言

刚完成机器视觉的作业(利用预训练好的模型,对花的数据集进行识别),所以就记录一下。本次实验中,我使用的是keras的vgg16模型,然后再添加了三层全连接层对花进行识别,50个epoch后在验证集中的准确率为87.63,不算很好,但有由于确实太耗费时间了,就不太想去重新调参然后训练了,就只能勉强接受了。
我的实验数据是直接在kaggle上下的,链接:Flowers Recognition

VGG16

VGG是Oxford的Visual Geometry Group的组提出的。该网络是在ILSVRC 2014上的相关工作,主要工作是证明了增加网络的深度能够在一定程度上影响网络最终的性能。VGG16共包含16个卷积层(Convolutional Layer),3个全连接层(Fully connected Layer),以及5个池化层(Pool layer),其中,卷积层和全连接层具有权重系数,因此也被称为权重层,总数目为13+3=16,这即是VGG16中16的来源。
VGG16的突出特点是:
1.卷积层均采用相同的卷积核参数。卷积层均表示为conv3-XXX,其中conv3说明该卷积层采用的卷积核的尺寸(kernel size)是3,即宽(width)和高(height)均为3,3*3是很小的卷积核尺寸,结合其它参数(步幅stride=1,填充方式padding=same),这样就能够使得每一个卷积层(张量)与前一层(张量)保持相同的宽和高。XXX代表卷积层的通道数。
2.池化层均采用相同的池化核参数。池化层的参数均为2×。
3.模型是由若干卷积层和池化层堆叠(stack)的方式构成,比较容易形成较深的网络结构(在2014年,16层已经被认为很深了)。
VGG16网络结构:
利用VGG16做花数据集的识别_第1张图片

实验源码及结果展示

源码

其实也很简单,就是直接在keras上调取VGG16模型就行了,不过模型比较大,可能需要下载一会。

import os
import cv2
import random
from tensorflow.python.keras.applications import VGG16, VGG19
from tensorflow.python.keras import Sequential
from tensorflow.python.keras import layers
from tensorflow.python.keras.optimizers import SGD
from tensorflow.python.keras.models import Model
import matplotlib.pyplot as plt
import numpy as np

def get_data():
    data = []
    labels = []
    types = os.listdir('./flowers')
    for name in types:
        flowers = os.listdir('./flowers' + '/' + name)
        for flower in flowers:
            img = cv2.imread('./flowers' + '/' + name + '/' + flower)
            img = cv2.resize(img, (240, 320))
            data.append(img)
            labels.append(name)
    return data, labels
if __name__ == '__main__':
    type = {"daisy": 0, "dandelion": 1, "rose": 2, "sunflower": 3, "tulip": 4}
    data, labels = get_data()
    # 打包数据并打乱
    upset = list(zip(data, labels))
    random.shuffle(upset)
    data[:], labels[:] = zip(*upset)
    train_data = np.array([data[i] for i in range(len(labels)) if i % 9 > 1])
    train_label = [labels[i] for i in range(len(labels)) if i % 9 > 1]
    test_data = np.array([data[i] for i in range(len(labels)) if i % 9 <= 1])
    test_label = [labels[i] for i in range(len(labels)) if i % 9 <= 1]
    train_labels = np.zeros((len(train_label), 5))
    test_labels = np.zeros((len(test_label), 5))
    for i in range(len(train_labels)):
        train_labels[i][type[train_label[i]]] = 1
    for i in range(len(test_labels)):
        test_labels[i][type[test_label[i]]] = 1

    sgd = SGD(lr=0.001, decay=1e-6, momentum=0.9, nesterov=True)


    model_vgg16 = VGG16(weights='imagenet', include_top=False, input_shape=(320, 240, 3))
    for layer in model_vgg16.layers:
        layer.trainable = False
    model = layers.Flatten(name='flatten')(model_vgg16.output)
    model = layers.Dense(64, activation='relu')(model)
    model = layers.BatchNormalization()(model)
    model = layers.Dropout(0.5)(model)
    model = layers.Dense(32, activation='relu')(model)
    model = layers.BatchNormalization()(model)
    model = layers.Dropout(0.5)(model)
    model = layers.Dense(5, activation='softmax')(model)
    model = Model(inputs=model_vgg16.input, outputs=model, name='vgg16')


    model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
    history = model.fit(train_data, train_labels, batch_size=256, epochs=50, validation_data=(test_data, test_labels))
    plt.plot(history.history['accuracy'], label='training acc')
    plt.plot(history.history['val_accuracy'], label='val acc')
    plt.title('model accuracy')
    plt.ylabel('accuracy')
    plt.xlabel('epoch')
    plt.show()
    plt.close()
    plt.plot(history.history['loss'], label='training loss')
    plt.plot(history.history['val_loss'], label='val loss')
    plt.title('model loss')
    plt.ylabel('loss')
    plt.xlabel('epoch')
    plt.show()
    plt.close()

实验结果

在经过50个epoch训练后,实验的训练精度达到了96.91,而验证精度为87.63.
Epoch 50/50
3361/3361 [==============================] - 46s 14ms/sample - loss: 0.1543 - accuracy: 0.9691 - val_loss: 0.3734 - val_accuracy: 0.8763
从模型准确度和损失图可以看出,在经过20个epoch左右,验证集的准确度和损失变大就很小了,没太多了提升空间了,最后验证集精度也基本稳定在87-88了,验证损失停留在在0.37 -0.38。本来想多做几组实验对照一下,但由于需要的计算时间的资源太大就放弃了,目前的效果也就还行。
利用VGG16做花数据集的识别_第2张图片
利用VGG16做花数据集的识别_第3张图片

你可能感兴趣的:(机器视觉,卷积,深度学习,python)