class_docstr: The K-Elbow Visualizer implements the "elbow" method of selecting the
  optimal number of clusters for K-means clustering. K-means is a simple
  unsupervised machine learning algorithm that groups data into a specified
  number (k) of clusters. Because the user must specify in advance what k to
  choose, the algorithm is somewhat naive -- it assigns all members to k
  clusters even if that is not the right k for the dataset.
  
  The elbow method runs k-means clustering on the dataset for a range of
  values for k (say from 1-10) and then for each value of k computes an
  average score for all clusters. By default, the ``distortion`` score is
  computed, the sum of square distances from each point to its assigned
  center. Other metrics can also be used such as the ``silhouette`` score,
  the mean silhouette coefficient for all samples or the
  ``calinski_harabasz`` score, which computes the ratio of dispersion between
  and within clusters.
  
  When these overall metrics for each model are plotted, it is possible to
  visually determine the best value for k. If the line chart looks like an
  arm, then the "elbow" (the point of inflection on the curve) is the best
  value of k. The "arm" can be either up or down, but if there is a strong
  inflection point, it is a good indication that the underlying model fits
  best at that point.
  
  Parameters
  ----------
  
  estimator : a scikit-learn clusterer
      Should be an instance of an unfitted clusterer, specifically ``KMeans`` or
      ``MiniBatchKMeans``. If it is not a clusterer, an exception is raised.
  
  ax : matplotlib Axes, default: None
      The axes to plot the figure on. If None is passed in the current axes
      will be used (or generated if required).
  
  k : integer, tuple, or iterable
      The k values to compute silhouette scores for. If a single integer
      is specified, then will compute the range (2,k). If a tuple of 2
      integers is specified, then k will be in np.arange(k[0], k[1]).
      Otherwise, specify an iterable of integers to use as values for k.
  
  metric : string, default: ``"distortion"``
      Select the scoring metric to evaluate the clusters. The default is the
      mean distortion, defined by the sum of squared distances between each
      observation and its closest centroid. Other metrics include:
  
      - **distortion**: mean sum of squared distances to centers
      - **silhouette**: mean ratio of intra-cluster and nearest-cluster distance
      - **calinski_harabasz**: ratio of within to between cluster dispersion
  
  distance_metric : str or callable, default='euclidean'
      The metric to use when calculating distance between instances in a
      feature array. If metric is a string, it must be one of the options allowed
      by sklearn's metrics.pairwise.pairwise_distances. If X is the distance array
      itself, use metric="precomputed".
  
  timings : bool, default: True
      Display the fitting time per k to evaluate the amount of time required
      to train the clustering model.
  
  locate_elbow : bool, default: True
      Automatically find the "elbow" or "knee" which likely corresponds to the optimal
      value of k using the "knee point detection algorithm". The knee point detection
      algorithm finds the point of maximum curvature, which in a well-behaved
      clustering problem also represents the pivot of the elbow curve. The point is
      labeled with a dashed line and annotated with the score and k values.
  
  kwargs : dict
      Keyword arguments that are passed to the base class and may influence
      the visualization as defined in other Visualizers.
  
  Attributes
  ----------
  k_scores_ : array of shape (n,) where n is no. of k values
      The silhouette score corresponding to each k value.
  
  k_timers_ : array of shape (n,) where n is no. of k values
      The time taken to fit n KMeans model corresponding to each k value.
  
  elbow_value_ : integer
      The optimal value of k.
  
  elbow_score_ : float
      The silhouette score corresponding to the optimal value of k.
  
  Examples
  --------
  
  >>> from yellowbrick.cluster import KElbowVisualizer
  >>> from sklearn.cluster import KMeans
  >>> model = KElbowVisualizer(KMeans(), k=10)
  >>> model.fit(X)
  >>> model.show()
  
  Notes
  -----
  
  If you get a visualizer that doesn't have an elbow or inflection point,
  then this method may not be working. The elbow method does not work well
  if the data is not very clustered; in this case, you might see a smooth
  curve and the value of k is unclear. Other scoring methods, such as BIC or
  SSE, also can be used to explore if clustering is a correct choice.
  
  For a discussion on the Elbow method, read more at
  `Robert Gove's Block website <https://bl.ocks.org/rpgove/0060ff3b656618e9136b>`_.
  For more on the knee point detection algorithm see the paper `"Finding a "kneedle"
  in a Haystack" <https://raghavan.usc.edu//papers/kneedle-simplex11.pdf>`_.
  
  .. seealso:: The scikit-learn documentation for the `silhouette_score
      <https://bit.ly/2LYWjYb>`_ and `calinski_harabasz_score
      <https://bit.ly/2ItAgts>`_. The default, ``distortion_score``, is
      implemented in ``yellowbrick.cluster.elbow``.
  
  .. todo:: add parallelization option for performance
  .. todo:: add different metrics for scores and silhouette
  .. todo:: add timing information about how long it's taking
class_docstr_tok: ["The","K-Elbow","Visualizer","implements","the","``","elbow","''","method","of","selecting","the","optimal","number","of","clusters","for","K-means","clustering",".","K-means","is","a","simple","unsupervised","machine","learning","algorithm","that","groups","data","into","a","specified","number","(","k",")","of","clusters",".","Because","the","user","must","specify","in","advance","what","k","to","choose",",","the","algorithm","is","somewhat","naive","--","it","assigns","all","members","to","k","clusters","even","if","that","is","not","the","right","k","for","the","dataset",".","The","elbow","method","runs","k-means","clustering","on","the","dataset","for","a","range","of","values","for","k","(","say","from","1-10",")","and","then","for","each","value","of","k","computes","an","average","score","for","all","clusters",".","By","default",",","the","``","distortion","``","score","is","computed",",","the","sum","of","square","distances","from","each","point","to","its","assigned","center",".","Other","metrics","can","also","be","used","such","as","the","``","silhouette","``","score",",","the","mean","silhouette","coefficient","for","all","samples","or","the","``","calinski_harabasz","``","score",",","which","computes","the","ratio","of","dispersion","between","and","within","clusters",".","When","these","overall","metrics","for","each","model","are","plotted",",","it","is","possible","to","visually","determine","the","best","value","for","k.","If","the","line","chart","looks","like","an","arm",",","then","the","``","elbow","''","(","the","point","of","inflection","on","the","curve",")","is","the","best","value","of","k.","The","``","arm","''","can","be","either","up","or","down",",","but","if","there","is","a","strong","inflection","point",",","it","is","a","good","indication","that","the","underlying","model","fits","best","at","that","point",".","Parameters","--","--","--","--","--","estimator",":","a","scikit-learn","clusterer","Should","be","an","instance","of","an","unfitted","clusterer",",","specifically","``","KMeans","``","or","``","MiniBatchKMeans","``",".","If","it","is","not","a","clusterer",",","an","exception","is","raised",".","ax",":","matplotlib","Axes",",","default",":","None","The","axes","to","plot","the","figure","on",".","If","None","is","passed","in","the","current","axes","will","be","used","(","or","generated","if","required",")",".","k",":","integer",",","tuple",",","or","iterable","The","k","values","to","compute","silhouette","scores","for",".","If","a","single","integer","is","specified",",","then","will","compute","the","range","(","2",",","k",")",".","If","a","tuple","of","2","integers","is","specified",",","then","k","will","be","in","np.arange","(","k","[","0","]",",","k","[","1","]",")",".","Otherwise",",","specify","an","iterable","of","integers","to","use","as","values","for","k.","metric",":","string",",","default",":","``","``","distortion","''","``","Select","the","scoring","metric","to","evaluate","the","clusters",".","The","default","is","the","mean","distortion",",","defined","by","the","sum","of","squared","distances","between","each","observation","and","its","closest","centroid",".","Other","metrics","include",":","-","*","*","distortion","*","*",":","mean","sum","of","squared","distances","to","centers","-","*","*","silhouette","*","*",":","mean","ratio","of","intra-cluster","and","nearest-cluster","distance","-","*","*","calinski_harabasz","*","*",":","ratio","of","within","to","between","cluster","dispersion","distance_metric",":","str","or","callable",",","default='euclidean'","The","metric","to","use","when","calculating","distance","between","instances","in","a","feature","array",".","If","metric","is","a","string",",","it","must","be","one","of","the","options","allowed","by","sklearn","'s","metrics.pairwise.pairwise_distances",".","If","X","is","the","distance","array","itself",",","use","metric=","''","precomputed","''",".","timings",":","bool",",","default",":","True","Display","the","fitting","time","per","k","to","evaluate","the","amount","of","time","required","to","train","the","clustering","model",".","locate_elbow",":","bool",",","default",":","True","Automatically","find","the","``","elbow","''","or","``","knee","''","which","likely","corresponds","to","the","optimal","value","of","k","using","the","``","knee","point","detection","algorithm","''",".","The","knee","point","detection","algorithm","finds","the","point","of","maximum","curvature",",","which","in","a","well-behaved","clustering","problem","also","represents","the","pivot","of","the","elbow","curve",".","The","point","is","labeled","with","a","dashed","line","and","annotated","with","the","score","and","k","values",".","kwargs",":","dict","Keyword","arguments","that","are","passed","to","the","base","class","and","may","influence","the","visualization","as","defined","in","other","Visualizers",".","Attributes","--","--","--","--","--","k_scores_",":","array","of","shape","(","n",",",")","where","n","is","no",".","of","k","values","The","silhouette","score","corresponding","to","each","k","value",".","k_timers_",":","array","of","shape","(","n",",",")","where","n","is","no",".","of","k","values","The","time","taken","to","fit","n","KMeans","model","corresponding","to","each","k","value",".","elbow_value_",":","integer","The","optimal","value","of","k.","elbow_score_",":","float","The","silhouette","score","corresponding","to","the","optimal","value","of","k.","Examples","--","--","--","--",">",">",">","from","yellowbrick.cluster","import","KElbowVisualizer",">",">",">","from","sklearn.cluster","import","KMeans",">",">",">","model","=","KElbowVisualizer","(","KMeans","(",")",",","k=10",")",">",">",">","model.fit","(","X",")",">",">",">","model.show","(",")","Notes","--","--","-","If","you","get","a","visualizer","that","does","n't","have","an","elbow","or","inflection","point",",","then","this","method","may","not","be","working",".","The","elbow","method","does","not","work","well","if","the","data","is","not","very","clustered",";","in","this","case",",","you","might","see","a","smooth","curve","and","the","value","of","k","is","unclear",".","Other","scoring","methods",",","such","as","BIC","or","SSE",",","also","can","be","used","to","explore","if","clustering","is","a","correct","choice",".","For","a","discussion","on","the","Elbow","method",",","read","more","at","`","Robert","Gove","'s","Block","website","<","https",":","\/\/bl.ocks.org\/rpgove\/0060ff3b656618e9136b",">","`","_",".","For","more","on","the","knee","point","detection","algorithm","see","the","paper","`","``","Finding","a","``","kneedle","''","in","a","Haystack","''","<","https",":","\/\/raghavan.usc.edu\/\/papers\/kneedle-simplex11.pdf",">","`","_",".","..","seealso",":",":","The","scikit-learn","documentation","for","the","`","silhouette_score","<","https",":","\/\/bit.ly\/2LYWjYb",">","`","_","and","`","calinski_harabasz_score","<","https",":","\/\/bit.ly\/2ItAgts",">","`","_",".","The","default",",","``","distortion_score","``",",","is","implemented","in","``","yellowbrick.cluster.elbow","``",".","..","todo",":",":","add","parallelization","option","for","performance","..","todo",":",":","add","different","metrics","for","scores","and","silhouette","..","todo",":",":","add","timing","information","about","how","long","it","'s","taking"]
docstr: Draw the elbow curve for the specified scores and values of K.
docstr_tok: ["Draw","the","elbow","curve","for","the","specified","scores","and","values","of","K","."]
code: def draw(self):
      """
      Draw the elbow curve for the specified scores and values of K.
      """
      # Plot the silhouette score against k
      self.ax.plot(
          self.k_values_,
          self.k_scores_,
          marker="D",
          c=self.metric_color,
      )
      if self.locate_elbow is True and self.elbow_value_ is not None:
          elbow_label = "elbow at $k={}$, $score={:0.3f}$".format(
              self.elbow_value_, self.elbow_score_
          )
          self.ax.axvline(
              self.elbow_value_,
              c=self.vline_color,
              linestyle="--",
              label=elbow_label,
          )
  
      # If we're going to plot the timings, create a twinx axis
      if self.timings:
          self.axes = [self.ax, self.ax.twinx()]
          self.axes[1].plot(
              self.k_values_,
              self.k_timers_,
              label="fit time",
              c=self.timing_color,
              marker="o",
              linestyle="--",
              alpha=0.75,
          )
  
      return self.ax
  
imports: import time
  import warnings
  import numpy
  import scipy.sparse
  from collections.abc import Iterable
  from sklearn.preprocessing import LabelEncoder
  from sklearn.metrics.pairwise import pairwise_distances
  from sklearn.metrics import silhouette_score, DistanceMetric
  from yellowbrick.utils import KneeLocator, get_param_names
  from yellowbrick.style.palettes import LINE_COLOR
  from yellowbrick.cluster.base import ClusteringScoreVisualizer
  from yellowbrick.exceptions import YellowbrickValueError, YellowbrickWarning
label_desc: Use image node_id 3 for calling the KElbowVisualizer obj's underlying member method code with example usage: obj.draw() and returns: self