【華為云-上云之路】手把手教你用ModelArts基于FasterRCNN算法實現物體檢測
華為云—華為公司傾力打造的云戰略品牌,2011年成立,致力于為全球客戶提供領先的公有云服務,包含彈性云服務器、云數據庫、云安全等云計算服務,軟件開發服務,面向企業的大數據和人工智能服務,以及場景化的解決方案。

華為云用在線的方式將華為30多年在ICT基礎設施領域的技術積累和產品解決方案開放給客戶,致力于提供穩定可靠、安全可信、可持續創新的云服務,做智能世界的“黑土地”,推進實現“用得起、用得好、用得放心”的普惠AI。華為云作為底座,為華為全棧全場景AI戰略提供強大的算力平臺和更易用的開發平臺。
華為云官方網站
ModelArts是華為云產品中面向開發者的一站式AI開發平臺,為機器學習與深度學習提供海量數據預處理及半自動化標注、大規模分布式Training、自動化模型生成,及端-邊-云模型按需部署能力,幫助用戶快速創建和部署模型,管理全周期AI工作流。
華為云官方網站
基于FasterRCNN算法實現物體檢測
本實驗我們將聚焦于用FasterRCNN算法實現物體檢測,在ModelArts的Notebook開發環境中實現用FasterRCNN算法構建一個物體檢測的神經網絡模型,并在該環境中實現對物體檢測神經網絡模型的訓練與測試,最終達到實現物體檢測的實驗目的。
基于FasterRCNN算法實現物體檢測實驗流程
1.準備實驗環境與創建開發環境
2.下載數據與訓練代碼
3.準備數據
4.FasterRCNN模型訓練
5.FasterRCNN模型測試
1
1.1進入ModelArts
首先需要進入華為云Modelarts主頁,輸入自己的賬號密碼:
https://www.huaweicloud.com/product/modelarts.html
點擊進入“進入控制臺”
在左側開發環境處,點擊Notebook:
點擊“創建”,填寫配置信息:
名稱:自定義(此處我設置的是notebook-fasterrcnn)
工作環境:Python3
資源池:公共資源池
類型:GPU
規格:體驗規格GPU(這樣就不要花費)
存儲配置:云硬盤
這里我說說我對云硬盤與對象存儲服務的理解:
云硬盤對應的是云服務器,就如同電腦的自帶硬盤,存儲在云硬盤的數據可以隨時的在云端查看。
對象存儲服務就如同移動硬盤,可以隨時做資料備份。
按“下一步”確認信息無誤,點擊“提交”即可:
即可完成創建:
點擊“返回Notebook列表”,即看到正在運行的Notebook環境:
點擊進入創建的notebook-fasterrcnn中:
點擊選擇右側的“New”
點擊選擇Pytorch-1.0.0開發環境后,進入頁面:
輸入下面代碼后,點擊“Run”進行測試:
print("Hello world!")
成功輸出“Hello world!”,說明環境配置正確
2
2.數據和代碼下載
點擊“Run”運行下面代碼,進行實驗代碼和實驗數據的下載和解壓:
from?modelarts.session?import?Session
sess = Session()
if?sess.region_name ==?'cn-north-1':
bucket_path="modelarts-labs/notebook/DL_object_detection_faster/fasterrcnn.tar.gz"
elif?sess.region_name ==?'cn-north-4':
bucket_path="modelarts-labs-bj4/notebook/DL_object_detection_faster/fasterrcnn.tar.gz"
else:
print("請更換地區到北京一或北京四")
sess.download_data(bucket_path=bucket_path, path="./fasterrcnn.tar.gz")
# 解壓文件
!tar -xf ./fasterrcnn.tar.gz
# 清理壓縮包
!rm -r ./fasterrcnn.tar.gz
本案例使用PASCAL VOC 2007數據集訓練模型,共20個類別的物體:
下載后的代碼和數據保存在了之前設置的云硬盤(EVS)中
這里是已經下載好的文件目錄:
安裝依賴:
!pip?install?pycocotools==2.0.0
!pip?install?torchvision==0.4.0
!pip?install?protobuf==3.9.0
運行之后的頁面如下:
利用下面兩段代碼引用之前安裝的依賴:
代碼1:
import?tools._init_paths
%matplotlib inline
from?__future__?import?absolute_import
from?__future__?import?division
from?__future__?import?print_function
import?tensorboardX?as?tb
from?datasets.factory?import?get_imdb
from?model.train_val?import?get_training_roidb, train_net
from?model.config?import?cfg, cfg_from_file, cfg_from_list, get_output_dir, get_output_tb_dir
代碼2:
import?roi_data_layer.roidb?as?rdl_roidb
from?roi_data_layer.layer?import?RoIDataLayer
import?utils.timer
import?pickle
import?torch
import?torch.optim?as?optim
from?nets.vgg16?import?vgg16
import?numpy?as?np
import?os
import?sys
import?glob
import?time
運行之后的頁面如下:
3
3.神經網絡搭建
為了節省時間,運行以下代碼,本實驗將在預訓練模型的基礎上進行訓練。實驗中我們使用VGG16作為FasterRCNN的主干網絡:
imdb_name?=?"voc_2007_trainval"
imdbval_name?=?"voc_2007_test"
# 使用的預訓練模型位置
weight?=?"./data/imagenet_weights/vgg16.pth"
# 訓練迭代次數
max_iters?=?100
# cfg模型文件位置
cfg_file?= None
set_cfgs?= None
運行結果如下:
運行下面代碼,定義讀取數據集函數:
數據集的標注格式是PASCAL VOC格式。
def?combined_roidb(imdb_names):
def?get_roidb(imdb_name):
# 加載數據集
imdb = get_imdb(imdb_name)
print('Loaded dataset `{:s}` for training'.format(imdb.name))
# 使用ground truth作為數據集策略
imdb.set_proposal_method(cfg.TRAIN.PROPOSAL_METHOD)
print('Set proposal method: {:s}'.format(cfg.TRAIN.PROPOSAL_METHOD))
roidb = get_training_roidb(imdb)
return?roidb
roidbs = [get_roidb(s)?for?s?in?imdb_names.split('+')]
roidb = roidbs[0]
if?len(roidbs) >?1:
for?r?in?roidbs[1:]:
roidb.extend(r)
tmp = get_imdb(imdb_names.split('+')[1])
imdb = datasets.imdb.imdb(imdb_names, tmp.classes)
else:
imdb = get_imdb(imdb_names)
return?imdb, roidb
運行界面:
運行下面代碼,設置模型訓練參數:
if?cfg_file?is?not?None:
cfg_from_file(cfg_file)
if?set_cfgs?is?not?None:
cfg_from_list(set_cfgs)
print('Using config:')
print(cfg)
np.random.seed(cfg.RNG_SEED)
# 加載訓練數據集
imdb, roidb = combined_roidb(imdb_name)
print('{:d} roidb entries'.format(len(roidb)))
# 設置輸出路徑
output_dir = get_output_dir(imdb,None)
print('Output will be saved to `{:s}`'.format(output_dir))
# 設置日志保存路徑
tb_dir = get_output_tb_dir(imdb,?None)
print('TensorFlow summaries will be saved to `{:s}`'.format(tb_dir))
# 加載驗證數據集
orgflip = cfg.TRAIN.USE_FLIPPED
cfg.TRAIN.USE_FLIPPED =?False
_, valroidb = combined_roidb(imdbval_name)
print('{:d} validation roidb entries'.format(len(valroidb)))
cfg.TRAIN.USE_FLIPPED = orgflip
# 創建backbone網絡
# 在案例中使用的是VGG16模型,可以嘗試其他不同的模型結構,例如Resnet等
net = vgg16()
運行界面:
v
運行下面代碼,對ROI進行篩選,將無效的ROI數據篩選掉:
from?model.train_val?import?filter_roidb, SolverWrapper
# 對ROI進行篩選,將無效的ROI數據篩選掉
roidb = filter_roidb(roidb)
valroidb = filter_roidb(valroidb)
sw = SolverWrapper(
net,
imdb,
roidb,
valroidb,
output_dir,
tb_dir,
pretrained_model=weight)
print('Solving...')
運行界面:
運行下面代碼,顯示所有模型屬性:
# 顯示所有模型屬性
sw.__dict__.keys()
運行界面如下:
運行下面代碼,輸出查看主干網絡:
#?sw.net為主干網絡
print(sw.net)
運行界面如下:
定義神經網絡結構,使用PyTorch搭建神經網絡:
# 構建網絡結構,模型加入ROI數據層
sw.data_layer = RoIDataLayer(sw.roidb,?sw.imdb.num_classes)
sw.data_layer_val = RoIDataLayer(sw.valroidb,?sw.imdb.num_classes, random=True)
# 構建網絡結構,在VGG16基礎上加入ROI和Classifier部分
lr, train_op =?sw.construct_graph()
# 加載之前的snapshot
lsf, nfiles, sfiles =?sw.find_previous()
# snapshot 為訓練提供了斷點訓練,如果有snapshot將加載進來,繼續訓練
if?lsf ==?0:
lr, last_snapshot_iter, stepsizes, np_paths, ss_paths =?sw.initialize()
else:
lr, last_snapshot_iter, stepsizes, np_paths, ss_paths =?sw.restore(str(sfiles[-1]), str(nfiles[-1]))
iter = last_snapshot_iter +?1
last_summary_time = time.time()
# 在之前的訓練基礎上繼續進行訓練
stepsizes.append(max_iters)
stepsizes.reverse()
next_stepsize = stepsizes.pop()
# 將net切換成訓練模式
print("網絡結構:")
sw.net.train()
sw.net.to(sw.net._device)
運行界面如下:
4
4.FasterRCNN模型訓練
本實驗使用的是Pytorch深度學習框架搭建FasterRCNN神經網絡模型。
在實驗中可以進入Notebook的管理控制臺查看相應的源碼實現。
訓練神經網絡:
while?iter < max_iters +?1:
cfg.SNAPSHOT_PREFIX =?"VGG_faster_rcnn"
if?iter == next_stepsize +?1:
# 加入snapshot節點
sw.snapshot(iter)
lr?*= cfg.TRAIN.GAMMA
scale_lr(sw.optimizer, cfg.TRAIN.GAMMA)
next_stepsize = stepsizes.pop()
utils.timer.timer.tic()
# 數據通過ROI數據層,進行前向計算
blobs =?sw.data_layer.forward()
now = time.time()
if?iter ==?1?or?now - last_summary_time > cfg.TRAIN.SUMMARY_INTERVAL:
# 計算loss函數
# 根據loss函數對模型進行訓練
rpn_loss_cls, rpn_loss_box, loss_cls, loss_box, total_loss, summary = \
sw.net.train_step_with_summary(blobs,?sw.optimizer)
for?_sum in summary:
sw.writer.add_summary(_sum, float(iter))
# 進行數據層驗證計算
blobs_val =?sw.data_layer_val.forward()
summary_val =?sw.net.get_summary(blobs_val)
for?_sum in summary_val:
sw.valwriter.add_summary(_sum, float(iter))
last_summary_time = now
else:
rpn_loss_cls, rpn_loss_box, loss_cls, loss_box, total_loss = \
sw.net.train_step(blobs,?sw.optimizer)
utils.timer.timer.toc()
if?iter % (cfg.TRAIN.DISPLAY) ==?0:
print('iter: %d / %d, total loss: %.6f\n >>> rpn_loss_cls: %.6f\n '
'>>> rpn_loss_box: %.6f\n >>> loss_cls: %.6f\n >>> loss_box: %.6f\n >>> lr: %f'?% \
(iter, max_iters, total_loss, rpn_loss_cls, rpn_loss_box, loss_cls, loss_box,?lr))
print('speed: {:.3f}s / iter'.format(
utils.timer.timer.average_time()))
# 進行snapshot存儲
if?iter % cfg.TRAIN.SNAPSHOT_ITERS ==?0:
last_snapshot_iter = iter
ss_path, np_path =?sw.snapshot(iter)
np_paths.append(np_path)
ss_paths.append(ss_path)
# 刪掉多余的snapshot
if?len(np_paths) > cfg.TRAIN.SNAPSHOT_KEPT:
sw.remove_snapshot(np_paths, ss_paths)
iter +=?1
if?last_snapshot_iter != iter -?1:
sw.snapshot(iter -?1)
sw.writer.close()
sw.valwriter.close()
點擊“Run”,運行界面如下:
5
運行以下代碼,點擊“Run”,利用訓練得到的代碼進行推理測試:
%matplotlib inline
from?__future__?import?absolute_import
from?__future__?import?division
from?__future__?import?print_function
# 將路徑轉入lib
import?tools._init_paths
from?model.config?import?cfg
from?model.test?import?im_detect
from?torchvision.ops?import?nms
from?utils.timer?import?Timer
import?matplotlib.pyplot?as?plt
import?numpy?as?np
import?os, cv2
import?argparse
from?nets.vgg16?import?vgg16
from?nets.resnet_v1?import?resnetv1
from?model.bbox_transform?import?clip_boxes, bbox_transform_inv
import?torch
運行界面如下:
運行下面代碼進行模型參數定義:
# PASCAL VOC類別設置
CLASSES = ('__background__',
'aeroplane',?'bicycle',?'bird',?'boat',
'bottle',?'bus',?'car',?'cat',?'chair',
'cow',?'diningtable',?'dog',?'horse',
'motorbike',?'person',?'pottedplant',
'sheep',?'sofa',?'train',?'tvmonitor')
# 網絡模型文件名定義
NETS = {'vgg16': ('vgg16_faster_rcnn_iter_%d.pth',),'res101': ('res101_faster_rcnn_iter_%d.pth',)}
# 數據集文件名定義
DATASETS= {'pascal_voc': ('voc_2007_trainval',),'pascal_voc_0712': ('voc_2007_trainval+voc_2012_trainval',)}
運行界面如下:
結果繪制,將預測的標簽和邊界框繪制在原圖上:
def?vis_detections(im, class_dets, thresh=0.5):
"""Draw detected bounding boxes."""
im = im[:, :, (2,?1,?0)]
fig, ax = plt.subplots(figsize=(12,?12))
ax.imshow(im, aspect='equal')
for?class_name?in?class_dets:
dets = class_dets[class_name]
inds = np.where(dets[:,?-1] >= thresh)[0]
if?len(inds) ==?0:
continue
for?i?in?inds:
bbox = dets[i, :4]
score = dets[i,?-1]
ax.add_patch(
plt.Rectangle((bbox[0], bbox[1]),
bbox[2] - bbox[0],
bbox[3] - bbox[1], fill=False,
edgecolor='red', linewidth=3.5)
)
ax.text(bbox[0], bbox[1] -?2,
'{:s} {:.3f}'.format(class_name, score),
bbox=dict(facecolor='blue', alpha=0.5),
fontsize=14, color='white')
plt.axis('off')
plt.tight_layout()
plt.draw()
運行結果如下所示:
繼續輸入代碼,選擇測試圖片的文件夾路徑:
test_file?=?"./test"
運行結果如下;
運行以下代碼,進行模型推理:
import?cv2
from?utils.timer?import?Timer
from?model.test?import?im_detect
from?torchvision.ops?import?nms
cfg.TEST.HAS_RPN =?True??# Use RPN for proposals
# 模型存儲位置
# 這里我們加載一個已經訓練110000迭代之后的模型,可以選擇自己的訓練模型位置
saved_model =?"./models/vgg16-voc0712/vgg16_faster_rcnn_iter_110000.pth"
print('trying to load weights from ', saved_model)
# 加載backbone
net = vgg16()
# 構建網絡
net.create_architecture(21, tag='default', anchor_scales=[8,?16,?32])
# 加載權重文件
net.load_state_dict(torch.load(saved_model, map_location=lambda?storage, loc: storage))
net.eval()
# 選擇推理設備
net.to(net._device)
print('Loaded network {:s}'.format(saved_model))
for?file?in?os.listdir(test_file):
if?file.startswith("._") ==?False:
file_path = os.path.join(test_file, file)
print(file_path)
# 打開測試圖片文件
im = cv2.imread(file_path)
# 定義計時器
timer = Timer()
timer.tic()
# 檢測得到圖片ROI
scores, boxes = im_detect(net, im)
print(scores.shape, boxes.shape)
timer.toc()
print('Detection took {:.3f}s for {:d} object proposals'.format(timer.total_time(), boxes.shape[0]))
# 定義閾值
CONF_THRESH =?0.7
NMS_THRESH =?0.3
cls_dets = {}
# NMS 非極大值抑制操作,過濾邊界框
for?cls_ind, cls?in?enumerate(CLASSES[1:]):
cls_ind +=?1?# 跳過 background
cls_boxes = boxes[:,?4*cls_ind:4*(cls_ind +?1)]
cls_scores = scores[:, cls_ind]
dets = np.hstack((cls_boxes,
cls_scores[:, np.newaxis])).astype(np.float32)
keep = nms(torch.from_numpy(cls_boxes), torch.from_numpy(cls_scores), NMS_THRESH)
dets = dets[keep.numpy(), :]
if?len(dets) >?0:
if?cls?in?cls_dets:
cls_dets[cls] = np.vstack([cls_dets[cls], dets])
else:
cls_dets[cls] = dets
vis_detections(im, cls_dets, thresh=CONF_THRESH)
plt.show()
運行界面如下:
測試1
利用步驟進行其它圖片測試:
測試2
測試3
測試4
測試5
測試6
至此實驗全部完成。
大家使用的云端資源記得全部刪除如ModelArts創建的Notebook開發環境需要刪除,并停用訪問密鑰,以免造成不必要的花費。
通過對實驗結果的比對,可以看出利用
[華為云ModelArts]訓練出來的物體檢測模型是很棒的,六個字總結就是-高效,快捷,省心。
正因我們國家有許多像華為這樣強大的民族企業在國家背后默默做支撐,做奉獻。我們國家才能屹立于世界民族之林。
華為,中國驕傲!中華有為!
人工智能 ModelArts
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。