{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 出力層の設計" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* ニューラルネットワークは、分類問題と回帰問題に使える\n", "* 回帰問題では恒等関数\n", "* 分類問題ではソフトマックス関数" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 恒等関数\n", "\n", "> ある入力データから、(連続的な)数値の予測を行う問題\n", "\n", "恒等関数は、入力された数値をそのまま出力する関数のこと" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ソフトマックス関数\n", "\n", "出力層の内、入力$a_i$と$k$番目の出力$y_k$を求める計算式は\n", "\n", "$$\n", " y_k = \\frac{\\exp(-x)}{\\sum_{i=1}^n\\exp(a_i)}\n", "$$" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 1.34985881 18.17414537 54.59815003]\n" ] } ], "source": [ "import numpy as np\n", "a = np.array([0.3, 2.9, 4.0])\n", "\n", "exp_a = np.exp(a) # 指数関数 exp\n", "print(exp_a)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "74.1221542101633\n" ] } ], "source": [ "sum_exp_a = np.sum(exp_a) # expの和\n", "print(sum_exp_a)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0.01821127 0.24519181 0.73659691]\n" ] } ], "source": [ "y = exp_a / sum_exp_a\n", "print(y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "素直にPythonで書くとこうなるが、指数関数の計算は値が大きくなってしまいます。 \n", "つまり、オーバーフローを起こす危険がある…" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ ":2: RuntimeWarning: overflow encountered in exp\n", " np.exp(a) / np.sum(np.exp(a))\n", ":2: RuntimeWarning: invalid value encountered in true_divide\n", " np.exp(a) / np.sum(np.exp(a))\n" ] }, { "data": { "text/plain": [ "array([nan, nan, nan])" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.array([1010, 1000, 990])\n", "np.exp(a) / np.sum(np.exp(a))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$y_k = \\frac{\\exp(-x)}{\\sum_{i=1}^n\\exp(a_i)}$ を式変形して使うと:\n", "\n", "$$\n", " y_k = \\frac{\\exp(a_k + C')}{\\sum_{i=1}^n\\exp(a_i + C')}\n", "$$" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 0, -10, -20])" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c = np.max(a)\n", "a - c" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([9.99954600e-01, 4.53978686e-05, 2.06106005e-09])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.exp(a - c) / np.sum(np.exp(a - c))" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "def softmax(a):\n", " c = np.max(a)\n", " exp_a = np.exp(a - c) # オーバーフロー対策\n", " sum_exp_a = np.sum(exp_a)\n", " return exp_a / sum_exp_a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ソフトマックス関数の特徴は、出力した総和が$1$になることです" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0.01821127 0.24519181 0.73659691]\n" ] } ], "source": [ "a = np.array([0.3, 2.9, 4.0])\n", "y = softmax(a)\n", "print(y)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.0" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.sum(y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この性質があるので、ソフトマックス関数の結果は「確率」と解釈することができます。\n", "\n", "またソフトマックス関数の入力と出力を比較したとき、大小関係は入力時と出力時で変化がありません。 \n", "そのためニューラルネットワークでは、出力層のソフトマックス関数は省略し、コンピューターに計算をさせないのが一般的です。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 出力層のニューロンの数\n", "\n", "出力層のニューロンの数は、とくべき問題によって変わります。 \n", "例えば、10クラス分類問題と呼ばれるもの。\n", "\n", "ある入力画像に対して、その画像が数字の0から9のどれなのかを予想します。この場合、出力層は0~9の10個必要です。" ] } ], "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.8.3" } }, "nbformat": 4, "nbformat_minor": 4 }