class_docstr: Finds the "elbow" or "knee" which is a value corresponding to the point of maximum curvature
  in an elbow curve, using knee point detection algorithm. This point is accessible via the
  `knee` attribute.
  
  Parameters
  ----------
  x : list
     A list of k values representing the no. of clusters in KMeans Clustering algorithm.
  
  y : list
     A list of k scores corresponding to each value of k. The type of k scores are determined 
     by the metric parameter from the KElbowVisualizer class.
  
  S : float, default: 1.0
     Sensitivity parameter that allows us to adjust how aggressive we want KneeLocator to
     be when detecting "knees" or "elbows".
  
  curve_nature : string, default: 'concave'
     A string that determines the nature of the elbow curve in which "knee" or "elbow" is
     to be found.
  
  curve_direction : string, default: 'increasing'
     A string that determines the increasing or decreasing nature of the elbow curve in
     which "knee" or "elbow" is to be found.
  
  online : bool, default: False
      kneed will correct old knee points if True, will return first knee if False
  
  Notes
  -----
  The KneeLocator is implemented using the "knee point detection algorithm" which can be read at
  `<https://www1.icsi.berkeley.edu/~barath/papers/kneedle-simplex11.pdf>`
class_docstr_tok: ["Finds","the","``","elbow","''","or","``","knee","''","which","is","a","value","corresponding","to","the","point","of","maximum","curvature","in","an","elbow","curve",",","using","knee","point","detection","algorithm",".","This","point","is","accessible","via","the","`","knee","`","attribute",".","Parameters","--","--","--","--","--","x",":","list","A","list","of","k","values","representing","the","no",".","of","clusters","in","KMeans","Clustering","algorithm",".","y",":","list","A","list","of","k","scores","corresponding","to","each","value","of","k.","The","type","of","k","scores","are","determined","by","the","metric","parameter","from","the","KElbowVisualizer","class",".","S",":","float",",","default",":","1.0","Sensitivity","parameter","that","allows","us","to","adjust","how","aggressive","we","want","KneeLocator","to","be","when","detecting","``","knees","''","or","``","elbows","''",".","curve_nature",":","string",",","default",":","'concave'","A","string","that","determines","the","nature","of","the","elbow","curve","in","which","``","knee","''","or","``","elbow","''","is","to","be","found",".","curve_direction",":","string",",","default",":","'increasing'","A","string","that","determines","the","increasing","or","decreasing","nature","of","the","elbow","curve","in","which","``","knee","''","or","``","elbow","''","is","to","be","found",".","online",":","bool",",","default",":","False","kneed","will","correct","old","knee","points","if","True",",","will","return","first","knee","if","False","Notes","--","--","-","The","KneeLocator","is","implemented","using","the","``","knee","point","detection","algorithm","''","which","can","be","read","at","`","<","https",":","\/\/www1.icsi.berkeley.edu\/~barath\/papers\/kneedle-simplex11.pdf",">","`"]
docstr: This function finds and sets the knee value and the normalized knee value. 
docstr_tok: ["This","function","finds","and","sets","the","knee","value","and","the","normalized","knee","value","."]
code: def find_knee(
      self,
  ):
      """This function finds and sets the knee value and the normalized knee value."""
      if not self.maxima_indices.size:
          warning_message = (
              'No "knee" or "elbow point" detected '
              "This could be due to bad clustering, no "
              "actual clusters being formed etc."
          )
          warnings.warn(warning_message, YellowbrickWarning)
          return None, None
  
      # placeholder for which threshold region i is located in.
      maxima_threshold_index = 0
      minima_threshold_index = 0
      # traverse the difference curve
      for i, x in enumerate(self.x_difference):
          # skip points on the curve before the the first local maxima
          if i < self.maxima_indices[0]:
              continue
  
          j = i + 1
  
          # reached the end of the curve
          if x == 1.0:
              break
  
          # if we're at a local max, increment the maxima threshold index and continue
          if (self.maxima_indices == i).any():
              threshold = self.Tmx[maxima_threshold_index]
              threshold_index = i
              maxima_threshold_index += 1
          # values in difference curve are at or after a local minimum
          if (self.minima_indices == i).any():
              threshold = 0.0
              minima_threshold_index += 1
  
          if self.y_difference[j] < threshold:
              if self.curve_nature == "convex":
                  if self.curve_direction == "decreasing":
                      knee = self.x[threshold_index]
                      norm_knee = self.x_normalized[threshold_index]
                  else:
                      knee = self.x[-(threshold_index + 1)]
                      norm_knee = self.x_normalized[threshold_index]
  
              elif self.curve_nature == "concave":
                  if self.curve_direction == "decreasing":
                      knee = self.x[-(threshold_index + 1)]
                      norm_knee = self.x_normalized[threshold_index]
                  else:
                      knee = self.x[threshold_index]
                      norm_knee = self.x_normalized[threshold_index]
  
              # add the y value at the knee
              y_at_knee = self.y[self.x == knee][0]
              y_norm_at_knee = self.y_normalized[
                  self.x_normalized == norm_knee
              ][0]
              if knee not in self.all_knees:
                  self.all_knees_y.append(y_at_knee)
                  self.all_norm_knees_y.append(y_norm_at_knee)
  
              # now add the knee
              self.all_knees.add(knee)
              self.all_norm_knees.add(norm_knee)
  
              # if detecting in offline mode, return the first knee found
              if self.online is False:
                  return knee, norm_knee
  
      if self.all_knees == set():
          return None, None
  
      return knee, norm_knee
  
imports: import numpy
  from scipy import interpolate
  from scipy.signal import argrelextrema
  import warnings
  from yellowbrick.exceptions import YellowbrickWarning
label_desc: Use image node_id 4 for calling the KneeLocator obj's underlying member method code with example usage: obj.find_knee() and returns: knee,  norm_knee, None,  None, None,  None, knee,  norm_knee