Skip to content

Instantly share code, notes, and snippets.

@yamasakih
Last active December 16, 2018 13:00
Show Gist options
  • Save yamasakih/f3a0c77634cc95d467dc08db719024b0 to your computer and use it in GitHub Desktop.
Save yamasakih/f3a0c77634cc95d467dc08db719024b0 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## LogS QSPR with TPOT"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import pandas as pd\n",
"from tpot import TPOTRegressor\n",
"\n",
"from rdkit import Chem\n",
"from rdkit.Chem import Descriptors\n",
"from rdkit.ML.Descriptors import MoleculeDescriptors\n",
"\n",
"from sklearn.metrics import mean_absolute_error\n",
"from sklearn.model_selection import cross_validate, KFold, train_test_split\n",
"\n",
"\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1. Load dataset. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1290個の水溶解度のデータセットをロードする。ダウンロードは[こちら](https://datachemeng.com/pythonassignment/)からさせていただいた。 \n",
"Reference \n",
"`T. J. Hou, K. Xia, W. Zhang and X. J. Xu, ADME Evaluation in Drug Discovery. 4. Prediction of Aqueous Solubility Based on Atom Contribution Approach, J. Chem. Inf. Comput. Sci., 44(1), 266–275, 2004.`"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"RDKitで読み込めた化合物は全部で1290個である。\n"
]
}
],
"source": [
"supp = Chem.SDMolSupplier('logSdataset1290_2d.sdf')\n",
"mols = [mol for mol in supp if mol]\n",
"print(f'RDKitで読み込めた化合物は全部で{len(mols)}個である。')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2. Make y. "
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'CAS_Number': '60-35-5', 'logS': 1.58}"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mol = mols[0]\n",
"mol.GetPropsAsDict()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"目的変数 logS は logS という Prop に入っている。"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'1.58'"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"mol.GetProp('logS')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"文字列なのに注意し、すべての Mol オブジェクトから logS のデータを取り出し数値データに変換して numpy.array である変数 y に保存する。"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([1.58, 1.34, 1.22, 1.15, 1.12])"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"y = np.array([float(mol.GetProp('logS')) for mol in mols])\n",
"y[:5]"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(array([ 2., 4., 27., 41., 81., 204., 309., 361., 191., 70.]),\n",
" array([-11.62, -10.3 , -8.98, -7.66, -6.34, -5.02, -3.7 , -2.38,\n",
" -1.06, 0.26, 1.58]),\n",
" <a list of 10 Patch objects>)"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.hist(y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"少し偏ってるけどだいたい正規分布になっている。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3. Make X. "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"RDKit で計算可能な記述子を計算する。"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['MaxEStateIndex',\n",
" 'MinEStateIndex',\n",
" 'MaxAbsEStateIndex',\n",
" 'MinAbsEStateIndex',\n",
" 'qed']"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"descriptor_names = [d[0] for d in Descriptors._descList]\n",
"descriptor_names[:5]"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"全部で200個ある\n"
]
}
],
"source": [
"print(f'全部で{len(descriptor_names)}個ある')"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"calc = MoleculeDescriptors.MolecularDescriptorCalculator(descriptor_names)\n",
"descs = [calc.CalcDescriptors(mol) for mol in mols]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"人間の目で見た時にわかりやすくしたいならカラム名を追加してデータフレームにすれば良い。"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>MaxEStateIndex</th>\n",
" <th>MinEStateIndex</th>\n",
" <th>MaxAbsEStateIndex</th>\n",
" <th>MinAbsEStateIndex</th>\n",
" <th>qed</th>\n",
" <th>MolWt</th>\n",
" <th>HeavyAtomMolWt</th>\n",
" <th>ExactMolWt</th>\n",
" <th>NumValenceElectrons</th>\n",
" <th>NumRadicalElectrons</th>\n",
" <th>...</th>\n",
" <th>fr_sulfide</th>\n",
" <th>fr_sulfonamd</th>\n",
" <th>fr_sulfone</th>\n",
" <th>fr_term_acetylene</th>\n",
" <th>fr_tetrazole</th>\n",
" <th>fr_thiazole</th>\n",
" <th>fr_thiocyan</th>\n",
" <th>fr_thiophene</th>\n",
" <th>fr_unbrch_alkane</th>\n",
" <th>fr_urea</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>9.222222</td>\n",
" <td>-0.333333</td>\n",
" <td>9.222222</td>\n",
" <td>0.333333</td>\n",
" <td>0.401031</td>\n",
" <td>59.068</td>\n",
" <td>54.028</td>\n",
" <td>59.037114</td>\n",
" <td>24</td>\n",
" <td>0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>4.597222</td>\n",
" <td>1.652778</td>\n",
" <td>4.597222</td>\n",
" <td>1.652778</td>\n",
" <td>0.273315</td>\n",
" <td>46.073</td>\n",
" <td>40.025</td>\n",
" <td>46.053098</td>\n",
" <td>20</td>\n",
" <td>0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>9.000000</td>\n",
" <td>-0.833333</td>\n",
" <td>9.000000</td>\n",
" <td>0.833333</td>\n",
" <td>0.429883</td>\n",
" <td>60.052</td>\n",
" <td>56.020</td>\n",
" <td>60.021129</td>\n",
" <td>24</td>\n",
" <td>0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3.222222</td>\n",
" <td>1.250000</td>\n",
" <td>3.222222</td>\n",
" <td>1.250000</td>\n",
" <td>0.434794</td>\n",
" <td>71.123</td>\n",
" <td>62.051</td>\n",
" <td>71.073499</td>\n",
" <td>30</td>\n",
" <td>0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>9.229167</td>\n",
" <td>-0.939815</td>\n",
" <td>9.229167</td>\n",
" <td>0.939815</td>\n",
" <td>0.256644</td>\n",
" <td>76.055</td>\n",
" <td>72.023</td>\n",
" <td>76.027277</td>\n",
" <td>30</td>\n",
" <td>0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5 rows × 200 columns</p>\n",
"</div>"
],
"text/plain": [
" MaxEStateIndex MinEStateIndex MaxAbsEStateIndex MinAbsEStateIndex \\\n",
"0 9.222222 -0.333333 9.222222 0.333333 \n",
"1 4.597222 1.652778 4.597222 1.652778 \n",
"2 9.000000 -0.833333 9.000000 0.833333 \n",
"3 3.222222 1.250000 3.222222 1.250000 \n",
"4 9.229167 -0.939815 9.229167 0.939815 \n",
"\n",
" qed MolWt HeavyAtomMolWt ExactMolWt NumValenceElectrons \\\n",
"0 0.401031 59.068 54.028 59.037114 24 \n",
"1 0.273315 46.073 40.025 46.053098 20 \n",
"2 0.429883 60.052 56.020 60.021129 24 \n",
"3 0.434794 71.123 62.051 71.073499 30 \n",
"4 0.256644 76.055 72.023 76.027277 30 \n",
"\n",
" NumRadicalElectrons ... fr_sulfide fr_sulfonamd fr_sulfone \\\n",
"0 0 ... 0 0 0 \n",
"1 0 ... 0 0 0 \n",
"2 0 ... 0 0 0 \n",
"3 0 ... 0 0 0 \n",
"4 0 ... 0 0 0 \n",
"\n",
" fr_term_acetylene fr_tetrazole fr_thiazole fr_thiocyan fr_thiophene \\\n",
"0 0 0 0 0 0 \n",
"1 0 0 0 0 0 \n",
"2 0 0 0 0 0 \n",
"3 0 0 0 0 0 \n",
"4 0 0 0 0 0 \n",
"\n",
" fr_unbrch_alkane fr_urea \n",
"0 0 0 \n",
"1 0 0 \n",
"2 0 0 \n",
"3 0 0 \n",
"4 0 1 \n",
"\n",
"[5 rows x 200 columns]"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"descs_df = pd.DataFrame(descs, columns=descriptor_names)\n",
"descs_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"今回は Automated ML の引数にするので y 同様 numpy.array に変換し X に保存しておく。 pandas.DataFrame のままでも問題はない。"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[ 9.22222222, -0.33333333, 9.22222222, 0.33333333, 0.40103092],\n",
" [ 4.59722222, 1.65277778, 4.59722222, 1.65277778, 0.27331504],\n",
" [ 9. , -0.83333333, 9. , 0.83333333, 0.42988288],\n",
" [ 3.22222222, 1.25 , 3.22222222, 1.25 , 0.43479446],\n",
" [ 9.22916667, -0.93981481, 9.22916667, 0.93981481, 0.25664361]])"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"X = np.array(descs)\n",
"X[:5, :5]"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(1290, 200)"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"X.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"再度確認すると、サンプル数は1290個、説明変数の数は200個である。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4. Split dataset to training set and test set."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1290個のデータのうち1000個を予測モデル構築のための Training set、290個を構築した予測モデルの評価のための Test set とする。 \n",
"今回は再現性を担保するために乱数を固定したいと思う。 train_test_split や TPOT の `random_state` という引数に整数を与えると乱数を固定できる。"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"random_state = 20181216"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"training_X, test_X, training_y, test_y = train_test_split(\n",
" X, y, test_size=290, random_state=random_state)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(1000, 200)"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"training_X.shape"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(290, 200)"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"test_X.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1000個と290個に分割できた。ヒストグラムもみてみる。"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(array([ 3., 5., 11., 21., 30., 41., 71., 62., 31., 15.]),\n",
" array([-8.65 , -7.673, -6.696, -5.719, -4.742, -3.765, -2.788, -1.811,\n",
" -0.834, 0.143, 1.12 ]),\n",
" <a list of 10 Patch objects>)"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 576x288 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.figure(figsize=(8, 4))\n",
"plt.subplot(1, 2, 1)\n",
"plt.hist(training_y)\n",
"plt.subplot(1, 2, 2)\n",
"plt.hist(test_y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"ほぼ同じ分布で Training set, Test set に分割できている。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 5. Automated ML with TPOT."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"いよいよ TPOT を用いて Automated ML を行ってみる。 \n",
"Cross Validation として `KFold(n_splits=5, shuffle=True)` を採用する。"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"kfold = KFold(n_splits=5, shuffle=True, random_state=random_state)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"計算に用いる CPU の数を TPOT の `n_jobs` という引数で指定する。私は今回の検証はすべて `n_jobs=-1` で行った。 \n",
"`n_jobs=-1` とするとすべての CPU を用いて計算する。冬の寒い日はパソコンが暖かくなってちょうど良いが他の作業ができなくなるので注意しよう。 "
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"n_jobs = 1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 5.1 Automated ML."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"最初は計算コストを下げすぐに終了するように `generations=3, population_size=5` で行ってみる。 \n",
"`population_size` の数だけ並行して Pipeline の探索を行い、 generations の数だけ並行した結果を考慮してよりよい Pipeline の候補を構築し探索するということを繰り返す。"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"tpot1 = TPOTRegressor(generations=3, population_size=5, scoring='neg_mean_absolute_error', cv=kfold, \n",
" n_jobs=n_jobs, random_state=random_state, verbosity=2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"sklearn の機械学習を行う時と同様に `fit` メソッドの引数に `Training set` の説明変数, `Training set` の目的変数を与えて Automated ML を行うことができる。"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "79c2ebff902a49d6b684624077696cc7",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, description='Optimization Progress', max=20, style=ProgressStyle(descripti…"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Generation 1 - Current best internal CV score: -0.45904943717365965\n",
"Generation 2 - Current best internal CV score: -0.45904943717365965\n",
"Generation 3 - Current best internal CV score: -0.45904943717365965\n",
"\n",
"Best pipeline: ExtraTreesRegressor(input_matrix, bootstrap=False, max_features=0.6500000000000001, min_samples_leaf=5, min_samples_split=14, n_estimators=100)\n"
]
},
{
"data": {
"text/plain": [
"TPOTRegressor(config_dict=None, crossover_rate=0.1,\n",
" cv=KFold(n_splits=5, random_state=20181216, shuffle=True),\n",
" disable_update_check=False, early_stop=None, generations=3,\n",
" max_eval_time_mins=5, max_time_mins=None, memory=None,\n",
" mutation_rate=0.9, n_jobs=-1, offspring_size=None,\n",
" periodic_checkpoint_folder=None, population_size=5,\n",
" random_state=20181216, scoring='neg_mean_absolute_error',\n",
" subsample=1.0, use_dask=False, verbosity=2, warm_start=False)"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tpot1.fit(training_X, training_y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"私のパソコンでは1分ほどで計算が終わった。 \n",
"\n",
"`Current best internal CV score: -0.5172185206482698` と書いている部分が各 Generation で最も良い Pipeline の スコアである。 \n",
"\n",
"今回のスコアは `neg_mean_absolute_error` なので0に近づくほど良い。計算コストを下げたので予測性能が向上していないように見えるが、 \n",
"内部で複数のアルゴリズムの比較を行い最も良い予測モデルのみを表示しているので CV score は Generation 1 の時点でもそれなりに良い値を示していることが多い。 \n",
"予測性能が向上して行くところは 5.4 で詳しくみたいと思う。 \n",
"\n",
"また、 xgboost をインストールしていない場合は `Warning: xgboost.XGBRegressor is not available and will not be used by TPOT.` と表示される。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"今回最もよかった Pipeline (予測モデルのワークフローのこと) は \n",
"`ExtraTreesRegressor(input_matrix, bootstrap=False, max_features=0.6500000000000001, min_samples_leaf=5, min_samples_split=14, n_estimators=100)` \n",
"であった。また以下のように `export` メソッドを実行すると結果を書き出すことができる。"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tpot1.export('tpot1_logS_QSPR.py')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"どのようなファイルが出力されているかは `6. Evaluate prediction pipeline.` でふれたい。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 5.2 Change argument max_time_mins=5"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`max_time_mins` に時間を指定するとその指定した時間まで最適な予測モデルの Pipeline を探索してくれる。 \n",
"探索ツールはどれぐらいの時間がかかるか不明瞭な時が多いので時間を指定できるのは非常に便利だ。 \n",
"なお `max_time_mins` を指定した場合 `generations` は無視されることに注意しておこう。 (無視されるのを確認するために今回はわざと generation=3 と書いておく)"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
"tpot2 = TPOTRegressor(generations=3, population_size=5, scoring='neg_mean_absolute_error', cv=kfold, \n",
" n_jobs=n_jobs, max_time_mins=3, random_state=random_state, verbosity=2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`max_time_mins=3` としたので3分を超えた時点の Generation が終わると計算を終了する。"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "d3866c165f6b438e96b5558f1917f5b9",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, description='Optimization Progress', max=5, style=ProgressStyle(descriptio…"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Generation 1 - Current best internal CV score: -0.45904943717365965\n",
"Generation 2 - Current best internal CV score: -0.45904943717365965\n",
"Generation 3 - Current best internal CV score: -0.45904943717365965\n",
"Generation 4 - Current best internal CV score: -0.4580808516874792\n",
"Generation 5 - Current best internal CV score: -0.43517099826728833\n",
"Generation 6 - Current best internal CV score: -0.4348320502269952\n",
"Generation 7 - Current best internal CV score: -0.4315345048520923\n",
"Generation 8 - Current best internal CV score: -0.4315345048520923\n",
"\n",
"3.4183998 minutes have elapsed. TPOT will close down.\n",
"TPOT closed prematurely. Will use the current best pipeline.\n",
"\n",
"Best pipeline: ExtraTreesRegressor(GradientBoostingRegressor(input_matrix, alpha=0.99, learning_rate=0.1, loss=lad, max_depth=7, max_features=0.7000000000000001, min_samples_leaf=20, min_samples_split=7, n_estimators=100, subsample=0.9000000000000001), bootstrap=False, max_features=0.7000000000000001, min_samples_leaf=5, min_samples_split=5, n_estimators=100)\n"
]
},
{
"data": {
"text/plain": [
"TPOTRegressor(config_dict=None, crossover_rate=0.1,\n",
" cv=KFold(n_splits=5, random_state=20181216, shuffle=True),\n",
" disable_update_check=False, early_stop=None, generations=1000000,\n",
" max_eval_time_mins=5, max_time_mins=3, memory=None,\n",
" mutation_rate=0.9, n_jobs=-1, offspring_size=None,\n",
" periodic_checkpoint_folder=None, population_size=5,\n",
" random_state=20181216, scoring='neg_mean_absolute_error',\n",
" subsample=1.0, use_dask=False, verbosity=2, warm_start=False)"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tpot2.fit(training_X, training_y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"5分後に計算が終了している。その時の最も良い Pipeline も表示してくれている。 \n",
"また 5.1 よりも計算量を多くしたので、世代を経るごとに CV score の値が0に近づいていきよくなっていっているのがわかる。 "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 5.3 強制終了時の挙動"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"次の例のように途中で `Ctrl + C` や Jupyter Notebook の `Interrupt the Kernel` で強制終了したという時も、その時の最も良い Pipeline を表示してくれる。"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
"tpot_mistaken = TPOTRegressor(generations=3, population_size=5, scoring='neg_mean_absolute_error', cv=kfold, \n",
" n_jobs=n_jobs, max_time_mins=5, random_state=random_state, verbosity=2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"下のセルを実行した後わざと強制終了してみてほしい。"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "91e931217d3748f9b17d84731bb6492b",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, description='Optimization Progress', max=5, style=ProgressStyle(descriptio…"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Generation 1 - Current best internal CV score: -0.45904943717365965\n",
"Generation 2 - Current best internal CV score: -0.45904943717365965\n",
"Generation 3 - Current best internal CV score: -0.45904943717365965\n",
"Generation 4 - Current best internal CV score: -0.4580808516874792\n",
"Generation 5 - Current best internal CV score: -0.43517099826728833\n",
"Generation 6 - Current best internal CV score: -0.4348320502269952\n",
"Generation 7 - Current best internal CV score: -0.4315345048520923\n",
"\n",
"\n",
"TPOT closed prematurely. Will use the current best pipeline.\n",
"\n",
"Best pipeline: ExtraTreesRegressor(GradientBoostingRegressor(input_matrix, alpha=0.99, learning_rate=0.1, loss=lad, max_depth=7, max_features=0.7000000000000001, min_samples_leaf=20, min_samples_split=7, n_estimators=100, subsample=0.9000000000000001), bootstrap=False, max_features=0.7000000000000001, min_samples_leaf=5, min_samples_split=5, n_estimators=100)\n"
]
},
{
"data": {
"text/plain": [
"TPOTRegressor(config_dict=None, crossover_rate=0.1,\n",
" cv=KFold(n_splits=5, random_state=20181216, shuffle=True),\n",
" disable_update_check=False, early_stop=None, generations=1000000,\n",
" max_eval_time_mins=5, max_time_mins=5, memory=None,\n",
" mutation_rate=0.9, n_jobs=-1, offspring_size=None,\n",
" periodic_checkpoint_folder=None, population_size=5,\n",
" random_state=20181216, scoring='neg_mean_absolute_error',\n",
" subsample=1.0, use_dask=False, verbosity=2, warm_start=False)"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tpot_mistaken.fit(training_X, training_y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"強制終了したもののその時点での計算をちゃんと保存しており、この時点での最も良い Pipeline を出力することもできる。"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tpot_mistaken.export('tpot_mistaken_logS_QSPR.py')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 5.4 generation, Population_size を増やした Pipeline の構築"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"5.1 よりも計算コストはかかるが `generation`, `population_size` を増やして Pipeline の探索を行ってみる。 \n",
"今回は `generation=10`, `population_size=20` とした。 "
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [],
"source": [
"tpot3 = TPOTRegressor(generations=10, population_size=20, scoring='neg_mean_absolute_error', cv=kfold, \n",
" n_jobs=n_jobs, random_state=random_state, verbosity=2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`max_time_mins=3` としたので3分を超えた時点の Generation が終わると計算を終了する。"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "394c364e77324929a9562ab8ef16d0dd",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, description='Optimization Progress', max=220, style=ProgressStyle(descript…"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Generation 1 - Current best internal CV score: -0.4745942938299195\n",
"Generation 2 - Current best internal CV score: -0.4655966251361625\n",
"Generation 3 - Current best internal CV score: -0.46018596571526854\n",
"Generation 4 - Current best internal CV score: -0.45646592009261855\n",
"Generation 5 - Current best internal CV score: -0.4461230389900289\n",
"Generation 6 - Current best internal CV score: -0.4461230389900289\n",
"Generation 7 - Current best internal CV score: -0.4380682448809523\n",
"Generation 8 - Current best internal CV score: -0.4380682448809523\n",
"Generation 9 - Current best internal CV score: -0.43677564142857134\n",
"Generation 10 - Current best internal CV score: -0.43677564142857134\n",
"\n",
"Best pipeline: ExtraTreesRegressor(ZeroCount(input_matrix), bootstrap=False, max_features=0.7000000000000001, min_samples_leaf=4, min_samples_split=5, n_estimators=100)\n"
]
},
{
"data": {
"text/plain": [
"TPOTRegressor(config_dict=None, crossover_rate=0.1,\n",
" cv=KFold(n_splits=5, random_state=20181216, shuffle=True),\n",
" disable_update_check=False, early_stop=None, generations=10,\n",
" max_eval_time_mins=5, max_time_mins=None, memory=None,\n",
" mutation_rate=0.9, n_jobs=-1, offspring_size=None,\n",
" periodic_checkpoint_folder=None, population_size=20,\n",
" random_state=20181216, scoring='neg_mean_absolute_error',\n",
" subsample=1.0, use_dask=False, verbosity=2, warm_start=False)"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tpot3.fit(training_X, training_y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"私のパソコンでは15分ほどで計算が終わった。その時の最も良い Pipeline も表示してくれている。 \n",
"また 5.1 よりも計算量を多くしたので、世代を経るごとに CV score の値が0に近づいていきよくなっていっているのがわかる。 "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"5.1 で求めた Pipeline と比較を行いたいのでこちらも `export` メソッドで結果を書き出しておく。"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tpot3.export('tpot3_logS_QSPR.py')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 6. Evaluate prediction pipeline."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 6.1 すべての Pipeline の確認"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"すべての Pipeline を確認したい場合は `evaluated_individuals_` attribute を参照する。 \n",
"今回はより複雑な Pipeline になっていそうな 5.3 の Pipeline を確認してみよう。"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"tpot3 の結果では全部で206個の Pipeline がある。\n"
]
}
],
"source": [
"print(f'tpot3 の結果では全部で{len(tpot3.evaluated_individuals_)}個の Pipeline がある。')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"全部表示すると大変なので最後の一つだけ表示してみる。(最後のが一番良いとは限らないのに注意したい)"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"最後の Pipeline は ExtraTreesRegressor(GradientBoostingRegressor(input_matrix, GradientBoostingRegressor__alpha=0.85, GradientBoostingRegressor__learning_rate=0.1, GradientBoostingRegressor__loss=lad, GradientBoostingRegressor__max_depth=9, GradientBoostingRegressor__max_features=0.15000000000000002, GradientBoostingRegressor__min_samples_leaf=4, GradientBoostingRegressor__min_samples_split=16, GradientBoostingRegressor__n_estimators=100, GradientBoostingRegressor__subsample=0.45), ExtraTreesRegressor__bootstrap=True, ExtraTreesRegressor__max_features=0.7000000000000001, ExtraTreesRegressor__min_samples_leaf=6, ExtraTreesRegressor__min_samples_split=8, ExtraTreesRegressor__n_estimators=100)\n"
]
}
],
"source": [
"for key in tpot3.evaluated_individuals_.keys():\n",
" pass\n",
"print(f'最後の Pipeline は {key}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"最後の Pipeline は `GradientBoostingRegressor` で予測を行った後に `ExtraTreesRegressor` で再び予測を行う Pipeline のようだ。 \n",
"このように TPOT では、前処理も含めどのアルゴリズムがよいか、また場合によってはそれを組み合わせの検討を行い Pipeline を探索する。"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'generation': 'INVALID',\n",
" 'mutation_count': 5,\n",
" 'crossover_count': 0,\n",
" 'predecessor': ('ExtraTreesRegressor(SelectPercentile(GradientBoostingRegressor(input_matrix, GradientBoostingRegressor__alpha=0.85, GradientBoostingRegressor__learning_rate=0.1, GradientBoostingRegressor__loss=lad, GradientBoostingRegressor__max_depth=9, GradientBoostingRegressor__max_features=0.15000000000000002, GradientBoostingRegressor__min_samples_leaf=4, GradientBoostingRegressor__min_samples_split=16, GradientBoostingRegressor__n_estimators=100, GradientBoostingRegressor__subsample=0.45), SelectPercentile__percentile=56), ExtraTreesRegressor__bootstrap=True, ExtraTreesRegressor__max_features=0.7000000000000001, ExtraTreesRegressor__min_samples_leaf=6, ExtraTreesRegressor__min_samples_split=8, ExtraTreesRegressor__n_estimators=100)',),\n",
" 'operator_count': 2,\n",
" 'internal_cv_score': -0.4444842302707152}"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tpot3.evaluated_individuals_[key]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"value の方には細かい情報が保存されている。 `operator_count` で Pipeline のシンプルさでフィルターをかけたりも可能だ。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"たまに最も良い Pipeline は GradientBoosting 回帰モデルを3回パラメータを変えて行ったものであると TPOT によって求められる時があり、 \n",
"(あまり人間が介入しすぎると Automated ML とは言えなくなるが) さすがにこれはちょっとなぁという Pipeline の時は他の Pipeline をこのようにチェックしたり \n",
"generation や population_size が小さすぎた場合は大きい値にして再度計算したりすると良いと思う。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 6.2 Export された file の確認"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"5.4 で出力した file の中身を確認してみたい。この Jupyter Notebook と同じフォルダにある tpot3_logS_QSPR.py をテキストエディタや cat コマンドで開いてみる。"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"import numpy as np\n",
"import pandas as pd\n",
"from sklearn.ensemble import ExtraTreesRegressor\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.pipeline import make_pipeline\n",
"from tpot.builtins import ZeroCount\n",
"\n",
"# NOTE: Make sure that the class is labeled 'target' in the data file\n",
"tpot_data = pd.read_csv('PATH/TO/DATA/FILE', sep='COLUMN_SEPARATOR', dtype=np.float64)\n",
"features = tpot_data.drop('target', axis=1).values\n",
"training_features, testing_features, training_target, testing_target = \\\n",
" train_test_split(features, tpot_data['target'].values, random_state=20181216)\n",
"\n",
"# Average CV score on the training set was:-0.43677564142857134\n",
"exported_pipeline = make_pipeline(\n",
" ZeroCount(),\n",
" ExtraTreesRegressor(bootstrap=False, max_features=0.7000000000000001, min_samples_leaf=4, min_samples_split=5, n_estimators=100)\n",
")\n",
"\n",
"exported_pipeline.fit(training_features, training_target)\n",
"results = exported_pipeline.predict(testing_features)\n"
]
}
],
"source": [
"!cat tpot3_logS_QSPR.py"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"上記のように最も良い Pipeline を用いた ML を行うためのスクリプトを書き出してくれており非常に助かる。 \n",
"実際に用いるためには後は `PATH/TO/DATA/FILE`, `COLUMN_SEPARATOR`, `target` を自分のデータセットに合わせて適宜変更するだけで良い。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"最もよい Pipeline は `ZeroCount` で前処理を行った後に `ExtraTreesRegressor` で予測を行う Pipeline のようだ。 "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 6.3 Pipeline の再構築"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"今回はこの Jupyter Notebook で準備したデータセットを使って引き続き Pipeline を用いて予測を行いたいので以下の部分だけ抜き出した。"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np #すでにimportしているがわかりやすさを重視するためにわざと残している\n",
"import pandas as pd #すでにimportしているがわかりやすさを重視するためにわざと残している\n",
"from sklearn.ensemble import ExtraTreesRegressor\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.pipeline import make_pipeline\n",
"from tpot.builtins import ZeroCount\n",
"\n",
"exported_pipeline_tpot3 = make_pipeline(\n",
" ZeroCount(),\n",
" ExtraTreesRegressor(bootstrap=False, max_features=0.7000000000000001, min_samples_leaf=4, min_samples_split=5, n_estimators=100)\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`make_pipeline` 関数を用いることで最も良いとされた Pipeline を再現して予測モデルの構築ができる。 \n",
"Sklearn の ML 同様 `fit` メソッドで予測モデルの構築ができる。"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Pipeline(memory=None,\n",
" steps=[('zerocount', ZeroCount()), ('extratreesregressor', ExtraTreesRegressor(bootstrap=False, criterion='mse', max_depth=None,\n",
" max_features=0.7000000000000001, max_leaf_nodes=None,\n",
" min_impurity_decrease=0.0, min_impurity_split=None,\n",
" min_samples_leaf=4, min_samples_split=5,\n",
" min_weight_fraction_leaf=0.0, n_estimators=100, n_jobs=None,\n",
" oob_score=False, random_state=None, verbose=0, warm_start=False))])"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"exported_pipeline_tpot3.fit(training_X, training_y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Pipeline が構築できた。続けて Sklearn の ML 同様 predict メソッドでデータセットの予測ができる。"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([-4.55851 , -5.30955607, -1.40719952, -0.09583857, -4.0573719 ,\n",
" -3.2350931 , -1.73425476, -1.02698429, -7.44066464, -4.13389024])"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"predicted_training_y = exported_pipeline_tpot3.predict(training_X)\n",
"predicted_training_y[:10]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 6.4 5-fold Cross Validation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`make_pipeline` 関数で作成した `exported_pipeline` オブジェクトは `cross_validate` 関数の引数 `estimator` に用いることもでき、 \n",
"5-fold Cross Validation などを行うことも簡単にでき、ロバストであるかどうかの検証も行える。"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'fit_time': array([0.61394882, 0.58112717, 0.58521986, 0.59816813, 0.61214423]),\n",
" 'score_time': array([0.00735998, 0.0070889 , 0.00589609, 0.00773478, 0.00749111]),\n",
" 'test_score': array([-0.43199187, -0.45730515, -0.43283408, -0.46029806, -0.42407188]),\n",
" 'train_score': array([-0.19643681, -0.1964946 , -0.20369601, -0.19860522, -0.19826147])}"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"kfold = KFold(n_splits=5, shuffle=True, random_state=random_state)\n",
"cross_validate(estimator=exported_pipeline_tpot3, X=training_X, y=training_y, scoring='neg_mean_absolute_error', \n",
" cv=kfold, n_jobs=-1, return_train_score=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"今回は5回ともおおよそ同じ `test_score`, `train_score` でありロバストと言えそうだ。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 6.5 tpot1, tpot3 で求めた Pipeline の比較"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"6.5.1 tpot1 で求めた Pipeline の構築"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"最後に 5.1, 5.4 で求めた Pipeline の比較を行いたい。計算コストを下げたので 5.1 の方が Pipeline がシンプルで予測性能が低いと考えられるがその通りになるだろうか。 \n",
"6.3 同様に 5.1 の方の Pipeline も構築する。"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"import numpy as np\n",
"import pandas as pd\n",
"from sklearn.ensemble import ExtraTreesRegressor\n",
"from sklearn.model_selection import train_test_split\n",
"\n",
"# NOTE: Make sure that the class is labeled 'target' in the data file\n",
"tpot_data = pd.read_csv('PATH/TO/DATA/FILE', sep='COLUMN_SEPARATOR', dtype=np.float64)\n",
"features = tpot_data.drop('target', axis=1).values\n",
"training_features, testing_features, training_target, testing_target = \\\n",
" train_test_split(features, tpot_data['target'].values, random_state=20181216)\n",
"\n",
"# Average CV score on the training set was:-0.45904943717365965\n",
"exported_pipeline = ExtraTreesRegressor(bootstrap=False, max_features=0.6500000000000001, min_samples_leaf=5, min_samples_split=14, n_estimators=100)\n",
"\n",
"exported_pipeline.fit(training_features, training_target)\n",
"results = exported_pipeline.predict(testing_features)\n"
]
}
],
"source": [
"!cat tpot1_logS_QSPR.py"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [],
"source": [
"exported_pipeline_tpot1 = ExtraTreesRegressor(bootstrap=False, max_features=0.6500000000000001, min_samples_leaf=5, min_samples_split=14, n_estimators=100)"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"ExtraTreesRegressor(bootstrap=False, criterion='mse', max_depth=None,\n",
" max_features=0.6500000000000001, max_leaf_nodes=None,\n",
" min_impurity_decrease=0.0, min_impurity_split=None,\n",
" min_samples_leaf=5, min_samples_split=14,\n",
" min_weight_fraction_leaf=0.0, n_estimators=100, n_jobs=None,\n",
" oob_score=False, random_state=None, verbose=0, warm_start=False)"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"exported_pipeline_tpot1.fit(training_X, training_y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"tpot1 で求めた Pipeline も構築できた。 tpot1 は `ExtraTressRegressor` を行っているだけというシンプルな Pipeline のようだ。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 6.5.2 tpot1, tpot3 のそれぞれの予測性能を計算する。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"可読性を上げるために X, y , pipeline を引数に与えたら MAE を計算する関数を宣言する。"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [],
"source": [
"def calculate_MAE(X, y, pipeline):\n",
" predicted_y = pipeline.predict(X)\n",
" return mean_absolute_error(y, predicted_y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"tpot1, tpot3 の Training set, Test set に対する MAE を求める。"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [],
"source": [
"MAE = np.zeros(4, )\n",
"i = 0\n",
"for pipeline in [exported_pipeline_tpot1, exported_pipeline_tpot3]:\n",
" for X, y in [(training_X, training_y), (test_X, test_y)]:\n",
" MAE[i] = calculate_MAE(X, y, pipeline)\n",
" i += 1"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>Training</th>\n",
" <th>Test</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>tpot1</th>\n",
" <td>0.269629</td>\n",
" <td>0.463421</td>\n",
" </tr>\n",
" <tr>\n",
" <th>tpot3</th>\n",
" <td>0.195962</td>\n",
" <td>0.455865</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" Training Test\n",
"tpot1 0.269629 0.463421\n",
"tpot3 0.195962 0.455865"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"result = pd.DataFrame(MAE.reshape(2, -1), index=['tpot1', 'tpot3'], columns=['Training', 'Test'])\n",
"result"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"tpot3 の方が Training set は大幅に, Test set はわずかではあるがどちらもよい予測性能を示した。 \n",
"今回は計算コストをあまり大きくせず、比較的シンプルな結果を優先したためあまり差が出なかったが、 \n",
"generation, population_size を増やせばよりよい Pipeline が探索できてはいたことも伝えておく。ぜひ自分自身で探索してほしい。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"実測値と予測値の散布図もプロットしてみる。こちらも可読性を上げるために実測値と予測値を与えたら散布図をプロットする関数を宣言する。"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [],
"source": [
"def plot_experimented_and_predicted_value(training_y, predicted_training_y,\n",
" test_y, predicted_test_y, title):\n",
" \n",
" def _plot_experimented_and_predicted_value(experimented_value, predicted_value, title):\n",
" lim = (min(experimented_value.min(), predicted_value.min()),\n",
" max(experimented_value.max(), predicted_value.max()))\n",
" plt.scatter(predicted_value, experimented_value, s=3)\n",
" plt.plot(lim, lim, c='red', alpha=0.5)\n",
" plt.xlim(lim)\n",
" plt.ylim(lim)\n",
" plt.xlabel('Predicted value', fontsize=16)\n",
" plt.ylabel('Experimented value', fontsize=16)\n",
" plt.title(title, fontsize=16)\n",
" \n",
" plt.figure(figsize=(11, 5))\n",
" plt.subplot(1, 2, 1)\n",
" _plot_experimented_and_predicted_value(training_y, predicted_training_y, f'{title}: Training set')\n",
" plt.subplot(1, 2, 2)\n",
" _plot_experimented_and_predicted_value(test_y, predicted_test_y, f'{title}: Test set')\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"プロットを行う。"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 792x360 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plot_experimented_and_predicted_value(training_y, exported_pipeline_tpot1.predict(training_X),\n",
" test_y, exported_pipeline_tpot1.predict(test_X), 'tpot1')"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 792x360 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plot_experimented_and_predicted_value(training_y, exported_pipeline_tpot3.predict(training_X),\n",
" test_y, exported_pipeline_tpot3.predict(test_X), 'tpot3')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 7. まとめ"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"TPOT による Automated ML の一例を示した。 \n",
"今回はチュートリアルということで計算コストを下げて行ったが実際に用いる時は generation, population_size どちらも大きな値にして行うべきだと考えられる。 \n",
"特に population_size の値は探索に大きく関わるので default の 100 などで Automated ML を行うとよいと思う。 \n",
"また、回帰と同様に判別モデルも `TPOTClassifier` を用いることで行うことができる。自動でよい予測性能を示す Pipeline を探してくれるので興味のある方はぜひ使ってみてほしい。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# EOF"
]
}
],
"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.6.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment