Skip to content

Instantly share code, notes, and snippets.

@hoto17296
Last active May 13, 2018 05:17
Show Gist options
  • Save hoto17296/0f5c6ef3aad4a9f1127f05bf00d7854e to your computer and use it in GitHub Desktop.
Save hoto17296/0f5c6ef3aad4a9f1127f05bf00d7854e to your computer and use it in GitHub Desktop.
ちゅら.ai アルゴリズム実装会 #1「決定木」
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 参考\n",
"- [Rによるデータサイエンス13「樹木モデル」](https://www.slideshare.net/takemikami/r13-9821987)\n",
"- [2-5. ジニ係数 | 統計学の時間 | 統計WEB](https://bellcurve.jp/statistics/course/3798.html)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ジニ係数を計算できるようにする"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/opt/conda/lib/python3.6/site-packages/matplotlib/__init__.py:1067: UserWarning: Duplicate key in file \"/opt/conda/lib/python3.6/site-packages/matplotlib/mpl-data/matplotlibrc\", line #620\n",
" (fname, cnt))\n"
]
}
],
"source": [
"from sklearn.datasets import load_iris\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import pandas as pd"
]
},
{
"cell_type": "code",
"execution_count": 2,
"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>x0</th>\n",
" <th>x1</th>\n",
" <th>x2</th>\n",
" <th>x3</th>\n",
" <th>y</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>5.1</td>\n",
" <td>3.5</td>\n",
" <td>1.4</td>\n",
" <td>0.2</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>4.9</td>\n",
" <td>3.0</td>\n",
" <td>1.4</td>\n",
" <td>0.2</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>4.7</td>\n",
" <td>3.2</td>\n",
" <td>1.3</td>\n",
" <td>0.2</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>4.6</td>\n",
" <td>3.1</td>\n",
" <td>1.5</td>\n",
" <td>0.2</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>5.0</td>\n",
" <td>3.6</td>\n",
" <td>1.4</td>\n",
" <td>0.2</td>\n",
" <td>0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" x0 x1 x2 x3 y\n",
"0 5.1 3.5 1.4 0.2 0\n",
"1 4.9 3.0 1.4 0.2 0\n",
"2 4.7 3.2 1.3 0.2 0\n",
"3 4.6 3.1 1.5 0.2 0\n",
"4 5.0 3.6 1.4 0.2 0"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"iris = load_iris()\n",
"df = pd.DataFrame(iris.data, columns=['x{}'.format(i) for i in range(4)])\n",
"df['y'] = iris.target\n",
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.collections.PathCollection at 0x7f7d273b49b0>"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/opt/conda/lib/python3.6/site-packages/matplotlib/font_manager.py:1328: UserWarning: findfont: Font family ['TakaoPGothic'] not found. Falling back to DejaVu Sans\n",
" (prop.get_family(), self.defaultFamily[fontext]))\n"
]
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 1152x288 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig = plt.figure(figsize=(16, 4))\n",
"ax = fig.add_subplot(121)\n",
"ax.set_title('Sepal')\n",
"ax.set_xlabel('Length (x0)')\n",
"ax.set_ylabel('Width (x1)')\n",
"ax.scatter(x=df.x0, y=df.x1, c=df.y, alpha=0.5)\n",
"ax = fig.add_subplot(122)\n",
"ax.set_title('Petal')\n",
"ax.set_xlabel('Length (x2)')\n",
"ax.set_ylabel('Width (x3)')\n",
"ax.scatter(x=df.x2, y=df.x3, c=df.y, alpha=0.5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ひとまず Iris データセット全体のジニ係数を計算する"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.66666666666666674"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def gini_index(df, target='y'):\n",
" return 1 - ((df.groupby(target).size() / len(df)) ** 2).sum()\n",
"\n",
"gini_index(df)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## x0 で二分割した場合のジニ係数を計算する\n",
"特に意味は無いけど x0 の平均値で分けてみる"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.17476190476190478"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def binary(df, root_gi, x, boundary):\n",
" df0 = df[x < boundary]\n",
" df1 = df[x >= boundary]\n",
" gi = root_gi - (len(df0) * gini_index(df0) + len(df1) * gini_index(df1)) / len(df)\n",
" return gi, (df0, df1)\n",
"\n",
"gi, _ = binary(df, gini_index(df), df.x0, df.x0.mean())\n",
"gi"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## すべての説明変数の中でジニ係数が最も高い二分境界を計算する"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"class Node:\n",
"\n",
" def classify(self):\n",
" raise NotImplementedError()\n",
"\n",
"\n",
"class Tree(Node):\n",
" \n",
" def __init__(self, col, boundary, gi, depth=0):\n",
" self.col = col\n",
" self.boundary = boundary\n",
" self.gi = gi\n",
" self.depth = depth\n",
" self.nodes = []\n",
"\n",
" def __repr__(self):\n",
" text = '<{} col={col} boundary={boundary} gi={gi} depth={depth}>'.format(type(self).__name__, **self.__dict__)\n",
" for node in self.nodes:\n",
" text += '\\n'\n",
" text += '\\t' * (self.depth + 1)\n",
" text += repr(node)\n",
" return text\n",
"\n",
" def classify(self, row):\n",
" if row[self.col] < self.boundary:\n",
" return self.nodes[0].classify(row)\n",
" else:\n",
" return self.nodes[1].classify(row)\n",
"\n",
"\n",
"class Leaf(Node):\n",
" \n",
" def __init__(self, category):\n",
" self.category = category\n",
" \n",
" def __repr__(self):\n",
" return '<{} category={category}>'.format(type(self).__name__, **self.__dict__)\n",
"\n",
" def classify(self, row):\n",
" return self.category"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<Tree col=x3 boundary=1.0 gi=0.3333333333333334 depth=0>"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def search_boundary(df, target='y'):\n",
" root_gi = gini_index(df, target)\n",
" max_node = Tree(None, None, 0.0)\n",
" max_separated = ()\n",
" for col in df.columns:\n",
" if col == target: continue\n",
" for boundary in df[col].drop_duplicates().sort_values():\n",
" gi, separated = binary(df, root_gi, df[col], boundary)\n",
" if max_node.gi <= gi:\n",
" max_node = Tree(col, boundary, gi)\n",
" max_separated = separated\n",
" return max_node, max_separated\n",
"\n",
"tree, separated = search_boundary(df)\n",
"tree"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<Tree col=x3 boundary=1.8 gi=0.38969404186795487 depth=0>"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"search_boundary(separated[1])[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 分割しまくって木を作る"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"def make_tree(df, depth=0, max_depth=4, target='y'):\n",
" \"\"\"Tree または Leaf オブジェクトを返す\"\"\"\n",
" global importance\n",
" categories = df[target].unique()\n",
" assert categories.size > 0\n",
" if categories.size == 1:\n",
" return Leaf(categories[0])\n",
" if depth > max_depth:\n",
" return Leaf(df.groupby(target).size().idxmax())\n",
" tree, separated = search_boundary(df, target)\n",
" importance[tree.col] += tree.gi * len(df)\n",
" tree.depth = depth\n",
" tree.nodes = [make_tree(_df, depth+1, max_depth) for _df in separated]\n",
" return tree"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<Tree col=x3 boundary=1.0 gi=0.3333333333333334 depth=0>\n",
"\t<Leaf category=0>\n",
"\t<Tree col=x3 boundary=1.8 gi=0.38969404186795487 depth=1>\n",
"\t\t<Tree col=x2 boundary=5.0 gi=0.08239026063100137 depth=2>\n",
"\t\t\t<Tree col=x3 boundary=1.7 gi=0.04079861111111116 depth=3>\n",
"\t\t\t\t<Leaf category=1>\n",
"\t\t\t\t<Leaf category=2>\n",
"\t\t\t<Tree col=x3 boundary=1.6 gi=0.2222222222222222 depth=3>\n",
"\t\t\t\t<Leaf category=2>\n",
"\t\t\t\t<Tree col=x2 boundary=5.8 gi=0.4444444444444444 depth=4>\n",
"\t\t\t\t\t<Leaf category=1>\n",
"\t\t\t\t\t<Leaf category=2>\n",
"\t\t<Tree col=x2 boundary=4.9 gi=0.013547574039067499 depth=2>\n",
"\t\t\t<Tree col=x1 boundary=3.2 gi=0.4444444444444444 depth=3>\n",
"\t\t\t\t<Leaf category=2>\n",
"\t\t\t\t<Leaf category=1>\n",
"\t\t\t<Leaf category=2>"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"importance = pd.Series(index=df.columns.drop('y')).fillna(0)\n",
"tree = make_tree(df)\n",
"importance /= importance.sum()\n",
"tree"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"x0 0.000000\n",
"x1 0.013333\n",
"x2 0.064056\n",
"x3 0.922611\n",
"dtype: float64"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"importance"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 分類できるようにする"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(Tree クラスと Leaf クラスに classify メソッドを実装した)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tree.classify(df.iloc[100])"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0 0\n",
"1 0\n",
"2 0\n",
"3 0\n",
"4 0\n",
"dtype: int64"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pred = pd.Series([tree.classify(row) for _, row in df.iterrows()])\n",
"pred.head()"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"(df.y == pred).all()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"学習データをそのまま突っ込んだらすべて正しく分類できたっぽい"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 精度を計算する\n",
"ランダムに分割した 80% で学習 20% で検証を 20 回やって正解率の平均を出す"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.94833333333333325"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"precisions = []\n",
"for _ in range(20):\n",
" shuffled_df = df.reindex(np.random.permutation(df.index)).reset_index(drop=True)\n",
" p = int(0.8 * len(df))\n",
" train_df = shuffled_df.iloc[:p, :].reset_index(drop=True)\n",
" test_df = shuffled_df.iloc[p:, :].reset_index(drop=True)\n",
" # train\n",
" tree = make_tree(train_df)\n",
" # predict\n",
" pred = pd.Series([tree.classify(row) for _, row in test_df.iterrows()])\n",
" # evaluate\n",
" precisions.append((pred == test_df.y).sum() / len(test_df))\n",
"np.array(precisions).mean()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 書き直し\n",
"- scikit-learn っぽいインタフェースにしたい\n",
"- Tree, Leaf クラスは上記のものを使いまわしている"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"class BinaryDecisionTree:\n",
" \n",
" def __init__(self, max_depth=4):\n",
" \"\"\"モデルのパラメータを設定する\"\"\"\n",
" self.max_depth = 4\n",
" \n",
" def fit(self, df, target='y'):\n",
" \"\"\"学習データから決定木を構築する\"\"\"\n",
" self.importance = pd.Series(index=df.columns.drop(target)).fillna(0)\n",
" self.target = target\n",
" self.tree = self._make_tree(df)\n",
"\n",
" def _make_tree(self, df, depth=0):\n",
" categories = df[self.target].unique()\n",
" assert categories.size > 0\n",
" if categories.size == 1:\n",
" return Leaf(categories[0])\n",
" if depth > self.max_depth:\n",
" return Leaf(df.groupby(target).size().idxmax())\n",
" tree, separated = search_boundary(df)\n",
" self.importance[tree.col] += tree.gi * len(df)\n",
" tree.depth = depth # TODO ダサい\n",
" tree.nodes = [self._make_tree(_df, depth+1) for _df in separated]\n",
" return tree\n",
" \n",
" def _search_boundary(self, df):\n",
" \"\"\"与えられたデータの中で最良の分割条件を探索する\"\"\"\n",
" root_gi = gini_index(df, self.target)\n",
" max_node = Tree(None, None, 0.0)\n",
" max_separated = ()\n",
" for col in df.columns:\n",
" if col == target: continue\n",
" for boundary in df[col].drop_duplicates().sort_values():\n",
" gi, separated = self._binary(df, root_gi, df[col], boundary)\n",
" if max_node.gi <= gi:\n",
" max_node = Tree(col, boundary, gi)\n",
" max_separated = separated\n",
" return max_node, max_separated\n",
" \n",
" def _binary(self, df, root_gi, x, boundary):\n",
" \"\"\"与えられた分割条件でデータを分割した場合の情報利得を計算する\"\"\"\n",
" df0 = df[x < boundary]\n",
" df1 = df[x >= boundary]\n",
" gi = root_gi - (len(df0) * self._gini_index(df0) + len(df1) * self._gini_index(df1)) / len(df)\n",
" return gi, (df0, df1)\n",
" \n",
" def _gini_index(df, target='y'):\n",
" \"\"\"与えられたデータのジニ係数を計算する\"\"\"\n",
" return 1 - ((df.groupby(target).size() / len(df)) ** 2).sum()\n",
"\n",
" def predict(self, df):\n",
" \"\"\"説明変数から目的変数を予測する\"\"\"\n",
" return pd.Series([self.tree.classify(row) for _, row in df.iterrows()])"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"shuffled_df = df.reindex(np.random.permutation(df.index)).reset_index(drop=True)\n",
"p = int(0.8 * len(df))\n",
"train_df = shuffled_df.iloc[:p, :].reset_index(drop=True)\n",
"test_df = shuffled_df.iloc[p:, :].reset_index(drop=True)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"x0 0.000000\n",
"x1 1.333333\n",
"x2 6.240821\n",
"x3 72.359179\n",
"dtype: float64"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model = BinaryDecisionTree()\n",
"model.fit(train_df)\n",
"model.importance"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<Tree col=x3 boundary=1.0 gi=0.32464769647696473 depth=0>\n",
"\t<Leaf category=0>\n",
"\t<Tree col=x3 boundary=1.8 gi=0.3672941686999054 depth=1>\n",
"\t\t<Tree col=x2 boundary=5.0 gi=0.09339949590422182 depth=2>\n",
"\t\t\t<Tree col=x3 boundary=1.7 gi=0.04875000000000007 depth=3>\n",
"\t\t\t\t<Leaf category=1>\n",
"\t\t\t\t<Leaf category=2>\n",
"\t\t\t<Tree col=x3 boundary=1.6 gi=0.2222222222222222 depth=3>\n",
"\t\t\t\t<Leaf category=2>\n",
"\t\t\t\t<Tree col=x2 boundary=5.8 gi=0.4444444444444444 depth=4>\n",
"\t\t\t\t\t<Leaf category=1>\n",
"\t\t\t\t\t<Leaf category=2>\n",
"\t\t<Tree col=x2 boundary=4.9 gi=0.01697530864197544 depth=2>\n",
"\t\t\t<Tree col=x1 boundary=3.2 gi=0.4444444444444444 depth=3>\n",
"\t\t\t\t<Leaf category=2>\n",
"\t\t\t\t<Leaf category=1>\n",
"\t\t\t<Leaf category=2>"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.tree"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.0"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pred = model.predict(test_df)\n",
"(pred == test_df.y).sum() / len(test_df)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"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