From d36e607ed2de33cfcd116324bd0fd35b90ba8bf4 Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Mon, 24 Apr 2017 08:45:18 +0900 Subject: [PATCH 01/16] Add a rst file --- docs/image/trainer/mnist_accuracy.png | Bin 0 -> 16563 bytes docs/image/trainer/mnist_graph.png | Bin 0 -> 89300 bytes docs/image/trainer/mnist_loss.png | Bin 0 -> 16121 bytes docs/image/trainer/mnist_output.png | Bin 0 -> 4508 bytes docs/image/trainer/trainer.png | Bin 0 -> 31187 bytes docs/source/tutorial/trainer.rst | 339 ++++++++++++++++++++++++++ 6 files changed, 339 insertions(+) create mode 100644 docs/image/trainer/mnist_accuracy.png create mode 100644 docs/image/trainer/mnist_graph.png create mode 100644 docs/image/trainer/mnist_loss.png create mode 100644 docs/image/trainer/mnist_output.png create mode 100644 docs/image/trainer/trainer.png create mode 100644 docs/source/tutorial/trainer.rst diff --git a/docs/image/trainer/mnist_accuracy.png b/docs/image/trainer/mnist_accuracy.png new file mode 100644 index 0000000000000000000000000000000000000000..c6607e3421d0d6322f5583ffd57b08e2fe745b8c GIT binary patch literal 16563 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 Bu4VuL literal 0 HcmV?d00001 diff --git a/docs/image/trainer/mnist_graph.png b/docs/image/trainer/mnist_graph.png new file mode 100644 index 0000000000000000000000000000000000000000..089e09e6dae6073cd39b213d0f36bdc3ac320925 GIT binary patch literal 89300 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 literal 0 HcmV?d00001 diff --git a/docs/image/trainer/mnist_loss.png b/docs/image/trainer/mnist_loss.png new file mode 100644 index 0000000000000000000000000000000000000000..81607e276293f08f852d70f3e4faf32065fd5dea GIT binary patch literal 16121 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 H^St?A0Z>}w literal 0 HcmV?d00001 diff --git a/docs/image/trainer/trainer.png b/docs/image/trainer/trainer.png new file mode 100644 index 0000000000000000000000000000000000000000..410e16ca8985fd7b85835dc74694731601964f60 GIT binary patch literal 31187 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�P)8U|5qMb%@jMjVb)+6(f zbRS7e4SMgU^T!srav}DmufN^pQx9bnMFw#k7jG(`ZB4^BHkBNQT-Z)+cK}RAXnh<` zl<;0v&O-G$5S0-s_k$B2d#9N`=~j&r+KyQj6gl~{JB_tA{#3-cP&Dny_2C6+5n|6K zy6`o0(lL`5w6W85rSPZ8KelLyhtpZBA3NqKD|g-ZwnOq)F~``QpS3gB_i1=80`U-+xhQZ9{3&PITBKxAOLIr~eFbBDj%J7mvuH_?VNC&?5d3m-*v1^F zMmC0>-1YcC$i69&_)+Rgn`e@`z`Z>#Lkmv+&N`;Ac;!dOlUgz4v$3}mWw11Rs(E7< zED|buv*ev9BkjHid)vzF=v_J%RYy0}Ke8AA@=9mn#dAq6*~h0JFR1{^rw7x{tTip*8;8ItAW3YkvjRei#@&o*>Z1pP@{T)s{{ayO5c*g+l}WpKKy#u zzEkl4=sYimdO0qvHui6(<|aZi?2CXxBRjYwLLP?O9_Bu3f@8Mg94W=E$_|uBQp@+0 z8`IR6hkeyCa-m+-5>|TWauQN{+RXdYaeR@uaB&|bT?a?ADe-aJ)Ld%BqfLN7)dpCX zEMiLRN@5cHd7&F?I48Sax7*JINFe+4wX)yL*y*zAr7b65^psJ$zI3oZhMiWG>de#l z<1`7Z1Abw~Y}3J+!V*k%hlTUCVt$c#c&63v(3UHKH5$QIySx1cnQA6oMUbBRcRnl9 z_9!RaaN<7w-MRO9V_R<<_0FNSy?zweD=E9Qs?8P(6ku`$hUTiGs<+iY$s{HG>Udo1 zn;+_5u&)9MN5%d^!Po3Ozx_aQ+&Q+<~sJ=fJ-c8~52Tgbq!}p4} zthBDj`2$a|=9LbChbwJ=)no3THT^?wi7a9IflG3kYns=ED~u-E?Z2t*!O@*cU5|if zI_g91Kc@^uTDN??C$yeuS>ykWc*)O^1IW?DiM@QDcmi#2sCRODlpO+p4X4h|aB1vv-Z#ynx%alQ6?^(t^NMeu6k28UQsM2)g zhZR-`d5B%a5sT@2fZz=DzFmVH_cQJXD0B31*;LCB~NU1t2AzyC}?WbiJxq4JTnT*At1x4q@>LHeySH%K{M-J@|(cUkA;Jl zmohyXx~94kI^~_yiv5QJS!WDb$B4|+K|DuhR*fa#05ztn#sd>qQ2F)D9TCXby_Lg7Nv?yV8S@2#U zY^woIZg+LsXr_MKZvJc0(k+jEjZI3>v%Xb}FjvQM^9Ep!sgza9J|d=93}#>%LX8p~ z4LtXN!f{?l5vif_X7NDx)f$9u7-7p%3?8tjkH6}DzFejF;;xP-3z}t@Y=TO{@ur8S zf0ewoVF4muLHjvsaWI~b1l$32_#!|?HGPs(8@u=2-3qnSq=VsWUSWC2I zLM2xp6uxaG+qEMwaN=qJhkwb=LnykMvz?FyG{R1;h^-EPsSOM~{u&a7tAp&N!8Mix zubHNwv1m(;f15?6L!AH&Jan}?>mVLG_@Ff9oRfLjfmAwk@}fq{VBFG(<1-qrJIqZD zB|q^JGzLY_b9MBDHBVodUg}*fw!D#Y$M5v{2D)rOAln7!MiLchJZ{NmT+?p|{RL{+|6)Yn zeI+JUZn)ro!JTJh$+A;De=bhxh7(xH9G}Cwyl-kOG@{__9@%e|`QPc^ibAMHW-?Xp zc@Abo(#`*qq`mo%hqbT;htT!n|1GRFvT}2$GD=h|@3=;kM3y~0Z=VnXZ_uSl^nYOX&yW07khPtQ9lB+E|4?9WPE8HIvFhd0gjd8}1?!ZK zU<5UnSH#;fzawcUP9J%&&H44&o5@;1UU_;Gn4HizHg+YED#NZGF*s(YN`*lCPQk0~ zeE@d`2k}-Vldo?S2vrRgVTTW)vf0hht*nbiN?RNBvt#!8Lt#ezumL$IgNB!5-SN_@ zgsNb(=uUe@`C^^bM)s7bE05r|&GIACk^T#RD+4YxBO+YGLEH~VM*dv<96$mKC;B3-_X>;wLN^6?#@ ziTv|J#z%#pq1s%54mQxVVuv5?{o|!qWkg5>y~@(1KOXUcRQ^h6QZy<1#97b|WW{f~ z^Ufy(ih-H>d--KMrF+Tmwc!KPQ(f_-%hPpm8YvZbFAHZLA2?Nh{HDQ%l zQk9ih?qz+-A4q=JgvaVSWA3`69?GUVQu*|Hu9NiZ(x)3NJVC;lI4$~6L*yPqOxkK< zklDQQ^Om1?oB08os$AuyXqhR}=TPD%`&;%*(UBnGqB1u8+{&esr6G+IqU~~%dJWqT z-C2){D4cW4lvsx*qBd(vZ=DTjA*z_PJ|nB%EL7kVIWHbNPqK==y5@DrqnWXo9MY|r)L^8N_{}&pFtNNS~J&dPp*^pfR zezJ}%V>`U|6ZUtE^+v=~nihLH7g zrF#9Nj}og^78NUGI2f#M1KTM?4%K@$+o4D6pKnSp6qJ-$^4B;|>sYO}|x3HsiGjGNyV`^xBkf?)U z0;nUOe_)ta+|Z-i(!*tmU|F?g!{G&s_gu(D$Lh*e1aW60GfEltW+m6Lx8l17x|Y=K z9-GiSk9s*(s+^ux4JF?Ee(5_`B7}r_+9m;P6n4>$!v#0V0z9xN(Qh;!oNDv3V?AU_#>nEQpv7$7cSE8LEc+m-x zSBxdP`*KlWH*I^5IgaK94nME{y!GGt-T#d9R1K=X9yc64+#MgsnVGW|C3}lp#G2FC z$QaaM_c;bJxJNrH0X53V-c}gtA?Rg9r2's dot format. The output location +(directory) to save the graph is set by the +:attr:`~chainer.training.Trainer.out` argument of +:class:`~chainer.training.Trainer`. + +:class:`~chainer.training.extensions.Evaluator` +............................................... + +The :class:`~chainer.dataset.Iterator` that uses the evaluation dataset and the +model object are passed to :class:`~chainer.training.extensions.Evaluator`. +The :class:`~chainer.training.extensions.Evaluator` evaluates the model using +the given dataset at the specified timing interval. + +:class:`~chainer.training.extensions.PrintReport` +................................................. + +:class:`~chainer.Reporter` aggregates the results to output to the standard +output. The timing for displaying the output can be given by the list. + +:class:`~chainer.training.extensions.PlotReport` +................................................ + +:class:`~chainer.training.extensions.PlotReport` plots the values specified by +its arguments, draws the graph and saves the image in the directory set by +:attr:`~chainer.training.extensions.PlotReport.file name`. + +The :class:`~chainer.training.Extension` class has a lot of options other than +those mentioned here. For instance, by using the +:attr:`~chainer.training.Extension.trigger` option, you can set individual +timings to activate the :class:`~chainer.training.Extension` more flexibly. +Please take a look at the official document in more detail: +`Trainer extensions`_. + +7. Start Training +''''''''''''''''' + +To start training, just call :meth:`~chainer.training.Trainer.run` method from +:class:`~chainer.training.Trainer` object. + +.. testcode:: + + trainer.run() + +:: + epoch main/loss main/accuracy validation/main/loss validation/main/accuracy elapsed_time + 1 1.53241 0.638409 0.74935 0.835839 4.93409 + 2 0.578334 0.858059 0.444722 0.882812 7.72883 + 3 0.418569 0.886844 0.364943 0.899229 10.4229 + 4 0.362342 0.899089 0.327569 0.905558 13.148 + 5 0.331067 0.906517 0.304399 0.911788 15.846 + 6 0.309019 0.911964 0.288295 0.917722 18.5395 + 7 0.292312 0.916128 0.272073 0.921776 21.2173 + 8 0.278291 0.92059 0.261351 0.923457 23.9211 + 9 0.266266 0.923541 0.253195 0.927314 26.6612 + 10 0.255489 0.926739 0.242415 0.929094 29.466 + +Let's see the graph of loss saved in the ``mnist_result`` directory. + +.. image:: image/trainer/mnist_loss.png + +How about the accuracy? + +.. image:: image/trainer/mnist_accuracy.png + +Furthermore, let's visualize the computaional graph output by +:meth:`~chainer.training.extensions.dump_graph` of +:class:`~chainer.training.Extension` using Graphviz. + +.. code:: + + dot -Tpng mnist_result/cg.dot -o mnist_result/cg.png + +.. image:: image/trainer/mnist_graph.png + +From the top to the bottom, you can track the data flow of the computations, +how data and paremeters are passed to what type of :class:`~chainer.Function` +and the calculated loss is output. + +8. Evaluate a pre-trained model +''''''''''''''''''''''''''''''' + +.. testcode:: + + from chainer.cuda import to_gpu + from chainer.cuda import to_cpu + + model = MLP() + serializers.load_npz('mnist_result/model_epoch-10', model) + model.to_gpu(gpu_id) + + %matplotlib inline + import matplotlib.pyplot as plt + + x, t = test[0] + plt.imshow(x.reshape(28, 28), cmap='gray') + plt.show() + print('label:', t) + + x = to_gpu(x[None, ...]) + y = model(x) + y = to_cpu(y.data) + + print('predicted_label:', y.argmax(axis=1)[0]) + +.. image:: image/trainer/mnist_graph.png + +.. bash:: + label: 7 + predicted_label: 7 + +It successfully executed !! From af48e852818419738d99d1d405d65f38f639a39a Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Mon, 24 Apr 2017 08:54:03 +0900 Subject: [PATCH 02/16] Fix some bash output part --- docs/source/tutorial/trainer.rst | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/source/tutorial/trainer.rst b/docs/source/tutorial/trainer.rst index cded56d8577e..26a772ff0b2a 100644 --- a/docs/source/tutorial/trainer.rst +++ b/docs/source/tutorial/trainer.rst @@ -69,7 +69,7 @@ Here, we are going to use the same model as before. :class:`~chainer.tarining.Trainer` is a class that holds all of the necessary components needed for training. The main components are shown below. -.. image:: image/trainer/trainer.png +.. image:: ../../image/trainer/trainer.png Basically, all you need to pass to :class:`~chainer.training.Trainer` is an :class:`~chainer.training.Updator`. However, :class:`~chainer.training.Updator` @@ -145,8 +145,7 @@ the training will not stop automatically. .. testcode:: # Send Updater to Trainer - trainer = training.Trainer(updater, (max_epoch, 'epoch'), - out='mnist_result') + trainer = training.Trainer(updater, (max_epoch, 'epoch'), out='mnist_result') The :attr:`~chainer.training.Trainer.out` argument in the :class:`~chainer.training.Trainer` will set up an output directory to save the @@ -270,6 +269,7 @@ To start training, just call :meth:`~chainer.training.Trainer.run` method from trainer.run() :: + epoch main/loss main/accuracy validation/main/loss validation/main/accuracy elapsed_time 1 1.53241 0.638409 0.74935 0.835839 4.93409 2 0.578334 0.858059 0.444722 0.882812 7.72883 @@ -284,21 +284,21 @@ To start training, just call :meth:`~chainer.training.Trainer.run` method from Let's see the graph of loss saved in the ``mnist_result`` directory. -.. image:: image/trainer/mnist_loss.png +.. image:: ../../image/trainer/mnist_loss.png How about the accuracy? -.. image:: image/trainer/mnist_accuracy.png +.. image:: ../../image/trainer/mnist_accuracy.png Furthermore, let's visualize the computaional graph output by :meth:`~chainer.training.extensions.dump_graph` of :class:`~chainer.training.Extension` using Graphviz. -.. code:: +:: - dot -Tpng mnist_result/cg.dot -o mnist_result/cg.png + % dot -Tpng mnist_result/cg.dot -o mnist_result/cg.png -.. image:: image/trainer/mnist_graph.png +.. image:: ../../image/trainer/mnist_graph.png From the top to the bottom, you can track the data flow of the computations, how data and paremeters are passed to what type of :class:`~chainer.Function` @@ -330,9 +330,10 @@ and the calculated loss is output. print('predicted_label:', y.argmax(axis=1)[0]) -.. image:: image/trainer/mnist_graph.png +.. image:: ../../image/trainer/mnist_output.png + +:: -.. bash:: label: 7 predicted_label: 7 From 745411a54303afce9a49267daf22e27d1139497c Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Mon, 15 May 2017 14:26:56 +0900 Subject: [PATCH 03/16] Fix --- docs/source/tutorial/trainer.rst | 58 +++++++++++++++----------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/docs/source/tutorial/trainer.rst b/docs/source/tutorial/trainer.rst index 26a772ff0b2a..528f52820f85 100644 --- a/docs/source/tutorial/trainer.rst +++ b/docs/source/tutorial/trainer.rst @@ -46,17 +46,17 @@ Here, we are going to use the same model as before. class MLP(Chain): - def __init__(self, n_mid_units=100, n_out=10): - super(MLP, self).__init__( - l1=L.Linear(None, n_mid_units), - l2=L.Linear(None, n_mid_units), - l3=L.Linear(None, n_out), - ) - - def __call__(self, x): - h1 = F.relu(self.l1(x)) - h2 = F.relu(self.l2(h1)) - return self.l3(h2) + def __init__(self, n_mid_units=100, n_out=10): + super(MLP, self).__init__( + l1=L.Linear(None, n_mid_units), + l2=L.Linear(None, n_mid_units), + l3=L.Linear(None, n_out), + ) + + def __call__(self, x): + h1 = F.relu(self.l1(x)) + h2 = F.relu(self.l2(h1)) + return self.l3(h2) gpu_id = 0 @@ -72,20 +72,20 @@ components needed for training. The main components are shown below. .. image:: ../../image/trainer/trainer.png Basically, all you need to pass to :class:`~chainer.training.Trainer` is an -:class:`~chainer.training.Updator`. However, :class:`~chainer.training.Updator` +:class:`~chainer.training.updater`. However, :class:`~chainer.training.updater` contains an :class:`~chainer.training.Iterator` and :class:`~chainer.Optimizer`. Since :class:`~chainer.training.Iterator` can access the dataset and :class:`~chainer.Optimizer` has references to the model, -:class:`~chainer.training.Updator` can update the parameters of models. +:class:`~chainer.training.updater` can update the parameters of models. -So, :class:`~chainer.training.Updator` can perform the training procedure as +So, :class:`~chainer.training.updater` can perform the training procedure as shown below: 1. Retrieve the data from dataset, one batch at a time (:class:`~chainer.dataset.Iterator`) 2. Pass the data to the model and calculate the loss (Model = :attr:`~chainer.Optimizer.target`) 3. Update the parameters of the model (:class:`~chainer.Optimizer`) -Now let's create the :class:`~chainer.training.Updator` object ! +Now let's create the :class:`~chainer.training.updater` object ! .. testcode:: @@ -93,7 +93,7 @@ Now let's create the :class:`~chainer.training.Updator` object ! # Note: If you don't have a GPU, set this to -1 to run on CPU only gpu_id = 0 - # Wrapp your model by Classifier and include the process of loss calculation within your model. + # Wapp your model by Classifier and include the process of loss calculation within your model. # Since we do not specify a loss funciton here, the default 'softmax_cross_entropy' is # used. model = L.Classifier(model) @@ -104,7 +104,7 @@ Now let's create the :class:`~chainer.training.Updator` object ! # Give the optimizer a reference to the model optimizer.setup(model) - # Get an Updator that uses the Iterator and Optimizer + # Get an updater that uses the Iterator and Optimizer updater = training.StandardUpdater(train_iter, optimizer, device=gpu_id) .. note:: @@ -124,10 +124,10 @@ Now let's create the :class:`~chainer.training.Updator` object ! ``L.Classifiler``, the :attr:`~chainer.links.Classifier.lossfun` is set to :meth:`~chainer.functions.softmax_cross_entropy` as default. - :class:`~chainer.training.StandardUpdator` is the simplest class to process - the :class:`~chainer.training.Updator` described above. Other than this - :class:`~chainer.training.StandardUpdator`, there is also a - :class:`~chainer.training.ParallelUpdator` to utilize multiple GPUs. + :class:`~chainer.training.Standardupdater` is the simplest class to process + the :class:`~chainer.training.updater` described above. Other than this + :class:`~chainer.training.Standardupdater`, there is also a + :class:`~chainer.training.Parallelupdater` to utilize multiple GPUs. 5. Setup Trainer '''''''''''''''' @@ -187,7 +187,7 @@ simply pass the desired :class:`~chainer.training.Extension` object to the :class:`~chainer.training.extensions.LogReport` ............................................... -Collect ``loss`` and ``accuracy`` automarically every ``epoch`` or +Collect ``loss`` and ``accuracy`` automatically every ``epoch`` or ``iteration`` and store the information under the ``log`` file in the directory assigned by the :attr:`~chainer.training.Trainer.out` argument of :class:`~chainer.training.Trainer`. @@ -200,7 +200,7 @@ The :meth:`~chainer.training.extensions.snapshot` method saves the every epoch) in the directory assigned by :attr:`~chainer.training.Trainer.out` argument in :class:`~chainer.training.Trainer`. The :class:`~chainer.training.Trainer` object, as mentioned before, has an -:class:`~chainer.training.Updator` which contains an +:class:`~chainer.training.updater` which contains an :class:`~chainer.Optimizer` and a model inside. Therefore, as long as you have the snapshot file, you can use it to come back to the training or make inferences using the previously trained model later. @@ -224,8 +224,8 @@ example code. :meth:`~chainer.training.extensions.dump_graph` ............................................... -This method save the computaional graph of the model. The graph is saved in the -`Graphviz`_'s dot format. The output location +This method save the computational graph of the model. The graph is saved in the +`Graphviz _`s dot format. The output location (directory) to save the graph is set by the :attr:`~chainer.training.Trainer.out` argument of :class:`~chainer.training.Trainer`. @@ -256,7 +256,7 @@ those mentioned here. For instance, by using the :attr:`~chainer.training.Extension.trigger` option, you can set individual timings to activate the :class:`~chainer.training.Extension` more flexibly. Please take a look at the official document in more detail: -`Trainer extensions`_. +`Trainer extensions _`. 7. Start Training ''''''''''''''''' @@ -301,7 +301,7 @@ Furthermore, let's visualize the computaional graph output by .. image:: ../../image/trainer/mnist_graph.png From the top to the bottom, you can track the data flow of the computations, -how data and paremeters are passed to what type of :class:`~chainer.Function` +how data and parameters are passed to what type of :class:`~chainer.Function` and the calculated loss is output. 8. Evaluate a pre-trained model @@ -316,9 +316,7 @@ and the calculated loss is output. serializers.load_npz('mnist_result/model_epoch-10', model) model.to_gpu(gpu_id) - %matplotlib inline - import matplotlib.pyplot as plt - + # Show the output x, t = test[0] plt.imshow(x.reshape(28, 28), cmap='gray') plt.show() From 5011c39298625fba76fd819f9eefadcee62c2edd Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Mon, 15 May 2017 14:32:55 +0900 Subject: [PATCH 04/16] Fix --- docs/source/tutorial/trainer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/trainer.rst b/docs/source/tutorial/trainer.rst index 528f52820f85..53511cbfaf86 100644 --- a/docs/source/tutorial/trainer.rst +++ b/docs/source/tutorial/trainer.rst @@ -242,7 +242,7 @@ the given dataset at the specified timing interval. ................................................. :class:`~chainer.Reporter` aggregates the results to output to the standard -output. The timing for displaying the output can be given by the list. +output. The content for displaying the output can be given by the list. :class:`~chainer.training.extensions.PlotReport` ................................................ From 3dc73cb6f90e8b14ea1f82b945c0df72ed43bc57 Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Mon, 15 May 2017 14:36:23 +0900 Subject: [PATCH 05/16] Fix a link --- docs/source/tutorial/trainer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/trainer.rst b/docs/source/tutorial/trainer.rst index 53511cbfaf86..85b6823bd4f3 100644 --- a/docs/source/tutorial/trainer.rst +++ b/docs/source/tutorial/trainer.rst @@ -13,7 +13,7 @@ dataset. .. note:: Please read the custom training loop tutorial: - :doc:`tutorial/custom_training.rst` before this tutorial. + :doc:`tutorial/train_loop.rst` before this tutorial. 1. Prepare the dataset '''''''''''''''''''''' From 59c5b75add6febb309b0e2e24a005ed5c8a03a92 Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Mon, 15 May 2017 14:52:43 +0900 Subject: [PATCH 06/16] Add matplotlib import --- docs/source/tutorial/trainer.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/tutorial/trainer.rst b/docs/source/tutorial/trainer.rst index 85b6823bd4f3..4436effb063f 100644 --- a/docs/source/tutorial/trainer.rst +++ b/docs/source/tutorial/trainer.rst @@ -309,6 +309,7 @@ and the calculated loss is output. .. testcode:: + import matplotlib.pyplot as plt from chainer.cuda import to_gpu from chainer.cuda import to_cpu From b65bd364c95f87f28a74b46e32e4fdfa0c0972d3 Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Mon, 12 Jun 2017 15:24:54 +0900 Subject: [PATCH 07/16] Fix typos --- docs/source/tutorial/trainer.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/source/tutorial/trainer.rst b/docs/source/tutorial/trainer.rst index 4436effb063f..6329dc1beef2 100644 --- a/docs/source/tutorial/trainer.rst +++ b/docs/source/tutorial/trainer.rst @@ -61,7 +61,7 @@ Here, we are going to use the same model as before. gpu_id = 0 model = MLP() - model.to_gpu(gpu_id) # If you use CPU, comment out this Linear + model.to_gpu(gpu_id) # If you use CPU, comment out this line 4. Prepare the Updater '''''''''''''''''''''' @@ -72,20 +72,20 @@ components needed for training. The main components are shown below. .. image:: ../../image/trainer/trainer.png Basically, all you need to pass to :class:`~chainer.training.Trainer` is an -:class:`~chainer.training.updater`. However, :class:`~chainer.training.updater` +:class:`~chainer.training.Updater`. However, :class:`~chainer.training.Updater` contains an :class:`~chainer.training.Iterator` and :class:`~chainer.Optimizer`. Since :class:`~chainer.training.Iterator` can access the dataset and :class:`~chainer.Optimizer` has references to the model, -:class:`~chainer.training.updater` can update the parameters of models. +:class:`~chainer.training.Updater` can update the parameters of models. -So, :class:`~chainer.training.updater` can perform the training procedure as +So, :class:`~chainer.training.Updater` can perform the training procedure as shown below: 1. Retrieve the data from dataset, one batch at a time (:class:`~chainer.dataset.Iterator`) 2. Pass the data to the model and calculate the loss (Model = :attr:`~chainer.Optimizer.target`) 3. Update the parameters of the model (:class:`~chainer.Optimizer`) -Now let's create the :class:`~chainer.training.updater` object ! +Now let's create the :class:`~chainer.training.Updater` object ! .. testcode:: @@ -93,7 +93,7 @@ Now let's create the :class:`~chainer.training.updater` object ! # Note: If you don't have a GPU, set this to -1 to run on CPU only gpu_id = 0 - # Wapp your model by Classifier and include the process of loss calculation within your model. + # Wrapp your model by Classifier and include the process of loss calculation within your model. # Since we do not specify a loss funciton here, the default 'softmax_cross_entropy' is # used. model = L.Classifier(model) @@ -125,7 +125,7 @@ Now let's create the :class:`~chainer.training.updater` object ! :meth:`~chainer.functions.softmax_cross_entropy` as default. :class:`~chainer.training.Standardupdater` is the simplest class to process - the :class:`~chainer.training.updater` described above. Other than this + the :class:`~chainer.training.Updater` described above. Other than this :class:`~chainer.training.Standardupdater`, there is also a :class:`~chainer.training.Parallelupdater` to utilize multiple GPUs. @@ -200,7 +200,7 @@ The :meth:`~chainer.training.extensions.snapshot` method saves the every epoch) in the directory assigned by :attr:`~chainer.training.Trainer.out` argument in :class:`~chainer.training.Trainer`. The :class:`~chainer.training.Trainer` object, as mentioned before, has an -:class:`~chainer.training.updater` which contains an +:class:`~chainer.training.Updater` which contains an :class:`~chainer.Optimizer` and a model inside. Therefore, as long as you have the snapshot file, you can use it to come back to the training or make inferences using the previously trained model later. From 964cae5150f9dd415106b307f9850b1cb277c226 Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Thu, 22 Jun 2017 13:14:05 +0900 Subject: [PATCH 08/16] Fix the constructor of the model to follow the recommended way to add links to a model in V2 --- docs/source/tutorial/trainer.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/source/tutorial/trainer.rst b/docs/source/tutorial/trainer.rst index 6329dc1beef2..17ec5d6dc5ae 100644 --- a/docs/source/tutorial/trainer.rst +++ b/docs/source/tutorial/trainer.rst @@ -47,18 +47,18 @@ Here, we are going to use the same model as before. class MLP(Chain): def __init__(self, n_mid_units=100, n_out=10): - super(MLP, self).__init__( - l1=L.Linear(None, n_mid_units), - l2=L.Linear(None, n_mid_units), - l3=L.Linear(None, n_out), - ) + super(MLP, self).__init__() + self.init_scope(): + self.l1 = L.Linear(None, n_mid_units) + self.l2 = L.Linear(None, n_mid_units) + self.l3 = L.Linear(None, n_out) def __call__(self, x): h1 = F.relu(self.l1(x)) h2 = F.relu(self.l2(h1)) return self.l3(h2) - gpu_id = 0 + gpu_id = 0 # Set to -1 if you use CPU model = MLP() model.to_gpu(gpu_id) # If you use CPU, comment out this line @@ -91,7 +91,7 @@ Now let's create the :class:`~chainer.training.Updater` object ! max_epoch = 10 # Note: If you don't have a GPU, set this to -1 to run on CPU only - gpu_id = 0 + gpu_id = 0 # Wrapp your model by Classifier and include the process of loss calculation within your model. # Since we do not specify a loss funciton here, the default 'softmax_cross_entropy' is From ff2f87797552be13cb22e419304649e83eb45f45 Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Fri, 14 Jul 2017 16:31:11 +0900 Subject: [PATCH 09/16] Fix the content --- docs/source/tutorial/trainer.rst | 192 +++++++++---------------------- 1 file changed, 55 insertions(+), 137 deletions(-) diff --git a/docs/source/tutorial/trainer.rst b/docs/source/tutorial/trainer.rst index 17ec5d6dc5ae..eae1b08871b4 100644 --- a/docs/source/tutorial/trainer.rst +++ b/docs/source/tutorial/trainer.rst @@ -1,25 +1,18 @@ Let's try using the Trainer feature ``````````````````````````````````` -By using :class:`~chainer.training.Trainer`, you don't need to write the -tedious training loop explicitly any more. Chainer contains several extensions -that can be used with :class:`~chainer.training.Trainer` to visualize your -results, evaluate your model, store and manage log files more easily. +By using :class:`~chainer.training.Trainer`, you don't need to write the tedious training loop explicitly any more. Furthermore, Chainer provides many useful extensions that can be used with :class:`~chainer.training.Trainer` to visualize your results, evaluate your model, store and manage log files more easily. -This example will show how to use the :class:`~chainer.training.Trainer` -feature to train a fully-connected feed-forward neural network on the MNIST -dataset. +This example will show how to use the :class:`~chainer.training.Trainer` to train a fully-connected feed-forward neural network on the MNIST dataset. .. note:: - Please read the custom training loop tutorial: - :doc:`tutorial/train_loop.rst` before this tutorial. + If you would like to know how to write a training loop without using this functionality, please check :doc:`tutorial/train_loop.rst` instead of this tutorial. 1. Prepare the dataset '''''''''''''''''''''' -Load the MNIST dataset, which contains a training set of images and class -labels as well as a corresponding test set. +Load the MNIST dataset, which contains a training set of images and class labels as well as a corresponding test set. .. testcode:: @@ -30,6 +23,8 @@ labels as well as a corresponding test set. 2. Prepare the dataset iterations ''''''''''''''''''''''''''''''''' +:class:`~chainer.training.Iterator` creates a mini-batch from the given dataset. + .. testcode:: batchsize = 128 @@ -40,7 +35,7 @@ labels as well as a corresponding test set. 3. Prepare the model '''''''''''''''''''' -Here, we are going to use the same model as before. +Here, we are going to use the same model as :doc:`tutorial/train_loop.rst`. .. testcode:: @@ -66,23 +61,16 @@ Here, we are going to use the same model as before. 4. Prepare the Updater '''''''''''''''''''''' -:class:`~chainer.tarining.Trainer` is a class that holds all of the necessary -components needed for training. The main components are shown below. +:class:`~chainer.tarining.Trainer` is a class that holds all of the necessary components needed for training. The main components are shown below. .. image:: ../../image/trainer/trainer.png -Basically, all you need to pass to :class:`~chainer.training.Trainer` is an -:class:`~chainer.training.Updater`. However, :class:`~chainer.training.Updater` -contains an :class:`~chainer.training.Iterator` and -:class:`~chainer.Optimizer`. Since :class:`~chainer.training.Iterator` can -access the dataset and :class:`~chainer.Optimizer` has references to the model, -:class:`~chainer.training.Updater` can update the parameters of models. +Basically, all you need to pass to :class:`~chainer.training.Trainer` is an :class:`~chainer.training.Updater`. However, :class:`~chainer.training.Updater` contains an :class:`~chainer.training.Iterator` and :class:`~chainer.Optimizer`. Since :class:`~chainer.training.Iterator` can access the dataset and :class:`~chainer.Optimizer` has references to the model, :class:`~chainer.training.Updater` can access to the model to update its parameters. -So, :class:`~chainer.training.Updater` can perform the training procedure as -shown below: +So, :class:`~chainer.training.Updater` can perform the training procedure as shown below: -1. Retrieve the data from dataset, one batch at a time (:class:`~chainer.dataset.Iterator`) -2. Pass the data to the model and calculate the loss (Model = :attr:`~chainer.Optimizer.target`) +1. Retrieve the data from dataset and construct a mini-batch (:class:`~chainer.dataset.Iterator`) +2. Pass the mini-batch to the model and calculate the loss 3. Update the parameters of the model (:class:`~chainer.Optimizer`) Now let's create the :class:`~chainer.training.Updater` object ! @@ -90,88 +78,59 @@ Now let's create the :class:`~chainer.training.Updater` object ! .. testcode:: max_epoch = 10 - # Note: If you don't have a GPU, set this to -1 to run on CPU only - gpu_id = 0 # Wrapp your model by Classifier and include the process of loss calculation within your model. - # Since we do not specify a loss funciton here, the default 'softmax_cross_entropy' is - # used. + # Since we do not specify a loss funciton here, the default 'softmax_cross_entropy' is used. model = L.Classifier(model) - model.to_gpu(gpu_id) # selection of your optimizing method - optimizer = optimizers.SGD() + optimizer = optimizers.MomentumSGD() + # Give the optimizer a reference to the model optimizer.setup(model) # Get an updater that uses the Iterator and Optimizer - updater = training.StandardUpdater(train_iter, optimizer, device=gpu_id) + updater = training.StandardUpdater(train_iter, optimizer) .. note:: - Here, the model defined above is passed to - ``L.Classifier`` and changed to a new :class:`~chainer.Chain` class model. - ``L.Classifier``, which in fact inherits from the :class:`~chainer.Chain` - class, keeps the :class:`~chainer.Chain` model in its - :attr:`~chainer.links.Classifier.predictor` attribute. Once you give input - data and corresponding output class labels to the model by the - ``()`` accessor, :meth:`__call__` of the model is invoked. The data is then - given to :attr:`~chainer.links.Classifier.predictor` to obtain the output - ``y``. Next, together with the label data, the output ``y`` will be passed - to the loss function which is assigned by - :attr:`~chainer.links.Classifier.lossfun` argument in the constructor and - the ouput will be returned as a :class:`~chainer.Variable`. In - ``L.Classifiler``, the :attr:`~chainer.links.Classifier.lossfun` is set to + Here, the model defined above is passed to :class:`~chainer.links.Classifier` and changed to a new :class:`~chainer.Chain`. :class:`~chainer.links.Classifier`, which in fact inherits from the :class:`~chainer.Chain` class, keeps the :class:`~chainer.Chain` model in its :attr:`~chainer.links.Classifier.predictor` attribute. Once you give the input data and the corresponding class labels to the model by the ``()`` accessor, + + 1. :meth:`__call__` of the model is invoked. The data is then given to :attr:`~chainer.links.Classifier.predictor` to obtain the output ``y``. + 2. Next, together with the given labels, the output ``y`` is passed to the loss function which is determined by :attr:`~chainer.links.Classifier.lossfun` argument in the constructor. + 3. The loss is returned as a :class:`~chainer.Variable`. + + In :class:`~chianer.links.Classifiler`, the :attr:`~chainer.links.Classifier.lossfun` is set to :meth:`~chainer.functions.softmax_cross_entropy` as default. - :class:`~chainer.training.Standardupdater` is the simplest class to process - the :class:`~chainer.training.Updater` described above. Other than this - :class:`~chainer.training.Standardupdater`, there is also a - :class:`~chainer.training.Parallelupdater` to utilize multiple GPUs. + :class:`~chainer.training.Standardupdater` is the simplest class among several updaters. There are also the :class:`~chainer.training.Parallelupdater` and the :class:`~chainer.training.updaters.MultiprocessParallelUpdater` to utilize multiple GPUs. 5. Setup Trainer '''''''''''''''' -Lastly, we will setup :class:`~chainer.training.Trainer`. The only requirement -for creating a :class:`~chainer.training.Trainer` is to pass the -:class:`~chainer.training.Updater` that we previously created above. You can -also pass a :attr:`~chainer.training.Trainer.stop_trigger` to the second -trainer argument as a tuple, ``(length, unit)`` to tell the trainer stop -automatically according to your indicated timing. The ``length`` is given as an -arbitrary integer, The ``unit`` is given as a string, by selecting ``epoch`` or -``iteration``. Without setting :attr:`~chainer.training.Trainer.stop_trigger`, -the training will not stop automatically. +Lastly, we will setup :class:`~chainer.training.Trainer`. The only requirement for creating a :class:`~chainer.training.Trainer` is to pass the :class:`~chainer.training.Updater` object that we previously created above. You can also pass a :attr:`~chainer.training.Trainer.stop_trigger` to the second trainer argument as a tuple like ``(length, unit)`` to tell the trainer when to stop the training. The ``length`` is given as an integer and the ``unit`` is given as a string which should be either ``epoch`` or ``iteration``. Without setting :attr:`~chainer.training.Trainer.stop_trigger`, the training will never be stopped. .. testcode:: - # Send Updater to Trainer + # Setup a Trainer trainer = training.Trainer(updater, (max_epoch, 'epoch'), out='mnist_result') -The :attr:`~chainer.training.Trainer.out` argument in the -:class:`~chainer.training.Trainer` will set up an output directory to save the -log files, the image files of graphs to show the time progress of loss, -accuracy, etc. Next, we will explain how to display/save those outputs by using -:class:`~chainer.training.Extension`. +The :attr:`~chainer.training.Trainer.out` argument specifies an output directory used to save the +log files, the image files of graphs to show the time progress of loss, accuracy, etc. Next, we will explain how to display or save those information by using :class:`~chainer.training.Extension`. +6. Add Extensions to the Trainer object +''''''''''''''''''''''''''''''''''''''' -6. Add Extensions to Trainer -'''''''''''''''''''''''''''' - -The :class:`~chainer.training.Trainer` extensions provide the following -capabilites: +The :class:`~chainer.training.Trainer` extensions provide the following capabilites: * Save log files automatically (:class:`~chainer.training.extensions.LogReport`) * Display the training information to the terminal periodically (:class:`~chainer.training.extensions.PrintReport`) -* Visualize the loss progress by plottig a graph periodically and save its image (:class:`~chainer.training.extensions.PlotReport`) -* Automatically serialize the model or the state of Optimizer periodically (:meth:`~chainer.training.extensions.snapshot` / :meth:`~chainer.training.extensions.snapshot_object`) -* Display Progress Bar to show the progress of training (:class:`~chainer.training.extensions.ProgressBar`) -* Save the model architechture as a dot format readable by Graphviz (:meth:`~chainer.training.extensions.dump_graph`) +* Visualize the loss progress by plottig a graph periodically and save it as an image file (:class:`~chainer.training.extensions.PlotReport`) +* Automatically serialize the state periodically (:meth:`~chainer.training.extensions.snapshot` / :meth:`~chainer.training.extensions.snapshot_object`) +* Display a progress bar to the terminal to show the progress of training (:class:`~chainer.training.extensions.ProgressBar`) +* Save the model architechture as a Graphviz's dot file (:meth:`~chainer.training.extensions.dump_graph`) -Now you can utilize the wide variety of tools shown above right away! To do so, -simply pass the desired :class:`~chainer.training.Extension` object to the -:class:`~chainer.training.Trainer` object by using the -:meth:`~chainer.training.Trainer.extend` method of -:class:`~chainer.training.Trainer`. +To use these wide variety of tools for your tarining task, pass :class:`~chainer.training.Extension` objects to the :meth:`~chainer.training.Trainer.extend` method of your :class:`~chainer.training.Trainer` object. .. testcode:: @@ -187,82 +146,48 @@ simply pass the desired :class:`~chainer.training.Extension` object to the :class:`~chainer.training.extensions.LogReport` ............................................... -Collect ``loss`` and ``accuracy`` automatically every ``epoch`` or -``iteration`` and store the information under the ``log`` file in the directory -assigned by the :attr:`~chainer.training.Trainer.out` argument of -:class:`~chainer.training.Trainer`. +Collect ``loss`` and ``accuracy`` automatically every ``epoch`` or ``iteration`` and store the information under the ``log`` file in the directory specified by the :attr:`~chainer.training.Trainer.out` argument when you create a :class:`~chainer.training.Trainer` object. :meth:`~chainer.training.extensions.snapshot` ............................................. -The :meth:`~chainer.training.extensions.snapshot` method saves the -:class:`~chainer.training.Trainer` object at the designated timing (defaut: -every epoch) in the directory assigned by :attr:`~chainer.training.Trainer.out` -argument in :class:`~chainer.training.Trainer`. The -:class:`~chainer.training.Trainer` object, as mentioned before, has an -:class:`~chainer.training.Updater` which contains an -:class:`~chainer.Optimizer` and a model inside. Therefore, as long as you have -the snapshot file, you can use it to come back to the training or make -inferences using the previously trained model later. +The :meth:`~chainer.training.extensions.snapshot` method saves the :class:`~chainer.training.Trainer` object at the designated timing (defaut: every epoch) in the directory specified by :attr:`~chainer.training.Trainer.out`. The :class:`~chainer.training.Trainer` object, as mentioned before, has an :class:`~chainer.training.Updater` which contains an :class:`~chainer.Optimizer` and a model inside. Therefore, as long as you have the snapshot file, you can use it to come back to the training or make inferences using the previously trained model later. :meth:`~chainer.training.extensions.snapshot_object` .................................................... -However, when you keep the whole :class:`~chainer.training.Trainer` object, in -some cases, it is very tedious to retrieve only the inside of the model. By -using :meth:`~chainer.training.extensions.snapshot_object`, you can save the -particular object (in this case, the model wrapped by -:class:`~chainer.links.Classifier`) in addition to saving the -:class:`~chainer.training.Trainer` object. :class:`~chainer.links.Classifier` -is a :class:`~chainer.Chain` object which keeps the :class:`~chainer.Chain` -object given by the first argument as a property called -:attr:`~chainer.links.Classifier.predictor` and calculate the loss. -:class:`~chainer.links.Classifier` doesn't have any parameters other than those -inside its predictor model, so we only keep ``model.predictor`` in the above -example code. +However, when you keep the whole :class:`~chainer.training.Trainer` object, in some cases, it is very tedious to retrieve only the inside of the model. By using :meth:`~chainer.training.extensions.snapshot_object`, you can save the particular object (in this case, the model wrapped by :class:`~chainer.links.Classifier`) as a separeted snapshot. :class:`~chainer.links.Classifier` is a :class:`~chainer.Chain` object which keeps the model that is also a :class:`~chainer.Chain` object as its :attr:`~chainer.links.Classifier.predictor` property, and all the parameters are under the :attr:`~chainer.links.Classifier.predictor`, so taking the snapshot of :attr:`~chainer.links.Classifier.predictor` is enough to keep all the trained parameters. :meth:`~chainer.training.extensions.dump_graph` ............................................... -This method save the computational graph of the model. The graph is saved in the -`Graphviz _`s dot format. The output location -(directory) to save the graph is set by the -:attr:`~chainer.training.Trainer.out` argument of -:class:`~chainer.training.Trainer`. +This method save the structure of the computational graph of the model. The graph is saved in the +`Graphviz _`s dot format. The output location (directory) to save the graph is set by the :attr:`~chainer.training.Trainer.out` argument of :class:`~chainer.training.Trainer`. :class:`~chainer.training.extensions.Evaluator` ............................................... -The :class:`~chainer.dataset.Iterator` that uses the evaluation dataset and the -model object are passed to :class:`~chainer.training.extensions.Evaluator`. -The :class:`~chainer.training.extensions.Evaluator` evaluates the model using -the given dataset at the specified timing interval. +The :class:`~chainer.dataset.Iterator` that uses the evaluation dataset and the model object are required to use :class:`~chainer.training.extensions.Evaluator`. It evaluates the model using the given dataset (typically it's a validation dataset) at the specified timing interval. :class:`~chainer.training.extensions.PrintReport` ................................................. -:class:`~chainer.Reporter` aggregates the results to output to the standard -output. The content for displaying the output can be given by the list. +It outputs the spcified values to the standard output. :class:`~chainer.training.extensions.PlotReport` ................................................ -:class:`~chainer.training.extensions.PlotReport` plots the values specified by -its arguments, draws the graph and saves the image in the directory set by -:attr:`~chainer.training.extensions.PlotReport.file name`. +:class:`~chainer.training.extensions.PlotReport` plots the values specified by its arguments saves it as a image file which has the same naem as the :attr:`~chainer.training.extensions.PlotReport.file_name` argument. + +--- -The :class:`~chainer.training.Extension` class has a lot of options other than -those mentioned here. For instance, by using the -:attr:`~chainer.training.Extension.trigger` option, you can set individual -timings to activate the :class:`~chainer.training.Extension` more flexibly. -Please take a look at the official document in more detail: -`Trainer extensions _`. +Each :class:`~chainer.training.Extension` class has different options and some extensions are not mentioned here. And one of other important feature is, for instance, by using the :attr:`~chainer.training.Extension.trigger` option, you can set individual timings to fire the :class:`~chainer.training.Extension`. To know more details of all extensions, please take a look at the official document: `Trainer extensions _`. 7. Start Training ''''''''''''''''' -To start training, just call :meth:`~chainer.training.Trainer.run` method from -:class:`~chainer.training.Trainer` object. +Just call :meth:`~chainer.training.Trainer.run` method from +:class:`~chainer.training.Trainer` object to start training. .. testcode:: @@ -282,7 +207,7 @@ To start training, just call :meth:`~chainer.training.Trainer.run` method from 9 0.266266 0.923541 0.253195 0.927314 26.6612 10 0.255489 0.926739 0.242415 0.929094 29.466 -Let's see the graph of loss saved in the ``mnist_result`` directory. +Let's see the plot of loss progress saved in the ``mnist_result`` directory. .. image:: ../../image/trainer/mnist_loss.png @@ -290,9 +215,7 @@ How about the accuracy? .. image:: ../../image/trainer/mnist_accuracy.png -Furthermore, let's visualize the computaional graph output by -:meth:`~chainer.training.extensions.dump_graph` of -:class:`~chainer.training.Extension` using Graphviz. +Furthermore, let's visualize the computaional graph saved with :meth:`~chainer.training.extensions.dump_graph` using Graphviz. :: @@ -300,22 +223,19 @@ Furthermore, let's visualize the computaional graph output by .. image:: ../../image/trainer/mnist_graph.png -From the top to the bottom, you can track the data flow of the computations, -how data and parameters are passed to what type of :class:`~chainer.Function` -and the calculated loss is output. +From the top to the bottom, you can see the data flow in the computational graph. It basically shows how data and parameters are passed to the :class:`~chainer.Function` s. 8. Evaluate a pre-trained model ''''''''''''''''''''''''''''''' +Evaluation using the snapshot of a model is as easy as what explained in the :doc:`tutorial/train_loop.rst`. + .. testcode:: import matplotlib.pyplot as plt - from chainer.cuda import to_gpu - from chainer.cuda import to_cpu model = MLP() serializers.load_npz('mnist_result/model_epoch-10', model) - model.to_gpu(gpu_id) # Show the output x, t = test[0] @@ -323,9 +243,7 @@ and the calculated loss is output. plt.show() print('label:', t) - x = to_gpu(x[None, ...]) y = model(x) - y = to_cpu(y.data) print('predicted_label:', y.argmax(axis=1)[0]) @@ -336,4 +254,4 @@ and the calculated loss is output. label: 7 predicted_label: 7 -It successfully executed !! +The prediction looks correct. Yatta! From a8956ea7d3a752a496047a7acc633dd3215dcb74 Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Fri, 14 Jul 2017 16:39:06 +0900 Subject: [PATCH 10/16] Add a description about a Python list --- docs/source/tutorial/trainer.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/source/tutorial/trainer.rst b/docs/source/tutorial/trainer.rst index eae1b08871b4..4667998c3dd0 100644 --- a/docs/source/tutorial/trainer.rst +++ b/docs/source/tutorial/trainer.rst @@ -20,6 +20,17 @@ Load the MNIST dataset, which contains a training set of images and class labels train, test = mnist.get_mnist() +.. note:: + + **You can use a Python list as a dataset.** Because all types of objects whose element can be accessed via ``[]`` accessor and lengh can be obtained with ``len()`` function, can be used as a dataset given to the :class:`~chainer.training.Iterator`. For example, + + .. code-block:: python + + train = [(x1, t1), (x2, t2), ...] + + a list of tuples like this can also be used equally to a :class:`~chainer.dataset.DatasetMixin` object. But many useful :mod:`~chainer.dataset` classes enable to avoid storing all data on the memory at a time, so it's better to use them for large datasets. + + 2. Prepare the dataset iterations ''''''''''''''''''''''''''''''''' From 5029deda0f775be29e1dd3d3acb3f24354c40e0e Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Mon, 7 Aug 2017 11:20:08 +0900 Subject: [PATCH 11/16] Fix link --- docs/source/tutorial/index.rst | 1 + docs/source/tutorial/train.rst | 8 ++++++++ docs/source/tutorial/trainer.rst | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 docs/source/tutorial/train.rst diff --git a/docs/source/tutorial/index.rst b/docs/source/tutorial/index.rst index 9f7c65d3d2fd..20224e3269ca 100644 --- a/docs/source/tutorial/index.rst +++ b/docs/source/tutorial/index.rst @@ -6,6 +6,7 @@ Chainer Tutorial basic writenet + train gpu function type_check diff --git a/docs/source/tutorial/train.rst b/docs/source/tutorial/train.rst new file mode 100644 index 000000000000..e7e6fbef66fa --- /dev/null +++ b/docs/source/tutorial/train.rst @@ -0,0 +1,8 @@ +How to Train a Network +------------------------- + +.. toctree:: + :maxdepth: 2 + + train_loop + trainer diff --git a/docs/source/tutorial/trainer.rst b/docs/source/tutorial/trainer.rst index 4667998c3dd0..3484ad91756d 100644 --- a/docs/source/tutorial/trainer.rst +++ b/docs/source/tutorial/trainer.rst @@ -22,7 +22,7 @@ Load the MNIST dataset, which contains a training set of images and class labels .. note:: - **You can use a Python list as a dataset.** Because all types of objects whose element can be accessed via ``[]`` accessor and lengh can be obtained with ``len()`` function, can be used as a dataset given to the :class:`~chainer.training.Iterator`. For example, + **You can use a Python list as a dataset.** Because all types of objects whose element can be accessed via ``[]`` accessor and lengh can be obtained with ``len()`` function, can be used as a dataset given to the :class:`~chainer.dataset.Iterator`. For example, .. code-block:: python From a023d4f55a795e9663886639afa9770b2a1ee979 Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Mon, 7 Aug 2017 11:31:12 +0900 Subject: [PATCH 12/16] Fix links --- .gitignore | 3 +++ docs/source/tutorial/trainer.rst | 10 ++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index abc9ee4ffad1..70ea36df0ff8 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ chainer.egg-info/ dist/ htmlcov/ .idea/ +docs/source/reference/core +docs/source/reference/generated +docs/source/reference/util diff --git a/docs/source/tutorial/trainer.rst b/docs/source/tutorial/trainer.rst index 3484ad91756d..0c79c1ba3b13 100644 --- a/docs/source/tutorial/trainer.rst +++ b/docs/source/tutorial/trainer.rst @@ -28,13 +28,15 @@ Load the MNIST dataset, which contains a training set of images and class labels train = [(x1, t1), (x2, t2), ...] - a list of tuples like this can also be used equally to a :class:`~chainer.dataset.DatasetMixin` object. But many useful :mod:`~chainer.dataset` classes enable to avoid storing all data on the memory at a time, so it's better to use them for large datasets. + a list of tuples like this can also be used equally to a :class:`~chainer.dataset.DatasetMixin` object. + + But many useful abstracted :mod:`~chainer.datasets` enable to avoid storing all data on the memory at a time, so it's better to use them for large datasets. For example, :class:`~chainer.datasets.ImageDataset` takes paths to image files as its argument, and just keep the list in the dataset object. It means the actual image data will be loaded from disks using given paths when :meth:`~chainer.datasets.ImageDataset.__getitem__` is called. Until then, no images are loaded to the memory, so it can save the memory consumption. 2. Prepare the dataset iterations ''''''''''''''''''''''''''''''''' -:class:`~chainer.training.Iterator` creates a mini-batch from the given dataset. +:class:`~chainer.dataset.Iterator` creates a mini-batch from the given dataset. .. testcode:: @@ -46,7 +48,7 @@ Load the MNIST dataset, which contains a training set of images and class labels 3. Prepare the model '''''''''''''''''''' -Here, we are going to use the same model as :doc:`tutorial/train_loop.rst`. +Here, we are going to use the same model as defined in :doc:`tutorial/train_loop.rst`. .. testcode:: @@ -76,7 +78,7 @@ Here, we are going to use the same model as :doc:`tutorial/train_loop.rst`. .. image:: ../../image/trainer/trainer.png -Basically, all you need to pass to :class:`~chainer.training.Trainer` is an :class:`~chainer.training.Updater`. However, :class:`~chainer.training.Updater` contains an :class:`~chainer.training.Iterator` and :class:`~chainer.Optimizer`. Since :class:`~chainer.training.Iterator` can access the dataset and :class:`~chainer.Optimizer` has references to the model, :class:`~chainer.training.Updater` can access to the model to update its parameters. +Basically, all you need to pass to :class:`~chainer.training.Trainer` is an :class:`~chainer.training.Updater`. However, :class:`~chainer.training.Updater` contains an :class:`~chainer.dataset.Iterator` and :class:`~chainer.Optimizer`. Since :class:`~chainer.dataset.Iterator` can access the dataset and :class:`~chainer.Optimizer` has references to the model, :class:`~chainer.training.Updater` can access to the model to update its parameters. So, :class:`~chainer.training.Updater` can perform the training procedure as shown below: From 534a96e3065caf6ef7ca362c8594f5da7b209ffc Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Mon, 7 Aug 2017 11:53:05 +0900 Subject: [PATCH 13/16] Fix some typos --- docs/source/tutorial/trainer.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/source/tutorial/trainer.rst b/docs/source/tutorial/trainer.rst index 0c79c1ba3b13..775c4b547533 100644 --- a/docs/source/tutorial/trainer.rst +++ b/docs/source/tutorial/trainer.rst @@ -107,16 +107,16 @@ Now let's create the :class:`~chainer.training.Updater` object ! .. note:: - Here, the model defined above is passed to :class:`~chainer.links.Classifier` and changed to a new :class:`~chainer.Chain`. :class:`~chainer.links.Classifier`, which in fact inherits from the :class:`~chainer.Chain` class, keeps the :class:`~chainer.Chain` model in its :attr:`~chainer.links.Classifier.predictor` attribute. Once you give the input data and the corresponding class labels to the model by the ``()`` accessor, + Here, the model defined above is passed to :class:`~chainer.links.Classifier` and changed to a new :class:`~chainer.Chain`. :class:`~chainer.links.Classifier`, which in fact inherits from the :class:`~chainer.Chain` class, keeps the given :class:`~chainer.Chain` model in its :attr:`~chainer.links.Classifier.predictor` attribute. Once you give the input data and the corresponding class labels to the model by the ``()`` accessor, - 1. :meth:`__call__` of the model is invoked. The data is then given to :attr:`~chainer.links.Classifier.predictor` to obtain the output ``y``. - 2. Next, together with the given labels, the output ``y`` is passed to the loss function which is determined by :attr:`~chainer.links.Classifier.lossfun` argument in the constructor. + 1. :meth:`~chainer.links.Classifier.__call__` of the model is invoked. The data is then given to :attr:`~chainer.links.Classifier.predictor` to obtain the output ``y``. + 2. Next, together with the given labels, the output ``y`` is passed to the loss function which is determined by :attr:`~chainer.links.Classifier.lossfun` argument in the constructor of :class:`~chainer.links.Classifier`. 3. The loss is returned as a :class:`~chainer.Variable`. - In :class:`~chianer.links.Classifiler`, the :attr:`~chainer.links.Classifier.lossfun` is set to + In :class:`~chainer.links.Classifiler`, the :attr:`~chainer.links.Classifier.lossfun` is set to :meth:`~chainer.functions.softmax_cross_entropy` as default. - :class:`~chainer.training.Standardupdater` is the simplest class among several updaters. There are also the :class:`~chainer.training.Parallelupdater` and the :class:`~chainer.training.updaters.MultiprocessParallelUpdater` to utilize multiple GPUs. + :class:`~chainer.training.StandardUpdater` is the simplest class among several updaters. There are also the :class:`~chainer.training.ParallelUpdater` and the :class:`~chainer.training.updaters.MultiprocessParallelUpdater` to utilize multiple GPUs. 5. Setup Trainer '''''''''''''''' @@ -129,7 +129,7 @@ Lastly, we will setup :class:`~chainer.training.Trainer`. The only requirement f trainer = training.Trainer(updater, (max_epoch, 'epoch'), out='mnist_result') The :attr:`~chainer.training.Trainer.out` argument specifies an output directory used to save the -log files, the image files of graphs to show the time progress of loss, accuracy, etc. Next, we will explain how to display or save those information by using :class:`~chainer.training.Extension`. +log files, the image files of plots to show the time progress of loss, accuracy, etc. when you use :class:`~chainer.training.extensions.PlotReport` extension. Next, we will explain how to display or save those information by using trainer :class:`~chainer.training.Extension`. 6. Add Extensions to the Trainer object ''''''''''''''''''''''''''''''''''''''' From 242a39191ad4f5f624c92d4586b8431440ca93bf Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Mon, 7 Aug 2017 14:46:40 +0900 Subject: [PATCH 14/16] Fix typo --- docs/source/tutorial/trainer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/tutorial/trainer.rst b/docs/source/tutorial/trainer.rst index 775c4b547533..299dca2997af 100644 --- a/docs/source/tutorial/trainer.rst +++ b/docs/source/tutorial/trainer.rst @@ -192,7 +192,7 @@ It outputs the spcified values to the standard output. :class:`~chainer.training.extensions.PlotReport` plots the values specified by its arguments saves it as a image file which has the same naem as the :attr:`~chainer.training.extensions.PlotReport.file_name` argument. ---- +---- Each :class:`~chainer.training.Extension` class has different options and some extensions are not mentioned here. And one of other important feature is, for instance, by using the :attr:`~chainer.training.Extension.trigger` option, you can set individual timings to fire the :class:`~chainer.training.Extension`. To know more details of all extensions, please take a look at the official document: `Trainer extensions _`. From faca33781b79b529113b25538faf021f1dabfd1a Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Mon, 7 Aug 2017 15:01:59 +0900 Subject: [PATCH 15/16] Fix doctest errors --- docs/source/tutorial/trainer.rst | 42 +++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/docs/source/tutorial/trainer.rst b/docs/source/tutorial/trainer.rst index 299dca2997af..d8f1e5dede42 100644 --- a/docs/source/tutorial/trainer.rst +++ b/docs/source/tutorial/trainer.rst @@ -38,6 +38,10 @@ Load the MNIST dataset, which contains a training set of images and class labels :class:`~chainer.dataset.Iterator` creates a mini-batch from the given dataset. +.. testsetup:: * + + train, test = mnist.get_mnist() + .. testcode:: batchsize = 128 @@ -56,7 +60,7 @@ Here, we are going to use the same model as defined in :doc:`tutorial/train_loop def __init__(self, n_mid_units=100, n_out=10): super(MLP, self).__init__() - self.init_scope(): + with self.init_scope(): self.l1 = L.Linear(None, n_mid_units) self.l2 = L.Linear(None, n_mid_units) self.l3 = L.Linear(None, n_out) @@ -88,6 +92,31 @@ So, :class:`~chainer.training.Updater` can perform the training procedure as sho Now let's create the :class:`~chainer.training.Updater` object ! +.. testsetup:: * + + from chainer.datasets import mnist + + class MLP(Chain): + + def __init__(self, n_mid_units=100, n_out=10): + super(MLP, self).__init__() + with self.init_scope(): + self.l1 = L.Linear(None, n_mid_units) + self.l2 = L.Linear(None, n_mid_units) + self.l3 = L.Linear(None, n_out) + + def __call__(self, x): + h1 = F.relu(self.l1(x)) + h2 = F.relu(self.l2(h1)) + return self.l3(h2) + + model = MLP() + + batchsize = 128 + + train_iter = iterators.SerialIterator(train, batchsize) + test_iter = iterators.SerialIterator(test, batchsize, False, False) + .. testcode:: max_epoch = 10 @@ -123,6 +152,13 @@ Now let's create the :class:`~chainer.training.Updater` object ! Lastly, we will setup :class:`~chainer.training.Trainer`. The only requirement for creating a :class:`~chainer.training.Trainer` is to pass the :class:`~chainer.training.Updater` object that we previously created above. You can also pass a :attr:`~chainer.training.Trainer.stop_trigger` to the second trainer argument as a tuple like ``(length, unit)`` to tell the trainer when to stop the training. The ``length`` is given as an integer and the ``unit`` is given as a string which should be either ``epoch`` or ``iteration``. Without setting :attr:`~chainer.training.Trainer.stop_trigger`, the training will never be stopped. +.. testsetup:: * + + model = L.Classifier(model) + optimizer = optimizers.MomentumSGD() + optimizer.setup(model) + updater = training.StandardUpdater(train_iter, optimizer) + .. testcode:: # Setup a Trainer @@ -202,7 +238,7 @@ Each :class:`~chainer.training.Extension` class has different options and some e Just call :meth:`~chainer.training.Trainer.run` method from :class:`~chainer.training.Trainer` object to start training. -.. testcode:: +.. code-block:: python trainer.run() @@ -243,7 +279,7 @@ From the top to the bottom, you can see the data flow in the computational graph Evaluation using the snapshot of a model is as easy as what explained in the :doc:`tutorial/train_loop.rst`. -.. testcode:: +.. code-block:: python import matplotlib.pyplot as plt From 243976d4c014619ed95f71a77d579d320cf123f4 Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Mon, 7 Aug 2017 15:10:20 +0900 Subject: [PATCH 16/16] Fix testsetup --- docs/source/tutorial/trainer.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/tutorial/trainer.rst b/docs/source/tutorial/trainer.rst index d8f1e5dede42..dd97634632d1 100644 --- a/docs/source/tutorial/trainer.rst +++ b/docs/source/tutorial/trainer.rst @@ -114,6 +114,7 @@ Now let's create the :class:`~chainer.training.Updater` object ! batchsize = 128 + train, test = mnist.get_mnist() train_iter = iterators.SerialIterator(train, batchsize) test_iter = iterators.SerialIterator(test, batchsize, False, False)