{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Introduction to PyCall\n", "\n", "まず、PyCall について簡単に説明します。\n", "\n", "PyCall の実態は「**Ruby から libpython.so を使うための拡張ライブラリ**」です。\n", "PyCall は libpython.so の機能を利用して、Ruby から Python のオブジェクトを触れるようにするブリッジ機能を提供します。\n", "PyCall を使うと、例えば以下のように Python 側の `sin` 関数を Ruby 側に持ってきて呼び出すことが可能です。" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "require 'pycall'\n", "\n", "# PyCall.import_module function loads a module in Python, and brings the loaded module object in Ruby\n", "pymath = PyCall.import_module('math')" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Accessing `sin` attribute of `math` module\n", "pymath.sin" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "1.2246467991473532e-16" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Calling function object by the syntax sugar of `.call` method call\n", "pymath.sin.(Math::PI)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ruby 側に持ってきた Python オブジェクトは、基本的なクラスを除いてすべて PyObject クラスのインスタンスによってラップされます。" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "PyCall::PyObject" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# pymath is a module object in Python, but it is wrapped by an instance of PyObject in Ruby\n", "pymath.class" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "PyCall::PyObject" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# pymath.sin is a builtin-function object in Python, but it is wrapped by an instance of PyObject in Ruby\n", "pymath.sin.class" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "Float" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# The result of pymath.sin is a float object in Python, but it is automatically converted to Float object in Ruby\n", "pymath.sin.(Math::PI).class" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "\"sin\"" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# The name of a function object\n", "pymath.sin.__name__" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "String" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# It is converted to a String object in Ruby\n", "pymath.sin.__name__.class" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`pycall/import` が提供する機能を利用すると、Python での `import math` と同じような記法でモジュールをインポートできます。\n", "\n", "やってみましょう" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ ":math" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "require 'pycall/import'\n", "include PyCall::Import\n", "\n", "pyimport :math" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "math" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "math.sin" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.2246467991473532e-16" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "math.sin.(Math::PI)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "PyCall は PyObjectWrapper というモジュールを提供しています。このモジュールを使うと、Python のクラスに対応するラッパークラスを定義できます。ラッパークラスを定義すると、インスタンスメソッドやクラスメソッドの呼び出しを自然に記述できるようになります。\n", "\n", "numpy を例に違いを見てみましょう。\n", "\n", "まず、ラッパークラスを定義せずに numpy を使ってみます。" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ ":np" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pyimport :numpy, as: :np" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# `np.array` retrives a function object\n", "np.array" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 0.78720422, 0.04989502, 0.61287186, 0.58935543, 0.10911719,\n", " 0.90534304, 0.17907297, 0.56424541, 0.7532547 , 0.32246486,\n", " 0.65825915, 0.70162822, 0.90634646, 0.19754435, 0.29295796,\n", " 0.61622797, 0.14356238, 0.64854779, 0.18438799, 0.93683436])" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Use `.call` method to call `np.array`\n", "ary = np.array.([*1..20].map { rand })" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "PyCall::PyObject" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# This is a PyObject\n", "ary.class" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# `ary.mean` retrieves a function object\n", "ary.mean" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.5079560660124105" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Use `.call` method to call `ary.mean`\n", "ary.mean.()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "次に、ラッパークラスを定義します。" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[#, rbtype=Numpy::NDArray>]" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "module Numpy\n", " class NDArray\n", " include PyCall::PyObjectWrapper\n", " wrap_class PyCall.import_module('numpy').ndarray\n", " end\n", "end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "これで Numpy::NDArray クラスが np.ndarray のラッパーになりました。\n", "\n", "もう一度 ndarray オブジェクトを生成してみましょう。" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 10.43929293, 10.774188 , 10.69860716, 10.349782 ,\n", " 10.40455471, 10.31237692, 10.42337371, 10.85054457,\n", " 10.797475 , 10.29543447, 10.97507191, 10.77216906,\n", " 10.80617675, 10.90382459, 10.80300021, 10.61905881,\n", " 10.67108304, 10.77988371, 10.91601262, 10.6303129 ])" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ary2 = np.array.([*1..20].map { rand + 10 })" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Numpy::NDArray" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ary2 is a Numpy::NDArray!!\n", "ary2.class" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10.661111153255195" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# ary2.mean calls mean method!!\n", "ary2.mean" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このように、PyObjectWrapper を利用して Python クラスのラッパーを Ruby 側に定義できました。\n", "matplotlib のラッパーライブラリでは、この機能を使って Figure や Axes などのクラスのラッパーを定義しています。\n", "\n", "残念ながら pandas の DataFrame ライブラリに対して wrap_class を適用するとエラーが出てしまう[問題があります](https://github.com/mrkn/pycall/issues/16)。\n", "そのため、このチュートリアルでは pandas のラッパーを定義せずに使っていきます。\n", "\n", "モジュールに対するラッパーを定義する機能はまだ作っていませんが、近日中に提供できる予定になっています。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Data Analysis with Ruby using PyCall\n", "\n", "それでは、PyCall を利用して Ruby でデータ分析をやってみましょう。\n", "\n", "## 準備編\n", "\n", "分析に入る前に、いくつか準備をします。\n", "\n", "データの可視化のために seaborn ライブラリを利用します。このライブラリは matplotlib を利用しているため、IRuby と matplotlib の間の連携を有効にします。" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[:inline, \"module://ruby.matplotlib.backend_inline\"]" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "require 'matplotlib/iruby'\n", "Matplotlib::IRuby.activate" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "利用するライブラリをインポートしておきましょう。" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/plain": [ ":sns" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pyimport :pandas, as: :pd\n", "pyimport :seaborn, as: :sns" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "pandas のデータフレームを IRuby ノートブック上で見やすく表示するための準備をします。\n", "これは、将来的には require 'pandas/iruby' などで自動的に実施されるようにする予定です。" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": true }, "outputs": [], "source": [ "module Pandas\n", " class DataFrame < PyCall::PyObject\n", " end\n", "end\n", "\n", "PyCall::Conversions.python_type_mapping(pd.DataFrame, Pandas::DataFrame)\n", "\n", "dataframe_max_rows = 20\n", "\n", "IRuby::Display::Registry.module_eval do\n", " type { Pandas::DataFrame }\n", " format \"text/html\" do |pyobj|\n", " pyobj.to_html.(max_rows: dataframe_max_rows, show_dimensions: true, notebook: true)\n", " end\n", "end" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## データ分析の実演\n", "\n", "### データの準備と前処理\n", "\n", "タイタニック号の乗客のデータを用いて、乗客の生存予測をするためのモデルを作ってみます。\n", "\n", "seaborn ライブラリの `load_dataset` 関数を使ってデータのダウンロードと読み込みをします。" ] }, { "cell_type": "code", "execution_count": 27, "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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
survivedpclasssexagesibspparchfareembarkedclasswhoadult_maledeckembark_townalivealone
003male22.0107.2500SThirdmanTrueNaNSouthamptonnoFalse
111female38.01071.2833CFirstwomanFalseCCherbourgyesFalse
213female26.0007.9250SThirdwomanFalseNaNSouthamptonyesTrue
311female35.01053.1000SFirstwomanFalseCSouthamptonyesFalse
403male35.0008.0500SThirdmanTrueNaNSouthamptonnoTrue
503maleNaN008.4583QThirdmanTrueNaNQueenstownnoTrue
601male54.00051.8625SFirstmanTrueESouthamptonnoTrue
703male2.03121.0750SThirdchildFalseNaNSouthamptonnoFalse
813female27.00211.1333SThirdwomanFalseNaNSouthamptonyesFalse
912female14.01030.0708CSecondchildFalseNaNCherbourgyesFalse
................................................
88103male33.0007.8958SThirdmanTrueNaNSouthamptonnoTrue
88203female22.00010.5167SThirdwomanFalseNaNSouthamptonnoTrue
88302male28.00010.5000SSecondmanTrueNaNSouthamptonnoTrue
88403male25.0007.0500SThirdmanTrueNaNSouthamptonnoTrue
88503female39.00529.1250QThirdwomanFalseNaNQueenstownnoFalse
88602male27.00013.0000SSecondmanTrueNaNSouthamptonnoTrue
88711female19.00030.0000SFirstwomanFalseBSouthamptonyesTrue
88803femaleNaN1223.4500SThirdwomanFalseNaNSouthamptonnoFalse
88911male26.00030.0000CFirstmanTrueCCherbourgyesTrue
89003male32.0007.7500QThirdmanTrueNaNQueenstownnoTrue
\n", "

891 rows × 15 columns

\n", "
" ], "text/plain": [ " survived pclass sex age sibsp parch fare embarked class \\\n", "0 0 3 male 22.0 1 0 7.2500 S Third \n", "1 1 1 female 38.0 1 0 71.2833 C First \n", "2 1 3 female 26.0 0 0 7.9250 S Third \n", "3 1 1 female 35.0 1 0 53.1000 S First \n", "4 0 3 male 35.0 0 0 8.0500 S Third \n", "5 0 3 male NaN 0 0 8.4583 Q Third \n", "6 0 1 male 54.0 0 0 51.8625 S First \n", "7 0 3 male 2.0 3 1 21.0750 S Third \n", "8 1 3 female 27.0 0 2 11.1333 S Third \n", "9 1 2 female 14.0 1 0 30.0708 C Second \n", "10 1 3 female 4.0 1 1 16.7000 S Third \n", "11 1 1 female 58.0 0 0 26.5500 S First \n", "12 0 3 male 20.0 0 0 8.0500 S Third \n", "13 0 3 male 39.0 1 5 31.2750 S Third \n", "14 0 3 female 14.0 0 0 7.8542 S Third \n", "15 1 2 female 55.0 0 0 16.0000 S Second \n", "16 0 3 male 2.0 4 1 29.1250 Q Third \n", "17 1 2 male NaN 0 0 13.0000 S Second \n", "18 0 3 female 31.0 1 0 18.0000 S Third \n", "19 1 3 female NaN 0 0 7.2250 C Third \n", "20 0 2 male 35.0 0 0 26.0000 S Second \n", "21 1 2 male 34.0 0 0 13.0000 S Second \n", "22 1 3 female 15.0 0 0 8.0292 Q Third \n", "23 1 1 male 28.0 0 0 35.5000 S First \n", "24 0 3 female 8.0 3 1 21.0750 S Third \n", "25 1 3 female 38.0 1 5 31.3875 S Third \n", "26 0 3 male NaN 0 0 7.2250 C Third \n", "27 0 1 male 19.0 3 2 263.0000 S First \n", "28 1 3 female NaN 0 0 7.8792 Q Third \n", "29 0 3 male NaN 0 0 7.8958 S Third \n", ".. ... ... ... ... ... ... ... ... ... \n", "861 0 2 male 21.0 1 0 11.5000 S Second \n", "862 1 1 female 48.0 0 0 25.9292 S First \n", "863 0 3 female NaN 8 2 69.5500 S Third \n", "864 0 2 male 24.0 0 0 13.0000 S Second \n", "865 1 2 female 42.0 0 0 13.0000 S Second \n", "866 1 2 female 27.0 1 0 13.8583 C Second \n", "867 0 1 male 31.0 0 0 50.4958 S First \n", "868 0 3 male NaN 0 0 9.5000 S Third \n", "869 1 3 male 4.0 1 1 11.1333 S Third \n", "870 0 3 male 26.0 0 0 7.8958 S Third \n", "871 1 1 female 47.0 1 1 52.5542 S First \n", "872 0 1 male 33.0 0 0 5.0000 S First \n", "873 0 3 male 47.0 0 0 9.0000 S Third \n", "874 1 2 female 28.0 1 0 24.0000 C Second \n", "875 1 3 female 15.0 0 0 7.2250 C Third \n", "876 0 3 male 20.0 0 0 9.8458 S Third \n", "877 0 3 male 19.0 0 0 7.8958 S Third \n", "878 0 3 male NaN 0 0 7.8958 S Third \n", "879 1 1 female 56.0 0 1 83.1583 C First \n", "880 1 2 female 25.0 0 1 26.0000 S Second \n", "881 0 3 male 33.0 0 0 7.8958 S Third \n", "882 0 3 female 22.0 0 0 10.5167 S Third \n", "883 0 2 male 28.0 0 0 10.5000 S Second \n", "884 0 3 male 25.0 0 0 7.0500 S Third \n", "885 0 3 female 39.0 0 5 29.1250 Q Third \n", "886 0 2 male 27.0 0 0 13.0000 S Second \n", "887 1 1 female 19.0 0 0 30.0000 S First \n", "888 0 3 female NaN 1 2 23.4500 S Third \n", "889 1 1 male 26.0 0 0 30.0000 C First \n", "890 0 3 male 32.0 0 0 7.7500 Q Third \n", "\n", " who adult_male deck embark_town alive alone \n", "0 man True NaN Southampton no False \n", "1 woman False C Cherbourg yes False \n", "2 woman False NaN Southampton yes True \n", "3 woman False C Southampton yes False \n", "4 man True NaN Southampton no True \n", "5 man True NaN Queenstown no True \n", "6 man True E Southampton no True \n", "7 child False NaN Southampton no False \n", "8 woman False NaN Southampton yes False \n", "9 child False NaN Cherbourg yes False \n", "10 child False G Southampton yes False \n", "11 woman False C Southampton yes True \n", "12 man True NaN Southampton no True \n", "13 man True NaN Southampton no False \n", "14 child False NaN Southampton no True \n", "15 woman False NaN Southampton yes True \n", "16 child False NaN Queenstown no False \n", "17 man True NaN Southampton yes True \n", "18 woman False NaN Southampton no False \n", "19 woman False NaN Cherbourg yes True \n", "20 man True NaN Southampton no True \n", "21 man True D Southampton yes True \n", "22 child False NaN Queenstown yes True \n", "23 man True A Southampton yes True \n", "24 child False NaN Southampton no False \n", "25 woman False NaN Southampton yes False \n", "26 man True NaN Cherbourg no True \n", "27 man True C Southampton no False \n", "28 woman False NaN Queenstown yes True \n", "29 man True NaN Southampton no True \n", ".. ... ... ... ... ... ... \n", "861 man True NaN Southampton no False \n", "862 woman False D Southampton yes True \n", "863 woman False NaN Southampton no False \n", "864 man True NaN Southampton no True \n", "865 woman False NaN Southampton yes True \n", "866 woman False NaN Cherbourg yes False \n", "867 man True A Southampton no True \n", "868 man True NaN Southampton no True \n", "869 child False NaN Southampton yes False \n", "870 man True NaN Southampton no True \n", "871 woman False D Southampton yes False \n", "872 man True B Southampton no True \n", "873 man True NaN Southampton no True \n", "874 woman False NaN Cherbourg yes False \n", "875 child False NaN Cherbourg yes True \n", "876 man True NaN Southampton no True \n", "877 man True NaN Southampton no True \n", "878 man True NaN Southampton no True \n", "879 woman False C Cherbourg yes False \n", "880 woman False NaN Southampton yes False \n", "881 man True NaN Southampton no True \n", "882 woman False NaN Southampton no True \n", "883 man True NaN Southampton no True \n", "884 man True NaN Southampton no True \n", "885 woman False NaN Queenstown no False \n", "886 man True NaN Southampton no True \n", "887 woman False B Southampton yes True \n", "888 woman False NaN Southampton no False \n", "889 man True C Cherbourg yes True \n", "890 man True NaN Queenstown no True \n", "\n", "[891 rows x 15 columns]" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = sns.load_dataset.('titanic')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "変数 `df` に代入されたオブジェクトは pandas のデータフレームです。" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "pytype(DataFrame)" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.type" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "データ解析の最初のステップは、データの内容を観察することから始まります。\n", "\n", "上の表を見るとわかるように、このデータには、15個のカラムで構成されるレコードが890行あります。\n", "これらのカラムのうち、以下のように内容が重複しているものがあります。\n", "\n", "- `survived` は `alive` を `no` -> 0, `yes` -> 1 として変換して生成したもの\n", "- `embarked` は `embark_town` の頭文字\n", "- `pclass` は `class` を数値にしたもの\n", "- `sex` と `who` は、`male` => `man`, `female` => `woman` という対応関係にある\n", "\n", "内容が重複しているカラムが複数存在すると、情報量は変わらないのに処理量が増えてしまうため、これらを削除します。" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array(['survived', 'pclass', 'sex', 'age', 'sibsp', 'parch', 'fare',\n", " 'embarked', 'adult_male', 'deck', 'alone'], dtype=object)" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = df.drop.([:alive, :embark_town, :class, :who], axis: 1)\n", "df.columns.values" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "こうして残ったカラムは次のような意味を持っています。\n", "\n", "| カラム名 | 意味 |\n", "|:--- |:--- |\n", "| `survived` | 1: 生存, 0: 死亡 |\n", "| `pclass` | 乗客クラス (1: Upper, 2: Middle, 3: Lower) |\n", "| `sex` | 性別 (`male`: 男性, `female`: 女性) |\n", "| `age` | 年齢 (1歳未満は小数) |\n", "| `sibsp` | 同乗している兄弟・配偶者の人数 |\n", "| `parch` | 同乗している親・子供の人数 |\n", "| `fare` | チケット料金 |\n", "| `embarked` | 乗船した都市名の頭文字 |\n", "| `adult_male` | 大人の男性の場合 true |\n", "| `deck` | 客室種別 |\n", "| `alone` | 一人で乗船の場合 true |" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "生のデータにはほぼ確実に欠損値が含まれています。このデータの場合はどうでしょうか?調べてみましょう。\n", "\n", "データフレームの `isnull` メソッドを用いると、各行各列について欠損値の場合に `true`、そうで無い場合に `false` を対応させた同じ形のデータフレームが作られます。そのような欠損値フラグを集めたデータフレムに対して `sum` メソッドを適用することで、カラム別に欠損値の個数をカウントできます (`true` を 1, `false` を 0 として総和をとる)。" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "survived 0\n", "pclass 0\n", "sex 0\n", "age 177\n", "sibsp 0\n", "parch 0\n", "fare 0\n", "embarked 2\n", "adult_male 0\n", "deck 688\n", "alone 0\n", "dtype: int64" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.isnull.().sum.()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "これより、`age` カラムには177個の欠損値、`deck` カラムには688個の欠損値が存在し、その他のカラムには欠損値が無いことがわかりました。\n", "\n", "全体で890行あるうち688個も値が欠損しているということは、`deck` カラムの値は分析には使えなさそうです。\n", "今回は `deck` カラムは捨てることにします。" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": true }, "outputs": [], "source": [ "df = df.drop.(:deck, axis: 1)\n", "nil" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`age` カラムの分布を見てみましょう。" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sampled_age = df[:age].dropna.().sample.(100) # 全てのデータを使うと少し時間がかかるのでランダムサンプリングする\n", "sns.kdeplot.(sampled_age, shade: true, cut: 0)\n", "sns.rugplot.(sampled_age)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "あと、平均値も見てみます。せっかくなので全カラムの要約統計量を `describe` メソッドで求めましょう。" ] }, { "cell_type": "code", "execution_count": 33, "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", "
survivedpclassagesibspparchfare
count891.000000891.000000714.000000891.000000891.000000891.000000
mean0.3838382.30864229.6991180.5230080.38159432.204208
std0.4865920.83607114.5264971.1027430.80605749.693429
min0.0000001.0000000.4200000.0000000.0000000.000000
25%0.0000002.00000020.1250000.0000000.0000007.910400
50%0.0000003.00000028.0000000.0000000.00000014.454200
75%1.0000003.00000038.0000001.0000000.00000031.000000
max1.0000003.00000080.0000008.0000006.000000512.329200
\n", "

8 rows × 6 columns

\n", "
" ], "text/plain": [ " survived pclass age sibsp parch fare\n", "count 891.000000 891.000000 714.000000 891.000000 891.000000 891.000000\n", "mean 0.383838 2.308642 29.699118 0.523008 0.381594 32.204208\n", "std 0.486592 0.836071 14.526497 1.102743 0.806057 49.693429\n", "min 0.000000 1.000000 0.420000 0.000000 0.000000 0.000000\n", "25% 0.000000 2.000000 20.125000 0.000000 0.000000 7.910400\n", "50% 0.000000 3.000000 28.000000 0.000000 0.000000 14.454200\n", "75% 1.000000 3.000000 38.000000 1.000000 0.000000 31.000000\n", "max 1.000000 3.000000 80.000000 8.000000 6.000000 512.329200" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.describe.()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`age` の平均値は 29.699118、中央値は 28 であることが分かりました。\n", "\n", "`age` の欠損値の位置を記録しておいて、ひとまず中央値を使って欠損値を埋めることにします。" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": true }, "outputs": [], "source": [ "age_isnull = df[:age].isnull.() # 欠損値の位置を記憶 (あとで使うかもしれないので)\n", "nil" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": true }, "outputs": [], "source": [ "df[:age].fillna.(df[:age].median.(), inplace: true) # 欠損値を中央値で埋める\n", "nil" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "もう一度欠損値の個数を求めてみましょう。" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "survived 0\n", "pclass 0\n", "sex 0\n", "age 0\n", "sibsp 0\n", "parch 0\n", "fare 0\n", "embarked 2\n", "adult_male 0\n", "alone 0\n", "dtype: int64" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.isnull.().sum.()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "残るは `embarked` の2つですが、2件だけなので無視して進みます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "生存予測をするためのモデルを作るので、予測の対象となるカラムは `survived` です。\n", "まず、各カラムが `survived` とどのくらい相関を持っているか見てみましょう。\n", "そのためには、ラベルが入っている `sex` と `embarked` の2カラムの値を数値に変換する必要があります。\n", "\n", "ラベル変数を数値変数へ変換したものをダミー変数と言い、pandas では `get_dummies` 関数を使って処理します。" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "scrolled": false }, "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", " \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", " \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", " \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", "
survivedpclassagesibspparchfareadult_malealonefemalemaleCQ
00322.0107.2500TrueFalse0100
11138.01071.2833FalseFalse1010
21326.0007.9250FalseTrue1000
31135.01053.1000FalseFalse1000
40335.0008.0500TrueTrue0100
50328.0008.4583TrueTrue0101
60154.00051.8625TrueTrue0100
7032.03121.0750FalseFalse0100
81327.00211.1333FalseFalse1000
91214.01030.0708FalseFalse1010
.......................................
8810333.0007.8958TrueTrue0100
8820322.00010.5167FalseTrue1000
8830228.00010.5000TrueTrue0100
8840325.0007.0500TrueTrue0100
8850339.00529.1250FalseFalse1001
8860227.00013.0000TrueTrue0100
8871119.00030.0000FalseTrue1000
8880328.01223.4500FalseFalse1000
8891126.00030.0000TrueTrue0110
8900332.0007.7500TrueTrue0101
\n", "

891 rows × 12 columns

\n", "
" ], "text/plain": [ " survived pclass age sibsp parch fare adult_male alone female \\\n", "0 0 3 22.0 1 0 7.2500 True False 0 \n", "1 1 1 38.0 1 0 71.2833 False False 1 \n", "2 1 3 26.0 0 0 7.9250 False True 1 \n", "3 1 1 35.0 1 0 53.1000 False False 1 \n", "4 0 3 35.0 0 0 8.0500 True True 0 \n", "5 0 3 28.0 0 0 8.4583 True True 0 \n", "6 0 1 54.0 0 0 51.8625 True True 0 \n", "7 0 3 2.0 3 1 21.0750 False False 0 \n", "8 1 3 27.0 0 2 11.1333 False False 1 \n", "9 1 2 14.0 1 0 30.0708 False False 1 \n", "10 1 3 4.0 1 1 16.7000 False False 1 \n", "11 1 1 58.0 0 0 26.5500 False True 1 \n", "12 0 3 20.0 0 0 8.0500 True True 0 \n", "13 0 3 39.0 1 5 31.2750 True False 0 \n", "14 0 3 14.0 0 0 7.8542 False True 1 \n", "15 1 2 55.0 0 0 16.0000 False True 1 \n", "16 0 3 2.0 4 1 29.1250 False False 0 \n", "17 1 2 28.0 0 0 13.0000 True True 0 \n", "18 0 3 31.0 1 0 18.0000 False False 1 \n", "19 1 3 28.0 0 0 7.2250 False True 1 \n", "20 0 2 35.0 0 0 26.0000 True True 0 \n", "21 1 2 34.0 0 0 13.0000 True True 0 \n", "22 1 3 15.0 0 0 8.0292 False True 1 \n", "23 1 1 28.0 0 0 35.5000 True True 0 \n", "24 0 3 8.0 3 1 21.0750 False False 1 \n", "25 1 3 38.0 1 5 31.3875 False False 1 \n", "26 0 3 28.0 0 0 7.2250 True True 0 \n", "27 0 1 19.0 3 2 263.0000 True False 0 \n", "28 1 3 28.0 0 0 7.8792 False True 1 \n", "29 0 3 28.0 0 0 7.8958 True True 0 \n", ".. ... ... ... ... ... ... ... ... ... \n", "861 0 2 21.0 1 0 11.5000 True False 0 \n", "862 1 1 48.0 0 0 25.9292 False True 1 \n", "863 0 3 28.0 8 2 69.5500 False False 1 \n", "864 0 2 24.0 0 0 13.0000 True True 0 \n", "865 1 2 42.0 0 0 13.0000 False True 1 \n", "866 1 2 27.0 1 0 13.8583 False False 1 \n", "867 0 1 31.0 0 0 50.4958 True True 0 \n", "868 0 3 28.0 0 0 9.5000 True True 0 \n", "869 1 3 4.0 1 1 11.1333 False False 0 \n", "870 0 3 26.0 0 0 7.8958 True True 0 \n", "871 1 1 47.0 1 1 52.5542 False False 1 \n", "872 0 1 33.0 0 0 5.0000 True True 0 \n", "873 0 3 47.0 0 0 9.0000 True True 0 \n", "874 1 2 28.0 1 0 24.0000 False False 1 \n", "875 1 3 15.0 0 0 7.2250 False True 1 \n", "876 0 3 20.0 0 0 9.8458 True True 0 \n", "877 0 3 19.0 0 0 7.8958 True True 0 \n", "878 0 3 28.0 0 0 7.8958 True True 0 \n", "879 1 1 56.0 0 1 83.1583 False False 1 \n", "880 1 2 25.0 0 1 26.0000 False False 1 \n", "881 0 3 33.0 0 0 7.8958 True True 0 \n", "882 0 3 22.0 0 0 10.5167 False True 1 \n", "883 0 2 28.0 0 0 10.5000 True True 0 \n", "884 0 3 25.0 0 0 7.0500 True True 0 \n", "885 0 3 39.0 0 5 29.1250 False False 1 \n", "886 0 2 27.0 0 0 13.0000 True True 0 \n", "887 1 1 19.0 0 0 30.0000 False True 1 \n", "888 0 3 28.0 1 2 23.4500 False False 1 \n", "889 1 1 26.0 0 0 30.0000 True True 0 \n", "890 0 3 32.0 0 0 7.7500 True True 0 \n", "\n", " male C Q \n", "0 1 0 0 \n", "1 0 1 0 \n", "2 0 0 0 \n", "3 0 0 0 \n", "4 1 0 0 \n", "5 1 0 1 \n", "6 1 0 0 \n", "7 1 0 0 \n", "8 0 0 0 \n", "9 0 1 0 \n", "10 0 0 0 \n", "11 0 0 0 \n", "12 1 0 0 \n", "13 1 0 0 \n", "14 0 0 0 \n", "15 0 0 0 \n", "16 1 0 1 \n", "17 1 0 0 \n", "18 0 0 0 \n", "19 0 1 0 \n", "20 1 0 0 \n", "21 1 0 0 \n", "22 0 0 1 \n", "23 1 0 0 \n", "24 0 0 0 \n", "25 0 0 0 \n", "26 1 1 0 \n", "27 1 0 0 \n", "28 0 0 1 \n", "29 1 0 0 \n", ".. ... .. .. \n", "861 1 0 0 \n", "862 0 0 0 \n", "863 0 0 0 \n", "864 1 0 0 \n", "865 0 0 0 \n", "866 0 1 0 \n", "867 1 0 0 \n", "868 1 0 0 \n", "869 1 0 0 \n", "870 1 0 0 \n", "871 0 0 0 \n", "872 1 0 0 \n", "873 1 0 0 \n", "874 0 1 0 \n", "875 0 1 0 \n", "876 1 0 0 \n", "877 1 0 0 \n", "878 1 0 0 \n", "879 0 1 0 \n", "880 0 0 0 \n", "881 1 0 0 \n", "882 0 0 0 \n", "883 1 0 0 \n", "884 1 0 0 \n", "885 0 0 1 \n", "886 1 0 0 \n", "887 0 0 0 \n", "888 0 0 0 \n", "889 1 1 0 \n", "890 1 0 1 \n", "\n", "[891 rows x 12 columns]" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sex_dummies = pd.get_dummies.(df[:sex])\n", "embarked_dummies = pd.get_dummies.(df[:embarked])\n", "df = pd.concat.(PyCall.tuple(df, sex_dummies, embarked_dummies), axis: 1)\n", "df = df.drop.([:sex, :embarked, :S], axis: 1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`sex` のダミー変数である `female` と `male`, および `embarked` のダミー変数である `C`, `Q` が追加されました。\n", "元の `sex` と `embarked` は削除しました。\n", "\n", "`embarked` のダミー変数にはもう一つ `S` が存在していますが、`C` と `Q` の両方が 0 の場合、(2件ある欠損値を除いて) `S` が 1 になっているはずです。ですから、`S` は情報量を持たないため削除しています。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "これで、全てのカラムが数値データになったので、カラム間の相関係数を `corr` メソッドで求めます。" ] }, { "cell_type": "code", "execution_count": 38, "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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
survivedpclassagesibspparchfareadult_malealonefemalemaleCQ
survived1.000000-0.338481-0.064910-0.0353220.0816290.257307-0.557080-0.2033670.543351-0.5433510.1682400.003650
pclass-0.3384811.000000-0.3398980.0830810.018443-0.5495000.0940350.135207-0.1319000.131900-0.2432920.221009
age-0.064910-0.3398981.000000-0.233296-0.1724820.0966880.2477040.171647-0.0811630.0811630.030248-0.031415
sibsp-0.0353220.083081-0.2332961.0000000.4148380.159651-0.253586-0.5844710.114631-0.114631-0.059528-0.026354
parch0.0816290.018443-0.1724820.4148381.0000000.216225-0.349943-0.5833980.245489-0.245489-0.011069-0.081228
fare0.257307-0.5495000.0966880.1596510.2162251.000000-0.182024-0.2718320.182333-0.1823330.269335-0.117216
adult_male-0.5570800.0940350.247704-0.253586-0.349943-0.1820241.0000000.404744-0.9085780.908578-0.065980-0.076789
alone-0.2033670.1352070.171647-0.584471-0.583398-0.2718320.4047441.000000-0.3036460.303646-0.0952980.086464
female0.543351-0.131900-0.0811630.1146310.2454890.182333-0.908578-0.3036461.000000-1.0000000.0828530.074115
male-0.5433510.1319000.081163-0.114631-0.245489-0.1823330.9085780.303646-1.0000001.000000-0.082853-0.074115
C0.168240-0.2432920.030248-0.059528-0.0110690.269335-0.065980-0.0952980.082853-0.0828531.000000-0.148258
Q0.0036500.221009-0.031415-0.026354-0.081228-0.117216-0.0767890.0864640.074115-0.074115-0.1482581.000000
\n", "

12 rows × 12 columns

\n", "
" ], "text/plain": [ " survived pclass age sibsp parch fare \\\n", "survived 1.000000 -0.338481 -0.064910 -0.035322 0.081629 0.257307 \n", "pclass -0.338481 1.000000 -0.339898 0.083081 0.018443 -0.549500 \n", "age -0.064910 -0.339898 1.000000 -0.233296 -0.172482 0.096688 \n", "sibsp -0.035322 0.083081 -0.233296 1.000000 0.414838 0.159651 \n", "parch 0.081629 0.018443 -0.172482 0.414838 1.000000 0.216225 \n", "fare 0.257307 -0.549500 0.096688 0.159651 0.216225 1.000000 \n", "adult_male -0.557080 0.094035 0.247704 -0.253586 -0.349943 -0.182024 \n", "alone -0.203367 0.135207 0.171647 -0.584471 -0.583398 -0.271832 \n", "female 0.543351 -0.131900 -0.081163 0.114631 0.245489 0.182333 \n", "male -0.543351 0.131900 0.081163 -0.114631 -0.245489 -0.182333 \n", "C 0.168240 -0.243292 0.030248 -0.059528 -0.011069 0.269335 \n", "Q 0.003650 0.221009 -0.031415 -0.026354 -0.081228 -0.117216 \n", "\n", " adult_male alone female male C Q \n", "survived -0.557080 -0.203367 0.543351 -0.543351 0.168240 0.003650 \n", "pclass 0.094035 0.135207 -0.131900 0.131900 -0.243292 0.221009 \n", "age 0.247704 0.171647 -0.081163 0.081163 0.030248 -0.031415 \n", "sibsp -0.253586 -0.584471 0.114631 -0.114631 -0.059528 -0.026354 \n", "parch -0.349943 -0.583398 0.245489 -0.245489 -0.011069 -0.081228 \n", "fare -0.182024 -0.271832 0.182333 -0.182333 0.269335 -0.117216 \n", "adult_male 1.000000 0.404744 -0.908578 0.908578 -0.065980 -0.076789 \n", "alone 0.404744 1.000000 -0.303646 0.303646 -0.095298 0.086464 \n", "female -0.908578 -0.303646 1.000000 -1.000000 0.082853 0.074115 \n", "male 0.908578 0.303646 -1.000000 1.000000 -0.082853 -0.074115 \n", "C -0.065980 -0.095298 0.082853 -0.082853 1.000000 -0.148258 \n", "Q -0.076789 0.086464 0.074115 -0.074115 -0.148258 1.000000 " ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.corr.()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "性別系のカラム (`female`, `male`, `adult_male`) が最も相関が高いことがわかります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "### モデリング\n", "\n", "ここでは、ランダムフォレスト ( `sklearn.ensemble.RandomForestClassifier` )、ロジスティック回帰 ( `sklearn.linear_model.LogisticRegression` )、サポートベクトルマシン ( `sklearn.svm.SVC` ) の3種類のモデルを作り、それぞれの精度を比較します。\n", "モデルのハイパーパラメータをグリッドサーチ ( `sklearn.model_selection.GridSearchCV` ) で最適化します。" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "pytype(GridSearchCV)" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pyfrom 'sklearn.ensemble', import: :RandomForestClassifier\n", "pyfrom 'sklearn.linear_model', import: :LogisticRegression\n", "pyfrom 'sklearn.svm', import: :SVC\n", "pyfrom 'sklearn.model_selection', import: :GridSearchCV" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### ランダムフォレストによる分類モデルの作成" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "GridSearchCV(cv=5, error_score='raise',\n", " estimator=RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',\n", " max_depth=None, max_features='auto', max_leaf_nodes=None,\n", " min_impurity_split=1e-07, min_samples_leaf=1,\n", " min_samples_split=2, min_weight_fraction_leaf=0.0,\n", " n_estimators=10, n_jobs=2, oob_score=False, random_state=None,\n", " verbose=0, warm_start=False),\n", " fit_params={}, iid=True, n_jobs=4,\n", " param_grid={'n_estimators': [10, 20, 50], 'max_depth': [4, 5, 6, 7], 'max_features': ['auto', 'log2', None]},\n", " pre_dispatch='2*n_jobs', refit=True, return_train_score=True,\n", " scoring='roc_auc', verbose=0)" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rfc = GridSearchCV.(\n", " RandomForestClassifier.(n_jobs: 2),\n", " {\n", " n_estimators: [10, 20, 50],\n", " max_depth: [4, 5, 6, 7],\n", " max_features: [:auto, :log2, PyCall.None],\n", " },\n", " scoring: :roc_auc,\n", " n_jobs: 4,\n", " cv: 5\n", ")" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "GridSearchCV(cv=5, error_score='raise',\n", " estimator=RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',\n", " max_depth=None, max_features='auto', max_leaf_nodes=None,\n", " min_impurity_split=1e-07, min_samples_leaf=1,\n", " min_samples_split=2, min_weight_fraction_leaf=0.0,\n", " n_estimators=10, n_jobs=2, oob_score=False, random_state=None,\n", " verbose=0, warm_start=False),\n", " fit_params={}, iid=True, n_jobs=4,\n", " param_grid={'n_estimators': [10, 20, 50], 'max_depth': [4, 5, 6, 7], 'max_features': ['auto', 'log2', None]},\n", " pre_dispatch='2*n_jobs', refit=True, return_train_score=True,\n", " scoring='roc_auc', verbose=0)" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x_names = [:pclass, :age, :sibsp, :parch, :fare, :adult_male, :alone, :female, :male, :C, :Q]\n", "x = df[x_names]\n", "y = df[:survived]\n", "rfc.fit.(x, y)" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'max_depth': 7, 'max_features': 'auto', 'n_estimators': 20}" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rfc.best_params_" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.8764839649977957" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rfc.best_score_" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "グリッドサーチおよび交差検定の結果は `cv_results_` 属性に入っています。この属性の値は、そのまま pandas の DataFrame に渡せます。" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "scrolled": false }, "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", " \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", " \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", " \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", " \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", " \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", "
mean_fit_timemean_score_timemean_test_scoremean_train_scoreparam_max_depthparam_max_featuresparam_n_estimatorsrank_test_scoresplit0_test_scoresplit0_train_scoresplit1_test_scoresplit1_train_scoresplit2_test_scoresplit2_train_scoresplit3_test_scoresplit3_train_scoresplit4_test_scoresplit4_train_scorestd_fit_timestd_score_timestd_test_scorestd_train_score
00.1350950.1055500.8630780.8936004auto10340.8575100.8931220.8272730.9079410.8620990.8880210.8675130.8904150.9014440.8885000.0121070.0006270.0236710.007392
10.1252550.1034050.8586640.8957144auto20360.8544140.9002060.8200920.9024510.8700530.8917210.8468580.8951670.9023880.8890260.0061310.0004560.0271300.005031
20.1824100.1043240.8662820.8969974auto50250.8560610.9005690.8297100.9075400.8729280.8948710.8702540.8968580.9029280.8851440.0123500.0011520.0238420.007334
30.1325390.1040100.8646710.8913644log210310.8625160.8896260.8250330.9027180.8665110.8884910.8741980.8960730.8955070.8799150.0113790.0007050.0228970.007661
40.1529710.1042650.8648050.8955174log220300.8639000.8989290.8322790.9018620.8638370.8890230.8653070.9022700.8990830.8855010.0240550.0008320.0211270.006928
50.1525430.1034660.8651510.8967614log250290.8538210.8971980.8366930.9061930.8715240.8929880.8631020.8994360.9010390.8879890.0068870.0008390.0212910.006123
60.1149020.1029680.8684850.9154554None10210.8532940.9232270.8324770.9258600.8775400.9124670.8582890.9117060.9214110.9040150.0037080.0002340.0300080.008032
70.1243460.1040100.8657440.9200274None20270.8407110.9241740.8174570.9314540.8829550.9159130.8677810.9157670.9205340.9128280.0048020.0020740.0353650.006851
80.1551400.1030400.8658410.9202214None50260.8378130.9253670.8133730.9322430.8908420.9172930.8803480.9204270.9075150.9057770.0109090.0002230.0349680.008812
90.1150440.1035780.8734320.9122435auto1060.8713440.9263940.8388670.9171360.8768050.9080150.8641710.9113320.9164190.8983370.0015890.0009830.0250480.009341
.....................................................................
260.1393500.1027830.8677160.9597546None50220.8386690.9618720.8155470.9659820.8969250.9534110.8649730.9604780.9232330.9570260.0018270.0006210.0387360.004277
270.1123840.1028760.8664790.9464157auto10240.8517130.9514260.8139000.9557060.8862300.9444030.8784090.9404500.9027250.9400880.0019990.0006970.0310890.006182
280.1232560.1032520.8764840.9507037auto2010.8596180.9569450.8281950.9608380.8802140.9450730.8886360.9504930.9264030.9401670.0066650.0006270.0324490.007542
290.1434060.1028110.8751910.9554437auto5020.8633730.9589690.8293150.9630990.8951200.9480070.8659090.9558430.9228280.9512980.0036350.0004050.0315950.005360
300.1147500.1035710.8606260.9456367log210350.8517130.9514260.8159420.9513840.8896390.9411440.8436500.9441370.9027250.9400880.0021560.0008100.0315420.004894
310.1243440.1053110.8719640.9524077log22080.8454550.9553510.8313570.9616180.8877010.9473840.8886360.9504930.9072450.9471880.0038140.0041630.0287180.005471
320.1495120.1038680.8693590.9523237log250170.8543480.9562730.8194330.9591900.8951200.9480070.8602940.9508500.9182410.9472920.0101450.0010120.0342010.004666
330.1125300.1042840.8715600.9680327None1090.8456520.9740790.8137680.9751930.8996660.9598330.8847590.9696220.9146650.9614300.0018910.0008380.0369800.006343
340.1207630.1029490.8646540.9717897None20320.8417000.9740590.8118580.9770670.8954550.9671910.8584220.9742530.9165540.9663780.0011160.0003480.0373930.004231
350.1397710.1031920.8713350.9732697None50100.8386030.9739670.8123190.9783770.9102270.9702090.8819520.9744150.9143280.9693760.0025130.0004250.0400850.003238
\n", "

36 rows × 22 columns

\n", "
" ], "text/plain": [ " mean_fit_time mean_score_time mean_test_score mean_train_score \\\n", "0 0.135095 0.105550 0.863078 0.893600 \n", "1 0.125255 0.103405 0.858664 0.895714 \n", "2 0.182410 0.104324 0.866282 0.896997 \n", "3 0.132539 0.104010 0.864671 0.891364 \n", "4 0.152971 0.104265 0.864805 0.895517 \n", "5 0.152543 0.103466 0.865151 0.896761 \n", "6 0.114902 0.102968 0.868485 0.915455 \n", "7 0.124346 0.104010 0.865744 0.920027 \n", "8 0.155140 0.103040 0.865841 0.920221 \n", "9 0.115044 0.103578 0.873432 0.912243 \n", "10 0.119204 0.105111 0.872546 0.914753 \n", "11 0.154862 0.103477 0.870855 0.917777 \n", "12 0.115686 0.103893 0.868964 0.910325 \n", "13 0.128181 0.103131 0.863800 0.910893 \n", "14 0.160281 0.103907 0.869836 0.917284 \n", "15 0.117599 0.104991 0.873508 0.934520 \n", "16 0.126553 0.105983 0.869542 0.940223 \n", "17 0.153157 0.103327 0.871002 0.942536 \n", "18 0.118098 0.103806 0.865280 0.930026 \n", "19 0.127066 0.103749 0.868677 0.932113 \n", "20 0.141172 0.103467 0.874621 0.936588 \n", "21 0.115320 0.103669 0.874284 0.928126 \n", "22 0.121289 0.103003 0.869396 0.932330 \n", "23 0.151305 0.103404 0.868924 0.938588 \n", "24 0.112815 0.103616 0.869369 0.953285 \n", "25 0.120892 0.102985 0.867146 0.957426 \n", "26 0.139350 0.102783 0.867716 0.959754 \n", "27 0.112384 0.102876 0.866479 0.946415 \n", "28 0.123256 0.103252 0.876484 0.950703 \n", "29 0.143406 0.102811 0.875191 0.955443 \n", "30 0.114750 0.103571 0.860626 0.945636 \n", "31 0.124344 0.105311 0.871964 0.952407 \n", "32 0.149512 0.103868 0.869359 0.952323 \n", "33 0.112530 0.104284 0.871560 0.968032 \n", "34 0.120763 0.102949 0.864654 0.971789 \n", "35 0.139771 0.103192 0.871335 0.973269 \n", "\n", " param_max_depth param_max_features param_n_estimators rank_test_score \\\n", "0 4 auto 10 34 \n", "1 4 auto 20 36 \n", "2 4 auto 50 25 \n", "3 4 log2 10 31 \n", "4 4 log2 20 30 \n", "5 4 log2 50 29 \n", "6 4 None 10 21 \n", "7 4 None 20 27 \n", "8 4 None 50 26 \n", "9 5 auto 10 6 \n", "10 5 auto 20 7 \n", "11 5 auto 50 12 \n", "12 5 log2 10 18 \n", "13 5 log2 20 33 \n", "14 5 log2 50 13 \n", "15 5 None 10 5 \n", "16 5 None 20 14 \n", "17 5 None 50 11 \n", "18 6 auto 10 28 \n", "19 6 auto 20 20 \n", "20 6 auto 50 3 \n", "21 6 log2 10 4 \n", "22 6 log2 20 15 \n", "23 6 log2 50 19 \n", "24 6 None 10 16 \n", "25 6 None 20 23 \n", "26 6 None 50 22 \n", "27 7 auto 10 24 \n", "28 7 auto 20 1 \n", "29 7 auto 50 2 \n", "30 7 log2 10 35 \n", "31 7 log2 20 8 \n", "32 7 log2 50 17 \n", "33 7 None 10 9 \n", "34 7 None 20 32 \n", "35 7 None 50 10 \n", "\n", " split0_test_score split0_train_score ... split2_test_score \\\n", "0 0.857510 0.893122 ... 0.862099 \n", "1 0.854414 0.900206 ... 0.870053 \n", "2 0.856061 0.900569 ... 0.872928 \n", "3 0.862516 0.889626 ... 0.866511 \n", "4 0.863900 0.898929 ... 0.863837 \n", "5 0.853821 0.897198 ... 0.871524 \n", "6 0.853294 0.923227 ... 0.877540 \n", "7 0.840711 0.924174 ... 0.882955 \n", "8 0.837813 0.925367 ... 0.890842 \n", "9 0.871344 0.926394 ... 0.876805 \n", "10 0.864163 0.911846 ... 0.888102 \n", "11 0.861067 0.918363 ... 0.876537 \n", "12 0.854875 0.916831 ... 0.873864 \n", "13 0.861924 0.915342 ... 0.877807 \n", "14 0.858893 0.917345 ... 0.883556 \n", "15 0.851713 0.943653 ... 0.905013 \n", "16 0.846706 0.942940 ... 0.898529 \n", "17 0.843083 0.946765 ... 0.897527 \n", "18 0.852701 0.938371 ... 0.873797 \n", "19 0.873847 0.941171 ... 0.882019 \n", "20 0.864097 0.941012 ... 0.895521 \n", "21 0.867852 0.927466 ... 0.893048 \n", "22 0.873847 0.941171 ... 0.879947 \n", "23 0.855599 0.940595 ... 0.885094 \n", "24 0.826943 0.951058 ... 0.914906 \n", "25 0.846772 0.957091 ... 0.890775 \n", "26 0.838669 0.961872 ... 0.896925 \n", "27 0.851713 0.951426 ... 0.886230 \n", "28 0.859618 0.956945 ... 0.880214 \n", "29 0.863373 0.958969 ... 0.895120 \n", "30 0.851713 0.951426 ... 0.889639 \n", "31 0.845455 0.955351 ... 0.887701 \n", "32 0.854348 0.956273 ... 0.895120 \n", "33 0.845652 0.974079 ... 0.899666 \n", "34 0.841700 0.974059 ... 0.895455 \n", "35 0.838603 0.973967 ... 0.910227 \n", "\n", " split2_train_score split3_test_score split3_train_score \\\n", "0 0.888021 0.867513 0.890415 \n", "1 0.891721 0.846858 0.895167 \n", "2 0.894871 0.870254 0.896858 \n", "3 0.888491 0.874198 0.896073 \n", "4 0.889023 0.865307 0.902270 \n", "5 0.892988 0.863102 0.899436 \n", "6 0.912467 0.858289 0.911706 \n", "7 0.915913 0.867781 0.915767 \n", "8 0.917293 0.880348 0.920427 \n", "9 0.908015 0.864171 0.911332 \n", "10 0.911311 0.882821 0.915551 \n", "11 0.913560 0.883757 0.920066 \n", "12 0.903800 0.875401 0.907853 \n", "13 0.908289 0.853075 0.910027 \n", "14 0.911827 0.871791 0.919288 \n", "15 0.927203 0.873463 0.937802 \n", "16 0.934261 0.863570 0.942944 \n", "17 0.936801 0.874332 0.944324 \n", "18 0.923042 0.868783 0.930520 \n", "19 0.928737 0.857420 0.935046 \n", "20 0.935013 0.871658 0.936489 \n", "21 0.920988 0.870388 0.932694 \n", "22 0.930644 0.869452 0.926633 \n", "23 0.932690 0.871658 0.936489 \n", "24 0.952850 0.873663 0.952114 \n", "25 0.952376 0.872326 0.958831 \n", "26 0.953411 0.864973 0.960478 \n", "27 0.944403 0.878409 0.940450 \n", "28 0.945073 0.888636 0.950493 \n", "29 0.948007 0.865909 0.955843 \n", "30 0.941144 0.843650 0.944137 \n", "31 0.947384 0.888636 0.950493 \n", "32 0.948007 0.860294 0.950850 \n", "33 0.959833 0.884759 0.969622 \n", "34 0.967191 0.858422 0.974253 \n", "35 0.970209 0.881952 0.974415 \n", "\n", " split4_test_score split4_train_score std_fit_time std_score_time \\\n", "0 0.901444 0.888500 0.012107 0.000627 \n", "1 0.902388 0.889026 0.006131 0.000456 \n", "2 0.902928 0.885144 0.012350 0.001152 \n", "3 0.895507 0.879915 0.011379 0.000705 \n", "4 0.899083 0.885501 0.024055 0.000832 \n", "5 0.901039 0.887989 0.006887 0.000839 \n", "6 0.921411 0.904015 0.003708 0.000234 \n", "7 0.920534 0.912828 0.004802 0.002074 \n", "8 0.907515 0.905777 0.010909 0.000223 \n", "9 0.916419 0.898337 0.001589 0.000983 \n", "10 0.911360 0.911961 0.001261 0.000830 \n", "11 0.909404 0.907590 0.008851 0.000683 \n", "12 0.907178 0.900527 0.003163 0.000692 \n", "13 0.908729 0.903243 0.004763 0.000626 \n", "14 0.912979 0.911894 0.023513 0.001555 \n", "15 0.925594 0.921155 0.007179 0.001646 \n", "16 0.922895 0.933975 0.005028 0.003048 \n", "17 0.922895 0.933033 0.008430 0.000568 \n", "18 0.915677 0.925245 0.006188 0.000669 \n", "19 0.910753 0.916004 0.006584 0.000852 \n", "20 0.918173 0.924498 0.001793 0.000669 \n", "21 0.923570 0.918161 0.002209 0.001296 \n", "22 0.910753 0.916004 0.001124 0.000493 \n", "23 0.917701 0.932735 0.007009 0.001459 \n", "24 0.914126 0.948984 0.001158 0.000908 \n", "25 0.916892 0.954931 0.002987 0.000276 \n", "26 0.923233 0.957026 0.001827 0.000621 \n", "27 0.902725 0.940088 0.001999 0.000697 \n", "28 0.926403 0.940167 0.006665 0.000627 \n", "29 0.922828 0.951298 0.003635 0.000405 \n", "30 0.902725 0.940088 0.002156 0.000810 \n", "31 0.907245 0.947188 0.003814 0.004163 \n", "32 0.918241 0.947292 0.010145 0.001012 \n", "33 0.914665 0.961430 0.001891 0.000838 \n", "34 0.916554 0.966378 0.001116 0.000348 \n", "35 0.914328 0.969376 0.002513 0.000425 \n", "\n", " std_test_score std_train_score \n", "0 0.023671 0.007392 \n", "1 0.027130 0.005031 \n", "2 0.023842 0.007334 \n", "3 0.022897 0.007661 \n", "4 0.021127 0.006928 \n", "5 0.021291 0.006123 \n", "6 0.030008 0.008032 \n", "7 0.035365 0.006851 \n", "8 0.034968 0.008812 \n", "9 0.025048 0.009341 \n", "10 0.031713 0.004435 \n", "11 0.028184 0.007212 \n", "12 0.024264 0.008222 \n", "13 0.029759 0.005106 \n", "14 0.029695 0.005292 \n", "15 0.039749 0.008884 \n", "16 0.037490 0.005201 \n", "17 0.037422 0.006772 \n", "18 0.032245 0.005479 \n", "19 0.029955 0.009140 \n", "20 0.031590 0.007148 \n", "21 0.034914 0.008315 \n", "22 0.031521 0.010964 \n", "23 0.033786 0.006600 \n", "24 0.041327 0.004270 \n", "25 0.036813 0.003892 \n", "26 0.038736 0.004277 \n", "27 0.031089 0.006182 \n", "28 0.032449 0.007542 \n", "29 0.031595 0.005360 \n", "30 0.031542 0.004894 \n", "31 0.028718 0.005471 \n", "32 0.034201 0.004666 \n", "33 0.036980 0.006343 \n", "34 0.037393 0.004231 \n", "35 0.040085 0.003238 \n", "\n", "[36 rows x 22 columns]" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.DataFrame.(data: rfc.cv_results_).drop.(:params, axis: 1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "もっとも成績が良かったランダムフォレストモデルにおける特徴量の重要度を見てみましょう。\n", "\n", "もっとも成績が良いモデルは `best_estimator_` で取得できます。\n", "このモデルは RandomForestClassifier のインスタンスなので、`feature_importances_` 属性を持っています。\n", "これと `x_names` を seaborn の barplot を使って可視化します。" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "image/png": "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tH37dh07dkyBgYEKDw/XXXfdpUGDBrm7PI9HKAacoEOHDu4uoUWpq6tTbW2tvLxa/n9ivv32WwUHBysmJsbhMc6cOaO2bds6sSoYgTO+e/AcR44c0W233SZfX19lZGSoZ8+eqqmp0YcffqjMzExt3brV3SVesOLiYi1ZskS7du3SiRMnFBwcrOuuu05Tp05tEX8UsnzCxSZNmqQ5c+Zozpw56tu3rwYOHKjFixfbjipWV1frueee09ChQ9WrVy8NHz5c//M//9PgWOXl5XrooYc0ePBg9e7dW2PGjNG7775r12fr1q0aM2aMoqKiNHDgQCUnJ+vHH3+U9PNyjPHjx6tPnz7q16+fbr31Vn333XeufQP089GQ2267Tf369dPAgQOVlpamw4cP27Z/9tlnGjt2rCIjI5WQkKBt27bV+6e8r776Snfffbeio6MVGxurRx55pN5tupvD2d7fhv7Zrra29qyfuyStW7dOI0aMUGRkpGJjYzVt2jTbtvN9b5ztfK/39ttvKyEhQdHR0br66quVnp5udxv1X5b67NixQwkJCYqMjNSnn34qSfrggw+UmJioyMhIDRw4UFOnTrV77Z9++kmPPfaYoqOjdc011+jNN990yRwb8uijj2ru3Lk6evSoQkNDFR8ff97v6y//1Jybm6uJEycqMjJSmzdvliR98sknuv322xUVFaWhQ4fqqaeesv3+nc35Xq+goEDjxo2z/X789z9xb9y4Uf369bNr++V3qCFLly7Vpk2b9P777ys0NFShoaH66KOPzlnj/53zL/NLTEzU119/rYKCAtt34+6777b7vSwoKFBKSooGDhyovn37auLEiSosLDznaxUXF+uBBx5Qv379NGDAAN177706cuRIo9+v//bxxx9r/Pjx6tWrl+Li4rRgwQLV1NTYtk+aNElPPfWUnn32WQ0YMEBXX321li5dajdGRUWFnnjiCV111VWKiYnRnXfeqS+++OKc8zifhr57VqtVr776quLj4xUVFaWbbrrJLgj98nu2a9cujRs3TlFRUbrzzjtVWlqqHTt26IYbblBMTIzS09NVVVXl8Hsmuf6/uZMmTdLcuXP19NNPq3///oqNjdX69ev1448/2v57MHz4cO34f+3daVhU59kH8P+IeIWKFglLAlhEdNgMiygKaixXVCSFVkMUqmArJKJVqxh6iUQEExIJ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", "text/plain": [ "" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_importance = pd.DataFrame.(data: {\n", " name: x_names,\n", " importance: rfc.best_estimator_.feature_importances_\n", "})\n", "sns.barplot.(x: :name, y: :importance, data: df_importance)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`adult_male` や性別 (`female`, `male`) が大きく寄与していることがわかります。\n", "逆に `alone`、`C`、`Q` はほとんど寄与していません。\n", "\n", "もう一度、カラム間の相関行列を見てみましょう。" ] }, { "cell_type": "code", "execution_count": 46, "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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
survivedpclassagesibspparchfareadult_malealonefemalemaleCQ
survived1.000000-0.338481-0.064910-0.0353220.0816290.257307-0.557080-0.2033670.543351-0.5433510.1682400.003650
pclass-0.3384811.000000-0.3398980.0830810.018443-0.5495000.0940350.135207-0.1319000.131900-0.2432920.221009
age-0.064910-0.3398981.000000-0.233296-0.1724820.0966880.2477040.171647-0.0811630.0811630.030248-0.031415
sibsp-0.0353220.083081-0.2332961.0000000.4148380.159651-0.253586-0.5844710.114631-0.114631-0.059528-0.026354
parch0.0816290.018443-0.1724820.4148381.0000000.216225-0.349943-0.5833980.245489-0.245489-0.011069-0.081228
fare0.257307-0.5495000.0966880.1596510.2162251.000000-0.182024-0.2718320.182333-0.1823330.269335-0.117216
adult_male-0.5570800.0940350.247704-0.253586-0.349943-0.1820241.0000000.404744-0.9085780.908578-0.065980-0.076789
alone-0.2033670.1352070.171647-0.584471-0.583398-0.2718320.4047441.000000-0.3036460.303646-0.0952980.086464
female0.543351-0.131900-0.0811630.1146310.2454890.182333-0.908578-0.3036461.000000-1.0000000.0828530.074115
male-0.5433510.1319000.081163-0.114631-0.245489-0.1823330.9085780.303646-1.0000001.000000-0.082853-0.074115
C0.168240-0.2432920.030248-0.059528-0.0110690.269335-0.065980-0.0952980.082853-0.0828531.000000-0.148258
Q0.0036500.221009-0.031415-0.026354-0.081228-0.117216-0.0767890.0864640.074115-0.074115-0.1482581.000000
\n", "

12 rows × 12 columns

\n", "
" ], "text/plain": [ " survived pclass age sibsp parch fare \\\n", "survived 1.000000 -0.338481 -0.064910 -0.035322 0.081629 0.257307 \n", "pclass -0.338481 1.000000 -0.339898 0.083081 0.018443 -0.549500 \n", "age -0.064910 -0.339898 1.000000 -0.233296 -0.172482 0.096688 \n", "sibsp -0.035322 0.083081 -0.233296 1.000000 0.414838 0.159651 \n", "parch 0.081629 0.018443 -0.172482 0.414838 1.000000 0.216225 \n", "fare 0.257307 -0.549500 0.096688 0.159651 0.216225 1.000000 \n", "adult_male -0.557080 0.094035 0.247704 -0.253586 -0.349943 -0.182024 \n", "alone -0.203367 0.135207 0.171647 -0.584471 -0.583398 -0.271832 \n", "female 0.543351 -0.131900 -0.081163 0.114631 0.245489 0.182333 \n", "male -0.543351 0.131900 0.081163 -0.114631 -0.245489 -0.182333 \n", "C 0.168240 -0.243292 0.030248 -0.059528 -0.011069 0.269335 \n", "Q 0.003650 0.221009 -0.031415 -0.026354 -0.081228 -0.117216 \n", "\n", " adult_male alone female male C Q \n", "survived -0.557080 -0.203367 0.543351 -0.543351 0.168240 0.003650 \n", "pclass 0.094035 0.135207 -0.131900 0.131900 -0.243292 0.221009 \n", "age 0.247704 0.171647 -0.081163 0.081163 0.030248 -0.031415 \n", "sibsp -0.253586 -0.584471 0.114631 -0.114631 -0.059528 -0.026354 \n", "parch -0.349943 -0.583398 0.245489 -0.245489 -0.011069 -0.081228 \n", "fare -0.182024 -0.271832 0.182333 -0.182333 0.269335 -0.117216 \n", "adult_male 1.000000 0.404744 -0.908578 0.908578 -0.065980 -0.076789 \n", "alone 0.404744 1.000000 -0.303646 0.303646 -0.095298 0.086464 \n", "female -0.908578 -0.303646 1.000000 -1.000000 0.082853 0.074115 \n", "male 0.908578 0.303646 -1.000000 1.000000 -0.082853 -0.074115 \n", "C -0.065980 -0.095298 0.082853 -0.082853 1.000000 -0.148258 \n", "Q -0.076789 0.086464 0.074115 -0.074115 -0.148258 1.000000 " ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.corr.()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`adult_male`, `female`, `male`, はどれも0.5を超える相関係数を持っていて、かつ、特徴量としての重要度も高くなっていました。\n", "しかし、`fare` と `alone` を見てみると、これらは同程度の相関係数になっていますが、特徴量としての重要度は `fare` は `female` と同じくらい高いのに対し、`alone` はもっとも重要度が低い特徴量でした。\n", "このように、単に相関係数を見るだけでは、特徴量が分類にどの程度重要になるかは分からないのです。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### ロジスティク回帰による分類モデルの作成" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "GridSearchCV(cv=5, error_score='raise',\n", " estimator=LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,\n", " intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=2,\n", " penalty='l2', random_state=None, solver='liblinear', tol=0.0001,\n", " verbose=0, warm_start=False),\n", " fit_params={}, iid=True, n_jobs=4,\n", " param_grid={'penalty': ['l2', 'l1'], 'C': [10.0, 1.0, 0.1, 0.01]},\n", " pre_dispatch='2*n_jobs', refit=True, return_train_score=True,\n", " scoring='roc_auc', verbose=0)" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lrc = GridSearchCV.(\n", " LogisticRegression.(n_jobs: 2),\n", " {\n", " penalty: [:l2, :l1],\n", " C: [10.0, 1.0, 0.1, 0.01],\n", " },\n", " scoring: :roc_auc,\n", " n_jobs: 4,\n", " cv: 5\n", ")" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "GridSearchCV(cv=5, error_score='raise',\n", " estimator=LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,\n", " intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=2,\n", " penalty='l2', random_state=None, solver='liblinear', tol=0.0001,\n", " verbose=0, warm_start=False),\n", " fit_params={}, iid=True, n_jobs=4,\n", " param_grid={'penalty': ['l2', 'l1'], 'C': [10.0, 1.0, 0.1, 0.01]},\n", " pre_dispatch='2*n_jobs', refit=True, return_train_score=True,\n", " scoring='roc_auc', verbose=0)" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lrc.fit.(x, y)" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'C': 10.0, 'penalty': 'l1'}" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lrc.best_params_" ] }, { "cell_type": "code", "execution_count": 50, "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", " \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", " \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", "
mean_fit_timemean_score_timemean_test_scoremean_train_scoreparam_Cparam_penaltyrank_test_scoresplit0_test_scoresplit0_train_scoresplit1_test_scoresplit1_train_scoresplit2_test_scoresplit2_train_scoresplit3_test_scoresplit3_train_scoresplit4_test_scoresplit4_train_scorestd_fit_timestd_score_timestd_test_scorestd_train_score
00.0195780.0025490.8618750.87010710l220.8516470.8732220.8392620.8759630.8674470.8692570.8544790.8713030.8969240.8607910.0030530.0005020.0196190.005156
10.0577000.0019650.8619020.87007410l110.8527010.8730800.8384720.8760040.8678480.8692160.8535430.8712530.8973290.8608160.0303850.0003290.0199410.005139
20.0070030.0011800.8610990.8698691l240.8525690.8716780.8384720.8773310.8655750.8683430.8544790.8707370.8947650.8612560.0013670.0002820.0188520.005220
30.0197800.0017200.8615480.8701841l130.8541500.8725790.8400530.8769720.8657090.8685260.8519390.8716850.8962490.8611560.0057930.0005640.0191030.005260
40.0086170.0018690.8542990.8630250.1l250.8437420.8625080.8380760.8685030.8491310.8635210.8547460.8664470.8861310.8541470.0010680.0006480.0167910.004920
50.0063090.0012800.8500510.8582380.1l160.8507250.8554410.8357050.8617780.8428480.8595800.8443850.8621240.8768210.8522640.0013060.0003570.0141630.003820
60.0080140.0018780.8411880.8515570.01l270.8135700.8517610.8370220.8550860.8293450.8519150.8421790.8531620.8842420.8458610.0016520.0004280.0235190.003087
70.0056910.0016340.6687660.6783270.01l180.5699600.7140900.7300400.6746690.6431150.6845520.6960560.6613700.7050730.6569550.0016060.0006930.0570760.020374
\n", "

8 rows × 21 columns

\n", "
" ], "text/plain": [ " mean_fit_time mean_score_time mean_test_score mean_train_score param_C \\\n", "0 0.019578 0.002549 0.861875 0.870107 10 \n", "1 0.057700 0.001965 0.861902 0.870074 10 \n", "2 0.007003 0.001180 0.861099 0.869869 1 \n", "3 0.019780 0.001720 0.861548 0.870184 1 \n", "4 0.008617 0.001869 0.854299 0.863025 0.1 \n", "5 0.006309 0.001280 0.850051 0.858238 0.1 \n", "6 0.008014 0.001878 0.841188 0.851557 0.01 \n", "7 0.005691 0.001634 0.668766 0.678327 0.01 \n", "\n", " param_penalty rank_test_score split0_test_score split0_train_score \\\n", "0 l2 2 0.851647 0.873222 \n", "1 l1 1 0.852701 0.873080 \n", "2 l2 4 0.852569 0.871678 \n", "3 l1 3 0.854150 0.872579 \n", "4 l2 5 0.843742 0.862508 \n", "5 l1 6 0.850725 0.855441 \n", "6 l2 7 0.813570 0.851761 \n", "7 l1 8 0.569960 0.714090 \n", "\n", " split1_test_score ... split2_test_score split2_train_score \\\n", "0 0.839262 ... 0.867447 0.869257 \n", "1 0.838472 ... 0.867848 0.869216 \n", "2 0.838472 ... 0.865575 0.868343 \n", "3 0.840053 ... 0.865709 0.868526 \n", "4 0.838076 ... 0.849131 0.863521 \n", "5 0.835705 ... 0.842848 0.859580 \n", "6 0.837022 ... 0.829345 0.851915 \n", "7 0.730040 ... 0.643115 0.684552 \n", "\n", " split3_test_score split3_train_score split4_test_score \\\n", "0 0.854479 0.871303 0.896924 \n", "1 0.853543 0.871253 0.897329 \n", "2 0.854479 0.870737 0.894765 \n", "3 0.851939 0.871685 0.896249 \n", "4 0.854746 0.866447 0.886131 \n", "5 0.844385 0.862124 0.876821 \n", "6 0.842179 0.853162 0.884242 \n", "7 0.696056 0.661370 0.705073 \n", "\n", " split4_train_score std_fit_time std_score_time std_test_score \\\n", "0 0.860791 0.003053 0.000502 0.019619 \n", "1 0.860816 0.030385 0.000329 0.019941 \n", "2 0.861256 0.001367 0.000282 0.018852 \n", "3 0.861156 0.005793 0.000564 0.019103 \n", "4 0.854147 0.001068 0.000648 0.016791 \n", "5 0.852264 0.001306 0.000357 0.014163 \n", "6 0.845861 0.001652 0.000428 0.023519 \n", "7 0.656955 0.001606 0.000693 0.057076 \n", "\n", " std_train_score \n", "0 0.005156 \n", "1 0.005139 \n", "2 0.005220 \n", "3 0.005260 \n", "4 0.004920 \n", "5 0.003820 \n", "6 0.003087 \n", "7 0.020374 \n", "\n", "[8 rows x 21 columns]" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.DataFrame.(data: lrc.cv_results_).drop.(:params, axis: 1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### サポートベクトルマシンによる分類モデルの作成" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "GridSearchCV(cv=5, error_score='raise',\n", " estimator=SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,\n", " decision_function_shape=None, degree=3, gamma='auto', kernel='rbf',\n", " max_iter=-1, probability=False, random_state=None, shrinking=True,\n", " tol=0.001, verbose=False),\n", " fit_params={}, iid=True, n_jobs=4,\n", " param_grid={'C': [10.0, 1.0, 0.1, 0.01], 'gamma': [0.2, 0.1, 0.06666666666666667, 0.05]},\n", " pre_dispatch='2*n_jobs', refit=True, return_train_score=True,\n", " scoring='roc_auc', verbose=0)" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "svc = GridSearchCV.(\n", " SVC.(kernel: :rbf),\n", " {\n", " C: [10.0, 1.0, 0.1, 0.01],\n", " gamma: [5, 10, 15, 20].map {|x| 1.0 / x },\n", " },\n", " scoring: :roc_auc,\n", " n_jobs: 4,\n", " cv: 5\n", ")" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "GridSearchCV(cv=5, error_score='raise',\n", " estimator=SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,\n", " decision_function_shape=None, degree=3, gamma='auto', kernel='rbf',\n", " max_iter=-1, probability=False, random_state=None, shrinking=True,\n", " tol=0.001, verbose=False),\n", " fit_params={}, iid=True, n_jobs=4,\n", " param_grid={'C': [10.0, 1.0, 0.1, 0.01], 'gamma': [0.2, 0.1, 0.06666666666666667, 0.05]},\n", " pre_dispatch='2*n_jobs', refit=True, return_train_score=True,\n", " scoring='roc_auc', verbose=0)" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "svc.fit.(x, y)" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'C': 1.0, 'gamma': 0.05}" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "svc.best_params_" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.7861745269974777" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "svc.best_score_" ] }, { "cell_type": "code", "execution_count": 55, "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", " \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", " \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", " \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", " \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", "
mean_fit_timemean_score_timemean_test_scoremean_train_scoreparam_Cparam_gammarank_test_scoresplit0_test_scoresplit0_train_scoresplit1_test_scoresplit1_train_scoresplit2_test_scoresplit2_train_scoresplit3_test_scoresplit3_train_scoresplit4_test_scoresplit4_train_scorestd_fit_timestd_score_timestd_test_scorestd_train_score
00.0793610.0085250.7642780.973148100.270.7065880.9774460.7397890.9730870.7921790.9787130.7961900.9672240.7872370.9692680.0183220.0012470.0353950.004463
10.0424050.0059430.7641560.969342100.180.6984190.9754600.7416340.9698660.7868320.9757540.8078210.9643470.7866970.9612810.0076240.0010100.0394290.005809
20.0385380.0040080.7704270.964944100.066666760.7318840.9665570.7409750.9659610.7770720.9671740.8149060.9627100.7877770.9623180.0040630.0001510.0306030.002025
30.0323190.0041810.7713510.957600100.0550.7227930.9579050.7461130.9591690.7691840.9617540.8194520.9566990.7997840.9524720.0035460.0003360.0350060.003063
40.0244430.0052620.7768940.95681310.230.7226610.9572200.7415020.9599780.7841580.9622360.8273400.9524090.8094980.9522230.0008460.0008050.0396560.004001
50.0244680.0042560.7754440.94132310.140.6974970.9453800.7359680.9455180.7864300.9484100.8257350.9348840.8325690.9324240.0024960.0000930.0520700.006402
60.0239040.0044720.7818210.92724910.066666720.7000000.9283590.7420290.9338450.7870990.9352830.8350940.9237030.8459260.9150550.0011100.0002680.0552440.007356
70.0233740.0046060.7861750.91839710.0510.7088270.9241450.7476940.9294390.7957890.9255480.8336230.9076990.8459260.9051510.0012360.0006410.0517380.009960
80.0260610.0078470.7621360.9333530.10.290.6977600.9324720.7158100.9351550.7699870.9428650.8201200.9322410.8078790.9240300.0039820.0044820.0486150.006044
90.0233140.0080070.7568440.9091560.10.1160.6400530.9029680.7142290.9159140.7694520.9156880.8209220.9052050.8409340.9060050.0008440.0048080.0732250.005517
100.0280510.0048080.7587740.8896900.10.0666667120.6237150.8773100.7284580.8955880.7772060.9000510.8207890.8861090.8451160.8893910.0055200.0004270.0785260.007852
110.0223240.0047460.7586990.8753190.10.05130.6209490.8602380.7267460.8799680.7780080.8852440.8285430.8710120.8406640.8801340.0012160.0005390.0800050.008824
120.0231410.0047230.7620120.9347550.010.2100.6971010.9352920.7178520.9384090.7705210.9427320.8191840.9319660.8062600.9253730.0029680.0001460.0479020.005883
130.0217300.0046230.7581000.9086550.010.1150.6392620.9014080.7154150.9160810.7698530.9164620.8254680.9036010.8418780.9057230.0024840.0004160.0743760.006368
140.0259440.0061890.7587790.8907560.010.0666667110.6218710.8771850.7278000.8969060.7801470.9023450.8205210.8875220.8449810.8898220.0034510.0007040.0792930.008575
150.0276010.0073140.7585610.8755790.010.05140.6212120.8621910.7283270.8802100.7826870.8844210.8235960.8726740.8383700.8784010.0012070.0013080.0787410.007685
\n", "

16 rows × 21 columns

\n", "
" ], "text/plain": [ " mean_fit_time mean_score_time mean_test_score mean_train_score param_C \\\n", "0 0.079361 0.008525 0.764278 0.973148 10 \n", "1 0.042405 0.005943 0.764156 0.969342 10 \n", "2 0.038538 0.004008 0.770427 0.964944 10 \n", "3 0.032319 0.004181 0.771351 0.957600 10 \n", "4 0.024443 0.005262 0.776894 0.956813 1 \n", "5 0.024468 0.004256 0.775444 0.941323 1 \n", "6 0.023904 0.004472 0.781821 0.927249 1 \n", "7 0.023374 0.004606 0.786175 0.918397 1 \n", "8 0.026061 0.007847 0.762136 0.933353 0.1 \n", "9 0.023314 0.008007 0.756844 0.909156 0.1 \n", "10 0.028051 0.004808 0.758774 0.889690 0.1 \n", "11 0.022324 0.004746 0.758699 0.875319 0.1 \n", "12 0.023141 0.004723 0.762012 0.934755 0.01 \n", "13 0.021730 0.004623 0.758100 0.908655 0.01 \n", "14 0.025944 0.006189 0.758779 0.890756 0.01 \n", "15 0.027601 0.007314 0.758561 0.875579 0.01 \n", "\n", " param_gamma rank_test_score split0_test_score split0_train_score \\\n", "0 0.2 7 0.706588 0.977446 \n", "1 0.1 8 0.698419 0.975460 \n", "2 0.0666667 6 0.731884 0.966557 \n", "3 0.05 5 0.722793 0.957905 \n", "4 0.2 3 0.722661 0.957220 \n", "5 0.1 4 0.697497 0.945380 \n", "6 0.0666667 2 0.700000 0.928359 \n", "7 0.05 1 0.708827 0.924145 \n", "8 0.2 9 0.697760 0.932472 \n", "9 0.1 16 0.640053 0.902968 \n", "10 0.0666667 12 0.623715 0.877310 \n", "11 0.05 13 0.620949 0.860238 \n", "12 0.2 10 0.697101 0.935292 \n", "13 0.1 15 0.639262 0.901408 \n", "14 0.0666667 11 0.621871 0.877185 \n", "15 0.05 14 0.621212 0.862191 \n", "\n", " split1_test_score ... split2_test_score split2_train_score \\\n", "0 0.739789 ... 0.792179 0.978713 \n", "1 0.741634 ... 0.786832 0.975754 \n", "2 0.740975 ... 0.777072 0.967174 \n", "3 0.746113 ... 0.769184 0.961754 \n", "4 0.741502 ... 0.784158 0.962236 \n", "5 0.735968 ... 0.786430 0.948410 \n", "6 0.742029 ... 0.787099 0.935283 \n", "7 0.747694 ... 0.795789 0.925548 \n", "8 0.715810 ... 0.769987 0.942865 \n", "9 0.714229 ... 0.769452 0.915688 \n", "10 0.728458 ... 0.777206 0.900051 \n", "11 0.726746 ... 0.778008 0.885244 \n", "12 0.717852 ... 0.770521 0.942732 \n", "13 0.715415 ... 0.769853 0.916462 \n", "14 0.727800 ... 0.780147 0.902345 \n", "15 0.728327 ... 0.782687 0.884421 \n", "\n", " split3_test_score split3_train_score split4_test_score \\\n", "0 0.796190 0.967224 0.787237 \n", "1 0.807821 0.964347 0.786697 \n", "2 0.814906 0.962710 0.787777 \n", "3 0.819452 0.956699 0.799784 \n", "4 0.827340 0.952409 0.809498 \n", "5 0.825735 0.934884 0.832569 \n", "6 0.835094 0.923703 0.845926 \n", "7 0.833623 0.907699 0.845926 \n", "8 0.820120 0.932241 0.807879 \n", "9 0.820922 0.905205 0.840934 \n", "10 0.820789 0.886109 0.845116 \n", "11 0.828543 0.871012 0.840664 \n", "12 0.819184 0.931966 0.806260 \n", "13 0.825468 0.903601 0.841878 \n", "14 0.820521 0.887522 0.844981 \n", "15 0.823596 0.872674 0.838370 \n", "\n", " split4_train_score std_fit_time std_score_time std_test_score \\\n", "0 0.969268 0.018322 0.001247 0.035395 \n", "1 0.961281 0.007624 0.001010 0.039429 \n", "2 0.962318 0.004063 0.000151 0.030603 \n", "3 0.952472 0.003546 0.000336 0.035006 \n", "4 0.952223 0.000846 0.000805 0.039656 \n", "5 0.932424 0.002496 0.000093 0.052070 \n", "6 0.915055 0.001110 0.000268 0.055244 \n", "7 0.905151 0.001236 0.000641 0.051738 \n", "8 0.924030 0.003982 0.004482 0.048615 \n", "9 0.906005 0.000844 0.004808 0.073225 \n", "10 0.889391 0.005520 0.000427 0.078526 \n", "11 0.880134 0.001216 0.000539 0.080005 \n", "12 0.925373 0.002968 0.000146 0.047902 \n", "13 0.905723 0.002484 0.000416 0.074376 \n", "14 0.889822 0.003451 0.000704 0.079293 \n", "15 0.878401 0.001207 0.001308 0.078741 \n", "\n", " std_train_score \n", "0 0.004463 \n", "1 0.005809 \n", "2 0.002025 \n", "3 0.003063 \n", "4 0.004001 \n", "5 0.006402 \n", "6 0.007356 \n", "7 0.009960 \n", "8 0.006044 \n", "9 0.005517 \n", "10 0.007852 \n", "11 0.008824 \n", "12 0.005883 \n", "13 0.006368 \n", "14 0.008575 \n", "15 0.007685 \n", "\n", "[16 rows x 21 columns]" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.DataFrame.(data: svc.cv_results_).drop.(:params, axis: 1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 結果" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "image/png": "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e3urc+fO+uUvfykfHx9XzgkAAABUq9ZBe/LkSaWlpWn79u0qLCyUu7u7mjVrJi8vL128eFElJSWy2Wzq16+fIiMjNWrUKLm5cSMYAAAAt0atgvbZZ5/Vtm3bFBQUpNmzZyswMFDdunWTu7u7Y5vCwkIdOXJEe/fu1SuvvKLVq1frpZdeUlBQkMuHBwAAAGp9h/a9995Thw4dfnK9j4+PQkJCFBISovnz52v79u06c+YMQQsAAIBbolZBu3Dhwlod3N3dXePGjavVPgAAAEBtuOThVrvdrm+//VZlZWWuOBwAAABQYzcVtHv37tWECRPk7++voUOH6vPPP5f047O277zzjksGBAAAAK7H6aB99913NX36dLVv317PP/+8KioqHOvuvPNOvf322y4ZEAAAALgep4N29erVmjJlipYuXarw8PBK67p166Yvv/zypocDAAAAbsTpoD116pRCQkKqXdeoUSNdvHjR6aEAAACAmnI6aP38/JSbm1vtus8//1y/+MUvnB4KAAAAqCmng3bUqFFauXKlsrKyHMtsNpu++OILJScna8yYMS4ZEAAAALieWn+xwjWzZs3Sl19+qejoaN1xxx2SpGnTpqmwsFBDhgzR9OnTXTYkAAAA8FOcDlovLy/9x3/8h/bv3699+/apqKhILVq0UHBwsIKDg105IwAAAPCTnAraK1euaNOmTRo4cKAGDBigAQMGuHouAAAAoEaceoa2QYMGWrZsmc6fP+/qeQAAAIBacfpNYT179tRXX33lylkAAACAWnM6aJ955hmlpqZq586dKikpceVMAAAAQI05/aawKVOm6OrVq3ryySclSQ0bNpTNZnOst9lsOnTo0M1PCAAAAFyH00H7m9/8plLAAgAAAFZwOmhnz57tyjkAAAAApzgdtNfY7XZ9/fXXunDhglq0aKHOnTtz5xYAAAB15qaCNi0tTatXr1ZhYaHsdrtsNpt8fX01c+ZMPfLII66aEQAAAPhJTgftW2+9pYULF+rBBx9UWFiYWrZsqXPnzikzM1MLFy6Up6enIiMjXTkrAAAAUIXTQbt+/XpNmjRJv//97ystHz58uHx8fLRu3TqCFgAAALec059De/r0aQ0dOrTadUOGDNGZM2ecHgoAAACoKaeD1s/PT9nZ2dWuO3z4sPz8/JweCgAAAKgppx85GD9+vFavXq3S0lKFhobK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", "text/plain": [ "" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result = pd.DataFrame.(data: {\n", " model: %w[RFC LRC SVC],\n", " score: [rfc.best_score_, lrc.best_score_, svc.best_score_]\n", "})\n", "sns.barplot.(x: :model, y: :score, data: result)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Ruby 2.4.0", "language": "ruby", "name": "ruby" }, "language_info": { "file_extension": ".rb", "mimetype": "application/x-ruby", "name": "ruby", "version": "2.4.0" } }, "nbformat": 4, "nbformat_minor": 2 }