{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPython 3.7.3\n", "IPython 7.5.0\n", "\n", "numpy 1.16.3\n", "scipy 1.2.1\n", "sklearn 0.21.1\n", "pandas 0.24.2\n", "matplotlib 3.0.3\n" ] } ], "source": [ "%load_ext watermark\n", "%watermark -v -p numpy,scipy,sklearn,pandas,matplotlib" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**3장 – 분류**\n", "\n", "_이 노트북은 3장에 있는 모든 샘플 코드와 연습문제 해답을 가지고 있습니다._" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 설정" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "파이썬 2와 3을 모두 지원합니다. 공통 모듈을 임포트하고 맷플롯립 그림이 노트북 안에 포함되도록 설정하고 생성한 그림을 저장하기 위한 함수를 준비합니다:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# 파이썬 2와 파이썬 3 지원\n", "from __future__ import division, print_function, unicode_literals\n", "\n", "# 공통\n", "import numpy as np\n", "import os\n", "\n", "# 일관된 출력을 위해 유사난수 초기화\n", "np.random.seed(42)\n", "\n", "# 맷플롯립 설정\n", "%matplotlib inline\n", "import matplotlib\n", "import matplotlib.pyplot as plt\n", "plt.rcParams['axes.labelsize'] = 14\n", "plt.rcParams['xtick.labelsize'] = 12\n", "plt.rcParams['ytick.labelsize'] = 12\n", "\n", "# 한글출력\n", "matplotlib.rc('font', family='NanumBarunGothic')\n", "plt.rcParams['axes.unicode_minus'] = False\n", "\n", "# 그림을 저장할 폴드\n", "PROJECT_ROOT_DIR = \".\"\n", "CHAPTER_ID = \"classification\"\n", "\n", "def save_fig(fig_id, tight_layout=True):\n", " path = os.path.join(PROJECT_ROOT_DIR, \"images\", CHAPTER_ID, fig_id + \".png\")\n", " if tight_layout:\n", " plt.tight_layout()\n", " plt.savefig(path, format='png', dpi=300)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# MNIST" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "scrolled": false }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/utils/deprecation.py:85: DeprecationWarning: Function fetch_mldata is deprecated; fetch_mldata was deprecated in version 0.20 and will be removed in version 0.22. Please use fetch_openml.\n", " warnings.warn(msg, category=DeprecationWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/utils/deprecation.py:85: DeprecationWarning: Function mldata_filename is deprecated; mldata_filename was deprecated in version 0.20 and will be removed in version 0.22. Please use fetch_openml.\n", " warnings.warn(msg, category=DeprecationWarning)\n" ] }, { "data": { "text/plain": [ "{'DESCR': 'mldata.org dataset: mnist-original',\n", " 'COL_NAMES': ['label', 'data'],\n", " 'target': array([0., 0., 0., ..., 9., 9., 9.]),\n", " 'data': array([[0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0],\n", " [0, 0, 0, ..., 0, 0, 0]], dtype=uint8)}" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.datasets import fetch_mldata\n", "mnist = fetch_mldata('MNIST original')\n", "mnist" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(70000, 784)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X, y = mnist[\"data\"], mnist[\"target\"]\n", "X.shape" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(70000,)" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y.shape" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "784" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "28*28" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`fetch_mldata`는 0.22 버전에서 삭제될 예정입니다. 0.20 버전에서 관련된 경고를 피하기 위해 대신 `fetch_openml` 함수를 사용하는 것이 좋습니다." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "from sklearn.datasets import fetch_openml\n", "mnist = fetch_openml('mnist_784', version=1)\n", "X, y = mnist[\"data\"], mnist[\"target\"]\n", "y = y.astype(np.int)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "import matplotlib\n", "import matplotlib.pyplot as plt\n", "\n", "some_digit = X[36000]\n", "some_digit_image = some_digit.reshape(28, 28)\n", "plt.imshow(some_digit_image, cmap = matplotlib.cm.binary,\n", " interpolation=\"nearest\")\n", "plt.axis(\"off\")\n", "\n", "save_fig(\"some_digit_plot\")\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "def plot_digit(data):\n", " image = data.reshape(28, 28)\n", " plt.imshow(image, cmap = matplotlib.cm.binary,\n", " interpolation=\"nearest\")\n", " plt.axis(\"off\")" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "# 숫자 그림을 위한 추가 함수\n", "def plot_digits(instances, images_per_row=10, **options):\n", " size = 28\n", " images_per_row = min(len(instances), images_per_row)\n", " images = [instance.reshape(size,size) for instance in instances]\n", " n_rows = (len(instances) - 1) // images_per_row + 1\n", " row_images = []\n", " n_empty = n_rows * images_per_row - len(instances)\n", " images.append(np.zeros((size, size * n_empty)))\n", " for row in range(n_rows):\n", " rimages = images[row * images_per_row : (row + 1) * images_per_row]\n", " row_images.append(np.concatenate(rimages, axis=1))\n", " image = np.concatenate(row_images, axis=0)\n", " plt.imshow(image, cmap = matplotlib.cm.binary, **options)\n", " plt.axis(\"off\")" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoYAAAKACAYAAAAB07lkAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAIABJREFUeJzsnWWgFGUfxX++JiomdmEjKFggitiAioUKKnZjiyLYid2KhQGCAgbYYiGCit2t2Bi8Ktgtvh9ezjyzc3f31sbs3vP7cufOzs599u7M7M55zv/8Z/n3338xxhhjjDHmP+UegDHGGGOMSQf+YmiMMcYYYwB/MTTGGGOMMTPxF0NjjDHGGAP4i6ExxhhjjJmJvxgaY4wxxhjAXwyNMcYYY8xM/MXQGGOMMcYA/mJojDHGGGNmMlu5B5DAbViMMcYYY4rLLLkesGJojDHGGGMAfzE0xhhjjDEz8RdDY4wxxhgD+IuhMcYYY4yZib8YGmOMMcYYIH1VycYYY4xpglxyySXR8kUXXQTAaaedBsDBBx9cljE1RawYGmOMMcYYwF8MjTHGGGPMTDyVbEwFMXHiRAD++usvAMaPHw/AlClTANhhhx0AaN68efSczTffvJRDNMaYeqEp5AEDBkTr/vnnHwB+//33soypEHz++ecAPPnkkwA888wzdX7u66+/DkC3bt2idccccwwAc801V6GGmBUrhsYYY4wxBoBZ/v03VV3oSjIY3Yn88MMPObcZNGgQAL/++isA7733HgBXXXUVAP369QNg5MiRQOY3+OOPPx4IpllTfgYOHAjAAw88AMCSSy4JwOjRo8s2piQ61u677z4Azj//fAC+/fbbaJsvvvgCgBkzZtR5v0svvTQAPXv2BGDnnXcGYIMNNmjkiIvHH3/8AcBNN92Usf67774D4JRTTqnxHJ2Te++9NwCrr756MYdoCsQvv/wCwO233w7Ab7/9BsCjjz4KwIQJE6JtdZ3VMdyrVy8ANtxww9IM1hSF9u3bA/DSSy9F6zbaaCMgXA/jsyBpY+rUqQA8++yzAFx99dUAvPDCCwBMnz69IH9nv/32A2Dw4MEAzDrrrI3ZnVviGWOMMcaY/FSdYvjZZ58B8Oeff0brJk2aBMBTTz0FwPfffw/AnXfeWef9LrPMMgCsu+66ANx1110AzDvvvAC0a9cu2vass84CYJNNNqn3+E1xOPHEEwE499xzgfC+SZUA6NixY+kHFmO77bYDwh2yiKvRukNs3bo1EI5HIdUxfmwnvTqzzfZ/a/EVV1wBwCGHHFKYF1AAXn75ZQD22msvAN5+++1672OppZYCYMSIEQCsvfbaAMwzzzyFGGLZ+eqrrwAYN24cAGPGjIke03UpF1IczjzzTCD8r8qBZmG6dOkCBAV7iSWWAGDTTTcFwvsH8MknnwAwatQoILz27bffHoDjjjsOgBVWWKGYQ08VN998MxDOY6lWbdu2LduY6ssss8yS8ROC6tanT5+yjKkunH766QBce+21QFAO55hjjoztZp99diAzcmfllVcGYMstt8y6bynnPXr0iNbpnJFnsZFKuRVDY4wxxhiTn6pRDF955RUANttsMyC/f7A+SKGR1ympOsirtuCCC0brVl111YL87UIhhfSggw6K1t1xxx0Z26y00kpA+D9KUasWlltuOSAoyrozjXvY9tlnn5KPK078bhmCAiC1E4JfsD7897//BWD//fcH4P777weCMiPlabXVVqv3vguNFK2hQ4c2el+6tvXt2xfIDM+tJKQcyB8rleKtt96qsa2O82TVolTjyZMnA0HhKGdosN4X+UmlENWHb775Bgje76R6BtC/f/9GjTONfPTRR9HyiiuuCITrx6uvvgpUhmIoH7V8+fFZmwcffBDI/GxNG0cccQQQahI0I6XX0xj+/vtvALbddtto3UMPPQTAeeedB2RWcTcAK4bGGGOMMSY/VZNjqDvlFi1aAPVTDNdbbz0g885E+XDyCuy5554FGWcpUYaS7hylHAL85z//vyeYc845Afjwww8BOPXUU4HKVVdyIWXkpJNOylgv/ymUXzF84403gOCp2XfffYGGqYRxFl10UQDuvvtuANZff30gVMzpLjQNimG8KjGO/Dg77bRTjcfkQ7z33nuzPlev+4ADDojWyaOZZuQnkmIsP538SvJhxtWxNm3aADUrOHWcd+rUCYCxY8cC6Wgz1qFDhwY/d5FFFgGCiiovuFTxakEzHcOGDQNCu7g4J598MhDOlTSjHNZ77rknY/2BBx4YLadZKczFrrvuWrB9TZs2DQjX5zhx32ExsGJojDHGGGOAKlIMF1poIQAuvPBCILOyc6211gLgyCOPzHjOmmuuCcBjjz0GZPoH33zzTSBU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gRWINddcE4DmzZsDMH369KzbyXMIQUU0lYWuQKWcJUmjanD22WcDwWejK/94Pl+yMk/qtzLLkiibEUKHhBtvvBGA1157DQiqRK7vQxrJNtaFFlqoDCMpP8n8xjhSEZNKm1THNOQcTp06FYDLL78cqDl7kU/XsbpsK5+evmdrrLEGEHzISpxIAz169ABg3LhxABx88MFAmOXKxuabbw6E7748mtdeey0ALVq0KM5g68Hnn38OwJlnngmEmQD5oNOOFUNjjDHGGAP4xNAYY4wxxsyiUUwli9tvvx3IHt4MYQoqjqRfheimEZXxa+pCU8qeLq6JAq8riXhLMLU7rERatmwJwFVXXVXvx7jvvvsA6NevX7RMocBChWJqZ6nWU2lGhTM33HBDjXWnnnpqrfedOHFidFsFK2qD+fHHHwPhvUhz4Zimh/OJq0kjOg7LfvThhx8CtReYqMBovfXWA6Bnz54AdOzYMWM7/UbJUhLn1VdfBcI+oHgyWafUChZCbMpKK61UtxdVIPTdV/HjrrvuCsCgQYNme9+DDjoICPFrOhaqmEfxThAKVsqFvn9dunQBQpOJSsGKoTHGGGOMAaBJPgbYElCWwSgs+LjjjouWybiuMOd4MGXaUBiwri6lGEqFaMwowFtX67pCrq3FWtro06dPdDvZ+m7++ecHQjyP1IFqQcHyiryJh7QLtYpTwUElxNIkueOOOwDYY489omUqOnn//feBMHshZei8884D4JZbbonuk+t4rv2/c+fOQGg91r59+8K8gDKRVOFUsFLO4pM2bdoAuQvERDycXt/bFVdcsd7PqzDlffbZBwhB11Iw40htGz58eL2frz7o89K+/e677wJhNiEfpMLdeuutQGa7ObW9LTWKhNMxqFevXgAcccQR9X5Mff8hnKso3mejjTYCghKror06klPCtmJojDHGGGOARuYxzIV8PVIJARZbbDEAVltttbKMqdjotcZDr+MoyifPK5DUkVRQ/vnnnzKNpDgo3FyKg0J055tvvmibr7/+GggB70nUYm255ZYr1jDrjUKx5SOU4hD/XBXDdNRRR2V9DL03cdVf71taUCu0OGolKKVQyo8CfvUdlioOIQZk0UUXzXgsxWeMHTsWgJ122gmAUaNGRdvocSuBXD7ENARbS7lLqpn6HBUbM3To0II+r3yKimVTswK1x5w0aVK0rfx4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qVMBGD9+fMa2d911FxC+F2ngiSeeAGDzzTcHYN555wXCZ3PggQdG284999xZH2PjjTcGgvpfrWy77bbRbX221aoYarZH6q9+v1555RUg7CelJu75mjZtGgBzzTUXEHyRhxxySL0fX69P34f493377bcH0n2cSnLHHXdk/P/ZZ58BcNxxx0XL5APX75p47rnngOD/rwT+/PNPINMPr1lIzVSJ119/HcgeRyWmTJkCNNgHb8XQGGOMMcbUTqNqiSdfRi6lsJJUwjjyEu633351vo98gosvvjgAbdq0AYKHR6214r4sLdMVW9zbBDB48GAAFltssfxeQJ5IIf3666+BcDUNmepJXZg5c2Z0e/jw4RmPf9555zVonHXl008/BXK3+VJ1JsALL7wAwIgRIwB49tlngeA/qwtJn973339f5/uWC3lCH3/88fIOJOV07NgRgPnmm6/MIykOel1KSFA1qI7t8nKVGvkJ40i9bIhSKFTtmq3CXr7qSkDq3x577DHbbeXJ1F8lExx77LEATJw4sRhDLAr6vY2j9yD5Xuj3QGkDcRVV3HTTTQCceeaZBR2nsGJojDHGGGOARqIYjho1CghVpkJXl2effXbO+0qtkUeg3J4deRTee++9aFkupVPeKqkt8StXVTPtsMMOWe+rat6471K+L6H2P1K6VBXXpUuX2b+QeqDnGzhwIAArr7wy0LCrJilvEDLRDj/8cKB4OYZSOVTJ9u233wJBvU0Sr2R7//33M9Zpf0iqgMrdBJhzzn+/5moJl1TMpRanEb2+lHmhU4u8bs2aNSvzSIqLfM4XX3wxELyV5VIMlekKoZVfIdBsSNIXHKcErdMajDyFSXVMPkJVVmvWJhv6nXn++eeBoBhWktewLuh1KjkhG/nMDtYHK4bGGGOMMQaoYsVQKiEEL5wq2k466SSgdqVJVVI77rgjAC1btsx43HIph1Iu27Vrl3MbVcOpaninnXaq8+PLwyW/oFStOAsttBAQ8gvle9PyYqGrTnkv9t9//3o/ljx5J554YrRMiuqFF15Y78etC/KQxLPPIHcladyzOWTIkIx16oKhxusi3glCaqKy35KKYRq59957gTD2cnfXqRR0vKpEvvnmGwAee+wxIHRfirPzzjsDQVX5z3/+1TaKfeyZHf369SvK4+rY+tVXXxXl8YtJvPI4qRTuvvvuNbaZHVIV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vTsPuHJO/zj+ZsiSfSfZI2uWqCzZyhaSaoxCEZVtwsj0sxsaNMq+r8kyQsiWpSKJIhM1jCXrINmGCSnx+2Oez/29z/2c86xnuc95Pq9/nvOc7fk+59znPvd9fa/vdbHrrrsC8MwzzxRsnJZ/F110EQDPPvssAPvssw8AgwcPBmDJJZcs+pgcMTQzMzMzoIIihlOnTgVg1KhRAAwcOLDafUaOHAnAK6+8knH9G2+8AUDz5s2j61q0aAHAOuusA4Szso033hiAww47DIDWrVsDsMQS6Xspv/76awC6desGwOTJk6PbFEm47bbbAGjZsiUAF154IQAff/wxALfffntxBms56T0CeP3114EQ+dF2/uWXXwIhMjR8+PDoMUsttRQAa6+9dtbn//HHHwE47rjjAPj000+j284880yg9Nv3559/DkCHDh1y3kfbtH7ed999GT9XWmml6L4HHnhgQcZZatoObrjhBiC8FgsWLADCjEC5UqT49NNPBzK3VYC//e1vGben0ffffw/A2LFjo+tuvvlmACZNmgSE76KDDjoIgGuvvRaAvfbaC4CjjjoqemybNm0yniMt4mPU93LSpptuCoRomb6HmpLx48cD8PzzzwNhG1hhhRUAOOmkk4o+JkcMzczMzAyooIjhiBEjAHjggQcAuO6666LbdNacy2+//QZknk1/9tlnNd5Xq/tefPFFANq3b9+QYRdU//79gTDGuO7duwNwwQUXANC5c+eM2999990Cj85q89ZbbwEhigvw0UcfAbD77rtn/H799dcDIRoRpwh5rhzKV199FQiR5fhK7V69egGwySabNOyfKKJrrrkGgO233z7jev1f9dmmzz77bAAmTJgQXTds2DAg5HKl0dChQ0s9hLybMmVKdFm5kYsWLQJgrbXWAsLMjfZnes8hzPKUmqK5mm2aOHFidNuGG24IwBVXXAFAz549gTBjJcof1GcWss+OpUH8s5PrO1ifSe1f4vdTnrve00qjvNLkDKZcffXVgCOGZmZmZlZCFRMxVHTsqaeeArJHTpJWWWUVIKy8jJ+taEWj5v0VQZw7d27Gc+gM/dFHH23w2PNFq48VYdLKY4mffSrfcplllgFCDpfssMMOBRtnvikfEuCyyy4DQh232sQjw2lZlfztt98CYTWtooJx2i71U7beemsgnG1D7f9X27ZtAbj33nsB2G+/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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=(9,9))\n", "example_images = np.r_[X[:12000:600], X[13000:30600:600], X[30600:60000:590]]\n", "plot_digits(example_images, images_per_row=10)\n", "save_fig(\"more_digits_plot\")\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "9" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y[36000]" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "shuffle_index = np.random.permutation(60000)\n", "X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 이진 분류기" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "y_train_5 = (y_train == 5)\n", "y_test_5 = (y_test == 5)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "scrolled": true }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n" ] }, { "data": { "text/plain": [ "SGDClassifier(alpha=0.0001, average=False, class_weight=None,\n", " early_stopping=False, epsilon=0.1, eta0=0.0, fit_intercept=True,\n", " l1_ratio=0.15, learning_rate='optimal', loss='hinge', max_iter=5,\n", " n_iter_no_change=5, n_jobs=None, penalty='l2', power_t=0.5,\n", " random_state=42, shuffle=True, tol=0.001, validation_fraction=0.1,\n", " verbose=0, warm_start=False)" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.linear_model import SGDClassifier\n", "\n", "sgd_clf = SGDClassifier(max_iter=5, random_state=42)\n", "sgd_clf.fit(X_train, y_train_5)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([False])" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sgd_clf.predict([some_digit])" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n" ] }, { "data": { "text/plain": [ "array([0.964 , 0.9579, 0.9571])" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.model_selection import cross_val_score\n", "cross_val_score(sgd_clf, X_train, y_train_5, cv=3, scoring=\"accuracy\")" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "0.964\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "0.9579\n", "0.9571\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n" ] } ], "source": [ "from sklearn.model_selection import StratifiedKFold\n", "from sklearn.base import clone\n", "\n", "skfolds = StratifiedKFold(n_splits=3, random_state=42)\n", "\n", "for train_index, test_index in skfolds.split(X_train, y_train_5):\n", " clone_clf = clone(sgd_clf)\n", " X_train_folds = X_train[train_index]\n", " y_train_folds = (y_train_5[train_index])\n", " X_test_fold = X_train[test_index]\n", " y_test_fold = (y_train_5[test_index])\n", "\n", " clone_clf.fit(X_train_folds, y_train_folds)\n", " y_pred = clone_clf.predict(X_test_fold)\n", " n_correct = sum(y_pred == y_test_fold)\n", " print(n_correct / len(y_pred))" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "from sklearn.base import BaseEstimator\n", "class Never5Classifier(BaseEstimator):\n", " def fit(self, X, y=None):\n", " pass\n", " def predict(self, X):\n", " return np.zeros((len(X), 1), dtype=bool)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([0.909 , 0.90745, 0.9125 ])" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "never_5_clf = Never5Classifier()\n", "cross_val_score(never_5_clf, X_train, y_train_5, cv=3, scoring=\"accuracy\")" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n" ] } ], "source": [ "from sklearn.model_selection import cross_val_predict\n", "\n", "y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[54058, 521],\n", " [ 1899, 3522]])" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.metrics import confusion_matrix\n", "\n", "confusion_matrix(y_train_5, y_train_pred)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "y_train_perfect_predictions = y_train_5" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[54579, 0],\n", " [ 0, 5421]])" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "confusion_matrix(y_train_5, y_train_perfect_predictions)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.8711352955725946" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.metrics import precision_score, recall_score\n", "\n", "precision_score(y_train_5, y_train_pred)" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.7687135020350381" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "4344 / (4344 + 1307)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.6496956281128943" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "recall_score(y_train_5, y_train_pred)" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.801328168234643" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "4344 / (4344 + 1077)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.7442941673710904" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.metrics import f1_score\n", "f1_score(y_train_5, y_train_pred)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.7846820809248555" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "4344 / (4344 + (1077 + 1307)/2)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([-400042.39513131])" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y_scores = sgd_clf.decision_function([some_digit])\n", "y_scores" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "threshold = 0\n", "y_some_digit_pred = (y_scores > threshold)" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([False])" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y_some_digit_pred" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([False])" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "threshold = 200000\n", "y_some_digit_pred = (y_scores > threshold)\n", "y_some_digit_pred" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n" ] } ], "source": [ "y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3,\n", " method=\"decision_function\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "노트: 만약 사이킷런 0.19.0 버전을 사용하고 있다면 `method=\"decision_function\"` 옵션으로 `cross_val_predict()` 함수를 사용할 때 이진 분류에서 1차원 배열이 아니고 2차원 배열을 반환하는 [버그](https://github.com/scikit-learn/scikit-learn/issues/9589)가 있습니다. 사이킷런 0.19.1로 업그레이드하거나 다음 셀에서 y_scores\\[:, 1\\] 처럼 두 번째 열만 사용해야 합니다." ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(60000,)" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y_scores.shape" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [], "source": [ "# hack to work around issue #9589 introduced in Scikit-Learn 0.19.0\n", "# if y_scores.ndim == 2:\n", "# y_scores = y_scores[:, 1]" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "from sklearn.metrics import precision_recall_curve\n", "\n", "precisions, recalls, thresholds = precision_recall_curve(y_train_5, y_scores)" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def plot_precision_recall_vs_threshold(precisions, recalls, thresholds):\n", " plt.plot(thresholds, precisions[:-1], \"b--\", label=\"정밀도\", linewidth=2)\n", " plt.plot(thresholds, recalls[:-1], \"g-\", label=\"재현율\", linewidth=2)\n", " plt.xlabel(\"임계값\", fontsize=16)\n", " plt.legend(loc=\"upper left\", fontsize=16)\n", " plt.ylim([0, 1])\n", "\n", "plt.figure(figsize=(8, 4))\n", "plot_precision_recall_vs_threshold(precisions, recalls, thresholds)\n", "plt.xlim([-700000, 700000])\n", "save_fig(\"precision_recall_vs_threshold_plot\")\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(y_train_pred == (y_scores > 0)).all()" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [], "source": [ "y_train_pred_90 = (y_scores > 70000)" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.9309882747068676" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "precision_score(y_train_5, y_train_pred_90)" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.5126360450101457" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "recall_score(y_train_5, y_train_pred_90)" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def plot_precision_vs_recall(precisions, recalls):\n", " plt.plot(recalls, precisions, \"b-\", linewidth=2)\n", " plt.xlabel(\"재현율\", fontsize=16)\n", " plt.ylabel(\"정밀도\", fontsize=16)\n", " plt.axis([0, 1, 0, 1])\n", "\n", "plt.figure(figsize=(8, 6))\n", "plot_precision_vs_recall(precisions, recalls)\n", "save_fig(\"precision_vs_recall_plot\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ROC 곡선" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [], "source": [ "from sklearn.metrics import roc_curve\n", "\n", "fpr, tpr, thresholds = roc_curve(y_train_5, y_scores)" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "data": { "image/png": "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TqOqqopnn32WiRMnRh2WiIhIqxTrBKc1Wbx4MVOmTGHYsGGsXbuW008/PeqQREREWi09RRWx7du306VLF84//3zy8vL49re/3ap6nkRERFoi9eBEZN++fVx33XUcc8wxbNmyhZycHIYPH67kRkREpBmoBycCb7/9NhdeeCHl5eWMGzeOrl27Rh2SiIhIrCjBybDFixczduxYzIzFixdTUlISdUgiIiKxowQnw5YuXcoJJ5zAokWL6NWrV9ThiIiIxFKsdxOv/Oufow4DgPXr19O2bVuOOeYY9uzZQ7t27WjTpk3UYYmIiLRo2k28hXJ35syZw4ABA7jqqqsA6Nixo5IbERGRNFOCkybbt2+npKSE8ePHM3jwYObNmxd1SCIiIllDc3DSYOPGjZx11lls3bqVW265hcmTJ5OTo1xSREQkU5TgpEGPHj3o378/Dz74IAMHDow6HBERkawT226FTC+Xt3XrVi655BJ27dpFXl4eS5cuVXIjIiISkdgmOJm0bNkyCgsLWbx4MatXr446HBERkaynBOcAVFZWMmnSJIYOHcqRRx7JqlWrOPPMM6MOS0REJOspwTkAkyZNYtasWVx++eW89NJLHH/88VGHJCIiIsR4ob+8I/p4RZoW+quoqCAvL4/NmzezZs0ahg0blpbPERERyWYHstCfnqJqhN27dzNx4kQ++OADli1bRkFBAQUFBVGHJSIiIkk0RJWiV199lVNOOYWFCxfy1a9+lbj2fImIiMSBEpwGuDuzZ8+muLiYTz75hOXLlzNt2jRyc3OjDk1ERETqoDk4DdixYwd9+/alf//+3HvvvXTr1q0ZohMREZGGaA5OGrz00kv079+fzp07U15eTvfu3THL9PKBIiIi0hQaokpSVVXFDTfcQHFxMbfffjsARx11lJIbERGRVkQ9OAk2bdrE6NGjWblyJWPGjGHChAlRhyQiIiJNoAQn9NRTTzFq1Cj27dvHggULGD16dNQhiYiISBPFN8Fp5IhSfn4+J5xwAvPmzaN3797piUlEREQyIqvn4LzxxhtMnz4dgH79+lFWVqbkRkREJAayMsFxd+6++26KioqYNWsW27ZtA9BEYhERkZiIbYJjdYxR7dy5k5EjRzJ27FhOO+00XnvtNfLz8zMcnYiIiKRTfOfg1KK6uprBgwezfv16pk+fzrXXXktOTmxzPBERkayV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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def plot_roc_curve(fpr, tpr, label=None):\n", " plt.plot(fpr, tpr, linewidth=2, label=label)\n", " plt.plot([0, 1], [0, 1], 'k--')\n", " plt.axis([0, 1, 0, 1])\n", " plt.xlabel('거짓 양성 비율', fontsize=16)\n", " plt.ylabel('진짜 양성 비율', fontsize=16)\n", "\n", "plt.figure(figsize=(8, 6))\n", "plot_roc_curve(fpr, tpr)\n", "save_fig(\"roc_curve_plot\")\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.9598058535696421" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.metrics import roc_auc_score\n", "\n", "roc_auc_score(y_train_5, y_scores)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "랜덤 포레스트 `n_estimator` 매개변수의 기본값이 0.22 버전에서 10에서 100으로 변경될 예정입니다. 경고를 피하기 위해서 `n_estimator=10`으로 지정합니다." ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [], "source": [ "from sklearn.ensemble import RandomForestClassifier\n", "forest_clf = RandomForestClassifier(n_estimators=10, random_state=42)\n", "y_probas_forest = cross_val_predict(forest_clf, X_train, y_train_5, cv=3,\n", " method=\"predict_proba\")" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [], "source": [ "y_scores_forest = y_probas_forest[:, 1] # 점수는 양상 클래스의 확률입니다\n", "fpr_forest, tpr_forest, thresholds_forest = roc_curve(y_train_5,y_scores_forest)" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "data": { "image/png": "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8LbXjOGfw4fdPI358938k3Ll3PoXDz3kbolduzZY4DRpArNmBedgxMa6wqZJEzeBNcPll7shodA5Is2bu4yhypY98hZVyHy7rogUPz///DPXXXcdP/74I3fddRdpaWknvLZNboTFbeIFIS+3iVtr+fynLfxnxi/8un0/AGfWiOW+LqfRoVFV3Uotmezf7wqQ+Pjgra5ffOEWG7vjjuAdNK++6ia43nBDcA2KUaPcSqC33x68RXj2bDfs066d+xxc0VO9uitiMuaZBALBIZklS1zRAe4uoNKl3TBR1fRFvLZudXcAnXlm5omwIiIFxVrLhAkTGDx4MGXLluWNN97g4osvztO5ivxt4uFg3todjPx8Fct/d9tb1a5Umrs7N+KypjX/XlVVio9du4Irjx465HpB5s5164GUKeN6TDKGZH791U1qBXeL8HvvuTknNWq4npQ//3TDP1WqBAuc0AXTMlSv7ia8nnFGsK1aNTcvJvSW3IgIl69cucxzT95++8jXUb36kQuaiYgUpF27djFs2DDatGnDpEmTqFGjhic5in2B8+Pve3jqi1V8t2YHAFXLRTO4U0OuSziFklGaHOw3KSluxdSMzrgPP3S9JNde6+5U2bEj2PuRlOSKiKgoN7k1MdFNsu3Y0fXYXHaZm8eyaFGwwOnSxRUUqanBAujyy93HSy4J5uja1S0eF9qrctpp8O67R2Z+7rkj27SOiIiEm59++okzzjiDSpUqMW/ePOrXr09k1jsAClGxHaL6dfs+np6xmk9//BNwi+f173AqN51bl9Ili33dV+QdOOAWX6tZMzjHpXFjN6S0fbvrTQF36+4PPwRvWw4E3BL3Cxe69UgyVmkdN84VQrfe6npmIPMmcSIixVUgEGDUqFE8+OCDjBo1iiFZF146ARqiyqVx367jP1/8QlrAEh0VwY3n1uX2DqdSobTWDA93ycmwYYPr7cgoLrp3d/vSjB0b7Elp08YtIDdzprvl2Fo3LLRihZske+217rirr3bHVqrknkdEuDk0lSplLl769z8yi4obESnutm7dyg033MCMGTO4+uqr6dOnj9eR/lbsxmC2JSUz6otfCFhLj5an8M295zHs4jNU3ISZNWvcfjZ167riJUPp0m6Tv1mzXLFz8KC7jfnTT2HTpuBxCQmu5+ann9xzY9w8mmnTgsUNwMMPuzVcQtdWqVxZ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OobL2+IlNw87516N9OBm3kuqxpEjRxg3bhw7duwgKiqKOXPmcN111/kdloiI1FK+dVE55zLMbADwNzNzeN1T/w3UB9oCjcJVJwEJwFgzGxsuO+Kc617S8TXIuOps2LCBgQMH8uWXX9K2bVtGjRrld0giIlLL+Trq0zn3IXBuEZta5atzddVFJGX1yiuvMHr0aGJjY/nHP/5Bv379/A5JREQkuDMZS+V74YUXuP766+nWrRsrV65UciMiItVGYJ/bDYW8pRo0k3HFy8nJITo6mkGDBpGZmcmtt95KdHS032GJiIjk8W0m48pWNyHR7d20gQYN/I4kOEKhEE8//TSpqal89NFHxMbG+h2SiPhk//79pKenk5WV5XcoUgPFxMTQokUL4uPjS6xXU2cyrlRRURAX53cUwZGenk5ycjLz58+nf//+HDlyRAmOSC21f/9+du/eTcuWLYmLi8P0yKqUgXOOzMxMvv32W4BSk5zyCuwYHDNQr0nF+OCDD+jatSsLFy7kf/7nf3jzzTdp1KhR6TuKSCClp6fTsmVL6tevr+RGyszMqF+/Pi1btiQ9Pb3SzhPYFhypGKFQiLFjx9K4cWPee+89unTp4ndIIuKzrKws4tRELscpLi6uUrs4A5vgOAdHj0Ldun5HUjNt3bqVE088kfj4eN566y2aNm3KCSec4HdYIlJNqOVGjldlfw8FtosqFILsbL+jqJneeOMNunbtypgxYwBo06aNkhsREalRApvgREVBTIzfUdQsmZmZ/O53v2PAgAGceuqp3HvvvX6HJCIiUi6BTXDMlOCUxfr16zn33HOZMmUKd911F2lpaZxyyil+hyUiIlIugU1wpGzq169PKBTin//8JxMmTKCuBi+JSC0zffp0zj33XOLj42nRogU9e/bkjTfeKFDnyJEjPPvssyQlJdGoUSMaNmxI586dufHGG/n666/z6rVr1w4zw8yIjY2lVatWXHHFFcyaNYucnJyq/mi1UmATHOe8cThSvB9++IHHH3+cUChE69atWb16Nb179/Y7LBGRKvfEE08wevRoBg8ezP/93/8xc+ZMevToQUpKSl6d3bt3k5SUxAMPPECvXr2YN28eH374IePGjWPdunWMHDmywDEHDRrEv//9bz7++GOee+45EhISSE5OpmfPnuzfv7+KP2Et5JwL5CumRUeXmemkGJ988olr27atq1Onjvv000/9DkdEapCvvvrK7xAqXPPmzd2YMWOOKT9w4IBzzrlQKOQuuugi17ZtW7d58+Yij/HOO+/kfd22bVt38803H1Pnk08+cfXr13eDBg2qmMBruNK+l4Blrpx5QGBbcMy8lxQUCoV47LHHuOiii4iKimLJkiWcd955foclIuKrw4cPFzknS4Pwej/z5s0jLS2NF198kXbt2hV5jMsvv7zU8yQlJTF+/HhSU1MLdGlJxQtsghMVBfXq+R1F9TN8+HDuvfderr76ar788kt++ctf+h2SiIjvLrjgAqZNm8bbb79d5PY33niDjh070rNnz+M+17XXXotzjgULFhz3saR4gU1wpCAXXlR1+PDhTJs2jVmzZmm5BRGpUEW1nPfr55XNm/dT2dSpXln+ISs7d3plP/tZwf3POccrX778p7KUFK8s3/CYAtvLY/LkyTRv3pz+/fvTrVs33nrrrQLb16xZQ7du5Vrz8RitW7emUaNGbNy4sUKOJ0VTghNwR48e5c4778yb0+biiy/mhhtu0CykIiL5JCYmsnLlSu69916+/vprrrzySrp37853330HeAuMFv6jcOrUqdSpUyfvddZZZ0V8vgYNGvDjjz9W6GeQggKb4IRC3lINtdnGjRu54IILmDRpEgcOHMhrxRERqQzOea/85s3zyvr1+6ls5EivbOrUn8p+9jOvbOfOgvsvX+6Vn3POT2UpKV5Z/hac/NvLq3HjxjzyyCNs27aNu+66iyVLlnDxxRdz+PBh4uPjycjIKFB/wIABrFixghUrVtC3b1+yyzB9fkZGBk2aNDn+oKVYgV6LqjZ79dVX+d3vfkd0dDRz5szhqquu8jskEZEaoVGjRkyYMIH27dszatQo3nzzTTp16sSKFSsK1DvxxBM58cQTAS85itTGjRs5ePAgXbt2rdC4paDAtuBER9femYy3b9/O8OHD6dKlCytWrFByIyJSDkOGDAFg27Zt9OvXjzVr1rD8eAf7ANOmTSM+Pp4+ffoc97GkeIFNcKD2PSa+fft2wBvAtmjRIhYtWkTbtm19jkpEpHpLT0/nvffeO6Y89zHuDh06cNVVV9G5c2duuOEG9u3bV+5zvfPOO0yaNImHHnqoTK0+UnaBTnBqC+cczz77LB06dMibVvz888+nTp3A9kCKiFSYQ4cO0bdvX0aPHs3777/P8uXLmTVrFoMHD+b000+nX79+xMTEMGfOHPbu3UvXrl156qmn+Pjjj/niiy+YNGkSs2fPJiqq4C117969rF69mmXLlvH6668zcOBArrzySu655x5uu+02nz5t7WFBHXha76REd+jbDURH+x1J5fr+++8ZPnw4//jHP7j88suZPn06zZs39zssEQmwtWvX0qlTJ7/DqDDOOaZOncpLL73EN998w4EDB2jdujX9+/fnrrvuomnTpnl1MzIymDRpEnPnzuWbb74hFAqRmJhI3759GTVqFK1atQK8tai2bt0KQFxcHG3atKFHjx6MGjVKY2/yKe17ycyWO+fK9Xx+YBOcugleghPkRoy0tDQGDx7M7t27eeKJJ7jtttv0+LeIVLqgJTjin8pMcAJ7+4+K8l5BtmPHDuLi4li6dClnn3223+GIiIhUG4FNAcyCmeBs3749b4bNQYMGsWrVKiU3IiIihQQwBQiut99+m7POOosRI0Zw8OBBAGJjY32OSkREpPoJbIJT1IyaNdXhw4e55ZZb6N+/P+3ateOTTz7JW+FWREREjhXYMTihkJfg1PQxt0eOHCEpKYkVK1Zwxx138Nhjj1FPy6SLiIiUKLAtODU9sclVr149BgwYwDvvvMNTTz2l5EZERCQCgU1wavJTVPv37+faa68lLS0NgHvvvZfLL7/c56hERERqjhqaAgTX559/zi9+8QtmzZrFqlWr/A5HRESkRlKCU02EQiGefPJJfvWrX5Gdnc3ixYu5+eab/Q5LRESkRgpsgpOT43cEZTN79mzGjh3LFVdcwYoVK7jgggv8DklERKTGCuxTVDXFvn37OPHEE/ntb39LbGwsv/71r7XcgoiIyHEKbAtOdV9kMysri3HjxpGYmMiOHTuIioqif//+Sm5EREQqgFpwfLB582YGDx7M0qVLGTlyJE2aNPE7JBGRWqtbt24sX768QNnEiRO58847SU5O5ocffuCtt94iJSWFN954g9WrVwOQkpLCgw8+WOQx58+fz2WXXQZAcnIyW7ZsYdGiRcXGsHPnTvbv319qrK1atcqb6HXPnj3s2bOnwPY2bdpQv359tmzZQvv27UlLSyM7O5tLLrmEzZs3065du2KPfeaZZ3LOOefw0ksvlRhDUectrFGjRpx88smlfp7KpASnis2ePZsRI0ZgZsyePZsBAwb4HZKISK321ltvcfjw4bz3PXr0iHjfZs2a5U3pkV/r1q3LFMOYMWN47bXXSq03d+5c+vfvD8DTTz/NI488UmD7hx9+WKb480tPT6d58+al1ivqvIVdf/31pSZKlS2wCU4o5HcERZs7dy6nn346s2bNKjGTFhGRqtGqVasC7+vUifzWGB0dzWmnnVagLCMjg+3btxd4X5rU1FRSU1OZM2cO3bp1o23btnnbPvroI+Li4jj33HML7POnP/2JP/3pTwB5LTbltW7dOtLT00lPT4+o/s9//nM2btxY7vNVhcAmONVpHarVq1dTt25dEhMT+etf/0q9evWIiYnxOywREQF27dpVoAUnOzu7wPbNmzfz3HPP8dlnn0V0vNdff50RI0YUKOvevXtE+w4cOJDnn3+eG2+8Ma9s/PjxdOrU6ZgEpyI988wzNGnShFdffZWhQ4fSq1evEuvn5OSwY8eOYrc3adKE+vXrV3SYZRLYBKc6zGLsnGPKlCnccccd9OjRg/nz52uRTBGRambgwIEsXry42O3ffPMNzz33HHv27OGkk04q9Xg33nhjgQQldwxOJOrVq8fRo0cLlGVmZhaZLOzfvz9v3M6uXbvyyufNm1di8lHY/PnzmTJlCq+++ipr1qzhmmuuIS0tjc6dOxe7z5YtW0rshps+fTrJyckRx1AZApvg+P0w0r59+xgxYgRz5syhd+/evvdFiohUpnbj3vU7BAC2PF6+ZW1KGjPSs2fPAoOM88vJycnrqsnOzubgwYPs3r2bTZs2sXPnTh5//PEyxVFcgnPCCSccU/epp54qcpDzww8/HFFXk3OOF198kVtuuYXbbruNa665huzsbNasWcOll17KzJkzi23JURdVLbVhwwZ69erFzp07mThxImPGjCGqOjQpiYhIkY4ePcru3bvJyMhg3759bN68OaIBt3v27KFjx45572NjY2nevDnt2rUjKSkp4vNv3LiR7OxsoqOj2bVrV4Hk4eDBg/z444+sW7eOpk2bFoirTZs2rFmzJu99XFwcn332WaljclJTU3n00UdZu3YtKSkpjB8/HvDGH6WmpjJq1Ch69+7NkCFDGDt2LF26dIn4s1QXgU1w/ByD06ZNG84++2xef/11zjvvPP8CERGpIuVtOakuZs2axaxZs4iKiqJFixYkJiYyevToEve57777GDduHABmRp06dYgu5yRs559/Pt9//z0A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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=(8, 6))\n", "plt.plot(fpr, tpr, \"b:\", linewidth=2, label=\"SGD\")\n", "plot_roc_curve(fpr_forest, tpr_forest, \"랜덤 포레스트\")\n", "plt.legend(loc=\"lower right\", fontsize=16)\n", "save_fig(\"roc_curve_comparison_plot\")\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.9928250745111685" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "roc_auc_score(y_train_5, y_scores_forest)" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.9870386643233744" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y_train_pred_forest = cross_val_predict(forest_clf, X_train, y_train_5, cv=3)\n", "precision_score(y_train_5, y_train_pred_forest)" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.8288138719793396" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "recall_score(y_train_5, y_train_pred_forest)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 다중 분류" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n" ] }, { "data": { "text/plain": [ "array([9])" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sgd_clf.fit(X_train, y_train)\n", "sgd_clf.predict([some_digit])" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[-780634.17445014, -367988.10902669, -857510.2219226 ,\n", " -109587.17435534, -6978.239532 , -120352.38122307,\n", " -785831.32198027, -377771.38059503, -198143.6559996 ,\n", " 107815.22648992]])" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "some_digit_scores = sgd_clf.decision_function([some_digit])\n", "some_digit_scores" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "9" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.argmax(some_digit_scores)" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sgd_clf.classes_" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sgd_clf.classes_[5]" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n" ] }, { "data": { "text/plain": [ "array([4])" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.multiclass import OneVsOneClassifier\n", "ovo_clf = OneVsOneClassifier(SGDClassifier(max_iter=5, random_state=42))\n", "ovo_clf.fit(X_train, y_train)\n", "ovo_clf.predict([some_digit])" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "45" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(ovo_clf.estimators_)" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([9])" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "forest_clf.fit(X_train, y_train)\n", "forest_clf.predict([some_digit])" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[0. , 0. , 0. , 0. , 0.1, 0. , 0. , 0. , 0. , 0.9]])" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "forest_clf.predict_proba([some_digit])" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n" ] }, { "data": { "text/plain": [ "array([0.87217556, 0.87109355, 0.83892584])" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cross_val_score(sgd_clf, X_train, y_train, cv=3, scoring=\"accuracy\")" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n" ] }, { "data": { "text/plain": [ "array([0.91106779, 0.9080454 , 0.90888633])" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.preprocessing import StandardScaler\n", "scaler = StandardScaler()\n", "X_train_scaled = scaler.fit_transform(X_train.astype(np.float64))\n", "cross_val_score(sgd_clf, X_train_scaled, y_train, cv=3, scoring=\"accuracy\")" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n", "/home/haesun/anaconda3/envs/handson-ml/lib/python3.7/site-packages/sklearn/linear_model/stochastic_gradient.py:561: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.\n", " ConvergenceWarning)\n" ] }, { "data": { "text/plain": [ "array([[5741, 2, 22, 11, 11, 40, 48, 7, 39, 2],\n", " [ 2, 6457, 49, 28, 6, 45, 9, 11, 125, 10],\n", " [ 55, 35, 5323, 98, 79, 24, 104, 62, 162, 16],\n", " [ 47, 40, 140, 5314, 3, 254, 34, 57, 141, 101],\n", " [ 19, 25, 41, 9, 5360, 10, 56, 36, 77, 209],\n", " [ 76, 39, 30, 174, 76, 4610, 110, 29, 168, 109],\n", " [ 36, 20, 42, 2, 39, 89, 5632, 7, 50, 1],\n", " [ 23, 19, 61, 26, 54, 11, 7, 5826, 14, 224],\n", " [ 56, 149, 78, 143, 12, 163, 56, 27, 5012, 155],\n", " [ 46, 30, 26, 83, 160, 35, 3, 207, 74, 5285]])" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y_train_pred = cross_val_predict(sgd_clf, X_train_scaled, y_train, cv=3)\n", "conf_mx = confusion_matrix(y_train, y_train_pred)\n", "conf_mx" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [], "source": [ "def plot_confusion_matrix(matrix):\n", " \"\"\"컬러 오차 행렬을 원할 경우\"\"\"\n", " fig = plt.figure(figsize=(8,8))\n", " ax = fig.add_subplot(111)\n", " cax = ax.matshow(matrix)\n", " fig.colorbar(cax)" ] }, { "cell_type": "code", "execution_count": 68, "metadata": { "scrolled": true }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.matshow(conf_mx, cmap=plt.cm.gray)\n", "save_fig(\"confusion_matrix_plot\", tight_layout=False)\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [], "source": [ "row_sums = conf_mx.sum(axis=1, keepdims=True)\n", "norm_conf_mx = conf_mx / row_sums" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "np.fill_diagonal(norm_conf_mx, 0)\n", "plt.matshow(norm_conf_mx, cmap=plt.cm.gray)\n", "save_fig(\"confusion_matrix_errors_plot\", tight_layout=False)\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAI3CAYAAAB9FJogAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAIABJREFUeJzsnXmgjOX7xj+KispSoUSlRUpCKlLfQhstJJESUZaKFku2Ni1IZakIJVpsZU3KkuWISslSJIkSSkJkOXZ+f8zvet45c+YcM+fMdubcn38Osz4z877P+zzXfd33nefIkSMYhmEYhmEkK8fEewCGYRiGYRjRxBY7hmEYhmEkNbbYMQzDMAwjqbHFjmEYhmEYSY0tdgzDMAzDSGpssWMYhmEYRlJjix3DMAzDMJIaW+wYhmEYhpHU2GLHMAzDMIykxhY7hmEYhmEkNXnjPYAArHeFYSQveeI9gP/H5hnDSF6CzjOm7BiGYRiGkdTYYscwDMMwjKTGFjuGYRiGYSQ1ttgxDMMwDCOpscWOYRiGYRhJTaJlY2WL7t27A/D8889TvXr1NPddd911QR+bqPzyyy8AfPzxxwAMHToUgHXr1mX4nMKFC9O+fXsAbrnlFgAqV64czWEmPZMmTQJg5syZ7rZhw4YB3jFVt25dihQpAsBtt90GwIknnhjLYRpGxBk+fDgADz74IABPPvkkAO3atXOP6dOnDwB58qRPgOnQoQMAxYsXj+o4DSMUTNkxDMMwDCOpyXPkSEKVnMjWYPyVnVB47rnn0jwvkahUqRIAP/zwQ5aef8cddwDw1FNPAZFVeLZv3w7AN998k+b2lJQU/vrrr6DP2b9/v1Op7rvvPgDuuusuAI477jgA8uXLxw033BCxcWaFvXv3AjB48GAAnn32WQB27doVdPcqdB7pM3344YcAHH/88VEba6isXLkSgLfeeguAcePGAbBx48Z0j5Ui+sILLwDwv//9L5JDSao6O5deeinLli076uOKFi0KwKxZswAoX758JN4+6hxzjG8vHMpxH+wxF198MUBI31FuYd++fQAcPHgQ8L7j33//HYARI0Y45XjTpk3pnt+1a9c0/z/11FMBT0VLdEaMGAHA3Llzj/rYu+++GyAr1wSrs2MYhmEYRu4jVys7Ys6cOQDpfD7xYtWqVdSsWRMgQ6UkVAoWLAh4u8pIKDyK3Ste709mO72jPebYY491foBXXnkl2+PMCjqGXnzxxTS3HzlyxI1Xfpy8eX2Wt//++y/dZ1q7di0ApUqVivaQj8pVV10FwLfffpvmdv/PFIjUtlq1arnd2EknnZTdoSSFsrN8+XIARo4cyXvvvQcE34UHIoVHivIjjzySnWFEHe2spQRq7pCaAJ5SEWynLk/b7NmzozpOfw4ePOiUTP1OGzZsAGDHjh0AjB071j3mtNNOA7z58dJLL43a2EaPHu3mNc0POiZWr14d0msEzjMXXHAB4Hk8E4H9+/cDvusY+L7bKVOmALB48WIAUlNTAd+cD3D48GH27NmT5nWkjisSEAZB55mkWuyIYGEpnYwpKSkZPi9RFj1jx451E42oV68eAFdeeSUtWrRIc9+WLVsA6NGjh7swBVK4cGEA/v3332yPTwuBkSNHAt6FsX79+mG9zqJFiwBP5v7jjz/cfV26dEnzXjopos3pp58OQLFixQBvMvS/MEme10Q1d+5c3n33XQBmzJgBQMuWLQEvHBZPrrzySgC+//77NLcXKFCABg0aAN55oWNJk9GRI0d46KGHABg4cCCQ+UL2KCTFYscffU+HDx8Oev/y5cupVq0aAIUKFQJg8uTJQMRDhBFHYU4dE+eccw4AJ598snuMFjI33nhjhs/XuRRJdN366aefAG9B9uabb7Jt2zbAOz9vvvlmwPv+a9as6RapuggrEeH222+P+FhFnjx50p07mm/8v1Oh40YLypNOOol33nnHvRbEf7GjBeUXX3zBwoULAW8+130Al112GQC33norAE888QQAp5xyCuALsbdp0waAtm3bAt414Mwzzwx3WBbGMgzDMAwj95GUyk4o1KhRI53KI0VHCk+82LNnDz169AA8o7HkVakowTh48CBNmzYFYMyYMWnuk1E2UCpMBGQKHjt2rDMES+YdNWoUAPfcc09MxiLpVTsuhQGPho6defPmAfDYY48B0K9fvwiPMHy2bt0KwOOPPw5A1apVAW8HFQypdBMnTnS3afeo3WQWSDplJyOkGPTo0cOFD99++22AdMpsTkRm986dOwOewnX22WcDPvVKCqhMuJFiz549TvF9+eWXAU/FadCggTt2a9SokeZ5Uki6du3q5sdevXoBcP/990d0jME444wzXEmQ2rVrA965WLJkyQyft3nz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GEZSY4sdwzAMwzCSGlvsGIZhGIaR1NhixzAMwzCMpMYWO4ZhGIZhJDW22DEMwzAMI6mxxY5hGIZhGEmNLXYMwzAMw0hqbLFjGIZhGEZSkzfeAzByPurK27NnTz744AMAtmzZAsDKlSvd40477TQA/ve//wFQtmxZAH7++WcAvv/+e/daixYtAuCiiy4CoECBAlH9DOGgrvOpqanuNnW/Pv744+MyJiPxSUlJAaB69erp7vv0008BWLVqFQAdOnSIyZj27dsHeMfv999/D0CxYsWoX79+hs+rXbs2ALVq1QIgX7580RymYWQbU3YMwzAMw0hqcnTXc+2U9Pf5558P6820w7ruuusA6N69e1jPjwWHDx8G4MCBAwCsW7eODz/8EIBff/0VgDFjxgDw0EMPUbNmTQDq1KkDQL9+/QB4/PHHAcifP3/ExyiFI5iKI4Un2G2bN28GPPUmNTXVqT39+/dPc9/u3bu58847Iz72jJgyZQoACxYsSHffkCFDANi6dau7bf369QCceeaZMRhdeOizaIxSDfbu3eseo3kgT570DYNfeuklAIoUKQJA1apVAahUqVK4Q8l1Xc+HDBnCt99+C8Do0aMBOO6449I9Tr+FzvPXXnsNgPbt28dimLz11lsAPPXUUwD8999/IT3vscceA7zz1QiNCRMmADBu3DjAOzaaN2/OSSedBED58uUBuPLKKwEoXbo0BQsWjPVQcyLW9dwwDMMwjNxHjlN2/FUc/TtSSOmZM2dORF83XMaMGcPSpUsB2LRpEwDvv/9+tl5zxIgRANxzzz1Bd++JzkUXXeR+n0GDBkXkNQ8dOgT4fAtt27YFPP+QVJC//vorpNdKVGXn33//dSqfvEbByEzZCeSMM84AfEqedqEhkigHXsQnPak3v/zyCwBdunQBfOdv4BxbokQJAG688UZ3m9TRsWPHAtCgQQMAPvroo0gPNVOkMM2ePZtPPvkEIN08u3//fv744480t3Xq1AmAl19+OfqDTAJKly4NkO57zIzy5cs7Ja1p06ZA4nilpk2b5n77Sy+9FIBly5a5+xs1agTA2WefDXheryhhyo5hGIZhGLmPHKPsyE8zd+5cIP1uI5I899xzMfXvyJezbds2ANq0acPHH38clffasWNHuLvxuKLY9l133UXr1q2ByCk78qI8++yzR33smWeeSd68vuTFYLux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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "cl_a, cl_b = 3, 5\n", "X_aa = X_train[(y_train == cl_a) & (y_train_pred == cl_a)]\n", "X_ab = X_train[(y_train == cl_a) & (y_train_pred == cl_b)]\n", "X_ba = X_train[(y_train == cl_b) & (y_train_pred == cl_a)]\n", "X_bb = X_train[(y_train == cl_b) & (y_train_pred == cl_b)]\n", "\n", "plt.figure(figsize=(8,8))\n", "plt.subplot(221); plot_digits(X_aa[:25], images_per_row=5)\n", "plt.subplot(222); plot_digits(X_ab[:25], images_per_row=5)\n", "plt.subplot(223); plot_digits(X_ba[:25], images_per_row=5)\n", "plt.subplot(224); plot_digits(X_bb[:25], images_per_row=5)\n", "save_fig(\"error_analysis_digits_plot\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 다중 레이블 분류" ] }, { "cell_type": "code", "execution_count": 72, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n", " metric_params=None, n_jobs=None, n_neighbors=5, p=2,\n", " weights='uniform')" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.neighbors import KNeighborsClassifier\n", "\n", "y_train_large = (y_train >= 7)\n", "y_train_odd = (y_train % 2 == 1)\n", "y_multilabel = np.c_[y_train_large, y_train_odd]\n", "\n", "knn_clf = KNeighborsClassifier()\n", "knn_clf.fit(X_train, y_multilabel)" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ True, True]])" ] }, "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ "knn_clf.predict([some_digit])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**경고**: 다음 셀은 실행하는데 매우 오래 걸립니다(하드웨어에 따라 몇 시간이 걸릴 수 있습니다)." ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.9768224011622285" ] }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y_train_knn_pred = cross_val_predict(knn_clf, X_train, y_multilabel, cv=3, n_jobs=-1)\n", "f1_score(y_multilabel, y_train_knn_pred, average=\"macro\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 다중 출력 분류" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [], "source": [ "noise = np.random.randint(0, 100, (len(X_train), 784))\n", "X_train_mod = X_train + noise\n", "noise = np.random.randint(0, 100, (len(X_test), 784))\n", "X_test_mod = X_test + noise\n", "y_train_mod = X_train\n", "y_test_mod = X_test" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "some_index = 5500\n", "plt.subplot(121); plot_digit(X_test_mod[some_index])\n", "plt.subplot(122); plot_digit(y_test_mod[some_index])\n", "save_fig(\"noisy_digit_example_plot\")\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "knn_clf.fit(X_train_mod, y_train_mod)\n", "clean_digit = knn_clf.predict([X_test_mod[some_index]])\n", "plot_digit(clean_digit)\n", "save_fig(\"cleaned_digit_example_plot\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 추가 내용" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 더미 (즉, 랜덤) 분류기" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [], "source": [ "from sklearn.dummy import DummyClassifier\n", "dmy_clf = DummyClassifier()\n", "y_probas_dmy = cross_val_predict(dmy_clf, X_train, y_train_5, cv=3, method=\"predict_proba\")\n", "y_scores_dmy = y_probas_dmy[:, 1]" ] }, { "cell_type": "code", "execution_count": 79, "metadata": { "scrolled": true }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "fprr, tprr, thresholdsr = roc_curve(y_train_5, y_scores_dmy)\n", "plot_roc_curve(fprr, tprr)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## KNN 분류기" ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n", " metric_params=None, n_jobs=-1, n_neighbors=4, p=2,\n", " weights='distance')" ] }, "execution_count": 80, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.neighbors import KNeighborsClassifier\n", "knn_clf = KNeighborsClassifier(n_jobs=-1, weights='distance', n_neighbors=4)\n", "knn_clf.fit(X_train, y_train)" ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [], "source": [ "y_knn_pred = knn_clf.predict(X_test)" ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.9714" ] }, "execution_count": 82, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.metrics import accuracy_score\n", "accuracy_score(y_test, y_knn_pred)" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "from scipy.ndimage.interpolation import shift\n", "def shift_digit(digit_array, dx, dy, new=0):\n", " return shift(digit_array.reshape(28, 28), [dy, dx], cval=new).reshape(784)\n", "\n", "plot_digit(shift_digit(some_digit, 5, 1, new=100))" ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "((300000, 784), (300000,))" ] }, "execution_count": 84, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X_train_expanded = [X_train]\n", "y_train_expanded = [y_train]\n", "for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)):\n", " shifted_images = np.apply_along_axis(shift_digit, axis=1, arr=X_train, dx=dx, dy=dy)\n", " X_train_expanded.append(shifted_images)\n", " y_train_expanded.append(y_train)\n", "\n", "X_train_expanded = np.concatenate(X_train_expanded)\n", "y_train_expanded = np.concatenate(y_train_expanded)\n", "X_train_expanded.shape, y_train_expanded.shape" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n", " metric_params=None, n_jobs=-1, n_neighbors=4, p=2,\n", " weights='distance')" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "knn_clf.fit(X_train_expanded, y_train_expanded)" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [], "source": [ "y_knn_expanded_pred = knn_clf.predict(X_test)" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.9763" ] }, "execution_count": 87, "metadata": {}, "output_type": "execute_result" } ], "source": [ "accuracy_score(y_test, y_knn_expanded_pred)" ] }, { "cell_type": "code", "execution_count": 88, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[0.24579675, 0. , 0. , 0. , 0. ,\n", " 0. , 0. , 0. , 0. , 0.75420325]])" ] }, "execution_count": 88, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ambiguous_digit = X_test[2589]\n", "knn_clf.predict_proba([ambiguous_digit])" ] }, { "cell_type": "code", "execution_count": 89, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPwAAAD7CAYAAABOrvnfAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAABzRJREFUeJzt3b2PjP8exnF7Iise1iIUGgWNh0iE5kd2KzZWCH+AjkJF4SEUChFCaAgiEQSV0Gwjgo5ShGQLFAoP2SgURMMGe4qTcyI55jPZmV3LXq9X6co990S8cxdfM9MxMjIyBcjwr4l+A8DvI3gIIngIIngIIngIIngIMnUC7ukcEMZfx6/+0BMegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegggegkyd6DfAfwwNDZX7hg0byv358+ct37u/v7/ce3t7y33//v3l3tnZOer3xPjwhIcggocggocggocggocggocgHSMjI7/7nr/9hn+CW7dulfvx48fLfXBwcCzfzqg0+zfS1dVV7h0dHQ235cuXl9ceOnSo3Ldt21buwX75l+4JD0EED0EED0EED0EED0EED0EED0Gcw4+RY8eOtbUPDw+3df+enp6G25IlS9p67WvXrpV7dc7ermnTppX7wYMHy33Hjh0Nt0WLFrX0nv4SzuEhneAhiOAhiOAhiOAhiOAhiOAhiHP4MbJs2bJyf/nyZVuvv3Xr1nK/fv16w627u7ute+/du7fcz5w50/Jr9/X1lfvjx4/L/ePHj+W+atWqhtvAwEB57V9+Tu8cHtIJHoIIHoIIHoIIHoIIHoIIHoL4uehROHv2bMPt9evXbb12s+9Xv3r1arm3e9ZeWbBgQVvXb968ueHW7Pv6d+7cWe43b94s92fPnjXcmv2dHjlypNz/Rp7wEETwEETwEETwEETwEETwEETwEMQ5/E+afT66+q3yr1+/lteuWbOm3K9cuVLuc+fOLffx9Pbt27aunz9/fsNt+vTp5bXnz58v92bfM/D06dOGm3N4YFITPAQRPAQRPAQRPAQRPARxLPeTd+/elXuzo7dKs2O1efPmtfza4+3ixYvl3uznordv397yvZv9vezevbvcq5+L/vDhQ3nt3bt3y33Tpk3l/ifyhIcggocggocggocggocggocggocgzuFp+lXRzTT7yed169a19fqV5cuXt3ztly9fyv3Vq1ctv/afyhMegggegggegggegggegggegggegjiHD/Dp06dyP336dFuvv3///nKfMWNGW69faec7ChJ5wkMQwUMQwUMQwUMQwUMQwUMQwUMQ5/CTRHXWvmHDhvLaJ0+etHXvf/75p63r23H06NGWr+3u7i738fwc/0TxhIcggocggocggocggocggocggocgzuF/smbNmnKfNWtWw+3z58/ltQ8ePCj3Zr+xPpGa/U56V1fXb3on/+/Hjx/lPjIy0nCbOXNmee3q1atbek9/Mk94CCJ4CCJ4CCJ4CCJ4CCJ4COJY7idr164t9zt37jTctm3bVl778ePHlt7TWJg2bVq53759u9z7+/vH8u2MyokTJ8r90aNH5V4dd07Gj7824wkPQQQPQQQPQQQPQQQPQQQPQQQPQZzDj0Jvb2/DbdeuXeW179+/L/d79+6V+9KlS8t95cqVDbdDhw6V1y5cuLDcJ9LAwEC5f/v2rdyrr6Les2dPS+/pb+YJD0EED0EED0EED0EED0EED0EED0Gcw4+RZp/bbubt27flPmfOnHKfyK+KbubNmzcNtxs3bpTXDg4OtnXvvr6+hltPT09br/038oSHIIKHIIKHIIKHIIKHIIKHIIKHIB3Vz+mOk99+Q8ZXs/9DcOHChYbbqVOn2rr3ihUryv3hw4cNt7lz57Z17z/cL7+Q3xMegggegggegggegggegggegvh4LE0NDQ2V+5YtW8q9nY+4Njt2O3z4cLlP8qO3UfOEhyCChyCChyCChyCChyCChyCChyA+Hhvg+/fv5X7u3Llyv3TpUrm/ePFi1O/pv2bPnl3ujx49KvfqZ7LD+XgspBM8BBE8BBE8BBE8BBE8BBE8BPF5+EmiOmuvviZ6ypQpU/bu3Vvuzf6vRkfHL498/2fmzJkNt8uXL5fXOmcfW57wEETwEETwEETwEETwEETwEETwEMTn4SeJ6rvjFy9eXF47PDxc7s3+jWzcuLHcDxw40HBbv359eS0t83l4SCd4CCJ4CCJ4CCJ4CCJ4CCJ4COIcPsD9+/fL/eTJk+Xe19dX7vv27Sv3zs7OcmdcOIeHdIKHIIKHIIKHIIKHIIKHII7lYHJyLAfpBA9BBA9BBA9BBA9BBA9BBA9BBA9BBA9BBA9BBA9BBA9BBA9BBA9BBA9Bpk7APX/5OV1g/HnCQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQxDBQ5B/AzMDI6iR7uoPAAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plot_digit(ambiguous_digit)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# 연습문제 해답" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. 97% 정확도의 MNIST 분류기" ] }, { "cell_type": "code", "execution_count": 90, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Fitting 5 folds for each of 6 candidates, totalling 30 fits\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[Parallel(n_jobs=-1)]: Using backend LokyBackend with 4 concurrent workers.\n", "[Parallel(n_jobs=-1)]: Done 30 out of 30 | elapsed: 122.9min finished\n" ] }, { "data": { "text/plain": [ "GridSearchCV(cv=5, error_score='raise-deprecating',\n", " estimator=KNeighborsClassifier(algorithm='auto', leaf_size=30,\n", " metric='minkowski',\n", " metric_params=None, n_jobs=None,\n", " n_neighbors=5, p=2,\n", " weights='uniform'),\n", " iid='warn', n_jobs=-1,\n", " param_grid=[{'n_neighbors': [3, 4, 5],\n", " 'weights': ['uniform', 'distance']}],\n", " pre_dispatch='2*n_jobs', refit=True, return_train_score=False,\n", " scoring=None, verbose=3)" ] }, "execution_count": 90, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.model_selection import GridSearchCV\n", "\n", "param_grid = [{'weights': [\"uniform\", \"distance\"], 'n_neighbors': [3, 4, 5]}]\n", "\n", "knn_clf = KNeighborsClassifier()\n", "grid_search = GridSearchCV(knn_clf, param_grid, cv=5, verbose=3, n_jobs=-1)\n", "grid_search.fit(X_train, y_train)" ] }, { "cell_type": "code", "execution_count": 91, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'n_neighbors': 4, 'weights': 'distance'}" ] }, "execution_count": 91, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grid_search.best_params_" ] }, { "cell_type": "code", "execution_count": 92, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.9731333333333333" ] }, "execution_count": 92, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grid_search.best_score_" ] }, { "cell_type": "code", "execution_count": 93, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.9714" ] }, "execution_count": 93, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.metrics import accuracy_score\n", "\n", "y_pred = grid_search.predict(X_test)\n", "accuracy_score(y_test, y_pred)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. 데이터 증식" ] }, { "cell_type": "code", "execution_count": 94, "metadata": {}, "outputs": [], "source": [ "from scipy.ndimage.interpolation import shift" ] }, { "cell_type": "code", "execution_count": 95, "metadata": {}, "outputs": [], "source": [ "def shift_image(image, dx, dy):\n", " image = image.reshape((28, 28))\n", " shifted_image = shift(image, [dy, dx], cval=0, mode=\"constant\")\n", " return shifted_image.reshape([-1])" ] }, { "cell_type": "code", "execution_count": 96, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "image = X_train[1000]\n", "shifted_image_down = shift_image(image, 0, 5)\n", "shifted_image_left = shift_image(image, -5, 0)\n", "\n", "plt.figure(figsize=(12,3))\n", "plt.subplot(131)\n", "plt.title(\"Original\", fontsize=14)\n", "plt.imshow(image.reshape(28, 28), interpolation=\"nearest\", cmap=\"Greys\")\n", "plt.subplot(132)\n", "plt.title(\"Shifted down\", fontsize=14)\n", "plt.imshow(shifted_image_down.reshape(28, 28), interpolation=\"nearest\", cmap=\"Greys\")\n", "plt.subplot(133)\n", "plt.title(\"Shifted left\", fontsize=14)\n", "plt.imshow(shifted_image_left.reshape(28, 28), interpolation=\"nearest\", cmap=\"Greys\")\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 97, "metadata": {}, "outputs": [], "source": [ "X_train_augmented = [image for image in X_train]\n", "y_train_augmented = [label for label in y_train]\n", "\n", "for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)):\n", " for image, label in zip(X_train, y_train):\n", " X_train_augmented.append(shift_image(image, dx, dy))\n", " y_train_augmented.append(label)\n", "\n", "X_train_augmented = np.array(X_train_augmented)\n", "y_train_augmented = np.array(y_train_augmented)" ] }, { "cell_type": "code", "execution_count": 98, "metadata": {}, "outputs": [], "source": [ "shuffle_idx = np.random.permutation(len(X_train_augmented))\n", "X_train_augmented = X_train_augmented[shuffle_idx]\n", "y_train_augmented = y_train_augmented[shuffle_idx]" ] }, { "cell_type": "code", "execution_count": 99, "metadata": {}, "outputs": [], "source": [ "knn_clf = KNeighborsClassifier(**grid_search.best_params_)" ] }, { "cell_type": "code", "execution_count": 100, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n", " metric_params=None, n_jobs=None, n_neighbors=4, p=2,\n", " weights='distance')" ] }, "execution_count": 100, "metadata": {}, "output_type": "execute_result" } ], "source": [ "knn_clf.fit(X_train_augmented, y_train_augmented)" ] }, { "cell_type": "code", "execution_count": 101, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.9763" ] }, "execution_count": 101, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y_pred = knn_clf.predict(X_test)\n", "accuracy_score(y_test, y_pred)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "간단한 데이터 증식으로 0.5%의 정확도가 향상되었습니다. :)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. 타이타닉 데이터셋에 도전" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "승객의 나이, 성별, 승객 등급, 승선 위치 같은 속성을 기반으로 하여 승객의 생존 여부를 예측하는 것이 목표입니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "먼저 [캐글](https://www.kaggle.com)에 로그인 하고 [타이타닉 챌린지](https://www.kaggle.com/c/titanic)에서 `train.csv`와 `test.csv`를 다운로드합니다. 두 파일을 `datasets/titanic` 디렉토리에 저장하세요." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "그다음 데이터를 적재합니다:" ] }, { "cell_type": "code", "execution_count": 102, "metadata": {}, "outputs": [], "source": [ "import os\n", "\n", "TITANIC_PATH = os.path.join(\"datasets\", \"titanic\")" ] }, { "cell_type": "code", "execution_count": 103, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "\n", "def load_titanic_data(filename, titanic_path=TITANIC_PATH):\n", " csv_path = os.path.join(titanic_path, filename)\n", " return pd.read_csv(csv_path)" ] }, { "cell_type": "code", "execution_count": 104, "metadata": {}, "outputs": [], "source": [ "train_data = load_titanic_data(\"train.csv\")\n", "test_data = load_titanic_data(\"test.csv\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "데이터는 이미 훈련 세트와 테스트 세트로 분리되어 있습니다. 그러나 테스트 데이터는 레이블을 가지고 있지 않습니다: 훈련 데이터를 이용하여 가능한 최고의 모델을 만들고 테스트 데이터에 대한 예측을 캐글(Kaggle)에 업로드하여 최종 점수를 확인하는 것이 목표입니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "훈련 세트에서 맨 위 몇 개의 열을 살펴 보겠습니다:" ] }, { "cell_type": "code", "execution_count": 105, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
PassengerIdSurvivedPclassNameSexAgeSibSpParchTicketFareCabinEmbarked
0103Braund, Mr. Owen Harrismale22.010A/5 211717.2500NaNS
1211Cumings, Mrs. John Bradley (Florence Briggs Th...female38.010PC 1759971.2833C85C
2313Heikkinen, Miss. Lainafemale26.000STON/O2. 31012827.9250NaNS
3411Futrelle, Mrs. Jacques Heath (Lily May Peel)female35.01011380353.1000C123S
4503Allen, Mr. William Henrymale35.0003734508.0500NaNS
\n", "
" ], "text/plain": [ " PassengerId Survived Pclass \\\n", "0 1 0 3 \n", "1 2 1 1 \n", "2 3 1 3 \n", "3 4 1 1 \n", "4 5 0 3 \n", "\n", " Name Sex Age SibSp \\\n", "0 Braund, Mr. Owen Harris male 22.0 1 \n", "1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 \n", "2 Heikkinen, Miss. Laina female 26.0 0 \n", "3 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 \n", "4 Allen, Mr. William Henry male 35.0 0 \n", "\n", " Parch Ticket Fare Cabin Embarked \n", "0 0 A/5 21171 7.2500 NaN S \n", "1 0 PC 17599 71.2833 C85 C \n", "2 0 STON/O2. 3101282 7.9250 NaN S \n", "3 0 113803 53.1000 C123 S \n", "4 0 373450 8.0500 NaN S " ] }, "execution_count": 105, "metadata": {}, "output_type": "execute_result" } ], "source": [ "train_data.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "속성은 다음과 같은 의미를 가집니다:\n", "* **Survived**: 타깃입니다. 0은 생존하지 못한 것이고 1은 생존을 의미합니다.\n", "* **Pclass**: 승객 등급. 1, 2, 3등석.\n", "* **Name**, **Sex**, **Age**: 이름 그대로 의미입니다.\n", "* **SibSp**: 함께 탑승한 형제, 배우자의 수.\n", "* **Parch**: 함께 탑승한 자녀, 부모의 수.\n", "* **Ticket**: 티켓 아이디\n", "* **Fare**: 티켓 요금 (파운드)\n", "* **Cabin**: 객실 번호\n", "* **Embarked**: 승객이 탑승한 곳. C(Cherbourg), Q(Queenstown), S(Southampton)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "누락된 데이터가 얼마나 되는지 알아보겠습니다:" ] }, { "cell_type": "code", "execution_count": 106, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 891 entries, 0 to 890\n", "Data columns (total 12 columns):\n", "PassengerId 891 non-null int64\n", "Survived 891 non-null int64\n", "Pclass 891 non-null int64\n", "Name 891 non-null object\n", "Sex 891 non-null object\n", "Age 714 non-null float64\n", "SibSp 891 non-null int64\n", "Parch 891 non-null int64\n", "Ticket 891 non-null object\n", "Fare 891 non-null float64\n", "Cabin 204 non-null object\n", "Embarked 889 non-null object\n", "dtypes: float64(2), int64(5), object(5)\n", "memory usage: 83.6+ KB\n" ] } ], "source": [ "train_data.info()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "괜찮네요. **Age**, **Cabin**, **Embarked** 속성의 일부가 null입니다(891개의 non-null 보다 작습니다). 특히 **Cabin**은 77%가 null입니다. 일단 **Cabin**은 무시하고 나머지를 활용하겠습니다. **Age**는 19%가 null이므로 이를 어떻게 처리할지 결정해야 합니다. null을 중간 나이로 바꾸는 것이 괜찮아 보입니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Name**과 **Ticket** 속성도 값을 가지고 있지만 머신러닝 모델이 사용할 수 있는 숫자로 변환하는 것이 조금 까다롭습니다. 그래서 지금은 이 두 속성을 무시하겠습니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "통계치를 살펴 보겠습니다:" ] }, { "cell_type": "code", "execution_count": 107, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
PassengerIdSurvivedPclassAgeSibSpParchFare
count891.000000891.000000891.000000714.000000891.000000891.000000891.000000
mean446.0000000.3838382.30864229.6991180.5230080.38159432.204208
std257.3538420.4865920.83607114.5264971.1027430.80605749.693429
min1.0000000.0000001.0000000.4200000.0000000.0000000.000000
25%223.5000000.0000002.00000020.1250000.0000000.0000007.910400
50%446.0000000.0000003.00000028.0000000.0000000.00000014.454200
75%668.5000001.0000003.00000038.0000001.0000000.00000031.000000
max891.0000001.0000003.00000080.0000008.0000006.000000512.329200
\n", "
" ], "text/plain": [ " PassengerId Survived Pclass Age SibSp \\\n", "count 891.000000 891.000000 891.000000 714.000000 891.000000 \n", "mean 446.000000 0.383838 2.308642 29.699118 0.523008 \n", "std 257.353842 0.486592 0.836071 14.526497 1.102743 \n", "min 1.000000 0.000000 1.000000 0.420000 0.000000 \n", "25% 223.500000 0.000000 2.000000 20.125000 0.000000 \n", "50% 446.000000 0.000000 3.000000 28.000000 0.000000 \n", "75% 668.500000 1.000000 3.000000 38.000000 1.000000 \n", "max 891.000000 1.000000 3.000000 80.000000 8.000000 \n", "\n", " Parch Fare \n", "count 891.000000 891.000000 \n", "mean 0.381594 32.204208 \n", "std 0.806057 49.693429 \n", "min 0.000000 0.000000 \n", "25% 0.000000 7.910400 \n", "50% 0.000000 14.454200 \n", "75% 0.000000 31.000000 \n", "max 6.000000 512.329200 " ] }, "execution_count": 107, "metadata": {}, "output_type": "execute_result" } ], "source": [ "train_data.describe()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* 이크, 38%만 **Survived**입니다. :( 거의 40%에 가까우므로 정확도를 사용해 모델을 평가해도 괜찮을 것 같습니다.\n", "* 평균 **Fare**는 32.20 파운드라 그렇게 비싸보이지는 않습니다(아마 요금을 많이 반환해 주었기 때문일 것입니다)\n", "* 평균 **Age**는 30보다 작습니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "타깃이 0과 1로 이루어졌는지 확인합니다:" ] }, { "cell_type": "code", "execution_count": 108, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0 549\n", "1 342\n", "Name: Survived, dtype: int64" ] }, "execution_count": 108, "metadata": {}, "output_type": "execute_result" } ], "source": [ "train_data[\"Survived\"].value_counts()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "범주형 특성들을 확인해 보겠습니다:" ] }, { "cell_type": "code", "execution_count": 109, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3 491\n", "1 216\n", "2 184\n", "Name: Pclass, dtype: int64" ] }, "execution_count": 109, "metadata": {}, "output_type": "execute_result" } ], "source": [ "train_data[\"Pclass\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 110, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "male 577\n", "female 314\n", "Name: Sex, dtype: int64" ] }, "execution_count": 110, "metadata": {}, "output_type": "execute_result" } ], "source": [ "train_data[\"Sex\"].value_counts()" ] }, { "cell_type": "code", "execution_count": 111, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "S 644\n", "C 168\n", "Q 77\n", "Name: Embarked, dtype: int64" ] }, "execution_count": 111, "metadata": {}, "output_type": "execute_result" } ], "source": [ "train_data[\"Embarked\"].value_counts()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Embarked** 특성은 승객이 탑승한 곳을 알려 줍니다: C=Cherbourg, Q=Queenstown, S=Southampton." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`CategoricalEncoder` 클래스는 범주형 특성을 원-핫 벡터로 변환시켜 줍니다. 이 클래스는 사이킷런 0.20에 포함될 예정이지만 지금은 아래 코드를 사용합니다([#9151](https://github.com/scikit-learn/scikit-learn/pull/9151) 풀 리퀘스트에서 복사했습니다)." ] }, { "cell_type": "code", "execution_count": 112, "metadata": {}, "outputs": [], "source": [ "# PR #9151에서 가져온 CategoricalEncoder 클래스의 정의.\n", "# 이 클래스는 사이킷런 0.20에 포함될 예정입니다.\n", "# 이 셀을 실행하거나 복사해서 사용하세요. 이 코드를 모두 이해할 필요는 없습니다.\n", "\n", "from sklearn.base import BaseEstimator, TransformerMixin\n", "from sklearn.utils import check_array\n", "from sklearn.preprocessing import LabelEncoder\n", "from scipy import sparse\n", "\n", "class CategoricalEncoder(BaseEstimator, TransformerMixin):\n", " \"\"\"Encode categorical features as a numeric array.\n", " The input to this transformer should be a matrix of integers or strings,\n", " denoting the values taken on by categorical (discrete) features.\n", " The features can be encoded using a one-hot aka one-of-K scheme\n", " (``encoding='onehot'``, the default) or converted to ordinal integers\n", " (``encoding='ordinal'``).\n", " This encoding is needed for feeding categorical data to many scikit-learn\n", " estimators, notably linear models and SVMs with the standard kernels.\n", " Read more in the :ref:`User Guide `.\n", " Parameters\n", " ----------\n", " encoding : str, 'onehot', 'onehot-dense' or 'ordinal'\n", " The type of encoding to use (default is 'onehot'):\n", " - 'onehot': encode the features using a one-hot aka one-of-K scheme\n", " (or also called 'dummy' encoding). This creates a binary column for\n", " each category and returns a sparse matrix.\n", " - 'onehot-dense': the same as 'onehot' but returns a dense array\n", " instead of a sparse matrix.\n", " - 'ordinal': encode the features as ordinal integers. This results in\n", " a single column of integers (0 to n_categories - 1) per feature.\n", " categories : 'auto' or a list of lists/arrays of values.\n", " Categories (unique values) per feature:\n", " - 'auto' : Determine categories automatically from the training data.\n", " - list : ``categories[i]`` holds the categories expected in the ith\n", " column. The passed categories are sorted before encoding the data\n", " (used categories can be found in the ``categories_`` attribute).\n", " dtype : number type, default np.float64\n", " Desired dtype of output.\n", " handle_unknown : 'error' (default) or 'ignore'\n", " Whether to raise an error or ignore if a unknown categorical feature is\n", " present during transform (default is to raise). When this is parameter\n", " is set to 'ignore' and an unknown category is encountered during\n", " transform, the resulting one-hot encoded columns for this feature\n", " will be all zeros.\n", " Ignoring unknown categories is not supported for\n", " ``encoding='ordinal'``.\n", " Attributes\n", " ----------\n", " categories_ : list of arrays\n", " The categories of each feature determined during fitting. When\n", " categories were specified manually, this holds the sorted categories\n", " (in order corresponding with output of `transform`).\n", " Examples\n", " --------\n", " Given a dataset with three features and two samples, we let the encoder\n", " find the maximum value per feature and transform the data to a binary\n", " one-hot encoding.\n", " >>> from sklearn.preprocessing import CategoricalEncoder\n", " >>> enc = CategoricalEncoder(handle_unknown='ignore')\n", " >>> enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]])\n", " ... # doctest: +ELLIPSIS\n", " CategoricalEncoder(categories='auto', dtype=<... 'numpy.float64'>,\n", " encoding='onehot', handle_unknown='ignore')\n", " >>> enc.transform([[0, 1, 1], [1, 0, 4]]).toarray()\n", " array([[ 1., 0., 0., 1., 0., 0., 1., 0., 0.],\n", " [ 0., 1., 1., 0., 0., 0., 0., 0., 0.]])\n", " See also\n", " --------\n", " sklearn.preprocessing.OneHotEncoder : performs a one-hot encoding of\n", " integer ordinal features. The ``OneHotEncoder assumes`` that input\n", " features take on values in the range ``[0, max(feature)]`` instead of\n", " using the unique values.\n", " sklearn.feature_extraction.DictVectorizer : performs a one-hot encoding of\n", " dictionary items (also handles string-valued features).\n", " sklearn.feature_extraction.FeatureHasher : performs an approximate one-hot\n", " encoding of dictionary items or strings.\n", " \"\"\"\n", "\n", " def __init__(self, encoding='onehot', categories='auto', dtype=np.float64,\n", " handle_unknown='error'):\n", " self.encoding = encoding\n", " self.categories = categories\n", " self.dtype = dtype\n", " self.handle_unknown = handle_unknown\n", "\n", " def fit(self, X, y=None):\n", " \"\"\"Fit the CategoricalEncoder to X.\n", " Parameters\n", " ----------\n", " X : array-like, shape [n_samples, n_feature]\n", " The data to determine the categories of each feature.\n", " Returns\n", " -------\n", " self\n", " \"\"\"\n", "\n", " if self.encoding not in ['onehot', 'onehot-dense', 'ordinal']:\n", " template = (\"encoding should be either 'onehot', 'onehot-dense' \"\n", " \"or 'ordinal', got %s\")\n", " raise ValueError(template % self.handle_unknown)\n", "\n", " if self.handle_unknown not in ['error', 'ignore']:\n", " template = (\"handle_unknown should be either 'error' or \"\n", " \"'ignore', got %s\")\n", " raise ValueError(template % self.handle_unknown)\n", "\n", " if self.encoding == 'ordinal' and self.handle_unknown == 'ignore':\n", " raise ValueError(\"handle_unknown='ignore' is not supported for\"\n", " \" encoding='ordinal'\")\n", "\n", " X = check_array(X, dtype=np.object, accept_sparse='csc', copy=True)\n", " n_samples, n_features = X.shape\n", "\n", " self._label_encoders_ = [LabelEncoder() for _ in range(n_features)]\n", "\n", " for i in range(n_features):\n", " le = self._label_encoders_[i]\n", " Xi = X[:, i]\n", " if self.categories == 'auto':\n", " le.fit(Xi)\n", " else:\n", " valid_mask = np.in1d(Xi, self.categories[i])\n", " if not np.all(valid_mask):\n", " if self.handle_unknown == 'error':\n", " diff = np.unique(Xi[~valid_mask])\n", " msg = (\"Found unknown categories {0} in column {1}\"\n", " \" during fit\".format(diff, i))\n", " raise ValueError(msg)\n", " le.classes_ = np.array(np.sort(self.categories[i]))\n", "\n", " self.categories_ = [le.classes_ for le in self._label_encoders_]\n", "\n", " return self\n", "\n", " def transform(self, X):\n", " \"\"\"Transform X using one-hot encoding.\n", " Parameters\n", " ----------\n", " X : array-like, shape [n_samples, n_features]\n", " The data to encode.\n", " Returns\n", " -------\n", " X_out : sparse matrix or a 2-d array\n", " Transformed input.\n", " \"\"\"\n", " X = check_array(X, accept_sparse='csc', dtype=np.object, copy=True)\n", " n_samples, n_features = X.shape\n", " X_int = np.zeros_like(X, dtype=np.int)\n", " X_mask = np.ones_like(X, dtype=np.bool)\n", "\n", " for i in range(n_features):\n", " valid_mask = np.in1d(X[:, i], self.categories_[i])\n", "\n", " if not np.all(valid_mask):\n", " if self.handle_unknown == 'error':\n", " diff = np.unique(X[~valid_mask, i])\n", " msg = (\"Found unknown categories {0} in column {1}\"\n", " \" during transform\".format(diff, i))\n", " raise ValueError(msg)\n", " else:\n", " # Set the problematic rows to an acceptable value and\n", " # continue `The rows are marked `X_mask` and will be\n", " # removed later.\n", " X_mask[:, i] = valid_mask\n", " X[:, i][~valid_mask] = self.categories_[i][0]\n", " X_int[:, i] = self._label_encoders_[i].transform(X[:, i])\n", "\n", " if self.encoding == 'ordinal':\n", " return X_int.astype(self.dtype, copy=False)\n", "\n", " mask = X_mask.ravel()\n", " n_values = [cats.shape[0] for cats in self.categories_]\n", " n_values = np.array([0] + n_values)\n", " indices = np.cumsum(n_values)\n", "\n", " column_indices = (X_int + indices[:-1]).ravel()[mask]\n", " row_indices = np.repeat(np.arange(n_samples, dtype=np.int32),\n", " n_features)[mask]\n", " data = np.ones(n_samples * n_features)[mask]\n", "\n", " out = sparse.csc_matrix((data, (row_indices, column_indices)),\n", " shape=(n_samples, indices[-1]),\n", " dtype=self.dtype).tocsr()\n", " if self.encoding == 'onehot-dense':\n", " return out.toarray()\n", " else:\n", " return out" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이제 전처리 파이프라인을 만듭니다. `DataFrame`으로부터 특정 속성만 선택하기 위해 이전 장에서 만든 `DataframeSelector`를 재사용하겠습니다:" ] }, { "cell_type": "code", "execution_count": 113, "metadata": {}, "outputs": [], "source": [ "from sklearn.base import BaseEstimator, TransformerMixin\n", "\n", "# 사이킷런이 DataFrame을 바로 사용하지 못하므로\n", "# 수치형이나 범주형 컬럼을 선택하는 클래스를 만듭니다.\n", "class DataFrameSelector(BaseEstimator, TransformerMixin):\n", " def __init__(self, attribute_names):\n", " self.attribute_names = attribute_names\n", " def fit(self, X, y=None):\n", " return self\n", " def transform(self, X):\n", " return X[self.attribute_names]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "숫자 특성을 위한 파이프라인을 만듭니다(`Imputer` 클래스는 0.22 버전에서 삭제될 예정입니다. 0.20 버전에서 추가된 `SimpleImputer`를 사용합니다):" ] }, { "cell_type": "code", "execution_count": 114, "metadata": {}, "outputs": [], "source": [ "from sklearn.pipeline import Pipeline\n", "#from sklearn.preprocessing import Imputer\n", "from sklearn.impute import SimpleImputer\n", "\n", "imputer = SimpleImputer(strategy=\"median\")\n", "\n", "num_pipeline = Pipeline([\n", " (\"select_numeric\", DataFrameSelector([\"Age\", \"SibSp\", \"Parch\", \"Fare\"])),\n", " (\"imputer\", SimpleImputer(strategy=\"median\")),\n", " ])" ] }, { "cell_type": "code", "execution_count": 115, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[22. , 1. , 0. , 7.25 ],\n", " [38. , 1. , 0. , 71.2833],\n", " [26. , 0. , 0. , 7.925 ],\n", " ...,\n", " [28. , 1. , 2. , 23.45 ],\n", " [26. , 0. , 0. , 30. ],\n", " [32. , 0. , 0. , 7.75 ]])" ] }, "execution_count": 115, "metadata": {}, "output_type": "execute_result" } ], "source": [ "num_pipeline.fit_transform(train_data)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "문자열로된 범주형 열을 위해 별도의 Imputer 클래스가 필요합니다(일반 `Imputer` 클래스는 이를 처리하지 못합니다):" ] }, { "cell_type": "code", "execution_count": 116, "metadata": {}, "outputs": [], "source": [ "# stackoverflow.com/questions/25239958 에서 착안했습니다\n", "class MostFrequentImputer(BaseEstimator, TransformerMixin):\n", " def fit(self, X, y=None):\n", " self.most_frequent_ = pd.Series([X[c].value_counts().index[0] for c in X],\n", " index=X.columns)\n", " return self\n", " def transform(self, X, y=None):\n", " return X.fillna(self.most_frequent_)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이제 범주형 특성을 위한 파이프라인을 만듭니다:" ] }, { "cell_type": "code", "execution_count": 117, "metadata": {}, "outputs": [], "source": [ "cat_pipeline = Pipeline([\n", " (\"select_cat\", DataFrameSelector([\"Pclass\", \"Sex\", \"Embarked\"])),\n", " (\"imputer\", MostFrequentImputer()),\n", " (\"cat_encoder\", CategoricalEncoder(encoding='onehot-dense')),\n", " ])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### future_encoders.py를 사용한 방법 ==========================\n", "\n", "주의: 번역서는 `CategoricalEncoder`를 사용하여 각 범주형 값을 원-핫 벡터로 변경합니다. `OneHotEncoder`를 사용하는 것이 더 낫습니다. 지금은 정수형 범주 입력만 다룰 수 있지만 사이킷런 0.20에서는 문자열 범주 입력도 다룰 수 있을 것입니다(PR #10521). 지금은 `future_encoders.py` 파일에서 임포트하지만 사이킷런 0.20 버전이 릴리스되면 `sklearn.preprocessing`에서 바로 임포팅할 수 있습니다.\n", "\n", "0.20에 추가된 `OneHotEncoder`를 사용하도록 코드를 변경합니다." ] }, { "cell_type": "code", "execution_count": 118, "metadata": {}, "outputs": [], "source": [ "# from future_encoders import OneHotEncoder\n", "from sklearn.preprocessing import OneHotEncoder\n", "\n", "cat_pipeline = Pipeline([\n", " (\"select_cat\", DataFrameSelector([\"Pclass\", \"Sex\", \"Embarked\"])),\n", " (\"imputer\", MostFrequentImputer()),\n", " (\"cat_encoder\", OneHotEncoder(sparse=False)),\n", " ])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "0.20 버전에 추가된 `SimpleImputer` 클래스에는 `most_frequent` 옵션을 사용할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 119, "metadata": {}, "outputs": [], "source": [ "cat_pipeline = Pipeline([\n", " (\"select_cat\", DataFrameSelector([\"Pclass\", \"Sex\", \"Embarked\"])),\n", " (\"imputer\", SimpleImputer(strategy='most_frequent')),\n", " (\"cat_encoder\", OneHotEncoder(sparse=False)),\n", " ])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ====================================================" ] }, { "cell_type": "code", "execution_count": 120, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[0., 0., 1., ..., 0., 0., 1.],\n", " [1., 0., 0., ..., 1., 0., 0.],\n", " [0., 0., 1., ..., 0., 0., 1.],\n", " ...,\n", " [0., 0., 1., ..., 0., 0., 1.],\n", " [1., 0., 0., ..., 1., 0., 0.],\n", " [0., 0., 1., ..., 0., 1., 0.]])" ] }, "execution_count": 120, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat_pipeline.fit_transform(train_data)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "마지막으로 숫자와 범주형 파이프라인을 연결합니다:" ] }, { "cell_type": "code", "execution_count": 121, "metadata": {}, "outputs": [], "source": [ "from sklearn.pipeline import FeatureUnion\n", "preprocess_pipeline = FeatureUnion(transformer_list=[\n", " (\"num_pipeline\", num_pipeline),\n", " (\"cat_pipeline\", cat_pipeline),\n", " ])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "사이킷런 0.20 버전에 추가된 `ColumnTransformer`를 사용하면 더 간단히 전처리 파이프라인을 구성할 수 있습니다." ] }, { "cell_type": "code", "execution_count": 122, "metadata": {}, "outputs": [], "source": [ "from sklearn.compose import ColumnTransformer\n", "\n", "num_pipeline = Pipeline([\n", " (\"imputer\", SimpleImputer(strategy=\"median\"))\n", " ])\n", "\n", "cat_pipeline = Pipeline([\n", " (\"imputer\", SimpleImputer(strategy='most_frequent')),\n", " (\"cat_encoder\", OneHotEncoder(sparse=False)),\n", " ])\n", "\n", "preprocess_pipeline = ColumnTransformer([\n", " (\"num_pipeline\", num_pipeline, [\"Age\", \"SibSp\", \"Parch\", \"Fare\"]),\n", " (\"cat_pipeline\", cat_pipeline, [\"Pclass\", \"Sex\", \"Embarked\"]),\n", " ])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "좋습니다! 이제 원본 데이터를 받아 머신러닝 모델에 주입할 숫자 입력 특성을 출력하는 전처리 파이프라인을 만들었습니다." ] }, { "cell_type": "code", "execution_count": 123, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[22., 1., 0., ..., 0., 0., 1.],\n", " [38., 1., 0., ..., 1., 0., 0.],\n", " [26., 0., 0., ..., 0., 0., 1.],\n", " ...,\n", " [28., 1., 2., ..., 0., 0., 1.],\n", " [26., 0., 0., ..., 1., 0., 0.],\n", " [32., 0., 0., ..., 0., 1., 0.]])" ] }, "execution_count": 123, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X_train = preprocess_pipeline.fit_transform(train_data)\n", "X_train" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "레이블을 가져옵니다:" ] }, { "cell_type": "code", "execution_count": 124, "metadata": {}, "outputs": [], "source": [ "y_train = train_data[\"Survived\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이제 분류기를 훈련시킬 차례입니다. 먼저 `SVC`를 사용해 보겠습니다:" ] }, { "cell_type": "code", "execution_count": 125, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,\n", " decision_function_shape='ovr', degree=3, gamma='auto', kernel='rbf',\n", " max_iter=-1, probability=False, random_state=None, shrinking=True,\n", " tol=0.001, verbose=False)" ] }, "execution_count": 125, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.svm import SVC\n", "\n", "svm_clf = SVC(gamma='auto')\n", "svm_clf.fit(X_train, y_train)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "모델이 잘 훈련된 것 같습니다. 이를 사용해서 테스트 세트에 대한 예측을 만듭니다:" ] }, { "cell_type": "code", "execution_count": 126, "metadata": {}, "outputs": [], "source": [ "X_test = preprocess_pipeline.transform(test_data)\n", "y_pred = svm_clf.predict(X_test)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이 예측 결과를 (캐글에서 기대하는 형태인) CSV 파일로 만들어 업로드하고 평가를 받아볼 수 있습니다. 하지만 그냥 좋을거라 기대하는 것보다 교차 검증으로 모델이 얼마나 좋은지 평가하는 것이 좋습니다." ] }, { "cell_type": "code", "execution_count": 127, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.7365250822835092" ] }, "execution_count": 127, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.model_selection import cross_val_score\n", "\n", "svm_scores = cross_val_score(svm_clf, X_train, y_train, cv=10)\n", "svm_scores.mean()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "정확도가 73% 이상입니다. 확실히 무작위로 선택한 것보다는 좋습니다. 하지만 아주 높은 점수는 아닙니다. 캐글에서 타이타닉 경연 대회의 [리더보드](https://www.kaggle.com/c/titanic/leaderboard)를 보면 상위 10%내에 들려면 80% 이상의 정확도를 내야합니다. 어떤 사람들은 100%를 달성했습니다. 하지만 타이타닉의 [희생자 목록](https://www.encyclopedia-titanica.org/titanic-victims/)을 쉽게 찾을 수 있으므로 머신러닝을 사용하지 않고도 이런 정확도를 달성할 수 있습니다! ;-) 우리는 80% 정도의 정확도를 내는 모델을 만들어 보겠습니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`RandomForestClassifier`를 적용해 보겠습니다:" ] }, { "cell_type": "code", "execution_count": 128, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.8115690614005221" ] }, "execution_count": 128, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.ensemble import RandomForestClassifier\n", "\n", "forest_clf = RandomForestClassifier(n_estimators=10, random_state=42)\n", "forest_scores = cross_val_score(forest_clf, X_train, y_train, cv=10)\n", "forest_scores.mean()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "훨씬 좋네요!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "10 폴드 교차 검증에 대한 평균 정확도를 보는 대신 모델에서 얻은 10개의 점수를 1사분위, 3사분위를 명료하게 표현해주는 상자 수염 그림(box-and-whisker) 그래프를 만들어 보겠습니다(이 방식을 제안해 준 Nevin Yilmaz에게 감사합니다). `boxplot()` 함수는 이상치(플라이어(flier)라고 부릅니다)를 감지하고 수염 부분에 이를 포함시키지 않습니다. 1사분위가 $Q_1$이고 3사분위가 $Q_3$이라면 사분위수 범위는 $IQR = Q_3 - Q_1$가 됩니다(이 값이 박스의 높이가 됩니다). $Q_1 - 1.5 \\times IQR$ 보다 낮거나 $Q3 + 1.5 \\times IQR$ 보다 높은 점수는 이상치로 간주됩니다." ] }, { "cell_type": "code", "execution_count": 129, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=(8, 4))\n", "plt.plot([1]*10, svm_scores, \".\")\n", "plt.plot([2]*10, forest_scores, \".\")\n", "plt.boxplot([svm_scores, forest_scores], labels=(\"SVM\",\"Random Forest\"))\n", "plt.ylabel(\"정확도\", fontsize=14)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이 결과를 더 향상시키려면:\n", "* 교차 검증과 그리드 탐색을 사용하여 더 많은 모델을 비교하고 하이퍼파라미터를 튜닝하세요.\n", "* 특성 공학을 더 시도해 보세요, 예를 들면:\n", " * **SibSp**와 **Parch**을 이 두 특성의 합으로 바꿉니다.\n", " * **Survived** 특성과 관련된 이름을 구별해 보세요(가령, 이름에 \"Countess\"가 있는 경우 생존할 가능성이 높습니다).\n", "* 수치 특성을 범주형 특성으로 바꾸어 보세요: 예를 들어, 나이대가 다른 경우 다른 생존 비율을 가질 수 있습니다(아래 참조). 그러므로 나이 구간을 범주로 만들어 나이 대신 사용하는 것이 도움이 될 수 있스니다. 비슷하게 생존자의 30%가 혼자 여행하는 사람이기 때문에 이들을 위한 특별한 범주를 만드는 것이 도움이 될 수 있습니다(아래 참조)." ] }, { "cell_type": "code", "execution_count": 130, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Survived
AgeBucket
0.00.576923
15.00.362745
30.00.423256
45.00.404494
60.00.240000
75.01.000000
\n", "
" ], "text/plain": [ " Survived\n", "AgeBucket \n", "0.0 0.576923\n", "15.0 0.362745\n", "30.0 0.423256\n", "45.0 0.404494\n", "60.0 0.240000\n", "75.0 1.000000" ] }, "execution_count": 130, "metadata": {}, "output_type": "execute_result" } ], "source": [ "train_data[\"AgeBucket\"] = train_data[\"Age\"] // 15 * 15\n", "train_data[[\"AgeBucket\", \"Survived\"]].groupby(['AgeBucket']).mean()" ] }, { "cell_type": "code", "execution_count": 131, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Survived
RelativesOnboard
00.303538
10.552795
20.578431
30.724138
40.200000
50.136364
60.333333
70.000000
100.000000
\n", "
" ], "text/plain": [ " Survived\n", "RelativesOnboard \n", "0 0.303538\n", "1 0.552795\n", "2 0.578431\n", "3 0.724138\n", "4 0.200000\n", "5 0.136364\n", "6 0.333333\n", "7 0.000000\n", "10 0.000000" ] }, "execution_count": 131, "metadata": {}, "output_type": "execute_result" } ], "source": [ "train_data[\"RelativesOnboard\"] = train_data[\"SibSp\"] + train_data[\"Parch\"]\n", "train_data[[\"RelativesOnboard\", \"Survived\"]].groupby(['RelativesOnboard']).mean()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. 스팸 필터" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "먼저 데이터를 다운받습니다:" ] }, { "cell_type": "code", "execution_count": 132, "metadata": {}, "outputs": [], "source": [ "import os\n", "import tarfile\n", "from six.moves import urllib\n", "\n", "DOWNLOAD_ROOT = \"http://spamassassin.apache.org/old/publiccorpus/\"\n", "HAM_URL = DOWNLOAD_ROOT + \"20030228_easy_ham.tar.bz2\"\n", "SPAM_URL = DOWNLOAD_ROOT + \"20030228_spam.tar.bz2\"\n", "SPAM_PATH = os.path.join(\"datasets\", \"spam\")\n", "\n", "def fetch_spam_data(spam_url=SPAM_URL, spam_path=SPAM_PATH):\n", " if not os.path.isdir(spam_path):\n", " os.makedirs(spam_path)\n", " for filename, url in ((\"ham.tar.bz2\", HAM_URL), (\"spam.tar.bz2\", SPAM_URL)):\n", " path = os.path.join(spam_path, filename)\n", " if not os.path.isfile(path):\n", " urllib.request.urlretrieve(url, path)\n", " tar_bz2_file = tarfile.open(path)\n", " tar_bz2_file.extractall(path=SPAM_PATH)\n", " tar_bz2_file.close()" ] }, { "cell_type": "code", "execution_count": 133, "metadata": {}, "outputs": [], "source": [ "fetch_spam_data()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "다음, 모든 이메일을 읽어 들입니다:" ] }, { "cell_type": "code", "execution_count": 134, "metadata": {}, "outputs": [], "source": [ "HAM_DIR = os.path.join(SPAM_PATH, \"easy_ham\")\n", "SPAM_DIR = os.path.join(SPAM_PATH, \"spam\")\n", "ham_filenames = [name for name in sorted(os.listdir(HAM_DIR)) if len(name) > 20]\n", "spam_filenames = [name for name in sorted(os.listdir(SPAM_DIR)) if len(name) > 20]" ] }, { "cell_type": "code", "execution_count": 135, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2500" ] }, "execution_count": 135, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(ham_filenames)" ] }, { "cell_type": "code", "execution_count": 136, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "500" ] }, "execution_count": 136, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(spam_filenames)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "파이썬의 `email` 모듈을 사용해 이메일을 파싱합니다(헤더, 인코딩 등을 처리합니다):" ] }, { "cell_type": "code", "execution_count": 137, "metadata": {}, "outputs": [], "source": [ "import email\n", "import email.policy\n", "\n", "def load_email(is_spam, filename, spam_path=SPAM_PATH):\n", " directory = \"spam\" if is_spam else \"easy_ham\"\n", " with open(os.path.join(spam_path, directory, filename), \"rb\") as f:\n", " return email.parser.BytesParser(policy=email.policy.default).parse(f)" ] }, { "cell_type": "code", "execution_count": 138, "metadata": {}, "outputs": [], "source": [ "ham_emails = [load_email(is_spam=False, filename=name) for name in ham_filenames]\n", "spam_emails = [load_email(is_spam=True, filename=name) for name in spam_filenames]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "데이터가 어떻게 구성되어 있는지 감을 잡기 위해 햄 메일과 스팸 메일을 하나씩 보겠습니다:" ] }, { "cell_type": "code", "execution_count": 139, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Martin A posted:\n", "Tassos Papadopoulos, the Greek sculptor behind the plan, judged that the\n", " limestone of Mount Kerdylio, 70 miles east of Salonika and not far from the\n", " Mount Athos monastic community, was ideal for the patriotic sculpture. \n", " \n", " As well as Alexander's granite features, 240 ft high and 170 ft wide, a\n", " museum, a restored amphitheatre and car park for admiring crowds are\n", "planned\n", "---------------------\n", "So is this mountain limestone or granite?\n", "If it's limestone, it'll weather pretty fast.\n", "\n", "------------------------ Yahoo! Groups Sponsor ---------------------~-->\n", "4 DVDs Free +s&p Join Now\n", "http://us.click.yahoo.com/pt6YBB/NXiEAA/mG3HAA/7gSolB/TM\n", "---------------------------------------------------------------------~->\n", "\n", "To unsubscribe from this group, send an email to:\n", "forteana-unsubscribe@egroups.com\n", "\n", " \n", "\n", "Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/\n" ] } ], "source": [ "print(ham_emails[1].get_content().strip())" ] }, { "cell_type": "code", "execution_count": 140, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help wanted. We are a 14 year old fortune 500 company, that is\n", "growing at a tremendous rate. We are looking for individuals who\n", "want to work from home.\n", "\n", "This is an opportunity to make an excellent income. No experience\n", "is required. We will train you.\n", "\n", "So if you are looking to be employed from home with a career that has\n", "vast opportunities, then go:\n", "\n", "http://www.basetel.com/wealthnow\n", "\n", "We are looking for energetic and self motivated people. If that is you\n", "than click on the link and fill out the form, and one of our\n", "employement specialist will contact you.\n", "\n", "To be removed from our link simple go to:\n", "\n", "http://www.basetel.com/remove.html\n", "\n", "\n", "4139vOLW7-758DoDY1425FRhM1-764SMFc8513fCsLl40\n" ] } ], "source": [ "print(spam_emails[6].get_content().strip())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "어떤 이메일은 이미지나 첨부 파일을 가진 멀티파트(multipart)입니다(메일에 포함되어 있을수 있습니다). 어떤 파일들이 있는지 살펴 보겠습니다:" ] }, { "cell_type": "code", "execution_count": 141, "metadata": {}, "outputs": [], "source": [ "def get_email_structure(email):\n", " if isinstance(email, str):\n", " return email\n", " payload = email.get_payload()\n", " if isinstance(payload, list):\n", " return \"multipart({})\".format(\", \".join([\n", " get_email_structure(sub_email)\n", " for sub_email in payload\n", " ]))\n", " else:\n", " return email.get_content_type()" ] }, { "cell_type": "code", "execution_count": 142, "metadata": {}, "outputs": [], "source": [ "from collections import Counter\n", "\n", "def structures_counter(emails):\n", " structures = Counter()\n", " for email in emails:\n", " structure = get_email_structure(email)\n", " structures[structure] += 1\n", " return structures" ] }, { "cell_type": "code", "execution_count": 143, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "[('text/plain', 2408),\n", " ('multipart(text/plain, application/pgp-signature)', 66),\n", " ('multipart(text/plain, text/html)', 8),\n", " ('multipart(text/plain, text/plain)', 4),\n", " ('multipart(text/plain)', 3),\n", " ('multipart(text/plain, application/octet-stream)', 2),\n", " ('multipart(text/plain, text/enriched)', 1),\n", " ('multipart(text/plain, application/ms-tnef, text/plain)', 1),\n", " ('multipart(multipart(text/plain, text/plain, text/plain), application/pgp-signature)',\n", " 1),\n", " ('multipart(text/plain, video/mng)', 1),\n", " ('multipart(text/plain, multipart(text/plain))', 1),\n", " ('multipart(text/plain, application/x-pkcs7-signature)', 1),\n", " ('multipart(text/plain, multipart(text/plain, text/plain), text/rfc822-headers)',\n", " 1),\n", " ('multipart(text/plain, multipart(text/plain, text/plain), multipart(multipart(text/plain, application/x-pkcs7-signature)))',\n", " 1),\n", " ('multipart(text/plain, application/x-java-applet)', 1)]" ] }, "execution_count": 143, "metadata": {}, "output_type": "execute_result" } ], "source": [ "structures_counter(ham_emails).most_common()" ] }, { "cell_type": "code", "execution_count": 144, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[('text/plain', 218),\n", " ('text/html', 183),\n", " ('multipart(text/plain, text/html)', 45),\n", " ('multipart(text/html)', 20),\n", " ('multipart(text/plain)', 19),\n", " ('multipart(multipart(text/html))', 5),\n", " ('multipart(text/plain, image/jpeg)', 3),\n", " ('multipart(text/html, application/octet-stream)', 2),\n", " ('multipart(text/plain, application/octet-stream)', 1),\n", " ('multipart(text/html, text/plain)', 1),\n", " ('multipart(multipart(text/html), application/octet-stream, image/jpeg)', 1),\n", " ('multipart(multipart(text/plain, text/html), image/gif)', 1),\n", " ('multipart/alternative', 1)]" ] }, "execution_count": 144, "metadata": {}, "output_type": "execute_result" } ], "source": [ "structures_counter(spam_emails).most_common()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "햄 메일은 평범한 텍스트가 많고 스팸은 HTML일 경우가 많습니다. 적은 수의 햄 이메일이 PGP로 서명되어 있지만 스팸 메일에는 없습니다. 요약하면 이메일 구조는 유용한 정보입니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이제 이메일 헤더를 살펴보겠습니다:" ] }, { "cell_type": "code", "execution_count": 145, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Return-Path : <12a1mailbot1@web.de>\n", "Delivered-To : zzzz@localhost.spamassassin.taint.org\n", "Received : from localhost (localhost [127.0.0.1])\tby phobos.labs.spamassassin.taint.org (Postfix) with ESMTP id 136B943C32\tfor ; Thu, 22 Aug 2002 08:17:21 -0400 (EDT)\n", "Received : from mail.webnote.net [193.120.211.219]\tby localhost with POP3 (fetchmail-5.9.0)\tfor zzzz@localhost (single-drop); Thu, 22 Aug 2002 13:17:21 +0100 (IST)\n", "Received : from dd_it7 ([210.97.77.167])\tby webnote.net (8.9.3/8.9.3) with ESMTP id NAA04623\tfor ; Thu, 22 Aug 2002 13:09:41 +0100\n", "From : 12a1mailbot1@web.de\n", "Received : from r-smtp.korea.com - 203.122.2.197 by dd_it7 with Microsoft SMTPSVC(5.5.1775.675.6);\t Sat, 24 Aug 2002 09:42:10 +0900\n", "To : dcek1a1@netsgo.com\n", "Subject : Life Insurance - Why Pay More?\n", "Date : Wed, 21 Aug 2002 20:31:57 -1600\n", "MIME-Version : 1.0\n", "Message-ID : <0103c1042001882DD_IT7@dd_it7>\n", "Content-Type : text/html; charset=\"iso-8859-1\"\n", "Content-Transfer-Encoding : quoted-printable\n" ] } ], "source": [ "for header, value in spam_emails[0].items():\n", " print(header,\":\",value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "보낸사람의 이메일 주소와 같이 헤더에는 유용한 정보가 많이 있지만 여기서는 `Subject` 헤더만 다뤄 보겠습니다:" ] }, { "cell_type": "code", "execution_count": 146, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Life Insurance - Why Pay More?'" ] }, "execution_count": 146, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spam_emails[0][\"Subject\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "좋습니다. 데이터에를 더 살펴보기 전에 훈련 세트와 테스트 세트로 나누도록 하겠습니다:" ] }, { "cell_type": "code", "execution_count": 147, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from sklearn.model_selection import train_test_split\n", "\n", "X = np.array(ham_emails + spam_emails)\n", "y = np.array([0] * len(ham_emails) + [1] * len(spam_emails))\n", "\n", "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이제 전처리 함수를 작성하겠습니다. 먼저 HTML을 일반 텍스트로 변환하는 함수가 필요합니다. 이 작업에는 당연히 [BeautifulSoup](https://www.crummy.com/software/BeautifulSoup/) 라이브러리를 사용하는게 좋지만 의존성을 줄이기 위해서 정규식을 사용하여 대강 만들어 보겠습니다([un̨ho͞ly radiańcé destro҉ying all enli̍̈́̂̈́ghtenment](https://stackoverflow.com/a/1732454/38626)의 위험에도 불구하고). 다음 함수는 `` 섹션을 삭제하고 모든 `` 태그를 HYPERLINK 문자로 바꿉니다. 그런 다음 모든 HTML 태그를 제거하고 텍스트만 남깁니다. 보기 편하게 여러개의 개행 문자를 하나로 만들고 (`>`나 ` ` 같은) html 엔티티를 복원합니다:" ] }, { "cell_type": "code", "execution_count": 148, "metadata": {}, "outputs": [], "source": [ "import re\n", "from html import unescape\n", "\n", "def html_to_plain_text(html):\n", " text = re.sub('.*?', '', html, flags=re.M | re.S | re.I)\n", " text = re.sub('', ' HYPERLINK ', text, flags=re.M | re.S | re.I)\n", " text = re.sub('<.*?>', '', text, flags=re.M | re.S)\n", " text = re.sub(r'(\\s*\\n)+', '\\n', text, flags=re.M | re.S)\n", " return unescape(text)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "잘 작동하는지 확인해 보겠습니다. 다음은 HTML 스팸입니다:" ] }, { "cell_type": "code", "execution_count": 149, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "
\n", "\n", "OTC
\n", "\n", " Newsletter
\n", "Discover Tomorrow's Winners 
comput\n", "Computation => comput\n", "Computing => comput\n", "Computed => comput\n", "Compute => comput\n", "Compulsive => compuls\n" ] } ], "source": [ "try:\n", " import nltk\n", "\n", " stemmer = nltk.PorterStemmer()\n", " for word in (\"Computations\", \"Computation\", \"Computing\", \"Computed\", \"Compute\", \"Compulsive\"):\n", " print(word, \"=>\", stemmer.stem(word))\n", "except ImportError:\n", " print(\"Error: stemming requires the NLTK module.\")\n", " stemmer = None" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "인터넷 주소는 \"URL\" 문자로 바꾸겠습니다. [정규식](https://mathiasbynens.be/demo/url-regex)을 하드 코딩할 수도 있지만 [urlextract](https://github.com/lipoja/URLExtract) 라이브러리를 사용하겠습니다. 다음 명령으로 설치합니다(먼저 virtualenv 환경을 활성화시켜야 합니다. 별도의 환경이 없다면 어드민 권한이 필요할지 모릅니다. 아니면 `--user` 옵션을 사용하세요):\n", "\n", "`$ pip install urlextract`" ] }, { "cell_type": "code", "execution_count": 154, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['github.com', 'https://youtu.be/7Pq-S557XQU?t=3m32s']\n" ] } ], "source": [ "try:\n", " import urlextract # 루트 도메인 이름을 다운로드하기 위해 인터넷 연결이 필요할지 모릅니다\n", " \n", " url_extractor = urlextract.URLExtract()\n", " print(url_extractor.find_urls(\"Will it detect github.com and https://youtu.be/7Pq-S557XQU?t=3m32s\"))\n", "except ImportError:\n", " print(\"Error: replacing URLs requires the urlextract module.\")\n", " url_extractor = None" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이들을 모두 하나의 변환기로 연결하여 이메일을 단어 카운트로 바꿀 것입니다. 파이썬의 `split()` 메서드를 사용하면 구둣점과 단어 경계를 기준으로 문장을 단어로 바꿉니다. 이 방법이 많은 언어에 통하지만 전부는 아닙니다. 예를 들어 중국어와 일본어는 일반적으로 단어 사이에 공백을 두지 않습니다. 베트남어는 음절 사이에 공백을 두기도 합니다. 여기서는 데이터셋이 (거의) 영어로 되어 있기 때문에 문제없습니다." ] }, { "cell_type": "code", "execution_count": 155, "metadata": {}, "outputs": [], "source": [ "from sklearn.base import BaseEstimator, TransformerMixin\n", "\n", "class EmailToWordCounterTransformer(BaseEstimator, TransformerMixin):\n", " def __init__(self, strip_headers=True, lower_case=True, remove_punctuation=True,\n", " replace_urls=True, replace_numbers=True, stemming=True):\n", " self.strip_headers = strip_headers\n", " self.lower_case = lower_case\n", " self.remove_punctuation = remove_punctuation\n", " self.replace_urls = replace_urls\n", " self.replace_numbers = replace_numbers\n", " self.stemming = stemming\n", " def fit(self, X, y=None):\n", " return self\n", " def transform(self, X, y=None):\n", " X_transformed = []\n", " for email in X:\n", " text = email_to_text(email) or \"\"\n", " if self.lower_case:\n", " text = text.lower()\n", " if self.replace_urls and url_extractor is not None:\n", " urls = list(set(url_extractor.find_urls(text)))\n", " urls.sort(key=lambda url: len(url), reverse=True)\n", " for url in urls:\n", " text = text.replace(url, \" URL \")\n", " if self.replace_numbers:\n", " text = re.sub(r'\\d+(?:\\.\\d*(?:[eE]\\d+))?', 'NUMBER', text)\n", " if self.remove_punctuation:\n", " text = re.sub(r'\\W+', ' ', text, flags=re.M)\n", " word_counts = Counter(text.split())\n", " if self.stemming and stemmer is not None:\n", " stemmed_word_counts = Counter()\n", " for word, count in word_counts.items():\n", " stemmed_word = stemmer.stem(word)\n", " stemmed_word_counts[stemmed_word] += count\n", " word_counts = stemmed_word_counts\n", " X_transformed.append(word_counts)\n", " return np.array(X_transformed)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이 변환기를 몇 개의 이메일에 적용해 보겠습니다:" ] }, { "cell_type": "code", "execution_count": 156, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([Counter({'chuck': 1, 'murcko': 1, 'wrote': 1, 'stuff': 1, 'yawn': 1, 'r': 1}),\n", " Counter({'the': 11, 'of': 9, 'and': 8, 'all': 3, 'christian': 3, 'to': 3, 'by': 3, 'jefferson': 2, 'i': 2, 'have': 2, 'superstit': 2, 'one': 2, 'on': 2, 'been': 2, 'ha': 2, 'half': 2, 'rogueri': 2, 'teach': 2, 'jesu': 2, 'some': 1, 'interest': 1, 'quot': 1, 'url': 1, 'thoma': 1, 'examin': 1, 'known': 1, 'word': 1, 'do': 1, 'not': 1, 'find': 1, 'in': 1, 'our': 1, 'particular': 1, 'redeem': 1, 'featur': 1, 'they': 1, 'are': 1, 'alik': 1, 'found': 1, 'fabl': 1, 'mytholog': 1, 'million': 1, 'innoc': 1, 'men': 1, 'women': 1, 'children': 1, 'sinc': 1, 'introduct': 1, 'burnt': 1, 'tortur': 1, 'fine': 1, 'imprison': 1, 'what': 1, 'effect': 1, 'thi': 1, 'coercion': 1, 'make': 1, 'world': 1, 'fool': 1, 'other': 1, 'hypocrit': 1, 'support': 1, 'error': 1, 'over': 1, 'earth': 1, 'six': 1, 'histor': 1, 'american': 1, 'john': 1, 'e': 1, 'remsburg': 1, 'letter': 1, 'william': 1, 'short': 1, 'again': 1, 'becom': 1, 'most': 1, 'pervert': 1, 'system': 1, 'that': 1, 'ever': 1, 'shone': 1, 'man': 1, 'absurd': 1, 'untruth': 1, 'were': 1, 'perpetr': 1, 'upon': 1, 'a': 1, 'larg': 1, 'band': 1, 'dupe': 1, 'import': 1, 'led': 1, 'paul': 1, 'first': 1, 'great': 1, 'corrupt': 1}),\n", " Counter({'url': 5, 's': 3, 'group': 3, 'to': 3, 'in': 2, 'martin': 2, 'an': 2, 'and': 2, 'we': 2, 'is': 2, 'yahoo': 2, 'forteana': 1, 'y': 1, 'adamson': 1, 'wrote': 1, 'for': 1, 'altern': 1, 'rather': 1, 'more': 1, 'factual': 1, 'base': 1, 'rundown': 1, 'on': 1, 'hamza': 1, 'career': 1, 'includ': 1, 'hi': 1, 'belief': 1, 'that': 1, 'all': 1, 'non': 1, 'muslim': 1, 'yemen': 1, 'should': 1, 'be': 1, 'murder': 1, 'outright': 1, 'know': 1, 'how': 1, 'unbias': 1, 'memri': 1, 'don': 1, 't': 1, 'html': 1, 'rob': 1, 'sponsor': 1, 'number': 1, 'dvd': 1, 'free': 1, 'p': 1, 'join': 1, 'now': 1, 'unsubscrib': 1, 'from': 1, 'thi': 1, 'send': 1, 'email': 1, 'your': 1, 'use': 1, 'of': 1, 'subject': 1})],\n", " dtype=object)" ] }, "execution_count": 156, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X_few = X_train[:3]\n", "X_few_wordcounts = EmailToWordCounterTransformer().fit_transform(X_few)\n", "X_few_wordcounts" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "제대로 작동하는 것 같네요!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이제 단어 카운트를 벡터로 변환해야 합니다. 이를 위해서 또 다른 변환기를 만들겠습니다. 이 변환기는 (자주 나타나는 단어 순으로 정렬된) 어휘 목록을 구축하는 `fit()` 메서드와 어휘 목록을 사용해 단어를 벡터로 바꾸는 `transform()` 메서드를 가집니다. 출력은 희소 행렬이 됩니다." ] }, { "cell_type": "code", "execution_count": 157, "metadata": {}, "outputs": [], "source": [ "from scipy.sparse import csr_matrix\n", "\n", "class WordCounterToVectorTransformer(BaseEstimator, TransformerMixin):\n", " def __init__(self, vocabulary_size=1000):\n", " self.vocabulary_size = vocabulary_size\n", " def fit(self, X, y=None):\n", " total_count = Counter()\n", " for word_count in X:\n", " for word, count in word_count.items():\n", " total_count[word] += min(count, 10)\n", " most_common = total_count.most_common()[:self.vocabulary_size]\n", " self.most_common_ = most_common\n", " self.vocabulary_ = {word: index + 1 for index, (word, count) in enumerate(most_common)}\n", " return self\n", " def transform(self, X, y=None):\n", " rows = []\n", " cols = []\n", " data = []\n", " for row, word_count in enumerate(X):\n", " for word, count in word_count.items():\n", " rows.append(row)\n", " cols.append(self.vocabulary_.get(word, 0))\n", " data.append(count)\n", " return csr_matrix((data, (rows, cols)), shape=(len(X), self.vocabulary_size + 1))" ] }, { "cell_type": "code", "execution_count": 158, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "<3x11 sparse matrix of type ''\n", "\twith 20 stored elements in Compressed Sparse Row format>" ] }, "execution_count": 158, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vocab_transformer = WordCounterToVectorTransformer(vocabulary_size=10)\n", "X_few_vectors = vocab_transformer.fit_transform(X_few_wordcounts)\n", "X_few_vectors" ] }, { "cell_type": "code", "execution_count": 159, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n", " [99, 11, 9, 8, 1, 3, 3, 1, 3, 2, 3],\n", " [63, 0, 1, 2, 5, 3, 1, 2, 0, 1, 0]], dtype=int64)" ] }, "execution_count": 159, "metadata": {}, "output_type": "execute_result" } ], "source": [ "X_few_vectors.toarray()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이 행렬은 무엇을 의미하나요? 세 번째 행의 첫 번째 열의 65는 세 번째 이메일이 어휘 목록에 없는 단어를 65개 가지고 있다는 뜻입니다. 그 다음의 0은 어휘 목록에 있는 첫 번째 단어가 한 번도 등장하지 않는다는 뜻이고 그 다음의 1은 한 번 나타난다는 뜻입니다. 이 단어들이 무엇인지 확인하려면 어휘 목록을 보면 됩니다. 첫 번째 단어는 \"the\"이고 두 번째 단어는 \"of\"입니다." ] }, { "cell_type": "code", "execution_count": 160, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'the': 1,\n", " 'of': 2,\n", " 'and': 3,\n", " 'url': 4,\n", " 'to': 5,\n", " 'all': 6,\n", " 'in': 7,\n", " 'christian': 8,\n", " 'on': 9,\n", " 'by': 10}" ] }, "execution_count": 160, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vocab_transformer.vocabulary_" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이제 스팸 분류기를 훈련시킬 준비를 마쳤습니다! 전체 데이터셋을 변환시켜보죠:" ] }, { "cell_type": "code", "execution_count": 161, "metadata": {}, "outputs": [], "source": [ "from sklearn.pipeline import Pipeline\n", "\n", "preprocess_pipeline = Pipeline([\n", " (\"email_to_wordcount\", EmailToWordCounterTransformer()),\n", " (\"wordcount_to_vector\", WordCounterToVectorTransformer()),\n", "])\n", "\n", "X_train_transformed = preprocess_pipeline.fit_transform(X_train)" ] }, { "cell_type": "code", "execution_count": 162, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[CV] ................................................................\n", "[CV] .................................... , score=0.984, total= 0.0s\n", "[CV] ................................................................\n", "[CV] .................................... , score=0.983, total= 0.0s\n", "[CV] ................................................................\n", "[CV] .................................... , score=0.991, total= 0.0s\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.\n", "[Parallel(n_jobs=1)]: Done 1 out of 1 | elapsed: 0.0s remaining: 0.0s\n", "[Parallel(n_jobs=1)]: Done 2 out of 2 | elapsed: 0.1s remaining: 0.0s\n", "[Parallel(n_jobs=1)]: Done 3 out of 3 | elapsed: 0.1s finished\n" ] }, { "data": { "text/plain": [ "0.9858333333333333" ] }, "execution_count": 162, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from sklearn.linear_model import LogisticRegression\n", "from sklearn.model_selection import cross_val_score\n", "\n", "log_clf = LogisticRegression(solver='liblinear', random_state=42)\n", "score = cross_val_score(log_clf, X_train_transformed, y_train, cv=3, verbose=3)\n", "score.mean()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "98.7%가 넘네요. 첫 번째 시도치고 나쁘지 않습니다! :) 그러나 이 데이터셋은 비교적 쉬운 문제입니다. 더 어려운 데이터셋에 적용해 보면 결과가 그리 높지 않을 것입니다. 여러개의 모델을 시도해 보고 제일 좋은 것을 골라 교차 검증으로 세밀하게 튜닝해 보세요.\n", "\n", "하지만 전체 내용을 파악했으므로 여기서 멈추겠습니다. 테스트 세트에서 정밀도/재현율을 출력해 보겠습니다:" ] }, { "cell_type": "code", "execution_count": 163, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "정밀도: 94.90%\n", "재현율: 97.89%\n" ] } ], "source": [ "from sklearn.metrics import precision_score, recall_score\n", "\n", "X_test_transformed = preprocess_pipeline.transform(X_test)\n", "\n", "log_clf = LogisticRegression(solver='liblinear', random_state=42)\n", "log_clf.fit(X_train_transformed, y_train)\n", "\n", "y_pred = log_clf.predict(X_test_transformed)\n", "\n", "print(\"정밀도: {:.2f}%\".format(100 * precision_score(y_test, y_pred)))\n", "print(\"재현율: {:.2f}%\".format(100 * recall_score(y_test, y_pred)))" ] } ], "metadata": { "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.3" }, "nav_menu": {}, "toc": { "navigate_menu": true, "number_sections": true, "sideBar": true, "threshold": 6, "toc_cell": false, "toc_section_display": "block", "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 1 }