<p dir="auto">In the sparse case, <code class="notranslate">preprocessing.binarize</code> always converts the input matrix to CSR format. For COO and CSC, the data attribute can also be accessed directly so in those cases there's no reason to convert to CSR. (CSC is especially useful for coordinate descent algorithms)</p>
<p dir="auto">This is a placeholder issue for sparse matrices support in the Histogram-based GBDT estimators.</p>
<p dir="auto">I guess <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="518378130" data-permission-text="Title is private" data-url="https://github.com/scikit-learn/scikit-learn/issues/15550" data-hovercard-type="issue" data-hovercard-url="/scikit-learn/scikit-learn/issues/15550/hovercard" href="https://github.com/scikit-learn/scikit-learn/issues/15550">#15550</a> should be tackled first.</p>
<hr>
<p dir="auto">Below are my thoughts and potential plan on the matter, feel free to ignore.</p>
<p dir="auto">Binning:</p>
<p dir="auto">We need a utility to compute quantiles on sparse data, and we need to map a float sparse matrix to a binned sparse matrix given those quantiles.  To avoid having to densify <code class="notranslate">X_binned</code>, the zeros in <code class="notranslate">X</code> should be mapped to bin 0, even if that's not their actual bin (called <code class="notranslate">actual_bin_zeros</code>). I guess that means all the bins in <code class="notranslate">range(0, actual_bin_zeros)</code> have an offset of 1, i.e. now they're actually mapped to <code class="notranslate">range(1, actual_bin_zeros + 1)</code>.  Though maybe we can avoid the offset by distinguishing between explicit and implicit zeros, IDK.</p>
<p dir="auto">Histograms:</p>
<p dir="auto">We need a histogram builder that can handle sparse data <em>and</em> that is aware of <code class="notranslate">actual_bin_zeros</code> in some way. We can't just build the histograms as usual, because that would mean that the zeros would be treated as the lowest value in the splitter.  In the histogram, the zeros should be placed in their proper bin, i.e. at index <code class="notranslate">actual_bin_zeros</code>. This way, the splitter can be left unchanged. The offset of the bins in <code class="notranslate">range(1, actual_bin_zeros)</code> should also be canceled here.</p>
<p dir="auto">When building a histogram, we can focus only on the non-zeros entries. We already know the totals <code class="notranslate">sum_gradients</code>, <code class="notranslate">sum_hessians</code>, and <code class="notranslate">count</code> at any given node. So we can just go through the samples that have non-zero values and fill-in the histogram at their respective bins, and then set <code class="notranslate">hist[actual_bin_zeros]['grad'] = total_sum_gradients - hist[:]['grad'].sum()</code>.</p>