def METHOD_NAME(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 = paddle.shape(X)[0], paddle.shape(X)[-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_