最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

MobileOne實戰(zhàn):使用MobileOne實現(xiàn)圖像分類任務(wù)(一)

2023-04-11 19:37 作者:AI小浩  | 我要投稿

@

  • 安裝timm


摘要

論文地址:https://arxiv.org/abs/2211.06088 代碼地址:https://github.com/federicopozzi33/MobileOne-PyTorch 另一個版本:https://github.com/shoutOutYangJie/MobileOne 特征重用一直是輕量級卷積神經(jīng)網(wǎng)絡(luò)設(shè)計的關(guān)鍵技術(shù)。隨著YoloV6和YoloV7的使用,這種方式越來越流行,MobileOne,也是這種方式。MobileOne(≈MobileNetV1+RepVGG+訓練Trick)是由Apple公司提出的一種基于iPhone12優(yōu)化的超輕量型架構(gòu),在ImageNet數(shù)據(jù)集上以<1ms的速度取得了75.9%的Top1精度。下圖展示MobileOne訓練和推理Block結(jié)構(gòu):

上圖,展示了原始的Ghost Bottleneck、RG-bneck train和RG-bneck inference的結(jié)構(gòu)。我通過上圖可以清楚的看到Ghos Bottleneck和RG-bneck的結(jié)構(gòu)。

ModelParams(M)Top-1 Acc.(%)MobileOne-S02.171.4MobileOne-S14.875.9MobileOne-S27.877.4MobileOne-S310.178.1MobileOne-S414.879.4

MobileOne包含多個模型,這篇文章選擇用的是 MobileOne-S4x的模型。由于沒有預(yù)訓練,我們直接訓練次數(shù)會比較多,得分也會不如有預(yù)訓練的模型高,只達到了90%。所以本篇文章只是演示如何訓練和推理MobileOne模型。

在這里插入圖片描述

通過這篇文章能讓你學到:

  1. 如何使用數(shù)據(jù)增強,包括transforms的增強、CutOut、MixUp、CutMix等增強手段?

  2. 如何實現(xiàn)MobileOne模型實現(xiàn)訓練?

  3. 如何使用pytorch自帶混合精度?

  4. 如何使用梯度裁剪防止梯度爆炸?

  5. 如何使用DP多顯卡訓練?

  6. 如何繪制loss和acc曲線?

  7. 如何生成val的測評報告?

  8. 如何編寫測試腳本測試測試集?

  9. 如何使用余弦退火策略調(diào)整學習率?

  10. 如何使用AverageMeter類統(tǒng)計ACC和loss等自定義變量?

  11. 如何理解和統(tǒng)計ACC1和ACC5?

  12. 如何使用EMA?

安裝包

安裝timm

使用pip就行,命令:

pip?install?timm

數(shù)據(jù)增強Cutout和Mixup

為了提高成績我在代碼中加入Cutout和Mixup這兩種增強方式。實現(xiàn)這兩種增強需要安裝torchtoolbox。安裝命令:

pip?install?torchtoolbox

Cutout實現(xiàn),在transforms中。

from?torchtoolbox.transform?import?Cutout
#?數(shù)據(jù)預(yù)處理
transform?=?transforms.Compose([
????transforms.Resize((224,?224)),
????Cutout(),
????transforms.ToTensor(),
????transforms.Normalize([0.5,?0.5,?0.5],?[0.5,?0.5,?0.5])

])

需要導入包:from timm.data.mixup import Mixup,

定義Mixup,和SoftTargetCrossEntropy

??mixup_fn?=?Mixup(
????mixup_alpha=0.8,?cutmix_alpha=1.0,?cutmix_minmax=None,
????prob=0.1,?switch_prob=0.5,?mode='batch',
????label_smoothing=0.1,?num_classes=12)
?criterion_train?=?SoftTargetCrossEntropy()

參數(shù)詳解:

mixup_alpha (float): mixup alpha 值,如果 > 0,則 mixup 處于活動狀態(tài)。

cutmix_alpha (float):cutmix alpha 值,如果 > 0,cutmix 處于活動狀態(tài)。

cutmix_minmax (List[float]):cutmix 最小/最大圖像比率,cutmix 處于活動狀態(tài),如果不是 None,則使用這個 vs alpha。

如果設(shè)置了 cutmix_minmax 則cutmix_alpha 默認為1.0

prob (float): 每批次或元素應(yīng)用 mixup 或 cutmix 的概率。

switch_prob (float): 當兩者都處于活動狀態(tài)時切換cutmix 和mixup 的概率 。

mode (str): 如何應(yīng)用 mixup/cutmix 參數(shù)(每個'batch','pair'(元素對),'elem'(元素)。

correct_lam (bool): 當 cutmix bbox 被圖像邊框剪裁時應(yīng)用。 lambda 校正

label_smoothing (float):將標簽平滑應(yīng)用于混合目標張量。

num_classes (int): 目標的類數(shù)。

EMA

EMA(Exponential Moving Average)是指數(shù)移動平均值。在深度學習中的做法是保存歷史的一份參數(shù),在一定訓練階段后,拿歷史的參數(shù)給目前學習的參數(shù)做一次平滑。具體實現(xiàn)如下:

"""?Exponential?Moving?Average?(EMA)?of?model?updates

Hacked?together?by?/?Copyright?2020?Ross?Wightman
"""

import?logging
from?collections?import?OrderedDict
from?copy?import?deepcopy
import?torch
import?torch.nn?as?nn

_logger?=?logging.getLogger(__name__)

class?ModelEma:
????def?__init__(self,?model,?decay=0.9999,?device='',?resume=''):
????????#?make?a?copy?of?the?model?for?accumulating?moving?average?of?weights
????????self.ema?=?deepcopy(model)
????????self.ema.eval()
????????self.decay?=?decay
????????self.device?=?device??#?perform?ema?on?different?device?from?model?if?set
????????if?device:
????????????self.ema.to(device=device)
????????self.ema_has_module?=?hasattr(self.ema,?'module')
????????if?resume:
????????????self._load_checkpoint(resume)
????????for?p?in?self.ema.parameters():
????????????p.requires_grad_(False)

????def?_load_checkpoint(self,?checkpoint_path):
????????checkpoint?=?torch.load(checkpoint_path,?map_location='cpu')
????????assert?isinstance(checkpoint,?dict)
????????if?'state_dict_ema'?in?checkpoint:
????????????new_state_dict?=?OrderedDict()
????????????for?k,?v?in?checkpoint['state_dict_ema'].items():
????????????????#?ema?model?may?have?been?wrapped?by?DataParallel,?and?need?module?prefix
????????????????if?self.ema_has_module:
????????????????????name?=?'module.'?+?k?if?not?k.startswith('module')?else?k
????????????????else:
????????????????????name?=?k
????????????????new_state_dict[name]?=?v
????????????self.ema.load_state_dict(new_state_dict)
????????????_logger.info("Loaded?state_dict_ema")
????????else:
????????????_logger.warning("Failed?to?find?state_dict_ema,?starting?from?loaded?model?weights")

????def?update(self,?model):
????????#?correct?a?mismatch?in?state?dict?keys
????????needs_module?=?hasattr(model,?'module')?and?not?self.ema_has_module
????????with?torch.no_grad():
????????????msd?=?model.state_dict()
????????????for?k,?ema_v?in?self.ema.state_dict().items():
????????????????if?needs_module:
????????????????????k?=?'module.'?+?k
????????????????model_v?=?msd[k].detach()
????????????????if?self.device:
????????????????????model_v?=?model_v.to(device=self.device)
????????????????ema_v.copy_(ema_v?*?self.decay?+?(1.?-?self.decay)?*?model_v)

加入到模型中。

#初始化
if?use_ema:
?????model_ema?=?ModelEma(
????????????model_ft,
????????????decay=model_ema_decay,
????????????device='cpu',
????????????resume=resume)

#?訓練過程中,更新完參數(shù)后,同步update?shadow?weights
def?train():
????optimizer.step()
????if?model_ema?is?not?None:
????????model_ema.update(model)


#?將model_ema傳入驗證函數(shù)中
val(model_ema.ema,?DEVICE,?test_loader)

導入模型文件

文件的路徑:https://github.com/federicopozzi33/MobileOne-PyTorch 將mobileone_pytorch文件夾復制到項目的根目錄。

項目結(jié)構(gòu)

MobileOne_demo
├─data1
│??├─Black-grass
│??├─Charlock
│??├─Cleavers
│??├─Common?Chickweed
│??├─Common?wheat
│??├─Fat?Hen
│??├─Loose?Silky-bent
│??├─Maize
│??├─Scentless?Mayweed
│??├─Shepherds?Purse
│??├─Small-flowered?Cranesbill
│??└─Sugar?beet
├─mobileone_pytorch
│??├─__init__.py
│??├─_depthwise_convolution.py
│??├─_mobileone_block.py
│??├─_mobileone_block_down.py
│??├─_mobileone_block_up.py
│??├─_mobileone_component.py
│??├─_mobileone_getters.py
│??├─_mobileone_network.py
│??├─_pointwise_convolution.py
│??├─_reparametrizable_module.py
│??└─_reparametrize.py
├─mean_std.py
├─makedata.py
├─train.py
└─test.py

mean_std.py:計算mean和std的值。 makedata.py:生成數(shù)據(jù)集。

為了能在DP方式中使用混合精度,還需要在模型的forward函數(shù)前增加@autocast(),如果使用GPU訓練導入包from torch.cuda.amp import autocast,如果使用CPU,則導入from torch.cpu.amp import autocast。

計算mean和std

為了使模型更加快速的收斂,我們需要計算出mean和std的值,新建mean_std.py,插入代碼:

from?torchvision.datasets?import?ImageFolder
import?torch
from?torchvision?import?transforms

def?get_mean_and_std(train_data):
????train_loader?=?torch.utils.data.DataLoader(
????????train_data,?batch_size=1,?shuffle=False,?num_workers=0,
????????pin_memory=True)
????mean?=?torch.zeros(3)
????std?=?torch.zeros(3)
????for?X,?_?in?train_loader:
????????for?d?in?range(3):
????????????mean[d]?+=?X[:,?d,?:,?:].mean()
????????????std[d]?+=?X[:,?d,?:,?:].std()
????mean.div_(len(train_data))
????std.div_(len(train_data))
????return?list(mean.numpy()),?list(std.numpy())

if?__name__?==?'__main__':
????train_dataset?=?ImageFolder(root=r'data1',?transform=transforms.ToTensor())
????print(get_mean_and_std(train_dataset))

數(shù)據(jù)集結(jié)構(gòu):

image-20220221153058619

運行結(jié)果:

([0.3281186,?0.28937867,?0.20702125],?[0.09407319,?0.09732835,?0.106712654])

把這個結(jié)果記錄下來,后面要用!

生成數(shù)據(jù)集

我們整理還的圖像分類的數(shù)據(jù)集結(jié)構(gòu)是這樣的

data
├─Black-grass
├─Charlock
├─Cleavers
├─Common?Chickweed
├─Common?wheat
├─Fat?Hen
├─Loose?Silky-bent
├─Maize
├─Scentless?Mayweed
├─Shepherds?Purse
├─Small-flowered?Cranesbill
└─Sugar?beet

pytorch和keras默認加載方式是ImageNet數(shù)據(jù)集格式,格式是

├─data
│??├─val
│??│???├─Black-grass
│??│???├─Charlock
│??│???├─Cleavers
│??│???├─Common?Chickweed
│??│???├─Common?wheat
│??│???├─Fat?Hen
│??│???├─Loose?Silky-bent
│??│???├─Maize
│??│???├─Scentless?Mayweed
│??│???├─Shepherds?Purse
│??│???├─Small-flowered?Cranesbill
│??│???└─Sugar?beet
│??└─train
│??????├─Black-grass
│??????├─Charlock
│??????├─Cleavers
│??????├─Common?Chickweed
│??????├─Common?wheat
│??????├─Fat?Hen
│??????├─Loose?Silky-bent
│??????├─Maize
│??????├─Scentless?Mayweed
│??????├─Shepherds?Purse
│??????├─Small-flowered?Cranesbill
│??????└─Sugar?beet

新增格式轉(zhuǎn)化腳本makedata.py,插入代碼:

import?glob
import?os
import?shutil

image_list=glob.glob('data1/*/*.png')
print(image_list)
file_dir='data'
if?os.path.exists(file_dir):
????print('true')
????#os.rmdir(file_dir)
????shutil.rmtree(file_dir)#刪除再建立
????os.makedirs(file_dir)
else:
????os.makedirs(file_dir)

from?sklearn.model_selection?import?train_test_split
trainval_files,?val_files?=?train_test_split(image_list,?test_size=0.3,?random_state=42)
train_dir='train'
val_dir='val'
train_root=os.path.join(file_dir,train_dir)
val_root=os.path.join(file_dir,val_dir)
for?file?in?trainval_files:
????file_class=file.replace("\\","/").split('/')[-2]
????file_name=file.replace("\\","/").split('/')[-1]
????file_class=os.path.join(train_root,file_class)
????if?not?os.path.isdir(file_class):
????????os.makedirs(file_class)
????shutil.copy(file,?file_class?+?'/'?+?file_name)

for?file?in?val_files:
????file_class=file.replace("\\","/").split('/')[-2]
????file_name=file.replace("\\","/").split('/')[-1]
????file_class=os.path.join(val_root,file_class)
????if?not?os.path.isdir(file_class):
????????os.makedirs(file_class)
????shutil.copy(file,?file_class?+?'/'?+?file_name)

完成上面的內(nèi)容就可以開啟訓練和測試了。


MobileOne實戰(zhàn):使用MobileOne實現(xiàn)圖像分類任務(wù)(一)的評論 (共 條)

分享到微博請遵守國家法律
常德市| 乐山市| 花垣县| 宝兴县| 澄江县| 河源市| 霍州市| 旬阳县| 沭阳县| 武邑县| 铅山县| 焉耆| 建瓯市| 如皋市| 潍坊市| 商都县| 岑溪市| 岗巴县| 宽城| 牡丹江市| 永新县| 桃江县| 本溪市| 秦皇岛市| 乐陵市| 曲沃县| 绵阳市| 晋州市| 兴隆县| 突泉县| 陇南市| 巫山县| 大邑县| 永登县| 左贡县| 正定县| 五家渠市| 武安市| 子洲县| 清远市| 耒阳市|