class_docstr: Utility for nearest neighbor search. It would first try to use `faiss`_ (requiring separate pacakge installment)
  as the backend for better computational performance. Otherwise, `scikit-learn` would be used as it is pre-installed
  with gpytorch.
  
  :param int k: number of nearest neighbors
  :param int dim: dimensionality of data
  :param torch.Size batch_shape: batch shape for train data
  :param str preferred_nnlib: currently supports `faiss` and `scikit-learn` (default: faiss).
  :param torch.device device: device that the NN search will be performed on.
  
  Example:
      >>> train_x = torch.randn(10, 5)
      >>> nn_util = NNUtil(k=3, dim=train_x.size(-1), device=train_x.device)
      >>> nn_util.set_nn_idx(train_x)
      >>> test_x = torch.randn(2, 5)
      >>> test_nn_indices = nn_util.find_nn_idx(test_x) # finding 3 nearest neighbors for test_x
      >>> test_nn_indices = nn_util.find_nn_idx(test_x, k=2) # finding 2 nearest neighbors for test_x
      >>> sequential_nn_idx = nn_util.build_sequential_nn_idx(train_x) # build up sequential nearest neighbor
      >>>     # structure for train_x
  
  .. _faiss:
      https://github.com/facebookresearch/faiss
class_docstr_tok: ["Utility","for","nearest","neighbor","search",".","It","would","first","try","to","use","`","faiss","`","_","(","requiring","separate","pacakge","installment",")","as","the","backend","for","better","computational","performance",".","Otherwise",",","`","scikit-learn","`","would","be","used","as","it","is","pre-installed","with","gpytorch",".",":","param","int","k",":","number","of","nearest","neighbors",":","param","int","dim",":","dimensionality","of","data",":","param","torch.Size","batch_shape",":","batch","shape","for","train","data",":","param","str","preferred_nnlib",":","currently","supports","`","faiss","`","and","`","scikit-learn","`","(","default",":","faiss",")",".",":","param","torch.device","device",":","device","that","the","NN","search","will","be","performed","on",".","Example",":",">",">",">","train_x","=","torch.randn","(","10",",","5",")",">",">",">","nn_util","=","NNUtil","(","k=3",",","dim=train_x.size","(","-1",")",",","device=train_x.device",")",">",">",">","nn_util.set_nn_idx","(","train_x",")",">",">",">","test_x","=","torch.randn","(","2",",","5",")",">",">",">","test_nn_indices","=","nn_util.find_nn_idx","(","test_x",")","#","finding","3","nearest","neighbors","for","test_x",">",">",">","test_nn_indices","=","nn_util.find_nn_idx","(","test_x",",","k=2",")","#","finding","2","nearest","neighbors","for","test_x",">",">",">","sequential_nn_idx","=","nn_util.build_sequential_nn_idx","(","train_x",")","#","build","up","sequential","nearest","neighbor",">",">",">","#","structure","for","train_x","..","_faiss",":","https",":","\/\/github.com\/facebookresearch\/faiss"]
docstr: Build the sequential :math:`k` nearest neighbor structure within training data in the following way:
  for the :math:`i`-th data point :math:`x_i`, find its :math:`k` nearest neighbors among preceding
  training data :math:`x_1, \cdots, x_{i-1}`, for `i=k+1:N` where `N` is the size of training data.
  
  :param x: training data. Shape `(N, D)`
  :rtype: torch.LongTensor
  :return: indices of nearest neighbors. Shape: `(N-k, k)`
docstr_tok: ["Build","the","sequential",":","math",":","`","k","`","nearest","neighbor","structure","within","training","data","in","the","following","way",":","for","the",":","math",":","`","i","`","-th","data","point",":","math",":","`","x_i","`",",","find","its",":","math",":","`","k","`","nearest","neighbors","among","preceding","training","data",":","math",":","`","x_1",",","\\cdots",",","x_","{","i-1","}","`",",","for","`","i=k+1",":","N","`","where","`","N","`","is","the","size","of","training","data",".",":","param","x",":","training","data",".","Shape","`","(","N",",","D",")","`",":","rtype",":","torch.LongTensor",":","return",":","indices","of","nearest","neighbors",".","Shape",":","`","(","N-k",",","k",")","`"]
code: def build_sequential_nn_idx(self, x):
      r"""
      Build the sequential :math:`k` nearest neighbor structure within training data in the following way:
      for the :math:`i`-th data point :math:`x_i`, find its :math:`k` nearest neighbors among preceding
      training data :math:`x_1, \cdots, x_{i-1}`, for `i=k+1:N` where `N` is the size of training data.
  
      :param x: training data. Shape `(N, D)`
      :rtype: torch.LongTensor
      :return: indices of nearest neighbors. Shape: `(N-k, k)`
      """
      x = self._expand_and_check_shape(x)
      N = x.shape[-2]
      assert (
          self.k < N
      ), f"k should be smaller than number of data, but got k = {self.k}, number of data = {N}."
  
      nn_idx = torch.empty(
          self.batch_shape.numel(),
          N - self.k,
          self.k,
          dtype=torch.int64,
      )
      x_np = x.view(-1, N, self.dim).data.float().cpu().numpy()
  
      if self.nnlib == "faiss":
          from faiss import IndexFlatL2
  
          # building nearest neighbor structure within inducing points
          index = IndexFlatL2(self.dim)
          with torch.no_grad():
              if self.res is not None:
                  from faiss import index_cpu_to_gpu
  
                  index = index_cpu_to_gpu(self.res, 0, index)
  
              for bi in range(self.batch_shape.numel()):
                  index.reset()
                  index.add(x_np[bi][: self.k])
                  for i in range(self.k, N):
                      row = x_np[bi][i][None, :]
                      nn_idx[bi][i - self.k].copy_(
                          torch.from_numpy(
                              index.search(row, self.k)[1][..., 0, :]
                          )
                          .long()
                          .to(x.device)
                      )
                      index.add(row)
  
      else:
          assert self.nnlib == "sklearn"
          from sklearn.neighbors import NearestNeighbors
  
          for bi in range(self.batch_shape.numel()):
              # finding k nearest neighbors in the first k
              for i in range(self.k, N):
                  train_neighbors = NearestNeighbors(
                      n_neighbors=self.k, algorithm="auto"
                  ).fit(x_np[bi][:i])
                  nn_idx_i = torch.from_numpy(
                      train_neighbors.kneighbors(x_np[bi][i][None,])[1]
                  ).squeeze()
  
                  nn_idx[bi][i - self.k].copy_(nn_idx_i)
      nn_idx = nn_idx.view(*self.batch_shape, N - self.k, self.k).to(
          device=x.device
      )
      return nn_idx
  
file_path: gpytorch/gpytorch/utils/nearest_neighbors.py
imports: import warnings
  import torch
  from torch.nn import Module
label_desc: Use image node_id 6 for calling the NNUtil obj's underlying member method code with example usage: obj.build_sequential_nn_idx(x) and returns: nn_idx