def __call__(self, batch): num_batch = len(batch) b = [items for items in zip(*batch)] image = nd.stack(*b[0]) labels = nd.full((num_batch, self.max_objs), -1) bboxes = nd.full((num_batch, self.max_objs, 4), -1) for i, (_labels, _bboxes) in enumerate(zip(b[1], b[2])): num_objs = _labels.shape[0] labels[i, :num_objs] = _labels bboxes[i, :num_objs] = _bboxes scale_factor = nd.stack(*b[3]) other = b[4:] return (image, labels, bboxes, scale_factor) + tuple(other)
def dot_attention(query, key, value, mask, dropout=0.0): # query: (batch_size, h, length_q, model_dim/h) # key: (batch_size, h, length_k, model_dim/h) # value: (batch_size, h, length_k, model_dim/h) query_shape = query.shape query = query.reshape(-3, -2) key = key.reshape(-3, -2) value = value.reshape(-3, -2) # matmul, t: (batch_size*h, length_q, length_k) t = nd.batch_dot(query, key.swapaxes(1, 2)) / math.sqrt(query.shape[-1]) # masked # mask PAD and future words m = nd.full(t.shape, LARGE_NEGATIVE_VALUE) mask = nd.ones(t.shape) * mask t = nd.where(mask, t, m) # softmax t = nd.softmax(t, axis=-1) if dropout > 0.0: t = nd.dropout(t, p=dropout) # (batch_size, h, length_q, model_dim/h) return nd.batch_dot(t, value).reshape(query_shape)
def test_isub(): a = nd.full(LARGE_X, 3) b = nd.ones(LARGE_X) c = a c -= b assert c.shape == a.shape assert c[-1] == 2
def forward(self, pos, start_idx=None): r"""Memory allocation and sampling Parameters ---------- pos : tensor The positional tensor of shape (B, N, C) start_idx : int, optional If given, appoint the index of the starting point, otherwise randomly select a point as the start point. (default: None) Returns ------- tensor of shape (B, self.npoints) The sampled indices in each batch. """ ctx = pos.context B, N, C = pos.shape pos = pos.reshape(-1, C) dist = nd.zeros((B * N), dtype=pos.dtype, ctx=ctx) if start_idx is None: start_idx = nd.random.randint(0, N - 1, (B, ), dtype=np.int, ctx=ctx) else: if start_idx >= N or start_idx < 0: raise DGLError( "Invalid start_idx, expected 0 <= start_idx < {}, got {}". format(N, start_idx)) start_idx = nd.full((B, ), start_idx, dtype=np.int, ctx=ctx) result = nd.zeros((self.npoints * B), dtype=np.int, ctx=ctx) farthest_point_sampler(pos, B, self.npoints, dist, start_idx, result) return result.reshape(B, self.npoints)
def corner_to_center(box, split=False, eps=1e-12): shape = box.shape assert len(shape) in (2,3) and shape[-1] == 4 # (B,N,1) or (N,1) xmin, ymin, xmax, ymax = nd.split(box, 4, axis=-1) width = xmax - xmin height = ymax - ymin cx = xmin + width / 2 cy = ymin + height / 2 width = nd.where(width==0, nd.full(width.shape, eps), width) height = nd.where(height==0, nd.full(height.shape, eps), height) result = [cx, cy, width, height] if split: return result else: return nd.concat(*result, dim=-1)
def batchify(self, data): data_shape = len(data[0].shape) if not isinstance(data[0], nd.NDArray): tmp = [] for i in data: tmp.append(nd.array(i, ctx=self._ctx)) data = tmp if data_shape == 1: # 2. Stack im_info return nd.stack(*data) elif data_shape == 2: # 2. Padding label buf = nd.full((len(data), self._label_max_size, data[0].shape[-1]), val=-1, ctx=self._ctx) for i, l in enumerate(data): buf[i][:l.shape[0], :] = l return buf elif data_shape == 3: # 2. Padding image buf = nd.zeros((len(data), data[0].shape[0], self._image_max_size, self._image_max_size), ctx=self._ctx) for i, img in enumerate(data): buf[i][:, :img.shape[1], :img.shape[2]] = img return buf else: raise NotImplementedError
def extract_pairwise_multi_position_embedding_nd(position_mat, feat_dim, wave_length=1000): """ Extract multi-class position embedding Args: position_mat: [num_fg_classes, num_rois, num_rois, 4] feat_dim: dimension of embedding feature wave_length: Returns: embedding: [num_fg_classes, num_rois, num_rois, feat_dim] """ feat_range = nd.arange(0, feat_dim / 8) dim_mat = nd.broadcast_power(lhs=nd.full((1, ), wave_length), rhs=(8. / feat_dim) * feat_range) dim_mat = nd.Reshape(dim_mat, shape=(1, 1, 1, 1, -1)) position_mat = nd.expand_dims(100.0 * position_mat, axis=4) div_mat = nd.broadcast_div(lhs=position_mat, rhs=dim_mat) sin_mat = nd.sin(data=div_mat) cos_mat = nd.cos(data=div_mat) # embedding, [num_fg_classes, num_rois, num_rois, 4, feat_dim/4] embedding = nd.concat(sin_mat, cos_mat, dim=4) embedding = nd.Reshape(embedding, shape=(0, 0, 0, feat_dim)) return embedding
def _viterbi_decode(self, feats): ''' CRF 的预测算法,维特比算法,即根据特征找出最好的路径 feats:长度为句子长度的列表,列表中每个元素为一个 nd.array,代表一批中每个词的特征向量,形状为: (batch_size, tagset_size) ''' backpointers = [] batch_size = feats[0].shape[0] vvars = nd.full((1, self.tagset_size), -10000., ctx=self.ctx) vvars[0, self.tag2idx[START_TAG]] = 0 # vvars 形状:(batch_size, tagset_size) vvars = nd.broadcast_axis(vvars, axis=0, size=batch_size) for feat in feats: bptrs_t = [] viterbivars_t = [] for next_tag in range(self.tagset_size): next_tag_var = vvars + nd.broadcast_axis( self.transitions.data()[next_tag].reshape((1, -1)), axis=0, size=batch_size) # best_tag_id 形状(batch_size, 1) best_tag_id = nd.argmax(next_tag_var, axis=1, keepdims=True) bptrs_t.append(best_tag_id) # viterbivars_t 列表中每个元素的形状为 (batch_size, 1) viterbivars_t.append( nd.pick(next_tag_var, best_tag_id, axis=1, keepdims=True)) vvars = (nd.concat(*viterbivars_t, dim=1) + feat) # bptrs_t 形状 :(batch_size, tagset_size) bptrs_t = nd.concat(*bptrs_t, dim=1) backpointers.append(bptrs_t) # 转换到 STOP_TAG terminal_var = vvars + self.transitions.data()[self.tag2idx[START_TAG]] best_tag_id = nd.argmax(terminal_var, axis=1) # path_score 形状(batch_size, ) path_score = nd.pick(terminal_var, best_tag_id, axis=1) # 根据反向指针 backpointers 去解码最好的路径 best_path = [best_tag_id] for bptrs_t in reversed(backpointers): best_tag_id = nd.pick(bptrs_t, best_tag_id, axis=1) best_path.append(best_tag_id) # 移除开始符号 # start 形状为 (batch_size, ) start = best_path.pop() # 检查start是否为开始符号 for i in range(batch_size): assert start[i].asscalar() == self.tag2idx[START_TAG] best_path.reverse() # 构建最佳路径的矩阵 new_best_path = [] for best_tag_id in best_path: best_tag_id = best_tag_id.reshape((-1, 1)) new_best_path.append(best_tag_id) best_path_matrix = nd.concat(*new_best_path, dim=1) return path_score, best_path_matrix
def mean(self) -> Tensor: result = ( self.mu.exp() * self.sigma * np.pi / (self.sigma * np.pi).sin() ) # Expectation diverges if sigma > 1 return nd.where( self.sigma > 1.0, nd.full(result.shape, np.inf), result )
def set_fixed(self, fixed): """Fixed has to be a boolean or a ndarray. The sizes accepted are n * (p+1), n and p+1. The non given value are deduced. If n values are given, they apply for each neurones. (If one neurones is fixed, all its connections too). If p + 1 values are given, they apply for each input. (If an input is fixed, all its connections too). If a boolean is given, then all the connections will follow its value. If an uncorrect argument is given then : If it has not shape as an attribute, it will cast it in boolean. Otherwise if the sizes in shape doesn't fit, it will raise a ValueError. BUT (CAREFUL) if the shape is correct, the values aren't tested.""" message = "'fixed' argument can either be one boolean for all the parameters or n booleans, one for each neurone and their connections, or p+1 booleans, one for each input (+bias, give the bias first) and their connections or a matrix of n*(p+1) booleans for each connection" try: if len(fixed.shape) == 1: if fixed.shape[0] == self.input_size + 1: self.bias_fixed = nd.full(self.bias.shape, fixed[0], ctx=self.ctx) self.weights_fixed = nd.dot( nd.full((self.output_size, 1), 1), fixed[1:].reshape( (1, self.input_size))).copyto(self.ctx) elif fixed.shape[0] == self.output_size: self.bias_fixed = fixed.copyto(self.ctx) self.weights_fixed = nd.dot( fixed.reshape((self.output_size, 1)), nd.full((1, self.input_size), 1)).copyto(self.ctx) else: raise ValueError(message) elif fixed.shape == (self.output_size, self.input_size + 1): self.bias_fixed = fixed[:, 0].copyto(self.ctx) self.weights_fixed = fixed[:, 1:].copyto(self.ctx) else: raise ValueError(message) except AttributeError: self.weights_fixed = nd.full(self.weights.shape, bool(fixed), ctx=self.ctx) self.bias_fixed = nd.full(self.bias.shape, bool(fixed), ctx=self.ctx) self.bias_fixed = self.bias_fixed.astype('uint8') self.weights_fixed = self.weights_fixed.astype('uint8')
def random_expand(src, max_ratio=4, fill=0, keep_ratio=True): """Random expand original image with borders, this is identical to placing the original image on a larger canvas. Modified for video from gluoncv default image transform Parameters ---------- src : mxnet.nd.NDArray The original image with KHWC format. max_ratio : int or float Maximum ratio of the output image on both direction(vertical and horizontal) fill : int or float or array-like The value(s) for padded borders. If `fill` is numerical type, RGB channels will be padded with single value. Otherwise `fill` must have same length as image channels, which resulted in padding with per-channel values. keep_ratio : bool If `True`, will keep output image the same aspect ratio as input. Returns ------- mxnet.nd.NDArray Augmented image. tuple Tuple of (offset_x, offset_y, new_width, new_height) """ if max_ratio <= 1: return src, (0, 0, src.shape[1], src.shape[0]) k, h, w, c = src.shape ratio_x = random.uniform(1, max_ratio) if keep_ratio: ratio_y = ratio_x else: ratio_y = random.uniform(1, max_ratio) oh, ow = int(h * ratio_y), int(w * ratio_x) off_y = random.randint(0, oh - h) off_x = random.randint(0, ow - w) # make canvas if isinstance(fill, numeric_types): dst = nd.full(shape=(k, oh, ow, c), val=fill, dtype=src.dtype) else: fill = nd.array(fill, dtype=src.dtype, ctx=src.context) if not c == fill.size: raise ValueError("Channel and fill size mismatch, {} vs {}".format(c, fill.size)) dst = nd.tile(fill.reshape((1, c)), reps=(k * oh * ow, 1)).reshape((k, oh, ow, c)) dst[:, off_y:off_y+h, off_x:off_x+w, :] = src return dst, (off_x, off_y, ow, oh)
def _forward_alg(self, feats): """Forward algorithm for CRF probability calculation Args: feats (NDArray): a representative representation of each symbol representing the entire sequence in a batch, shape is (seq_len, batch_size, tagset_size) Returns: alpha (NDArray): shape is (batch_size, ) """ # Defining forward NDArray batch_size = feats.shape[1] # alphas shape: (batch_size, self.tagset_size) alphas = nd.full((batch_size, self.tagset_size), -10000., ctx=self.ctx) alphas[:, self.tag2idx[START_TAG]] = 0. def update_alphas(data, alphas): """Calculate the batch update alpha for each time step Args: data (NDArray): NDArray shape: (seq_len, batch_size, self.tagset_size) alphas (NDArray): NDArray shape: (batch_size, self.tagset_size) """ # alphas_t shape: (self.tagset_size, batch_size, self.tagset_size) alphas_t = nd.broadcast_axis(nd.expand_dims(alphas, axis=0), axis=0, size=self.tagset_size) # emit_score shape: (self.tagset_size, batch_size, 1) emit_score = nd.transpose(nd.expand_dims(data, axis=0), axes=(2, 1, 0)) # trans_score shape: (self.tagset_size, 1, self.tagset_size) trans_score = nd.expand_dims(self.transitions.data(), axis=1) # next_tag_var shape: (self.tagset_size, batch_size, self.tagset_size) next_tag_var = alphas_t + emit_score + trans_score # alphas shape: (self.tagset_size, batch_size) alphas = log_sum_exp(next_tag_var) # alphas shape: (batch_size, self.tagset_size) alphas = nd.transpose(alphas, axes=(1, 0)) return data, alphas # Use the foreach operator to unroll _, alphas = nd.contrib.foreach(update_alphas, feats, alphas) # terminal_var shape:(batch_size, self.tagset_size) terminal_var = alphas + self.transitions.data()[self.tag2idx[STOP_TAG]] # alpha shape: (batch_size, ) alpha = log_sum_exp(terminal_var) assert alpha.shape == (batch_size,) return alpha
def extract_rank_embedding_nd(rank_dim, feat_dim, wave_length=1000): rank_range = nd.arange(0, rank_dim) feat_range = nd.arange(0, feat_dim / 2) dim_mat = nd.broadcast_power(lhs=nd.full((1, ), wave_length), rhs=(2. / feat_dim) * feat_range) dim_mat = nd.Reshape(dim_mat, shape=(1, -1)) rank_mat = nd.expand_dims(rank_range, axis=1) div_mat = nd.broadcast_div(lhs=rank_mat, rhs=dim_mat) sin_mat = nd.sin(data=div_mat) cos_mat = nd.cos(data=div_mat) embedding = nd.concat(sin_mat, cos_mat, dim=1) return embedding
def resize_contain(src, size, fill=0): """Resize the image to fit in the given area while keeping aspect ratio. If both the height and the width in `size` are larger than the height and the width of input image, the image is placed on the center with an appropriate padding to match `size`. Otherwise, the input image is scaled to fit in a canvas whose size is `size` while preserving aspect ratio. Parameters ---------- src : mxnet.nd.NDArray The original image with HWC format. size : tuple Tuple of length 2 as (width, height). fill : int or float or array-like The value(s) for padded borders. If `fill` is numerical type, RGB channels will be padded with single value. Otherwise `fill` must have same length as image channels, which resulted in padding with per-channel values. Returns ------- mxnet.nd.NDArray Augmented image. tuple Tuple of (offset_x, offset_y, scaled_x, scaled_y) """ h, w, c = src.shape ow, oh = size scale_h = oh / h scale_w = oh / w scale = min(min(scale_h, scale_w), 1) scaled_x = int(w * scale) scaled_y = int(h * scale) if scale < 1: src = mx.image.imresize(src, scaled_x, scaled_y) off_y = (oh - scaled_y) // 2 if scaled_y < oh else 0 off_x = (ow - scaled_x) // 2 if scaled_x < ow else 0 # make canvas if isinstance(fill, numeric_types): dst = nd.full(shape=(oh, ow, c), val=fill, dtype=src.dtype) else: fill = nd.array(fill, ctx=src.context) if not c == fill.size: raise ValueError("Channel and fill size mismatch, {} vs {}".format( c, fill.size)) dst = nd.repeat(fill, repeats=oh * ow).reshape((oh, ow, c)) dst[off_y:off_y + scaled_y, off_x:off_x + scaled_x, :] = src return dst, (off_x, off_y, scaled_x, scaled_y)
def resize_contain(src, size, fill=0): """Resize the image to fit in the given area while keeping aspect ratio. If both the height and the width in `size` are larger than the height and the width of input image, the image is placed on the center with an appropriate padding to match `size`. Otherwise, the input image is scaled to fit in a canvas whose size is `size` while preserving aspect ratio. Parameters ---------- src : mxnet.nd.NDArray The original image with HWC format. size : tuple Tuple of length 2 as (width, height). fill : int or float or array-like The value(s) for padded borders. If `fill` is numerical type, RGB channels will be padded with single value. Otherwise `fill` must have same length as image channels, which resulted in padding with per-channel values. Returns ------- mxnet.nd.NDArray Augmented image. tuple Tuple of (offset_x, offset_y, scaled_x, scaled_y) """ h, w, c = src.shape ow, oh = size scale_h = oh / h scale_w = ow / w scale = min(min(scale_h, scale_w), 1) scaled_x = int(w * scale) scaled_y = int(h * scale) if scale < 1: src = mx.image.imresize(src, scaled_x, scaled_y) off_y = (oh - scaled_y) // 2 if scaled_y < oh else 0 off_x = (ow - scaled_x) // 2 if scaled_x < ow else 0 # make canvas if isinstance(fill, numeric_types): dst = nd.full(shape=(oh, ow, c), val=fill, dtype=src.dtype) else: fill = nd.array(fill, ctx=src.context) if not c == fill.size: raise ValueError("Channel and fill size mismatch, {} vs {}".format(c, fill.size)) dst = nd.repeat(fill, repeats=oh * ow).reshape((oh, ow, c)) dst[off_y:off_y+scaled_y, off_x:off_x+scaled_x, :] = src return dst, (off_x, off_y, scaled_x, scaled_y)
def collate_fn(batch): images = nd.stack(*[sample[0] for sample in batch], axis=0) num_samples = len(batch) max_num_objs = batch[0][1].shape[0] for sample in batch: if sample[1].shape[0] > max_num_objs: max_num_objs = sample[1].shape[0] labels = nd.full((num_samples, max_num_objs), -1, dtype=np.int64) # -1 means no objects bboxes = nd.full((num_samples, max_num_objs, 4), -1, dtype=np.float32) # -1 means bbox can not be mapped to to original image scale_factors = nd.full((num_samples, 4), -1, dtype=np.float32) for i, sample in enumerate(batch): num_objs = sample[1].shape[0] labels[i, 0:num_objs] = nd.array(sample[1]) bboxes[i, 0:num_objs, :] = sample[2] scale_factors[i, :] = sample[3] return images, labels, bboxes, scale_factors
def set_seed_distributed(local_seed): # single-element tensor with the local seed in it rank_0_seed = nd.full((1), local_seed, dtype=np.int32) if hvd.size() > 1: rank_0_seed = hvd.broadcast_(tensor=rank_0_seed, root_rank=0, name="broadcast_the_seed") nd.ndarray.waitall() local_seed = (rank_0_seed[0].asscalar() + hvd.rank()) % 2**31 log_event(key=mlperf_constants.SEED, value=local_seed) random.seed(local_seed) np.random.seed(local_seed) mx.random.seed(local_seed) return local_seed
def random_expand(src, max_ratio=4, fill=0, keep_ratio=True): """Random expand original image with borders, this is identical to placing the original image on a larger canvas. Parameters ---------- src : mxnet.nd.NDArray The original image with HWC format. max_ratio : int or float Maximum ratio of the output image on both direction(vertical and horizontal) fill : int or float or array-like The value(s) for padded borders. If `fill` is numerical type, RGB channels will be padded with single value. Otherwise `fill` must have same length as image channels, which resulted in padding with per-channel values. keep_ratio : bool If `True`, will keep output image the same aspect ratio as input. Returns ------- mxnet.nd.NDArray Augmented image. tuple Tuple of (offset_x, offset_y, new_width, new_height) """ if max_ratio <= 1: return src, (0, 0, src.shape[1], src.shape[0]) h, w, c = src.shape ratio_x = random.uniform(1, max_ratio) if keep_ratio: ratio_y = ratio_x else: ratio_y = random.uniform(1, max_ratio) oh, ow = int(h * ratio_y), int(w * ratio_x) off_y = random.randint(0, oh - h) off_x = random.randint(0, ow - w) # make canvas if isinstance(fill, numeric_types): dst = nd.full(shape=(oh, ow, c), val=fill, dtype=src.dtype) else: fill = nd.array(fill, dtype=src.dtype, ctx=src.context) if not c == fill.size: raise ValueError("Channel and fill size mismatch, {} vs {}".format(c, fill.size)) dst = nd.tile(fill.reshape((1, c)), reps=(oh * ow, 1)).reshape((oh, ow, c)) dst[off_y:off_y+h, off_x:off_x+w, :] = src return dst, (off_x, off_y, ow, oh)
def update(self, index, weight, grad, state): """Performs w += rescale_grad * grad.""" assert (isinstance(weight, NDArray)) assert (isinstance(grad, NDArray)) self._update_count(index) lr = self._get_lr(index) wd = self._get_wd(index) t = self._index_update_count[index] grad *= self.rescale_grad amsbound = self.group['amsbound'] exp_avg, exp_avg_sq = state['exp_avg'], state['exp_avg_sq'] if amsbound: max_exp_avg_sq = state['max_exp_avg_sq'] beta1, beta2 = self.group['betas'] if self.group['wd'] != 0: grad = grad + (wd * weight) exp_avg[:] *= beta1 exp_avg[:] += ((1 - beta1) * grad) exp_avg_sq[:] *= beta2 exp_avg_sq[:] = exp_avg_sq + (1 - beta2) * grad * grad denom = nd.zeros(weight.shape, ctx=weight.context) if amsbound: # Maintains the maximum of all 2nd moment running avg. till now max_exp_avg_sq = nd.max(nd.stack(max_exp_avg_sq, exp_avg_sq), axis=0) # Use the max. for normalizing running avg. of gradient denom[:] = max_exp_avg_sq.sqrt() + self.group['eps'] else: denom[:] = exp_avg_sq.sqrt() + self.group['eps'] bias_correction1 = 1 - beta1 ** t bias_correction2 = 1 - beta2 ** t step_size = self.group['learning_rate'] * math.sqrt(bias_correction2) / bias_correction1 final_lr = self.group['final_lr'] * self.group['learning_rate'] / lr lower_bound = final_lr * (1 - 1 / (self.group['gamma'] * t + 1)) upper_bound = final_lr * (1 + 1 / (self.group['gamma'] * t)) step_size = nd.full(denom.shape, step_size, ctx=weight.context) step_size[:] /= denom step_size = nd.clip(step_size, lower_bound, upper_bound) step_size[:] *= exp_avg weight[:] -= step_size
def _pad_arrs_to_max_length(arrs, max_gt_box_number, pad_axis=0, pad_val=-1): """Inner Implementation of the Pad batchify""" if not isinstance(arrs[0], (nd.NDArray, np.ndarray)): arrs = [np.asarray(ele) for ele in arrs] max_size = max_gt_box_number ret_shape = list(arrs[0].shape) ret_shape[pad_axis] = max_size ret_shape = (len(arrs), ) + tuple(ret_shape) ret = nd.full(shape=ret_shape, val=pad_val, dtype=arrs[0].dtype) for i, arr in enumerate(arrs): if arr.shape[pad_axis] == max_size: ret[i] = arr else: slices = [slice(None) for _ in range(arr.ndim)] slices[pad_axis] = slice(0, arr.shape[pad_axis]) slices = [slice(i, i + 1)] + slices ret[tuple(slices)] = arr return ret
def ndarray_example(): a = nd.array(((1, 2, 3), (5, 6, 7))) b = nd.full((2, 3), 2.0) b.shape, b.size, b.dtype # Operations. x = nd.ones((2, 3)) y = nd.random.uniform(-1, 1, (2, 3)) x * y y.exp() nd.dot(x, y.T) # Indexing. y[1, 2] y[:, 1:3] y[:, 1:3] = 2 y[1:2, 0:2] = 4 # Converting between MXNet NDArray and NumPy. na = x.asnumpy() nd.array(na)
def test_full(): a = nd.full((SMALL_Y, LARGE_X), 3) assert a.shape == (SMALL_Y, LARGE_X) assert a[SMALL_Y//2][LARGE_X//2] == 3 assert a[-1][-1] == 3
def check_lt(): a = nd.full(LARGE_X, 2) b = nd.full(LARGE_X, 3) d = (a <= b) assert (d.asnumpy() == 1).all()
def check_eq(): a = nd.full(LARGE_X, 3) b = nd.full(LARGE_X, 3) c = (a == b) assert (c.asnumpy() == 1).all()