{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Early stopping" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Installing packages:\n", "\t.package(path: \"/home/ubuntu/fastai_docs/dev_swift/FastaiNotebook_05_anneal\")\n", "\t\tFastaiNotebook_05_anneal\n", "With SwiftPM flags: []\n", "Working in: /tmp/tmpwo74wr9b/swift-install\n", "Fetching https://github.com/mxcl/Path.swift\n", "Fetching https://github.com/JustHTTP/Just\n", "Completed resolution in 2.98s\n", "Cloning https://github.com/mxcl/Path.swift\n", "Resolving https://github.com/mxcl/Path.swift at 0.16.2\n", "Cloning https://github.com/JustHTTP/Just\n", "Resolving https://github.com/JustHTTP/Just at 0.7.1\n", "Compile Swift Module 'Just' (1 sources)\n", "Compile Swift Module 'Path' (9 sources)\n", "Compile Swift Module 'FastaiNotebook_05_anneal' (9 sources)\n", "Compile Swift Module 'jupyterInstalledPackages' (1 sources)\n", "Linking ./.build/x86_64-unknown-linux/debug/libjupyterInstalledPackages.so\n", "Initializing Swift...\n", "Installation complete!\n" ] } ], "source": [ "%install '.package(path: \"$cwd/FastaiNotebook_05_anneal\")' FastaiNotebook_05_anneal" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load data" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('inline', 'module://ipykernel.pylab.backend_inline')\n" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import FastaiNotebook_05_anneal\n", "%include \"EnableIPythonDisplay.swift\"\n", "IPythonDisplay.shell.enable_matplotlib(\"inline\")" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "// export\n", "import Path\n", "import TensorFlow\n", "import Python" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "let data = mnistDataBunch(flat: true)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "let (n,m) = (60000,784)\n", "let c = 10\n", "let nHid = 50" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "var opt = SGD(learningRate: 1e-2)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "func modelInit() -> BasicModel {return BasicModel(nIn: m, nHid: nHid, nOut: c)}" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "let learner = Learner(data: data, lossFunction: softmaxCrossEntropy, optimizer: opt, initializingWith: modelInit)\n", "let recorder = learner.makeRecorder()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Check the previous callbacks load." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "learner.delegates = [learner.makeTrainEvalDelegate(), learner.makeShowProgress(),\n", " learner.makeNormalize(mean: mnistStats.mean, std: mnistStats.std),\n", " learner.makeAvgMetric(metrics: [accuracy]), recorder]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch 0: [0.30384538, 0.9101] \n", "Epoch 1: [0.24380504, 0.9296] \n", " \r" ] } ], "source": [ "learner.fit(2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Make an extension to quickly load them. " ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "// export\n", "//TODO: when recorder can be accessed as a property, remove it from the return\n", "extension Learner where Opt.Scalar: PythonConvertible {\n", " public func makeDefaultDelegates(metrics: [(Tensor, Tensor) -> Tensor] = []) -> Recorder {\n", " let recorder = makeRecorder()\n", " delegates = [makeTrainEvalDelegate(), makeShowProgress(), recorder]\n", " if !metrics.isEmpty { delegates.append(makeAvgMetric(metrics: metrics)) }\n", " return recorder\n", " }\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Control Flow test" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "extension Learner {\n", " public class TestControlFlow: Delegate {\n", " public override var order: Int { return 3 }\n", " var waitForSkipBatch, waitForSkipEpoch, waitForEndTrain: Int\n", " \n", " public init(nIter:Int, nBatch: Int, nEpoch: Int){ \n", " (waitForSkipBatch, waitForSkipEpoch, waitForEndTrain) = (nIter, nBatch, nEpoch)\n", " }\n", " \n", " public override func didProduceNewGradient(learner: Learner) throws {\n", " if learner.currentIter >= waitForSkipBatch {throw LearnerAction.skipBatch}\n", " }\n", " \n", " public override func batchDidFinish(learner: Learner) throws {\n", " if learner.currentIter >= waitForSkipBatch {\n", " print(\"batchDidFinish properly executed after skip batch at iter \\(learner.currentIter)\")\n", " }\n", " if learner.currentIter >= waitForSkipEpoch {throw LearnerAction.skipEpoch}\n", " }\n", " \n", " public override func epochDidFinish(learner: Learner) throws {\n", " print(\"epochDidFinish properly executed after skip epoch (number \\(learner.currentEpoch))\")\n", " if learner.currentEpoch >= waitForEndTrain {throw LearnerAction.stop}\n", " }\n", " \n", " public override func trainingDidFinish(learner: Learner){\n", " print(\"trainingDidFinish properly executed after stop\")\n", " } \n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "let learner = Learner(data: data, lossFunction: softmaxCrossEntropy, optimizer: opt, initializingWith: modelInit)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "learner.delegates = [type(of: learner).TestControlFlow(nIter:5, nBatch: 7, nEpoch: 2),\n", " learner.makeTrainEvalDelegate()]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "batchDidFinish properly executed after skip batch at iter 5\n", "batchDidFinish properly executed after skip batch at iter 6\n", "batchDidFinish properly executed after skip batch at iter 7\n", "epochDidFinish properly executed after skip epoch (number 0)\n", "batchDidFinish properly executed after skip batch at iter 5\n", "batchDidFinish properly executed after skip batch at iter 6\n", "batchDidFinish properly executed after skip batch at iter 7\n", "epochDidFinish properly executed after skip epoch (number 1)\n", "batchDidFinish properly executed after skip batch at iter 5\n", "batchDidFinish properly executed after skip batch at iter 6\n", "batchDidFinish properly executed after skip batch at iter 7\n", "epochDidFinish properly executed after skip epoch (number 2)\n", "trainingDidFinish properly executed after stop\n" ] } ], "source": [ "learner.fit(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Check if the orders were taken into account:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "▿ 2 elements\n", " - .0 : 0\n", " - .1 : 3\n" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(learner.delegates[0].order,learner.delegates[1].order)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### LR Finder" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "// export\n", "extension Learner where Opt.Scalar: BinaryFloatingPoint {\n", " public class LRFinder: Delegate {\n", " public typealias ScheduleFunc = (Float) -> Float\n", "\n", " // A learning rate schedule from step to float.\n", " private var scheduler: ScheduleFunc\n", " private var numIter: Int\n", " private var minLoss: Float? = nil\n", " \n", " public init(start: Float = 1e-5, end: Float = 10, numIter: Int = 100) {\n", " scheduler = makeAnnealer(start: start, end: end, schedule: expSchedule)\n", " self.numIter = numIter\n", " }\n", " \n", " override public func batchWillStart(learner: Learner) {\n", " learner.optimizer.learningRate = Opt.Scalar(scheduler(Float(learner.currentIter)/Float(numIter)))\n", " }\n", " \n", " override public func batchDidFinish(learner: Learner) throws {\n", " if minLoss == nil {minLoss = learner.currentLoss.scalar}\n", " else { \n", " if learner.currentLoss.scalarized() < minLoss! { minLoss = learner.currentLoss.scalarized()}\n", " if learner.currentLoss.scalarized() > 4 * minLoss! { throw LearnerAction.stop }\n", " if learner.currentIter >= numIter { throw LearnerAction.stop }\n", " }\n", " }\n", " \n", " override public func validationWillStart(learner: Learner) throws {\n", " //Skip validation during the LR range test\n", " throw LearnerAction.skipEpoch\n", " }\n", " }\n", " \n", " public func makeLRFinder(start: Float = 1e-5, end: Float = 10, numIter: Int = 100) -> LRFinder {\n", " return LRFinder(start: start, end: end, numIter: numIter)\n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "let learner = Learner(data: data, lossFunction: softmaxCrossEntropy, optimizer: opt, initializingWith: modelInit)\n", "let recorder = learner.makeDefaultDelegates()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "learner.delegates.append(learner.makeNormalize(mean: mnistStats.mean, std: mnistStats.std))\n", "learner.delegates.append(learner.makeLRFinder())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " \r" ] } ], "source": [ "learner.fit(2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "recorder.plotLRFinder()" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "// export\n", "//TODO: when Recorder is a property of Learner don't return it.\n", "extension Learner where Opt.Scalar: PythonConvertible & BinaryFloatingPoint {\n", " public func lrFind(start: Float = 1e-5, end: Float = 10, numIter: Int = 100) -> Recorder {\n", " let epochCount = data.train.count/numIter + 1\n", " let recorder = makeDefaultDelegates()\n", " delegates.append(makeLRFinder(start: start, end: end, numIter: numIter))\n", " try! self.fit(epochCount)\n", " return recorder\n", " }\n", "}" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " \r" ] } ], "source": [ "let recorder = learner.lrFind()" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "recorder.plotLRFinder()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Export" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "notebookToScript(fname: (Path.cwd / \"05b_early_stopping.ipynb\").string)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Swift", "language": "swift", "name": "swift" }, "language_info": { "file_extension": ".swift", "mimetype": "text/x-swift", "name": "swift", "version": "" } }, "nbformat": 4, "nbformat_minor": 2 }