上次(2017年1月10日),我学习了一个2级分类的神经网络,可以微调VGG 16并对狗或猫进行分类。 这个时候,我想学习一个神经网络,用同样的方法对17种花进行分类。 它看起来像以前的应用程序版本。 我不知道结果会如何,因为这个实验是原创的,但是它进行得很顺利,我一起尝试了。
知识库:17flowers
所使用的数据是牛津大学提出的VGG 16的17类别花数据集。 下面的17种花的图像数据。 这是非常美丽的。

与之前的实验(2017年1月4日)相同,甚至向日葵也不能被默认的VGG 16分类,但通过微调VGG 16,可以将这17种花(向日葵)分类, 我想知道? 让我们试试吧!
设置
下载名为17flowers.tgz的文件。 当你解压缩后,每个类中的80张图片,从 jpg 目录中的image_0001.jpg到image_1360.jpg,总共包含1360张图片。 尽管1360张图片是从卷积神经网络的头开始学习的意想不到的数据的数量,但是这一次使用转换学习足以使用少量的数据来调整VGG 16。
由于我们有17个类,每个类有80张,共1360张图片,但是我不知道每张图是哪个标签。 我创建了一个名为labels.txt的文件,其中标签分配如下所示,通过与示例图像进行比较。 例如,第一行意味着从image_0001.jpg到image_0080.jpg是郁金香。
1 80 Tulip 81 160 Snowdrop 161 240 LilyValley 241 320 Bluebell 321 400 Crocus 401 480 Iris 481 560 Tigerlily 561 640 Daffodil 641 720 Fritillary 721 800 Sunflower 801 880 Daisy 881 960 ColtsFoot 961 1040 Dandelion 1041 1120 Cowslip 1121 1200 Buttercup 1201 1280 Windflower 1281 1360 Pansy
code
首先,为了方便从Keras加载,请使用下面的setup.py分割图像文件。 在每堂课中,我们分了70个训练数据和10个测试数据。 就像狗猫分类的情况一样,如果你将一个类名添加到一个子目录中,它会自动识别它。 我使用上面的labels.txt来命名这个类。
import os import shutil import random IN_DIR = 'jpg' TRAIN_DIR = 'train_images' TEST_DIR = 'test_images' if not os.path.exists(TRAIN_DIR): os.mkdir(TRAIN_DIR) if not os.path.exists(TEST_DIR): os.mkdir(TEST_DIR) # name => (start idx, end idx) flower_dics = {} with open('labels.txt') as fp: for line in fp: line = line.rstrip() cols = line.split() assert len(cols) == 3 start = int(cols[0]) end = int(cols[1]) name = cols[2] flower_dics[name] = (start, end) # 花ごとのディレクトリを作成 for name in flower_dics: os.mkdir(os.path.join(TRAIN_DIR, name)) os.mkdir(os.path.join(TEST_DIR, name)) # jpgをスキャン for f in sorted(os.listdir(IN_DIR)): # image_0001.jpg => 1 prefix = f.replace('.jpg', '') idx = int(prefix.split('_')[1]) for name in flower_dics: start, end = flower_dics[name] if idx in range(start, end + 1): source = os.path.join(IN_DIR, f) dest = os.path.join(TRAIN_DIR, name) shutil.copy(source, dest) continue # 訓練データの各ディレクトリからランダムに10枚をテストとする for d in os.listdir(TRAIN_DIR): files = os.listdir(os.path.join(TRAIN_DIR, d)) random.shuffle(files) for f in files[:10]: source = os.path.join(TRAIN_DIR, d, f) dest = os.path.join(TEST_DIR, d) shutil.move(source, dest) os import shutil import random IN_DIR = 'jpg' TRAIN_DIR = 'train_images' TEST_DIR = 'test_images' if not os.path.exists(TRAIN_DIR): os.mkdir(TRAIN_DIR) if not os.path.exists(TEST_DIR): os.mkdir(TEST_DIR) # name => (start idx, end idx) flower_dics = {} with open('labels.txt') as fp: for line in fp: line = line.rstrip() cols = line.split() assert len(cols) == 3 start = int(cols[0]) end = int(cols[1]) name = cols[2] flower_dics[name] = (start, end) # 花ごとのディレクトリを作成 for name in flower_dics: os.mkdir(os.path.join(TRAIN_DIR, name)) os.mkdir(os.path.join(TEST_DIR, name)) # jpgをスキャン for f in sorted(os.listdir(IN_DIR)): # image_0001.jpg => 1 prefix = f.replace('.jpg', '') idx = int(prefix.split('_')[1]) for name in flower_dics: start, end = flower_dics[name] if idx in range(start, end + 1): source = os.path.join(IN_DIR, f) dest = os.path.join(TRAIN_DIR, name) shutil.copy(source, dest) continue # 訓練データの各ディレクトリからランダムに10枚をテストとする for d in os.listdir(TRAIN_DIR): files = os.listdir(os.path.join(TRAIN_DIR, d)) random.shuffle(files) for f in files[:10]: source = os.path.join(TRAIN_DIR, d, f) dest = os.path.join(TEST_DIR, d) shutil.move(source, dest)
code
1.从头开始学习小型卷积神经网络
让我们来学习一个等价于LeNet的小型卷积神经网络作为这次和以前的时间* 1的基线。 首先建立一个模型。
model = Sequential() model.add(Convolution2D(32, 3, 3, input_shape=(img_rows, img_cols, channels))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Convolution2D(32, 3, 3)) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Convolution2D(64, 3, 3)) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Flatten()) model.add(Dense(64)) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(nb_classes)) model.add(Activation('softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) 32, 3, 3, input_shape=(img_rows, img_cols, channels))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Convolution2D(32, 3, 3)) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Convolution2D(64, 3, 3)) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Flatten()) model.add(Dense(64)) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(nb_classes)) model.add(Activation('softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
code
我已经有很多次了,没有遇到任何困难。 由于这次是17类的多类分类,我们使用categorical_crossentropy作为损失函数。
当仅提供图像文件时,使用ImageDataGenerator读取数据很方便。 我们还使用shear_range,zoom_range和horizontal_flip进行数据扩展(2016/12/12),但是如果您仔细确定数据的特征并仔细确定,可能会更准确。
# ディレクトリの画像を使ったジェネレータ train_datagen = ImageDataGenerator( rescale=1.0 / 255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True) test_datagen = ImageDataGenerator(rescale=1.0 / 255) train_datagen = ImageDataGenerator( rescale=1.0 / 255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True) test_datagen = ImageDataGenerator(rescale=1.0 / 255)
code
实际上使用上述设置创建一个生成器。 只需指定包含图像文件的目录。 在这里,当你自己指定类的时候,你可以按顺序分配类标签。 我无法掌握什么color_mode和class_mode使用,但rgb和分类看起来不错。
classes = ['Tulip', 'Snowdrop', 'LilyValley', 'Bluebell', 'Crocus', 'Iris', 'Tigerlily', 'Daffodil', 'Fritillary', 'Sunflower', 'Daisy', 'ColtsFoot', 'Dandelion', 'Cowslip', 'Buttercup', 'Windflower', 'Pansy'] train_generator = train_datagen.flow_from_directory( directory='train_images', target_size=(img_rows, img_cols), color_mode='rgb', classes=classes, class_mode='categorical', batch_size=batch_size, shuffle=True) test_generator = test_datagen.flow_from_directory( directory='test_images', target_size=(img_rows, img_cols), color_mode='rgb', classes=classes, class_mode='categorical', batch_size=batch_size, shuffle=True) 'Tulip', 'Snowdrop', 'LilyValley', 'Bluebell', 'Crocus', 'Iris', 'Tigerlily', 'Daffodil', 'Fritillary', 'Sunflower', 'Daisy', 'ColtsFoot', 'Dandelion', 'Cowslip', 'Buttercup', 'Windflower', 'Pansy'] train_generator = train_datagen.flow_from_directory( directory='train_images', target_size=(img_rows, img_cols), color_mode='rgb', classes=classes, class_mode='categorical', batch_size=batch_size, shuffle=True) test_generator = test_datagen.flow_from_directory( directory='test_images', target_size=(img_rows, img_cols), color_mode='rgb', classes=classes, class_mode='categorical', batch_size=batch_size, shuffle=True)
code
在生成器生成时,使用生成器生成的图像的四维张量训练 模型 。 这和上次一样。
history = model.fit_generator( train_generator, samples_per_epoch=samples_per_epoch, nb_epoch=nb_epoch, validation_data=test_generator, nb_val_samples=nb_val_samples) save_history(history, os.path.join(result_dir, 'history_smallcnn.txt'))'history_smallcnn.txt'))
code
学习过程中的损失和准确性保存在一个文件中,以便以后参考。
2、VGG-16的Fine-tuning
接下来,让我们以类似上次的感觉来微调VGG 16。 只对最后的卷积层块和完整的连接层重新调整权重。
# VGG16モデルと学習済み重みをロード # Fully-connected層(FC)はいらないのでinclude_top=False) input_tensor = Input(shape=(img_rows, img_cols, 3)) vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor) # FC層を構築 top_model = Sequential() top_model.add(Flatten(input_shape=vgg16.output_shape[1:])) top_model.add(Dense(256, activation='relu')) top_model.add(Dropout(0.5)) top_model.add(Dense(nb_classes, activation='softmax')) # VGG16とFCを接続 model = Model(input=vgg16.input, output=top_model(vgg16.output)) # 最後のconv層の直前までの層をfreeze for layer in model.layers[:15]: layer.trainable = False # Fine-tuningのときはSGDの方がよい model.compile(loss='categorical_crossentropy', optimizer=optimizers.SGD(lr=1e-4, momentum=0.9), metrics=['accuracy']) # Fully-connected層(FC)はいらないのでinclude_top=False) input_tensor = Input(shape=(img_rows, img_cols, 3)) vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor) # FC層を構築 top_model = Sequential() top_model.add(Flatten(input_shape=vgg16.output_shape[1:])) top_model.add(Dense(256, activation='relu')) top_model.add(Dropout(0.5)) top_model.add(Dense(nb_classes, activation='softmax')) # VGG16とFCを接続 model = Model(input=vgg16.input, output=top_model(vgg16.output)) # 最後のconv層の直前までの層をfreeze for layer in model.layers[:15]: layer.trainable = False # Fine-tuningのときはSGDの方がよい model.compile(loss='categorical_crossentropy', optimizer=optimizers.SGD(lr=1e-4, momentum=0.9), metrics=['accuracy'])
code
这和上次几乎一样。 不同之处在于,FC层的输出被分为17类,因此它使用softmax作为激活函数,并且使用categorical_crossentropy作为损失函数。 由于它几乎相同,省略它。
实验结果:
损失和准确性的历史如下。 在小卷积神经网络中,分类 精度 仅为60%左右,但可以确认在微调VGG时分类精度跳跃到85%左右。


虽然是16级的VGG 16,但在1000级中没有向日葵,似乎可以学习用于花卉分类的特征提取器。
花卉分类的例子

% python predict.py test_images/Sunflower/image_0724.jpg input: test_images/Sunflower/image_0724.jpg ('Sunflower', 0.9999969) ('ColtsFoot', 1.3097971e-06) ('Iris', 8.8473638e-07) ('Tigerlily', 6.5053348e-07) ('Buttercup', 1.2474243e-07)
code

% python predict.py test_images/Iris/image_0410.jpg input: test_images/Iris/image_0410.jpg ('Iris', 0.99993575) ('Crocus', 1.9791674e-05) ('Sunflower', 1.734318e-05) ('Buttercup', 9.1189122e-06) ('Fritillary', 4.9292394e-06)
code

% python predict.py test_images/Dandelion/image_0966.jpg input: test_images/Dandelion/image_0966.jpg ('Dandelion', 0.99502832) ('ColtsFoot', 0.0034611411) ('Sunflower', 0.0014925624) ('Tigerlily', 5.2598648e-06) ('Buttercup', 4.0573868e-06)
code

% python predict.py test_images/Windflower/image_1219.jpg input: test_images/Windflower/image_1219.jpg ('Windflower', 0.99989629) ('Pansy', 4.6885198e-05) ('Daisy', 3.5976835e-05) ('LilyValley', 8.592202e-06) ('Snowdrop', 5.5862884e-06)
code

% python predict.py test_images/Daisy/image_0807.jpg input: test_images/Daisy/image_0807.jpg ('Daisy', 0.99801069) ('Sunflower', 0.0019772816) ('ColtsFoot', 1.0563146e-05) ('Pansy', 8.2547245e-07) ('Windflower', 4.5572747e-07)
code
雏菊也是正确的。
当你看到如此美丽的图像时,张力会上升。 这是一个非常有趣的实验。
接下来我要深化卷积神经网络滤波器的可视化方法,并把它连接到Deep Dream。 现在有些东西很强大(^ ^;
数据集:http://www.robots.ox.ac.uk/~vgg/data/flowers/17/
相关知识
【PyTorch】PyTorch搭建基础VGG16网络
利用VGG16做花数据集的识别
Keras复现VGG16及实现花卉分类
VGG16模型进行十种花卉分类与识别(pycharm+python3.6解释器)
利用VGG16网络模块进行迁移学习,实操(附源码)
基于VGG16网络的花卉识别
用VGG16对102种鲜花分类
基于卷积神经网络的花卉识别系统,resnet50,vgg16模型(pytorch框架,python代码)
25か国の25の国の花
美しい家の装飾のための卸売11本の白いバラの花
网址: VGG16のFine https://m.huajiangbk.com/newsview2599854.html
| 上一篇: ML.NET 样例项目指南:从入 |
下一篇: Python怎么实现识别花卉种类 |