{ "nbformat": 4, "nbformat_minor": 2, "metadata": { "colab": { "name": "lesson_1-R.ipynb", "provenance": [], "collapsed_sections": [], "toc_visible": true }, "kernelspec": { "name": "ir", "display_name": "R" }, "language_info": { "name": "R" }, "coopTranslator": { "original_hash": "c18d3bd0bd8ae3878597e89dcd1fa5c1", "translation_date": "2025-09-03T19:43:03+00:00", "source_file": "2-Regression/1-Tools/solution/R/lesson_1-R.ipynb", "language_code": "zh" } }, "cells": [ { "cell_type": "markdown", "source": [], "metadata": { "id": "YJUHCXqK57yz" } }, { "cell_type": "markdown", "source": [ "## 回归简介 - 第1课\n", "\n", "#### 放到实际情境中\n", "\n", "✅ 回归方法有很多种,选择哪一种取决于你想要得到的答案。如果你想预测某个年龄段的人可能的身高,你会使用 `线性回归`,因为你在寻找一个**数值结果**。如果你想知道某种菜肴是否应该被归类为素食,你是在寻找一个**类别分配**,因此你会使用 `逻辑回归`。稍后你会学习更多关于逻辑回归的内容。试着思考一些你可以从数据中提出的问题,以及哪种方法更适合这些问题。\n", "\n", "在本节中,你将使用一个[关于糖尿病的小型数据集](https://www4.stat.ncsu.edu/~boos/var.select/diabetes.html)。假设你想测试一种针对糖尿病患者的治疗方法。机器学习模型可能会帮助你根据变量的组合确定哪些患者对治疗的反应更好。即使是一个非常基础的回归模型,在可视化时也可能显示出一些关于变量的信息,这些信息可以帮助你组织理论上的临床试验。\n", "\n", "话不多说,让我们开始这项任务吧!\n", "\n", "
\n",
" \n",
"
\n",
"\n",
"> `glimpse()` 和 `slice()` 是 [`dplyr`](https://dplyr.tidyverse.org/) 包中的函数。Dplyr 是 Tidyverse 的一部分,它是一种数据操作的语法,提供了一组一致的动词,帮助解决最常见的数据处理问题。\n",
"\n",
"
\n",
"\n",
"现在我们已经有了数据,接下来让我们聚焦于一个特征(`bmi`),作为本次练习的目标。为此,我们需要选择所需的列。那么,我们该如何操作呢?\n",
"\n",
"[`dplyr::select()`](https://dplyr.tidyverse.org/reference/select.html) 函数允许我们在数据框中*选择*(并可选地重命名)列。\n"
],
"metadata": {
"id": "UwjVT1Hz-c3Z"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Select predictor feature `bmi` and outcome `y`\r\n",
"diabetes_select <- diabetes %>% \r\n",
" select(c(bmi, y))\r\n",
"\r\n",
"# Print the first 5 rows\r\n",
"diabetes_select %>% \r\n",
" slice(1:10)"
],
"outputs": [],
"metadata": {
"id": "RDY1oAKI-m80"
}
},
{
"cell_type": "markdown",
"source": [
"## 3. 训练和测试数据\n",
"\n",
"在监督学习中,通常的做法是将数据*分割*成两个子集:一个(通常较大的)用于训练模型的集合,以及一个较小的“保留”集合,用于查看模型的表现如何。\n",
"\n",
"现在我们已经准备好了数据,可以看看机器是否能够帮助我们在这个数据集中找到一个合理的分割方式。我们可以使用 [rsample](https://tidymodels.github.io/rsample/) 包,它是 Tidymodels 框架的一部分,用来创建一个包含数据分割信息的对象,然后使用另外两个 rsample 函数提取生成的训练集和测试集:\n"
],
"metadata": {
"id": "SDk668xK-tc3"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"set.seed(2056)\r\n",
"# Split 67% of the data for training and the rest for tesing\r\n",
"diabetes_split <- diabetes_select %>% \r\n",
" initial_split(prop = 0.67)\r\n",
"\r\n",
"# Extract the resulting train and test sets\r\n",
"diabetes_train <- training(diabetes_split)\r\n",
"diabetes_test <- testing(diabetes_split)\r\n",
"\r\n",
"# Print the first 3 rows of the training set\r\n",
"diabetes_train %>% \r\n",
" slice(1:10)"
],
"outputs": [],
"metadata": {
"id": "EqtHx129-1h-"
}
},
{
"cell_type": "markdown",
"source": [
"## 4. 使用Tidymodels训练线性回归模型\n",
"\n",
"现在我们可以开始训练模型了!\n",
"\n",
"在Tidymodels中,你可以通过`parsnip()`指定模型,主要涉及以下三个概念:\n",
"\n",
"- 模型**类型**区分了不同的模型,例如线性回归、逻辑回归、决策树模型等。\n",
"\n",
"- 模型**模式**包括常见选项如回归和分类;某些模型类型支持这两种模式,而有些仅支持其中一种。\n",
"\n",
"- 模型**引擎**是用于拟合模型的计算工具。通常这些是R包,例如 **`\"lm\"`** 或 **`\"ranger\"`**。\n",
"\n",
"这些建模信息会被捕获到一个模型规范中,所以让我们来构建一个吧!\n"
],
"metadata": {
"id": "sBOS-XhB-6v7"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Build a linear model specification\r\n",
"lm_spec <- \r\n",
" # Type\r\n",
" linear_reg() %>% \r\n",
" # Engine\r\n",
" set_engine(\"lm\") %>% \r\n",
" # Mode\r\n",
" set_mode(\"regression\")\r\n",
"\r\n",
"\r\n",
"# Print the model specification\r\n",
"lm_spec"
],
"outputs": [],
"metadata": {
"id": "20OwEw20--t3"
}
},
{
"cell_type": "markdown",
"source": [
"在模型被*指定*之后,可以使用 [`fit()`](https://parsnip.tidymodels.org/reference/fit.html) 函数对模型进行`估计`或`训练`,通常使用公式和一些数据。\n",
"\n",
"`y ~ .` 表示我们将拟合 `y` 作为预测值/目标,由所有预测变量/特征解释,即 `.`(在这个例子中,我们只有一个预测变量:`bmi`)。\n"
],
"metadata": {
"id": "_oDHs89k_CJj"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Build a linear model specification\r\n",
"lm_spec <- linear_reg() %>% \r\n",
" set_engine(\"lm\") %>%\r\n",
" set_mode(\"regression\")\r\n",
"\r\n",
"\r\n",
"# Train a linear regression model\r\n",
"lm_mod <- lm_spec %>% \r\n",
" fit(y ~ ., data = diabetes_train)\r\n",
"\r\n",
"# Print the model\r\n",
"lm_mod"
],
"outputs": [],
"metadata": {
"id": "YlsHqd-q_GJQ"
}
},
{
"cell_type": "markdown",
"source": [
"从模型输出中,我们可以看到训练过程中学习到的系数。它们表示最佳拟合线的系数,该线使实际变量与预测变量之间的总体误差最小。\n",
"
\n",
"\n",
"## 5. 在测试集上进行预测\n",
"\n",
"现在我们已经训练了一个模型,可以使用它通过 [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html) 来预测测试数据集中的疾病进展 y。这将用于绘制数据组之间的分界线。\n"
],
"metadata": {
"id": "kGZ22RQj_Olu"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Make predictions for the test set\r\n",
"predictions <- lm_mod %>% \r\n",
" predict(new_data = diabetes_test)\r\n",
"\r\n",
"# Print out some of the predictions\r\n",
"predictions %>% \r\n",
" slice(1:5)"
],
"outputs": [],
"metadata": {
"id": "nXHbY7M2_aao"
}
},
{
"cell_type": "markdown",
"source": [
"哇哦!💃🕺 我们刚刚训练了一个模型,并用它进行了预测!\n",
"\n",
"在进行预测时,tidymodels 的惯例是始终生成一个带有标准化列名的 tibble/数据框结果。这使得将原始数据和预测结果结合在一个可用的格式中变得非常简单,方便后续操作,例如绘图。\n",
"\n",
"`dplyr::bind_cols()` 可以高效地将多个数据框按列绑定在一起。\n"
],
"metadata": {
"id": "R_JstwUY_bIs"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Combine the predictions and the original test set\r\n",
"results <- diabetes_test %>% \r\n",
" bind_cols(predictions)\r\n",
"\r\n",
"\r\n",
"results %>% \r\n",
" slice(1:5)"
],
"outputs": [],
"metadata": {
"id": "RybsMJR7_iI8"
}
},
{
"cell_type": "markdown",
"source": [
"## 6. 绘制模型结果\n",
"\n",
"现在是时候用视觉化方式来看结果了 📈。我们将创建一个散点图,展示测试集中的所有 `y` 和 `bmi` 值,然后使用预测结果绘制一条线,将模型的数据分组之间连接起来,放在最合适的位置。\n",
"\n",
"R 有多种绘图系统,但 `ggplot2` 是其中最优雅且最灵活的一个。它允许你通过**组合独立组件**来构建图表。\n"
],
"metadata": {
"id": "XJbYbMZW_n_s"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"# Set a theme for the plot\r\n",
"theme_set(theme_light())\r\n",
"# Create a scatter plot\r\n",
"results %>% \r\n",
" ggplot(aes(x = bmi)) +\r\n",
" # Add a scatter plot\r\n",
" geom_point(aes(y = y), size = 1.6) +\r\n",
" # Add a line plot\r\n",
" geom_line(aes(y = .pred), color = \"blue\", size = 1.5)"
],
"outputs": [],
"metadata": {
"id": "R9tYp3VW_sTn"
}
},
{
"cell_type": "markdown",
"source": [
"✅ 想一想这里发生了什么。一条直线穿过了许多小数据点,但它究竟在做什么呢?你能看出如何利用这条直线来预测一个新的、未见过的数据点应该如何与图表的 y 轴相关联吗?试着用语言描述这个模型的实际用途。\n",
"\n",
"恭喜你!你已经构建了第一个线性回归模型,用它进行了预测,并在图表中展示了结果!\n"
],
"metadata": {
"id": "zrPtHIxx_tNI"
}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**免责声明**: \n本文档使用AI翻译服务[Co-op Translator](https://github.com/Azure/co-op-translator)进行翻译。尽管我们努力确保翻译的准确性,但请注意,自动翻译可能包含错误或不准确之处。原始语言的文档应被视为权威来源。对于关键信息,建议使用专业人工翻译。我们不对因使用此翻译而产生的任何误解或误读承担责任。\n"
]
}
]
}