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",
+ "
"
+ ]
+ },
+ {
+ "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