提交 56f17d7e authored 作者: Olivier Delalleau's avatar Olivier Delalleau

Added warning about bug recently found in is_1pexp

Also updated NEWS.txt accordingly. This fixes gh-302.
上级 e3e92456
...@@ -98,6 +98,9 @@ Bug fixes (the result changed): ...@@ -98,6 +98,9 @@ Bug fixes (the result changed):
* div by zero in verify_grad. This hid a bug in the grad of Images2Neibs. (James) * div by zero in verify_grad. This hid a bug in the grad of Images2Neibs. (James)
* theano.sandbox.neighbors.Images2Neibs grad was returning a wrong value. * theano.sandbox.neighbors.Images2Neibs grad was returning a wrong value.
The grad is now disabled and returns an error. (Frederic) The grad is now disabled and returns an error. (Frederic)
* An expression of the form "1 / (exp(x) +- constant)" was systematically matched to "1 / (exp(x) + 1)"
and turned into a sigmoid regardless of the value of the constant. A warning will be issued if your
code was affected by this bug. (Olivier, reported by Sander Dieleman)
Crashes fixed: Crashes fixed:
......
...@@ -98,6 +98,9 @@ Bug fixes (the result changed): ...@@ -98,6 +98,9 @@ Bug fixes (the result changed):
* div by zero in verify_grad. This hid a bug in the grad of Images2Neibs. (James) * div by zero in verify_grad. This hid a bug in the grad of Images2Neibs. (James)
* theano.sandbox.neighbors.Images2Neibs grad was returning a wrong value. * theano.sandbox.neighbors.Images2Neibs grad was returning a wrong value.
The grad is now disabled and returns an error. (Frederic) The grad is now disabled and returns an error. (Frederic)
* An expression of the form "1 / (exp(x) +- constant)" was systematically matched to "1 / (exp(x) + 1)"
and turned into a sigmoid regardless of the value of the constant. A warning will be issued if your
code was affected by this bug. (Olivier, reported by Sander Dieleman)
Crashes fixed: Crashes fixed:
......
...@@ -3,18 +3,18 @@ ...@@ -3,18 +3,18 @@
These functions implement special cases of exp and log to improve numerical stability. These functions implement special cases of exp and log to improve numerical stability.
""" """
import warnings
from itertools import imap from itertools import imap
import numpy import numpy
from theano import gof import theano
from theano import scalar from theano import config, gof, printing, scalar
from theano import printing
from theano.tensor import basic as tensor
from theano.printing import pprint, debugprint
from theano.tensor import elemwise
from theano.tensor import opt
from theano.compile import optdb from theano.compile import optdb
from theano.configparser import AddConfigVar, BoolParam
from theano.printing import pprint, debugprint
from theano.tensor import basic as tensor
from theano.tensor import elemwise, opt
############ ############
...@@ -166,9 +166,28 @@ def is_1pexp(t): ...@@ -166,9 +166,28 @@ def is_1pexp(t):
scal_sum = scal_sum + s scal_sum = scal_sum + s
if numpy.allclose(scal_sum, 1): if numpy.allclose(scal_sum, 1):
return False, maybe_exp.owner.inputs[0] return False, maybe_exp.owner.inputs[0]
# Before 7987b51 there used to be a bug where *any* constant
# was considered as if it was equal to 1, and thus this
# function would incorrectly identify it as (1 + exp(x)).
if config.warn.identify_1pexp_bug:
warnings.warn(
'Although your current code is fine, please note that '
'Theano versions prior to 0.5 (more specifically, '
'prior to commit 7987b51 on 2011-12-18) may have '
'yielded an incorrect result. To remove this warning, '
'either set the `warn.identify_1pexp_bug` config '
'option to False, or `warn.ignore_bug_before` to at '
'least \'0.4.1\'.')
return None return None
AddConfigVar('warn.identify_1pexp_bug',
'Warn if Theano versions prior to 7987b51 (2011-12-18) could have '
'yielded a wrong result due to a bug in the is_1pexp function',
BoolParam(theano.configdefaults.warn_default('0.4.1')),
in_c_key=False)
def is_exp(var): def is_exp(var):
""" """
Match a variable with either of the `exp(x)` or `-exp(x)` patterns. Match a variable with either of the `exp(x)` or `-exp(x)` patterns.
......
...@@ -301,6 +301,9 @@ class T_sigmoid_utils(unittest.TestCase): ...@@ -301,6 +301,9 @@ class T_sigmoid_utils(unittest.TestCase):
False, [[False, [[False, x], [False, y]]], [True, z]]] False, [[False, [[False, x], [False, y]]], [True, z]]]
def test_is_1pexp(self): def test_is_1pexp(self):
backup = config.warn.identify_1pexp_bug
config.warn.identify_1pexp_bug = False
try:
x = tensor.vector('x') x = tensor.vector('x')
exp = tensor.exp exp = tensor.exp
assert is_1pexp(1 + exp(x)) == (False, x) assert is_1pexp(1 + exp(x)) == (False, x)
...@@ -313,3 +316,5 @@ class T_sigmoid_utils(unittest.TestCase): ...@@ -313,3 +316,5 @@ class T_sigmoid_utils(unittest.TestCase):
assert is_1pexp(exp(x) - 1) is None assert is_1pexp(exp(x) - 1) is None
assert is_1pexp(-1 + exp(x)) is None assert is_1pexp(-1 + exp(x)) is None
assert is_1pexp(1 + 2 * exp(x)) is None assert is_1pexp(1 + 2 * exp(x)) is None
finally:
config.warn.identify_1pexp_bug = backup
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论