昇思25天學習打卡營第十五天|基于MobileNetv2的垃圾分類

基于MobileNetv2的垃圾分類

MobileNetv2模型原理介紹

MobileNet網絡是由Google團隊于2017年提出的專注于移動端、嵌入式或IoT設備的輕量級CNN網絡,相比于傳統的卷積神經網絡,MobileNet網絡使用深度可分離卷積(Depthwise Separable Convolution)的思想在準確率小幅度降低的前提下,大大減小了模型參數與運算量。并引入寬度系數 α和分辨率系數 β使模型滿足不同應用場景的需求。

由于MobileNet網絡中Relu激活函數處理低維特征信息時會存在大量的丟失,所以MobileNetV2網絡提出使用倒殘差結構(Inverted residual block)和Linear Bottlenecks來設計網絡,以提高模型的準確率,且優化后的模型更小。
在這里插入圖片描述
圖中Inverted residual block結構是先使用1x1卷積進行升維,然后使用3x3的DepthWise卷積,最后使用1x1的卷積進行降維,與Residual block結構相反。Residual block是先使用1x1的卷積進行降維,然后使用3x3的卷積,最后使用1x1的卷積進行升維。

  • 說明:
    詳細內容可參見MobileNetV2論文

數據處理

數據準備

MobileNetV2的代碼默認使用ImageFolder格式管理數據集,每一類圖片整理成單獨的一個文件夾, 數據集結構如下:

└─ImageFolder

├─train
│   class1Folder
│   ......
└─evalclass1Folder......
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)
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)

數據加載

import math
import numpy as np
import os
import randomfrom 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, CheckpointConfigos.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 
})

數據預處理操作

利用ImageFolderDataset方法讀取垃圾分類數據集,并整體對數據集進行處理。

讀取數據集時指定訓練集和測試集,首先對整個數據集進行歸一化,修改圖像頻道等預處理操作。然后對訓練集的數據依次進行RandomCropDecodeResize、RandomHorizontalFlip、RandomColorAdjust、shuffle操作,以增加訓練數據的豐富度;對測試集進行Decode、Resize、CenterCrop等預處理操作;最后返回處理后的數據集。

def create_dataset(dataset_path, config, training=True, buffer_size=1000):"""create a train or eval datasetArgs: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()

MobileNetV2模型搭建

__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_vclass 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 xclass 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 outputclass 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 channelReturns: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 == ouplayers = []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 xclass 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 xdef _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.featuresclass 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 xdef _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.headclass 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_headdef construct(self, x):x = self.backbone(x)x = self.head(x)return xclass 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 = headdef construct(self, x):x = self.backbone(x)x = self.head(x)return xdef mobilenet_v2(backbone, head):return MobileNetV2Combine(backbone, head)

MobileNetV2模型的訓練與測試

訓練策略

一般情況下,模型訓練時采用靜態學習率,如0.01。隨著訓練步數的增加,模型逐漸趨于收斂,對權重參數的更新幅度應該逐漸降低,以減小模型訓練后期的抖動。所以,模型訓練時可以采用動態下降的學習率,常見的學習率下降策略有:

  • polynomial decay/square decay;
  • cosine decay;
  • exponential decay;
  • stage decay.

這里使用cosine 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

在模型訓練過程中,可以添加檢查點(Checkpoint)用于保存模型的參數,以便進行推理及中斷后再訓練使用。使用場景如下:

  • 訓練后推理場景
  1. 模型訓練完畢后保存模型的參數,用于推理或預測操作。
  2. 訓練過程中,通過實時驗證精度,把精度最高的模型參數保存下來,用于預測操作。
  • 再訓練場景
  1. 進行長時間訓練任務時,保存訓練過程中的Checkpoint文件,防止任務異常退出后從初始狀態開始訓練。
  2. 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)

模型訓練與測試

在進行正式的訓練之前,定義訓練函數,讀取數據并對模型進行實例化,定義優化器和損失函數。

首先簡單介紹損失函數及優化器的概念:

  • 損失函數:又叫目標函數,用于衡量預測值與實際值差異的程度。深度學習通過不停地迭代來縮小損失函數的值。定義一個好的損失函數,可以有效提高模型的性能。

  • 優化器:用于最小化損失函數,從而在訓練過程中改進模型。

定義了損失函數后,可以得到損失函數關于權重的梯度。梯度用于指示優化器優化權重的方向,以提高模型性能。

在訓練MobileNetV2之前對MobileNetV2Backbone層的參數進行了固定,使其在訓練過程中對該模塊的權重參數不進行更新;只對MobileNetV2Head模塊的參數進行更新。

MindSpore支持的損失函數有SoftmaxCrossEntropyWithLogits、L1Loss、MSELoss等。這里使用SoftmaxCrossEntropyWithLogits損失函數。

訓練測試過程中會打印loss值,loss值會波動,但總體來說loss值會逐步減小,精度逐步提高。每個人運行的loss值有一定隨機性,不一定完全相同。

每打印一個epoch后模型都會在測試集上的計算測試精度,從打印的精度值分析MobileNetV2模型的預測能力在不斷提升。

from mindspore.amp import FixedLossScaleManager
import time
LOSS_SCALE = 1024train_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 losssize = 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 ==============")

模型推理

加載模型Checkpoint進行推理,使用load_checkpoint接口加載數據時,需要把數據傳入給原始網絡,而不能傳遞給帶有優化器和損失函數的訓練網絡。

CKPT="save_mobilenetV2_model.ckpt"
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_tensordef 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()

導出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.pswp.cn/web/38749.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/38749.shtml
英文地址,請注明出處:http://en.pswp.cn/web/38749.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Zabbix 6.0 案例

自定義監控內容 案列&#xff1a;自定義監控客戶端服務器登錄的人數 需求&#xff1a;限制登錄人數不超過 3 個&#xff0c;超過 3 個就發出報警信息 1.在客戶端創建自定義 key 明確需要執行的 linux 命令 who | wc -l 2.在被監控主機的配置文件目錄中&#xff08;/etc/za…

港大推出XRec:「會說話」的推薦系統大模型, 從黑盒預測到可解釋

代碼鏈接: https://github.com/HKUDS/XRec 論文鏈接: https://arxiv.org/pdf/2406.02377 實驗室鏈接: https://sites.google.com/view/chaoh 最近,香港大學數據智能實驗室推出了一款名為 XRec 的全新智能大模型,旨在為傳統推薦系統注入可解釋性的新動力。XRec 利用大語言模型…

PyTorch入門筆記

學習參考&#xff1a; PyTorch簡單入門視頻 深入淺出PyTorch 小土堆筆記 前置知識 AI vs ML vs DL AI&#xff08;Artificial Intelligence&#xff09;&#xff1a;通過讓機器模仿人類進而超越人類ML&#xff08;Machine Learning&#xff09;&#xff1a;讓機器模仿人類的一…

【AI原理解析】—支持向量機原理

目錄 1. 支持向量機&#xff08;SVM&#xff09;概述 2. 超平面與支持向量 3. 間隔最大化 4. 優化問題 5. 核函數 6. 總結 1. 支持向量機&#xff08;SVM&#xff09;概述 定義&#xff1a;支持向量機是一種監督學習模型&#xff0c;主要用于數據分類問題。其基本思想是…

【C++】const詳解

&#x1f4e2;博客主頁&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;歡迎點贊 &#x1f44d; 收藏 ?留言 &#x1f4dd; 如有錯誤敬請指正&#xff01; &#x1f4e2;本文作為 JohnKi &#xff0c;引用了部分大佬的案例 &#x1f4e2;未來很長&#xff0c;…

Android 常用文件系統命令

Android 常用文件系統命令 當系統正在對某個文件系統的區域進行寫入操作時&#xff08;讀的話沒關系&#xff09;&#xff0c;突然斷電&#xff0c;會造成文件系統對應區域的損壞&#xff08;如寫入臟數據&#xff09;&#xff0c; 而e2fsck算法就是用來恢復受損的文件系統&am…

力扣1177.構建回文串檢測

力扣1177.構建回文串檢測 因為子串可以重新排序 因此考慮一下什么情況需要替換字母1.當前有一個字母的數量為奇數 需要替換的次數為0 2.當前有二個字母的數量為奇數 需要替換的次數為1 (奇數個a 奇數個b 需要將b -> a) 3.當前有三個字母的數量為奇數 需要替換的次數為1 4.當…

Edge瀏覽器選中后,出現AI智能生成 AI專業寫作

這個是擴展里邊的“ 網頁萬能復制 & ChatGPT AI寫作助手”造成的&#xff0c;這個拓展增加了AI寫作功能。關閉這個拓展就解決了。

入門Axure:快速掌握原型設計技能

2002 年&#xff0c;維克托和馬丁在舊金山灣區的一家初創公司工作&#xff0c;發現自己一再被軟件開發生命周期的限制所困擾&#xff0c;而且產品團隊在編寫規范之前很難評估他們的解決方案&#xff0c;開發人員經常不理解&#xff08;或不閱讀&#xff09;給出的規范&#xff…

承載網與核心網的區別

承載網和核心網是通信網絡中的兩個重要組成部分&#xff0c;它們有以下主要區別&#xff1a; 功能方面&#xff1a; 承載網主要負責提供數據傳輸的通道和鏈路&#xff0c;確保各種業務數據能夠在網絡中高效、可靠地傳輸。它類似于通信網絡中的“道路”&#xff0c;專注于數據的…

【linux學習---1】點亮一個LED---驅動一個GPIO

文章目錄 1、原理圖找對應引腳2、IO復用3、IO配置4、GPIO配置5、GPIO時鐘使能6、總結 1、原理圖找對應引腳 從上圖 可以看出&#xff0c; 蜂鳴器 接到了 BEEP 上&#xff0c; BEEP 就是 GPIO5_IO05 2、IO復用 查找IMX6UL參考手冊 和 STM32一樣&#xff0c;如果某個 IO 要作為…

14-16 AI Agent:您無法忽視的盈利未來

忘掉關于機器人接管我們工作的爭論吧。一場更加微妙、可能更有利可圖的革命正在醞釀之中——智能代理的崛起&#xff0c;而智能代理的光芒常常被其更簡單的“表親”虛擬助理所掩蓋。 雖然 Siri 和 Alexa 可以處理基本任務和基本對話&#xff0c;但人工智能代理則完全不同。想象…

HTML5的多線程技術:Web Worker API

Web Workers API 是HTML5的一項技術&#xff0c;它允許在瀏覽器后臺獨立于主線程運行腳本&#xff0c;即允許進行多線程處理。這對于執行密集型計算任務特別有用&#xff0c;因為它可以防止這些任務阻塞用戶界面&#xff0c;從而保持網頁的響應性和交互性。Web Workers在自己的…

中國動物志(140卷)

中國動物志&#xff0c;共140卷&#xff0c;包括昆蟲綱、鳥綱、獸綱、無脊椎動物、硬骨魚綱等多類&#xff0c;是反映我國動物分類區系研究工作成果的系列專著&#xff0c;是研究物種多樣性、探討物種演化和系統發育的重要參考&#xff0c;是動物資源開發利用、有害物種控制、瀕…

昇思25天學習打卡營第12天|linchenfengxue

DCGAN生成漫畫頭像 通過示例代碼說明DCGAN網絡如何設置網絡、優化器、如何計算損失函數以及如何初始化模型權重。 GAN基礎原理 生成式對抗網絡(Generative Adversarial Networks&#xff0c;GAN)是一種生成式機器學習模型&#xff0c;是近年來復雜分布上無監督學習最具前景的…

esp32 模擬藍牙鍵盤不生效一例

esp32 使用 GitHub - T-vK/ESP32-BLE-Keyboard: Bluetooth LE Keyboard library for the ESP32 (Arduino IDE compatible) 這個開源庫模擬鍵盤功能早之前已經玩過&#xff0c;生效&#xff0c;昨天再來玩的時候發覺莫名奇妙居然又不能用了&#xff0c;各種折騰&#xff1a;換了…

如何在Java中使用Kafka

如何在Java中使用Kafka 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01; Kafka是一個分布式流處理平臺&#xff0c;廣泛用于實時數據流的處理和傳輸。本文將詳細…

什么是Web3D交互展示?有什么優勢?

在智能互聯網蓬勃發展的時代&#xff0c;傳統的圖片、文字及視頻等展示手段因缺乏互動性&#xff0c;正逐漸在吸引用戶注意力和提升宣傳效果上顯得力不從心。而Web3D交互展示技術的橫空出世&#xff0c;則為眾多品牌與企業開啟了一扇全新的展示之門&#xff0c;讓線上產品體驗從…

【C語言】extern 關鍵字

在C語言中&#xff0c;extern關鍵字用于聲明一個變量或函數是定義在另一個文件中的。它使得在多個文件之間共享變量或函數成為可能。extern關鍵字常見于大型項目中&#xff0c;通常用于聲明全局變量或函數&#xff0c;這些變量或函數的定義位于其他文件中。 基本用法 變量聲明…

Python基礎入門知識

目錄 引言 簡要介紹Python語言 為什么要學習Python Python的應用領域 Python安裝和環境配置 Python的下載和安裝(Windows, macOS, Linux) 配置Python環境變量 安裝和使用IDE(如PyCharm, VS Code) Python基本語法 注釋 變量和數據類型(數字,字符串,列表,元組,字典,…