docstr: X is the training data which must be, in general, a 2D array of dimension n_samples * n_features
  
  Fit K-Medoids to the provided data.
  
  Parameters
  ----------
  X : {array-like, sparse matrix}, shape = (n_samples, n_features),                 or (n_samples, n_samples) if metric == 'precomputed'
      Dataset to cluster.
  
  y : Ignored
  
  Returns
  -------
  self
docstr_tok: ["X","is","the","training","data","which","must","be",",","in","general",",","a","2D","array","of","dimension","n_samples","*","n_features","Fit","K-Medoids","to","the","provided","data",".","Parameters","--","--","--","--","--","X",":","{","array-like",",","sparse","matrix","}",",","shape","=","(","n_samples",",","n_features",")",",","or","(","n_samples",",","n_samples",")","if","metric","==","'precomputed'","Dataset","to","cluster",".","y",":","Ignored","Returns","--","--","--","-","self"]
code: def fit(self, X, Y=None):
      """ X is the training data which must be, in general, a 2D array of dimension n_samples * n_features
  
          Fit K-Medoids to the provided data.
  
          Parameters
          ----------
          X : {array-like, sparse matrix}, shape = (n_samples, n_features), \
                  or (n_samples, n_samples) if metric == 'precomputed'
              Dataset to cluster.
  
          y : Ignored
  
          Returns
          -------
          self
          """
  
      self._check_arguments()
  
      random_state_object = self._get_random_state(self.random_state)
  
      if Y != None:
          raise Exception("Clustering fit takes only one parameter")
  
      X = check_array(X, accept_sparse=["csc", "csr"])
  
      n_samples, n_features = X.shape[0], X.shape[1]
  
      if self.n_clusters > n_samples:
          raise ValueError(
              f"Number of clusters {self.n_clusters} cannot be greater than number of samples {n_samples}"
          )
  
      distances = pairwise_distances(X, Y, metric=self.metric)
      # print("Distances:", distances.shape)
      medoids = self._initialize_medoids(
          distances, self.n_clusters, random_state_object
      )  # Initialized medoids.
      d_closest_medoid, d_second_closest_medoid = np.sort(
          distances[medoids], axis=0
      )[[0, 1]]
      labels = None
  
      for i in range(self.max_iter):
          medoids_copy = np.copy(medoids)
          not_medoids = np.delete(np.arange(len(distances)), medoids)
          # Associate each data point with closest medoid
          labels = np.argmin(distances[medoids, :], axis=0)
          # For each medoid m and each observation o, compute cost of swap
          optimal_swap = self._compute_optimal_swap(
              distances,
              medoids,
              not_medoids,
              d_closest_medoid,
              d_second_closest_medoid,
              self.n_clusters,
          )
          # If cost is current best, keep this medoid and o combo
          if optimal_swap:
              current_medoid, potential_medoid, _ = optimal_swap
              medoids[medoids == current_medoid] = potential_medoid
              d_closest_medoid, d_second_closest_medoid = np.sort(
                  distances[medoids], axis=0
              )[[0, 1]]
          # If cost function decreases (total intra-cluster sum), swap. Else terminate.
  
          if np.all(medoids_copy == medoids):
              break
          elif i == self.max_iter - 1:
              warnings.warn(
                  "Maximum number of iteration reached before "
                  "convergence. Consider increasing max_iter to "
                  "improve the fit.",
                  ConvergenceWarning,
              )
  
      self.cluster_centers_ = X[medoids]
      self.labels_ = np.argmin(distances[medoids, :], axis=0)
      self.medoid_indices_ = medoids
      self.inertia_ = self._compute_inertia(self.transform(X))
      self.score_ = -self.inertia_
      # Return self to enable method chaining
      return self
  
imports: import warnings
  import numpy
  from sklearn.base import BaseEstimator, ClusterMixin
  from sklearn.exceptions import ConvergenceWarning
  from sklearn.metrics.pairwise import pairwise_distances, pairwise_distances_argmin
  from sklearn.utils import check_array
  from sklearn.utils.validation import check_is_fitted
label_desc: Use image node_id 8 for calling the KMedoids obj's underlying member method code with example usage: obj.fit(X, Y) and returns: self