{
  "id": 664008,
  "title": "** R^2 Calculation Methods in Open Source Solutions**",
  "url": "/competitions/csiro-biomass/discussion/664008",
  "author_name": "x_sj",
  "post_date": "2025-12-22T04:25:25.606000",
  "votes": 3,
  "comment_count": 0,
  "views": 0,
  "content": "<p><em>(Corrections and friendly discussion are welcome if there are any errors 😊)</em></p>\n<p>I noticed that some notebooks in open-source solutions use the following method to calculate R^2:</p>\n<pre><code>def weighted_r2_score(y_true: np.ndarray, y_pred: np.ndarray, weights=None):\n    \"\"\"Calculate weighted R² score - y_true, y_pred: shape (N, 5)\"\"\"\n    if weights is None:\n        weights = CFG.TARGET_WEIGHTS\n\n    r2_scores = []\n    for i in range(5):\n        y_t = y_true[:, i]\n        y_p = y_pred[:, i]\n        ss_res = np.sum((y_t - y_p) ** 2)\n        ss_tot = np.sum((y_t - np.mean(y_t)) ** 2)\n        r2 = 1 - ss_res / ss_tot if ss_tot &gt; 0 else 0.0\n        r2_scores.append(r2)\n\n    r2_scores = np.array(r2_scores)\n    weighted_r2 = np.sum(r2_scores * weights) / np.sum(weights)\n    return weighted_r2, r2_scores\n</code></pre>\n<p>This is equivalent to calculating the R^2 for each of the five targets independently and then taking their weighted average.</p>\n<p>However, the official formula requires calculating the weighted average of the global true labels first before applying it to the formula. Therefore, the calculation formula in the code below aligns more closely with the official calculation method:</p>\n<pre><code>def weighted_r2_score(y_true: np.ndarray, y_pred: np.ndarray):\n    weights = np.array(cfg.loss_weight[:5])\n    # First, calculate the global y_hat_w\n    y_hat_w = weights * np.mean(y_true, axis=0)\n\n    ss_res = 0\n    ss_tot = 0\n    for i in range(5):\n        ss_res += weights[i] * ((y_true[:, i] - y_pred[:, i]) ** 2).mean()\n        ss_tot += weights[i] * ((y_true[:, i] - y_hat_w) ** 2).mean() \n    # If aiming for a mathematically perfect match, change 'mean' here to 'sum'\n\n    weighted_r2 = 1 - ss_res / ss_tot\n\n    return weighted_r2\n</code></pre>",
  "messages": [
    {
      "id": 3380257,
      "postDate": "2025-12-22T04:25:25.607Z",
      "content": "<p><em>(Corrections and friendly discussion are welcome if there are any errors 😊)</em></p>\n<p>I noticed that some notebooks in open-source solutions use the following method to calculate R^2:</p>\n<pre><code>def weighted_r2_score(y_true: np.ndarray, y_pred: np.ndarray, weights=None):\n    \"\"\"Calculate weighted R² score - y_true, y_pred: shape (N, 5)\"\"\"\n    if weights is None:\n        weights = CFG.TARGET_WEIGHTS\n\n    r2_scores = []\n    for i in range(5):\n        y_t = y_true[:, i]\n        y_p = y_pred[:, i]\n        ss_res = np.sum((y_t - y_p) ** 2)\n        ss_tot = np.sum((y_t - np.mean(y_t)) ** 2)\n        r2 = 1 - ss_res / ss_tot if ss_tot &gt; 0 else 0.0\n        r2_scores.append(r2)\n\n    r2_scores = np.array(r2_scores)\n    weighted_r2 = np.sum(r2_scores * weights) / np.sum(weights)\n    return weighted_r2, r2_scores\n</code></pre>\n<p>This is equivalent to calculating the R^2 for each of the five targets independently and then taking their weighted average.</p>\n<p>However, the official formula requires calculating the weighted average of the global true labels first before applying it to the formula. Therefore, the calculation formula in the code below aligns more closely with the official calculation method:</p>\n<pre><code>def weighted_r2_score(y_true: np.ndarray, y_pred: np.ndarray):\n    weights = np.array(cfg.loss_weight[:5])\n    # First, calculate the global y_hat_w\n    y_hat_w = weights * np.mean(y_true, axis=0)\n\n    ss_res = 0\n    ss_tot = 0\n    for i in range(5):\n        ss_res += weights[i] * ((y_true[:, i] - y_pred[:, i]) ** 2).mean()\n        ss_tot += weights[i] * ((y_true[:, i] - y_hat_w) ** 2).mean() \n    # If aiming for a mathematically perfect match, change 'mean' here to 'sum'\n\n    weighted_r2 = 1 - ss_res / ss_tot\n\n    return weighted_r2\n</code></pre>",
      "rawMarkdown": "*(Corrections and friendly discussion are welcome if there are any errors 😊)*\n\nI noticed that some notebooks in open-source solutions use the following method to calculate R^2:\n\n```python\ndef weighted_r2_score(y_true: np.ndarray, y_pred: np.ndarray, weights=None):\n    \"\"\"Calculate weighted R² score - y_true, y_pred: shape (N, 5)\"\"\"\n    if weights is None:\n        weights = CFG.TARGET_WEIGHTS\n\n    r2_scores = []\n    for i in range(5):\n        y_t = y_true[:, i]\n        y_p = y_pred[:, i]\n        ss_res = np.sum((y_t - y_p) ** 2)\n        ss_tot = np.sum((y_t - np.mean(y_t)) ** 2)\n        r2 = 1 - ss_res / ss_tot if ss_tot > 0 else 0.0\n        r2_scores.append(r2)\n\n    r2_scores = np.array(r2_scores)\n    weighted_r2 = np.sum(r2_scores * weights) / np.sum(weights)\n    return weighted_r2, r2_scores\n```\n\nThis is equivalent to calculating the R^2 for each of the five targets independently and then taking their weighted average.\n\nHowever, the official formula requires calculating the weighted average of the global true labels first before applying it to the formula. Therefore, the calculation formula in the code below aligns more closely with the official calculation method:\n\n```python\ndef weighted_r2_score(y_true: np.ndarray, y_pred: np.ndarray):\n    weights = np.array(cfg.loss_weight[:5])\n    # First, calculate the global y_hat_w\n    y_hat_w = weights * np.mean(y_true, axis=0)\n\n    ss_res = 0\n    ss_tot = 0\n    for i in range(5):\n        ss_res += weights[i] * ((y_true[:, i] - y_pred[:, i]) ** 2).mean()\n        ss_tot += weights[i] * ((y_true[:, i] - y_hat_w) ** 2).mean() \n    # If aiming for a mathematically perfect match, change 'mean' here to 'sum'\n\n    weighted_r2 = 1 - ss_res / ss_tot\n\n    return weighted_r2\n```",
      "votes": 3
    }
  ],
  "comments": [],
  "raw_markdown_by_id": {
    "3380257": "*(Corrections and friendly discussion are welcome if there are any errors 😊)*\n\nI noticed that some notebooks in open-source solutions use the following method to calculate R^2:\n\n```python\ndef weighted_r2_score(y_true: np.ndarray, y_pred: np.ndarray, weights=None):\n    \"\"\"Calculate weighted R² score - y_true, y_pred: shape (N, 5)\"\"\"\n    if weights is None:\n        weights = CFG.TARGET_WEIGHTS\n\n    r2_scores = []\n    for i in range(5):\n        y_t = y_true[:, i]\n        y_p = y_pred[:, i]\n        ss_res = np.sum((y_t - y_p) ** 2)\n        ss_tot = np.sum((y_t - np.mean(y_t)) ** 2)\n        r2 = 1 - ss_res / ss_tot if ss_tot > 0 else 0.0\n        r2_scores.append(r2)\n\n    r2_scores = np.array(r2_scores)\n    weighted_r2 = np.sum(r2_scores * weights) / np.sum(weights)\n    return weighted_r2, r2_scores\n```\n\nThis is equivalent to calculating the R^2 for each of the five targets independently and then taking their weighted average.\n\nHowever, the official formula requires calculating the weighted average of the global true labels first before applying it to the formula. Therefore, the calculation formula in the code below aligns more closely with the official calculation method:\n\n```python\ndef weighted_r2_score(y_true: np.ndarray, y_pred: np.ndarray):\n    weights = np.array(cfg.loss_weight[:5])\n    # First, calculate the global y_hat_w\n    y_hat_w = weights * np.mean(y_true, axis=0)\n\n    ss_res = 0\n    ss_tot = 0\n    for i in range(5):\n        ss_res += weights[i] * ((y_true[:, i] - y_pred[:, i]) ** 2).mean()\n        ss_tot += weights[i] * ((y_true[:, i] - y_hat_w) ** 2).mean() \n    # If aiming for a mathematically perfect match, change 'mean' here to 'sum'\n\n    weighted_r2 = 1 - ss_res / ss_tot\n\n    return weighted_r2\n```"
  }
}