{ "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-04T01:32:53+00:00", "source_file": "2-Regression/1-Tools/solution/R/lesson_1-R.ipynb", "language_code": "ko" } }, "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/) 패키지의 함수입니다. Tidyverse의 일부인 dplyr은 데이터 조작을 위한 문법으로, 가장 일반적인 데이터 조작 문제를 해결하는 데 도움을 주는 일관된 동사 세트를 제공합니다.\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",
"이제 데이터를 준비했으니, 이 데이터 세트에서 숫자들을 논리적으로 분할하는 데 머신이 도움을 줄 수 있는지 확인해 봅시다. 이를 위해 Tidymodels 프레임워크의 일부인 [rsample](https://tidymodels.github.io/rsample/) 패키지를 사용할 수 있습니다. 이 패키지를 사용하면 데이터를 *어떻게* 분할할지에 대한 정보를 포함하는 객체를 생성할 수 있으며, 이후 두 개의 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",
"- 모델 **유형(type)**: 선형 회귀, 로지스틱 회귀, 결정 트리 모델 등과 같은 모델을 구분합니다.\n",
"\n",
"- 모델 **모드(mode)**: 회귀(regression)와 분류(classification)와 같은 일반적인 옵션을 포함하며, 일부 모델 유형은 둘 중 하나를 지원하거나 하나의 모드만 가질 수 있습니다.\n",
"\n",
"- 모델 **엔진(engine)**: 모델을 학습시키는 데 사용되는 계산 도구입니다. 종종 **`\"lm\"`** 또는 **`\"ranger\"`**와 같은 R 패키지가 사용됩니다.\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",
"이제 모델을 훈련했으니, 이를 사용하여 테스트 데이터셋의 질병 진행 y를 [parsnip::predict()](https://parsnip.tidymodels.org/reference/predict.model_fit.html)를 통해 예측할 수 있습니다. 이는 데이터 그룹 간의 선을 그리는 데 사용됩니다.\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"
]
}
]
}