<commit_before>{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "OoasdhSAp0zJ"
   },
   "source": [
    "##### Copyright 2019 The TensorFlow Authors."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "cellView": "form",
    "colab": {},
    "colab_type": "code",
    "id": "cIrwotvGqsYh"
   },
   "outputs": [],
   "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"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "C81KT2D_j-xR"
   },
   "source": [
    "# 추정기(Estimator)로 선형 모델 만들기\n",
    "\n",
    "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://www.tensorflow.org/beta/guide/using_gpu\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />TensorFlow.org에서 보기</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs/blob/master/site/ko/beta/tutorials/estimators/linear.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />구글 코랩(Colab)에서 실행하기</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs/blob/master/site/ko/beta/tutorials/estimators/linear.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />깃허브(GitHub) 소스 보기</a>\n",
    "  </td>\n",
    "</table>"
   ]
  },
  {
   "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) 깃헙 저장소로 풀 리퀘스트를 보내주시기 바랍니다. 문서 번역이나 리뷰에 참여하려면 [<EMAIL>](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs-ko)로 메일을 보내주시기 바랍니다."
    ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "tUP8LMdYtWPz"
   },
   "source": [
    "## 개요\n",
    "\n",
    "이 문서에서는 `tf.estimator` API를 사용하여 로지스틱 회귀 모델(logistic regression model)을 훈련합니다. 이 모델은 다른 더 복잡한 알고리즘의 기초로 사용할 수 있습니다.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "vkC_j6VpqrDw"
   },
   "source": [
    "## 설정"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "rutbJGmpqvm3"
   },
   "outputs": [],
   "source": [
    "!pip install sklearn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "54mb4J9PqqDh"
   },
   "outputs": [],
   "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"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "fsjkwfsGOBMT"
   },
   "source": [
    "## 타이타닉 데이터셋을 불러오기\n",
    "타이타닉 데이터셋을 사용할 것입니다. 성별, 나이, 클래스, 기타 등 주어진 정보를 활용하여 승객이 살아남을 것인지 예측하는 것을 목표로 합니다." 
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "bNiwh-APcRVD"
   },
   "outputs": [],
   "source": [
    "!pip install tensorflow==2.0.0-beta0\n",
    "import tensorflow.compat.v2.feature_column as fc\n",
    "\n",
    "import tensorflow as tf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "DSeMKcx03d5R"
   },
   "outputs": [],
   "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')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "jjm4Qj0u7_cp"
   },
   "source": [
    "## 데이터 탐험하기"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "UrQzxKKh4d6u"
   },
   "source": [
    "데이터셋은 다음의 특성을 가집니다"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "rTjugo3n308g"
   },
   "outputs": [],
   "source": [
    "dftrain.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "y86q1fj44lZs"
   },
   "outputs": [],
   "source": [
    "dftrain.describe()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "8JSa_duD4tFZ"
   },
   "source": [
    "훈련셋은 627개의 사례로 평가셋은 264개의 사례로 구성되어 있습니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "Fs3Nu5pV4v5J"
   },
   "outputs": [],
   "source": [
    "dftrain.shape[0], dfeval.shape[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "RxCA4Nr45AfF"
   },
   "source": [
    "대부분의 승객은 20대와 30대 입니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "RYeCMm7K40ZN"
   },
   "outputs": [],
   "source": [
    "dftrain.age.hist(bins=20)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "DItSwJ_B5B0f"
   },
   "source": [
    "남자 승객이 여자 승객보다 대략 2배 많습니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "b03dVV9q5Dv2"
   },
   "outputs": [],
   "source": [
    "dftrain.sex.value_counts().plot(kind='barh')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "rK6WQ29q5Jf5"
   },
   "source": [
    "대부분의 승객은 \"삼등석\" 입니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "dgpJVeCq5Fgd"
   },
   "outputs": [],
   "source": [
    "dftrain['class'].value_counts().plot(kind='barh')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "FXJhGGL85TLp"
   },
   "source": [
    "여자는 남자보다 살아남을 확률이 훨씬 높습니다. 이는 모델에서 명확하게 예측가능한 특성입니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "lSZYa7c45Ttt"
   },
   "outputs": [],
   "source": [
    "pd.concat([dftrain, y_train], axis=1).groupby('sex').survived.mean().plot(kind='barh').set_xlabel('% survive')"
   ]
  },
  {
   "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",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "GpveXYSsADS6"
   },
   "outputs": [],
   "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))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Gt8HMtwOh9lJ"
   },
   "source": [
    "`input_function`은 입력 파이프라인을 스트리밍으로 공급하는 `tf.data.Dataset`으로 데이터를 변환하는 방법을 명시합니다. `tf.data.Dataset`은 데이터 프레임, CSV 형식 파일 등과 같은 여러 소스를 사용합니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "qVtrIHFnAe7w"
   },
   "outputs": [],
   "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)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "P7UMVkQnkrgb"
   },
   "source": [
    "다음과 같이 데이터셋을 점검할 수 있습니다:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "8ZcG_3KiCb1M"
   },
   "outputs": [],
   "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())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "lMNBMyodjlW3"
   },
   "source": [
    "또한 `tf.keras.layers.DenseFeatures` 층을 사용하여 특정한 특성 열의 결과를 점검할 수 있습니다:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "IMjlmbPlDmkB"
   },
   "outputs": [],
   "source": [
    "age_column = feature_columns[7]\n",
    "tf.keras.layers.DenseFeatures([age_column])(feature_batch).numpy()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "f4zrAdCIjr3s"
   },
   "source": [
    "`DenseFeatures`는 조밀한(dense) 텐서만 허용합니다. 우선 범주 열을 지시 열로 변환해야 합니다:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "1VXmXFTSFEvv"
   },
   "outputs": [],
   "source": [
    "gender_column = feature_columns[0]\n",
    "tf.keras.layers.DenseFeatures([tf.feature_column.indicator_column(gender_column)])(feature_batch).numpy()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "MEp59g5UkHYY"
   },
   "source": [
    "모든 기본 특성을 모델에 추가한 다음에 모델을 훈련해 봅시다. 모델을 훈련하려면 `tf.estimator` API를 이용한 커맨드 하나면 충분합니다:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "aGXjdnqqdgIs"
   },
   "outputs": [],
   "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)"
   ]
  },
  {
   "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",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "AM-RsDzNfGlu"
   },
   "outputs": [],
   "source": [
    "age_x_gender = tf.feature_column.crossed_column(['age', 'sex'], hash_bucket_size=100)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "DqDFyPKQmGTN"
   },
   "source": [
    "조합 특성을 모델에 추가하고 모델을 다시 훈련합니다:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "s8FV9oPQfS-g"
   },
   "outputs": [],
   "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)"
   ]
  },
  {
   "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",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "wiScyBcef6Dq"
   },
   "outputs": [],
   "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='예측 확률')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "UEHRCd4sqrLs"
   },
   "source": [
    "마지막으로, 수신자 조작 특성(receiver operating characteristic, ROC)을 살펴보면 정탐률(true positive rate)과 오탐률(false positive rate)의 상충관계에 대해 더 잘 이해할 수 있습니다. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "kqEjsezIokIe"
   },
   "outputs": [],
   "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,)"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [],
   "name": "linear.ipynb",
   "private_outputs": true,
   "provenance": [],
   "toc_visible": true,
   "version": "0.3.2"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "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"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
<commit_msg>'Download notebook' add<commit_after>{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "OoasdhSAp0zJ"
   },
   "source": [
    "##### Copyright 2019 The TensorFlow Authors."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "cellView": "form",
    "colab": {},
    "colab_type": "code",
    "id": "cIrwotvGqsYh"
   },
   "outputs": [],
   "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"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "C81KT2D_j-xR"
   },
   "source": [
    "# 추정기(Estimator)로 선형 모델 만들기\n",
    "\n",
    "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://www.tensorflow.org/beta/guide/using_gpu\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />TensorFlow.org에서 보기</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs/blob/master/site/ko/beta/tutorials/estimators/linear.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />구글 코랩(Colab)에서 실행하기</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs/blob/master/site/ko/beta/tutorials/estimators/linear.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />깃허브(GitHub) 소스 보기</a>\n",
    "  </td>\n",
    "  <td>\n",
    "    <a target=\"_blank\" href=\"https://storage.googleapis.com/tensorflow_docs/site/ko/beta/tutorials/estimators/linear.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\" />노트북 다운로드</a>\n",
    "  </td>\n",
    "</table>"
   ]
  },
  {
   "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) 깃헙 저장소로 풀 리퀘스트를 보내주시기 바랍니다. 문서 번역이나 리뷰에 참여하려면 [<EMAIL>](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs-ko)로 메일을 보내주시기 바랍니다."
    ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "tUP8LMdYtWPz"
   },
   "source": [
    "## 개요\n",
    "\n",
    "이 문서에서는 `tf.estimator` API를 사용하여 로지스틱 회귀 모델(logistic regression model)을 훈련합니다. 이 모델은 다른 더 복잡한 알고리즘의 기초로 사용할 수 있습니다.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "vkC_j6VpqrDw"
   },
   "source": [
    "## 설정"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "rutbJGmpqvm3"
   },
   "outputs": [],
   "source": [
    "!pip install sklearn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "54mb4J9PqqDh"
   },
   "outputs": [],
   "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"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "fsjkwfsGOBMT"
   },
   "source": [
    "## 타이타닉 데이터셋을 불러오기\n",
    "타이타닉 데이터셋을 사용할 것입니다. 성별, 나이, 클래스, 기타 등 주어진 정보를 활용하여 승객이 살아남을 것인지 예측하는 것을 목표로 합니다." 
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "bNiwh-APcRVD"
   },
   "outputs": [],
   "source": [
    "!pip install tensorflow==2.0.0-beta0\n",
    "import tensorflow.compat.v2.feature_column as fc\n",
    "\n",
    "import tensorflow as tf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "DSeMKcx03d5R"
   },
   "outputs": [],
   "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')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "jjm4Qj0u7_cp"
   },
   "source": [
    "## 데이터 탐험하기"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "UrQzxKKh4d6u"
   },
   "source": [
    "데이터셋은 다음의 특성을 가집니다"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "rTjugo3n308g"
   },
   "outputs": [],
   "source": [
    "dftrain.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "y86q1fj44lZs"
   },
   "outputs": [],
   "source": [
    "dftrain.describe()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "8JSa_duD4tFZ"
   },
   "source": [
    "훈련셋은 627개의 사례로 평가셋은 264개의 사례로 구성되어 있습니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "Fs3Nu5pV4v5J"
   },
   "outputs": [],
   "source": [
    "dftrain.shape[0], dfeval.shape[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "RxCA4Nr45AfF"
   },
   "source": [
    "대부분의 승객은 20대와 30대 입니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "RYeCMm7K40ZN"
   },
   "outputs": [],
   "source": [
    "dftrain.age.hist(bins=20)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "DItSwJ_B5B0f"
   },
   "source": [
    "남자 승객이 여자 승객보다 대략 2배 많습니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "b03dVV9q5Dv2"
   },
   "outputs": [],
   "source": [
    "dftrain.sex.value_counts().plot(kind='barh')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "rK6WQ29q5Jf5"
   },
   "source": [
    "대부분의 승객은 \"삼등석\" 입니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "dgpJVeCq5Fgd"
   },
   "outputs": [],
   "source": [
    "dftrain['class'].value_counts().plot(kind='barh')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "FXJhGGL85TLp"
   },
   "source": [
    "여자는 남자보다 살아남을 확률이 훨씬 높습니다. 이는 모델에서 명확하게 예측가능한 특성입니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "lSZYa7c45Ttt"
   },
   "outputs": [],
   "source": [
    "pd.concat([dftrain, y_train], axis=1).groupby('sex').survived.mean().plot(kind='barh').set_xlabel('% survive')"
   ]
  },
  {
   "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",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "GpveXYSsADS6"
   },
   "outputs": [],
   "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))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "Gt8HMtwOh9lJ"
   },
   "source": [
    "`input_function`은 입력 파이프라인을 스트리밍으로 공급하는 `tf.data.Dataset`으로 데이터를 변환하는 방법을 명시합니다. `tf.data.Dataset`은 데이터 프레임, CSV 형식 파일 등과 같은 여러 소스를 사용합니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "qVtrIHFnAe7w"
   },
   "outputs": [],
   "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)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "P7UMVkQnkrgb"
   },
   "source": [
    "다음과 같이 데이터셋을 점검할 수 있습니다:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "8ZcG_3KiCb1M"
   },
   "outputs": [],
   "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())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "lMNBMyodjlW3"
   },
   "source": [
    "또한 `tf.keras.layers.DenseFeatures` 층을 사용하여 특정한 특성 열의 결과를 점검할 수 있습니다:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "IMjlmbPlDmkB"
   },
   "outputs": [],
   "source": [
    "age_column = feature_columns[7]\n",
    "tf.keras.layers.DenseFeatures([age_column])(feature_batch).numpy()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "f4zrAdCIjr3s"
   },
   "source": [
    "`DenseFeatures`는 조밀한(dense) 텐서만 허용합니다. 우선 범주 열을 지시 열로 변환해야 합니다:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "1VXmXFTSFEvv"
   },
   "outputs": [],
   "source": [
    "gender_column = feature_columns[0]\n",
    "tf.keras.layers.DenseFeatures([tf.feature_column.indicator_column(gender_column)])(feature_batch).numpy()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "MEp59g5UkHYY"
   },
   "source": [
    "모든 기본 특성을 모델에 추가한 다음에 모델을 훈련해 봅시다. 모델을 훈련하려면 `tf.estimator` API를 이용한 커맨드 하나면 충분합니다:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "aGXjdnqqdgIs"
   },
   "outputs": [],
   "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)"
   ]
  },
  {
   "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",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "AM-RsDzNfGlu"
   },
   "outputs": [],
   "source": [
    "age_x_gender = tf.feature_column.crossed_column(['age', 'sex'], hash_bucket_size=100)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "DqDFyPKQmGTN"
   },
   "source": [
    "조합 특성을 모델에 추가하고 모델을 다시 훈련합니다:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "s8FV9oPQfS-g"
   },
   "outputs": [],
   "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)"
   ]
  },
  {
   "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",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "wiScyBcef6Dq"
   },
   "outputs": [],
   "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='예측 확률')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "UEHRCd4sqrLs"
   },
   "source": [
    "마지막으로, 수신자 조작 특성(receiver operating characteristic, ROC)을 살펴보면 정탐률(true positive rate)과 오탐률(false positive rate)의 상충관계에 대해 더 잘 이해할 수 있습니다. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "kqEjsezIokIe"
   },
   "outputs": [],
   "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,)"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [],
   "name": "linear.ipynb",
   "private_outputs": true,
   "provenance": [],
   "toc_visible": true,
   "version": "0.3.2"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "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"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}

{'fraction_non_alphanumeric': 0.20506313998268502, 'fraction_numerical': 0.011344299489506523, 'mean_word_length': 2.7722972972972975, 'pattern_counts': {'":': 664, '<': 44, '<?xml version=': 0, '>': 44, 'https://': 28, 'lorem ipsum': 0, 'www.': 13, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4883871', 'n_tokens_mistral': 16867, 'n_tokens_neox': 17966, 'n_words': 2644}