> For the complete documentation index, see [llms.txt](https://docs.crunchdao.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.crunchdao.com/zh/competitions/competitions/broad-obesity/crunch-1.md).

# Crunch 1 — 预测保留单基因扰动的效应

预测单细胞对未见单基因扰动的转录组响应。

## 评估阶段 <a href="#evaluation-phases" id="evaluation-phases"></a>

在 Crunch 1 中，你将有机会在验证数据集上评估模型的预测性能。

验证检查点：

* 每周一 UTC 18:00 进行一次验证检查点
  * 检查点 1：12月22日
  * 检查点 n：每周一
  * 最后检查点：2月23日
* 最终提交截止日期：2月28日

{% hint style="info" %}
你仍然可以多次提交并运行代码到平台上。

在每个检查点，你的所有（未评分）预测结果将被评分。
{% endhint %}

## 概述 <a href="#overview" id="overview"></a>

在 Crunch 1 中，我们将探索如何准确预测训练数据集中未测量和提供的单基因扰动的单细胞转录组响应。

## 数据集 <a href="#dataset" id="dataset"></a>

该数据集包含针对157个基因的扰动，其中150个是转录因子（TFs）。对于每种扰动，我们提供在脂肪细胞分化第14天测量的单细胞基因表达（RNA-seq）数据，并附有基因扰动身份、质量控制（QC）指标和细胞元数据。训练数据集包含这些扰动的一个子集，而另一组独立的单基因扰动被保留用于验证和测试。

布局如下：

* 数据集以 [AnnData 格式（.h5ad）](https://anndata.readthedocs.io/en/stable/)提供，文件名为 `obesity_challenge_1.h5ad`。
* 标准化后的基因表达值存储在 `adata.X` 中。原始计数经过每个细胞目标总和归一化到100,000，并进行了 $$log\_2(1+x)$$ 转换（标准单细胞RNA-seq归一化流程；[详见速成课程的第二讲](https://docs.crunchdao.com/~/changes/206/competitions/competitions/broad-obesity/crash-course#lecture-2)）。
* 归一化前的原始基因表达计数存储在 `adata.layers['counts']` 中，以便重现和替代预处理。
* **扰动目标基因信息**存储在 `adata.obs['gene']` 中，其值为“NC”表示对照细胞，或对应的目标基因名称（如果细胞被扰动）。对照细胞接受的扰动不会影响其RNA-Seq表达谱。
* 细胞状态/程序富集信息存储在 `.obs` 中，列包括 `pre_adipo`、`adipo`、`lipo` 和 `other`，分别表示每个细胞是否富集前脂肪细胞、脂肪细胞或脂质生成程序。other 指未富集前脂肪细胞或脂肪细胞程序的细胞。程序富集分配基于专家策划的标准签名基因，签名基因列表提供在 `signature_genes.csv` 中。
  * 用于确定程序富集的完整分析流程在随附的 [R 笔记本中提供](https://github.com/julielaffy/obesity-broad-ml-competition-2025?tab=readme-ov-file)，可查阅更多方法细节。
  * 每种扰动的细胞状态比例在单独的文件 `program_proportion.csv` 中提供。
* 在预处理过程中，应用了标准的单细胞质量控制（QC）方法，基于测序文库复杂度、基因检测率和线粒体基因含量，去除了低质量细胞和细胞双连体。数据集随后限定为具有单一高置信度引导分配到扰动的细胞，并且代表细胞数少于10个的引导被排除。检测到的基因少于10个细胞的基因被移除，`signature_genes.csv` 中的已知签名基因随后被重新引入。

`.obs` 列的定义如下：

* `orig.ident`：原始样本 ID。
* `nCount_RNA`：每个细胞检测到的 UMIs 数量。
* `nFeature_RNA`：每个细胞检测到的基因数量。
* `nCount_guide`：每个细胞检测到的 sgRNA UMIs 数量。
* `nFeature_guide`：每个细胞检测到的 sgRNA 数量。
* `percent.mt`：每个细胞中映射到线粒体转录本的 UMIs 比例。
* `SampleID`：样本 ID。
* `Day`：样本采集的天数。
* `num_features`：每个细胞的引导数量（对于低 MOI 数据，经过 QC 后，仅保留含 1 个引导的细胞）。
* `feature_call`：每个细胞的引导分配。
* `num_umis`：每个细胞的引导 UMIs 数量。
* `gene`：扰动目标基因（或扰动身份）。
* `positive_control`：扰动是否为阳性对照之一。

## 预期输出 <a href="#expected-output" id="expected-output"></a>

参与者需要提交三个输出：

### 文件：`prediction.h5ad` <a href="#file-prediction.h5ad" id="file-prediction.h5ad"></a>

个 [AnnData](https://anndata.readthedocs.io/en/stable/) 文件，包含 [`predict_perturbations.txt`](#user-content-fn-1)[^1] 中指定的 2,863 个基因扰动的预测基因表达谱，需经过归一化和 log 转换后的结果。

预测结果应存储在 `adata.X` 矩阵中，对应的扰动身份记录在 `adata.obs['gene']` 中。

预测中包含的基因集（列）由推理时提供的 `genes_to_predict` 明确定义，`adata.X` 的列必须按照此顺序排列。

请注意，`genes_to_predict` 列表在验证阶段（N=10,237）和测试阶段可能会变化，您的模型必须为提供的任何基因集生成预测结果。`genes_to_predict` 中可能包含的最大基因数量为 21,592，对应于数据集中的总基因数。

对于每个基因扰动，我们要求您预测 100 个细胞的基因表达谱，以量化每个扰动预测的分布。因此，最终预测文件的维度应为 \[286,300 × N]（细胞 × genes\_to\_predict）。

### 文件：`predict_program_proportion.csv` <a href="#file-predict_program_proportion.csv" id="file-predict_program_proportion.csv"></a>

一个 [CSV](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_csv.html) 文件，报告 `predict_perturbations.txt` 中列出的每个基因扰动的富集程序细胞比例的预测值。

该文件应包含每个扰动一行，列定义如下：

* `gene`：扰动名称，
* `pre_adipo`、`adipo`、`lipo`、`other`：预测的细胞在各对应状态下的比例，
* `lipo_adipo`：脂质生成程序富集的脂肪细胞与脂肪细胞的比例（lipo/adipo）。

文件应包含 2,863 行 和 [6 列](#user-content-fn-2)[^2]。示例文件可在 `data/` 目录中找到。

### 文件：`Method description.md` <a href="#file-method-description.md" id="file-method-description.md"></a>

请撰写一份简短文档，概述生成预测结果及各程序富集细胞比例估计所使用的方法。文档需包含以下内容：

* **方法描述（Method Description）**：说明您的方法如何工作。（5-10句话）
* **理论依据（Rationale）**：阐述模型背后的设计理念。（5-10句话）
* **使用的数据和资源（Data and Resources Used）**：列出使用的数据集及其他资源。（5-10句话）

文档应以 Markdown 格式组织，并使用上述标题作为一级标题。

**注意事项：**

* 比赛结束时，人工将审核文档内容，不合格的作品可能被取消资格。
* 提交时必须提供此文件，如需修改内容，必须重新提交更新版本。
* 文件名必须为 `Method Description.md`（大小写不敏感）。
* 仅计算非空行和非注释行。

以下是 `Method Description.md` 的示例内容，您可以参考此格式和结构编写您的文档：

{% code expandable="true" %}

```markdown
# Method Description

<!-- 解释您的方法如何工作。（5-10句话） -->
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam eget augue quis metus viverra vehicula sit amet lacinia odio.

# Rationale

<!-- 阐述您的基因面板设计背后的理由。（5-10句话） -->
Praesent dignissim ipsum vel leo eleifend, eget pulvinar mauris ornare.
Duis efficitur lectus posuere iaculis dictum.

# Data and Resources Used

<!-- 指定使用的数据集和其他资源。（5-10句话） -->
Donec feugiat eros vel odio gravida venenatis.
Nam et sem sit amet nisi vestibulum semper bibendum et libero.
```

{% endcode %}

{% hint style="info" %}
如果格式存在明显问题，您将立即收到通知。

[Notebook 用户必须使用嵌入文件。](https://docs.crunchdao.com/~/changes/206/competitions/participate/notebook-processor#embed-files)
{% endhint %}

## 评分 <a href="#scoring" id="scoring"></a>

每个指标将在不同的排行榜中显示，每个排行榜将有不同的排名和获奖机会。

这些指标分为两类：

* 转录组范围的指标，将使用每个扰动的预测矩阵中的部分基因（即预测矩阵的列）进行计算。
  * 评分指标包括：
    * 预测扰动效应与观测扰动效应相对于扰动均值的皮尔**逊 Delta**。
    * 预测单细胞表达谱分布与观测分布之间的最大均**值差异（MMD）**。
  * **公开排行榜 / 验证阶段（每周更新）**：评估使用 1,000 个隐藏基因。
  * **私密排行榜 / 测试阶段**：评分基因的数量和身份将保持未知。
* 程序层面的指标，用于评估模型是否捕捉到有意义的生物学结果：
  * 每个扰动的预测细胞状态比例（即前脂肪细胞、脂肪生成、脂质生成和其他状态）与观测比例之间的 **L1 距离**。

{% hint style="info" %}
评分代码已在 [GitHub](https://github.com/crunchdao/competitions/blob/master/competitions/broad-obesity-1/scoring/scoring.py) 上开源。

本地评分代码可在 [quickstarter](https://colab.research.google.com/github/crunchdao/quickstarters/blob/master/competitions/broad-obesity-1/quickstarters/perturbed-mean-baseline/perturbed-mean-baseline.ipynb) 中获取。

有关评分指标公式的详细信息，请查阅 完[整规范说明（Full Specifications）](https://docs.crunchdao.com/~/changes/206/competitions/competitions/broad-obesity/full-specifications)。
{% endhint %}

## 提交 <a href="#submit" id="submit"></a>

要构建有效的提交，您的模型需要在 **infer 函数** 中编码，并严格遵循 **crunch 代码提交接口** 的要求。

{% code title="Python Notebook 单元格" %}

```python
def train(
    data_directory_path: str,
    model_directory_path: str,
) -> None:
    """
    训练一个扰动预测模型。

    参数:
      data_directory_path: 数据所在的目录路径。
      model_directory_path: 应保存模型状态的目录路径（通常命名为 `resources/`）。

    返回:
      None: 返回值将被忽略。
    """
```

{% endcode %}

{% hint style="warning" %}
我们建议在本地训练并提交模型权重，因为数据集较大且云资源有限。

请确保 [`Method Description.md`](https://docs.crunchdao.com/~/changes/206/competitions/competitions/broad-obesity/crunch-1#file-method-description.md) 文件详细记录您的模型，以便 Eric 和 Wendy Schmidt Center 团队能在其出版物中引用您的工作。
{% endhint %}

{% code title="Python Notebook 单元格" %}

```python
def infer(
    data_directory_path: str,
    prediction_directory_path: str,
    prediction_h5ad_file_path: str,
    program_proportion_csv_file_path: str,
    model_directory_path: str,
    predict_perturbations: list[str],
    genes_to_predict: list[str],
):
    """
    对一组扰动运行推理。

    参数:
      data_directory_path: 训练 AnnData 文件的路径。
      prediction_directory_path: 可写入预测文件的目录路径。
      prediction_h5ad_file_path: 写入 `prediction.h5ad` 文件的直接路径。
      program_proportion_csv_file_path: 写入 `predict_program_proportion.csv` 文件的直接路径。
      model_directory_path: 包含已保存模型文件的目录路径。
      predict_perturbations: 需要生成预测的扰动列表。
      genes_to_predict: 需要包含在 `prediction.h5ad` AnnData 对象中的基因名称列表（列）。

    返回:
      None: 返回值将被忽略。

    预期生成的文件:
      prediction_directory_path / "prediction.h5ad": anndata.AnnData
            大小为 (n_perturbations * cells_per_perturbation, n_genes_to_predict) 的 AnnData 矩阵，包含预测的基因表达值。
      prediction_directory_path / "predict_program_proportion.csv": pd.DataFrame
            包含每个扰动的估计细胞类型比例的 DataFrame（index=False）。
    """
```

{% endcode %}

{% hint style="info" %}
**示例可在** [**quickstarter**](https://colab.research.google.com/github/crunchdao/quickstarters/blob/master/competitions/broad-obesity-1/quickstarters/perturbed-mean-baseline/perturbed-mean-baseline.ipynb) **中查看。**
{% endhint %}

## 常见问题（FAQ） <a href="#faq" id="faq"></a>

<details>

<summary>我错过了一个检查点，还能参加下一个吗？</summary>

是的。

每周一都有检查点，错过一个不会影响您的最终排名。模型准备好后，随时提交即可！

</details>

<details>

<summary>为什么外部资源必须是已发表或公共领域的？</summary>

虽然鼓励发布完整模型，但如果模型权重足以实现可重复性，则不是严格要求。

当限制条件影响发布内容时，我们要求清楚记录方法和训练流程。这些情况可逐个审核，以确保透明度和公平性。

</details>

[^1]: 文件位于 `data/` 目录中。

[^2]: 保存文件时请使用 `.to_csv(index=False)`。
