昇思MindSpore学习笔记3-03热门LLM及其他AI应用--基于MobileNetv2的垃圾分类

摘要:

MindSpore AI框架使用MobileNetv2模型开发垃圾分检代码。检测本地图像中的垃圾物体,保存检测结果到文件。记录了开发过程和步骤,包括环境准备、数据下载、加载和预处理、模型搭建、训练、测试、推理应用等。

1、实验目的

了解垃圾分类应用代码的编写(Python语言);

了解Linux操作系统的基本使用;

掌握atc命令进行模型转换的基本操作。

2、概念

MobileNetv2网络模型原理

        Google 2017年提出

        用于轻量级CNN网络

                移动端

                嵌入式或IoT设备

        技术采用

                使用深度可分离卷积(Depthwise Separable Convolution)

                引入宽度系数α和分辨率系数β

                倒残差结构(Inverted residual block)

                Linear Bottlenecks

        优点

                减少模型参数

                减小运算量

                提高模型的准确率,且优化后的模型更小

Inverted residual block结构

        1x1卷积升维

        3x3 DepthWise卷积

        1x1卷积降维

Residual block结构

        1x1卷积降维

        3x3卷积

        1x1卷积升维

3、实验环境

支持win_x86和Linux系统,CPU/GPU/Ascend均可

参考《MindSpore环境搭建实验手册》

%%capture captured_output
# 实验环境已经预装了mindspore==2.2.14,如需更换mindspore版本,可更改下面mindspore的版本号
!pip uninstall mindspore -y
!pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore==2.2.14
# 查看当前 mindspore 版本
!pip show mindspore

输出:

Name: mindspore
Version: 2.2.14
Summary: MindSpore is a new open source deep learning training/inference framework that could be used for mobile, edge and cloud scenarios.
Home-page: https://www.mindspore.cn
Author: The MindSpore Authors
Author-email: contact@mindspore.cn
License: Apache 2.0
Location: /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages
Requires: asttokens, astunparse, numpy, packaging, pillow, protobuf, psutil, scipy
Required-by: mindnlp

4、数据处理

4.1数据集格式

ImageFolder格式每一类图片整理成单独的一个文件夹

数据集结构:

└─ImageFolder
├─train
│   class1Folder
│   ......
└─evalclass1Folder
......

4.2下载数据集

from download import download
​
# 下载data_en数据集
url = "https://ascend-professional-construction-dataset.obs.cn-north-4.myhuaweicloud.com:443/MindStudio-pc/data_en.zip" 
path = download(url, "./", kind="zip", replace=True)

输出:

Downloading data from https://ascend-professional-construction-dataset.obs.cn-north-4.myhuaweicloud.com:443/MindStudio-pc/data_en.zip (21.3 MB)file_sizes: 100%|███████████████████████████| 22.4M/22.4M [00:00<00:00, 123MB/s]
Extracting zip file...
Successfully downloaded / unzipped to ./

4.3下载训练权重文件

from download import download
​
# 下载预训练权重文件
url = "https://ascend-professional-construction-dataset.obs.cn-north-4.myhuaweicloud.com:443/ComputerVision/mobilenetV2-200_1067.zip" 
path = download(url, "./", kind="zip", replace=True)

输出:

Downloading data from https://ascend-professional-construction-dataset.obs.cn-north-4.myhuaweicloud.com:443/ComputerVision/mobilenetV2-200_1067.zip (25.5 MB)file_sizes: 100%|███████████████████████████| 26.7M/26.7M [00:00<00:00, 109MB/s]
Extracting zip file...
Successfully downloaded / unzipped to ./

4.4数据加载

将模块导入,具体如下:

import math
import numpy as np
import os
import random
​
from matplotlib import pyplot as plt
from easydict import EasyDict
from PIL import Image
import numpy as np
import mindspore.nn as nn
from mindspore import ops as P
from mindspore.ops import add
from mindspore import Tensor
import mindspore.common.dtype as mstype
import mindspore.dataset as de
import mindspore.dataset.vision as C
import mindspore.dataset.transforms as C2
import mindspore as ms
from mindspore import set_context, nn, Tensor, load_checkpoint, save_checkpoint, export
from mindspore.train import Model
from mindspore.train import Callback, LossMonitor, ModelCheckpoint, CheckpointConfig
​
os.environ['GLOG_v'] = '3' # Log level includes 3(ERROR), 2(WARNING), 1(INFO), 0(DEBUG).
os.environ['GLOG_logtostderr'] = '0' # 0:输出到文件,1:输出到屏幕
os.environ['GLOG_log_dir'] = '../../log' # 日志目录
os.environ['GLOG_stderrthreshold'] = '2' # 输出到目录也输出到屏幕:3(ERROR), 2(WARNING), 1(INFO), 0(DEBUG).
set_context(mode=ms.GRAPH_MODE, device_target="CPU", device_id=0) # 设置采用图模式执行,设备为Ascend#

配置后续训练、验证、推理用到的参数:

# 垃圾分类数据集标签,以及用于标签映射的字典。
garbage_classes = {'干垃圾': ['贝壳', '打火机', '旧镜子', '扫把', '陶瓷碗', '牙刷', '一次性筷子', '脏污衣服'],'可回收物': ['报纸', '玻璃制品', '篮球', '塑料瓶', '硬纸板', '玻璃瓶', '金属制品', '帽子', '易拉罐', '纸张'],'湿垃圾': ['菜叶', '橙皮', '蛋壳', '香蕉皮'],'有害垃圾': ['电池', '药片胶囊', '荧光灯', '油漆桶']
}
​
class_cn = ['贝壳', '打火机', '旧镜子', '扫把', '陶瓷碗', '牙刷', '一次性筷子', '脏污衣服','报纸', '玻璃制品', '篮球', '塑料瓶', '硬纸板', '玻璃瓶', '金属制品', '帽子', '易拉罐', '纸张','菜叶', '橙皮', '蛋壳', '香蕉皮','电池', '药片胶囊', '荧光灯', '油漆桶']
class_en = ['Seashell', 'Lighter','Old Mirror', 'Broom','Ceramic Bowl', 'Toothbrush','Disposable Chopsticks','Dirty Cloth','Newspaper', 'Glassware', 'Basketball', 'Plastic Bottle', 'Cardboard','Glass Bottle', 'Metalware', 'Hats', 'Cans', 'Paper','Vegetable Leaf','Orange Peel', 'Eggshell','Banana Peel','Battery', 'Tablet capsules','Fluorescent lamp', 'Paint bucket']
​
index_en = {'Seashell': 0, 'Lighter': 1, 'Old Mirror': 2, 'Broom': 3, 'Ceramic Bowl': 4, 'Toothbrush': 5, 'Disposable Chopsticks': 6, 'Dirty Cloth': 7,'Newspaper': 8, 'Glassware': 9, 'Basketball': 10, 'Plastic Bottle': 11, 'Cardboard': 12, 'Glass Bottle': 13, 'Metalware': 14, 'Hats': 15, 'Cans': 16, 'Paper': 17,'Vegetable Leaf': 18, 'Orange Peel': 19, 'Eggshell': 20, 'Banana Peel': 21,'Battery': 22, 'Tablet capsules': 23, 'Fluorescent lamp': 24, 'Paint bucket': 25}
​
# 训练超参
config = EasyDict({"num_classes": 26,"image_height": 224,"image_width": 224,#"data_split": [0.9, 0.1],"backbone_out_channels":1280,"batch_size": 16,"eval_batch_size": 8,"epochs": 10,"lr_max": 0.05,"momentum": 0.9,"weight_decay": 1e-4,"save_ckpt_epochs": 1,"dataset_path": "./data_en","class_index": index_en,"pretrained_ckpt": "./mobilenetV2-200_1067.ckpt" # mobilenetV2-200_1067.ckpt 
})

4.5数据预处理操作

读取垃圾分类数据集

        ImageFolderDataset方法

                指定训练集和测试集

预处理

        归一化

        修改图像频道

        训练集增加丰富度

                RandomCropDecodeResize

                RandomHorizontalFlip

                RandomColorAdjust

                Shuffle

        测试集

                Decode

                Resize

                CenterCrop

def create_dataset(dataset_path, config, training=True, buffer_size=1000):"""create a train or eval dataset
​Args:dataset_path(string): the path of dataset.config(struct): the config of train and eval in diffirent platform.
​Returns:train_dataset, val_dataset"""data_path = os.path.join(dataset_path, 'train' if training else 'test')ds = de.ImageFolderDataset(data_path, num_parallel_workers=4, class_indexing=config.class_index)resize_height = config.image_heightresize_width = config.image_widthnormalize_op = C.Normalize(mean=[0.485*255, 0.456*255, 0.406*255], std=[0.229*255, 0.224*255, 0.225*255])change_swap_op = C.HWC2CHW()type_cast_op = C2.TypeCast(mstype.int32)
​if training:crop_decode_resize = C.RandomCropDecodeResize(resize_height, scale=(0.08, 1.0), ratio=(0.75, 1.333))horizontal_flip_op = C.RandomHorizontalFlip(prob=0.5)color_adjust = C.RandomColorAdjust(brightness=0.4, contrast=0.4, saturation=0.4)train_trans = [crop_decode_resize, horizontal_flip_op, color_adjust, normalize_op, change_swap_op]train_ds = ds.map(input_columns="image", operations=train_trans, num_parallel_workers=4)train_ds = train_ds.map(input_columns="label", operations=type_cast_op, num_parallel_workers=4)train_ds = train_ds.shuffle(buffer_size=buffer_size)ds = train_ds.batch(config.batch_size, drop_remainder=True)else:decode_op = C.Decode()resize_op = C.Resize((int(resize_width/0.875), int(resize_width/0.875)))center_crop = C.CenterCrop(resize_width)eval_trans = [decode_op, resize_op, center_crop, normalize_op, change_swap_op]eval_ds = ds.map(input_columns="image", operations=eval_trans, num_parallel_workers=4)eval_ds = eval_ds.map(input_columns="label", operations=type_cast_op, num_parallel_workers=4)ds = eval_ds.batch(config.eval_batch_size, drop_remainder=True)
​return ds

展示部分处理后的数据:

ds = create_dataset(dataset_path=config.dataset_path, config=config, training=False)
print(ds.get_dataset_size())
data = ds.create_dict_iterator(output_numpy=True)._get_next()
images = data['image']
labels = data['label']
​
for i in range(1, 5):plt.subplot(2, 2, i)plt.imshow(np.transpose(images[i], (1,2,0)))plt.title('label: %s' % class_en[labels[i]])plt.xticks([])
plt.show()

输出:

Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). Got range [-1.9831933..2.64].
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). Got range [-2.117904..2.4285715].
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). Got range [-2.0494049..2.273987].
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). Got range [-1.9809059..2.64].
32

5、MobileNetV2模型搭建

定义MobileNetV2网络

继承mindspore.nn.Cell基类

        __init__方法     定义神经网络的各层

        Construct         构造方法

        ReLU6             原始模型激活函数

        池化模块         全局平均池化层

__all__ = ['MobileNetV2', 'MobileNetV2Backbone', 'MobileNetV2Head', 'mobilenet_v2']
​
def _make_divisible(v, divisor, min_value=None):if min_value is None:min_value = divisornew_v = max(min_value, int(v + divisor / 2) // divisor * divisor)if new_v < 0.9 * v:new_v += divisorreturn new_v
​
class GlobalAvgPooling(nn.Cell):"""Global avg pooling definition.
​Args:
​Returns:Tensor, output tensor.
​Examples:>>> GlobalAvgPooling()"""
​def __init__(self):super(GlobalAvgPooling, self).__init__()
​def construct(self, x):x = P.mean(x, (2, 3))return x
​
class ConvBNReLU(nn.Cell):"""Convolution/Depthwise fused with Batchnorm and ReLU block definition.
​Args:in_planes (int): Input channel.out_planes (int): Output channel.kernel_size (int): Input kernel size.stride (int): Stride size for the first convolutional layer. Default: 1.groups (int): channel group. Convolution is 1 while Depthiwse is input channel. Default: 1.
​Returns:Tensor, output tensor.
​Examples:>>> ConvBNReLU(16, 256, kernel_size=1, stride=1, groups=1)"""
​def __init__(self, in_planes, out_planes, kernel_size=3, stride=1, groups=1):super(ConvBNReLU, self).__init__()padding = (kernel_size - 1) // 2in_channels = in_planesout_channels = out_planesif groups == 1:conv = nn.Conv2d(in_channels, out_channels, kernel_size, stride, 
pad_mode='pad', padding=padding)else:out_channels = in_planesconv = nn.Conv2d(in_channels, out_channels, kernel_size, stride, pad_mode='pad',padding=padding, group=in_channels)
​layers = [conv, nn.BatchNorm2d(out_planes), nn.ReLU6()]self.features = nn.SequentialCell(layers)
​def construct(self, x):output = self.features(x)return output
​
class InvertedResidual(nn.Cell):"""Mobilenetv2 residual block definition.
​Args:inp (int): Input channel.oup (int): Output channel.stride (int): Stride size for the first convolutional layer. Default: 1.expand_ratio (int): expand ration of input channel
​Returns:Tensor, output tensor.
​Examples:>>> ResidualBlock(3, 256, 1, 1)"""
​def __init__(self, inp, oup, stride, expand_ratio):super(InvertedResidual, self).__init__()assert stride in [1, 2]
​hidden_dim = int(round(inp * expand_ratio))self.use_res_connect = stride == 1 and inp == oup
​layers = []if expand_ratio != 1:layers.append(ConvBNReLU(inp, hidden_dim, kernel_size=1))layers.extend([ConvBNReLU(hidden_dim, hidden_dim,stride=stride, groups=hidden_dim),nn.Conv2d(hidden_dim, oup, kernel_size=1,stride=1, has_bias=False),nn.BatchNorm2d(oup),])self.conv = nn.SequentialCell(layers)self.cast = P.Cast()
​def construct(self, x):identity = xx = self.conv(x)if self.use_res_connect:return P.add(identity, x)return x
​
class MobileNetV2Backbone(nn.Cell):"""MobileNetV2 architecture.
​Args:class_num (int): number of classes.width_mult (int): Channels multiplier for round to 8/16 and others. Default is 1.has_dropout (bool): Is dropout used. Default is falseinverted_residual_setting (list): Inverted residual settings. Default is Noneround_nearest (list): Channel round to . Default is 8Returns:Tensor, output tensor.
​Examples:>>> MobileNetV2(num_classes=1000)"""
​def __init__(self, width_mult=1., inverted_residual_setting=None, round_nearest=8,input_channel=32, last_channel=1280):super(MobileNetV2Backbone, self).__init__()block = InvertedResidual# setting of inverted residual blocksself.cfgs = inverted_residual_settingif inverted_residual_setting is None:self.cfgs = [# t, c, n, s[1, 16, 1, 1],[6, 24, 2, 2],[6, 32, 3, 2],[6, 64, 4, 2],[6, 96, 3, 1],[6, 160, 3, 2],[6, 320, 1, 1],]
​# building first layerinput_channel = _make_divisible(input_channel * width_mult, round_nearest)self.out_channels = _make_divisible(last_channel * max(1.0, width_mult), round_nearest)features = [ConvBNReLU(3, input_channel, stride=2)]# building inverted residual blocksfor t, c, n, s in self.cfgs:output_channel = _make_divisible(c * width_mult, round_nearest)for i in range(n):stride = s if i == 0 else 1features.append(block(input_channel, output_channel, stride, expand_ratio=t))input_channel = output_channelfeatures.append(ConvBNReLU(input_channel, self.out_channels, kernel_size=1))self.features = nn.SequentialCell(features)self._initialize_weights()
​def construct(self, x):x = self.features(x)return x
​def _initialize_weights(self):"""Initialize weights.
​Args:
​Returns:None.
​Examples:>>> _initialize_weights()"""self.init_parameters_data()for _, m in self.cells_and_names():if isinstance(m, nn.Conv2d):n = m.kernel_size[0] * m.kernel_size[1] * m.out_channelsm.weight.set_data(Tensor(np.random.normal(0, np.sqrt(2. / n),m.weight.data.shape).astype("float32")))if m.bias is not None:m.bias.set_data(Tensor(np.zeros(m.bias.data.shape, dtype="float32")))elif isinstance(m, nn.BatchNorm2d):m.gamma.set_data(Tensor(np.ones(m.gamma.data.shape, dtype="float32")))m.beta.set_data(Tensor(np.zeros(m.beta.data.shape, dtype="float32")))
​@propertydef get_features(self):return self.features
​
class MobileNetV2Head(nn.Cell):"""MobileNetV2 architecture.
​Args:class_num (int): Number of classes. Default is 1000.has_dropout (bool): Is dropout used. Default is falseReturns:Tensor, output tensor.
​Examples:>>> MobileNetV2(num_classes=1000)"""
​
def __init__(self, input_channel=1280, num_classes=1000, 
has_dropout=False, activation="None"):super(MobileNetV2Head, self).__init__()# mobilenet headhead = ([GlobalAvgPooling(), nn.Dense(input_channel, num_classes, has_bias=True)] 
if not has_dropout else[GlobalAvgPooling(), nn.Dropout(0.2), nn.Dense(input_channel, num_classes, has_bias=True)])self.head = nn.SequentialCell(head)self.need_activation = Trueif activation == "Sigmoid":self.activation = nn.Sigmoid()elif activation == "Softmax":self.activation = nn.Softmax()else:self.need_activation = Falseself._initialize_weights()
​def construct(self, x):x = self.head(x)if self.need_activation:x = self.activation(x)return x
​def _initialize_weights(self):"""Initialize weights.
​Args:
​Returns:None.
​Examples:>>> _initialize_weights()"""self.init_parameters_data()for _, m in self.cells_and_names():if isinstance(m, nn.Dense):m.weight.set_data(Tensor(np.random.normal(0, 0.01, m.weight.data.shape).astype("float32")))if m.bias is not None:m.bias.set_data(Tensor(np.zeros(m.bias.data.shape, dtype="float32")))@propertydef get_head(self):return self.head
​
class MobileNetV2(nn.Cell):"""MobileNetV2 architecture.
​Args:class_num (int): number of classes.width_mult (int): Channels multiplier for round to 8/16 and others. Default is 1.has_dropout (bool): Is dropout used. Default is falseinverted_residual_setting (list): Inverted residual settings. Default is Noneround_nearest (list): Channel round to . Default is 8Returns:Tensor, output tensor.
​Examples:>>> MobileNetV2(backbone, head)"""
​def __init__(self, num_classes=1000, width_mult=1., has_dropout=False, inverted_residual_setting=None, \round_nearest=8, input_channel=32, last_channel=1280):super(MobileNetV2, self).__init__()self.backbone = MobileNetV2Backbone(width_mult=width_mult, \inverted_residual_setting=inverted_residual_setting, \round_nearest=round_nearest, input_channel=input_channel, \
last_channel=last_channel).get_featuresself.head = MobileNetV2Head(input_channel=self.backbone.out_channel, \
num_classes=num_classes, \
has_dropout=has_dropout).get_head
​def construct(self, x):x = self.backbone(x)x = self.head(x)return x
​
class MobileNetV2Combine(nn.Cell):"""MobileNetV2Combine architecture.
​Args:backbone (Cell): the features extract layers.head (Cell):  the fully connected layers.Returns:Tensor, output tensor.
​Examples:>>> MobileNetV2(num_classes=1000)"""
​def __init__(self, backbone, head):super(MobileNetV2Combine, self).__init__(auto_prefix=False)self.backbone = backboneself.head = head
​def construct(self, x):x = self.backbone(x)x = self.head(x)return x
​
def mobilenet_v2(backbone, head):return MobileNetV2Combine(backbone, head)

6、MobileNetV2模型的训练与测试

6.1训练策略

静态学习率,如0.01。

随着训练步数的增加,模型逐渐收敛,逐渐降低权重参数的更新幅度,减小模型训练抖动。

动态下降学习率常见策略:

        polynomial decay/square decay;

        cosine decay,此例选用;

        exponential decay;

        stage decay.

def cosine_decay(total_steps, lr_init=0.0, lr_end=0.0, lr_max=0.1, warmup_steps=0):"""Applies cosine decay to generate learning rate array.
​Args:total_steps(int): all steps in training.lr_init(float): init learning rate.lr_end(float): end learning ratelr_max(float): max learning rate.warmup_steps(int): all steps in warmup epochs.
​Returns:list, learning rate array."""lr_init, lr_end, lr_max = float(lr_init), float(lr_end), float(lr_max)decay_steps = total_steps - warmup_stepslr_all_steps = []inc_per_step = (lr_max - lr_init) / warmup_steps if warmup_steps else 0for i in range(total_steps):if i < warmup_steps:lr = lr_init + inc_per_step * (i + 1)else:cosine_decay = 0.5 * (1 + math.cos(math.pi * (i - warmup_steps) / decay_steps))lr = (lr_max - lr_end) * cosine_decay + lr_endlr_all_steps.append(lr)
​return lr_all_steps

6.2保存训练模型

模型训练过程中添加检查点(Checkpoint)保存模型参数。

保存模型使用场景:

        训练后推理场景

                用于后续的推理或预测操作。

                保存实时验证精度最高的模型参数用于预测操作。

        再训练场景

                长时间训练,断点处继续训练。

        Fine-tuning微调场景

                微调用于其他类似任务的模型训练。

下例加载ImageNet数据上预训练的MobileNetv2进行Fine-tuning

        只训练最后修改的FC层

        训练过程中保存Checkpoint

def switch_precision(net, data_type):if ms.get_context('device_target') == "Ascend":net.to_float(data_type)for _, cell in net.cells_and_names():if isinstance(cell, nn.Dense):cell.to_float(ms.float32)

6.3模型训练与测试

训练之前

        定义训练函数

        读取数据并对模型进行实例化,

        定义优化器和损失函数

概念:

损失函数(目标函数

        衡量预测值与实际值的差异程度。

        深度学习通过迭代缩小损失函数的值,提高模型性能。

优化器

        最小化损失函数,在训练过程中改进模型。

损失函数关于权重的梯度

        指示优化器优化方向

参数更新

        固定MobileNetV2Backbone层参数,训练中不更新

        只更新MobileNetV2Head模块参数

MindSpore损失函数

        SoftmaxCrossEntropyWithLogits,此例选用

        L1Loss

        MSELoss

训练测试过程中打印loss值总体趋势逐步减小,精度逐步提高。

每一epoch模型会计算测试精度,不断提升MobileNetV2模型的预测能力

from mindspore.amp import FixedLossScaleManager
import time
LOSS_SCALE = 1024
​
train_dataset = create_dataset(dataset_path=config.dataset_path, config=config)
eval_dataset = create_dataset(dataset_path=config.dataset_path, config=config)
step_size = train_dataset.get_dataset_size()backbone = MobileNetV2Backbone() #last_channel=config.backbone_out_channels
# Freeze parameters of backbone. You can comment these two lines.
for param in backbone.get_parameters():param.requires_grad = False
# load parameters from pretrained model
load_checkpoint(config.pretrained_ckpt, backbone)
​
head = MobileNetV2Head(input_channel=backbone.out_channels, num_classes=config.num_classes)
network = mobilenet_v2(backbone, head)
​
# define loss, optimizer, and model
loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
loss_scale = FixedLossScaleManager(LOSS_SCALE, drop_overflow_update=False)
lrs = cosine_decay(config.epochs * step_size, lr_max=config.lr_max)
opt = nn.Momentum(network.trainable_params(), lrs, config.momentum, config.weight_decay, loss_scale=LOSS_SCALE)
​
# 定义用于训练的train_loop函数。
def train_loop(model, dataset, loss_fn, optimizer):# 定义正向计算函数def forward_fn(data, label):logits = model(data)loss = loss_fn(logits, label)return loss
​# 定义微分函数,使用mindspore.value_and_grad获得微分函数grad_fn,输出loss和梯度。# 由于是对模型参数求导,grad_position 配置为None,传入可训练参数。grad_fn = ms.value_and_grad(forward_fn, None, optimizer.parameters)
​# 定义 one-step training函数def train_step(data, label):loss, grads = grad_fn(data, label)optimizer(grads)return loss
​size = dataset.get_dataset_size()model.set_train()for batch, (data, label) in enumerate(dataset.create_tuple_iterator()):loss = train_step(data, label)
​if batch % 10 == 0:loss, current = loss.asnumpy(), batchprint(f"loss: {loss:>7f}  [{current:>3d}/{size:>3d}]")
​
# 定义用于测试的test_loop函数。
def test_loop(model, dataset, loss_fn):num_batches = dataset.get_dataset_size()model.set_train(False)total, test_loss, correct = 0, 0, 0for data, label in dataset.create_tuple_iterator():pred = model(data)total += len(data)test_loss += loss_fn(pred, label).asnumpy()correct += (pred.argmax(1) == label).asnumpy().sum()test_loss /= num_batchescorrect /= totalprint(f"Test: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
​
print("============== Starting Training ==============")
# 由于时间问题,训练过程只进行了2个epoch ,可以根据需求调整。
epoch_begin_time = time.time()
epochs = 2
for t in range(epochs):begin_time = time.time()print(f"Epoch {t+1}\n-------------------------------")train_loop(network, train_dataset, loss, opt)ms.save_checkpoint(network, "save_mobilenetV2_model.ckpt")end_time = time.time()times = end_time - begin_timeprint(f"per epoch time: {times}s")test_loop(network, eval_dataset, loss)
epoch_end_time = time.time()
times = epoch_end_time - epoch_begin_time
print(f"total time:  {times}s")
print("============== Training Success ==============")

输出:

============== Starting Training ==============
Epoch 1
-------------------------------
[ERROR] CORE(185595,ffff82d60930,python):2024-06-07-01:11:59.680.056 [mindspore/core/utils/file_utils.cc:253] GetRealPath] Get realpath failed, path[/tmp/ipykernel_185595/1438112663.py]
[ERROR] CORE(185595,ffff82d60930,python):2024-06-07-01:11:59.680.141 [mindspore/core/utils/file_utils.cc:253] GetRealPath] Get realpath failed, path[/tmp/ipykernel_185595/1438112663.py]
[ERROR] CORE(185595,ffff82d60930,python):2024-06-07-01:11:59.680.195 [mindspore/core/utils/file_utils.cc:253] GetRealPath] Get realpath failed, path[/tmp/ipykernel_185595/1438112663.py]
loss: 3.241972  [  0/162]
loss: 3.257221  [ 10/162]
loss: 3.279036  [ 20/162]
loss: 3.319016  [ 30/162]
loss: 3.203032  [ 40/162]
loss: 3.281466  [ 50/162]
loss: 3.279725  [ 60/162]
loss: 3.229515  [ 70/162]
loss: 3.267290  [ 80/162]
loss: 3.188127  [ 90/162]
loss: 3.212995  [100/162]
loss: 3.241497  [110/162]
loss: 3.209007  [120/162]
loss: 3.172501  [130/162]
loss: 3.197280  [140/162]
loss: 3.272911  [150/162]
loss: 3.216317  [160/162]
per epoch time: 76.58693552017212s
[ERROR] CORE(185595,ffff82d60930,python):2024-06-07-01:13:15.037.060 [mindspore/core/utils/file_utils.cc:253] GetRealPath] Get realpath failed, path[/tmp/ipykernel_185595/3136751602.py]
[ERROR] CORE(185595,ffff82d60930,python):2024-06-07-01:13:15.037.167 [mindspore/core/utils/file_utils.cc:253] GetRealPath] Get realpath failed, path[/tmp/ipykernel_185595/3136751602.py]
Test: Accuracy: 8.0%, Avg loss: 3.194478 Epoch 2
-------------------------------
[ERROR] CORE(185595,ffff82d60930,python):2024-06-07-01:14:30.208.773 [mindspore/core/utils/file_utils.cc:253] GetRealPath] Get realpath failed, path[/tmp/ipykernel_185595/1438112663.py]
[ERROR] CORE(185595,ffff82d60930,python):2024-06-07-01:14:30.208.853 [mindspore/core/utils/file_utils.cc:253] GetRealPath] Get realpath failed, path[/tmp/ipykernel_185595/1438112663.py]
[ERROR] CORE(185595,ffff82d60930,python):2024-06-07-01:14:30.208.907 [mindspore/core/utils/file_utils.cc:253] GetRealPath] Get realpath failed, path[/tmp/ipykernel_185595/1438112663.py]
loss: 3.188095  [  0/162]
loss: 3.165776  [ 10/162]
loss: 3.191228  [ 20/162]
loss: 3.138081  [ 30/162]
loss: 3.074074  [ 40/162]
loss: 3.163727  [ 50/162]
loss: 3.165467  [ 60/162]
loss: 3.173247  [ 70/162]
loss: 3.159379  [ 80/162]
loss: 3.143544  [ 90/162]
loss: 3.200886  [100/162]
loss: 3.201387  [110/162]
loss: 3.165534  [120/162]
loss: 3.171612  [130/162]
loss: 3.203765  [140/162]
loss: 3.166876  [150/162]
loss: 3.125233  [160/162]
per epoch time: 76.00073027610779s
Test: Accuracy: 17.4%, Avg loss: 3.111141 total time:  295.01550674438477s
============== Training Success ==============

7、模型推理

加载模型Checkpoint

        load_checkpoint接口加载数据

        把数据传入给原始网络

CKPT="save_mobilenetV2_model.ckpt"
[13]:def image_process(image):"""Precess one image per time.Args:image: shape (H, W, C)"""mean=[0.485*255, 0.456*255, 0.406*255]std=[0.229*255, 0.224*255, 0.225*255]image = (np.array(image) - mean) / stdimage = image.transpose((2,0,1))img_tensor = Tensor(np.array([image], np.float32))return img_tensor
​
def infer_one(network, image_path):image = Image.open(image_path).resize((config.image_height, config.image_width))logits = network(image_process(image))pred = np.argmax(logits.asnumpy(), axis=1)[0]print(image_path, class_en[pred])
​
def infer():backbone = MobileNetV2Backbone(last_channel=config.backbone_out_channels)head = MobileNetV2Head(input_channel=backbone.out_channels, num_classes=config.num_classes)network = mobilenet_v2(backbone, head)load_checkpoint(CKPT, network)for i in range(91, 100):infer_one(network, f'data_en/test/Cardboard/000{i}.jpg')
infer()

输出:

[ERROR] CORE(185595,ffff82d60930,python):2024-06-07-01:16:53.811.718 [mindspore/core/utils/file_utils.cc:253] GetRealPath] Get realpath failed, path[/tmp/ipykernel_185595/3136751602.py]
[ERROR] CORE(185595,ffff82d60930,python):2024-06-07-01:16:53.811.810 [mindspore/core/utils/file_utils.cc:253] GetRealPath] Get realpath failed, path[/tmp/ipykernel_185595/3136751602.py]
data_en/test/Cardboard/00091.jpg Lighter
data_en/test/Cardboard/00092.jpg Broom
data_en/test/Cardboard/00093.jpg Basketball
data_en/test/Cardboard/00094.jpg Basketball
data_en/test/Cardboard/00095.jpg Basketball
data_en/test/Cardboard/00096.jpg Glassware
data_en/test/Cardboard/00097.jpg Lighter
data_en/test/Cardboard/00098.jpg Basketball
data_en/test/Cardboard/00099.jpg Basketball

8、导出AIR/GEIR/ONNX模型文件

导出AIR模型文件,用于后续Atlas 200 DK上的模型转换与推理。

当前仅支持MindSpore+Ascend环境。

backbone = MobileNetV2Backbone(last_channel=config.backbone_out_channels)
head = MobileNetV2Head(input_channel=backbone.out_channels, num_classes=config.num_classes)
network = mobilenet_v2(backbone, head)
load_checkpoint(CKPT, network)
​
input = np.random.uniform(0.0, 1.0, size=[1, 3, 224, 224]).astype(np.float32)
# export(network, Tensor(input), file_name='mobilenetv2.air', file_format='AIR')
# export(network, Tensor(input), file_name='mobilenetv2.pb', file_format='GEIR')
export(network, Tensor(input), file_name='mobilenetv2.onnx', file_format='ONNX')

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DDoS攻击详解

DDoS 攻击&#xff0c;其本质是通过操控大量的傀儡主机或者被其掌控的网络设备&#xff0c;向目标系统如潮水般地发送海量的请求或数据。这种行为的目的在于竭尽全力地耗尽目标系统的网络带宽、系统资源以及服务能力&#xff0c;从而致使目标系统无法正常地为合法用户提供其所应…

aop的几种动态代理以及简单案例(1)

Sping AOP是通过动态代理模式实现的&#xff0c;具体有两种实现方式&#xff0c;一种是基于Java原生的动态代理&#xff0c;一种是基于cglib的动态代理。 1.jdk动态代理 1.1创建需要被代理的方法接口 public interface TargetInteface {void method1();void method2();int me…

到底哪款护眼大路灯好?五款适合学生用的护眼落地灯分享

到底哪款护眼大路灯好&#xff1f;影响青少年近视的最大“杀手”竟是学习环境光的影响。而对于这种情形&#xff0c;尤其是对于需要长时间用眼的学生群体和伏案工作者来说&#xff0c;护眼大路灯简直就是必备神器&#xff0c;但有人会问&#xff0c;我手机打开一搜就出现了那么…

有没有适合低预算党的主食冻干?希喂主食冻干真实喂养体验分享

铲屎官们好&#xff0c;今天来和大家聊聊一款让我喂出花来的主食冻干——希喂CPMR2.0大橙罐。作为一个注重猫咪身体健康和幸福感的铲屎官&#xff0c;怎么会不喂主食冻干。铲屎官们都致力于找到一款适合自家猫咪和平衡自己预算的主食冻干&#xff0c;我也做了不少尝试&#xff…

Apache配置与应用(企业网站架构部署与优化)

本章结构 如果要修改以上文件中的内容&#xff0c;想要生效&#xff0c;需要在主配置文件中能够扫描到这个默认文件的修改&#xff1a; 文件在&#xff1a; Apache 连接保持 Apache 的访问控制 针对IP地址的限制缺陷是不可预知性&#xff0c;需要事先直到对方的IP才能进行基于…

深度学习模型分布式训练

单机单卡训练 单机多卡训练 使用torch.nn.DataParallel方式&#xff0c;修改简单&#xff0c;但单进程效率慢 使用DDP方式&#xff0c;多进程效率高&#xff0c;推荐 多机多卡 模型并行 示例&#xff1a;

如何让自动化测试框架更自动化?

一、引言 ​对于大厂的同学来说&#xff0c;接口自动化是个老生常谈的话题了&#xff0c;毕竟每年的MTSC大会议题都已经能佐证了&#xff0c;不是大数据测试&#xff0c;就是AI测试等等&#xff08;越来越高大上了&#xff09;。不可否认这些专项的方向是质量智能化发展的方向&…

Redis基本数据结构

Redis基本数据结构 ​Redis​是C​语言开发的一个开源的&#xff08;遵从BSD​协议&#xff09;高性能键值对&#xff08;key-value​&#xff09;的内存数据库&#xff0c;可以用作数据库、缓存、消息中间件等。它是一种NoSQL​&#xff08;not-only sql​&#xff0c;泛指非…

几种不同的方式禁止IP访问网站(PHP、Nginx、Apache设置方法)

1、PHP禁止IP和IP段访问 <?//禁止某个IP$banned_ip array ("127.0.0.1",//"119.6.20.66","192.168.1.4");if ( in_array( getenv("REMOTE_ADDR"), $banned_ip ) ){die ("您的IP禁止访问&#xff01;");}//禁止某个IP段…

中国式报表怎么做?用这款免费可视化工具快速搞定复杂报表

1. 什么是中国式报表&#xff1f; 中国式报表是一种中国独有的复杂报表&#xff0c;有格式复杂、计算复杂、数据来源复杂等特点&#xff0c;并且还有多样化的功能要求&#xff0c;例如图形、联动、回填等。因此许多国外报表工具在制作中国式报表方便表现得有些“水土不服”&am…

UE5.3-基础蓝图类整理一

常用蓝图类整理&#xff1a; 1、获取当前关卡名&#xff1a;Get Current LevelName 2、通过关卡名打开关卡&#xff1a;Open Level(by name) 3、碰撞检测事件&#xff1a;Event ActorBeginOverlap 4、获取当前player&#xff1a;Get Player Pawn 5、判断是否相等&#xff1…

基于OpenCv的快速图片颜色交换,轻松实现图片背景更换

图片颜色更换 图片颜色转换 当我们有2张图片,很喜欢第一张图片的颜色,第2张图片的前景照片,很多时候我们需要PS进行图片的颜色转换,这当然需要我们有强大的PS功底,当然小编这里不是介绍PS的,我们使用代码完全可以代替PS 进行图片的颜色转换 图片颜色转换步骤: 步骤…

中职网络安全B模块Cenots6.8数据库

任务环境说明&#xff1a; ✓ 服务器场景&#xff1a;CentOS6.8&#xff08;开放链接&#xff09; ✓ 用户名&#xff1a;root&#xff1b;密码&#xff1a;123456 进入虚拟机操作系统&#xff1a;CentOS 6.8&#xff0c;登陆数据库&#xff08;用户名&#xff1a;root&#x…

海南云亿商务咨询有限公司抖音电商服务领军者

在当今这个数字化高速发展的时代&#xff0c;抖音电商已经成为了一种不可忽视的新型商业模式。作为行业的佼佼者&#xff0c;海南云亿商务咨询有限公司凭借其专业团队和卓越的服务能力&#xff0c;为众多商家提供了一站式的抖音电商解决方案&#xff0c;助力商家在竞争激烈的市…

【C++项目】从零实现一个在线编译器

前言 身为一名程序员&#xff0c;想必大家都有接触过像leetcode这样的刷题网站&#xff0c;不知你们在刷题的过程中是否思考过一个问题&#xff1a;它们是如何实现在线编译运行的功能。如果你对此感到好奇&#xff0c;那么本文将一步步带你来实现一个简易在线编译器。 项目概…

Django项目的基本准备工作【1】

【 一 】pip换源 # 1 之前装第三方模块 pip3 install django -i 镜像仓库 ​ # 2 一劳永逸--》整点配置&#xff0c;以后安装模块&#xff0c;自动去配置好的源下载 ###windows 1、文件管理器文件路径地址栏敲&#xff1a;%APPDATA% 回车&#xff0c;快速进入 C:\Users\电脑用…

【Python】已解决:ModuleNotFoundError: No module named ‘nltk’

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;ModuleNotFoundError: No module named ‘nltk’ 一、分析问题背景 在使用Python进行自然语言处理或文本分析时&#xff0c;我们经常会用到各种库来辅助我们的工…

C++Windows环境搭建(CLion)

文章目录 CLion下载安装CLion下载CLion安装新建项目新建一个文件基础设置字体设置clion中单工程多main函数设置 参考 CLion下载安装 CLion下载 打开网址&#xff1a;https://www.jetbrains.com/clion/download/ 点击Download进行下载。 CLion安装 双击下载好的安装包&…

1.9-改进的CBOW模型的实现

文章目录 0引言1 CBOW模型的重构1.1模型初始化1.2模型的前向计算1.3模型的反向传播 2总结 0引言 前面讲述了对word2vec高速化的改进&#xff1a; 改进输入侧的计算&#xff0c;变成Embedding&#xff0c;即从权重矩阵中选取特定的行&#xff1b;改进输出侧的计算&#xff0c;包…

100359.统计X和Y频数相等的子矩阵数量

1.题目描述 给你一个二维字符矩阵 grid&#xff0c;其中 grid[i][j] 可能是 X、Y 或 .&#xff0c;返回满足以下条件的子矩阵数量&#xff1a; 包含 grid[0][0]X 和 Y 的频数相等。至少包含一个 X。 示例 1&#xff1a; 输入&#xff1a; grid [["X","Y",…