{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "name": "day34_01_simpleRNN.ipynb", "provenance": [], "collapsed_sections": [], "authorship_tag": "ABX9TyOcbQPro0QML4vSSylreSP3", "include_colab_link": true }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "language_info": { "name": "python" } }, "cells": [ { "cell_type": "markdown", "metadata": { "id": "view-in-github", "colab_type": "text" }, "source": [ "<a href=\"https://colab.research.google.com/github/rkti498/e_shikaku/blob/main/day34_01_simpleRNN.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>" ] }, { "cell_type": "markdown", "metadata": { "id": "92THlk0B11ZF" }, "source": [ "# RNN バイナリ加算のサンプル" ] }, { "cell_type": "code", "metadata": { "id": "j0boG2fNAaBl" }, "source": [ "import numpy as np\n", "\n", "# 中間層の活性化関数\n", "# シグモイド関数(ロジスティック関数)\n", "def sigmoid(x):\n", " return 1/(1 + np.exp(-x))\n", "\n", "# ReLU関数\n", "def relu(x):\n", " return np.maximum(0, x)\n", "\n", "# ステップ関数(閾値0)\n", "def step_function(x):\n", " return np.where( x > 0, 1, 0) \n", "\n", "# 出力層の活性化関数\n", "# ソフトマックス関数\n", "def softmax(x):\n", " if x.ndim == 2:\n", " x = x.T\n", " x = x - np.max(x, axis=0)\n", " y = np.exp(x) / np.sum(np.exp(x), axis=0)\n", " return y.T\n", "\n", " x = x - np.max(x) # オーバーフロー対策\n", " return np.exp(x) / np.sum(np.exp(x))\n", "\n", "# ソフトマックスとクロスエントロピーの複合関数\n", "def softmax_with_loss(d, x):\n", " y = softmax(x)\n", " return cross_entropy_error(d, y)\n", "\n", "# 誤差関数\n", "# 平均二乗誤差\n", "def mean_squared_error(d, y):\n", " return np.mean(np.square(d - y)) / 2\n", "\n", "# クロスエントロピー\n", "def cross_entropy_error(d, y):\n", " if y.ndim == 1:\n", " d = d.reshape(1, d.size)\n", " y = y.reshape(1, y.size)\n", " \n", " # 教師データがone-hot-vectorの場合、正解ラベルのインデックスに変換\n", " if d.size == y.size:\n", " d = d.argmax(axis=1)\n", " \n", " batch_size = y.shape[0]\n", " return -np.sum(np.log(y[np.arange(batch_size), d] + 1e-7)) / batch_size\n", "\n", "\n", "\n", "# 活性化関数の導関数\n", "# シグモイド関数(ロジスティック関数)の導関数\n", "def d_sigmoid(x):\n", " dx = (1.0 - sigmoid(x)) * sigmoid(x)\n", " return dx\n", "\n", "# ReLU関数の導関数\n", "def d_relu(x):\n", " return np.where( x > 0, 1, 0)\n", " \n", "# ステップ関数の導関数\n", "def d_step_function(x):\n", " return 0\n", "\n", "# 平均二乗誤差の導関数\n", "def d_mean_squared_error(d, y):\n", " if type(d) == np.ndarray:\n", " batch_size = d.shape[0]\n", " dx = (y - d)/batch_size\n", " else:\n", " dx = y - d\n", " return dx\n", "\n", "\n", "# ソフトマックスとクロスエントロピーの複合導関数\n", "def d_softmax_with_loss(d, y):\n", " batch_size = d.shape[0]\n", " if d.size == y.size: # 教師データがone-hot-vectorの場合\n", " dx = (y - d) / batch_size\n", " else:\n", " dx = y.copy()\n", " dx[np.arange(batch_size), d] -= 1\n", " dx = dx / batch_size\n", " return dx\n", "\n", "# シグモイドとクロスエントロピーの複合導関数\n", "def d_sigmoid_with_loss(d, y):\n", " return y - d\n", "\n", "# 数値微分\n", "def numerical_gradient(f, x):\n", " h = 1e-4\n", " grad = np.zeros_like(x)\n", "\n", " for idx in range(x.size):\n", " tmp_val = x[idx]\n", " # f(x + h)の計算\n", " x[idx] = tmp_val + h\n", " fxh1 = f(x)\n", "\n", " # f(x - h)の計算\n", " x[idx] = tmp_val - h\n", " fxh2 = f(x)\n", "\n", " grad[idx] = (fxh1 - fxh2) / (2 * h)\n", " # 値を元に戻す\n", " x[idx] = tmp_val\n", "\n", " return grad\n", "\n", "\n", "def im2col(input_data, filter_h, filter_w, stride=1, pad=0):\n", " N, C, H, W = input_data.shape\n", " out_h = (H + 2*pad - filter_h)//stride + 1\n", " out_w = (W + 2*pad - filter_w)//stride + 1\n", "\n", " img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant')\n", " col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))\n", "\n", " for y in range(filter_h):\n", " y_max = y + stride*out_h\n", " for x in range(filter_w):\n", " x_max = x + stride*out_w\n", " col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]\n", "\n", " col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1)\n", " return col\n", "\n", "\n", "def col2im(col, input_shape, filter_h, filter_w, stride=1, pad=0):\n", " N, C, H, W = input_shape\n", " out_h = (H + 2*pad - filter_h)//stride + 1\n", " out_w = (W + 2*pad - filter_w)//stride + 1\n", " col = col.reshape(N, out_h, out_w, C, filter_h, filter_w).transpose(0, 3, 4, 5, 1, 2)\n", "\n", " img = np.zeros((N, C, H + 2*pad + stride - 1, W + 2*pad + stride - 1))\n", " for y in range(filter_h):\n", " y_max = y + stride*out_h\n", " for x in range(filter_w):\n", " x_max = x + stride*out_w\n", " img[:, :, y:y_max:stride, x:x_max:stride] += col[:, :, y, x, :, :]\n", "\n", " return img[:, :, pad:H + pad, pad:W + pad]" ], "execution_count": null, "outputs": [] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 1000 }, "id": "Ma8DLL-i1l_0", "outputId": "7e85f0b8-cf2f-4d50-b263-8ebac7e7bbd4" }, "source": [ "import numpy as np\n", "# from common import functions\n", "import matplotlib.pyplot as plt\n", "\n", "\n", "def d_tanh(x):\n", " return 1/(np.cosh(x) ** 2)\n", "\n", "# データを用意\n", "# 2進数の桁数\n", "binary_dim = 8\n", "# 最大値 + 1\n", "largest_number = pow(2, binary_dim)\n", "# largest_numberまで2進数を用意\n", "binary = np.unpackbits(np.array([range(largest_number)],dtype=np.uint8).T,axis=1)\n", "\n", "input_layer_size = 2\n", "hidden_layer_size = 16\n", "output_layer_size = 1\n", "\n", "weight_init_std = 1\n", "learning_rate = 0.1\n", "\n", "iters_num = 10000\n", "plot_interval = 100\n", "\n", "# ウェイト初期化 (バイアスは簡単のため省略)\n", "# W_in = weight_init_std * np.random.randn(input_layer_size, hidden_layer_size)\n", "# W_out = weight_init_std * np.random.randn(hidden_layer_size, output_layer_size)\n", "# W = weight_init_std * np.random.randn(hidden_layer_size, hidden_layer_size)\n", "# Xavier\n", "W_in = np.random.randn(input_layer_size, hidden_layer_size) / (np.sqrt(input_layer_size))\n", "W_out = np.random.randn(hidden_layer_size, output_layer_size) / (np.sqrt(hidden_layer_size))\n", "W = np.random.randn(hidden_layer_size, hidden_layer_size) / (np.sqrt(hidden_layer_size))\n", "# He\n", "# W_in = np.random.randn(input_layer_size, hidden_layer_size) / (np.sqrt(input_layer_size)) * np.sqrt(2)\n", "# W_out = np.random.randn(hidden_layer_size, output_layer_size) / (np.sqrt(hidden_layer_size)) * np.sqrt(2)\n", "# W = np.random.randn(hidden_layer_size, hidden_layer_size) / (np.sqrt(hidden_layer_size)) * np.sqrt(2)\n", "\n", "\n", "# 勾配\n", "W_in_grad = np.zeros_like(W_in)\n", "W_out_grad = np.zeros_like(W_out)\n", "W_grad = np.zeros_like(W)\n", "\n", "u = np.zeros((hidden_layer_size, binary_dim + 1))\n", "z = np.zeros((hidden_layer_size, binary_dim + 1))\n", "y = np.zeros((output_layer_size, binary_dim))\n", "\n", "delta_out = np.zeros((output_layer_size, binary_dim))\n", "delta = np.zeros((hidden_layer_size, binary_dim + 1))\n", "\n", "all_losses = []\n", "\n", "for i in range(iters_num):\n", " \n", " # A, B初期化 (a + b = d)\n", " a_int = np.random.randint(largest_number/2)\n", " a_bin = binary[a_int] # binary encoding\n", " b_int = np.random.randint(largest_number/2)\n", " b_bin = binary[b_int] # binary encoding\n", " \n", " # 正解データ\n", " d_int = a_int + b_int\n", " d_bin = binary[d_int]\n", " \n", " # 出力バイナリ\n", " out_bin = np.zeros_like(d_bin)\n", " \n", " # 時系列全体の誤差\n", " all_loss = 0 \n", " \n", " # 時系列ループ\n", " for t in range(binary_dim):\n", " # 入力値\n", " X = np.array([a_bin[ - t - 1], b_bin[ - t - 1]]).reshape(1, -1)\n", " # 時刻tにおける正解データ\n", " dd = np.array([d_bin[binary_dim - t - 1]])\n", " \n", " u[:,t+1] = np.dot(X, W_in) + np.dot(z[:,t].reshape(1, -1), W)\n", "\n", " z[:,t+1] = sigmoid(u[:,t+1])\n", " y[:,t] = sigmoid(np.dot(z[:,t+1].reshape(1, -1), W_out))\n", "\n", " # z[:,t+1] = relu(u[:,t+1])\n", " # y[:,t] = relu(np.dot(z[:,t+1].reshape(1, -1), W_out))\n", "\n", " z[:,t+1] = np.tanh(u[:,t+1]) \n", " y[:,t] = np.tanh(np.dot(z[:,t+1].reshape(1, -1), W_out))\n", "\n", "\n", " #誤差\n", " loss = mean_squared_error(dd, y[:,t])\n", " \n", " delta_out[:,t] = d_mean_squared_error(dd, y[:,t]) * d_sigmoid(y[:,t]) \n", " \n", " all_loss += loss\n", "\n", " out_bin[binary_dim - t - 1] = np.round(y[:,t])\n", " \n", " \n", " for t in range(binary_dim)[::-1]:\n", " X = np.array([a_bin[-t-1],b_bin[-t-1]]).reshape(1, -1) \n", "\n", " delta[:,t] = (np.dot(delta[:,t+1].T, W.T) + np.dot(delta_out[:,t].T, W_out.T)) * d_sigmoid(u[:,t+1])\n", "\n", " # delta[:,t] = (np.dot(delta[:,t+1].T, W.T) + np.dot(delta_out[:,t].T, W_out.T)) * d_relu(u[:,t+1])\n", "\n", " # delta[:,t] = (np.dot(delta[:,t+1].T, W.T) + np.dot(delta_out[:,t].T, W_out.T)) * d_tanh(u[:,t+1]) \n", "\n", " # 勾配更新\n", " W_out_grad += np.dot(z[:,t+1].reshape(-1,1), delta_out[:,t].reshape(-1,1))\n", " W_grad += np.dot(z[:,t].reshape(-1,1), delta[:,t].reshape(1,-1))\n", " W_in_grad += np.dot(X.T, delta[:,t].reshape(1,-1))\n", " \n", " # 勾配適用\n", " W_in -= learning_rate * W_in_grad\n", " W_out -= learning_rate * W_out_grad\n", " W -= learning_rate * W_grad\n", " \n", " W_in_grad *= 0\n", " W_out_grad *= 0\n", " W_grad *= 0\n", " \n", "\n", " if(i % plot_interval == 0):\n", " all_losses.append(all_loss) \n", " print(\"iters:\" + str(i))\n", " print(\"Loss:\" + str(all_loss))\n", " print(\"Pred:\" + str(out_bin))\n", " print(\"True:\" + str(d_bin))\n", " out_int = 0\n", " for index,x in enumerate(reversed(out_bin)):\n", " out_int += x * pow(2, index)\n", " print(str(a_int) + \" + \" + str(b_int) + \" = \" + str(out_int))\n", " print(\"------------\")\n", "\n", "lists = range(0, iters_num, plot_interval)\n", "plt.plot(lists, all_losses, label=\"loss\")\n", "plt.show()" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "iters:0\n", "Loss:2.153564894745493\n", "Pred:[0 0 1 0 0 0 0 0]\n", "True:[1 1 0 1 0 1 0 0]\n", "121 + 91 = 32\n", "------------\n", "iters:100\n", "Loss:0.5659978109753718\n", "Pred:[0 0 1 1 1 1 1 0]\n", "True:[0 0 1 1 0 0 1 1]\n", "24 + 27 = 62\n", "------------\n", "iters:200\n", "Loss:1.5234273549747595\n", "Pred:[0 0 0 0 1 0 0 0]\n", "True:[0 1 0 1 1 0 1 1]\n", "5 + 86 = 8\n", "------------\n", "iters:300\n", "Loss:1.0732684500064333\n", "Pred:[0 0 0 1 1 1 0 0]\n", "True:[0 1 1 1 1 1 0 1]\n", "111 + 14 = 28\n", "------------\n", "iters:400\n", "Loss:1.3702915075700555\n", "Pred:[0 0 0 0 1 1 1 0]\n", "True:[0 1 1 1 1 0 0 1]\n", "10 + 111 = 14\n", "------------\n", "iters:500\n", "Loss:0.9647743604989347\n", "Pred:[0 1 0 0 1 1 0 0]\n", "True:[1 0 0 1 0 1 1 0]\n", "70 + 80 = 76\n", "------------\n", "iters:600\n", "Loss:1.1480619329217434\n", "Pred:[1 1 1 1 1 1 1 0]\n", "True:[1 1 1 0 0 0 0 1]\n", "114 + 111 = 254\n", "------------\n", "iters:700\n", "Loss:1.0431930834757628\n", "Pred:[1 1 1 1 1 0 1 0]\n", "True:[1 0 1 1 1 1 0 0]\n", "73 + 115 = 250\n", "------------\n", "iters:800\n", "Loss:0.8700848545561863\n", "Pred:[0 0 1 1 1 0 0 0]\n", "True:[0 1 0 0 0 0 0 0]\n", "24 + 40 = 56\n", "------------\n", "iters:900\n", "Loss:0.9435390961625657\n", "Pred:[1 1 0 1 0 0 0 0]\n", "True:[1 0 0 1 0 1 1 0]\n", "69 + 81 = 208\n", "------------\n", "iters:1000\n", "Loss:1.2748087371021117\n", "Pred:[0 0 1 1 1 1 0 1]\n", "True:[0 1 0 0 1 1 1 0]\n", "25 + 53 = 61\n", "------------\n", "iters:1100\n", "Loss:1.0681730984674394\n", "Pred:[0 0 1 1 1 0 0 1]\n", "True:[0 1 0 0 0 1 0 1]\n", "25 + 44 = 57\n", "------------\n", "iters:1200\n", "Loss:0.5352576913311647\n", "Pred:[0 1 1 1 0 0 0 0]\n", "True:[0 1 1 1 1 0 0 0]\n", "24 + 96 = 112\n", "------------\n", "iters:1300\n", "Loss:0.6447085338301011\n", "Pred:[0 0 0 0 0 0 0 0]\n", "True:[0 0 0 0 1 1 0 1]\n", "3 + 10 = 0\n", "------------\n", "iters:1400\n", "Loss:0.8743242683856232\n", "Pred:[0 0 1 0 0 0 0 0]\n", "True:[0 0 1 1 1 1 0 1]\n", "17 + 44 = 32\n", "------------\n", "iters:1500\n", "Loss:0.9926579862906834\n", "Pred:[0 0 1 0 0 1 0 0]\n", "True:[0 0 1 1 1 1 1 0]\n", "26 + 36 = 36\n", "------------\n", "iters:1600\n", "Loss:1.1973668032523332\n", "Pred:[1 1 1 1 1 1 0 1]\n", "True:[1 1 0 0 0 0 1 1]\n", "86 + 109 = 253\n", "------------\n", "iters:1700\n", "Loss:0.5712612361030289\n", "Pred:[0 0 1 1 0 1 1 0]\n", "True:[0 0 1 0 0 1 1 1]\n", "19 + 20 = 54\n", "------------\n", "iters:1800\n", "Loss:1.1251359893632809\n", "Pred:[1 0 1 1 1 1 0 0]\n", "True:[1 0 1 0 0 0 0 0]\n", "93 + 67 = 188\n", "------------\n", "iters:1900\n", "Loss:0.6588827075097232\n", "Pred:[1 1 1 1 1 0 1 0]\n", "True:[1 0 1 1 1 1 1 0]\n", "68 + 122 = 250\n", "------------\n", "iters:2000\n", "Loss:0.8459203533313725\n", "Pred:[0 1 0 1 1 1 0 0]\n", "True:[1 0 0 1 1 1 0 0]\n", "125 + 31 = 92\n", "------------\n", "iters:2100\n", "Loss:0.6806428475661361\n", "Pred:[1 1 0 1 1 1 0 0]\n", "True:[1 1 0 1 1 0 0 0]\n", "123 + 93 = 220\n", "------------\n", "iters:2200\n", "Loss:0.28051406170320214\n", "Pred:[0 1 0 0 1 0 0 0]\n", "True:[0 1 0 0 1 1 0 0]\n", "41 + 35 = 72\n", "------------\n", "iters:2300\n", "Loss:0.2678601472715533\n", "Pred:[0 0 1 1 1 0 1 1]\n", "True:[0 0 1 1 1 0 0 1]\n", "26 + 31 = 59\n", "------------\n", "iters:2400\n", "Loss:0.5053430276519022\n", "Pred:[0 1 0 0 1 1 1 1]\n", "True:[0 1 0 1 1 1 1 1]\n", "25 + 70 = 79\n", "------------\n", "iters:2500\n", "Loss:0.4214456423294395\n", "Pred:[1 1 1 0 1 0 0 0]\n", "True:[0 1 1 0 1 0 0 0]\n", "69 + 35 = 232\n", "------------\n", "iters:2600\n", "Loss:0.43138557041268244\n", "Pred:[0 0 1 1 0 0 1 1]\n", "True:[0 0 1 1 0 1 1 1]\n", "22 + 33 = 51\n", "------------\n", "iters:2700\n", "Loss:0.08342940450333307\n", "Pred:[1 1 1 0 1 0 1 0]\n", "True:[1 1 1 0 1 0 1 0]\n", "127 + 107 = 234\n", "------------\n", "iters:2800\n", "Loss:0.9843271892876817\n", "Pred:[1 1 0 1 1 1 0 0]\n", "True:[1 0 0 0 1 0 0 0]\n", "17 + 119 = 220\n", "------------\n", "iters:2900\n", "Loss:0.27041290556212505\n", "Pred:[0 1 1 1 0 1 1 1]\n", "True:[0 1 1 1 0 0 1 1]\n", "85 + 30 = 119\n", "------------\n", "iters:3000\n", "Loss:0.17747346976447112\n", "Pred:[0 0 1 1 1 1 0 1]\n", "True:[0 0 1 1 1 1 0 1]\n", "36 + 25 = 61\n", "------------\n", "iters:3100\n", "Loss:0.15474438566810336\n", "Pred:[0 1 0 0 1 1 0 1]\n", "True:[0 1 0 0 1 1 0 1]\n", "31 + 46 = 77\n", "------------\n", "iters:3200\n", "Loss:0.2925576273470318\n", "Pred:[1 0 1 1 1 1 1 0]\n", "True:[1 0 0 1 1 1 1 0]\n", "38 + 120 = 190\n", "------------\n", "iters:3300\n", "Loss:0.058212540150715524\n", "Pred:[0 1 1 0 0 0 0 1]\n", "True:[0 1 1 0 0 0 0 1]\n", "65 + 32 = 97\n", "------------\n", "iters:3400\n", "Loss:0.23097330361993285\n", "Pred:[0 1 1 1 0 0 0 1]\n", "True:[0 1 1 1 0 0 0 1]\n", "70 + 43 = 113\n", "------------\n", "iters:3500\n", "Loss:0.12528287152008144\n", "Pred:[0 1 0 1 1 0 1 0]\n", "True:[0 1 0 1 1 0 1 0]\n", "33 + 57 = 90\n", "------------\n", "iters:3600\n", "Loss:0.11931292858767471\n", "Pred:[1 0 0 1 0 1 1 1]\n", "True:[1 0 0 1 0 1 1 1]\n", "35 + 116 = 151\n", "------------\n", "iters:3700\n", "Loss:0.03487172172445985\n", "Pred:[0 1 1 0 0 0 0 0]\n", "True:[0 1 1 0 0 0 0 0]\n", "24 + 72 = 96\n", "------------\n", "iters:3800\n", "Loss:0.42386621971691407\n", "Pred:[1 1 0 0 0 1 1 0]\n", "True:[1 0 0 0 0 1 1 0]\n", "56 + 78 = 198\n", "------------\n", "iters:3900\n", "Loss:0.04679461229142709\n", "Pred:[0 1 0 0 1 1 1 0]\n", "True:[0 1 0 0 1 1 1 0]\n", "51 + 27 = 78\n", "------------\n", "iters:4000\n", "Loss:0.08500932952686045\n", "Pred:[0 1 0 1 1 1 0 0]\n", "True:[0 1 0 1 1 1 0 0]\n", "16 + 76 = 92\n", "------------\n", "iters:4100\n", "Loss:0.028449876185565142\n", "Pred:[1 1 1 1 0 0 1 1]\n", "True:[1 1 1 1 0 0 1 1]\n", "125 + 118 = 243\n", "------------\n", "iters:4200\n", "Loss:0.010387937689509383\n", "Pred:[1 0 0 0 0 1 1 1]\n", "True:[1 0 0 0 0 1 1 1]\n", "87 + 48 = 135\n", "------------\n", "iters:4300\n", "Loss:0.16121578777568452\n", "Pred:[1 0 0 0 0 1 0 1]\n", "True:[1 0 0 0 0 1 0 1]\n", "55 + 78 = 133\n", "------------\n", "iters:4400\n", "Loss:0.008219474578897448\n", "Pred:[0 1 1 1 0 1 1 1]\n", "True:[0 1 1 1 0 1 1 1]\n", "7 + 112 = 119\n", "------------\n", "iters:4500\n", "Loss:0.3146766921785453\n", "Pred:[1 1 1 1 1 1 0 0]\n", "True:[1 0 1 1 1 1 0 0]\n", "81 + 107 = 252\n", "------------\n", "iters:4600\n", "Loss:0.023366812397411115\n", "Pred:[1 1 1 0 0 0 1 0]\n", "True:[1 1 1 0 0 0 1 0]\n", "107 + 119 = 226\n", "------------\n", "iters:4700\n", "Loss:0.021387873678467333\n", "Pred:[1 1 0 1 0 1 0 0]\n", "True:[1 1 0 1 0 1 0 0]\n", "98 + 114 = 212\n", "------------\n", "iters:4800\n", "Loss:0.030882954549819937\n", "Pred:[0 1 1 0 1 1 0 1]\n", "True:[0 1 1 0 1 1 0 1]\n", "11 + 98 = 109\n", "------------\n", "iters:4900\n", "Loss:0.12399539928882054\n", "Pred:[0 1 0 0 1 0 1 1]\n", "True:[0 1 0 0 1 0 1 1]\n", "61 + 14 = 75\n", "------------\n", "iters:5000\n", "Loss:0.040624100294295765\n", "Pred:[0 1 1 1 0 1 1 0]\n", "True:[0 1 1 1 0 1 1 0]\n", "99 + 19 = 118\n", "------------\n", "iters:5100\n", "Loss:0.029890623469243406\n", "Pred:[1 0 0 1 1 0 1 1]\n", "True:[1 0 0 1 1 0 1 1]\n", "94 + 61 = 155\n", "------------\n", "iters:5200\n", "Loss:0.006747409869158992\n", "Pred:[1 1 0 1 0 1 0 0]\n", "True:[1 1 0 1 0 1 0 0]\n", "104 + 108 = 212\n", "------------\n", "iters:5300\n", "Loss:0.11362048400667227\n", "Pred:[0 0 1 1 1 1 0 0]\n", "True:[0 0 1 1 1 1 0 0]\n", "43 + 17 = 60\n", "------------\n", "iters:5400\n", "Loss:0.036499078282814464\n", "Pred:[1 0 0 1 0 0 0 1]\n", "True:[1 0 0 1 0 0 0 1]\n", "104 + 41 = 145\n", "------------\n", "iters:5500\n", "Loss:0.0020271442734815285\n", "Pred:[1 0 1 1 1 0 0 0]\n", "True:[1 0 1 1 1 0 0 0]\n", "92 + 92 = 184\n", "------------\n", "iters:5600\n", "Loss:0.019150168217955153\n", "Pred:[0 0 0 1 0 0 1 1]\n", "True:[0 0 0 1 0 0 1 1]\n", "14 + 5 = 19\n", "------------\n", "iters:5700\n", "Loss:0.015615537960966534\n", "Pred:[0 1 1 0 1 1 1 0]\n", "True:[0 1 1 0 1 1 1 0]\n", "11 + 99 = 110\n", "------------\n", "iters:5800\n", "Loss:0.055848845352638045\n", "Pred:[0 1 0 0 0 0 0 0]\n", "True:[0 1 0 0 0 0 0 0]\n", "3 + 61 = 64\n", "------------\n", "iters:5900\n", "Loss:0.027811941122713048\n", "Pred:[1 0 1 1 0 1 0 1]\n", "True:[1 0 1 1 0 1 0 1]\n", "85 + 96 = 181\n", "------------\n", "iters:6000\n", "Loss:0.010294577678977852\n", "Pred:[1 0 1 0 0 0 1 0]\n", "True:[1 0 1 0 0 0 1 0]\n", "106 + 56 = 162\n", "------------\n", "iters:6100\n", "Loss:0.0294434376838914\n", "Pred:[0 1 0 1 0 0 0 0]\n", "True:[0 1 0 1 0 0 0 0]\n", "63 + 17 = 80\n", "------------\n", "iters:6200\n", "Loss:0.09631313639715536\n", "Pred:[0 1 0 0 0 1 0 1]\n", "True:[0 1 0 0 0 1 0 1]\n", "24 + 45 = 69\n", "------------\n", "iters:6300\n", "Loss:0.01924271266456333\n", "Pred:[1 1 0 0 1 0 0 1]\n", "True:[1 1 0 0 1 0 0 1]\n", "110 + 91 = 201\n", "------------\n", "iters:6400\n", "Loss:0.08407179514535484\n", "Pred:[0 1 1 1 1 1 1 0]\n", "True:[0 1 1 1 1 1 1 0]\n", "20 + 106 = 126\n", "------------\n", "iters:6500\n", "Loss:0.004977384528896935\n", "Pred:[1 0 0 0 1 0 0 0]\n", "True:[1 0 0 0 1 0 0 0]\n", "36 + 100 = 136\n", "------------\n", "iters:6600\n", "Loss:0.023494576741571575\n", "Pred:[1 0 0 0 1 1 1 0]\n", "True:[1 0 0 0 1 1 1 0]\n", "95 + 47 = 142\n", "------------\n", "iters:6700\n", "Loss:0.003000975419069599\n", "Pred:[1 0 1 1 0 0 1 1]\n", "True:[1 0 1 1 0 0 1 1]\n", "96 + 83 = 179\n", "------------\n", "iters:6800\n", "Loss:0.0021108360627262197\n", "Pred:[1 0 0 1 1 0 0 1]\n", "True:[1 0 0 1 1 0 0 1]\n", "87 + 66 = 153\n", "------------\n", "iters:6900\n", "Loss:0.043114944696639484\n", "Pred:[0 1 0 1 1 0 1 0]\n", "True:[0 1 0 1 1 0 1 0]\n", "63 + 27 = 90\n", "------------\n", "iters:7000\n", "Loss:0.006124100758764581\n", "Pred:[0 1 1 1 1 0 0 0]\n", "True:[0 1 1 1 1 0 0 0]\n", "114 + 6 = 120\n", "------------\n", "iters:7100\n", "Loss:0.06282776676401762\n", "Pred:[0 1 1 0 0 0 0 1]\n", "True:[0 1 1 0 0 0 0 1]\n", "69 + 28 = 97\n", "------------\n", "iters:7200\n", "Loss:0.012013012155202389\n", "Pred:[0 1 0 0 0 0 0 1]\n", "True:[0 1 0 0 0 0 0 1]\n", "32 + 33 = 65\n", "------------\n", "iters:7300\n", "Loss:0.028836632944875068\n", "Pred:[1 1 0 1 1 0 0 1]\n", "True:[1 1 0 1 1 0 0 1]\n", "122 + 95 = 217\n", "------------\n", "iters:7400\n", "Loss:0.03777987985745057\n", "Pred:[0 1 1 0 0 0 1 1]\n", "True:[0 1 1 0 0 0 1 1]\n", "60 + 39 = 99\n", "------------\n", "iters:7500\n", "Loss:0.0016045064751352685\n", "Pred:[0 1 0 1 1 0 1 0]\n", "True:[0 1 0 1 1 0 1 0]\n", "10 + 80 = 90\n", "------------\n", "iters:7600\n", "Loss:0.011171217721587709\n", "Pred:[1 0 1 0 0 0 0 1]\n", "True:[1 0 1 0 0 0 0 1]\n", "125 + 36 = 161\n", "------------\n", "iters:7700\n", "Loss:0.08617873995102997\n", "Pred:[0 1 0 0 1 1 1 0]\n", "True:[0 1 0 0 1 1 1 0]\n", "40 + 38 = 78\n", "------------\n", "iters:7800\n", "Loss:0.010397438122656017\n", "Pred:[0 1 1 0 1 0 1 0]\n", "True:[0 1 1 0 1 0 1 0]\n", "88 + 18 = 106\n", "------------\n", "iters:7900\n", "Loss:0.02433398525828952\n", "Pred:[1 0 0 0 0 1 0 1]\n", "True:[1 0 0 0 0 1 0 1]\n", "77 + 56 = 133\n", "------------\n", "iters:8000\n", "Loss:0.001718991142316749\n", "Pred:[1 1 0 1 0 1 0 1]\n", "True:[1 1 0 1 0 1 0 1]\n", "117 + 96 = 213\n", "------------\n", "iters:8100\n", "Loss:0.0007114582440403065\n", "Pred:[0 1 1 1 0 1 1 1]\n", "True:[0 1 1 1 0 1 1 1]\n", "88 + 31 = 119\n", "------------\n", "iters:8200\n", "Loss:0.025349840562032013\n", "Pred:[1 1 0 0 1 1 1 1]\n", "True:[1 1 0 0 1 1 1 1]\n", "90 + 117 = 207\n", "------------\n", "iters:8300\n", "Loss:0.021087777651367698\n", "Pred:[0 0 0 0 1 1 1 0]\n", "True:[0 0 0 0 1 1 1 0]\n", "5 + 9 = 14\n", "------------\n", "iters:8400\n", "Loss:0.012730265116910503\n", "Pred:[1 0 1 0 0 0 0 1]\n", "True:[1 0 1 0 0 0 0 1]\n", "111 + 50 = 161\n", "------------\n", "iters:8500\n", "Loss:0.010435261233883586\n", "Pred:[1 0 1 0 1 0 0 1]\n", "True:[1 0 1 0 1 0 0 1]\n", "125 + 44 = 169\n", "------------\n", "iters:8600\n", "Loss:0.06613496188358742\n", "Pred:[0 1 1 1 0 1 0 1]\n", "True:[0 1 1 1 0 1 0 1]\n", "109 + 8 = 117\n", "------------\n", "iters:8700\n", "Loss:0.011993586944276585\n", "Pred:[0 0 1 1 1 0 0 1]\n", "True:[0 0 1 1 1 0 0 1]\n", "10 + 47 = 57\n", "------------\n", "iters:8800\n", "Loss:0.019079905925579396\n", "Pred:[0 0 1 0 0 1 1 1]\n", "True:[0 0 1 0 0 1 1 1]\n", "18 + 21 = 39\n", "------------\n", "iters:8900\n", "Loss:0.013600918569904754\n", "Pred:[1 0 1 0 0 1 1 1]\n", "True:[1 0 1 0 0 1 1 1]\n", "75 + 92 = 167\n", "------------\n", "iters:9000\n", "Loss:0.009621368877386419\n", "Pred:[1 0 0 0 1 0 0 1]\n", "True:[1 0 0 0 1 0 0 1]\n", "73 + 64 = 137\n", "------------\n", "iters:9100\n", "Loss:0.01811070525066136\n", "Pred:[0 1 1 0 1 0 1 0]\n", "True:[0 1 1 0 1 0 1 0]\n", "63 + 43 = 106\n", "------------\n", "iters:9200\n", "Loss:0.004258061377861931\n", "Pred:[1 0 1 1 1 1 1 0]\n", "True:[1 0 1 1 1 1 1 0]\n", "64 + 126 = 190\n", "------------\n", "iters:9300\n", "Loss:0.04397747646965129\n", "Pred:[0 1 1 0 1 0 0 0]\n", "True:[0 1 1 0 1 0 0 0]\n", "69 + 35 = 104\n", "------------\n", "iters:9400\n", "Loss:0.03249117145077845\n", "Pred:[0 1 1 0 0 0 0 1]\n", "True:[0 1 1 0 0 0 0 1]\n", "80 + 17 = 97\n", "------------\n", "iters:9500\n", "Loss:0.02220329506937916\n", "Pred:[1 0 1 1 0 0 0 0]\n", "True:[1 0 1 1 0 0 0 0]\n", "70 + 106 = 176\n", "------------\n", "iters:9600\n", "Loss:0.020627497677411313\n", "Pred:[1 0 1 0 0 0 0 1]\n", "True:[1 0 1 0 0 0 0 1]\n", "37 + 124 = 161\n", "------------\n", "iters:9700\n", "Loss:0.010723291665635452\n", "Pred:[0 1 0 1 0 0 0 0]\n", "True:[0 1 0 1 0 0 0 0]\n", "25 + 55 = 80\n", "------------\n", "iters:9800\n", "Loss:0.026674913935543214\n", "Pred:[1 0 0 0 1 1 1 0]\n", "True:[1 0 0 0 1 1 1 0]\n", "102 + 40 = 142\n", "------------\n", "iters:9900\n", "Loss:0.03234901207213073\n", "Pred:[0 1 1 0 1 0 0 0]\n", "True:[0 1 1 0 1 0 0 0]\n", "97 + 7 = 104\n", "------------\n" ], "name": "stdout" }, { "output_type": "display_data", "data": { "image/png": "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\n", "text/plain": [ "<Figure size 432x288 with 1 Axes>" ] }, "metadata": { "tags": [], "needs_background": "light" } } ] }, { "cell_type": "markdown", "metadata": { "id": "PlRjNu4cAz9G" }, "source": [ "sigmoid(ランダム初期化)の結果\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "id": "-TkkCuBOJ929" }, "source": [ "sigmoid(Xavier初期化) \n", "" ] }, { "cell_type": "markdown", "metadata": { "id": "692rSn7sBHp_" }, "source": [ "ReLU(ランダム初期化)の結果 \n", "\n" ] }, { "cell_type": "markdown", "metadata": { "id": "hBAK-mtmI0Fg" }, "source": [ "ReLU(He初期化)の結果 \n", "" ] }, { "cell_type": "markdown", "metadata": { "id": "I9DJd7AzBTMA" }, "source": [ "tanh(ランダム初期化)の結果 \n", "" ] }, { "cell_type": "markdown", "metadata": { "id": "zsFA4_zRJm2C" }, "source": [ "tanh(Xavier初期化)の結果 \n", "" ] }, { "cell_type": "markdown", "metadata": { "id": "FqjobgfAKPXK" }, "source": [ "### 考察\n", "実施する度に結果が少々ばらつくが、どれもうまい具合に収束する。\n", "tanhのランダム初期化だけはあまりうまくいかない。\n", "他のReLUとtanhは初期化にあまり影響を受けていないように見える。\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "id": "-u0A5ThGjKVH" }, "source": [ "# サイン波予測\n", "maxlen:2 iters_num:100 \n", "maxlen:2 iters_num:500 \n", "maxlen:2 iters_num:3000 \n", "maxlen:5 iters_num:100 \n", "maxlen:5 iters_num:500 \n", "maxlen:5 iters_num:3000 \n", "\n", "\n" ] }, { "cell_type": "code", "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 1000 }, "id": "IjjFN0eciCUL", "outputId": "c1b2a888-a131-4985-cec8-d37aaa09d3cd" }, "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from sklearn.model_selection import train_test_split\n", "\n", "np.random.seed(0)\n", "\n", "# sin曲線\n", "round_num = 10\n", "div_num = 500\n", "ts = np.linspace(0, round_num * np.pi, div_num)\n", "f = np.sin(ts)\n", "\n", "def d_tanh(x):\n", " return 1/(np.cosh(x)**2 + 1e-4)\n", "\n", "# ひとつの時系列データの長さ\n", "maxlen = 5\n", "\n", "# sin波予測の入力データ\n", "test_head = [[f[k]] for k in range(0, maxlen)]\n", "\n", "data = []\n", "target = []\n", "\n", "for i in range(div_num - maxlen):\n", " data.append(f[i: i + maxlen])\n", " target.append(f[i + maxlen])\n", " \n", "X = np.array(data).reshape(len(data), maxlen, 1)\n", "D = np.array(target).reshape(len(data), 1)\n", "\n", "# データ設定\n", "N_train = int(len(data) * 0.8)\n", "N_validation = len(data) - N_train\n", "\n", "x_train, x_test, d_train, d_test = train_test_split(X, D, test_size=N_validation)\n", "\n", "input_layer_size = 1\n", "hidden_layer_size = 5\n", "output_layer_size = 1\n", "\n", "weight_init_std = 0.01\n", "learning_rate = 0.1\n", "\n", "iters_num = 3000\n", "\n", "# ウェイト初期化 (バイアスは簡単のため省略)\n", "W_in = weight_init_std * np.random.randn(input_layer_size, hidden_layer_size)\n", "W_out = weight_init_std * np.random.randn(hidden_layer_size, output_layer_size)\n", "W = weight_init_std * np.random.randn(hidden_layer_size, hidden_layer_size)\n", "\n", "# 勾配\n", "W_in_grad = np.zeros_like(W_in)\n", "W_out_grad = np.zeros_like(W_out)\n", "W_grad = np.zeros_like(W)\n", "\n", "us = []\n", "zs = []\n", "\n", "u = np.zeros(hidden_layer_size)\n", "z = np.zeros(hidden_layer_size)\n", "y = np.zeros(output_layer_size)\n", "\n", "delta_out = np.zeros(output_layer_size)\n", "delta = np.zeros(hidden_layer_size)\n", "\n", "losses = []\n", "\n", "# トレーニング\n", "for i in range(iters_num):\n", " for s in range(x_train.shape[0]):\n", " us.clear()\n", " zs.clear()\n", " z *= 0\n", " \n", " # sにおける正解データ\n", " d = d_train[s]\n", "\n", " xs = x_train[s] \n", " \n", " # 時系列ループ\n", " for t in range(maxlen):\n", " \n", " # 入力値\n", " x = xs[t]\n", " u = np.dot(x, W_in) + np.dot(z, W)\n", " us.append(u)\n", " z = np.tanh(u)\n", " zs.append(z)\n", "\n", " y = np.dot(z, W_out)\n", " \n", " #誤差\n", " loss = mean_squared_error(d, y)\n", " \n", " delta_out = d_mean_squared_error(d, y)\n", " \n", " delta *= 0\n", " for t in range(maxlen)[::-1]:\n", " \n", " delta = (np.dot(delta, W.T) + np.dot(delta_out, W_out.T)) * d_tanh(us[t])\n", " \n", " # 勾配更新\n", " W_grad += np.dot(zs[t].reshape(-1,1), delta.reshape(1,-1))\n", " W_in_grad += np.dot(xs[t], delta.reshape(1,-1))\n", " W_out_grad = np.dot(z.reshape(-1,1), delta_out)\n", " \n", " # 勾配適用\n", " W -= learning_rate * W_grad\n", " W_in -= learning_rate * W_in_grad\n", " W_out -= learning_rate * W_out_grad.reshape(-1,1)\n", " \n", " W_in_grad *= 0\n", " W_out_grad *= 0\n", " W_grad *= 0\n", "\n", "# テスト \n", "for s in range(x_test.shape[0]):\n", " z *= 0\n", "\n", " # sにおける正解データ\n", " d = d_test[s]\n", "\n", " xs = x_test[s]\n", "\n", " # 時系列ループ\n", " for t in range(maxlen):\n", "\n", " # 入力値\n", " x = xs[t]\n", " u = np.dot(x, W_in) + np.dot(z, W)\n", " z = np.tanh(u)\n", "\n", " y = np.dot(z, W_out)\n", "\n", " #誤差\n", " loss = mean_squared_error(d, y)\n", " print('loss:', loss, ' d:', d, ' y:', y)\n", " \n", " \n", " \n", "original = np.full(maxlen, None)\n", "pred_num = 200\n", "\n", "xs = test_head\n", "\n", "# sin波予測\n", "for s in range(0, pred_num):\n", " z *= 0\n", " for t in range(maxlen):\n", " \n", " # 入力値\n", " x = xs[t]\n", " u = np.dot(x, W_in) + np.dot(z, W)\n", " z = np.tanh(u)\n", "\n", " y = np.dot(z, W_out)\n", " original = np.append(original, y)\n", " xs = np.delete(xs, 0)\n", " xs = np.append(xs, y)\n", "\n", "plt.figure()\n", "plt.ylim([-1.5, 1.5])\n", "plt.plot(np.sin(np.linspace(0, round_num* pred_num / div_num * np.pi, pred_num)), linestyle='dotted', color='#aaaaaa')\n", "plt.plot(original, linestyle='dashed', color='black')\n", "plt.show()" ], "execution_count": null, "outputs": [ { "output_type": "stream", "text": [ "loss: 1.0231756688222737e-07 d: [-0.29761864] y: [-0.29716628]\n", "loss: 1.2201090156041725e-08 d: [-0.56307233] y: [-0.56322854]\n", "loss: 4.038245320901024e-11 d: [-0.65766776] y: [-0.65765877]\n", "loss: 1.012613171470193e-08 d: [0.13182648] y: [0.13168417]\n", "loss: 6.953992391246068e-08 d: [0.49909101] y: [0.49871807]\n", "loss: 5.5838333193039375e-08 d: [0.9518317] y: [0.95149752]\n", "loss: 1.006541644062743e-07 d: [0.97784112] y: [0.97739245]\n", "loss: 1.7033534573325946e-08 d: [-0.58880346] y: [-0.58861889]\n", "loss: 5.2622812685924356e-08 d: [-0.78351093] y: [-0.78383534]\n", "loss: 2.60918282588755e-10 d: [-0.49909101] y: [-0.49906816]\n", "loss: 5.712849721315155e-08 d: [0.21857331] y: [0.21823529]\n", "loss: 9.126545094849141e-08 d: [-0.33938943] y: [-0.3389622]\n", "loss: 1.0304339135538811e-07 d: [-0.43793098] y: [-0.43747701]\n", "loss: 1.1445752972814562e-07 d: [-0.33346065] y: [-0.3329822]\n", "loss: 4.487028896407404e-08 d: [-0.99639027] y: [-0.9960907]\n", "loss: 4.518845122030081e-08 d: [0.88624247] y: [0.88654309]\n", "loss: 2.3166269315110745e-08 d: [-0.92833248] y: [-0.92811723]\n", "loss: 7.877136645016467e-10 d: [-0.52075286] y: [-0.52079255]\n", "loss: 8.254988700985761e-09 d: [-0.55262221] y: [-0.5527507]\n", "loss: 8.291678208274492e-08 d: [0.47711265] y: [0.47670543]\n", "loss: 3.515702303123948e-08 d: [0.60896952] y: [0.60923469]\n", "loss: 4.6349673171343807e-08 d: [-0.94587102] y: [-0.94556656]\n", "loss: 9.366188781076226e-08 d: [0.27953518] y: [0.27910237]\n", "loss: 7.187670231870784e-08 d: [0.73863456] y: [0.73901371]\n", "loss: 2.5175272023918393e-08 d: [-0.00629574] y: [-0.00607135]\n", "loss: 4.238282860583762e-08 d: [0.54208448] y: [0.54179333]\n", "loss: 5.364268767133932e-08 d: [0.99781582] y: [0.99748827]\n", "loss: 7.761284716153206e-08 d: [-0.96441607] y: [-0.96402208]\n", "loss: 7.29946476567447e-08 d: [0.07547747] y: [0.07509539]\n", "loss: 5.374729213271438e-12 d: [0.66239735] y: [0.66240063]\n", "loss: 3.917648631674704e-08 d: [-0.54736419] y: [-0.54708428]\n", "loss: 1.1396823999698672e-07 d: [0.99393675] y: [0.99345932]\n", "loss: 1.8916287872014157e-10 d: [0.96441607] y: [0.96443552]\n", "loss: 6.104853811859931e-08 d: [-0.22471249] y: [-0.22436306]\n", "loss: 3.374712152402054e-08 d: [-0.99393675] y: [-0.99367695]\n", "loss: 7.459208770391463e-08 d: [-0.71705202] y: [-0.71743827]\n", "loss: 3.3346599617550096e-09 d: [0.8649742] y: [0.86505587]\n", "loss: 1.0502769561892032e-07 d: [-0.11933469] y: [-0.11887638]\n", "loss: 3.7402892316320774e-08 d: [-0.40941891] y: [-0.4091454]\n", "loss: 1.1571745806193722e-07 d: [0.39789889] y: [0.39741782]\n", "loss: 1.3219146512941343e-08 d: [0.98611478] y: [0.98595218]\n", "loss: 6.82473798362108e-08 d: [-0.0691982] y: [-0.06882875]\n", "loss: 7.74733530193459e-08 d: [0.35709413] y: [0.3567005]\n", "loss: 4.2013170888265586e-08 d: [0.99583607] y: [0.9955462]\n", "loss: 2.1526965553360173e-08 d: [-0.92597363] y: [-0.92618113]\n", "loss: 6.817128658024936e-08 d: [0.36882689] y: [0.36845764]\n", "loss: 1.1810524118698761e-08 d: [0.91617219] y: [0.9160185]\n", "loss: 1.511514695515008e-09 d: [0.52611726] y: [0.52617224]\n", "loss: 8.054071771358459e-08 d: [0.96606148] y: [0.96566013]\n", "loss: 1.956018209202484e-08 d: [0.43793098] y: [0.43773319]\n", "loss: 2.365114287876332e-09 d: [-0.86811636] y: [-0.86818514]\n", "loss: 7.426592869136916e-08 d: [-0.99975723] y: [-0.99937184]\n", "loss: 3.369004516388851e-08 d: [0.77562491] y: [0.77588449]\n", "loss: 4.2428732558073345e-09 d: [0.04405617] y: [0.04414829]\n", "loss: 9.775107382870593e-09 d: [0.71705202] y: [0.71719184]\n", "loss: 4.388321808758248e-10 d: [0.8773359] y: [0.87736552]\n", "loss: 3.008800038067477e-08 d: [0.91363079] y: [0.9138761]\n", "loss: 3.4353135857868203e-09 d: [-0.97784112] y: [-0.97775823]\n", "loss: 8.641444917528756e-10 d: [0.96101064] y: [0.96105221]\n", "loss: 8.711809080390049e-08 d: [0.26742375] y: [0.26700633]\n", "loss: 5.0207765974484416e-08 d: [-0.87122411] y: [-0.871541]\n", "loss: 2.838017375633304e-08 d: [-0.91617219] y: [-0.91641043]\n", "loss: 1.5567226856080684e-09 d: [0.87122411] y: [0.87127991]\n", "loss: 9.803777837499867e-09 d: [0.98394564] y: [0.98380562]\n", "loss: 4.14806161320395e-08 d: [0.4036669] y: [0.40337887]\n", "loss: 8.246547424877302e-08 d: [0.0880268] y: [0.08762068]\n", "loss: 3.519939115353052e-08 d: [0.81012572] y: [0.81039105]\n", "loss: 3.3475921950765465e-08 d: [0.41515469] y: [0.41489593]\n", "loss: 3.920213266201233e-08 d: [-0.99524241] y: [-0.9949624]\n", "loss: 6.676591329593643e-09 d: [-0.94789551] y: [-0.94801107]\n", "loss: 2.7259396135763863e-08 d: [0.16916853] y: [0.16893503]\n", "loss: 5.901954968651478e-08 d: [-0.95374324] y: [-0.95339967]\n", "loss: 7.404264207154143e-08 d: [-0.72577151] y: [-0.72615633]\n", "loss: 1.950089841485295e-08 d: [0.74286391] y: [0.7430614]\n", "loss: 9.1706563452403e-09 d: [-0.94380904] y: [-0.94394447]\n", "loss: 1.8342443304828862e-08 d: [-0.83516734] y: [-0.83535887]\n", "loss: 4.0168629526980415e-08 d: [-0.94170965] y: [-0.94142621]\n", "loss: 1.0438172705832991e-07 d: [0.32156366] y: [0.32110676]\n", "loss: 7.96519652519902e-08 d: [-0.48263615] y: [-0.48223703]\n", "loss: 4.522391104134645e-08 d: [0.03776568] y: [0.03746493]\n", "loss: 8.671646127145176e-08 d: [0.34530476] y: [0.34488831]\n", "loss: 3.0057469610811475e-08 d: [0.56307233] y: [0.56282714]\n", "loss: 3.344824485318678e-08 d: [0.90843947] y: [0.90869812]\n", "loss: 9.740854716739049e-08 d: [0.99940055] y: [0.99895917]\n", "loss: 5.2790241458557934e-08 d: [0.85534252] y: [0.85566745]\n", "loss: 1.3438734027154209e-08 d: [0.93739898] y: [0.93756292]\n", "loss: 1.0825441262363102e-07 d: [0.99738016] y: [0.99691486]\n", "loss: 7.346796784291748e-08 d: [-0.6992734] y: [-0.69965672]\n", "loss: 9.62971935624344e-08 d: [-0.10682399] y: [-0.10638513]\n", "loss: 4.974432822949506e-09 d: [-0.54208448] y: [-0.54218422]\n", "loss: 7.137974552014359e-08 d: [0.9995987] y: [0.99922087]\n", "loss: 1.1991319740559976e-07 d: [0.29761864] y: [0.29712892]\n", "loss: 3.111699813899164e-08 d: [0.99322482] y: [0.99297535]\n", "loss: 9.573921959195159e-08 d: [0.33346065] y: [0.33302307]\n", "loss: 5.1818369725854564e-08 d: [-0.83168816] y: [-0.83201008]\n", "loss: 1.1452214926486475e-08 d: [-0.98504973] y: [-0.98489839]\n", "loss: 5.381547067764966e-08 d: [-0.64332332] y: [-0.6436514]\n", "loss: 1.0539082479572855e-07 d: [0.43226238] y: [0.43180327]\n", "loss: 3.26643400999611e-08 d: [-0.81380058] y: [-0.81405617]\n" ], "name": "stdout" }, { "output_type": "display_data", "data": { "image/png": "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\n", "text/plain": [ "<Figure size 432x288 with 1 Axes>" ] }, "metadata": { "tags": [], "needs_background": "light" } } ] }, { "cell_type": "markdown", "metadata": { "id": "iI6SQJcHj62q" }, "source": [ "maxlen:2 iters_num:100\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "id": "ylqvxrZ-9IvP" }, "source": [ "maxlen:2 iters_num:500\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "id": "qTUnnjwx9X_8" }, "source": [ "maxlen:2 iters_num:3000 \n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "id": "xyfTBafWRb2M" }, "source": [ "maxlen:5 iters_num:100 \n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "id": "52L8VqJ3RxqZ" }, "source": [ "maxlen:5 iters_num:500 \n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "id": "5SD7pir8UNRJ" }, "source": [ "maxlen:5 iters_num:3000 \n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "id": "pK4Jprp9UVx5" }, "source": [ "### 考察\n", "maxlen:2 のときは学習がうまく進まない。iters_numを増やしてもうまくいかない。\n", "maxlen:5 にすると、iters_num:3000でほぼ正確なサイン波を予測できている。\n" ] } ] }