{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Deep_Learning_with_JavaScript_chapter2","provenance":[{"file_id":"https://gist.github.com/obenjiro/7f1499520458fdb06fdf48086c9be50a","timestamp":1585404090900}],"collapsed_sections":[]},"kernelspec":{"name":"javascript","display_name":"Javascript"},"accelerator":"GPU"},"cells":[{"cell_type":"markdown","metadata":{"id":"bn4xzI818Qit","colab_type":"text"},"source":["## Deep Learning with Javascriptの勉強ノート\n","jupter notebookでjavascriptを使いたいと思っていたところ、以下のnotebookを見つけました。\n","\n","- Google Colaboratory + TensorflowJS example\n","\n","この方法のポイントは、以下の通りです。\n","- jupyter notebookのタイプをjavascriptにプリセット\n","- javascriptカーネルをインストールする以下のセルを追加\n","\n","以下にDeep Learning with Javascriptの2章の例題をGoogle Colabで実行してみます。 例題は、以下のGithubにありました。\n","- https://github.com/tensorflow/tfjs-examples/blob/master/getting-started/index.js\n"]},{"cell_type":"markdown","metadata":{"id":"fsqcND6Klagn","colab_type":"text"},"source":["## 準備(javascriptカーネルのインストール)"]},{"cell_type":"markdown","metadata":{"id":"bjNF3VjPjJHV","colab_type":"text"},"source":["以下のセルを実行して、本ノートブックの再ロード(F5キーを押下)してください。\n","\n","一度カーネル環境が作成された後(Google Colabのセッションが有効な間)は実行する必要はありません。"]},{"cell_type":"code","metadata":{"id":"ZVkF16NwcMsZ","colab_type":"code","outputId":"b0190280-ec4e-446a-f870-9fb5797899ec","executionInfo":{"status":"ok","timestamp":1586052826594,"user_tz":-540,"elapsed":41147,"user":{"displayName":"竹本浩","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjpTXXuyshXY_NrboOzg5G7TJmGKC0tOF6PjozObA=s64","userId":"00259582923506648077"}},"colab":{"base_uri":"https://localhost:8080/","height":391}},"source":["!npm install -g npm@latest\n","!npm cache verify\n","!npm install -g --unsafe-perm ijavascript\n","!ijsinstall --install=global\n","!jupyter-kernelspec list"],"execution_count":0,"outputs":[{"output_type":"stream","text":["ERROR! Session/line number was not unique in database. History logging moved to new session 59\n","\u001b[K\u001b[?25h/tools/node/bin/npm -> /tools/node/lib/node_modules/npm/bin/npm-cli.js\n","/tools/node/bin/npx -> /tools/node/lib/node_modules/npm/bin/npx-cli.js\n","\u001b[K\u001b[?25h+ npm@6.14.4\n","added 325 packages from 161 contributors, removed 423 packages and updated 59 packages in 10.505s\n","Cache verified and compressed (~/.npm/_cacache):\n","Content verified: 78 (21053000 bytes)\n","Index entries: 79\n","Finished in 0.705s\n","\u001b[K\u001b[?25h/tools/node/bin/ijs -> /tools/node/lib/node_modules/ijavascript/bin/ijavascript.js\n","/tools/node/bin/ijsconsole -> /tools/node/lib/node_modules/ijavascript/bin/ijsconsole.js\n","/tools/node/bin/ijsinstall -> /tools/node/lib/node_modules/ijavascript/bin/ijsinstall.js\n","/tools/node/bin/ijskernel -> /tools/node/lib/node_modules/ijavascript/lib/kernel.js\n","/tools/node/bin/ijsnotebook -> /tools/node/lib/node_modules/ijavascript/bin/ijsnotebook.js\n","\u001b[K\u001b[?25h\n","> zeromq@5.2.0 install /tools/node/lib/node_modules/ijavascript/node_modules/zeromq\n","> node scripts/prebuild-install.js || (node scripts/preinstall.js && node-gyp rebuild)\n","\n","\n","\n","+ ijavascript@5.2.0\n","added 67 packages from 65 contributors in 4.07s\n"],"name":"stdout"}]},{"cell_type":"markdown","metadata":{"id":"r2UzIt5Gi6Em","colab_type":"text"},"source":["以降のセルからjavascriptが使えるようになります。\n"]},{"cell_type":"markdown","metadata":{"id":"MMyXtMptltc9","colab_type":"text"},"source":["## 便利なユーティティ関数の定義"]},{"cell_type":"markdown","metadata":{"id":"qbVfsd0emCWY","colab_type":"text"},"source":["**注意事項 constとlet文は使わず、varを使ってください**\n","\n","セル内でコマンドを実行するsh関数を定義します。"]},{"cell_type":"code","metadata":{"id":"skqAs_UHc8_P","colab_type":"code","outputId":"28faf87c-b2c5-4489-8915-86d295031365","executionInfo":{"status":"ok","timestamp":1586064126171,"user_tz":-540,"elapsed":747,"user":{"displayName":"竹本浩","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjpTXXuyshXY_NrboOzg5G7TJmGKC0tOF6PjozObA=s64","userId":"00259582923506648077"}},"colab":{"base_uri":"https://localhost:8080/","height":306}},"source":["var { spawn } = require('child_process')\n","var sh = (cmd) => { \n"," $$.async()\n"," var sp = spawn(cmd, { cwd: process.cwd(), stdio: 'pipe', shell: true, encoding: 'utf-8' })\n"," sp.stdout.on('data', data => console.log(data.toString()))\n"," sp.stderr.on('data', data => console.error(data.toString()))\n"," sp.on('close', () => $$.done())\n","}\n","var run_async = async (pf) => {\n"," $$.async()\n"," await pf()\n"," $$.done()\n","}\n","sh('npm init -y')"],"execution_count":0,"outputs":[{"output_type":"stream","text":["Wrote to /content/package.json:\n","\n","{\n"," \"name\": \"content\",\n"," \"version\": \"1.0.0\",\n"," \"description\": \"\",\n"," \"main\": \"index.js\",\n"," \"scripts\": {\n"," \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n"," },\n"," \"keywords\": [],\n"," \"author\": \"\",\n"," \"license\": \"ISC\"\n","}\n","\n","\n","\n"],"name":"stdout"}]},{"cell_type":"markdown","metadata":{"id":"KpNj3bEyDoy3","colab_type":"text"},"source":["## 2章"]},{"cell_type":"markdown","metadata":{"id":"VkcCdP7uA-iq","colab_type":"text"},"source":["### 必要なライブラリのインストール\n","GPU版のTensorflowJSをインストールします。\n","\n","- tensorflow(GPU版)\n","- plotly(notebook版)"]},{"cell_type":"code","metadata":{"id":"y4huIP4qEc8y","colab_type":"code","outputId":"62bc2bea-f27e-4a06-a3ee-33102051a257","executionInfo":{"status":"ok","timestamp":1586064340610,"user_tz":-540,"elapsed":2355,"user":{"displayName":"竹本浩","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjpTXXuyshXY_NrboOzg5G7TJmGKC0tOF6PjozObA=s64","userId":"00259582923506648077"}},"colab":{"base_uri":"https://localhost:8080/","height":306}},"source":["sh('npm install @tensorflow/tfjs-node')\n","sh('npm install plotly-notebook-js')"],"execution_count":35,"outputs":[{"output_type":"stream","text":["npm\n"," WARN content@1.0.0 No description\n","\n","npm WARN content@1.0.0 No repository field.\n","\n","\n"],"name":"stderr"},{"output_type":"stream","text":["+ plotly-notebook-js@0.1.2\n","added 1 package from 1 contributor and audited 167 packages in 1.071s\n","\n","\n","1 package is looking for funding\n"," run `npm fund` for details\n","\n","\n","found 0 vulnerabilities\n","\n","\n"],"name":"stdout"}]},{"cell_type":"markdown","metadata":{"id":"GVQnmXOQYeJ-","colab_type":"text"},"source":["### データの準備\n","以下のセルの実行でエラーになった場合には、ブラウザーのF5(再読み込み)を実行してもう一度試してみまてください。\n"]},{"cell_type":"code","metadata":{"id":"psJPTwp79NXv","colab_type":"code","outputId":"b59bcba0-15a9-4ae4-d5a7-0ba268543ec1","executionInfo":{"status":"ok","timestamp":1586064193634,"user_tz":-540,"elapsed":732,"user":{"displayName":"竹本浩","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjpTXXuyshXY_NrboOzg5G7TJmGKC0tOF6PjozObA=s64","userId":"00259582923506648077"}},"colab":{"base_uri":"https://localhost:8080/","height":119}},"source":["var tf = require('@tensorflow/tfjs-node')\n","console.log(tf.backend().isUsingGpuDevice)"],"execution_count":19,"outputs":[{"output_type":"stream","text":["node-pre-gyp info This Node instance does not support builds for N-API version 4\n","node-pre-gyp info This Node instance does not support builds for N-API version 5\n","node-pre-gyp info This Node instance does not support builds for N-API version 4\n","node-pre-gyp info This Node instance does not support builds for N-API version 5\n"],"name":"stderr"},{"output_type":"stream","text":["false\n"],"name":"stdout"},{"output_type":"stream","text":["(node:247) Warning: N-API is an experimental feature and could change at any time.\n"],"name":"stderr"}]},{"cell_type":"markdown","metadata":{"id":"sfV1cdHwbHGl","colab_type":"text"},"source":["テストデータとして、ファイルサイズとダウンドード時間の観測データをtrainData, testDataにセットします。"]},{"cell_type":"code","metadata":{"id":"Rp0cOm1ZEd9j","colab_type":"code","colab":{}},"source":["var trainData = {\n"," sizeMB: [0.080, 9.000, 0.001, 0.100, 8.000, 5.000, 0.100, 6.000, 0.050, 0.500,\n"," 0.002, 2.000, 0.005, 10.00, 0.010, 7.000, 6.000, 5.000, 1.000, 1.000],\n"," timeSec: [0.135, 0.739, 0.067, 0.126, 0.646, 0.435, 0.069, 0.497, 0.068, 0.116,\n"," 0.070, 0.289, 0.076, 0.744, 0.083, 0.560, 0.480, 0.399, 0.153, 0.149]\n","}\n","var testData = {\n"," sizeMB: [5.000, 0.200, 0.001, 9.000, 0.002, 0.020, 0.008, 4.000, 0.001, 1.000,\n"," 0.005, 0.080, 0.800, 0.200, 0.050, 7.000, 0.005, 0.002, 8.000, 0.008],\n"," timeSec: [0.425, 0.098, 0.052, 0.686, 0.066, 0.078, 0.070, 0.375, 0.058, 0.136,\n"," 0.052, 0.063, 0.183, 0.087, 0.066, 0.558, 0.066, 0.068, 0.610, 0.057]\n","}"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"RL2wUmg4bb4V","colab_type":"text"},"source":["tf.tensor2d関数を使って2次元テンソルに変換します。[20,1]はデータの次数(shape)を指定します。"]},{"cell_type":"code","metadata":{"id":"GcQiKW6sJFZX","colab_type":"code","colab":{}},"source":["var trainTensors = {\n"," sizeMB: tf.tensor2d(trainData.sizeMB, [20, 1]),\n"," timeSec: tf.tensor2d(trainData.timeSec, [20, 1])\n","}\n","var testTensors = {\n"," sizeMB: tf.tensor2d(testData.sizeMB, [20, 1]),\n"," timeSec: tf.tensor2d(testData.timeSec, [20, 1]) \n","}"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"MJ5hxp33YSB9","colab_type":"text"},"source":["### データの可視化\n"]},{"cell_type":"markdown","metadata":{"id":"LKiUXjLQcRlQ","colab_type":"text"},"source":["trainDataとtestDataの分布をPlotlyライブラリを使って可視化(プロット)します。\n","\n","plotlyに渡すデータ構造にするために、dataTraceTrain, dataTraceTestに必要な情報をセットします。\n","- x: x軸要素\n","- y: y軸要素\n","- name: 凡例で使用する名称\n","- mode: プロット方法で、ポイントをマークで表示(markers)を指定\n","- type: プロットタイプで、散布図(scatter)を指定\n","- marker: マークの種別を指定"]},{"cell_type":"code","metadata":{"id":"FEhDv0gOMlu5","colab_type":"code","colab":{}},"source":["var dataTraceTrain = {\n"," x: trainData.sizeMB,\n"," y: trainData.timeSec,\n"," name: 'trainData',\n"," mode: 'markers',\n"," type: 'scatter',\n"," marker: {symbol: \"circle\", size: 8}\n","};\n","var dataTraceTest = {\n"," x: testData.sizeMB,\n"," y: testData.timeSec,\n"," name: 'testData',\n"," mode: 'markers',\n"," type: 'scatter',\n"," marker: {symbol: \"triangle-up\", size: 10}\n","};"],"execution_count":0,"outputs":[]},{"cell_type":"code","metadata":{"id":"tZY5eeQ9P3Pc","colab_type":"code","outputId":"1e46921a-fd1c-4c8c-a743-4370839d2cf7","executionInfo":{"status":"ok","timestamp":1586064351109,"user_tz":-540,"elapsed":698,"user":{"displayName":"竹本浩","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjpTXXuyshXY_NrboOzg5G7TJmGKC0tOF6PjozObA=s64","userId":"00259582923506648077"}},"colab":{"base_uri":"https://localhost:8080/","height":467}},"source":["var Plot = require('plotly-notebook-js')\n","var NotebookPlot = Plot.createPlot().constructor\n","NotebookPlot.prototype._toHtml = NotebookPlot.prototype.render\n","\n","Plot.createPlot([dataTraceTrain, dataTraceTest], {\n"," width: 700,\n"," title: 'File download duration',\n"," xaxis: {\n"," title: 'size (MB)'\n"," },\n"," yaxis: {\n"," title: 'time (sec)'\n"," }\n","})"],"execution_count":38,"outputs":[{"output_type":"execute_result","data":{"text/html":["
"],"text/plain":["NotebookPlot {\n"," data: \n"," [ { x: [Array],\n"," y: [Array],\n"," name: 'trainData',\n"," mode: 'markers',\n"," type: 'scatter',\n"," marker: [Object] },\n"," { x: [Array],\n"," y: [Array],\n"," name: 'testData',\n"," mode: 'markers',\n"," type: 'scatter',\n"," marker: [Object] } ],\n"," layout: \n"," { width: 700,\n"," title: 'File download duration',\n"," xaxis: { title: 'size (MB)' },\n"," yaxis: { title: 'time (sec)' } },\n"," scriptSource: '/notebooks/node_modules/plotly-notebook-js/build/plotly.min.js' }"]},"metadata":{"tags":[]},"execution_count":38}]},{"cell_type":"markdown","metadata":{"id":"jrcfwJ46KDlr","colab_type":"text"},"source":["## TensorflowJSを使った線形回帰\n","ニューラルネットワークの層を作成します。ここでは入力として1個の要素を持つ入れる配列を持つ、密結合の層(dense)を追加します。unitsで出力値が1個であると設定します。\n","\n","オプティマイザーとして'sgd'(確率的勾配降下法) , 'meanAbsoluteError'(損失関数として絶対値の平均)を指定して、modelをコンパイルします。\n"]},{"cell_type":"code","metadata":{"id":"JrHGpehIWD8t","colab_type":"code","colab":{}},"source":["var model = tf.sequential();\n","model.add(tf.layers.dense({\n"," units: 1,\n"," inputShape: [1],\n","}))\n","model.compile({ optimizer: 'sgd', loss: 'meanAbsoluteError' })\n"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"bDQaiQHXOv0M","colab_type":"text"},"source":["回帰で求めるのは、転送時間(timeSec)で、入力としてファイルサイズ(sizeMB)を与えます。\n","\n","回帰分析ではニューラルネットの重みmと切片bで計算されます。\n","$$\n","timeSec = kernel * sizeMB + bias\n","$$\n","\n","setWeights関数で重みkの初期値と切片bの初期値をここでは0として開始します。"]},{"cell_type":"code","metadata":{"id":"rnm2o03ImqV9","colab_type":"code","colab":{}},"source":["var k = 0\n","var b = 0\n","model.setWeights([tf.tensor2d([k], [1, 1]), tf.tensor1d([b])])"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"4FZasbc0QVkD","colab_type":"text"},"source":["kerasと同様にfit関数で回帰を実行します。\n","出力のlossがEpoch毎に小さくなって収束しているのがわかります。"]},{"cell_type":"code","metadata":{"id":"f39Whz5imwkf","colab_type":"code","outputId":"55ea3974-7838-40a8-d6e9-b2000a2d5a05","executionInfo":{"status":"ok","timestamp":1586066010514,"user_tz":-540,"elapsed":856,"user":{"displayName":"竹本浩","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjpTXXuyshXY_NrboOzg5G7TJmGKC0tOF6PjozObA=s64","userId":"00259582923506648077"}},"colab":{"base_uri":"https://localhost:8080/","height":935}},"source":["model.fit(trainTensors.sizeMB, trainTensors.timeSec, {epochs: 10})"],"execution_count":125,"outputs":[{"output_type":"stream","text":["Epoch 1 / 10\n"],"name":"stdout"},{"output_type":"stream","text":["\n"],"name":"stderr"},{"output_type":"stream","text":["7ms 330us/step - loss=0.295 \n","Epoch 2 / 10\n"],"name":"stdout"},{"output_type":"stream","text":["\n"],"name":"stderr"},{"output_type":"stream","text":["8ms 377us/step - loss=0.192 \n","Epoch 3 / 10\n"],"name":"stdout"},{"output_type":"stream","text":["\n"],"name":"stderr"},{"output_type":"stream","text":["7ms 329us/step - loss=0.0899 \n","Epoch 4 / 10\n"],"name":"stdout"},{"output_type":"stream","text":["\n"],"name":"stderr"},{"output_type":"stream","text":["6ms 307us/step - loss=0.0725 \n","Epoch 5 / 10\n"],"name":"stdout"},{"output_type":"stream","text":["\n"],"name":"stderr"},{"output_type":"stream","text":["8ms 385us/step - loss=0.0632 \n","Epoch 6 / 10\n"],"name":"stdout"},{"output_type":"stream","text":["\n"],"name":"stderr"},{"output_type":"stream","text":["6ms 321us/step - loss=0.0825 \n","Epoch 7 / 10\n"],"name":"stdout"},{"output_type":"stream","text":["\n"],"name":"stderr"},{"output_type":"stream","text":["9ms 453us/step - loss=0.0370 \n","Epoch 8 / 10\n"],"name":"stdout"},{"output_type":"stream","text":["\n"],"name":"stderr"},{"output_type":"stream","text":["8ms 386us/step - loss=0.0671 \n","Epoch 9 / 10\n"],"name":"stdout"},{"output_type":"stream","text":["\n"],"name":"stderr"},{"output_type":"stream","text":["8ms 403us/step - loss=0.0411 \n","Epoch 10 / 10\n"],"name":"stdout"},{"output_type":"stream","text":["\n"],"name":"stderr"},{"output_type":"stream","text":["8ms 410us/step - loss=0.0798 \n"],"name":"stdout"},{"output_type":"execute_result","data":{"text/plain":["History {\n"," validationData: null,\n"," params: \n"," { epochs: 10,\n"," initialEpoch: 0,\n"," samples: 20,\n"," steps: null,\n"," batchSize: 32,\n"," verbose: 1,\n"," doValidation: false,\n"," metrics: [ 'loss' ] },\n"," epoch: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ],\n"," history: \n"," { loss: \n"," [ 0.2950499951839447,\n"," 0.19248802959918976,\n"," 0.08992607891559601,\n"," 0.0724872499704361,\n"," 0.06317649036645889,\n"," 0.08248651027679443,\n"," 0.03697093203663826,\n"," 0.06710976362228394,\n"," 0.0411013700067997,\n"," 0.07980944216251373 ] } }"]},"metadata":{"tags":[]},"execution_count":125}]},{"cell_type":"markdown","metadata":{"id":"3-hRowOjzra1","colab_type":"text"},"source":["学習したニューラルネットのモデルを表示するために、testTensorsで評価してみましょう。\n","0.013と小さな誤差にまとまっているみたいです。"]},{"cell_type":"code","metadata":{"id":"m-7kVjjjkN87","colab_type":"code","outputId":"4e38423c-ec6d-4e2e-fc50-77aa4c4524c4","executionInfo":{"status":"ok","timestamp":1586066012398,"user_tz":-540,"elapsed":784,"user":{"displayName":"竹本浩","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjpTXXuyshXY_NrboOzg5G7TJmGKC0tOF6PjozObA=s64","userId":"00259582923506648077"}},"colab":{"base_uri":"https://localhost:8080/","height":51}},"source":["model.evaluate(testTensors.sizeMB, testTensors.timeSec).print()"],"execution_count":127,"outputs":[{"output_type":"stream","text":["Tensor\n"," 0.01322927325963974\n"],"name":"stdout"}]},{"cell_type":"markdown","metadata":{"id":"M39oj_PH0SHQ","colab_type":"text"},"source":["新しいファイルサイズ(7.8)に対するダウンロード時間は、7.8を2重に鍵かっこ([])で括ってtensor2dに渡してpredict関数で計算することができます。グラフと比較すると0.59とよい値を予測していることがわかります。"]},{"cell_type":"code","metadata":{"id":"y6tKKHVmnTnV","colab_type":"code","outputId":"7b0c65d0-544d-468c-f5a8-6c2bcdf21291","executionInfo":{"status":"ok","timestamp":1586066016957,"user_tz":-540,"elapsed":761,"user":{"displayName":"竹本浩","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjpTXXuyshXY_NrboOzg5G7TJmGKC0tOF6PjozObA=s64","userId":"00259582923506648077"}},"colab":{"base_uri":"https://localhost:8080/","height":51}},"source":["model.predict(tf.tensor2d([[7.8]])).print()"],"execution_count":129,"outputs":[{"output_type":"stream","text":["Tensor\n"," [[0.5941021],]\n"],"name":"stdout"}]},{"cell_type":"markdown","metadata":{"id":"xOFKQiHq3MsC","colab_type":"text"},"source":["回帰で求まったk, bの値をみてみましょう。"]},{"cell_type":"code","metadata":{"id":"68l93UzZqwuX","colab_type":"code","colab":{"base_uri":"https://localhost:8080/","height":34},"outputId":"8b825379-ee5d-416b-ea8e-979946df0b21","executionInfo":{"status":"ok","timestamp":1586066018929,"user_tz":-540,"elapsed":599,"user":{"displayName":"竹本浩","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjpTXXuyshXY_NrboOzg5G7TJmGKC0tOF6PjozObA=s64","userId":"00259582923506648077"}}},"source":["k = model.getWeights()[0].dataSync()[0]\n","b = model.getWeights()[1].dataSync()[0];\n","console.log(k, b)"],"execution_count":131,"outputs":[{"output_type":"stream","text":["0.06809000670909882 0.06300000101327896\n"],"name":"stdout"}]},{"cell_type":"markdown","metadata":{"id":"p9biAikd59UK","colab_type":"text"},"source":["### 回帰直線のプロット\n","kとbの値が求まったので、データと回帰直線を一緒にプロットしてみましょう。"]},{"cell_type":"code","metadata":{"id":"Tq9q6mL42rj-","colab_type":"code","colab":{"base_uri":"https://localhost:8080/","height":467},"outputId":"87877cf6-3008-46e0-a2aa-0f454611b904","executionInfo":{"status":"ok","timestamp":1586066149490,"user_tz":-540,"elapsed":664,"user":{"displayName":"竹本浩","photoUrl":"https://lh3.googleusercontent.com/a-/AOh14GjpTXXuyshXY_NrboOzg5G7TJmGKC0tOF6PjozObA=s64","userId":"00259582923506648077"}}},"source":["var traceLine = {\n"," x: [0, 10],\n"," y: [b, b + (k * 10)],\n"," name: 'trace line',\n"," mode: 'lines'\n","}\n","\n","Plot.createPlot([dataTraceTrain, dataTraceTest, traceLine], {\n"," width: 700,\n"," title: 'File download duration',\n"," xaxis: {\n"," title: 'size (MB)'\n"," },\n"," yaxis: {\n"," title: 'time (sec)'\n"," }\n","})"],"execution_count":138,"outputs":[{"output_type":"execute_result","data":{"text/html":["
"],"text/plain":["NotebookPlot {\n"," data: \n"," [ { x: [Array],\n"," y: [Array],\n"," name: 'trainData',\n"," mode: 'markers',\n"," type: 'scatter',\n"," marker: [Object] },\n"," { x: [Array],\n"," y: [Array],\n"," name: 'testData',\n"," mode: 'markers',\n"," type: 'scatter',\n"," marker: [Object] },\n"," { x: [Array], y: [Array], name: 'trace line', mode: 'lines' } ],\n"," layout: \n"," { width: 700,\n"," title: 'File download duration',\n"," xaxis: { title: 'size (MB)' },\n"," yaxis: { title: 'time (sec)' } },\n"," scriptSource: '/notebooks/node_modules/plotly-notebook-js/build/plotly.min.js' }"]},"metadata":{"tags":[]},"execution_count":138}]},{"cell_type":"code","metadata":{"id":"FYrqEJSA4k8M","colab_type":"code","colab":{}},"source":[""],"execution_count":0,"outputs":[]}]}