def _hard_anchor_sampling(self, X, y_hat, y):
        """
        Args:
            X (Tensor): reshaped feats, shape = [N, H * W, feat_channels]
            y_hat (Tensor): reshaped label, shape = [N, H * W]
            y (Tensor): reshaped predict, shape = [N, H * W]
        """
        batch_size, feat_dim = X.shape[0], X.shape[-1]
        classes = []
        total_classes = 0
        for i in range(batch_size):
            current_y = y_hat[i]
            current_classes = paddle.unique(current_y)
            current_classes = [
                x for x in current_classes if x != self.ignore_index
            ]
            current_classes = [
                x for x in current_classes
                if (current_y == x).nonzero().shape[0] > self.max_views
            ]

            classes.append(current_classes)
            total_classes += len(current_classes)

        n_view = self.max_samples // total_classes
        n_view = min(n_view, self.max_views)

        X_ = []
        y_ = paddle.zeros([total_classes], dtype='float32')

        X_ptr = 0
        for i in range(batch_size):
            this_y_hat = y_hat[i]
            current_y = y[i]
            current_classes = classes[i]

            for cls_id in current_classes:
                hard_indices = paddle.logical_and(
                    (this_y_hat == cls_id), (current_y != cls_id)).nonzero()
                easy_indices = paddle.logical_and(
                    (this_y_hat == cls_id), (current_y == cls_id)).nonzero()

                num_hard = hard_indices.shape[0]
                num_easy = easy_indices.shape[0]

                if num_hard >= n_view / 2 and num_easy >= n_view / 2:
                    num_hard_keep = n_view // 2
                    num_easy_keep = n_view - num_hard_keep
                elif num_hard >= n_view / 2:
                    num_easy_keep = num_easy
                    num_hard_keep = n_view - num_easy_keep
                elif num_easy >= n_view / 2:
                    num_hard_keep = num_hard
                    num_easy_keep = n_view - num_hard_keep
                else:
                    num_hard_keep = num_hard
                    num_easy_keep = num_easy

                indices = None
                if num_hard > 0:
                    perm = paddle.randperm(num_hard)
                    hard_indices = hard_indices[perm[:num_hard_keep]].reshape(
                        (-1, hard_indices.shape[-1]))
                    indices = hard_indices
                if num_easy > 0:
                    perm = paddle.randperm(num_easy)
                    easy_indices = easy_indices[perm[:num_easy_keep]].reshape(
                        (-1, easy_indices.shape[-1]))
                    if indices is None:
                        indices = easy_indices
                    else:
                        indices = paddle.concat((indices, easy_indices), axis=0)
                if indices is None:
                    raise UserWarning('hard sampling indice error')

                X_.append(paddle.index_select(X[i, :, :], indices.squeeze(1)))
                y_[X_ptr] = float(cls_id)
                X_ptr += 1
        X_ = paddle.stack(X_, axis=0)
        return X_, y_

        Args:
            X (Tensor): reshaped feats, shape = [N, H * W, feat_channels]
            y_hat (Tensor): reshaped label, shape = [N, H * W]
            y (Tensor): reshaped predict, shape = [N, H * W]
        
paddleseg/models/losses/pixel_contrast_cross_entropy_loss.py