小白科研筆記 簡析SA SSD中的資料增強機制

2021-10-05 16:02:54 字數 4812 閱讀 2905

當前,目標檢測的深度網路一般訓練至少50個epoch。如果每個epoch餵入的資料都是一樣的,網路的誤差函式可能會快速下降,但是會有很大的機率出現過擬合。這就像高中的筆者一直死記硬背地做一套習題,掌握不了知識變通一樣。為了融匯貫通知識點,就需要做各式各樣的練習題。在深度學習裡,這就是資料增強(data augmentation),把輸入的資料進行變形(ground truth也隨之變化)。在點雲處理中,常見的資料增強方式有:

點雲上的部分點加高斯雜訊

點雲翻轉(稱之為flip),關於xyz軸做映象翻轉

點雲旋轉,關於xyz軸做旋轉

點雲放大/縮小

當點雲做了上述的變換後,ground truth也會隨著變動。比如3d目標檢測來說,點雲做旋轉或翻轉後,目標的真值3d框也需要做同樣的旋轉或者翻轉。使用資料增強後,每乙個epoch資料都是不太一樣的,目標檢測網路也會學會了隨機應變檢測目標的能力,進而提高了它的泛化能力。

直接檢視sa-ssd中資料增強的**(位於kitti.py中):

# 使用資料增強後,輸入資料和真值標籤同時做變換

# 下面是常見的四種資料增強方式:

self.augmentor.noise_per_object_(gt_bboxes, points, num_try=

100)

gt_bboxes, points = self.augmentor.random_flip(gt_bboxes, points)

gt_bboxes, points = self.augmentor.global_rotation(gt_bboxes, points)

gt_bboxes, points = self.augmentor.global_scaling(gt_bboxes, points)

上述**中的self.augmentor對應的是pointaugmentor類(位於point_augmentor.py)。接下來會分析這四種資料增強的具體操作方式。

這一節分析函式noise_per_object_。**如下所示:

# 函式自變數都比較直觀,不去做解釋

defnoise_per_object_

(self,

gt_boxes,

points=

none

, valid_mask=

none

, num_try=

100)

:"""random rotate or remove each groundtrutn independently.

use kitti viewer to test this function points_transform_

args:

gt_boxes: [n, 7], gt box in lidar.points_transform_

points: [m, 4], point cloud in lidar.

"""num_boxes = gt_boxes.shape[0]

# valid_mask 表示哪些點需要加雜訊;哪些點不需要加;一般預設是全體點雲做增強

if valid_mask is

none

: valid_mask = np.ones(

(num_boxes,

), dtype=np.bool_)

center_noise_std = np.array(self._center_noise_std, dtype=gt_boxes.dtype)

# 位置雜訊,高斯分布雜訊

loc_noises = np.random.normal(

scale=center_noise_std, size=

[num_boxes, num_try,3]

)# 旋轉雜訊,均勻分布雜訊

rot_noises = np.random.uniform(

self._global_rot_range[0]

, self._global_rot_range[1]

, size=

[num_boxes, num_try]

) origin =

[0.5

,0.5,0

] gt_box_corners = center_to_corner_box3d(gt_boxes, origin=origin, axis=2)

# 位置雜訊加在與大地所在的平面上,只有 xy 和 wl 和 theta 會變化

selected_noise = noise_per_box(gt_boxes[:,

[0,1

,3,4

,6]]

, valid_mask, loc_noises, rot_noises)

loc_transforms = select_transform(loc_noises, selected_noise)

rot_transforms = select_transform(rot_noises, selected_noise)

su***ces = corner_to_su***ces_3d_jit(gt_box_corners)

# 位姿雜訊作用在點雲和真值框上

if points is

notnone

: point_masks = points_in_convex_polygon_3d_jit(points[:,

:3], su***ces)

points_transform_(points, gt_boxes[:,

:3], point_masks, loc_transforms,

rot_transforms, valid_mask)

box3d_transform_(gt_boxes, loc_transforms, rot_transforms, valid_mask)

其實這一段**還是比較複雜的,咱暫先弄懂它的大致意圖哈。如果後續需要深入理解,再去做更詳細的分析吧。

這一節分析random_flip

def

random_flip

(self, gt_boxes, points, probability=

0.5)

: enable = np.random.choice(

[false

,true

], replace=

false

, p=[1

- probability, probability]

)if enable:

gt_boxes[:,

1]=-gt_boxes[:,

1]gt_boxes[:,

6]=-gt_boxes[:,

6]+ np.pi

points[:,

1]=-points[:,

1]return gt_boxes, points

這段**寫得挺好玩的。做翻轉指的是做y軸對稱的翻轉。

這一節分析global_rotation

def

global_rotation

(self, gt_boxes, points)

: noise_rotation = np.random.uniform(self._global_rot_range[0]

, \ self._global_rot_range[1]

) points[:,

:3]= rotation_points_single_angle(

points[:,

:3], noise_rotation, axis=2)

gt_boxes[:,

:3]= rotation_points_single_angle(

gt_boxes[:,

:3], noise_rotation, axis=2)

gt_boxes[:,

6]+= noise_rotation

return gt_boxes, points

做旋轉指的是在z軸上做旋轉。

這一節分析global_scaling

def

global_scaling

(self, gt_boxes, points)

: noise_scale = np.random.uniform(self._min_scale, self._max_scale)

points[:,

:3]*= noise_scale

gt_boxes[:,

:6]*= noise_scale

return gt_boxes, points

做縮放指的是在xyz軸上做縮放。

資料增強的方式比較簡單,但是在實際過程中還是很有用的。

VC 中的 T 簡析

windows使用兩種字符集ansi和unicode,前者就是通常使用的單位元組方式,但這種方式處理象中文這樣的雙位元組字元不方便,容易出現半個漢字的情況。而後者是雙位元組方式,方便處理雙位元組字元。windows nt的所有與字元有關的函式都提供兩種方式的版本,而windows 9x只支援ansi...

CSS中的 important簡析

important是css1就定義的語法,作用是提高指定樣式規則的應用優先權。語法格式,即寫在定義的最後面,例如 box 假如我要對乙個div在ie7中寬為200px,在ie6中寬180px,則 div div important 表示某條屬性 宣告 具體最高的優化級,所以雖然看起來下面的把上方的屬...

簡析 JSON 中的 與

在 json 裡 是 array 也就是陣列 是ojbect 也就是物件 array 的key 是 int.的key 是 string 例如 var dot1 a 就是乙個陣列 var dot2 就是乙個物件 陣列和物件轉換非常簡單,dot1把 替換為 就是物件,dot2把替換為 就是素組。這在jq...