基于Tensorflow的Quick Draw图像分类

简介: Google的“Quick Draw”数据集是一个开源的数据集。该数据集共有345个类别,共5000万张图片,所有这些图片都是由参与挑战的1500万名用户在20s或者更短的时间内绘制完成。

@toc

1、数据集介绍

  Google的“Quick Draw”数据集是一个开源的数据集。该数据集共有345个类别,共5000万张图片,所有这些图片都是由参与挑战的1500万名用户在20s或者更短的时间内绘制完成。

  这里将在10个类别的100万张图片上进行学习,为了测试模型的辨别力,特意选择了一些比较相似的图像

2、Quick Draw图像分类

2.1 数据获取

  从Google 下载数据,并将其保存至名为"data_files"的空目录下面。

  具体操作如下:访问地址https://console.cloud.goole.com/storage/browser/quickdraw_dataset/full/numpy_bitmap?pli=1,下载10个数据集,保存到"data_files"目录下面。

  下载之后重命名文件,去掉文件前缀,修改之后如下所示:

image-20220709212549298

2.2 设置环境

  首先,导入依赖项:

import tensorflow as tf
from tensorflow.keras.datasets import mnist
import numpy as np
import h5py
from sklearn.model_selection import train_test_split
import os
from os import walk

  新建一些常量,以便后续使用

batch_size = 128
img_rows, img_cols = 28, 28       # image dims

  用os.walk方法从"data_files"文件夹中提取数据集的文件名。

注意:文件名保存在列表变量filenames中
data_path = "data_files/" # folder for image files
for (dirpath, dirnames, filenames) in walk(data_path):
    pass # file names accumulate in list  'filenames'
print(filenames)

image-20220709212932614

  要使用不同的图像运行此示例,只需将10个不同的文件下载到data_files文件夹中。

  下一步,定义模型所需的其他值。图像总数可在此处更改。

#图像总数num_images
num_images = 1000000 ### 如果出现内存问题,可减少此数字
num_files = len(filenames) # *** 共包含10个文件 ***
images_per_category = num_images//num_files
seed = np.random.randint(1, 10e7)
i=0
print(images_per_category)

image-20220709213406526

2.3 数据预处理

  接着将图像加载到内存中。

  遍历所有文件,在获得文件路径后,加载该文件或图像集(x)。然后,将x转换为浮点数,除以255,令其值在0-1范围内。之后,为这组图像x创建一个标签y。

  第一组图像,标签为0;下一组图像,标签为1;以知道最后一组图像,标签为9,标签y由变量i控制递增。

  接下来,对集合x和y进行切片,将图像和标签还原给x和y。之后,将x和y累加到x_all和y_all中。如果是第一次循环(即i>0),则将x和y拼接到x_all和y_all上。当该循环终止时,x_all和y_all将分别包含图像和图像的标签。

for file in filenames:
    file_path = data_path + file
    x = np.load(file_path)
    x = x.astype('float32')    ##图片标准化
    x /= 255.0
    y = [i] * len(x) # 为图片创建数字标签

    x = x[:images_per_category] # 获取图像岩本
    y = y[:images_per_category] # 获取标签样本

    if i == 0:  #第一次循环时创建两个新列表
        x_all = x
        y_all = y
    else:  #将x和y拼接到x_all和y_all两个列表当中
        x_all = np.concatenate((x,x_all), axis=0)
        y_all = np.concatenate((y,y_all), axis=0)
    i += 1
#x_all和y_all将分别包含图像和图像的标签
print(len(x_all))
print(len(y_all))

image-20220709213425349

  用sklearn.model.selection中的train_test_split方法,将训练集和测试集以8:2的比例进行分割,x_train和x_test分别代表训练集和测试集。

#将数据数组拆分为训练集和测试集 8:2
x_train, x_test, y_train, y_test = train_test_split(x_all, y_all, test_size=0.2, random_state=42)

  由于需要使用卷积神经网络进行图像分类,需将x_train和y_train变形为原来的图像大小28*28*1,前两个维度是图像的高度和宽度(单位为像素),第三个维度表示每个像素的灰度

#由于需要使用卷积神经网络进行图像分类,需将x_train和y_train变形为原来的图像大小
# 28*28*1,前两个维度是图像的高度和宽度(单位为像素),第三个维度表示每个像素的灰度
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
# 创建input_shape,该参数将用于convNet的第一层
input_shape = (img_rows, img_cols, 1)
print(x_train.shape)
print(x_test.shape)

image-20220709213633405

  对y_train和y_test标签进行独热编码

#对y_train和y_test标签进行独热编码
y_train = tf.keras.utils.to_categorical(y_train, num_files)
y_test = tf.keras.utils.to_categorical(y_test, num_files)

  进一步以9:1的比例分割为训练集和验证集

print('分割前:')
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
#进一步以9:1的比例分割为训练集和验证集
x_train, x_valid, y_train, y_valid = train_test_split(x_train, y_train, test_size=0.1, random_state=42)
print('分割后:')
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
print(x_valid.shape[0],'valid samples')

image-20220709213702533

2.4 模型创建

  该模型共有两个卷积层(均使用ReLU激活函数),卷积层之后均插入了最大池化层和dropout层;后接一个Flatten层将卷积层的输出展平为一维向量;之后是一个一维全连接层(同样使用ReLU激活函数);最后是一个dropout层和一个10单元的softmax层。softmax层输出单元的激活给出了该图像属于各图像类别的概率。该人工神经网络有足够的实验空间。

#模型定义
model = tf.keras.Sequential()

model.add(tf.keras.layers.Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=input_shape))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2)))
model.add(tf.keras.layers.Dropout(0.25))

model.add(tf.keras.layers.Conv2D(64, (3, 3), activation='relu'))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2)))
model.add(tf.keras.layers.Dropout(0.25))

model.add(tf.keras.layers.Flatten())

model.add(tf.keras.layers.Dense(128, activation='relu'))
model.add(tf.keras.layers.Dropout(0.5))

#softmax层输出单元的激活给出了该图像属于各图像类别的概率
model.add(tf.keras.layers.Dense(num_files, activation='softmax'))#num_files=10
print("Compiling...........")

image-20220709213733519

2.5 模型训练和测试

  现在可以使用fit方法来训练模型。要注意验证机的使用方法与训练集不同。callbacks列表可用于保存最佳模型或在学习停止时(前提是所有更新轮次尚未完成)。

epochs=10 # for testing, for training use 25
callbacks=[tf.keras.callbacks.TensorBoard(log_dir = os.path.join('tb_log_dir'), histogram_freq = 0)]
model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          callbacks=callbacks,
          verbose=1,
          validation_data=(x_valid, y_valid))
这里由于硬件跟不上,我只设置epochs=10,显卡好的就设置25或更大。

image-20220709214447028

  为确定模型的准确度,可采用evaluate方法。需要注意的是,此次评估使用了测试集。

#评估模型
score = model.evaluate(x_test, y_test, verbose=1)

print('Test loss:', score[0])
print('Test accuracy:', score[1])

image-20220709214510334

  还可以对测试图像进行随机采样,可通过以下代码查看模型效果。从文件名中提取标签,输出该标签以供参照,随后成对输出预测标签与实际标签。

#对测试图像随机采样
import os
labels = [os.path.splitext(file)[0] for file in filenames]
print(labels)
print("\nFor each pair in the following, the first label is predicted, second is actual\n")
for i in range(20):
    t = np.random.randint(len(x_test) )
    x1= x_test[t]
    x1 = x1.reshape(1,28,28,1)
    p = model.predict(x1)
    print("-------------------------")
    print(labels[np.argmax(p)])
    print(labels[np.argmax(y_test[t])])
    print("-------------------------")

image-20220709214700081

image-20220709214710070

2.6 模型保存、加载和重新测试

  保存模型

#保存模型
model.save("./QDrawModel.h5")

  删除模型

del model

  重新加载模型

from tensorflow.keras.models import load_model
import numpy as np
#加载保存的模型
model = load_model('./QDrawModel.h5')
model.summary()

image-20220709214954260

  打印出20个时装的测试样本,确认神经网络工作正常。

#打印出20个时装的测试样本,验证神经网络是否正常工作
print("For each pair, first is predicted, second is actual")
for i in range(20):
    t = np.random.randint(len(x_test))
    x1= x_test[t]
    x1 = x1.reshape(1,28,28,1)
    p = model.predict(x1)
    print("-------------------------")
    print(labels[np.argmax(p)])
    print(labels[np.argmax(y_test[t])])
    print("-------------------------")

image-20220709215033808

目录
相关文章
|
7月前
|
机器学习/深度学习 存储 TensorFlow
Azure 机器学习 - 使用 Visual Studio Code训练图像分类 TensorFlow 模型
Azure 机器学习 - 使用 Visual Studio Code训练图像分类 TensorFlow 模型
87 0
|
算法 数据挖掘 TensorFlow
tensorflow+k-means聚类 简单实现猫狗图像分类
利用k-means聚类实现数据集的分类
337 0
tensorflow+k-means聚类 简单实现猫狗图像分类
|
机器学习/深度学习 TensorFlow 算法框架/工具
【深度学习】基于tensorflow的服装图像分类训练(数据集:Fashion-MNIST)
【深度学习】基于tensorflow的服装图像分类训练(数据集:Fashion-MNIST)
275 0
|
TensorFlow 算法框架/工具
keras和tensorflow猫狗图像分类
keras和tensorflow猫狗图像分类
|
Ubuntu TensorFlow 算法框架/工具
ResNet实战:tensorflow2.X版本,ResNet50图像分类任务(小数据集)
本例提取了植物幼苗数据集中的部分数据做数据集,数据集共有12种类别,今天我和大家一起实现tensorflow2.X版本图像分类任务,分类的模型使用ResNet50。 通过这篇文章你可以学到: 1、如何加载图片数据,并处理数据。 2、如果将标签转为onehot编码 3、如何使用数据增强。 4、如何使用mixup。 5、如何切分数据集。 6、如何加载预训练模型。
1355 0
ResNet实战:tensorflow2.X版本,ResNet50图像分类任务(小数据集)
|
TensorFlow 算法框架/工具 计算机视觉
ResNet实战:tensorflow2.0以上版本,使用ResNet50实现图像分类任务
ResNet实战:tensorflow2.0以上版本,使用ResNet50实现图像分类任务
767 0
|
Ubuntu TensorFlow 算法框架/工具
MobileNet实战:tensorflow2.X版本,MobileNetV2图像分类任务(小数据集)
本例提取了植物幼苗数据集中的部分数据做数据集,数据集共有12种类别,今天我和大家一起实现tensorflow2.X版本图像分类任务,分类的模型使用MobileNetV2,MobileNetV2在MobileNetV1的基础上增加了线性瓶颈(Linear Bottleneck)和倒残差(Inverted Residual)是一种轻量级的网络,适合应用在真实的移动端应用场景。
283 0
MobileNet实战:tensorflow2.X版本,MobileNetV2图像分类任务(小数据集)
|
人工智能 算法 Ubuntu
MobileNet实战:tensorflow2.X版本,MobileNetV2图像分类任务(大数据集)
本例提取了植物幼苗数据集中的部分数据做数据集,数据集共有12种类别,今天我和大家一起实现tensorflow2.X版本图像分类任务,分类的模型使用MobileNetV2。本文实现的算法有一下几个特点: 1、自定义了图片加载方式,更加灵活高效,不用将图片一次性加载到内存中,节省内存,适合大规模数据集。 2、加载模型的预训练权重,训练时间更短。 3、数据增强选用albumentations。
177 0
MobileNet实战:tensorflow2.X版本,MobileNetV2图像分类任务(大数据集)
|
TensorFlow 算法框架/工具 计算机视觉
TensorFlow 实现VGG16图像分类
TensorFlow 实现VGG16图像分类
TensorFlow 实现VGG16图像分类
|
机器学习/深度学习 存储 算法
TensorFlow 实现图像分类|学习笔记
快速学习 TensorFlow 实现图像分类。
149 0
TensorFlow 实现图像分类|学习笔记