提交 9f67a227 authored 作者: Pascal Lamblin's avatar Pascal Lamblin

Do not use .value in the Theano tutorials (and associated tests)

上级 5f08407d
...@@ -77,12 +77,13 @@ subsequently make to ``np_array`` have no effect on our shared variable. ...@@ -77,12 +77,13 @@ subsequently make to ``np_array`` have no effect on our shared variable.
np_array += 1 # now it is an array of 2.0 s np_array += 1 # now it is an array of 2.0 s
s_default.value # -> array([1.0, 1.0]) s_default.get_value() # -> array([1.0, 1.0])
s_false.value # -> array([1.0, 1.0]) s_false.get_value() # -> array([1.0, 1.0])
s_true.value # -> array([2.0, 2.0]) s_true.get_value() # -> array([2.0, 2.0])
If we are running this with the CPU as the device, If we are running this with the CPU as the device,
then changes we make to np_array *right away* will show up in ``s_true.value`` then changes we make to np_array *right away* will show up in
``s_true.get_value()``
because numpy arrays are mutable, and ``s_true`` is using the ``np_array`` because numpy arrays are mutable, and ``s_true`` is using the ``np_array``
object as it's internal buffer. object as it's internal buffer.
...@@ -101,8 +102,8 @@ will terminate the aliasing). ...@@ -101,8 +102,8 @@ will terminate the aliasing).
It is safe practice (and a good idea) to use ``borrow=True`` in a shared It is safe practice (and a good idea) to use ``borrow=True`` in a shared
variable constructor when the shared variable stands for a large object (in variable constructor when the shared variable stands for a large object (in
terms of memory footprint) and you do not want to create copies of it in memory terms of memory footprint) and you do not want to create copies of it in
. memory.
It is not a reliable technique to use ``borrow=True`` to modify shared variables It is not a reliable technique to use ``borrow=True`` to modify shared variables
by side-effect, because with some devices (e.g. GPU devices) this technique will by side-effect, because with some devices (e.g. GPU devices) this technique will
......
...@@ -256,10 +256,11 @@ internal state, and returns the old state value. ...@@ -256,10 +256,11 @@ internal state, and returns the old state value.
This code introduces a few new concepts. The ``shared`` function constructs This code introduces a few new concepts. The ``shared`` function constructs
so-called :term:`shared variables`. These are hybrid symbolic and non-symbolic so-called :term:`shared variables`. These are hybrid symbolic and non-symbolic
variables. Shared variables can be used in symbolic expressions just like variables. Shared variables can be used in symbolic expressions just like
the objects returned by ``dmatrices(...)`` but they also have a ``.value`` the objects returned by ``dmatrices(...)`` but they also have an internal
property that defines the value taken by this symbolic variable in *all* the value, that defines the value taken by this symbolic variable in *all* the
functions that use it. It is called a *shared* variable because its value is functions that use it. It is called a *shared* variable because its value is
shared between many functions. We will come back to this soon. shared between many functions. The value can be accessed and modified by the
``.get_value()`` and ``.set_value()`` methods. We will come back to this soon.
The other new thing in this code is the ``updates`` parameter of function. The other new thing in this code is the ``updates`` parameter of function.
The updates is a list of pairs of the form (shared-variable, new expression). The updates is a list of pairs of the form (shared-variable, new expression).
...@@ -274,23 +275,23 @@ Anyway, let's try it out! ...@@ -274,23 +275,23 @@ Anyway, let's try it out!
.. If you modify this code, also change : .. If you modify this code, also change :
.. theano/tests/test_tutorial.py:T_examples.test_examples_8 .. theano/tests/test_tutorial.py:T_examples.test_examples_8
>>> state.value >>> state.get_value()
array(0) array(0)
>>> accumulator(1) >>> accumulator(1)
array(0) array(0)
>>> state.value >>> state.get_value()
array(1) array(1)
>>> accumulator(300) >>> accumulator(300)
array(1) array(1)
>>> state.value >>> state.get_value()
array(301) array(301)
It is possible to reset the state. Just assign to the ``.value`` property: It is possible to reset the state. Just use the ``.set_value()`` method:
>>> state.value = -1 >>> state.set_value(-1)
>>> accumulator(3) >>> accumulator(3)
array(-1) array(-1)
>>> state.value >>> state.get_value()
array(2) array(2)
As we mentioned above, you can define more than one function to use the same As we mentioned above, you can define more than one function to use the same
...@@ -302,7 +303,7 @@ shared variable. These functions can both update the value. ...@@ -302,7 +303,7 @@ shared variable. These functions can both update the value.
>>> decrementor = function([inc], state, updates=[(state, state-inc)]) >>> decrementor = function([inc], state, updates=[(state, state-inc)])
>>> decrementor(2) >>> decrementor(2)
array(2) array(2)
>>> state.value >>> state.get_value()
array(0) array(0)
You might be wondering why the updates mechanism exists. You can always You might be wondering why the updates mechanism exists. You can always
...@@ -329,7 +330,7 @@ for the purpose of one particular function. ...@@ -329,7 +330,7 @@ for the purpose of one particular function.
givens=[(state, foo)]) givens=[(state, foo)])
>>> skip_shared(1, 3) # we're using 3 for the state, not state.value >>> skip_shared(1, 3) # we're using 3 for the state, not state.value
array(7) array(7)
>>> state.value # old state still there, but we didn't use it >>> state.get_value() # old state still there, but we didn't use it
array(0) array(0)
The givens parameter can be used to replace any symbolic variable, not just a The givens parameter can be used to replace any symbolic variable, not just a
...@@ -411,9 +412,11 @@ Seedings Streams ...@@ -411,9 +412,11 @@ Seedings Streams
Random variables can be seeded individually or collectively. Random variables can be seeded individually or collectively.
You can seed just one random variable by seeding or assigning to the You can seed just one random variable by seeding or assigning to the
``.rng.value`` attribute. ``.rng`` attribute, using ``.rng.set_value()``.
>>> rv_u.rng.value.seed(89234) # seeds the generator for rv_u >>> rng_val = rv_u.rng.get_value(borrow=True) # Get the rng for rv_u
>>> rng_val.seed(89234) # seeds the generator
>>> rv_u.rng.set_value(rng_val, borrow=True) # Assign back seeded rng
You can also seed *all* of the random variables allocated by a :class:`RandomStreams` You can also seed *all* of the random variables allocated by a :class:`RandomStreams`
object by that object's ``seed`` method. This seed will be used to seed a object by that object's ``seed`` method. This seed will be used to seed a
...@@ -431,10 +434,12 @@ update the state of the generators used in function ``f`` above. ...@@ -431,10 +434,12 @@ update the state of the generators used in function ``f`` above.
For example: For example:
>>> state_after_v0 = rv_u.rng.value.get_state() >>> state_after_v0 = rv_u.rng.get_value().get_state()
>>> nearly_zeros() # this affects rv_u's generator >>> nearly_zeros() # this affects rv_u's generator
>>> v1 = f() >>> v1 = f()
>>> rv_u.rng.value.set_state(state_after_v0) >>> rng = rng.get_value(borrow=True)
>>> rng.set_state(state_after_v0)
>>> rv_u.rng.set_value(rng, borrow=True)
>>> v2 = f() # v2 != v1 >>> v2 = f() # v2 != v1
......
...@@ -595,19 +595,19 @@ class T_examples(unittest.TestCase): ...@@ -595,19 +595,19 @@ class T_examples(unittest.TestCase):
inc = T.iscalar('inc') inc = T.iscalar('inc')
accumulator = function([inc], state, updates=[(state, state+inc)]) accumulator = function([inc], state, updates=[(state, state+inc)])
assert state.value == array(0) assert state.get_value() == array(0)
assert accumulator(1) == array(0) assert accumulator(1) == array(0)
assert state.value == array(1) assert state.get_value() == array(1)
assert accumulator(300) == array(1) assert accumulator(300) == array(1)
assert state.value == array(301) assert state.get_value() == array(301)
state.value = -1 state.set_value(-1)
assert accumulator(3) == array(-1) assert accumulator(3) == array(-1)
assert state.value == array(2) assert state.get_value() == array(2)
decrementor = function([inc], state, updates=[(state, state-inc)]) decrementor = function([inc], state, updates=[(state, state-inc)])
assert decrementor(2) == array(2) assert decrementor(2) == array(2)
assert state.value == array(0) assert state.get_value() == array(0)
fn_of_state = state * 2 + inc fn_of_state = state * 2 + inc
foo = T.lscalar() # the type (lscalar) must match the shared variable we foo = T.lscalar() # the type (lscalar) must match the shared variable we
...@@ -615,7 +615,7 @@ class T_examples(unittest.TestCase): ...@@ -615,7 +615,7 @@ class T_examples(unittest.TestCase):
skip_shared = function([inc, foo], fn_of_state, skip_shared = function([inc, foo], fn_of_state,
givens=[(state, foo)]) givens=[(state, foo)])
assert skip_shared(1, 3) == array(7) assert skip_shared(1, 3) == array(7)
assert state.value == array(0) assert state.get_value() == array(0)
def test_examples_9(self): def test_examples_9(self):
...@@ -643,13 +643,17 @@ class T_examples(unittest.TestCase): ...@@ -643,13 +643,17 @@ class T_examples(unittest.TestCase):
nearly_zeros = function([], rv_u + rv_u - 2 * rv_u) nearly_zeros = function([], rv_u + rv_u - 2 * rv_u)
assert numpy.allclose(nearly_zeros(), [[0.,0.],[0.,0.]]) assert numpy.allclose(nearly_zeros(), [[0.,0.],[0.,0.]])
rv_u.rng.value.seed(89234) # seeds the generator for rv_u rng_val = rv_u.rng.get_value(borrow=True) # Get the rng for rv_u
rng_val.seed(89234) # seeds the generator
rv_u.rng.set_value(rng_val, borrow=True) # Assign back seeded rng
srng.seed(902340) # seeds rv_u and rv_n with different seeds each srng.seed(902340) # seeds rv_u and rv_n with different seeds each
state_after_v0 = rv_u.rng.value.get_state() state_after_v0 = rv_u.rng.get_value().get_state()
nearly_zeros() # this affects rv_u's generator nearly_zeros() # this affects rv_u's generator
v1 = f() v1 = f()
rv_u.rng.value.set_state(state_after_v0) rng = rv_u.rng.get_value(borrow=True)
rng.set_state(state_after_v0)
rv_u.rng.set_value(rng, borrow=True)
v2 = f() # v2 != v1 v2 = f() # v2 != v1
assert numpy.all(v1 != v2) assert numpy.all(v1 != v2)
...@@ -671,9 +675,9 @@ class T_aliasing(unittest.TestCase): ...@@ -671,9 +675,9 @@ class T_aliasing(unittest.TestCase):
np_array += 1 # now it is an array of 2.0 s np_array += 1 # now it is an array of 2.0 s
assert numpy.all(s_default.value == array([1.0, 1.0])) assert numpy.all(s_default.get_value() == array([1.0, 1.0]))
assert numpy.all(s_false.value == array([1.0, 1.0])) assert numpy.all(s_false.get_value() == array([1.0, 1.0]))
assert numpy.all(s_true.value == array([2.0, 2.0])) assert numpy.all(s_true.get_value() == array([2.0, 2.0]))
def test_aliasing_2(self): def test_aliasing_2(self):
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论