转载地址:https://bbs.huaweicloud.com/forum/thread-80033-1-1.html
作者:yangyaqin
随着电子技术的迅速发展,人们使用便携数码设备(如手机、相机等)获取花卉图像越来越方便,如何自动识别花卉种类受到了广泛的关注。由于花卉所处背景的复杂性,以及花卉自身的类间相似性和类内多样性,利用传统的手工提取特征进行图像分类的方法,并不能很好地解决花卉图像分类这一问题。
本实验基于卷积神经网络实现的花卉识别实验与传统图像分类方法不同,卷积神经网络无需人工提取特征,可以根据输入图像,自动学习包含丰富语义信息的特征,得到更为全面的花卉图像特征描述,可以很好地表达图像的不同类别信息。
本节将详细介绍实验的设计与实现。导入实验环境;数据准备;介绍构建花卉识别模型;介绍如何进行模型的测试,以及相应测试结果的展示。
glob包主要用于查找符合特定规则的文件路径名,跟使用windows下的文件搜索差不多; os模块主要用于处理文件和目录,比如:获取当前目录下文件,删除制定文件,改变目录,查看文件大小等;MindSpore是目前业界最流行的深度学习框架,在图像,语音,文本,目标检测等领域都有深入的应用,也是该实验的核心,主要用于定义占位符,定义变量,创建卷积神经网络模型;numpy是一个基于python的科学计算包,在该实验中主要用来处理数值运算;time模块主要用于处理时间系列的数据,在该实验主要用于返回当前时间戳,计算脚本每个epoch运行所需要的时间。
# 导入模块
from
easydict import
EasyDict as edict
import
glob
import
os
import
numpy as np
import
matplotlib.pyplot as plt
import
mindspore
import
mindspore.dataset as ds
import
mindspore.dataset.transforms.vision.c_transforms as CV
import
mindspore.dataset.transforms.c_transforms as C
from
mindspore.dataset.transforms.vision import
Inter
from
mindspore.common import
dtype as mstype
from
mindspore import
context
from
mindspore.common.initializer import
TruncatedNormal
from
mindspore import
nn
from
mindspore.train import
Model
from
mindspore.train.callback import
ModelCheckpoint, CheckpointConfig, LossMonitor, TimeMonitor
from
mindspore import
Tensor
context.set_context(mode=context.GRAPH_MODE,device_target="Ascend")
步骤 2 定义变量
cfg =
edict({
'data_path': 'flower_photos',
'data_size':3670,
'image_width': 100, # 图片宽度
'image_height': 100, # 图片高度
'batch_size': 32,
'channel': 3, # 图片通道数
'num_class':5, # 分类类别
'weight_decay': 0.01,
'lr':0.0001, # 学习率
'dropout_ratio': 0.5,
'epoch_size': 400, # 训练次数
'sigma':0.01,
'save_checkpoint_steps': 1, # 多少步保存一次模型
'keep_checkpoint_max': 3, # 最多保存多少个模型
'output_directory': './code/flowers//model', # 保存模型路径
'output_prefix': "checkpoint_classification"
# 保存模型文件名字
})
该数据集是开源数据集,总共包括5种花的类型:分别是daisy(雏菊,633张),dandelion(蒲公英,898张),roses(玫瑰,641张),sunflowers(向日葵,699张),tulips(郁金香,799张),保存在5个文件夹当中,总共3670张,大小大概在230M左右。为了在模型部署上线之后进行测试,数据集在这里分成了flower_train和flower_test两部分。
数据集下载地址:https://professional.obs.cn-north-4.myhuaweicloud.com/flower_photos.zip
步骤 1 读取图片数据集
数据读取并处理流程如下:
- MindSpore的mindspore.dataset提供了ImageFolderDatasetV2函数,可以直接读取文件 夹图片数据并映射文件夹名字为其标签(label)。这里我们使用ImageFolderDatasetV2函数 读取'daisy','dandelion','roses','sunflowers','tulips'数据。并将这五类标签映射为: {'daisy':0,'dandelion':1,'roses':2,'sunflowers':3,'tulips':4}
- 使用RandomCropDecodeResize、HWC2CHW、TypeCast、shuffle进行数据预处理
# 解压数据集,只需要第一次运行时解压,第二次无需再解压
#!unzip ./code/flowers/flower_photos.zip
de_dataset =
ds.ImageFolderDatasetV2(cfg.data_path, class_indexing={'daisy':0,'dandelion':1,'roses':2,'sunflowers':3,'tulips':4})
transform_img =
CV.RandomCropDecodeResize([cfg.image_width,cfg.image_height], scale=(0.08, 1.0), ratio=(0.75, 1.333)) #改变尺寸
hwc2chw_op =
CV.HWC2CHW()
type_cast_op =
C.TypeCast(mstype.float32)
de_dataset =
de_dataset.map(input_columns="image", num_parallel_workers=8, operations=transform_img)
de_dataset =
de_dataset.map(input_columns="image", operations=hwc2chw_op, num_parallel_workers=8)
de_dataset =
de_dataset.map(input_columns="image", operations=type_cast_op, num_parallel_workers=8)
de_dataset =
de_dataset.shuffle(buffer_size=cfg.data_size)
步骤 2 划分训练集与测试集
- 按照8:2的比列将数据划分为训练数据集和测试数据集
- 对训练数据和测试数据分批次(batch)
(de_train,de_test)=de_dataset.split([0.8,0.2])
de_train=de_train.batch(cfg.batch_size, drop_remainder=True)
de_train=de_train.repeat(cfg.epoch_size)
de_test=de_test.batch(cfg.batch_size, drop_remainder=True)
de_test=de_test.repeat(cfg.epoch_size)
print('训练数据集数量:',de_train.get_dataset_size()*cfg.batch_size)
print('测试数据集数量:',de_test.get_dataset_size()*cfg.batch_size)
data_next=de_dataset.create_dict_iterator().get_next()
print('通道数/图像长/宽:', data_next['image'].shape)
print('一张图像的标签样式:', data_next['label']) # 一共5类,用0-4的数字表达类别。
plt.figure()
plt.imshow(data_next['image'][0,...])
plt.colorbar()
plt.grid(False)
plt.show()
训练数据集数量: 2912
测试数据集数量: 704
通道数/图像长/宽: (3, 100, 100)
一张图像的标签样式: 0
花卉图像数据集准备完成,接下来我们就需要构建训练模型,本实验采用的是CNN神经网络算法。
步骤 1 定义图像识别模型
# 定义CNN图像识别网络
class
Identification_Net(nn.Cell):
def
__init__(self, num_class=5,channel=3,dropout_ratio=0.5,trun_sigma=0.01): # 一共分五类,图片通道数是3
super(Identification_Net, self).__init__()
self.num_class =
num_class
self.channel =
channel
self.dropout_ratio=dropout_ratio
self.conv1 =
nn.Conv2d(self.channel, 32,
kernel_size=5, stride=1, padding=0,
has_bias=True, pad_mode="same",
weight_init=TruncatedNormal(sigma=trun_sigma),bias_init='zeros')
self.relu =
nn.ReLU()
self.max_pool2d =
nn.MaxPool2d(kernel_size=2, stride=2,pad_mode="valid")
self.conv2 =
nn.Conv2d(32, 64,
kernel_size=5, stride=1, padding=0,
has_bias=True, pad_mode="same",
weight_init=TruncatedNormal(sigma=trun_sigma),bias_init='zeros')
self.conv3 =
nn.Conv2d(64, 128,
kernel_size=3, stride=1, padding=0,
has_bias=True, pad_mode="same",
weight_init=TruncatedNormal(sigma=trun_sigma),bias_init='zeros')
self.conv4 =
nn.Conv2d(128, 128,
kernel_size=3, stride=1, padding=0,
has_bias=True, pad_mode="same",
weight_init=TruncatedNormal(sigma=trun_sigma), bias_init='zeros')
self.flatten =
nn.Flatten()
self.fc1 =
nn.Dense(6*6*128, 1024,weight_init =TruncatedNormal(sigma=trun_sigma),bias_init =
0.1)
self.dropout =
nn.Dropout(self.dropout_ratio)
self.fc2 =
nn.Dense(1024, 512, weight_init=TruncatedNormal(sigma=trun_sigma), bias_init=0.1)
self.fc3 =
nn.Dense(512, self.num_class, weight_init=TruncatedNormal(sigma=trun_sigma), bias_init=0.1)
def
construct(self, x):
x =
self.conv1(x)
x =
self.relu(x)
x =
self.max_pool2d(x)
x =
self.conv2(x)
x =
self.relu(x)
x =
self.max_pool2d(x)
x =
self.conv3(x)
x =
self.max_pool2d(x)
x =
self.conv4(x)
x =
self.max_pool2d(x)
x =
self.flatten(x)
x =
self.fc1(x)
x =
self.relu(x)
x =
self.dropout(x)
x =
self.fc2(x)
x =
self.relu(x)
x =
self.dropout(x)
x =
self.fc3(x)
return
x
步骤 2 模型训练
net=Identification_Net(num_class=cfg.num_class, channel=cfg.channel, dropout_ratio=cfg.dropout_ratio)
net_loss =
nn.SoftmaxCrossEntropyWithLogits(is_grad=False, sparse=True, reduction="mean")
#opt
fc_weight_params =
list(filter(lambda
x: 'fc'
in
x.name and
'weight'
in
x.name, net.trainable_params()))
else_params=list(filter(lambda
x: x not
in
fc_weight_params, net.trainable_params()))
group_params =
[{'params': fc_weight_params, 'weight_decay': cfg.weight_decay},
{'params': else_params}]
net_opt =
nn.Adam(group_params, learning_rate=cfg.lr, weight_decay=0.0)
model =
Model(net, loss_fn=net_loss, optimizer=net_opt, metrics={"acc"})
loss_cb =
LossMonitor(per_print_times=de_train.get_dataset_size())
config_ck =
CheckpointConfig(save_checkpoint_steps=cfg.save_checkpoint_steps,
keep_checkpoint_max=cfg.keep_checkpoint_max)
ckpoint_cb =
ModelCheckpoint(prefix=cfg.output_prefix, directory=cfg.output_directory, config=config_ck)
print("============== Starting Training ==============")
model.train(cfg.epoch_size, de_train, callbacks=[loss_cb], dataset_sink_mode=True)
# 使用测试集评估模型,打印总体准确率
metric =
model.eval(de_test)
print(metric)
输出结果:
============== Starting Training ==============
epoch: 1 step 91, loss is 1.3102010488510132
Epoch time: 14017.676, per step time: 154.040, avg loss: 1.310
************************************************************
epoch: 2 step 91, loss is 1.237145185470581
Epoch time: 758.372, per step time: 8.334, avg loss: 1.237
************************************************************
epoch: 3 step 91, loss is 1.3110840320587158
Epoch time: 757.112, per step time: 8.320, avg loss: 1.311
************************************************************
epoch: 4 step 91, loss is 1.3393423557281494
Epoch time: 763.801, per step time: 8.393, avg loss: 1.339
************************************************************
...
...
...
************************************************************
epoch: 397 step 91, loss is 0.18403360247612
Epoch time: 764.593, per step time: 8.402, avg loss: 0.184
************************************************************
epoch: 398 step 91, loss is 0.09277979284524918
Epoch time: 766.729, per step time: 8.426, avg loss: 0.093
************************************************************
epoch: 399 step 91, loss is 0.20462298393249512
Epoch time: 769.085, per step time: 8.451, avg loss: 0.205
************************************************************
epoch: 400 step 91, loss is 0.24984098970890045
Epoch time: 761.465, per step time: 8.368, avg loss: 0.250
************************************************************
{'acc': 0.9147727272727273}
l * 掌握利图像识别模型验证方法。
步骤 1 加载训练模型
# 加载模型
#加载模型
CKPT =
'./code/flowers/model/checkpoint_classification-400_91.ckpt'
net =
Identification_Net(num_class=cfg.num_class, channel=cfg.channel, dropout_ratio=cfg.dropout_ratio)
load_checkpoint(CKPT, net=net)
model =
Model(net)
步骤 2 验证推理
# 预测
class_indexing={0:'daisy',1:'dandelion',2:'roses',3:'sunflowers',4:'tulips'}
test_ =
de_test.create_dict_iterator().get_next()
test =
Tensor(test_['image'], mindspore.float32)
predictions =
model.predict(test)
predictions =
predictions.asnumpy()
for
i in
range(10):
p_np =
predictions[i, :]
p_list =
p_np.tolist()
print('第'
+
str(i) +
'个sample预测结果:', class_indexing[p_list.index(max(p_list))], ' 真实结果:', class_indexing[test_['label']])
输出结果:
第0个sample预测结果: sunflowers 真实结果: sunflowers
第1个sample预测结果: dandelion 真实结果: dandelion
第2个sample预测结果: sunflowers 真实结果: sunflowers
第3个sample预测结果: sunflowers 真实结果: sunflowers
第4个sample预测结果: daisy 真实结果: daisy
第5个sample预测结果: dandelion 真实结果: dandelion
第6个sample预测结果: daisy 真实结果: daisy
第7个sample预测结果: sunflowers 真实结果: sunflowers
第8个sample预测结果: tulips 真实结果: tulips
第9个sample预测结果: dandelion 真实结果: dandelion
本章提供了一个基于华为ModelArts平台的图像识别实验。该实验演示了如何利用华为云ModelArts完成图像识别任务。本章对实验实验做了详尽的剖析。阐明了整个实验功能、结构与流程是如何设计的,详细解释了如何解析数据、如何构建深度学习模型、如何保存模型等内容。部署后的实验多个类别图片下进行测试,结果表明实验实验具有较快的推断速度和较好的识别性能。读者可以在该实验实验的基础上开发更有针对性的应用实验。
基于本实验的描述,请使用数据集CIFAR10完成图片识别任务并搭建一套自定义的图片识别实验。