class_center_sample

paddle.nn.functional. class_center_sample ( label, num_classes, num_samples, group=None ) [source]

Class center sample method is proposed from the paper PartialFC that only sample a subset of the class centers. The process of sampling subset class centers is straightforward:

  1. First select the positive class centers;

  2. Then randomly sample negative class centers.

Specifically, given a label tensor, shape [batch_size], select all the positive class centers and randomly sample negative class centers, then remap the input label tensor using the sampled class centers.

For more information, Partial FC: Training 10 Million Identities on a Single Machine arxiv: https://arxiv.org/abs/2010.05222

Note

If the number of the positive class centers is greater than the input num_samples, it keeps all the positive class centers and the shape of sampled_class_center will be [num_positive_class_centers].

The API supports CPU, single GPU and multi GPU.

For data parallel mode, set group=False.

For model parallel mode, set group=None or the group instance return by paddle.distributed.new_group.

Parameters
  • label (Tensor) – 1-D tensor with shape [N], each label in [0, num_classes)

  • num_classes (int) – A positive integer to specify the number of classes at local rank. Note that num_classes of each GPU can be different.

  • num_samples (int) – A positive integer to specify the number of class center to sample.

  • group (Group, optional) – The group instance return by paddle.distributed.new_group or None for global default group or False for data parallel (do not communication cross ranks). Default is None.

Returns

(remapped_label, sampled_class_center), remapped label using sampled class center, sampled class center from [0, num_classes).

Return type

Tuple of two Tensor

Examples:

>>> # CPU or single GPU
>>> import paddle
>>> num_classes = 20
>>> batch_size = 10
>>> num_samples = 6
>>> paddle.seed(2023)
>>> label = paddle.randint(low=0, high=num_classes, shape=[batch_size], dtype='int64')
>>> remapped_label, sampled_class_index = paddle.nn.functional.class_center_sample(label, num_classes, num_samples)
>>> print(label)
Tensor(shape=[10], dtype=int64, place=Place(cpu), stop_gradient=True,
[17, 10, 5 , 18, 8 , 8 , 19, 14, 10, 14])
>>> print(remapped_label)
Tensor(shape=[10], dtype=int64, place=Place(cpu), stop_gradient=True,
[4, 2, 0, 5, 1, 1, 6, 3, 2, 3])
>>> print(sampled_class_index)
Tensor(shape=[7], dtype=int64, place=Place(cpu), stop_gradient=True,
[5 , 8 , 10, 14, 17, 18, 19])
>>> 
>>> # required: distributed
>>> # Multi GPU, test_class_center_sample.py
>>> import paddle
>>> import paddle.distributed as dist
>>> strategy = dist.fleet.DistributedStrategy()
>>> dist.fleet.init(is_collective=True, strategy=strategy)
>>> batch_size = 10
>>> num_samples = 6
>>> rank_id = dist.get_rank()
>>> # num_classes of each GPU can be different, e.g num_classes_list = [10, 8]
>>> num_classes_list = [10, 10]
>>> num_classes = paddle.sum(paddle.to_tensor(num_classes_list))
>>> label = paddle.randint(low=0, high=num_classes.item(), shape=[batch_size], dtype='int64')
>>> label_list = []
>>> dist.all_gather(label_list, label)
>>> label = paddle.concat(label_list, axis=0)
>>> remapped_label, sampled_class_index = paddle.nn.functional.class_center_sample(label, num_classes_list[rank_id], num_samples)

>>> print(label)
>>> print(remapped_label)
>>> print(sampled_class_index)
>>> #python -m paddle.distributed.launch --gpus=0,1 test_class_center_sample.py
>>> # rank 0 output:
Tensor(shape=[20], dtype=int64, place=CUDAPlace(0), stop_gradient=True,
[10, 17, 15, 11, 9 , 12, 18, 18, 17, 18, 19, 2 , 8 , 13, 11, 13, 9 , 10, 0 , 4 ])
Tensor(shape=[20], dtype=int64, place=CUDAPlace(0), stop_gradient=True,
[6 , 11, 10, 7 , 4 , 8 , 12, 12, 11, 12, 13, 1 , 3 , 9 , 7 , 9 , 4 , 6 , 0 , 2 ])
Tensor(shape=[6], dtype=int64, place=CUDAPlace(0), stop_gradient=True,
[0, 2, 4, 8, 9, 3])
>>> # rank 1 output:
Tensor(shape=[20], dtype=int64, place=CUDAPlace(1), stop_gradient=True,
[10, 17, 15, 11, 9 , 12, 18, 18, 17, 18, 19, 2 , 8 , 13, 11, 13, 9 , 10, 0 , 4 ])
Tensor(shape=[20], dtype=int64, place=CUDAPlace(1), stop_gradient=True,
[6 , 11, 10, 7 , 4 , 8 , 12, 12, 11, 12, 13, 1 , 3 , 9 , 7 , 9 , 4 , 6 , 0 , 2 ])
Tensor(shape=[7], dtype=int64, place=CUDAPlace(1), stop_gradient=True,
[0, 1, 2, 3, 5, 7, 8])