code: def find_clusters(X, model, clustering_algorithm=DBSCAN(), mode="e"):
      """
      Perform link-based cluster analysis on a knowledge graph.
  
      The clustering happens on the embedding space of the entities and relations.
      For example, if we cluster some entities of a model that uses :math:`k=100`
      (i.e. embedding space of size 100), we will apply the chosen clustering algorithm
      on the 100-dimensional space of the provided input samples.
  
      Clustering can be used to evaluate the quality of the knowledge embeddings,
      by comparing to natural clusters. For example, in the example below we cluster
      the embeddings of international football matches and end up finding geographical
      clusters very similar to the continents. This comparison can be subjective by
      inspecting a 2D projection of the embedding space or objective using a
      `clustering metric <https://scikit-learn.org/stable/modules/clustering.html#clustering-performance-evaluation>`_.
  
      | The choice of the clustering algorithm and its corresponding tuning will greatly impact the results.
        Please see `scikit-learn documentation <https://scikit-learn.org/stable/modules/clustering.html#clustering>`_
        for a list of algorithms, their parameters, and pros and cons.
  
      Clustering is exclusive (i.e., a triple is assigned to one and only one cluster).
  
      Parameters
      ----------
  
      X : ndarray, shape (n, 3) or (n)
          The input to be clustered.
          ``X`` can either be the triples of a knowledge graph, its entities, or its relations.
          The argument ``mode`` defines whether ``X`` is supposed to be an array of triples
          or an array of either entities or relations.
      model : EmbeddingModel
          The fitted model that will be used to generate the embeddings.
          This model must have been fully trained already, be it directly with
          ``fit()`` or from a helper function such as :meth:`ampligraph.evaluation.select_best_model_ranking`.
      clustering_algorithm : object
          The initialized object of the clustering algorithm.
          It should be ready to apply the :meth:`fit_predict` method.
          Please see: `scikit-learn documentation <https://scikit-learn.org/stable/modules/clustering.html#clustering>`_
          to understand the clustering API provided by scikit-learn.
          The default clustering model is
          `sklearn's DBSCAN <https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html>`_
          with its default parameters.
      mode: str
          Clustering mode.
  
          Choose from:
  
          - | `'e'` (default): the algorithm will cluster the embeddings of the provided entities.
          - | `'r'`: the algorithm will cluster the embeddings of the provided relations.
          - | `'t'` : the algorithm will cluster the concatenation
              of the embeddings of the subject, predicate and object for each triple.
  
      Returns
      -------
      labels : ndarray, shape [n]
          Index of the cluster each triple belongs to.
  
      Example
      -------
      >>> # Note seaborn, matplotlib, adjustText are not AmpliGraph dependencies.
      >>> # and must therefore be installed manually as:
      >>> #
      >>> # $ pip install seaborn matplotlib adjustText
      >>>
      >>> import requests
      >>> import pandas as pd
      >>> import numpy as np
      >>> from sklearn.decomposition import PCA
      >>> from sklearn.cluster import KMeans
      >>> import matplotlib.pyplot as plt
      >>> import seaborn as sns
      >>>
      >>> # adjustText lib: https://github.com/Phlya/adjustText
      >>> from adjustText import adjust_text
      >>>
      >>> from ampligraph.datasets import load_from_csv
      >>> from ampligraph.latent_features import ScoringBasedEmbeddingModel
      >>> from ampligraph.discovery import find_clusters
      >>>
      >>> # International football matches triples
      >>> # See tutorial here to understand how the triples are created from a tabular dataset:
      >>> # https://github.com/Accenture/AmpliGraph/blob/master/docs/tutorials/\
  ClusteringAndClassificationWithEmbeddings.ipynb
      >>> url = 'https://ampligraph.s3-eu-west-1.amazonaws.com/datasets/football.csv'
      >>> open('football.csv', 'wb').write(requests.get(url).content)
      >>> X = load_from_csv('.', 'football.csv', sep=',')[:, 1:]
      >>>
      >>> model = ScoringBasedEmbeddingModel(eta=5,
      >>>                                  k=300,
      >>>                                  scoring_type='ComplEx')
      >>> model.compile(optimizer='adam', loss='multiclass_nll')
      >>> model.fit(X,
      >>>           batch_size=10000,
      >>>           epochs=10)
      >>>
      >>> df = pd.DataFrame(X, columns=["s", "p", "o"])
      >>>
      >>> teams = np.unique(np.concatenate((df.s[df.s.str.startswith("Team")],
      >>>                                   df.o[df.o.str.startswith("Team")])))
      >>> team_embeddings = model.get_embeddings(teams, embedding_type='e')
      >>>
      >>> embeddings_2d = PCA(n_components=2).fit_transform(np.array([i for i in team_embeddings]))
      >>>
      >>> # Find clusters of embeddings using KMeans
      >>>
      >>> kmeans = KMeans(n_clusters=6, n_init=100, max_iter=500)
      >>> clusters = find_clusters(teams, model, kmeans, mode='e')
      >>>
      >>> # Plot results
      >>> df = pd.DataFrame({"teams": teams, "clusters": "cluster" + pd.Series(clusters).astype(str),
      >>>                    "embedding1": embeddings_2d[:, 0], "embedding2": embeddings_2d[:, 1]})
      >>>
      >>> plt.figure(figsize=(10, 10))
      >>> plt.title("Cluster embeddings")
      >>>
      >>> ax = sns.scatterplot(data=df, x="embedding1", y="embedding2", hue="clusters")
      >>>
      >>> texts = []
      >>> for i, point in df.iterrows():
      >>>     if np.random.uniform() < 0.1:
      >>>         texts.append(plt.text(point['embedding1']+.02, point['embedding2'], str(point['teams'])))
      >>> adjust_text(texts)
  
      .. image:: ../img/clustering/clustered_embeddings_docstring.png
          :align: center
  
      """
      if model.is_backward:
          model = model.model
  
      if not model.is_fitted:
          msg = "Model has not been fitted."
          logger.error(msg)
          raise ValueError(msg)
  
      if not hasattr(clustering_algorithm, "fit_predict"):
          msg = "Clustering algorithm does not have the `fit_predict` method."
          logger.error(msg)
          raise ValueError(msg)
  
      modes = ("t", "e", "r")
      if mode not in modes:
          msg = "Argument `mode` must be one of the following: {}.".format(
              ", ".join(modes)
          )
          logger.error(msg)
          raise ValueError(msg)
  
      if mode == "t" and (len(X.shape) != 2 or X.shape[1] != 3):
          msg = "For 't' mode the input X must be a matrix with three columns."
          logger.error(msg)
          raise ValueError(msg)
  
      if mode in ("e", "r") and len(X.shape) != 1:
          msg = "For 'e' or 'r' mode the input X must be an array."
          raise ValueError(msg)
  
      if mode == "t":
          s = model.get_embeddings(X[:, 0], embedding_type="e")
          p = model.get_embeddings(X[:, 1], embedding_type="r")
          o = model.get_embeddings(X[:, 2], embedding_type="e")
          emb = np.hstack((s, p, o))
      else:
          emb = model.get_embeddings(X, embedding_type=mode)
  
      return clustering_algorithm.fit_predict(emb)
  
file_path: AmpliGraph/ampligraph/discovery/discovery.py
imports: import logging
  import networkx
  import numpy
  from scipy import optimize, spatial
  from sklearn.cluster import DBSCAN
  from sklearn.neighbors import NearestNeighbors
label_desc: Use image node_id 4 for calling a global function with example usage: find_clusters(X, model, clustering_algorithm, mode) and returns: clustering_algorithm