diff --git a/site/ko/beta/tutorials/estimators/linear.ipynb b/site/ko/beta/tutorials/estimators/linear.ipynb new file mode 100644 index 00000000000..8b80147a182 --- /dev/null +++ b/site/ko/beta/tutorials/estimators/linear.ipynb @@ -0,0 +1,679 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "linear.ipynb", + "version": "0.3.2", + "provenance": [], + "private_outputs": true, + "collapsed_sections": [], + "toc_visible": true + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.1" + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + } + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "OoasdhSAp0zJ" + }, + "source": [ + "##### Copyright 2019 The TensorFlow Authors." + ] + }, + { + "cell_type": "code", + "metadata": { + "cellView": "form", + "colab_type": "code", + "id": "cIrwotvGqsYh", + "colab": {} + }, + "source": [ + "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n", + "# you may not use this file except in compliance with the License.\n", + "# You may obtain a copy of the License at\n", + "#\n", + "# https://www.apache.org/licenses/LICENSE-2.0\n", + "#\n", + "# Unless required by applicable law or agreed to in writing, software\n", + "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", + "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", + "# See the License for the specific language governing permissions and\n", + "# limitations under the License.\n" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "C81KT2D_j-xR" + }, + "source": [ + "# 추정기(Estimator)로 선형 모델 만들기\n", + "\n", + "\n", + " \n", + " \n", + " \n", + "
\n", + " TensorFlow.org에서 보기\n", + " \n", + " 구글 코랩(Colab)에서 실행하기\n", + " \n", + " 깃허브(GitHub) 소스 보기\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "tUP8LMdYtWPz" + }, + "source": [ + "Note: 이 문서는 텐서플로 커뮤니티에서 번역했습니다. 커뮤니티 번역 활동의 특성상 정확한 번역과 최신 내용을 반영하기 위해 노력함에도 불구하고 [공식 영문 문서](https://github.com/tensorflow/docs/blob/master/site/en/r2/guide/using_gpu.ipynb)의 내용과 일치하지 않을 수 있습니다. 이 번역에 개선할 부분이 있다면 [tensorflow/docs](https://github.com/tensorflow/docs) 깃헙 저장소로 풀 리퀘스트를 보내주시기 바랍니다. 문서 번역이나 리뷰에 참여하려면 [docs-ko@tensorflow.org](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs-ko)로 메일을 보내주시기 바랍니다." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "nNgxmCgx8aAM" + }, + "source": [ + "## 개요\n", + "\n", + "이 문서에서는 `tf.estimator` API를 사용하여 로지스틱 회귀 모델(logistic regression model)을 훈련합니다. 이 모델은 다른 더 복잡한 알고리즘의 기초로 사용할 수 있습니다.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "vkC_j6VpqrDw" + }, + "source": [ + "## 설정" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "rutbJGmpqvm3", + "colab": {} + }, + "source": [ + "!pip install sklearn" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "54mb4J9PqqDh", + "colab": {} + }, + "source": [ + "from __future__ import absolute_import, division, print_function, unicode_literals\n", + "\n", + "import os\n", + "import sys\n", + "\n", + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from IPython.display import clear_output\n", + "from six.moves import urllib" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "fsjkwfsGOBMT" + }, + "source": [ + "## 타이타닉 데이터셋을 불러오기\n", + "타이타닉 데이터셋을 사용할 것입니다. 성별, 나이, 클래스, 기타 등 주어진 정보를 활용하여 승객이 살아남을 것인지 예측하는 것을 목표로 합니다." + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "bNiwh-APcRVD", + "colab": {} + }, + "source": [ + "!pip install tensorflow==2.0.0-beta1\n", + "import tensorflow.compat.v2.feature_column as fc\n", + "\n", + "import tensorflow as tf" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "DSeMKcx03d5R", + "colab": {} + }, + "source": [ + "# 데이터셋 불러오기.\n", + "dftrain = pd.read_csv('https://storage.googleapis.com/tf-datasets/titanic/train.csv')\n", + "dfeval = pd.read_csv('https://storage.googleapis.com/tf-datasets/titanic/eval.csv')\n", + "y_train = dftrain.pop('survived')\n", + "y_eval = dfeval.pop('survived')" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "jjm4Qj0u7_cp" + }, + "source": [ + "## 데이터 탐험하기" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "UrQzxKKh4d6u" + }, + "source": [ + "데이터셋은 다음의 특성을 가집니다" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "rTjugo3n308g", + "colab": {} + }, + "source": [ + "dftrain.head()" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "y86q1fj44lZs", + "colab": {} + }, + "source": [ + "dftrain.describe()" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "8JSa_duD4tFZ" + }, + "source": [ + "훈련셋은 627개의 샘플로 평가셋은 264개의 샘플로 구성되어 있습니다." + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "Fs3Nu5pV4v5J", + "colab": {} + }, + "source": [ + "dftrain.shape[0], dfeval.shape[0]" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "RxCA4Nr45AfF" + }, + "source": [ + "대부분의 승객은 20대와 30대 입니다." + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "RYeCMm7K40ZN", + "colab": {} + }, + "source": [ + "dftrain.age.hist(bins=20)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "DItSwJ_B5B0f" + }, + "source": [ + "남자 승객이 여자 승객보다 대략 2배 많습니다." + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "b03dVV9q5Dv2", + "colab": {} + }, + "source": [ + "dftrain.sex.value_counts().plot(kind='barh')" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "rK6WQ29q5Jf5" + }, + "source": [ + "대부분의 승객은 \"삼등석\" 입니다." + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "dgpJVeCq5Fgd", + "colab": {} + }, + "source": [ + "dftrain['class'].value_counts().plot(kind='barh')" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "FXJhGGL85TLp" + }, + "source": [ + "여자는 남자보다 살아남을 확률이 훨씬 높습니다. 이는 명확하게 모델에 유용한 특성입니다." + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "lSZYa7c45Ttt", + "colab": {} + }, + "source": [ + "pd.concat([dftrain, y_train], axis=1).groupby('sex').survived.mean().plot(kind='barh').set_xlabel('% survive')" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "VqDKQLZn8L-B" + }, + "source": [ + "## 모델을 위한 특성 공학(feature engineering)\n", + "추정기는 [특성 열(feature columns)](https://www.tensorflow.org/guide/feature_columns)이라는 시스템을 사용하여 모델이 각각의 입력 특성을 어떻게 해석할지 설명합니다. 추정기가 숫자 입력 벡터를 요구하면, *특성 열*은 모델이 어떻게 각 특성을 변환해야하는지 설명합니다.\n", + "\n", + "효과적인 모델 학습에서는 적절한 특성 열을 고르고 다듬는 것이 키포인트 입니다. 하나의 특성 열은 특성 딕셔너리(dict)의 원본 입력으로 만들어진 열(*기본 특성 열*)이거나 하나 이상의 기본 열(*얻어진 특성 열*)에 정의된 변환을 이용하여 새로 생성된 열입니다.\n", + "\n", + "선형 추정기는 수치형, 범주형 특성을 모두 사용할 수 있습니다. 특성 열은 모든 텐서플로 추정기와 함께 작동하고 목적은 모델링에 사용되는 특성들을 정의하는 것입니다. 또한 원-핫-인코딩(one-hot-encoding), 정규화(normalization), 버킷화(bucketization)와 같은 특성 공학 방법을 지원합니다." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "puZFOhTDkblt" + }, + "source": [ + "### 기본 특성 열" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "GpveXYSsADS6", + "colab": {} + }, + "source": [ + "CATEGORICAL_COLUMNS = ['sex', 'n_siblings_spouses', 'parch', 'class', 'deck',\n", + " 'embark_town', 'alone']\n", + "NUMERIC_COLUMNS = ['age', 'fare']\n", + "\n", + "feature_columns = []\n", + "for feature_name in CATEGORICAL_COLUMNS:\n", + " vocabulary = dftrain[feature_name].unique()\n", + " feature_columns.append(tf.feature_column.categorical_column_with_vocabulary_list(feature_name, vocabulary))\n", + "\n", + "for feature_name in NUMERIC_COLUMNS:\n", + " feature_columns.append(tf.feature_column.numeric_column(feature_name, dtype=tf.float32))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "Gt8HMtwOh9lJ" + }, + "source": [ + "`input_function`은 입력 파이프라인을 스트리밍으로 공급하는 `tf.data.Dataset`으로 데이터를 변환하는 방법을 명시합니다. `tf.data.Dataset`은 데이터 프레임, CSV 형식 파일 등과 같은 여러 소스를 사용합니다." + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "qVtrIHFnAe7w", + "colab": {} + }, + "source": [ + "def make_input_fn(data_df, label_df, num_epochs=10, shuffle=True, batch_size=32):\n", + " def input_function():\n", + " ds = tf.data.Dataset.from_tensor_slices((dict(data_df), label_df))\n", + " if shuffle:\n", + " ds = ds.shuffle(1000)\n", + " ds = ds.batch(batch_size).repeat(num_epochs)\n", + " return ds\n", + " return input_function\n", + "\n", + "train_input_fn = make_input_fn(dftrain, y_train)\n", + "eval_input_fn = make_input_fn(dfeval, y_eval, num_epochs=1, shuffle=False)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "P7UMVkQnkrgb" + }, + "source": [ + "다음과 같이 데이터셋을 점검할 수 있습니다:" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "8ZcG_3KiCb1M", + "colab": {} + }, + "source": [ + "ds = make_input_fn(dftrain, y_train, batch_size=10)()\n", + "for feature_batch, label_batch in ds.take(1):\n", + " print('특성 키:', list(feature_batch.keys()))\n", + " print()\n", + " print('클래스 배치:', feature_batch['class'].numpy())\n", + " print()\n", + " print('레이블 배치:', label_batch.numpy())" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "lMNBMyodjlW3" + }, + "source": [ + "또한 `tf.keras.layers.DenseFeatures` 층을 사용하여 특정한 특성 열의 결과를 점검할 수 있습니다:" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "IMjlmbPlDmkB", + "colab": {} + }, + "source": [ + "age_column = feature_columns[7]\n", + "tf.keras.layers.DenseFeatures([age_column])(feature_batch).numpy()" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "f4zrAdCIjr3s" + }, + "source": [ + "`DenseFeatures`는 조밀한(dense) 텐서만 허용합니다. 범주형 데이터를 점검하려면 우선 범주형 열에 indicator_column 함수를 적용해야 합니다:" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "1VXmXFTSFEvv", + "colab": {} + }, + "source": [ + "gender_column = feature_columns[0]\n", + "tf.keras.layers.DenseFeatures([tf.feature_column.indicator_column(gender_column)])(feature_batch).numpy()" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "MEp59g5UkHYY" + }, + "source": [ + "모든 기본 특성을 모델에 추가한 다음에 모델을 훈련해 봅시다. 모델을 훈련하려면 `tf.estimator` API를 이용한 메서드 호출 한번이면 충분합니다:" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "aGXjdnqqdgIs", + "colab": {} + }, + "source": [ + "linear_est = tf.estimator.LinearClassifier(feature_columns=feature_columns)\n", + "linear_est.train(train_input_fn)\n", + "result = linear_est.evaluate(eval_input_fn)\n", + "\n", + "clear_output()\n", + "print(result)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "3tOan4hDsG6d" + }, + "source": [ + "### 도출된 특성 열" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "NOG2FSTHlAMu" + }, + "source": [ + "이제 정확도 75%에 도달했습니다. 별도로 각 기본 특성 열을 사용하면 데이터를 설명하기에는 충분치 않을 수 있습니다. 예를 들면, 성별과 레이블간의 상관관계는 성별에 따라 다를 수 있습니다. 따라서 `gender=\"Male\"`과 'gender=\"Female\"`의 단일 모델가중치만 배우면 모든 나이-성별 조합(이를테면 `gender=\"Male\" 그리고 'age=\"30\"` 그리고 `gender=\"Male\"` 그리고 `age=\"40\"`을 구별하는 것)을 포함시킬 수 없습니다.\n", + "\n", + "서로 다른 특성 조합들 간의 차이를 학습하기 위해서 모델에 *교차 특성 열*을 추가할 수 있습니다(또한 교차 열 이전에 나이 열을 버킷화할 수 있습니다):" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "AM-RsDzNfGlu", + "colab": {} + }, + "source": [ + "age_x_gender = tf.feature_column.crossed_column(['age', 'sex'], hash_bucket_size=100)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "DqDFyPKQmGTN" + }, + "source": [ + "조합 특성을 모델에 추가하고 모델을 다시 훈련합니다:" + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "s8FV9oPQfS-g", + "colab": {} + }, + "source": [ + "derived_feature_columns = [age_x_gender]\n", + "linear_est = tf.estimator.LinearClassifier(feature_columns=feature_columns+derived_feature_columns)\n", + "linear_est.train(train_input_fn)\n", + "result = linear_est.evaluate(eval_input_fn)\n", + "\n", + "clear_output()\n", + "print(result)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "rwfdZj7ImLwb" + }, + "source": [ + "이제 정확도 77.6%에 도달했습니다. 기본 특성만 이용한 학습보다는 약간 더 좋았습니다. 더 많은 특성과 변환을 사용해서 더 잘할 수 있다는 것을 보여주세요!" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "8_eyb9d-ncjH" + }, + "source": [ + "이제 훈련 모델을 이용해서 평가셋에서 승객에 대해 예측을 할 수 있습니다. 텐서플로 모델은 한번에 샘플의 배치 또는 일부에 대한 예측을 하도록 최적화되어있습니다. 앞서, `eval_input_fn`은 모든 평가셋을 사용하도록 정의되어 있었습니다." + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "wiScyBcef6Dq", + "colab": {} + }, + "source": [ + "pred_dicts = list(linear_est.predict(eval_input_fn))\n", + "probs = pd.Series([pred['probabilities'][1] for pred in pred_dicts])\n", + "\n", + "probs.plot(kind='hist', bins=20, title='예측 확률')" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "UEHRCd4sqrLs" + }, + "source": [ + "마지막으로, 수신자 조작 특성(receiver operating characteristic, ROC)을 살펴보면 정탐률(true positive rate)과 오탐률(false positive rate)의 상충관계에 대해 더 잘 이해할 수 있습니다. " + ] + }, + { + "cell_type": "code", + "metadata": { + "colab_type": "code", + "id": "kqEjsezIokIe", + "colab": {} + }, + "source": [ + "from sklearn.metrics import roc_curve\n", + "from matplotlib import pyplot as plt\n", + "\n", + "fpr, tpr, _ = roc_curve(y_eval, probs)\n", + "plt.plot(fpr, tpr)\n", + "plt.title('ROC curve')\n", + "plt.xlabel('오탐률(false positive rate)')\n", + "plt.ylabel('정탐률(true positive rate)')\n", + "plt.xlim(0,)\n", + "plt.ylim(0,)" + ], + "execution_count": 0, + "outputs": [] + } + ] +} \ No newline at end of file