<h3 dir="auto">Describe the workflow you want to enable</h3>
<p dir="auto">When <code class="notranslate">verbose&gt;0</code>, the fitting is shown as a progress bar including the average time/pace and last fit attempted time.</p>
<h3 dir="auto">Describe your proposed solution</h3>
<p dir="auto">Implement <code class="notranslate">tqdm</code>-like or <code class="notranslate">keras</code>-like (familiar to epoch tracking) progress bar such that the feature can be enabled through an argument of <code class="notranslate">verbose</code>. This proposal is under the assumption that the iteration is accessible like <code class="notranslate">for</code> loop.</p>
<h3 dir="auto">Describe alternatives you've considered, if relevant</h3>
<p dir="auto"><em>No response</em></p>
<h3 dir="auto">Additional context</h3>
<p dir="auto">I've been using GridSearchCV and brute-forcing parameters (regarding algorithms, domain-knowledge agnostic) to find the best model parameters while leaving the machine unattended (disconnect from the cloud). But sometimes, the kernel might freeze without any indication. Even with <code class="notranslate">verbose</code> tracking, it's hard to skim through the log, especially among hundreds of fits to deduce that the process has been interrupted.<br>
The issue expanded from a simple inquiry of <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="121914425" data-permission-text="Title is private" data-url="https://github.com/scikit-learn/scikit-learn/issues/6021" data-hovercard-type="issue" data-hovercard-url="/scikit-learn/scikit-learn/issues/6021/hovercard" href="https://github.com/scikit-learn/scikit-learn/issues/6021">#6021</a> .</p>
<h3 dir="auto">Describe the bug</h3>
<p dir="auto">The constant:<code class="notranslate">sklearn.neighbors.VALID_METRICS['brute']</code> returns duplicate "cosine" keyword.<br>
It seems harmless, but I think it should return a unique keyword list to avoid unnecessary confusion.</p>
<p dir="auto">The constant is defined here:</p>
<p dir="auto"></p><div class="Box Box--condensed my-2">
  <div class="Box-header f6">
    <p class="mb-0 text-bold">
      <a href="https://github.com/scikit-learn/scikit-learn/blob/691972a7cf04e7a8918b907556b4e9904f82bd0c/sklearn/neighbors/_base.py#L40-L69">scikit-learn/sklearn/neighbors/_base.py</a>
    </p>
    <p class="mb-0 color-fg-muted">
        Lines 40 to 69
      in
      <a data-pjax="true" class="commit-tease-sha" href="/scikit-learn/scikit-learn/commit/691972a7cf04e7a8918b907556b4e9904f82bd0c">691972a</a>
    </p>
  </div>
  <div itemprop="text" class="Box-body p-0 blob-wrapper blob-wrapper-embedded data">
    <table class="highlight tab-size mb-0 js-file-line-container" data-tab-size="8" data-paste-markdown-skip="">

        <tbody><tr class="border-0">
          <td id="L40" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="40"></td>
          <td id="LC40" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> <span class="pl-v">VALID_METRICS</span> <span class="pl-c1">=</span> <span class="pl-en">dict</span>( </td>
        </tr>

        <tr class="border-0">
          <td id="L41" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="41"></td>
          <td id="LC41" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">     <span class="pl-s1">ball_tree</span><span class="pl-c1">=</span><span class="pl-v">BallTree</span>.<span class="pl-s1">valid_metrics</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L42" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="42"></td>
          <td id="LC42" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">     <span class="pl-s1">kd_tree</span><span class="pl-c1">=</span><span class="pl-v">KDTree</span>.<span class="pl-s1">valid_metrics</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L43" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="43"></td>
          <td id="LC43" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">     <span class="pl-c"># The following list comes from the</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L44" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="44"></td>
          <td id="LC44" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">     <span class="pl-c"># sklearn.metrics.pairwise doc string</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L45" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="45"></td>
          <td id="LC45" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">     <span class="pl-s1">brute</span><span class="pl-c1">=</span>( </td>
        </tr>

        <tr class="border-0">
          <td id="L46" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="46"></td>
          <td id="LC46" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         <span class="pl-en">list</span>(<span class="pl-v">PAIRWISE_DISTANCE_FUNCTIONS</span>.<span class="pl-en">keys</span>()) </td>
        </tr>

        <tr class="border-0">
          <td id="L47" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="47"></td>
          <td id="LC47" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         <span class="pl-c1">+</span> [ </td>
        </tr>

        <tr class="border-0">
          <td id="L48" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="48"></td>
          <td id="LC48" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"braycurtis"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L49" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="49"></td>
          <td id="LC49" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"canberra"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L50" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="50"></td>
          <td id="LC50" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"chebyshev"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L51" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="51"></td>
          <td id="LC51" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"correlation"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L52" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="52"></td>
          <td id="LC52" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"cosine"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L53" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="53"></td>
          <td id="LC53" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"dice"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L54" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="54"></td>
          <td id="LC54" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"hamming"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L55" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="55"></td>
          <td id="LC55" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"jaccard"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L56" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="56"></td>
          <td id="LC56" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"kulsinski"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L57" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="57"></td>
          <td id="LC57" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"mahalanobis"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L58" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="58"></td>
          <td id="LC58" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"matching"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L59" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="59"></td>
          <td id="LC59" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"minkowski"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L60" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="60"></td>
          <td id="LC60" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"rogerstanimoto"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L61" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="61"></td>
          <td id="LC61" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"russellrao"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L62" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="62"></td>
          <td id="LC62" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"seuclidean"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L63" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="63"></td>
          <td id="LC63" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"sokalmichener"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L64" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="64"></td>
          <td id="LC64" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"sokalsneath"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L65" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="65"></td>
          <td id="LC65" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"sqeuclidean"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L66" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="66"></td>
          <td id="LC66" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">             <span class="pl-s">"yule"</span>, </td>
        </tr>

        <tr class="border-0">
          <td id="L67" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="67"></td>
          <td id="LC67" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         ] </td>
        </tr>

        <tr class="border-0">
          <td id="L68" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="68"></td>
          <td id="LC68" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">     ), </td>
        </tr>

        <tr class="border-0">
          <td id="L69" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="69"></td>
          <td id="LC69" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> ) </td>
        </tr>
    </tbody></table>
  </div>
</div>
<p></p>
<p dir="auto">Removing <code class="notranslate">cosine</code> from the latter list looks OK, but I think using <code class="notranslate">set().union</code> is more robust.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="brute=(
    set(PAIRWISE_DISTANCE_FUNCTIONS.keys()).union([
        &quot;braycurtis&quot;,
        &quot;canberra&quot;,
        &quot;chebyshev&quot;,
        &quot;correlation&quot;,
        &quot;cosine&quot;,
        &quot;dice&quot;,
        ...
    ])
)"><pre class="notranslate"><span class="pl-s1">brute</span><span class="pl-c1">=</span>(
    <span class="pl-en">set</span>(<span class="pl-v">PAIRWISE_DISTANCE_FUNCTIONS</span>.<span class="pl-en">keys</span>()).<span class="pl-en">union</span>([
        <span class="pl-s">"braycurtis"</span>,
        <span class="pl-s">"canberra"</span>,
        <span class="pl-s">"chebyshev"</span>,
        <span class="pl-s">"correlation"</span>,
        <span class="pl-s">"cosine"</span>,
        <span class="pl-s">"dice"</span>,
        ...
    ])
)</pre></div>
<h3 dir="auto">Steps/Code to Reproduce</h3>
<p dir="auto">Run the following codes on the colab.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="!pip install scikit-learn -Uq"><pre class="notranslate"><code class="notranslate">!pip install scikit-learn -Uq
</code></pre></div>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import sklearn.neighbors
brute_metrics = sorted(sklearn.neighbors.VALID_METRICS['brute'])
print(len(brute_metrics), len(set(brute_metrics)))
print(brute_metrics[5:7])"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">sklearn</span>.<span class="pl-s1">neighbors</span>
<span class="pl-s1">brute_metrics</span> <span class="pl-c1">=</span> <span class="pl-en">sorted</span>(<span class="pl-s1">sklearn</span>.<span class="pl-s1">neighbors</span>.<span class="pl-v">VALID_METRICS</span>[<span class="pl-s">'brute'</span>])
<span class="pl-en">print</span>(<span class="pl-en">len</span>(<span class="pl-s1">brute_metrics</span>), <span class="pl-en">len</span>(<span class="pl-en">set</span>(<span class="pl-s1">brute_metrics</span>)))
<span class="pl-en">print</span>(<span class="pl-s1">brute_metrics</span>[<span class="pl-c1">5</span>:<span class="pl-c1">7</span>])</pre></div>
<p dir="auto">The result will be:</p>
<div class="highlight highlight-text-adblock notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="29 28
['cosine', 'cosine']"><pre class="notranslate">29 28
[<span class="pl-ii">'cosine', 'cosine'</span>]</pre></div>
<h3 dir="auto">Expected Results</h3>
<p dir="auto"><code class="notranslate">sklearn.neighbors.VALID_METRICS['brute']</code> returns unique keywords</p>
<h3 dir="auto">Actual Results</h3>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import sklearn.neighbors
brute_metrics = sorted(sklearn.neighbors.VALID_METRICS['brute'])
assert len(brute_metrics) == len(set(brute_metrics)), &quot;detect duplicates!&quot;"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">sklearn</span>.<span class="pl-s1">neighbors</span>
<span class="pl-s1">brute_metrics</span> <span class="pl-c1">=</span> <span class="pl-en">sorted</span>(<span class="pl-s1">sklearn</span>.<span class="pl-s1">neighbors</span>.<span class="pl-v">VALID_METRICS</span>[<span class="pl-s">'brute'</span>])
<span class="pl-k">assert</span> <span class="pl-en">len</span>(<span class="pl-s1">brute_metrics</span>) <span class="pl-c1">==</span> <span class="pl-en">len</span>(<span class="pl-en">set</span>(<span class="pl-s1">brute_metrics</span>)), <span class="pl-s">"detect duplicates!"</span></pre></div>
<p dir="auto">Got:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
[&lt;ipython-input-13-279d32fcf741&gt;](https://localhost:8080/#) in &lt;module&gt;()
      1 import sklearn.neighbors
      2 brute_metrics = sorted(sklearn.neighbors.VALID_METRICS['brute'])
----&gt; 3 assert len(brute_metrics) == len(set(brute_metrics)), &quot;detect duplicates!&quot;
      4 
      5 

AssertionError: detect duplicates!"><pre class="notranslate"><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span>
<span class="pl-v">AssertionError</span>                            <span class="pl-v">Traceback</span> (<span class="pl-s1">most</span> <span class="pl-s1">recent</span> <span class="pl-s1">call</span> <span class="pl-s1">last</span>)
[<span class="pl-c1">&lt;</span><span class="pl-s1">ipython</span><span class="pl-c1">-</span><span class="pl-s1">input</span><span class="pl-c1">-</span><span class="pl-c1">13</span><span class="pl-c1">-</span><span class="pl-c1">279</span><span class="pl-s1">d32fcf741</span><span class="pl-c1">&gt;</span>](<span class="pl-s1">https</span>:<span class="pl-c1">//</span><span class="pl-s1">localhost</span>:<span class="pl-c1">8080</span><span class="pl-c1">/</span><span class="pl-c">#) in &lt;module&gt;()</span>
      <span class="pl-c1">1</span> <span class="pl-s1">import</span> <span class="pl-s1">sklearn</span>.<span class="pl-s1">neighbors</span>
      <span class="pl-c1">2</span> <span class="pl-s1">brute_metrics</span> <span class="pl-c1">=</span> <span class="pl-en">sorted</span>(<span class="pl-s1">sklearn</span>.<span class="pl-s1">neighbors</span>.<span class="pl-v">VALID_METRICS</span>[<span class="pl-s">'brute'</span>])
<span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">-</span><span class="pl-c1">&gt;</span> <span class="pl-c1">3</span> <span class="pl-s1">assert</span> <span class="pl-en">len</span>(<span class="pl-s1">brute_metrics</span>) <span class="pl-c1">==</span> <span class="pl-en">len</span>(<span class="pl-en">set</span>(<span class="pl-s1">brute_metrics</span>)), <span class="pl-s">"detect duplicates!"</span>
      <span class="pl-c1">4</span> 
      <span class="pl-c1">5</span> 

<span class="pl-v">AssertionError</span>: <span class="pl-s1">detect</span> <span class="pl-s1">duplicates</span>!</pre></div>
<h3 dir="auto">Versions</h3>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="System:
    python: 3.7.12 (default, Jan 15 2022, 18:48:18)  [GCC 7.5.0]
executable: /usr/bin/python3
   machine: Linux-5.4.144+-x86_64-with-Ubuntu-18.04-bionic

Python dependencies:
          pip: 21.1.3
   setuptools: 57.4.0
      sklearn: 1.0.2
        numpy: 1.21.5
        scipy: 1.4.1
       Cython: 0.29.28
       pandas: 1.3.5
   matplotlib: 3.2.2
       joblib: 1.1.0
threadpoolctl: 3.1.0

Built with OpenMP: True"><pre class="notranslate">System:
    python: 3.7.12 (default, Jan 15 2022, 18:48:18)  [GCC 7.5.0]
executable: /usr/bin/python3
   machine: Linux-5.4.144+-x86_64-with-Ubuntu-18.04-bionic

Python dependencies:
          pip: 21.1.3
   setuptools: 57.4.0
      sklearn: 1.0.2
        numpy: 1.21.5
        scipy: 1.4.1
       Cython: 0.29.28
       pandas: 1.3.5
   matplotlib: 3.2.2
       joblib: 1.1.0
threadpoolctl: 3.1.0

Built with OpenMP: True</pre></div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content=""><pre class="notranslate"><code class="notranslate"></code></pre></div>