<h3 dir="auto">Describe the workflow you want to enable</h3>
<p dir="auto">As a user of Scikit-learn, I want to be able to calculate the McFadden's pseudo R-squared for a binary logistic regression model for that we need log-likelihood and null log-likelihood.</p>
<h3 dir="auto">Describe your proposed solution</h3>
<p dir="auto">I use the following functions and I propose to add them in the library as well.</p>
<h3 dir="auto">For Log Likelihood -</h3>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import numpy as np
from sklearn.linear_model import LogisticRegression

def log_likelihood(model, X, y):
    &quot;&quot;&quot;Calculate the log-likelihood of a binary logistic regression model.

    Parameters
    ----------
    model : sklearn.linear_model.LogisticRegression
        A trained binary logistic regression model.
    X : array-like, shape (n_samples, n_features)
        Feature matrix.
    y : array-like, shape (n_samples,)
        Binary class labels.

    Returns
    -------
    log_likelihood : float
        The log-likelihood of the model.
    &quot;&quot;&quot;

    # Get predicted probabilities
    pred_probs = model.predict_proba(X)[:, 1]

    # Calculate log-likelihood
    log_likelihood = np.sum(y * np.log(pred_probs) + (1 - y) * np.log(1 - pred_probs))

    return log_likelihood
"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">numpy</span> <span class="pl-k">as</span> <span class="pl-s1">np</span>
<span class="pl-k">from</span> <span class="pl-s1">sklearn</span>.<span class="pl-s1">linear_model</span> <span class="pl-k">import</span> <span class="pl-v">LogisticRegression</span>

<span class="pl-k">def</span> <span class="pl-en">log_likelihood</span>(<span class="pl-s1">model</span>, <span class="pl-v">X</span>, <span class="pl-s1">y</span>):
    <span class="pl-s">"""Calculate the log-likelihood of a binary logistic regression model.</span>
<span class="pl-s"></span>
<span class="pl-s">    Parameters</span>
<span class="pl-s">    ----------</span>
<span class="pl-s">    model : sklearn.linear_model.LogisticRegression</span>
<span class="pl-s">        A trained binary logistic regression model.</span>
<span class="pl-s">    X : array-like, shape (n_samples, n_features)</span>
<span class="pl-s">        Feature matrix.</span>
<span class="pl-s">    y : array-like, shape (n_samples,)</span>
<span class="pl-s">        Binary class labels.</span>
<span class="pl-s"></span>
<span class="pl-s">    Returns</span>
<span class="pl-s">    -------</span>
<span class="pl-s">    log_likelihood : float</span>
<span class="pl-s">        The log-likelihood of the model.</span>
<span class="pl-s">    """</span>

    <span class="pl-c"># Get predicted probabilities</span>
    <span class="pl-s1">pred_probs</span> <span class="pl-c1">=</span> <span class="pl-s1">model</span>.<span class="pl-en">predict_proba</span>(<span class="pl-v">X</span>)[:, <span class="pl-c1">1</span>]

    <span class="pl-c"># Calculate log-likelihood</span>
    <span class="pl-s1">log_likelihood</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">sum</span>(<span class="pl-s1">y</span> <span class="pl-c1">*</span> <span class="pl-s1">np</span>.<span class="pl-en">log</span>(<span class="pl-s1">pred_probs</span>) <span class="pl-c1">+</span> (<span class="pl-c1">1</span> <span class="pl-c1">-</span> <span class="pl-s1">y</span>) <span class="pl-c1">*</span> <span class="pl-s1">np</span>.<span class="pl-en">log</span>(<span class="pl-c1">1</span> <span class="pl-c1">-</span> <span class="pl-s1">pred_probs</span>))

    <span class="pl-k">return</span> <span class="pl-s1">log_likelihood</span></pre></div>
<h3 dir="auto">For Null Log Likelihood -</h3>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import numpy as np
from sklearn.metrics import log_loss

def null_log_likelihood(y):
    &quot;&quot;&quot;Calculate the null log-likelihood of a binary logistic regression model.

    Parameters
    ----------
    y : array-like, shape (n_samples,)
        Binary class labels.

    Returns
    -------
    null_log_likelihood : float
        The null log-likelihood of the model.
    &quot;&quot;&quot;

    # Calculate the proportion of positive class labels
    p0 = y.mean()

    # Create an array of predicted probabilities equal to the proportion of positive class labels
    probs = p0 * np.ones_like(y)

    # Calculate the null log-likelihood using the log_loss function from scikit-learn
    null_log_likelihood = -log_loss(y, probs, normalize=False)

    return null_log_likelihood
"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">numpy</span> <span class="pl-k">as</span> <span class="pl-s1">np</span>
<span class="pl-k">from</span> <span class="pl-s1">sklearn</span>.<span class="pl-s1">metrics</span> <span class="pl-k">import</span> <span class="pl-s1">log_loss</span>

<span class="pl-k">def</span> <span class="pl-en">null_log_likelihood</span>(<span class="pl-s1">y</span>):
    <span class="pl-s">"""Calculate the null log-likelihood of a binary logistic regression model.</span>
<span class="pl-s"></span>
<span class="pl-s">    Parameters</span>
<span class="pl-s">    ----------</span>
<span class="pl-s">    y : array-like, shape (n_samples,)</span>
<span class="pl-s">        Binary class labels.</span>
<span class="pl-s"></span>
<span class="pl-s">    Returns</span>
<span class="pl-s">    -------</span>
<span class="pl-s">    null_log_likelihood : float</span>
<span class="pl-s">        The null log-likelihood of the model.</span>
<span class="pl-s">    """</span>

    <span class="pl-c"># Calculate the proportion of positive class labels</span>
    <span class="pl-s1">p0</span> <span class="pl-c1">=</span> <span class="pl-s1">y</span>.<span class="pl-en">mean</span>()

    <span class="pl-c"># Create an array of predicted probabilities equal to the proportion of positive class labels</span>
    <span class="pl-s1">probs</span> <span class="pl-c1">=</span> <span class="pl-s1">p0</span> <span class="pl-c1">*</span> <span class="pl-s1">np</span>.<span class="pl-en">ones_like</span>(<span class="pl-s1">y</span>)

    <span class="pl-c"># Calculate the null log-likelihood using the log_loss function from scikit-learn</span>
    <span class="pl-s1">null_log_likelihood</span> <span class="pl-c1">=</span> <span class="pl-c1">-</span><span class="pl-en">log_loss</span>(<span class="pl-s1">y</span>, <span class="pl-s1">probs</span>, <span class="pl-s1">normalize</span><span class="pl-c1">=</span><span class="pl-c1">False</span>)

    <span class="pl-k">return</span> <span class="pl-s1">null_log_likelihood</span></pre></div>
<h3 dir="auto">Describe alternatives you've considered, if relevant</h3>
<p dir="auto">One alternative to adding these functions to Scikit-learn would be for users to use  <a href="https://www.statsmodels.org/stable/about.html#about-statsmodels" rel="nofollow">statsmodels</a>.<br>
However, adding these functions to Scikit-learn would make it easier for users to calculate log-likelihood and null log-likelihood within the Scikit-learn ecosystem and would provide a standardized implementation.</p>
<h3 dir="auto">Additional context</h3>
<p dir="auto"><em>No response</em></p>
<h3 dir="auto">Describe the workflow you want to enable</h3>
<p dir="auto">I'd like to evaluate models by "percentage of reduction in metric X", where X is:</p>
<ul dir="auto">
<li>LogLoss</li>
<li>absolute error</li>
<li>pinball loss</li>
</ul>
<p dir="auto">As <code class="notranslate">d2_tweedie_score</code> <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="606786356" data-permission-text="Title is private" data-url="https://github.com/scikit-learn/scikit-learn/issues/17036" data-hovercard-type="pull_request" data-hovercard-url="/scikit-learn/scikit-learn/pull/17036/hovercard" href="https://github.com/scikit-learn/scikit-learn/pull/17036">#17036</a>, these are generalizations of the <code class="notranslate">r2_score</code>.</p>
<h3 dir="auto">Describe your proposed solution</h3>
<p dir="auto">Add</p>
<ul dir="auto">
<li><code class="notranslate">d2_log_loss_score</code></li>
<li><code class="notranslate">d2_absolute_error_score</code></li>
<li><code class="notranslate">d2_pinball_loss_score</code></li>
</ul>
<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">See <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="606786356" data-permission-text="Title is private" data-url="https://github.com/scikit-learn/scikit-learn/issues/17036" data-hovercard-type="pull_request" data-hovercard-url="/scikit-learn/scikit-learn/pull/17036/hovercard?comment_id=903939035&amp;comment_type=issue_comment" href="https://github.com/scikit-learn/scikit-learn/pull/17036#issuecomment-903939035">#17036 (comment)</a>.</p>