Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save tatamiya/f549aaee716fc1429f588c2240277e51 to your computer and use it in GitHub Desktop.
Save tatamiya/f549aaee716fc1429f588c2240277e51 to your computer and use it in GitHub Desktop.
Anomaly detection based on Hotelling theory with scikit-learn
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**このシートの目的**\n",
"\n",
"井手剛「入門 機械学習による異常検知」 (コロナ社,2015)第2章のホテリング理論による異常検知を,Pythonのscikit-learnを使って試してみた。"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/tatamiya/.pyenv/versions/3.7.1/envs/sklearn/lib/python3.7/site-packages/pandas/compat/__init__.py:84: UserWarning: Could not import the lzma module. Your installed Python is incomplete. Attempting to use lzma compression will result in a RuntimeError.\n",
" warnings.warn(msg)\n",
"/Users/tatamiya/.pyenv/versions/3.7.1/envs/sklearn/lib/python3.7/site-packages/pandas/compat/__init__.py:84: UserWarning: Could not import the lzma module. Your installed Python is incomplete. Attempting to use lzma compression will result in a RuntimeError.\n",
" warnings.warn(msg)\n"
]
}
],
"source": [
"import numpy as np\n",
"from scipy.stats import chi2\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline\n",
"\n",
"from sklearn.covariance import EllipticEnvelope, EmpiricalCovariance, MinCovDet\n",
"from sklearn.metrics import classification_report\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn.datasets import make_blobs"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"# plot color setting\n",
"colors = ['#1f77b4', '#ff7f0e']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 準備"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**ホテリング理論の概要**\n",
"\n",
"学習データ数が自由度Mと比べて十分大きい場合,mahalanobis距離の2乗は自由度Mの$\\chi^2$分布\n",
"\n",
"$$\\chi^2(x | M, 1) = \\frac{1}{2^{M/2}\\Gamma(M/2)}x^{M/2 - 1}e^{-x/2}$$\n",
"\n",
"に従うと考えることができる。\n",
"\n",
"これに基づき,5%未満の確率で現れる大きな値を異常値とみなす。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 閾値の決定"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"5.991464547107979"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 90%信頼区間の上限を取る。\n",
"_, chi2_interval_max = chi2.interval(alpha=0.9, df=2)\n",
"chi2_interval_max"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 実験用データ\n",
"正常:共分散のある楕円常に分布した2次元データ\n",
"\n",
"異常:一様に分布したデータ\n",
"\n",
"参考:https://scikit-learn.org/stable/auto_examples/covariance/plot_mahalanobis_distances.html"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"# Example settings\n",
"n_samples = 300\n",
"outliers_fraction = 0.15\n",
"n_outliers = int(outliers_fraction * n_samples)\n",
"n_inliers = n_samples - n_outliers"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"n_features = 2\n",
"\n",
"# generate data\n",
"gen_cov = [[0.5,0.25], [0.25,0.4]]\n",
"\n",
"X_in = np.dot(np.random.randn(n_samples-n_outliers, n_features), gen_cov)\n",
"\n",
"rng = np.random.RandomState(42)\n",
"X_out = rng.uniform(low=-6, high=6,\n",
" size=(n_outliers, n_features))\n",
"X = np.vstack([X_in, X_out])\n",
"\n",
"y = np.ones(X.shape[0])\n",
"y[-n_outliers:] = -1"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.collections.PathCollection at 0x125138be0>"
]
},
"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": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.scatter(X[:-n_outliers, 0], X[:-n_outliers, 1], c=colors[0])\n",
"plt.scatter(X[-n_outliers:, 0], X[-n_outliers:, 1], c=colors[0], marker='x')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# EmpiricalCovarianceを使用した方法\n",
"- sklearn.metricsのEmpiricalCovarianceを使えば,標本共分散行列を最尤法により求めることができる。\n",
"- ただし,学習データに異常値が含まれる場合,標本共分散行列が過大評価され,conservativeな判定をしてしまう。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 訓練データに異常値を含まない場合"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"cov_emp = EmpiricalCovariance().fit(X_in)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[0.31107378, 0.21888055],\n",
" [0.21888055, 0.20255113]])"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cov_emp.covariance_"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/tatamiya/.pyenv/versions/3.7.1/envs/sklearn/lib/python3.7/site-packages/ipykernel_launcher.py:6: UserWarning: No contour levels were found within the data range.\n",
" \n"
]
},
{
"data": {
"text/plain": [
"<matplotlib.legend.Legend at 0x1273f1ef0>"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"xx, yy = np.meshgrid(np.linspace(-7, 7, 150),\n",
" np.linspace(-7, 7, 150))\n",
"\n",
"Z = cov_emp.mahalanobis(np.c_[xx.ravel(), yy.ravel()]) > chi2_interval_max\n",
"Z = Z.reshape(xx.shape)\n",
"plt.contour(xx, yy, Z, levels=[0], linewidths=2, colors='black')\n",
"\n",
"outlier_pred = cov_emp.mahalanobis(X) > chi2_interval_max\n",
"outlier_true = y == -1\n",
"\n",
"plt.scatter(X[outlier_pred&outlier_true, 0], X[outlier_pred&outlier_true, 1], c=colors[1], marker='x', label='TP')\n",
"plt.scatter(X[~outlier_pred&outlier_true, 0], X[~outlier_pred&outlier_true, 1], c=colors[0], marker='x', label='FN')\n",
"plt.scatter(X[outlier_pred&~outlier_true, 0], X[outlier_pred&~outlier_true, 1], c=colors[1], marker='o', label='FP')\n",
"plt.scatter(X[~outlier_pred&~outlier_true, 0], X[~outlier_pred&~outlier_true, 1], c=colors[0], marker='o', label='TN')\n",
"\n",
"plt.legend()"
]
},
{
"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>precision</th>\n",
" <th>recall</th>\n",
" <th>f1-score</th>\n",
" <th>support</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <td>False</td>\n",
" <td>1.0000</td>\n",
" <td>0.941176</td>\n",
" <td>0.969697</td>\n",
" <td>255.00</td>\n",
" </tr>\n",
" <tr>\n",
" <td>True</td>\n",
" <td>0.7500</td>\n",
" <td>1.000000</td>\n",
" <td>0.857143</td>\n",
" <td>45.00</td>\n",
" </tr>\n",
" <tr>\n",
" <td>accuracy</td>\n",
" <td>0.9500</td>\n",
" <td>0.950000</td>\n",
" <td>0.950000</td>\n",
" <td>0.95</td>\n",
" </tr>\n",
" <tr>\n",
" <td>macro avg</td>\n",
" <td>0.8750</td>\n",
" <td>0.970588</td>\n",
" <td>0.913420</td>\n",
" <td>300.00</td>\n",
" </tr>\n",
" <tr>\n",
" <td>weighted avg</td>\n",
" <td>0.9625</td>\n",
" <td>0.950000</td>\n",
" <td>0.952814</td>\n",
" <td>300.00</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" precision recall f1-score support\n",
"False 1.0000 0.941176 0.969697 255.00\n",
"True 0.7500 1.000000 0.857143 45.00\n",
"accuracy 0.9500 0.950000 0.950000 0.95\n",
"macro avg 0.8750 0.970588 0.913420 300.00\n",
"weighted avg 0.9625 0.950000 0.952814 300.00"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.DataFrame(classification_report(outlier_true, outlier_pred, output_dict=True)).T"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 問題点:訓練データが異常値を含む場合\n",
"- 共分散行列が異常値の影響を受けて過大評価されてしまう。"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"X_train, X_test, y_train, y_test = train_test_split(X, y)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[ 2.27804299, -0.40872802],\n",
" [-0.40872802, 2.07274656]])"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cov_emp = EmpiricalCovariance().fit(X_train)\n",
"cov_emp.covariance_"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/tatamiya/.pyenv/versions/3.7.1/envs/sklearn/lib/python3.7/site-packages/ipykernel_launcher.py:9: UserWarning: No contour levels were found within the data range.\n",
" if __name__ == '__main__':\n"
]
},
{
"data": {
"text/plain": [
"<matplotlib.legend.Legend at 0x1275299e8>"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAXIAAAD4CAYAAADxeG0DAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAgAElEQVR4nO3deXxU1d348c/JRsIWiiBIUIm4sYQ1kiqCEVBAoFB9rFtrq8gm5QFFkOVHWPogCtqgT1lKAZeKUheEggLVlFAQCYIIYREeWVRABIIJWxKynN8fkxlmkplkkrkzd+7M9/165QVz5869J8nMN+d+7znfo7TWCCGEsK4IsxsghBDCNxLIhRDC4iSQCyGExUkgF0IIi5NALoQQFhdlxkkbNWqkW7RoYcaphRDCsnbs2HFGa924/HZTAnmLFi3Yvn27GacWQgjLUkp95267pFaEEMLiJJALIYTFSSAXQgiLk0AuhBAWJ4FcCCEsTgK5EEJYnARyIYSwOAnkQghhcRLIhRDC4iSQCyGExUkgF0IIizMkkCulGiilPlBKfaOU2q+Uut2I4wohhKiaUUWzXgXWaa3/SykVA9Q26Lim01qjlPL4WAghzOZzj1wpFQ90B5YAaK0va61zfT1uMMjMzGT9+vXYF6jWWrN+/XoyMzPNbZgQQjgxIrWSCJwGXldK7VRKLVZK1Sm/k1JqqFJqu1Jq++nTpw04rX9prSkoKCArK8sRzNevX09WVhYFBQWO4C6EEGZTvgYkpVQysBXoqrXOUkq9CpzTWk/x9Jrk5GQdyHrkNU2POAdvu5SUFHr37i3pFSFEwCmldmitk8tvN6JHfgw4prW2R7sPgE4GHNcQvqRHlFL07t3bZZsEcSFEsPE5kGutTwI/KKVuKdvUE9jn63GN4Gt6xL6/M+c/CkIIEQyMGrUyClhWNmLlMPCEQcf1iXOPOisry5Ei8SY94hz07fs7p1mkZy6ECBaGBHKt9ddAhbxNMLAHc+c8tzdBWAGxsbFXgn7Z6yjbLkHcNzKsUwjjmLL4ciB5So9UGsw3zIKCPFL7zEJjC+qsm4iKjad37wkScHyUmZlJQUGB43dg/x3FxsaSmppqdvOEsJyQnqJfPj2SlpZGSkqKS87czYugIA+yFtiCN8C6ibbHBXlICPeNDOsUwngh3SNXSrmmR5xy5h7TI0pBn1m2/2ctsH0BpIywbZfeuE98uW8hhHDP53HkNWGJceRaw/QGVx5PzZUgbiCtNTNmzHA8TktLkyAuRBX8OY486JUPEF4F8XUTXbetm2jbLnwmwzqp8L2G0/cujBcWgbxa7EE8a4EtnTI11/ZvWc5cgrlvanTfIsRIDR9htJDOkdeIUhAb75oTt+fMY+MlveKjGt23CCHON3sBl/kJKSkpMgxT1EhY5MjL8ypnrrVr0C7/WPgknMeRSw0fUVNhnSN35vVlbfkPlHzADFXt+xYhRGr4CKOFVSCXMcwiGMjN3iBS/mdu0d9BWOXIZQyzMJvU8AkiZTO4HffC7AMdYuPh7olVvz6IhFWPHOSyVpjL083elJSUsLjZGzTKzeB2Ga1WkGe5nnnY3eyUG00iGITzzd6g4Ry87YJ8Brfc7ETGMIvgEc43e4OG89BiuyAO4pUJq0Aul7VCCIcQmsEdVjc7AVJTU10uY+3B3P5YLnmFCAPlZ3D3meWaZrFYzzzsAjl4vqyVOtlChIkQm8EdloHcHZk6LUSYuXui64xtezC34OdcAnkZGWMuRBgKkRncYXWzsyoyxlwIYUUSyJ3I1GkhhBVJaqWMTJ0WQliVYYFcKRUJbAeOa637G3XcQAn3OtlCCOsyskc+GtgP1DfwmAFV1RhzIYQIRobkyJVSzYF+wGIjjucLX9dClKnTQgirMepm51xgPFDqaQel1FCl1Hal1PbTp08bdFpXshaiECIc+RzIlVL9gVNa6x2V7ae1XqS1TtZaJzdu3NjX07o7viwaIYQwlkUWnjAiR94V+JVS6j4gFqivlHpba/1bA47tNStM6JE6LkJYiIUWnvC5R661nqi1bq61bgE8DPw70EHcLpgn9EjaRwgLsdjCEyE1IShYJ/RI2kcIi7HXXUkZYQve0xu4VkoMgs6hM0MnBGmtM4FMI49ZjXMH7YQeK6R9Qo2ksYTP7MHceQWhIAziEEIzO4N9Qo+9Pc5LzEkQv+Knn35i9uzZnDx50pBjlZSU0KxZM8e2EydOEBkZSZMmTTy+rmnTpowfP77SfUQY8bTwRBAG85AJ5BDcE3o8pX2CpX3+9uOPP3Lq1Cm3z+3YsYPnnnuOn3/+OcCtquiNN97g5ZdfplOnTm6fv/rqq7nmmmsC3CoRcE45cZ0yHNXnxSuP0bbHQfS5DalADsE5oSeY0z7+dunSJaZMmcLcuXMpLfU4zQCAe++9l9/97nc+/yy01uzevZtDhw45trVs2ZJ27dp5PLbWmrfeeotPP/2UJ5980uOxIyIiePbZZ5k+fTq1a9f2qZ0iiJUtPHEsYQB7SKU3oPrMQqM5dOwMxzZuDKrFZkIukAejYE/7GOHChQvMnDmTHTtcpxMcOHCA77//noiICJKSktx+r7GxsTz99NM8/vjjhv0stNbMmDHD8TgtLa3KYz/22GO8+eabLFiwgIKCArfH3Lt3Ly+//DLvvfcet9xyi8vzycnJTJo0ibp16xryPQhz6dQJ7ClYR9a2bVD2mV1PKlkntpFybUFQ3XdRZoyYSE5O1tu3bw/4ec0WSjfgSkpK2LZtGxcvXuTUqVNMmjSJ7777zu2+SUlJLF26lOTk5IC0zfkKyM6oG8tffvklgwcPJjs72+3zLVq04IUXXqBx48bUqVOHlJQUIiJCanBYWPHne6kmlFI7tNYVPkjSIw+gYEz71MS+fft46qmn+OKLL1y2d+rUiSlTprikHGJjY7n99tuJjo4OSNv8nca67bbb2L59O1u3bnXptV+6dIkZM2awc+dOHn30Ucf2O+64g8WLF9OqVauaf1PCNFYZpCCBXFTpzJkzTJo0iS+//BKwBfLLly/TpEkT2rZti1KKvn378t///d9ERZn7lgpEGismJobu3btX2N6vXz9ee+011q1bh9aaPXv2sGXLFjp06EDr1q1d9m3evDmzZs2ibdu2PrdH+I9lBilorQP+1blzZy2CX2lpqX733Xd1o0aNNODyNWTIEP3zzz+b3USPSktLK30cCGfPntWDBw+u8LOzf0VHR+upU6fqgoKCgLdNVK20tFSvXbtWT5s2Ta9du9bt40ADtms3MVVy5MKtY8eOMWLECNasWQNAjx49mDFjBrVr16Zhw4Zcf/31JrfQOr777jvOnj3reKy1ZvHixSxYYJto0qZNG5YsWUJKSopZTRQeZGZmUlBQ4OiB67IeemxsrCmjVjzlyCWQCwAuXrzI1KlTef/99ykpKSEnJ4eCggLq16/Pyy+/zFNPPRVcl5IhYOPGjTz11FN8++23KKUcE5hSUlJIT0/nuuuu89u5dQjdePe3YPpZSSAXHmVkZDBkyBCOHDnisn3gwIHMmzePhIQEk1oW+vLz85k2bRqvvPIKJSUlju1169bl2Wef5aqrrqJu3bo8+OCD1KtXz5BzBlsvU3jPUyCXcVFhLDc3l6eeeopevXpx5MgROnTowObNm/nhhx84deoUK1eulCDuZ3Fxcbz00kvk5OTwww8/8M033/DAAw9w4cIFZsyYwejRoxk8eDBt27atcNOtJrQUcAtJ0iMPUytXruTpp5/mxx9/JCYmhqlTpzJu3LiADRMUlVu9ejWfffYZWms2b97Mzp07AXj88cdJT0+nYcOGNT62c/C2kwJu1iCpFQHYCkqNGjWK999/H5BxzmbyNvdaXFxMeno6aWlpFBQUcPXVV/Pkk08SFRXFddddx+9//3tiYmKqfe7qznwV5pNAHua01rz99tuMGTOGs2fPUqdOHWbNmsXTTz9NZGSk2c0LOzXJUx88eJCnnnqKTZs2uWxv164dS5Ys8XrmrPTIrUtmdoax77//nuHDh7N27VoA7rnnHhYtWkSLFi3MbViYcs5TAy6zT1NSUjz2zG+++WYyMzN5//33OXjwIKWlpfz9739n9+7dpKSkMHbsWKZPn05cXFyl5w7XAm6hTHrkIay0tJSFCxfy/PPPc+HCBRo0aMDcuXMNLU4lasaoXnH56pI33ngjixcv5q677vL4Ghm1Yl2SWgkzBw4cYMiQIY7L8AceeIC//OUvNG3a1OSWCTsj89Tbtm1j8ODB7NmzB4Dhw4fz0ksvUb9+fY/nDpax0cJ7MvwwjJw5c4bk5GQ2bdpEkyZN+OCDD/jggw8kiAcRey/YmS/ry3bp0oUdO3Ywbdo0oqOjWbhwIa1bt+bjjz92u3+oFHATNhLIQ9Dhw4e5cOECCQkJ7Nu3jwceeMDsJgkn5fPUaWlppKSkuIztrgn7MNKvvvqKLl26cPz4cfr3789jjz3GmTNnDP4uRDCRQB5CtNYsW7aM++67D4AbbrjBp/HGwj88VWhMSUkxpEJj27Zt2bJlC6+88gpxcXG88847tGrViuXLl8uEnxAlOfIQsmrVKgYNGgRAr169WLx4sRS3CmKByFMfOnSIIUOGsGHDBgAGDBjAggULZMauRfktR66UulYptUEptU8ptVcpNdrXY4qa2b17NwAPPvgg//rXvzwG8fJ/vKWXZo5A5KlbtmxJRkYGixYton79+qxevZrWrVvzt7/9TX7vIcSI1EoxMFZr3Rr4JTBSKdW6itcIA507d45hw4aRlpYGUOkiw5mZmS55WHu+NjMzM1DNFQGmlGLIkCHs27ePAQMGcO7cOYYOHUrPnj1dFqgW1uVzINda/6i1/qrs/+eB/YBctwXQhAkTWLRoETExMfzpT3/i+eefd7ufFEwKbwkJCaxatYp3332Xxo0bs2HDBpKSkipUXhTWY2iOXCnVAvgP0FZrfa7cc0OBoQDXXXddZ08L9YrquXz5Mr169WLTpk0sWbKEJ598stL9ZXq2ANsQ1TFjxrBs2TLAthbp0qVLZem5IOf3ceRKqbrAh8CY8kEcQGu9SGudrLVObty4sVGnDWs7d+50jBdXSnn1IXRew9JOgnj4adSoEW+//TZr1qyhefPmfPnll3Tq1Ilp06Zx+fJlx35ylWYNhgRypVQ0tiC+TGu9wohjiqr95je/ITs7mxtuuIHPPvuMLl26VPkaoyeiCGvr168fe/fuZfjw4RQVFTF9+nQ6d+7Mtm3b5P6JhfhcNEvZunJLgP1a6z/73iThjSNHjnDy5EnAdgPz2muvrfI1UjBJuFO/fn3mz59PYmIiL730Env27OH2229n0KBB3HrrrXTr1k2m8Ac5I3rkXYHfAT2UUl+Xfd1nwHGFB/Pnz6dt27ZcuHCBZs2a0aRJE69e5++JKMK6lFKMGzeOJUuWcMcdd6C1ZsWKFSxdupR69eoFxXtDhs16JhOCLObo0aMkJiYC8PDDD/Pqq69y9dVXV+sYUjBJeGIv5HX8+HFWrVrFqVOnuPnmmzlw4ICp7ZKKjTZSjzxE5OfnA7ba1O+++26NjiEFk6wnOzubjIwM8vLyiI+Pp2fPniQlJRl6Duf7JwkJCTzyyCO8+uqr/Pjjj+zZs8e0ES01rd8eTiSQW1REhJTJCRfZ2dmsXr2aoqIiAPLy8li9ejWAYcHc3f2T1atX8+abb5Kbm0unTp2YPn06EyZMCHjQdB5plZWV5QjoMmz2CokGQgS5jIwMRxC3KyoqIiMjw7BzuLt/MmDAABYvXsyAAQMoKipi0qRJnDhxwrBzVrd9MmzWMwnkFlJaWuroiYnwkZeXV63tNZWamuoSLJVS3H///axatcqxLOCHH35oyk1GGTZbOQnkFpGTk0OPHj0c0+/79u1rcotEoHhagzM+Pt7wc8397P+YsWafS4CcsWYfzdreDsDo0aO55557OHz4sOHn9sRf9dtDieTILeKjjz5i48aNNGrUiPnz5/Nf//VfZjdJ+JHzzU13IiMj6dmzp6Hn1FpzrqCI1z8/CkBa/9bMWLOP1z8/yh+GTOLph/sxevRoMjIySEpKYubMmYwaNYrIyEhD21Gep2GzgAybLSOB3CKKi4sB29qbDz74oMmtEb5YufM4c9Yf4ERuPs0axPFw6zhKDmc5RqTcdNNN7Nq1q0Je3FlMTIzho1aUUqT1txUuff3zo46A/kTXFqT1b41SbbnnnnsYPXo0y5cv55lnnuHcuXOOqpv+lJqa6jI6xR7MJYjbSGpFiABaufM4E1dkczw3Hw0cz83n1S1n+CrH1qvNy8tj+/btlQZxuDIM1WjOwdzOFsRtAfPqq6/m3XffdSwaba+BHwgybNYzCeRCGCQ7O5u5c+cyffp05s6dS3Z2doV95qw/QH6Ra8nYYiLYUVy9ys/+yI9D2YSgNftctpXPmQN07NgRsN38fOCBBxzlIoQ5JJALYQD7WG97Tts+1rt8MD+R674nfVHHcKi4Ie8VJPF6fmfeK0jiULH79Vajo6MNz4/DlSD++udHeaJrC47Muo8nurbg9c+PVgjm/fr1Y/78+dStW5cVK1Zw//33G94e4T3JkQtRQ8657roRRXSMrEfLqLOO54uKivjoo49YsWKFI/cdQzGFbj52kZTwedH1lGBLsVzUtfi8yLZUn/Mx/TWrE2ypivqx0U458Stplvqx0S6pDKUUI0aMoEuXLiQnJ3Po0CEuXLhA3bp1DW+XqJoEciFqwJ7rtqdJzpdG83lpxcBr78Xac9/Q3u3xbAFcVdi2oziBTleV+C14l/fMPTdXuKnonCMvr2XLlsTFxXHq1Cnatm3L4sWL6dWrl9/bKVxJIBfCC9nZ2axdu9Zxk/H9wnbkl8a47GMPvM6BvDx3vfHKXNK1GDNmTPUb7IPq3FRs0KABW7Zs4cknn2Tnzp306dOH06dP84tf/MLfzRROJEcuHKRMqHvZ2dmsWrXKEcQPFTfkQmm0230v6hi32+3qqMtut3sKlXUjKh+9Egw6dOhAVlYWTZo0oaSkhPPnz5vdpLAjPXIBSJlQd9xNyjlU3LAsd+25l3qouKHbXvmh4oYU6QhAu7w+khJujDjDt6WNHDly+/aOkT8Y8a34XXR0NDExlf8RE/4jgVxImdAyzoE7Li6OwsJCSktLXfbZUZzgEmwrUmwturZCILf/AXB9raYWxaRE/0DLqLM0Kb7IjuIELuoY6qjLdI46TqerrLO6fXS07SplxIgRLFy40KtVq4QxJJALr8qEhvpiFNnZ2axcudIRuN1NuDlU3LDK1AnAZTcfK/d/ABRRqpSWUWeJjIzkpohclz8AtmGGA6r3jZjoxRdfZMiQIXzyySe0bduWrVu30qpVK7ObFRYkRy6AysuEZmZmOooT2b/si/KGSh597dq1FXrfzrxJqZTf35mnPwAXdQzx8fEMHDiQQYMGOSb6xMfHM2DAgICMVDHKgw8+yL59+2jfvj3nzp1DVgELHOmRW4y7G5JG9Iw9lQm99957HWmXY8eOkZCQgFLKkXZZt24dcXFxQZtHd7eyDuDY9mN0AjuKm3P6UmtHOsNdfjur6NoqUirOVIXRK3XUZS7qWhX2rBdRTF5eHhkZGfTs2TPgI1SM1qxZM5KSkti1a5fZTQkrEsgt5tixY47gbdQNSXerw9gfA9x7772ALe1y/PhxAEfufNu2bUGbR3e3ss6KFSsczx8qbsjn+VdTQgmguKhr8Z+iRLKKrnXkre37VXfYYPkeeOeo4xVy5M43M/2x6o/ZNm/ezMMPP+zInQv/kdSKRdh74idPnnSkOezBtqCgwKcUh6cyoSkpKcTGxhIREVEh7ZKVleUI4sFahc7dyjrOPOWtC4lmU1EL/p7fkdfzO/OfokS8TanYlR9m2DLqLF2jv6OOKgQ0dVQhXaO/qzAT1MhVf8zSvXt3ABYtWkRycjIHDx40uUWhT3rkFmGf+vz1118zc+ZMNm/eTHR0tGGBtLIyoe7SLnbBGsSzs7MrDBu0jwhR2AYAVkYTQXGNz665qGN4ryDJJVXTMupspZOFwPhVf8wwZMgQWrZsyZAhQ9i9ezfp6eksWLDA7GaFNEN65EqpPkqpA0qpb5VSE4w4ptUZPbnmoYceYvTo0Wit2bx5Mx9++CFgbCB1N6OvfNqlS5cuLvusW7cu6G542keg2NlvVNpy1AqNAseXMRQaHF+2Y9vrpZS/8amUCuiqP2bo0aMHkyZNAuDyZfeToIRxfA7kSqlIYB7QF2gNPKKUal35q0Kb8ygPwGWUR03FxMSQnp7OlClTADhz5gzg/3ULndMu9px4ly5dSElJISEhgW3btgXdclsZGRmUlpZyqLgh7+S35z9FidW4UVl9kZTQLfpIWTrFfb0UZ1pr+vbtWyF37K+qhiL0GZFa6QJ8q7U+DKCUWg4MBPZV+qoQ5a/JNfY/Bjk5OQA0atTIsW6h/Tz+SnHY0y4bN250pHLs7Ddbgym9kpeXx6HihvynqAX+vg2k0I5cty2XXlH5G5/x8fGOG5rlR9SEyo1OEVhGBPIEwHke8TEgpfxOSqmhwFCA6667zoDTBidvJtfU9LixsbG0a9fOsS2Q6xYqpSrk0e1tCKYgDrbFireevRb/38vXdIs+4sh7expi6Hzj07nXnZSUJIFbGCJgo1a01ou01sla6+TGjRsH6rSmqGxyjS9SU1O58847K5wnkGO4g325rezsbPZdrON2dqXxXNNJnaOOE4nrlPpakYpu9WyB3oqTfKxAir0Z0yM/DjgXVWheti1seZpcY0QwD/ZAarZ5q7PYVHgtRt7I9CzCZeKP/V/76JiEBrUZ1/sWBnW8LwBtCU9S7M3GiB75l8BNSqlEpVQM8DDwTwOOa0nlR3mkpaU5ctlG3BSMiLD9yo4ePcrixYvDsvdRmU3nG/r1xmZ55fPfLaPO8li9b1j92PV8PqEHgzpWby1O4T3n+1FGz62wGp975FrrYqXUH4H1QCSwVGu91+eWWZSnyTVgTC67ZcuWDBo0iJUrVzJkyBA++ugj1qxZE5I98/LVCMFWzMr5xmD5KfgX9Y0Gnd211KwnCQ1qc3+/++WmZSV++uknSkpKiIw09g+sv+5HWZEy469WcnKyDvWCOv6sFqi1Zvny5fz+97+nqKiIn376iauvvtqQYweL8tPry4uIiCAyMtLxvPOEH9/TKpr65HOOuHLHqlhH/JWHOkuv24NPP/3UUd7hjjvu4PXXX+fmm282/Dxaa2bMmOF4nJaWFrJBXCm1Q2udXH67TNH3E3/mspVSPPLII47ltELxErKy6fWHihuy/FIbFp1rxzv57XkrvwP/KUp0TPipOU0MRXSPPsIDcfvoHn3EZUr9LRGnXB7fU/+UBPFK3HPPPaxcuZJrrrmGLVu28Oijjxp+Dk/3o0LxM1EZmaIfAg4ePEiTJk3MboahPE1VL79AQyGVFWTyLj1iF0Mxj8Vdqdrnfkq9baRtdHQ0AwYEd63wYKghP3DgQFq2bElSUhK5ubmGHruqYm/hlF6RHrmF2Yv233333UyePJmSEuusJlMVT1PVq16hpzzvemaRlPDLaPfLqimlSExMtFStcH/MLq6p2NhYvxy3qmJv4RLEQXrklrZmzRomT57M//7v//LCCy9wxx130K9fP7ObZYiePXu6zZF7s0LPFYoYiigiqqy+Snm2IFdZHfKpU6dW43zBIZyW7qus2Fs4kUBuYXXr1uXVV1/l2LFjrFixgo0bN9K3b1/HEEUrS0pK4vvvv+cfWw+TVXRtteuB210miu7RR9yslwmgiKTEYxC3agGrcBvNIXMrJLUSEn75y18CMGfOHFJTUzl27JjJLTLG6l0/srmoRVkevGYVC+uoy45a4MpNmsVdUSuwfgErf80urolwu/FoBgnkIWDcuHF88MEHNGnShE2bNvHnP//Z7CYZYtP5hpRW6y3qGjDsvW2w3bj0FE7s6Rp7kLNCDrwqwTKa46uvvuLBBx8E/JcrF5JaCRkPPPAAP/74I6NGjeKLL77g1KlTlh9bXp18uKKUmyNOc0w34KKOqZD3jo+PJ6FWbY7n5ld4bUKD2kydYL1cuCfBMppj69at3HnnnZSUlJCYmMhf//pXv58zXEkgDyF33HEHtWvXZuvWrbRu3Zo33niD/v37m92sGmtcO4rTlzyNxLnSs6xFCd3q/Mi1pT/hWojTJiIigp49e9KiuCETV2STX3TlmHHRkYzrfYvBLTeXv2cXe2vv3r2UlJTQvXt3PvnkE+rUqROQ84YjCeQhpFOnTuzZs4chQ4aQkZHBlClTLBHIs7OzbcWuzjfkoo6hce0oJg9IYvKAJJ57/2uKS133j45QzHmwg9vJONnZ2axdu5b8fFvPOy4ujr59+9pKxpbtM2f9AU7k5tOsQVxZUavQm9QTTKM5brzxRgnifiaBPMQkJiYyd+5ckpKSOHLkCJmZmUFdBS47O5s/f7iJ/xQ0d4wqOX2phDH/+Jrf/vI6Xn6wA9NX7+XnS7ZhiA3iopn2qzYeg29VNb4HdUwIycDtjozmCB8SyENQy5Yt6dixIzt37uTuu+9m9OjRzJ071+xmuZWRkcG2wuvcTvJZtvV7kq9vyM60e01omRDWIaNWQlBcXBxbt25lxowZRERE8Oqrr/Lzzz+b3Sy38vLyPN7U1NjSIEKIykkgD1ExMTFMmTKFhg1tK7inp6ebtpp5dnY2c+fOZfr06cydO5fs7GzHc/Hx8S5LoZV3ws0oEyGEKwnkIW7o0KEA/OlPf+K2224j0OWD7eVo7UWw8vLyWL16tSOY9+zZky61TuKpJkqzBnGBaqow2NmzFWfLCv+QQB7iZs6cSUZGBjfccAO7d+8mJSWF8ePHU1BQUOVrjVgL0V052qKiIjIyMgDbzclnH+hGu9hcygfzUBwaGA4uXLjAyJEjGT9+PADXXHONyS0KfRLIw0CPHj3Izs5m7NixgG0q/+zZsyt9jVHV8zyVo3XenpSUxD+n/Za5D3UkoUEcCkhoEMes+5PCZoRJKJkyZQrz588nKiqKqVOnkpaWZnaTQp6MWgkTtWvX5uWXX6Zhw4ZMnjyZXbt2eVx+y8jqefHx8W6DubuCVOE0NDCUnTlzBoDXXnuNESNGVKzBmigAABgPSURBVLl/MNRNtzrpkYeZdu3aAbBixQq6devG/v37K+zjXNc5KyuLGTNmuEz3rs6HrGfPnkRHuy7+YPWCVMI7devWrXKfYKqbbmUSyMNM//79HctvffHFF3To0IGZM2dWyGMbVT0vKSmJAQMGWGpRBlEzWmveeust1qxZA0BUVOUX/M5XfvZgbr/yKygokKqJ1SCLL4ep3Nxcxo0bx+LFiwFbT33p0qV07twZcC28ZBeq9ayFMYYNG8aiRYsA2x/9f/zjH1XWdJf3WfXI4svCRYMGDfjb3/7GZ599RmJiomNEy/PPP8+lS5dccuJpaWmONEs4LmwrvLN27VoA5s2bx9q1a71amCOY6qZbmU+BXCk1Ryn1jVJqt1LqI6VUA6MaJgKjZ8+eZGdn8+yzz6K1Zvbs2XTo0IEDBw7IWojCK7m5uQwePJgffrBVnrz//vu9fo8ES910q/O1R/4p0FZr3Q44CEz0vUkBVv4NE4ZvoDp16vDKK6+wZcsWWrduzf/93/8xZswYVq1axfnz54ErPae77rrL5bXygQtv+fn5dOjQgaVLlxITE8Ps2bNp2rSpV68tXzddrvxqzqdArrX+l9a6uOzhVqC5700KoA2zYN3EK8Fba9vjDbPMbZdJUlJS+Oqrr0hLSyMqKoqFCxfSpk0bPvnkEwA2btwoIwyEixMnTvDdd98RHx/P119/zbhx47x+rae66XLlV31G5sifBNZ6elIpNVQptV0ptf306dMGnraGtIaCPMhacCWYr5toe1yQF5Y9c4BatWoxffp0duzYwW233caxY8fo168fv/vd7/jpp59khIFw2LZtG4MGDQKgWbNmtGrVqtrHSE1NdcmJ24N5MJdeDkZVjlpRSn0GuLtWmqy1XlW2z2QgGbhfe/GJDppRK87B2y5lBPSZBdIboKSkhLlz5zJlyhTy8/Np3LgxgwcPplatWo4PnowwCE9bt26la9eulJaWctNNN/HWW285FgEX/lPjUSta615a67ZuvuxB/A9Af+Axb4J4UFHKFrSdSRB3iIyMZOzYsezevZvU1FROnz7Niy++yPLlyzl37hwgIwzC1e7duyktLaV79+7s2rVLgrjJfB210gcYD/xKa33JmCYFkL1H7sw5Zy4A21JdGRkZLFy4kNq1a3PgwAHmzZvHjh07WLdunaRVwkhJSQnp6emMGTMGgPbt2xMXJxUqzeZrjvwvQD3gU6XU10qphQa0KTCc0yopI2Bqru1f55y5cFBKcf311zNs2DC6dOlCYWEhq1evZuTIkbzxxhumBHMjqjMK7+3Zs4euXbvy7LPPkp+fz6OPPsr06dPNbpbA91ErN2qtr9Vadyj7Gm5Uw/xOKYiNd82J95llexwbL+mVcuwjDO69916++OIL3nnnHRo1asSRI0cYMWIEc+fOpaTE04r3xkv/9CAz1uxzGUEzY80+0j89GLA2hIvLly8zffp0OnXqRFZWFgkJCaxevZply5bxi1/8wuzmCbB9AAL91blzZx00SksrfyxclDr9fE6dOqUfffRRja2QuE5JSdHZ2dkBacO0f+7R1z+/Rk/75x63j4Uxtm3bptu2bev4HQ8bNkzn5uaa3aywBWzXbmKq1FoRPluzZg3Dhw/n+PHjREdH8//+3/9jwoQJxMS4X4vTCLqsB/7650cd257o2oK0/q3l5qsBLl26RFpaGunp6ZSWltKyZUsWL14swwJNJrVWhN/079+fvXv3MmzYMIqKipg6dSo33XQTXbp0oXv37ixbtqzK/HX556vaXylFWv/WLtskiBtjw4YNtGvXjldeeQWA5557zjFySQQnCeTCEPHx8SxcuJANGzbQsmVLvv/+e7788ks2bdrEb3/7WwYMGOCoxVFeTWpS23vkzpxz5qL68vLyGD58OD169ODQoUMkJSWRlZXFnDlzqF27ttnNE5WQFYKEoVJTU9m7dy979uyhpKSEnTt38vzzz/Pxxx/Tpk0bZs+ezdChQ4mIsPUhdA1WI3JOq9jTKc5pFumZV1/59NiUKVN4/vnn/Zoe85eioiKOHTvm1bq0wSo2NpbmzZtXWJTFE8mRC787ceIEI0eOZOXKlQA0bdqU2NhYGjduzMyZM+nVq1e1a1Knf3qQcwVFjqBtD+71Y6N55p6bA/J9hYLTp08zevRo3n33XcD2c1+yZAlt2rQxuWU1d+TIEerVq8dVV11lyT/oWmtycnI4f/48iYmJLs95ypFLIBcBobXmgw8+4I9//COnTp1yee7xxx8nJSWFTz75hBtuuIGrrrqKtLS0Kj+E5Xvr7nrvwlVhYSErVqwgNzeXc+fOMWfOHHJycoiLi+OFF15g1KhRbtdxtZL9+/dz6623Wvq9oLXmm2++qVC/xlMgl+GHIqAKCgr04cOH9aFDh/SsWbN0rVq1HEPbAB0ZGal79OihV69eLcMIDbZlyxbdqlUrl583oHv06KEPHTpkdvMMs2/fPrObYAh33wcy/FAEo2+++YbJkyfz/fffEx0dzRdffAHY1nuMjo7mmmuuYebMmTz00EOW7mGZ6eLFi0yePJnXXnsNrTU33XSTY/Hrrl278thjj4XUz3b//v01qsQYbNx9H5565HKzU5jq1ltvZdSoURQUFNC7d2/+/e9/M3z4cL799luKi4s5fPgwjzzyCG+//TZdunQhIiKCvn37OtYWFRWVlpayfPlyvv32W0pLS3nzzTc5evQokZGRjB8/nrS0NGJjY81uZvDQ2nUmd/nH1ZSTk+P4Q3ny5EkiIyNp3LgxALt27aJ9+/YUFxfTqlUr3nzzTWNGBLnrpvv7S1IrojznNEppaanOy8vTeXl5+q9//auuX7++SypAKaWfeeYZ/fPPP+v8/HzH1+XLl038DsxVWFio8/Pz9Z49e3TXrl0rpE86dOigd+zYYXYzA6JaqZV/v6D1J89fmdFdWmp7/O8XDGnL1KlT9Zw5cxyP69Sp4/j/o48+ql955RWPr61OakV65CIoOF/aK6WoX78+AEOHDuW+++7j73//O/n5+Zw8eZKlS5eSnp5Oenq6yzGioqIYNmwYs2bNol69egFtv1nOnDnDs88+y7JlyygtLXVsb9q0KU888QRRUVFcf/31PP74414PZQsb2mlxGbDVWnIupOdjz7wq3bp1Y/fu3YYcSwK5CHrNmzdn4sQr5YaHDRvGyJEj+frrr132KywsZN68eaxevZoBAwa4/HFo2rQpf/zjH71a2T0YnTp1innz5nH27FnHttLSUt5//31Onz6NUopatWoRFRXFI488wuzZs6WgVVWc1yPIWnAloAdgcZni4mLWrl1Lnz59DDmeBHJhOZ07d2br1q0Vtu/atYvBgwezY8cO5s2bV+H5BQsW8Je//MXr/HpERATNmjXz643AU6dOUVhYWOk+mZmZPPPMM+Tk5Lh9/q677mLx4sXceOON/mhiQGizhpLag7nzKmF+DOL2xarB1iMfPHiwIceVQC5CRvv27dm6dSsffvihy1h1rTXvvPMOWVlZ/PrXv67WMW+77TaWLFlCUlKSoW394YcfGDFiBB9//LHXr+nVqxe/+tWvXLZdd911DBgwwDFT1ooyMzMdN7vtk7vWr19PbGys/+u7aA+Ly/gpmMfFxVW4kjSCBHIRUqKionjooYcqbB85ciSvvfYa8+fP93rqdl5eHl9++SXt2rWjUaNGjpEIvtJas3btWs6fP09cXBxXXXVVpfvXrVuX8ePH84c//CHohgn62pPWNSjRYBh7ELfnxJ1z5GCpZR8lkFeTaZeAwieRkZE888wzPPPMM16/5ty5c0yYMIH169dz+PBh/vGPfxjapoEDBzJ//nyaNWtm6HEDxYietFKK3r17A5CVleUI6AFZ1NvT4jJgucVlJJBXg6mXgCLg6tevz/z58zl//ny1UiDeSEhI4M4777RsJ8DInrQ9mDvX2gnYot53T3QdnWIP5gade9q0aS6PL1y4YMhxy5NA7iUzLgGl9x8c6tWrx8MPP+z2uXD9HRnZk7Z3iJytX78+cMG8/Dks+PuTQO6lQF8CSu8/+IX778iInrT9Z2bvEDl3kGpyvHBl3VvdJnAO5nb+eKM59/7tCy7Y39wFBQWyeEIQMPJ3VH5fq/x+PfWkq9N++6Lezh2i3r17k5KSQmxsrARxL0mPvBoCdQlo6g0g4RWjfkdW7dUb2ZNOTU11SUnZf7byPveeIT1ypdRYpZRWSjUy4njBqPwbNy0tjZSUFJcemZEC1fsXNefr78jKV15G96TL7y/v8+rxuUeulLoWuBf43vfmBC9Pb1zAp0tATzfLTL8BJKrk6+/I6lde0pMOHkakVtKB8cAqA44V1Ix+43q6rK5VqxaFhYVyAyiIGZVaMHXonQFCoSftj5FHkZGRLrOBV65cydGjR7n77rv55z//yYABAwDo378/zz33nM9pNJ9SK0qpgcBxrfUuL/YdqpTarpTafvr0aV9Oayqj3riVXVYXFhZSq1YtuQEUxIxKLRhxw1DUXPqnB5mxZp/j5621be3X9E8P+nRc+1R8+1eLFi0AWwG4mTNn+trsCqrskSulPgOaunlqMjAJW1qlSlrrRcAisK0QVI02hiRvLqvlsjW4+XqF5vzHu0uXLvTp08fxWGtNnz595PftR1przhUU8frnRwFI69+aGWv28frnR3miawu/zAlo3749RUVFfPrpp9xzzz2GHbfKQK617uVuu1IqCUgEdpV9s82Br5RSXbTWJw1rYQir6rI6FC5bQ50vvyN7rz4hIcHxut69e6O15vjx42zcuDGoR65YnVKKtP6tAXj986OOgP5E1xak9W/t0+fNucphYmIiH330keO5yZMnM2XKlMAGck+01tnA1fbHSqmjQLLW+owB7QoLckNT3HXXXRVmDCulOH78OM2bNw+bmaJmsQdzexAHfA7iUHmVw+7duwOwefNmn87hTMaRm0RmtAmw/sgVq7PnxJ3NWLPPkGBemcmTJ/M///M/REUZE4INm9mptW4hvXHvyYw2YSdzBsxhD+L2nPiRWffxRNcWvP75UZcboP5w77338vPPP8tSb6EgrMbhGrxSeSiRFJs5lFLUj412yYnbc+b1Y6P9/rOfPHkyAwcONORYyoxhTsnJyXr79u0BP68wyYZZtkVu7eVB7QX9Y+NtZUTDWGUpNkmv1Mz+/ftp1aqV1/sHawVLd9+HUmqH1jq5/L7SIxf+ZfJK5cHOXzOGhfdCYXSYBHLhnZqmRpR5K5VbRVil2IRfSBlbUbUNZb1oexrOnhrZMMu71zsHczsJ4i5CoVcozCOBXFTOOTViD+b21EhB3pXgXtUx3K1ULtPQhTCEpFZE5XxNjYTQSuVCBCvpkYuq+ZIaUR5WKk8ZYbmVykVFVl3dKNRIj1xUzVNqxNtg7ueVyoU5rLq6USB4KmM7cOBAEhMTKSws5OGHH2bq1KmGnE965KJy5VMjU3Nt/zrnzO37lX+ds/JBW4K4pVl5daMKdr8H6W1hWgPbv7vf8/mQnsrYduvWja+//prt27fz9ttv89VXX/l8LpAeuaiKp9QIXEmNyISfsBMyNWJ2vwer/xuK8m2P836wPQZo9xu/nbZOnTp07tyZb7/9lk6dOvl8POmRi6rdXS6NYg/m9pSJr6NahCWFRI2YjBlXgrhdUb5tuw/sZWw7dOjAr3/96wrP5+TksHXrVtq0aePTeeykRy684yk1IhN+wlZI1IjJO1a97V7yVMZ206ZNdOzYkYiICCZMmCCBXAQRezC3B3GQIF6JYK3tUR0hU4Y5vrktneJuux9069aNNWvWGH5cSa0I38mEH69lZma6rMlpD4iZmZnmNqyaQqYMc880iI5z3RYdZ9tuIdIjF76RCT9ecx7pAVSodGi1nnlI1Iix39DMmGFLp8Q3twVxP97o9AcJ5MI33oxqEUAIjfRwEhI1Ytr9xvDAfeHChQrbUlNT/Ta+XgK58J1M+PFaVQtuC1ETkiMXxpAJP17xNNLDUhNoRNCRHrkQARIyIz1E0JFALkSAyGpAwl8kkAsRQCEx0kMEHZ9z5EqpUUqpb5RSe5VSs41olBChLCRGeoig4lMgV0rdDQwE2mut2wAvG9IqIYSwqJycHEedlaZNm5KQkOB4rJRi7Nixjn1ffvllpk2b5vM5fU2tjABe1FoXAmitT/ncIiGECKCVO48zZ/0BTuTm06xBHON638Kgjgk1Pt5VV13lqLMybdo06taty3PPPQfY7oWsWLGCiRMn0qhRI0PaD76nVm4GuimlspRSG5VSt3naUSk1VCm1XSm1/fTp0z6eVgghfLdy53EmrsjmeG4+Gjiem8/EFdms3HncL+eLiopi6NChpKenG3rcKgO5UuozpdQeN18DsfXoGwK/BMYB7ykPCT+t9SKtdbLWOrlx48aGfhNCCFETc9YfIL+oxGVbflEJc9Yf8Ns5R44cybJly8jLyzPsmFWmVrTWvTw9p5QaAazQttkM25RSpUAjQLrcQoigdyI3v1rbjVC/fn0ef/xxXnvtNeLi4qp+gRd8Ta2sBO4GUErdDMQAZ3xtlBBCBEKzBu4DqaftRhkzZgxLlizh4sWLhhzP10C+FLhBKbUHWA78XstcYyGERYzrfQtx0ZEu2+KiIxnX+xa/nrdhw4b85je/YcmSJYYcz6dArrW+rLX+rda6rda6k9b634a0SgghAmBQxwRm3Z9EQoM4FJDQII5Z9yf5NGrFW2PHjuXMGWMSGDKzUwgR1gZ1TPBb4C4/Rty5vG2TJk24dOmSIeeR6odCCGFxEsiFEMLiJJALIUKO1cdcVLf9EsiFECElNjaWnJwcywZzrTU5OTnExsZ6/Rq52SmECCnNmzfn2LFjWLkUSGxsLM2bN/d6fwnkQoiQEh0dTWJiotnNCChJrQghhMVJIBdCCIuTQC6EEBanzLizq5Q6DXznx1M0wtrFu6T95rFy20HabzZ/t/96rXWFOuCmBHJ/U0pt11onm92OmpL2m8fKbQdpv9nMar+kVoQQwuIkkAshhMWFaiBfZHYDfCTtN4+V2w7SfrOZ0v6QzJELIUQ4CdUeuRBChA0J5EIIYXEhHciVUqOUUt8opfYqpWab3Z7qUkqNVUpppVQjs9tSHUqpOWU/991KqY+UUg3MbpM3lFJ9lFIHlFLfKqUmmN2e6lBKXauU2qCU2lf2fh9tdpuqSykVqZTaqZRaY3Zbqksp1UAp9UHZ+36/Uur2QJ4/ZAO5UupuYCDQXmvdBnjZ5CZVi1LqWuBe4Huz21IDnwJttdbtgIPARJPbUyWlVCQwD+gLtAYeUUq1NrdV1VIMjNVatwZ+CYy0WPsBRgP7zW5EDb0KrNNa3wq0J8DfR8gGcmAE8KLWuhBAa33K5PZUVzowHrDc3Wit9b+01sVlD7cC3tfjNE8X4Fut9WGt9WVgObaOgCVorX/UWn9V9v/z2AKJ/1cQNohSqjnQD1hsdluqSykVD3QHloBjUfrcQLYhlAP5zUA3pVSWUmqjUuo2sxvkLaXUQOC41nqX2W0xwJPAWrMb4YUE4Aenx8ewUCB0ppRqAXQEssxtSbXMxdZxKTW7ITWQCJwGXi9LDS1WStUJZAMsXY9cKfUZ0NTNU5OxfW8NsV1m3ga8p5S6QQfJeMsq2j4JW1olaFXWfq31qrJ9JmO75F8WyLaFM6VUXeBDYIzW+pzZ7fGGUqo/cEprvUMplWp2e2ogCugEjNJaZymlXgUmAFMC2QDL0lr38vScUmoEsKIscG9TSpViK2gTFMuGeGq7UioJ21/4XUopsKUlvlJKddFanwxgEytV2c8eQCn1B6A/0DNY/nhW4ThwrdPj5mXbLEMpFY0tiC/TWq8wuz3V0BX4lVLqPiAWqK+Ueltr/VuT2+WtY8AxrbX9CugDbIE8YEI5tbISuBtAKXUzEIMFqqpprbO11ldrrVtorVtge5N0CqYgXhWlVB9sl8m/0lpfMrs9XvoSuEkplaiUigEeBv5pcpu8pmx/9ZcA+7XWfza7PdWhtZ6otW5e9n5/GPi3hYI4ZZ/NH5RSt5Rt6gnsC2QbLN0jr8JSYKlSag9wGfi9RXqGoeAvQC3g07Kriq1a6+HmNqlyWutipdQfgfVAJLBUa73X5GZVR1fgd0C2Uurrsm2TtNafmNimcDIKWFbWCTgMPBHIk8sUfSGEsLhQTq0IIURYkEAuhBAWJ4FcCCEsTgK5EEJYnARyIYSwOAnkQghhcRLIhRDC4v4/4jqgsvqaHtkAAAAASUVORK5CYII=\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.scatter(X_train[y_train==1, 0], X_train[y_train==1, 1], c='gray', marker='o', label=None)\n",
"plt.scatter(X_train[y_train==-1, 0], X_train[y_train==-1, 1], c='gray', marker='x', label=None)\n",
"\n",
"xx, yy = np.meshgrid(np.linspace(-7, 7, 150),\n",
" np.linspace(-7, 7, 150))\n",
"\n",
"Z = cov_emp.mahalanobis(np.c_[xx.ravel(), yy.ravel()]) > chi2_interval_max\n",
"Z = Z.reshape(xx.shape)\n",
"plt.contour(xx, yy, Z, levels=[0], linewidths=2, colors='black')\n",
"\n",
"outlier_pred = cov_emp.mahalanobis(X_test) > chi2_interval_max\n",
"outlier_true = y_test == -1\n",
"\n",
"plt.scatter(X_test[outlier_pred&outlier_true, 0], X_test[outlier_pred&outlier_true, 1], c=colors[1], marker='x', label='TP')\n",
"plt.scatter(X_test[~outlier_pred&outlier_true, 0], X_test[~outlier_pred&outlier_true, 1], c=colors[0], marker='x', label='FN')\n",
"plt.scatter(X_test[outlier_pred&~outlier_true, 0], X_test[outlier_pred&~outlier_true, 1], c=colors[1], marker='o', label='FP')\n",
"plt.scatter(X_test[~outlier_pred&~outlier_true, 0], X_test[~outlier_pred&~outlier_true, 1], c=colors[0], marker='o', label='TN')\n",
"\n",
"plt.legend()"
]
},
{
"cell_type": "code",
"execution_count": 14,
"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>precision</th>\n",
" <th>recall</th>\n",
" <th>f1-score</th>\n",
" <th>support</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <td>False</td>\n",
" <td>0.970588</td>\n",
" <td>1.000000</td>\n",
" <td>0.985075</td>\n",
" <td>66.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <td>True</td>\n",
" <td>1.000000</td>\n",
" <td>0.777778</td>\n",
" <td>0.875000</td>\n",
" <td>9.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <td>accuracy</td>\n",
" <td>0.973333</td>\n",
" <td>0.973333</td>\n",
" <td>0.973333</td>\n",
" <td>0.973333</td>\n",
" </tr>\n",
" <tr>\n",
" <td>macro avg</td>\n",
" <td>0.985294</td>\n",
" <td>0.888889</td>\n",
" <td>0.930037</td>\n",
" <td>75.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <td>weighted avg</td>\n",
" <td>0.974118</td>\n",
" <td>0.973333</td>\n",
" <td>0.971866</td>\n",
" <td>75.000000</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" precision recall f1-score support\n",
"False 0.970588 1.000000 0.985075 66.000000\n",
"True 1.000000 0.777778 0.875000 9.000000\n",
"accuracy 0.973333 0.973333 0.973333 0.973333\n",
"macro avg 0.985294 0.888889 0.930037 75.000000\n",
"weighted avg 0.974118 0.973333 0.971866 75.000000"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.DataFrame(classification_report(outlier_true, outlier_pred, output_dict=True)).T"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Robustな共分散行列を用いた方法(MCD)\n",
"\n",
"上で見たように最尤法により求めた標本共分散行列は異常値に対してrobustでないため,代わりにMinimum Covariance Determinant (MCD)というものを使う。\n",
"\n",
"簡単に説明すると,学習データの中から一定数だけ取り出して共分散行列を計算し,その行列式が最小になるようなものを選び出す。\n",
"\n",
"単純に計算しようとするとサンプリングの組み合わせが膨大な数に上るため,アルゴリズムの工夫により高速化がなされている。\n",
"\n",
"・参考・\n",
"\n",
"[Robust vs Empirical covariance estimate](https://scikit-learn.org/stable/auto_examples/covariance/plot_robust_vs_empirical_covariance.html#sphx-glr-auto-examples-covariance-plot-robust-vs-empirical-covariance-py)\n",
"\n",
"[Robust covariance estimation and Mahalanobis distances relevance](https://scikit-learn.org/stable/auto_examples/covariance/plot_mahalanobis_distances.html#sphx-glr-auto-examples-covariance-plot-mahalanobis-distances-py)\n",
"\n",
"[Minimum Covariance Determinant and Extensions](https://arxiv.org/abs/1709.07045)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 最尤法との比較\n",
"- 図の点線が学習データ全体から計算した標本共分散行列による異常判定境界。異常値に引きずられて共分散行列を過大評価している。"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[ 2.23302122, -0.04287104],\n",
" [-0.04287104, 2.10112408]])"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cov_emp = EmpiricalCovariance().fit(X)\n",
"cov_emp.covariance_"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[0.28670225, 0.20108522],\n",
" [0.20108522, 0.18822739]])"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cov_mcd = MinCovDet().fit(X)\n",
"cov_mcd.covariance_"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/tatamiya/.pyenv/versions/3.7.1/envs/sklearn/lib/python3.7/site-packages/ipykernel_launcher.py:6: UserWarning: No contour levels were found within the data range.\n",
" \n",
"/Users/tatamiya/.pyenv/versions/3.7.1/envs/sklearn/lib/python3.7/site-packages/ipykernel_launcher.py:10: UserWarning: No contour levels were found within the data range.\n",
" # Remove the CWD from sys.path while we load stuff.\n"
]
},
{
"data": {
"text/plain": [
"<matplotlib.legend.Legend at 0x1275833c8>"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"xx, yy = np.meshgrid(np.linspace(-7, 7, 150),\n",
" np.linspace(-7, 7, 150))\n",
"\n",
"Z_emp = cov_emp.mahalanobis(np.c_[xx.ravel(), yy.ravel()]) > chi2_interval_max\n",
"Z_emp = Z_emp.reshape(xx.shape)\n",
"plt.contour(xx, yy, Z_emp, levels=[0], linewidths=1, colors='black', linestyles='dashed')\n",
"\n",
"Z_mcd = cov_mcd.mahalanobis(np.c_[xx.ravel(), yy.ravel()]) > chi2_interval_max\n",
"Z_mcd = Z_mcd.reshape(xx.shape)\n",
"plt.contour(xx, yy, Z_mcd, levels=[0], linewidths=2, colors='black')\n",
"\n",
"outlier_true = y == -1\n",
"plt.scatter(X[outlier_true, 0], X[outlier_true, 1], c=colors[0], marker='x', label='True')\n",
"plt.scatter(X[~outlier_true, 0], X[~outlier_true, 1], c=colors[0], marker='o', label='False')\n",
"\n",
"plt.legend()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## MinCovDetに基づく異常値検知"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[0.2622943 , 0.17854094],\n",
" [0.17854094, 0.17161828]])"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cov_mcd = MinCovDet().fit(X_train)\n",
"cov_mcd.covariance_"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/tatamiya/.pyenv/versions/3.7.1/envs/sklearn/lib/python3.7/site-packages/ipykernel_launcher.py:9: UserWarning: No contour levels were found within the data range.\n",
" if __name__ == '__main__':\n"
]
},
{
"data": {
"text/plain": [
"<matplotlib.legend.Legend at 0x12775fa90>"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.scatter(X_train[y_train==1, 0], X_train[y_train==1, 1], c='gray', marker='o', label=None)\n",
"plt.scatter(X_train[y_train==-1, 0], X_train[y_train==-1, 1], c='gray', marker='x', label=None)\n",
"\n",
"xx, yy = np.meshgrid(np.linspace(-7, 7, 150),\n",
" np.linspace(-7, 7, 150))\n",
"\n",
"Z = cov_mcd.mahalanobis(np.c_[xx.ravel(), yy.ravel()]) > chi2_interval_max\n",
"Z = Z.reshape(xx.shape)\n",
"plt.contour(xx, yy, Z, levels=[0], linewidths=2, colors='black')\n",
"\n",
"outlier_pred = cov_mcd.mahalanobis(X_test) > chi2_interval_max\n",
"outlier_true = y_test == -1\n",
"\n",
"plt.scatter(X_test[outlier_pred&outlier_true, 0], X_test[outlier_pred&outlier_true, 1], c=colors[1], marker='x', label='TP')\n",
"plt.scatter(X_test[~outlier_pred&outlier_true, 0], X_test[~outlier_pred&outlier_true, 1], c=colors[0], marker='x', label='FN')\n",
"plt.scatter(X_test[outlier_pred&~outlier_true, 0], X_test[outlier_pred&~outlier_true, 1], c=colors[1], marker='o', label='FP')\n",
"plt.scatter(X_test[~outlier_pred&~outlier_true, 0], X_test[~outlier_pred&~outlier_true, 1], c=colors[0], marker='o', label='TN')\n",
"\n",
"plt.legend()"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"scrolled": true
},
"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>precision</th>\n",
" <th>recall</th>\n",
" <th>f1-score</th>\n",
" <th>support</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <td>False</td>\n",
" <td>1.000000</td>\n",
" <td>0.939394</td>\n",
" <td>0.968750</td>\n",
" <td>66.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <td>True</td>\n",
" <td>0.692308</td>\n",
" <td>1.000000</td>\n",
" <td>0.818182</td>\n",
" <td>9.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <td>accuracy</td>\n",
" <td>0.946667</td>\n",
" <td>0.946667</td>\n",
" <td>0.946667</td>\n",
" <td>0.946667</td>\n",
" </tr>\n",
" <tr>\n",
" <td>macro avg</td>\n",
" <td>0.846154</td>\n",
" <td>0.969697</td>\n",
" <td>0.893466</td>\n",
" <td>75.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <td>weighted avg</td>\n",
" <td>0.963077</td>\n",
" <td>0.946667</td>\n",
" <td>0.950682</td>\n",
" <td>75.000000</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" precision recall f1-score support\n",
"False 1.000000 0.939394 0.968750 66.000000\n",
"True 0.692308 1.000000 0.818182 9.000000\n",
"accuracy 0.946667 0.946667 0.946667 0.946667\n",
"macro avg 0.846154 0.969697 0.893466 75.000000\n",
"weighted avg 0.963077 0.946667 0.950682 75.000000"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.DataFrame(classification_report(outlier_true, outlier_pred, output_dict=True)).T"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# ホテリング理論の限界\n",
"- データの分布が正規分布であることを仮定しているため,下記のような場合はうまくいかない。\n",
" - 分布が非対称\n",
" - 分布が複数の山からなる\n",
" \n",
" \n",
"・参考・\n",
"\n",
"https://scikit-learn.org/stable/auto_examples/plot_anomaly_comparison.html"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2つの山からなるデータに対して適用した場合\n",
"- 両方の山にまたがって分布を仮定してしまう。"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"blobs_params = dict(random_state=0, n_samples=n_inliers, n_features=2)\n",
"blobs = make_blobs(centers=[[2, 2], [-2, -2]], cluster_std=[0.5, 0.1],\n",
" **blobs_params)[0]\n",
"\n",
"X_blobs = np.concatenate([blobs, rng.uniform(low=-6, high=6,\n",
" size=(n_outliers, 2))], axis=0)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/Users/tatamiya/.pyenv/versions/3.7.1/envs/sklearn/lib/python3.7/site-packages/ipykernel_launcher.py:8: UserWarning: No contour levels were found within the data range.\n",
" \n"
]
},
{
"data": {
"text/plain": [
"<matplotlib.legend.Legend at 0x1277a32e8>"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"cov = MinCovDet(random_state=0).fit(X_blobs)\n",
"\n",
"X_blobsX_blobs, yy = np.meshgrid(np.linspace(-7, 7, 150),\n",
" np.linspace(-7, 7, 150))\n",
"\n",
"Z = cov.mahalanobis(np.c_[X_blobsX_blobs.ravel(), yy.ravel()]) > chi2_interval_max\n",
"Z = Z.reshape(X_blobsX_blobs.shape)\n",
"plt.contour(X_blobsX_blobs, yy, Z, levels=[0], linewidths=2, colors='black')\n",
"\n",
"outlier_pred = cov.mahalanobis(X_blobs) > chi2_interval_max\n",
"outlier_true = y == -1\n",
"\n",
"plt.scatter(X_blobs[outlier_pred&outlier_true, 0], X_blobs[outlier_pred&outlier_true, 1], c=colors[1], marker='x', label='TP')\n",
"plt.scatter(X_blobs[~outlier_pred&outlier_true, 0], X_blobs[~outlier_pred&outlier_true, 1], c=colors[0], marker='x', label='FN')\n",
"plt.scatter(X_blobs[outlier_pred&~outlier_true, 0], X_blobs[outlier_pred&~outlier_true, 1], c=colors[1], marker='o', label='FP')\n",
"plt.scatter(X_blobs[~outlier_pred&~outlier_true, 0], X_blobs[~outlier_pred&~outlier_true, 1], c=colors[0], marker='o', label='TN')\n",
"\n",
"plt.legend()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 【補足】EllipticEnvelopeクラス\n",
"- sklearn.metrics内に,マハラノビス距離を用いた異常検知を行うためのEllipticEnvelopeクラスが存在する。\n",
"- しかし,学習データ内のpercentileで閾値を決めているため,異常値の含有率次第で調整が必要。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 検知\n",
"- 下記のサンプルでは、かなり保守的な判断を下し,異常値の見落としが多い。"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[0.28670225, 0.20108522],\n",
" [0.20108522, 0.18822739]])"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cov = EllipticEnvelope(random_state=0).fit(X)\n",
"cov.covariance_"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.legend.Legend at 0x1277a3710>"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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87l8+TLBwcHMnj2bN9980+X+zz2d0zo7pZTxQDyYx5E767q6sCRZqzHZWtSyeXikbYvecp0SnnfNmjX07duXv/76i3LlyjFu3Diio6NLVdt01Mp4WlmTlEKaCyVxXy9BRT8fLl3LdulWt8XGjRuJjIzk+PHjNse7d+/OggULuP322/UJ7FYcNbfCQLRI5ClALavbYXnHPFdRtWwtknnB55fgfGfPnqV///785z//AaBt27YkJibSsGFD+2JxQePX7td9fRQLZ68jbo+LFy8ydOhQ3n//fQCaN29Ohw4dAGjfvj1dunRxuQ9twHFzKwxGi0S+HbhDCFEXcwJ/CfiXBuc1Jo1r2faFIvnoo48YPHgwFy5coEKFCkydOpV+/fq57S4seszQLLg2ub+vt6Gm169evZp+/fpx5swZypcvz/jx442xHZ+j+qMMyO7/KSlljhCiP7AB8Abek1Lutzsyo9Kolm2vP//8k169evHVV18B8NhjjxEfH094eLhTrq+FgqsRSglpGbYlioJT8J3N0uo2QqdlQWfOnKF///6sWrUKgPvvv5+EhAQaNHDNkTM3cfDcCiNRa604ik51O5PJxKJFi3j77be5cuUKlStX5p133uH11193za/GRShuKzVfL4Gvt+Batr6FlLkvNjNE0rYmpeSDDz5gyJAhXLx4kYoVKzJ9+nT69OljzD1VpYQJwTduj7vktklcrbXibGWoZdvr8OHDRERE8PPPPwPwzDPPEBcXx2233ebwa2utsOn11rJNUvex4pUDfA2XxI8fP06vXr34+uuvAejYsSOLFy+mTp06OkdWRo7sjzIQA378KgXl5OQwY8YM7r77bn7++WdCQkJYuXIlq1atMmQSB9cfC+7v6824rk30DuPWrL5tm0wm5sfGcuedd/L1119TpUoVli1bxvr1642fxC018XGXzH9br0fkIVSL3OB2795NREQEu3btAuCNN95g9uzZVKlSRefI7FMz2N8l1koB85T6NvUqczw1wzh1cKvRHAcPHSIiIoJffvkFgBdeeIHY2FhCQkJ0DtJOLtIf5QpUIjeozMxMJk2axIwZM8jNzaVOnTrEx8fz+OOP6x2aJqI7NrhljdwZBHBsugE3RMgbzZH9ywJiPtvCxE+3cv36dW6rKFg4uDvdJ37qPknOzrkV7kKVVgxo8+bNNG/enKlTp2IymRgw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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"xx, yy = np.meshgrid(np.linspace(-7, 7, 150),\n",
" np.linspace(-7, 7, 150))\n",
"\n",
"Z = cov.predict(np.c_[xx.ravel(), yy.ravel()])\n",
"Z = Z.reshape(xx.shape)\n",
"plt.contour(xx, yy, Z, levels=[0], linewidths=2, colors='black')\n",
"\n",
"outlier_pred = cov.predict(X) == -1\n",
"outlier_true = y == -1\n",
"\n",
"plt.scatter(X[outlier_pred&outlier_true, 0], X[outlier_pred&outlier_true, 1], c=colors[1], marker='x', label='TP')\n",
"plt.scatter(X[~outlier_pred&outlier_true, 0], X[~outlier_pred&outlier_true, 1], c=colors[0], marker='x', label='FN')\n",
"plt.scatter(X[outlier_pred&~outlier_true, 0], X[outlier_pred&~outlier_true, 1], c=colors[1], marker='o', label='FP')\n",
"plt.scatter(X[~outlier_pred&~outlier_true, 0], X[~outlier_pred&~outlier_true, 1], c=colors[0], marker='o', label='TN')\n",
"\n",
"plt.legend()"
]
},
{
"cell_type": "code",
"execution_count": 25,
"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>precision</th>\n",
" <th>recall</th>\n",
" <th>f1-score</th>\n",
" <th>support</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <td>False</td>\n",
" <td>0.944444</td>\n",
" <td>1.000000</td>\n",
" <td>0.971429</td>\n",
" <td>255.00</td>\n",
" </tr>\n",
" <tr>\n",
" <td>True</td>\n",
" <td>1.000000</td>\n",
" <td>0.666667</td>\n",
" <td>0.800000</td>\n",
" <td>45.00</td>\n",
" </tr>\n",
" <tr>\n",
" <td>accuracy</td>\n",
" <td>0.950000</td>\n",
" <td>0.950000</td>\n",
" <td>0.950000</td>\n",
" <td>0.95</td>\n",
" </tr>\n",
" <tr>\n",
" <td>macro avg</td>\n",
" <td>0.972222</td>\n",
" <td>0.833333</td>\n",
" <td>0.885714</td>\n",
" <td>300.00</td>\n",
" </tr>\n",
" <tr>\n",
" <td>weighted avg</td>\n",
" <td>0.952778</td>\n",
" <td>0.950000</td>\n",
" <td>0.945714</td>\n",
" <td>300.00</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" precision recall f1-score support\n",
"False 0.944444 1.000000 0.971429 255.00\n",
"True 1.000000 0.666667 0.800000 45.00\n",
"accuracy 0.950000 0.950000 0.950000 0.95\n",
"macro avg 0.972222 0.833333 0.885714 300.00\n",
"weighted avg 0.952778 0.950000 0.945714 300.00"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pd.DataFrame(classification_report(outlier_true, outlier_pred, output_dict=True)).T"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## predictの判定方法\n",
"\n",
"単純に学習データのmahananobis距離からpercentileで閾値を決めている。\n",
"\n",
"1. fitによりcovarianceを算出する\n",
"1. 学習データのmahalanobis距離(の2乗に負の符号をとったもの)のpercentileから閾値offset_を算出する。\n",
" - ちなみに学習データのmahalanobis距離(の2乗)はdist_に保存されている。\n",
" - この時のpercentileはfit関数の引数contaminationで調整できる(defaultでは0.1)\n",
"1. 新しい入力データからmahalanobis距離(の2乗に負の符号をとったもの)を計算し,offsetとの差をとる\n",
"\n",
"・参照・\n",
"\n",
"https://github.com/scikit-learn/scikit-learn/blob/1495f69242646d239d89a5713982946b8ffcf9d9/sklearn/covariance/elliptic_envelope.py#L131"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/plain": [
"-117.6554695385609"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cov.offset_"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"-117.6554695385609"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"np.percentile(-cov.dist_, 100*cov.contamination)"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.1"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cov.contamination"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.1"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment