Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
c7db795f
提交
c7db795f
authored
4月 10, 2008
作者:
bergstrj@iro.umontreal.ca
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
moved scalar_ops to scalar, removed old elemwise.py.
上级
f1153866
隐藏空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
194 行增加
和
857 行删除
+194
-857
_test_elemwise2.py
_test_elemwise2.py
+1
-1
_test_gradient.py
_test_gradient.py
+1
-1
_test_scalar.py
_test_scalar.py
+1
-1
elemwise.py
elemwise.py
+0
-691
elemwise2.py
elemwise2.py
+4
-4
op.py
gof/op.py
+2
-0
gradient.py
gradient.py
+3
-5
scalar.py
scalar.py
+180
-0
scalar_ops.py
scalar_ops.py
+0
-152
tensor.py
tensor.py
+2
-2
没有找到文件。
_test_elemwise2.py
浏览文件 @
c7db795f
...
...
@@ -5,7 +5,7 @@ import unittest
from
gof
import
ResultBase
,
Op
,
Env
,
modes
import
gof
from
scalar
_ops
import
*
from
scalar
import
*
from
elemwise2
import
*
...
...
_test_gradient.py
浏览文件 @
c7db795f
...
...
@@ -22,7 +22,7 @@ class _test_grad_sources_inputs(unittest.TestCase):
try
:
grad_sources_inputs
([(
a
.
out
,
1
)],
None
)
except
ValueError
,
e
:
self
.
failUnless
(
e
[
0
]
is
gradient
.
_msg_ret
Non
e
)
self
.
failUnless
(
e
[
0
]
is
gradient
.
_msg_ret
Typ
e
)
return
self
.
fail
()
def
test_retNone1_b
(
self
):
...
...
_test_scalar
_ops
.py
→
_test_scalar.py
浏览文件 @
c7db795f
...
...
@@ -4,7 +4,7 @@ import unittest
from
gof
import
ResultBase
,
Op
,
Env
,
modes
import
gof
from
scalar
_ops
import
*
from
scalar
import
*
def
inputs
():
...
...
elemwise.py
deleted
100644 → 0
浏览文件 @
f1153866
from
copy
import
copy
from
gof
import
Op
,
Destroyer
from
gof.utils
import
AbstractFunctionError
class
Elemwise
(
Op
):
def
var_desc
(
self
):
raise
AbstractFunctionError
()
def
c_var_names
(
self
):
idesc
,
odesc
=
self
.
var_desc
()
return
[[
i
[
0
]
for
i
in
idesc
],
[
o
[
0
]
for
o
in
odesc
]]
def
loop_variables
(
self
):
idesc
,
odesc
=
self
.
var_desc
()
return
[[
i
[
0
]
for
i
in
idesc
if
i
[
1
]],
[
o
[
0
]
for
o
in
odesc
if
o
[
1
]]]
def
c_code_init
(
self
):
raise
AbstractFunctionError
()
def
c_code_foreach
(
self
):
raise
AbstractFunctionError
()
def
c_code_finalize
(
self
):
raise
AbstractFunctionError
()
def
__c_code
(
self
):
try
:
before
=
self
.
c_code_init
()
except
AbstractFunctionError
:
before
=
""
during
=
self
.
c_code_foreach
()
try
:
after
=
self
.
c_code_finalize
()
except
AbstractFunctionError
:
after
=
""
idesc
,
odesc
=
self
.
var_desc
()
input_loop_vars
=
[
x
[
0
]
for
x
in
idesc
if
x
[
1
]]
output_loop_vars
=
[
x
[
0
]
for
x
in
odesc
if
x
[
1
]]
aliases
=
{}
try
:
dmap
=
self
.
destroy_map
()
except
:
dmap
=
{}
if
dmap
!=
{}:
for
(
oname
,
isloopvar
),
output
in
zip
(
odesc
,
self
.
outputs
):
if
isloopvar
:
for
input
in
dmap
.
get
(
output
,
[]):
iname
=
idesc
[
self
.
inputs
.
index
(
input
)][
0
]
aliases
[
"
%
("
+
oname
+
")s"
]
=
"
%
("
+
iname
+
")s"
output_loop_vars
.
remove
(
oname
)
ret
=
elemwise_wrap
(
before
,
during
,
after
,
[
"
%
("
+
v
+
")s"
for
v
in
input_loop_vars
],
[
"
%
("
+
v
+
")s"
for
v
in
output_loop_vars
],
aliases
)
return
ret
def
c_validate_update
(
self
,
input_names
,
output_names
,
sub
):
sub
=
dict
(
sub
)
icvn
,
ocvn
=
self
.
c_var_names
()
for
real
,
tosub
in
zip
(
input_names
+
output_names
,
icvn
+
ocvn
):
sub
[
tosub
]
=
real
(
valupd
,
valupd_cleanup
),
(
code
,
code_cleanup
)
=
self
.
__c_code
()
return
valupd
%
sub
def
c_validate_update_cleanup
(
self
,
input_names
,
output_names
,
sub
):
sub
=
dict
(
sub
)
icvn
,
ocvn
=
self
.
c_var_names
()
for
real
,
tosub
in
zip
(
input_names
+
output_names
,
icvn
+
ocvn
):
sub
[
tosub
]
=
real
(
valupd
,
valupd_cleanup
),
(
code
,
code_cleanup
)
=
self
.
__c_code
()
return
valupd_cleanup
%
sub
def
c_code
(
self
,
input_names
,
output_names
,
sub
):
sub
=
dict
(
sub
)
icvn
,
ocvn
=
self
.
c_var_names
()
for
real
,
tosub
in
zip
(
input_names
+
output_names
,
icvn
+
ocvn
):
sub
[
tosub
]
=
real
(
valupd
,
valupd_cleanup
),
(
code
,
code_cleanup
)
=
self
.
__c_code
()
return
code
%
sub
def
c_code_cleanup
(
self
,
input_names
,
output_names
,
sub
):
sub
=
dict
(
sub
)
icvn
,
ocvn
=
self
.
c_var_names
()
for
real
,
tosub
in
zip
(
input_names
+
output_names
,
icvn
+
ocvn
):
sub
[
tosub
]
=
real
(
valupd
,
valupd_cleanup
),
(
code
,
code_cleanup
)
=
self
.
__c_code
()
return
code_cleanup
%
sub
@classmethod
def
inplace_version
(
cls
,
dmap
=
{
0
:
0
}):
class
Ret
(
cls
,
Destroyer
):
def
destroy_map
(
self
):
return
{
self
.
outputs
[
0
]:
[
self
.
inputs
[
0
]]}
return
Ret
class
Looper
:
def
__init__
(
self
,
declare
,
init
,
acquire
,
next
,
cleanup
):
self
.
declare
=
declare
self
.
init
=
init
self
.
acquire
=
acquire
self
.
next
=
next
self
.
cleanup
=
cleanup
def
fill
(
self
,
**
template
):
ret
=
copy
(
self
)
ret
.
declare
%=
template
ret
.
init
%=
template
ret
.
acquire
%=
template
ret
.
next
%=
template
ret
.
cleanup
%=
template
return
ret
general_looper
=
Looper
(
declare
=
"""
PyArrayIterObject*
%(iter)
s_
%(name)
s = NULL;
//dtype_
%(name)
s&
%(name)
s_i;
"""
,
init
=
"""
%(iter)
s_
%(name)
s = (PyArrayIterObject*)PyArray_IterNew((PyObject*)
%(name)
s);
if (
%(iter)
s_
%(name)
s == NULL) {
PyErr_SetString(PyExc_ValueError, "Could not make an iterator over variable
%(name)
s.");
%%(fail)
s;
}
"""
,
acquire
=
"dtype_
%(name)
s&
%(name)
s_i = *((dtype_
%(name)
s*)
%(iter)
s_
%(name)
s->dataptr);"
,
next
=
"PyArray_ITER_NEXT(
%(iter)
s_
%(name)
s);"
,
cleanup
=
"if (
%(iter)
s_
%(name)
s) Py_DECREF(
%(iter)
s_
%(name)
s);"
)
contiguous_looper
=
Looper
(
declare
=
"""
dtype_
%(name)
s*
%(iter)
s_
%(name)
s = NULL;
//dtype_
%(name)
s
%(name)
s_i;
"""
,
init
=
"
%(iter)
s_
%(name)
s = (dtype_
%(name)
s*)PyArray_DATA(
%(name)
s);"
,
acquire
=
"dtype_
%(name)
s&
%(name)
s_i = *
%(iter)
s_
%(name)
s;"
,
next
=
"
%(iter)
s_
%(name)
s++;"
,
cleanup
=
""
)
alias_looper
=
Looper
(
declare
=
""
,
#dtype_%(name)s%(type_suffix)s %(name)s_i;",
init
=
""
,
acquire
=
"dtype_
%(name)
s&
%(name)
s_i =
%(other)
s_i;"
,
next
=
""
,
cleanup
=
""
)
def
elemwise_loopcode
(
loopcode
,
loopers
):
def
make_block
(
loopers
,
type
):
return
"
\n
"
.
join
([
getattr
(
looper
,
type
)
for
looper
in
loopers
])
template
=
dict
(
loopcode
=
loopcode
)
for
block_type
in
[
'declare'
,
'init'
,
'next'
,
'acquire'
,
'cleanup'
]:
template
[
block_type
]
=
make_block
(
loopers
,
block_type
)
code
=
"""
%(init)
s
while (__SIZE--) {
%(acquire)
s
%(loopcode)
s
%(next)
s
}
"""
%
template
cleanup
=
"""
%(cleanup)
s
"""
%
template
return
template
[
'declare'
],
code
,
cleanup
def
elemwise_wrap
(
beforeloop
,
inloop
,
afterloop
,
input_loop_vars
,
output_loop_vars
,
aliases
):
if
len
(
input_loop_vars
)
==
0
:
raise
Exception
(
"You need at least one input loop variable."
)
validate
=
"""
npy_intp nd =
%(first_loop_var)
s->nd;
npy_intp* dims =
%(first_loop_var)
s->dimensions;
npy_intp* dims2;
"""
%
dict
(
first_loop_var
=
input_loop_vars
[
0
])
for
other_loop_var
in
input_loop_vars
[
1
:]:
validate
+=
"""
if (
%(other_loop_var)
s->nd != nd) {
PyErr_SetString(PyExc_ValueError,
\"
The number of dimensions of the inputs do not match.
\"
);
%%(fail)
s
}
dims2 =
%(other_loop_var)
s->dimensions;
for (int i = 0; i < nd; i++) {
if (dims2[i] != dims[i]) {
PyErr_SetString(PyExc_ValueError,
\"
The dimensions of the inputs do not match.
\"
);
%%(fail)
s;
}
}
"""
%
dict
(
other_loop_var
=
other_loop_var
)
update
=
""
for
output_loop_var
in
output_loop_vars
:
update
+=
"""
if (!
%(output_loop_var)
s) {
%(output_loop_var)
s = (PyArrayObject*)PyArray_EMPTY(nd, dims, type_num_
%(output_loop_var)
s, 0);
}
else {
PyArray_Dims new_dims;
new_dims.len = nd;
new_dims.ptr = dims;
PyObject* success = PyArray_Resize(
%(output_loop_var)
s, &new_dims, 0, PyArray_CORDER);
if (!success) {
// If we can't resize the ndarray we have we can allocate a new one.
PyErr_Clear();
Py_XDECREF(
%(output_loop_var)
s);
%(output_loop_var)
s = (PyArrayObject*)PyArray_EMPTY(nd, dims, type_num_
%(output_loop_var)
s, 0);
}
}
if (!
%(output_loop_var)
s) {
%%(fail)
s
}
"""
%
dict
(
output_loop_var
=
output_loop_var
)
validate_update
=
validate
+
update
validate_update_cleanup
=
""
general_loopers
=
[]
general_loopers
+=
[
general_looper
.
fill
(
name
=
loop_var
,
iter
=
"iter_general_"
)
for
loop_var
in
input_loop_vars
+
output_loop_vars
]
general_loopers
+=
[
alias_looper
.
fill
(
name
=
v1
,
other
=
v2
,
iter
=
"iter_general_"
)
for
v1
,
v2
in
aliases
.
items
()]
contig_loopers
=
[]
contig_loopers
+=
[
contiguous_looper
.
fill
(
name
=
loop_var
,
iter
=
"iter_contig_"
)
for
loop_var
in
input_loop_vars
+
output_loop_vars
]
contig_loopers
+=
[
alias_looper
.
fill
(
name
=
v1
,
other
=
v2
,
iter
=
"iter_contig_"
)
for
v1
,
v2
in
aliases
.
items
()]
general_decl
,
general_loop
,
general_loop_cleanup
=
elemwise_loopcode
(
inloop
,
general_loopers
)
contig_decl
,
contig_loop
,
contig_loop_cleanup
=
elemwise_loopcode
(
inloop
,
contig_loopers
)
contiguity_check
=
""
.
join
([
"all_c_contiguous &= PyArray_ISCARRAY(
%(loop_var)
s);
\n
"
\
"all_f_contiguous &= PyArray_ISFARRAY(
%(loop_var)
s);
\n
"
\
%
dict
(
loop_var
=
loop_var
)
for
loop_var
in
input_loop_vars
+
output_loop_vars
])
v1
=
input_loop_vars
[
0
]
code
=
"""
%(general_decl)
s
%(contig_decl)
s
npy_intp __SIZE = PyArray_SIZE(
%(v1)
s);
bool all_c_contiguous = 1;
bool all_f_contiguous = 1;
%(beforeloop)
s
%(contiguity_check)
s
if (all_c_contiguous || all_f_contiguous) {
%(contig_loop)
s
}
else {
%(general_loop)
s
}
%(afterloop)
s
"""
%
locals
()
cleanup
=
"""
if (all_c_contiguous || all_f_contiguous) {
%(contig_loop_cleanup)
s
}
else {
%(general_loop_cleanup)
s
}
"""
%
locals
()
# print """
# VALIDATE_UPDATE
# %(validate_update)s
# CODE
# %(code)s
# CLEANUP
# %(cleanup)s
# VU_CLEANUP
# %(validate_update_cleanup)s
# """ % locals()
return
(
validate_update
,
validate_update_cleanup
),
(
code
,
cleanup
)
# import core
# def elemwise_loopcode(loopcode, init_template, next_template, acquire_template, cleanup_template, loop_vars, writable_loop_vars, aliases):
# all_loop_vars = loop_vars + writable_loop_vars
# template = dict(
# init = "".join([init_template % dict(loop_var = loop_var) for loop_var in all_loop_vars]),
# next = "".join([next_template % dict(loop_var = loop_var) for loop_var in all_loop_vars]),
# cleanup = "".join([cleanup_template % dict(loop_var = loop_var) for loop_var in all_loop_vars]),
# idefs = "".join([("%(loop_var)s_dtype %(loop_var)s_i = " + acquire_template + ";\n")
# % dict(loop_var = loop_var) for loop_var in loop_vars]),
# odefs = "".join([("%(loop_var)s_dtype& %(loop_var)s_i = " + acquire_template + ";\n")
# % dict(loop_var = loop_var) for loop_var in writable_loop_vars]),
# aliasdefs = "".join(["%(v1)s_dtype %(v1)s_i = %(v2)s_i;\n" % dict(v1=v1, v2=v2)
# for v1, v2 in aliases.items()]),
# loopcode = loopcode
# )
# code = """
# %(init)s
# while (__elemwise_size--) {
# %(idefs)s
# %(odefs)s
# %(aliasdefs)s
# %(loopcode)s
# %(next)s
# }
# %(cleanup)s
# """ % template
# return code
# def elemwise_wrap(beforeloop, inloop, afterloop, loop_vars, writable_loop_vars, aliases):
# check_init = """
# npy_intp nd = %(loop_var)s->nd;
# npy_intp* dims = %(loop_var)s->dimensions;
# npy_intp* dims2;
# """
# check = """
# if (%(loop_var)s->nd != nd) {
# PyErr_SetString(PyExc_ValueError, \"The number of dimensions of the inputs do not match.\");
# }
# dims2 = %(loop_var)s->dimensions;
# for (int i = 0; i < nd; i++) {
# if (dims2[i] != dims[i]) {
# PyErr_SetString(PyExc_ValueError, \"The dimensions of the inputs do not match.\");
# return 1;
# }
# }
# """
# general_init = "PyArrayIterObject* %(loop_var)s_iter = (PyArrayIterObject*)PyArray_IterNew((PyObject*)%(loop_var)s);\n"
# # "if (%(loop_var)s_iter == NULL) {\n" \
# # " PyErr_SetString(PyExc_ValueError, \"Could not make an iterator over variable %(loop_var)s.\");\n" \
# # " return 1;\n" \
# # "}\n"
# general_next = "PyArray_ITER_NEXT(%(loop_var)s_iter);\n"
# general_acquire = "*((%(loop_var)s_dtype*)%(loop_var)s_iter->dataptr)";
# general_cleanup = "if (%(loop_var)s_iter) Py_DECREF(%(loop_var)s_iter);\n";
# contiguous_init = "%(loop_var)s_dtype* __restrict__ %(loop_var)s_iter = (%(loop_var)s_dtype*)PyArray_DATA(%(loop_var)s);\n"
# contiguous_next = "%(loop_var)s_iter++;\n"
# contiguous_acquire = "*%(loop_var)s_iter"
# contiguous_cleanup = ""
# all_loop_vars = loop_vars + writable_loop_vars
# v1 = (loop_vars + writable_loop_vars)[0]
# template = dict(
# v1 = v1,
# check_init = check_init % dict(loop_var = v1),
# check = "\n".join([check % dict(loop_var = loop_var) for loop_var in loop_vars + writable_loop_vars if loop_var is not v1]),
# beforeloop = beforeloop,
# general_loop = elemwise_loopcode(
# inloop,
# general_init, general_next, general_acquire, general_cleanup,
# loop_vars, writable_loop_vars, aliases),
# contiguous_loop = elemwise_loopcode(
# inloop,
# contiguous_init, contiguous_next, contiguous_acquire, contiguous_cleanup,
# loop_vars, writable_loop_vars, aliases),
# contiguity_check = "".join(["all_c_contiguous &= PyArray_ISCARRAY(%(loop_var)s);\n" \
# "all_f_contiguous &= PyArray_ISFARRAY(%(loop_var)s);\n" \
# % dict(loop_var = loop_var)
# for loop_var in all_loop_vars]),
# afterloop = afterloop)
# code = """
# {
# %(check_init)s
# %(check)s
# }
# npy_intp __elemwise_size = PyArray_SIZE(%(v1)s);
# %(beforeloop)s
# bool all_c_contiguous = 1;
# bool all_f_contiguous = 1;
# %(contiguity_check)s
# if (all_c_contiguous || all_f_contiguous) {
# %(contiguous_loop)s
# }
# else {
# %(general_loop)s
# }
# %(afterloop)s
# """ % template
# return code
# class elemwise(omega_op):
# @staticmethod
# def __clsinit__(cls, name, bases, dct):
# for fname in ['c_init', 'c_foreach', 'c_finalize']:
# gof.make_static(cls, fname)
# # make impl, grad, etc. static methods
# omega_op.__clsinit__(cls, name, bases, dct)
# def TOGO_specs(self):
# try:
# return self.specs(*[input.spec for input in self.inputs])
# except NotImplementedError:
# inames, onames = self.variable_names()
# linames, lonames = self.loop_variables()
# for oname in onames:
# if oname not in lonames:
# raise Exception("cannot infer a specification automatically for variable " \
# "%s.%s because it is not part of the elementwise loop - "\
# "please override the specs method" % (self.__class__.__name__, oname))
# shape, dtype = None, None
# for iname, input in zip(inames, self.inputs):
# if iname in linames:
# if input.spec:
# shape = input.spec[2]
# if shape is None:
# raise Exception("cannot infer a specification automatically for output variables " \
# "because there is no input variable in the loop from which to get the shape, "\
# "or their shape is unknown")
# try:
# dtype = core.upcast(*[input.spec[1]
# for iname, input in zip(inames, self.inputs)
# if input.spec[0] is numpy.ndarray])
# except IndexError:
# raise Exception("not all numpy inputs are specified")
# dmap = self.destroy_map()
# res = []
# for output in self.outputs:
# inplace_inputs = dmap.get(output, [])
# if inplace_inputs:
# assert len(inplace_inputs) == 1
# res.append(inplace_inputs[0].spec)
# else:
# res.append((numpy.ndarray, dtype, shape))
# if self.nout == 1:
# return res[0]
# else:
# return res
# def TOGO_alloc(self, except_list = []):
# dmap = self.destroy_map()
# vmap = self.view_map()
# gof.PythonOp.alloc(self, except_list = except_list + dmap.keys())
# for output, (input, ) in dmap.items():
# if output not in except_list:
# output.set_value(input.data)
# def refresh_shape(self):
# """Make the output have the right stuff"""
# if len(self.outputs) > 1:
# raise NotImplementedError('multiple outputs')
# dmap = self.destroy_map()
# vmap = self.view_map()
# if dmap != {} or vmap != {}:
# raise NotImplementedError('destroys or views confuse things',
# self.__class__, dmap, vmap)
# # take the shape of the leftmost loop_variable input
# inames, onames = self.variable_names()
# linames, lonames = self.loop_variables()
# unknown_output_names = [n for n in onames if n not in lonames]
# if len(unknown_output_names):
# raise Exception("cannot infer a specification automatically for variables " \
# "%s.{%s} because it is not part of the elementwise loop - "\
# "please override the specs method" %
# (self.__class__.__name__, str(unknown_output_names)))
# # shape is leftmost loop-variable input
# input_loop_shapes = [i.shape for n,i in zip(inames, self.inputs) if n in linames]
# if len(input_loop_shapes) == 0:
# raise Exception("cannot infer a specification automatically for output variables " \
# "because there is no input loop variable ")
# for i in xrange(1,len(input_loop_shapes)):
# if input_loop_shapes[i] != input_loop_shapes[0]:
# raise Exception("Input loop variables have different shapes", self.__class__)
# return input_loop_shapes[0]
# def refresh_dtype(self):
# return core.upcast(*[i.dtype for i in self.inputs if hasattr(i, 'dtype')])
# @classmethod
# def set_impl(cls, impl):
# gof.lib.make_static(cls, 'impl')
# @staticmethod
# def is_loop_var(name):
# return name.endswith("_i")
# @staticmethod
# def extract_name(name):
# if name.endswith("_i"):
# return name[:-2]
# else:
# return name
# @classmethod
# def variable_names(cls):
# (inames, onames), _1, _2, _3 = inspect.getargspec(cls.c_foreach)
# spec = ([cls.extract_name(name) for name in inames],
# [cls.extract_name(name) for name in onames])
# if cls.c_init is not elemwise.c_init:
# (inames, onames), _1, _2, _3 = inspect.getargspec(cls.c_init)
# assert spec == (list(inames), list(onames))
# if cls.c_finalize is not elemwise.c_finalize:
# (inames, onames), _1, _2, _3 = inspect.getargspec(cls.c_finalize)
# assert spec == (list(inames), list(onames))
# return spec
# @classmethod
# def loop_variables(cls):
# (inames, onames), _1, _2, _3 = inspect.getargspec(cls.c_foreach)
# return ([cls.extract_name(name) for name in inames if cls.is_loop_var(name)],
# [cls.extract_name(name) for name in onames if cls.is_loop_var(name)])
# def _c_init(self):
# return self.c_init(self.inputs, self.outputs)
# def c_init(inputs, outputs):
# return ""
# def _c_foreach(self):
# return self.c_foreach(self.inputs, self.outputs)
# def c_foreach(inputs, outputs):
# raise NotImplementedError()
# def _c_finalize(self):
# return self.c_finalize(self.inputs, self.outputs)
# def c_finalize(inputs, outputs):
# return ""
# def c_code(self, converters = None, elemwise_wrap = elemwise_wrap):
# def mangle(name):
# if name.endswith("_i"):
# return name[:-2]
# else:
# return name
# try:
# self._c_impl()
# raise Exception("c_impl is not used by elemwise ops - define behavior in c_foreach instead")
# except NotImplementedError:
# pass
# before = self._c_init()
# during = self._c_foreach()
# after = self._c_finalize()
# (inames, onames) = self.variable_names()
# (linames, lonames) = self.loop_variables()
# aliases = {}
# dmap = self.destroy_map()
# if dmap != {}:
# for oname, output in zip(onames, self.outputs):
# if oname in lonames:
# for input in dmap.get(output, []):
# aliases[inames[self.inputs.index(input)]] = oname
# behavior = elemwise_wrap(before, during, after,
# [name for name in linames if name not in aliases],
# lonames,
# aliases)
# return cgen(self.__class__.__name__, behavior, inames + onames, self.inputs + self.outputs, converters)
# @classmethod
# def inplace_version(cls, dmap = {0: 0}):
# inames, onames = cls.variable_names()
# linames, lonames = cls.loop_variables()
# for i, oname in enumerate(onames):
# if i in dmap:
# assert oname in lonames
# class C(cls):
# def destroy_map(self):
# assert cls.destroy_map(self) == {}
# ret = {}
# for output, input in dmap.items():
# ret[self.outputs[output]] = [self.inputs[input]]
# return ret
# def _impl(self):
# if self.impl is not cls.impl:
# # If the user sets his own inplace operation, we use it
# return cls._impl(self)
# else:
# res = cls._impl(self)
# if isinstance(res, (list, tuple)):
# res = copy.copy(res)
# else:
# res = [res]
# for output, input in dmap.items():
# # The default implementation returned a copy, so we just
# # overwrite the original input with the contents of that copy
# # This is not meant to be efficient, only correct.
# #
# # TODO: change this to use set_value_inplace
# a = self.inputs[input].data
# a[:] = res[output]
# res[output] = a
# if len(res) == 1:
# return res[0]
# else:
# return res
# if dmap == {0:0}:
# C.__name__ = cls.__name__ + "_inplace" % dmap
# else:
# C.__name__ = cls.__name__ + "_inplace%s" % dmap
# return C
elemwise2.py
浏览文件 @
c7db795f
...
...
@@ -4,8 +4,8 @@ import elemwise_cgen as cgen
import
numpy
from
gof
import
Op
,
Viewer
,
Destroyer
from
base_tensor
import
BaseTensor
as
Tensor
import
scalar
from
scalar
import
upcast
,
Scalar
import
scalar_ops
import
gof
from
gof.python25
import
all
...
...
@@ -424,7 +424,7 @@ class CAReduce(Op):
tosum
=
self
.
dimensions_to_reduce
if
tosum
==
():
return
Broadcast
(
scalar
_ops
.
Identity
,
(
input
,
))
.
_c_all
(
inames
,
onames
,
sub
)
return
Broadcast
(
scalar
.
Identity
,
(
input
,
))
.
_c_all
(
inames
,
onames
,
sub
)
order1
=
[
i
for
i
in
xrange
(
len
(
input
.
broadcastable
))
if
i
not
in
tosum
]
order
=
order1
+
list
(
tosum
)
...
...
@@ -522,7 +522,7 @@ def make_reduce(scalar_opclass, name = None):
New
.
__name__
=
"Reduce"
+
scalar_opclass
.
__name__
return
New
class
Sum
(
make_reduce
(
scalar
_ops
.
Add
)):
class
Sum
(
make_reduce
(
scalar
.
Add
)):
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
if
self
.
dimensions_to_reduce
==
():
return
gz
,
...
...
@@ -534,7 +534,7 @@ class Sum(make_reduce(scalar_ops.Add)):
else
:
new_dims
.
append
(
i
)
i
+=
1
return
Broadcast
(
scalar
_ops
.
Second
,
(
x
,
DimShuffle
(
gz
,
new_dims
)
.
out
))
.
out
,
return
Broadcast
(
scalar
.
Second
,
(
x
,
DimShuffle
(
gz
,
new_dims
)
.
out
))
.
out
,
def
reduce
(
op
):
...
...
gof/op.py
浏览文件 @
c7db795f
...
...
@@ -58,6 +58,8 @@ class Op(object):
#
# Python stdlib compatibility
#
# These are defined so that sets of Ops, Results will have a consistent
# ordering
def
__cmp__
(
self
,
other
):
return
cmp
(
id
(
self
),
id
(
other
))
...
...
gradient.py
浏览文件 @
c7db795f
...
...
@@ -3,7 +3,7 @@ import numpy #for numeric_grad
from
gof.python25
import
all
_msg_ret
None
=
'op.grad(...) returned None, consider returning [None]
'
_msg_ret
Type
=
'op.grad(...) returned a non-list
'
_msg_badlen
=
'op.grad(...) returned wrong number of gradients'
def
_unpack_result
(
lst
):
...
...
@@ -82,10 +82,8 @@ def grad_sources_inputs(sources, graph_inputs):
output_arg
=
g_outputs
input_arg
=
op
.
inputs
op_grad
=
op
.
grad
(
input_arg
,
output_arg
)
if
op_grad
is
None
:
raise
ValueError
(
_msg_retNone
,
op
.
__class__
)
if
isinstance
(
op_grad
,
float
):
raise
TypeError
(
'wtf!!!!!!!!'
,
op
)
if
not
isinstance
(
op_grad
,
(
list
,
tuple
)):
raise
ValueError
(
_msg_retType
,
op
.
__class__
)
g_inputs
=
op_grad
#_pack_result(op_grad)
assert
isinstance
(
g_inputs
,
(
list
,
tuple
))
if
len
(
g_inputs
)
!=
len
(
op
.
inputs
):
...
...
scalar.py
浏览文件 @
c7db795f
import
numpy
import
math
from
copy
import
copy
import
inspect
...
...
@@ -143,6 +144,35 @@ class Scalar(ResultBase):
cpy
.
data
=
self
.
data
return
cpy
#UNARY
def
__abs__
(
self
):
return
Abs
(
self
)
.
out
def
__neg__
(
self
):
return
Neg
(
self
)
.
out
#CASTS
def
__int__
(
self
):
return
AsInt
(
self
)
.
out
def
__float__
(
self
):
return
AsInt
(
self
)
.
out
def
__complex__
(
self
):
return
AsComplex
(
self
)
.
out
#COMPARISONS
def
__lt__
(
self
,
other
):
return
lt
(
self
,
other
)
def
__le__
(
self
,
other
):
return
le
(
self
,
other
)
def
__gt__
(
self
,
other
):
return
gt
(
self
,
other
)
def
__ge__
(
self
,
other
):
return
ge
(
self
,
other
)
#ARITHMETIC - NORMAL
def
__add__
(
self
,
other
):
return
add
(
self
,
other
)
def
__sub__
(
self
,
other
):
return
sub
(
self
,
other
)
def
__mul__
(
self
,
other
):
return
mul
(
self
,
other
)
def
__div__
(
self
,
other
):
return
div
(
self
,
other
)
def
__pow__
(
self
,
other
):
return
pow
(
self
,
other
)
#ARITHMETIC - RIGHT-OPERAND
def
__radd__
(
self
,
other
):
return
add
(
other
,
self
)
def
__rsub__
(
self
,
other
):
return
sub
(
other
,
self
)
def
__rmul__
(
self
,
other
):
return
mul
(
other
,
self
)
def
__rdiv__
(
self
,
other
):
return
div
(
other
,
self
)
def
__rpow__
(
self
,
other
):
return
pow
(
other
,
self
)
class
ScalarMixedOp
(
GuardedOp
):
...
...
@@ -201,4 +231,154 @@ class BinaryScalarOp(PureScalarOp):
class
Add
(
BinaryScalarOp
):
identity
=
0
def
impl
(
self
,
x
,
y
):
return
x
+
y
def
c_code
(
self
,
(
x
,
y
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(x)
s +
%(y)
s;"
%
locals
()
def
grad
(
self
,
(
x
,
y
),
(
gz
,
)):
return
gz
,
gz
class
Sub
(
BinaryScalarOp
):
def
impl
(
self
,
x
,
y
):
return
x
-
y
def
c_code
(
self
,
(
x
,
y
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(x)
s -
%(y)
s;"
%
locals
()
def
grad
(
self
,
(
x
,
y
),
(
gz
,
)):
return
gz
,
neg
(
gz
)
class
Mul
(
BinaryScalarOp
):
def
impl
(
self
,
x
,
y
):
return
x
*
y
def
c_code
(
self
,
(
x
,
y
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(x)
s *
%(y)
s;"
%
locals
()
def
grad
(
self
,
(
x
,
y
),
(
gz
,
)):
return
mul
(
y
,
gz
),
mul
(
x
,
gz
)
class
Div
(
BinaryScalarOp
):
def
impl
(
self
,
x
,
y
):
return
x
/
y
def
c_code
(
self
,
(
x
,
y
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(x)
s /
%(y)
s;"
%
locals
()
def
grad
(
self
,
(
x
,
y
),
(
gz
,
)):
return
div
(
gz
,
y
),
neg
(
div
(
mul
(
x
,
gz
),
mul
(
y
,
y
)))
class
Pow
(
BinaryScalarOp
):
def
impl
(
self
,
x
,
y
):
return
x
**
y
def
c_code
(
self
,
(
x
,
y
),
(
z
,
),
sub
):
return
"
%(z)
s = pow(
%(x)
s,
%(y)
s);"
%
locals
()
def
grad
(
self
,
(
x
,
y
),
(
gz
,
)):
return
mul
(
gz
,
mul
(
y
,
pow
(
x
,
sub
(
y
,
as_scalar
(
1
))))),
mul
(
gz
,
mul
(
log
(
x
),
pow
(
x
,
y
)))
class
First
(
BinaryScalarOp
):
def
impl
(
self
,
x
,
y
):
return
x
def
c_code
(
self
,
(
x
,
y
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(x)
s;"
%
locals
()
def
grad
(
self
,
(
x
,
y
),
(
gz
,
)):
return
gz
,
None
class
Second
(
BinaryScalarOp
):
def
impl
(
self
,
x
,
y
):
return
y
def
c_code
(
self
,
(
x
,
y
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(y)
s;"
%
locals
()
def
grad
(
self
,
(
x
,
y
),
(
gz
,
)):
return
None
,
gz
class
Identity
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
x
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(x)
s;"
%
locals
()
def
grad
(
self
,
(
x
,
y
),
(
gz
,
)):
return
gz
,
class
Neg
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
-
x
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
neg
(
gz
),
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s = -
%(x)
s;"
%
locals
()
class
Abs
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
numpy
.
abs
(
x
)
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
mul
(
gz
,
sgn
(
x
)),
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s = abs(
%(x)
s);"
%
locals
()
class
Sgn
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
numpy
.
abs
(
x
)
/
x
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
None
,
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(x)
s/abs(
%(x)
s);"
%
locals
()
# TODO: C use copysign
class
Inv
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
1
/
x
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
div
(
neg
(
gz
),
mul
(
x
,
x
)),
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s = 1 /
%(x)
s;"
%
locals
()
class
Log
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
math
.
log
(
x
)
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
div
(
gz
,
x
),
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s = log(
%(x)
s);"
%
locals
()
class
Log2
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
numpy
.
log2
(
x
)
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
div
(
gz
,
mul
(
x
,
as_scalar
(
math
.
log
(
2.0
)))),
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s = log2(
%(x)
s);"
%
locals
()
class
Exp
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
math
.
exp
(
x
)
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
mul
(
gz
,
exp
(
x
)),
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s = exp(
%(x)
s);"
%
locals
()
class
Sqr
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
x
*
x
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
mul
(
gz
,
mul
(
x
,
as_scalar
(
2
))),
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(x)
s *
%(x)
s;"
%
locals
()
class
Sqrt
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
math
.
sqrt
(
x
)
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
div
(
mul
(
gz
,
as_scalar
(
0.5
)),
sqrt
(
x
)),
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s = sqrt(
%(x)
s);"
%
locals
()
#NOTE WELL!!!
# The following adds functions to this module automatically.
# For every scalar op class, a lower-case symbol is added which is a constructor
# for that class.
from
gof
import
modes
modes
.
make_constructors
(
globals
())
scalar_ops.py
deleted
100644 → 0
浏览文件 @
f1153866
from
scalar
import
*
import
math
class
Add
(
BinaryScalarOp
):
identity
=
0
def
impl
(
self
,
x
,
y
):
return
x
+
y
def
c_code
(
self
,
(
x
,
y
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(x)
s +
%(y)
s;"
%
locals
()
def
grad
(
self
,
(
x
,
y
),
(
gz
,
)):
return
gz
,
gz
class
Sub
(
BinaryScalarOp
):
def
impl
(
self
,
x
,
y
):
return
x
-
y
def
c_code
(
self
,
(
x
,
y
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(x)
s -
%(y)
s;"
%
locals
()
def
grad
(
self
,
(
x
,
y
),
(
gz
,
)):
return
gz
,
neg
(
gz
)
class
Mul
(
BinaryScalarOp
):
def
impl
(
self
,
x
,
y
):
return
x
*
y
def
c_code
(
self
,
(
x
,
y
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(x)
s *
%(y)
s;"
%
locals
()
def
grad
(
self
,
(
x
,
y
),
(
gz
,
)):
return
mul
(
y
,
gz
),
mul
(
x
,
gz
)
class
Div
(
BinaryScalarOp
):
def
impl
(
self
,
x
,
y
):
return
x
/
y
def
c_code
(
self
,
(
x
,
y
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(x)
s /
%(y)
s;"
%
locals
()
def
grad
(
self
,
(
x
,
y
),
(
gz
,
)):
return
div
(
gz
,
y
),
neg
(
div
(
mul
(
x
,
gz
),
mul
(
y
,
y
)))
class
Pow
(
BinaryScalarOp
):
def
impl
(
self
,
x
,
y
):
return
x
**
y
def
c_code
(
self
,
(
x
,
y
),
(
z
,
),
sub
):
return
"
%(z)
s = pow(
%(x)
s,
%(y)
s);"
%
locals
()
def
grad
(
self
,
(
x
,
y
),
(
gz
,
)):
return
mul
(
gz
,
mul
(
y
,
pow
(
x
,
sub
(
y
,
as_scalar
(
1
))))),
mul
(
gz
,
mul
(
log
(
x
),
pow
(
x
,
y
)))
class
First
(
BinaryScalarOp
):
def
impl
(
self
,
x
,
y
):
return
x
def
c_code
(
self
,
(
x
,
y
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(x)
s;"
%
locals
()
def
grad
(
self
,
(
x
,
y
),
(
gz
,
)):
return
gz
,
None
class
Second
(
BinaryScalarOp
):
def
impl
(
self
,
x
,
y
):
return
y
def
c_code
(
self
,
(
x
,
y
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(y)
s;"
%
locals
()
def
grad
(
self
,
(
x
,
y
),
(
gz
,
)):
return
None
,
gz
class
Identity
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
x
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(x)
s;"
%
locals
()
def
grad
(
self
,
(
x
,
y
),
(
gz
,
)):
return
gz
,
class
Neg
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
-
x
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
neg
(
gz
),
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s = -
%(x)
s;"
%
locals
()
class
Abs
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
numpy
.
abs
(
x
)
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
mul
(
gz
,
sgn
(
x
)),
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s = abs(
%(x)
s);"
%
locals
()
class
Sgn
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
numpy
.
abs
(
x
)
/
x
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
None
,
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(x)
s/abs(
%(x)
s);"
%
locals
()
# TODO: C use copysign
class
Inv
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
1
/
x
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
div
(
neg
(
gz
),
mul
(
x
,
x
)),
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s = 1 /
%(x)
s;"
%
locals
()
class
Log
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
math
.
log
(
x
)
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
div
(
gz
,
x
),
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s = log(
%(x)
s);"
%
locals
()
class
Log2
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
numpy
.
log2
(
x
)
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
div
(
gz
,
mul
(
x
,
as_scalar
(
math
.
log
(
2.0
)))),
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s = log2(
%(x)
s);"
%
locals
()
class
Exp
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
math
.
exp
(
x
)
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
mul
(
gz
,
exp
(
x
)),
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s = exp(
%(x)
s);"
%
locals
()
class
Sqr
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
x
*
x
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
mul
(
gz
,
mul
(
x
,
as_scalar
(
2
))),
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s =
%(x)
s *
%(x)
s;"
%
locals
()
class
Sqrt
(
UnaryScalarOp
):
def
impl
(
self
,
x
):
return
math
.
sqrt
(
x
)
def
grad
(
self
,
(
x
,
),
(
gz
,
)):
return
div
(
mul
(
gz
,
as_scalar
(
0.5
)),
sqrt
(
x
)),
def
c_code
(
self
,
(
x
,
),
(
z
,
),
sub
):
return
"
%(z)
s = sqrt(
%(x)
s);"
%
locals
()
# class Sigmoid(UnaryComposite):
# def expand_impl(self, x):
# return 1.0 / (1.0 + exp(-x))
from
gof
import
modes
modes
.
make_constructors
(
globals
())
tensor.py
浏览文件 @
c7db795f
...
...
@@ -12,7 +12,7 @@ from base_tensor import BaseTensor, BaseTensorOp
import
blas
# for gemm, dot
import
elemwise2
as
s2t
import
scalar
_ops
as
scal
import
scalar
as
scal
class
Tensor
(
BaseTensor
):
...
...
@@ -69,7 +69,7 @@ class Tensor(BaseTensor):
def
__getslice__
(
self
,
*
args
):
return
subtensor
(
self
,
slice
(
*
args
))
s2t
.
Tensor
=
Tensor
# alternate Tensor constructor
def
astensor
(
data
,
broadcastable
=
None
,
role
=
None
,
name
=
None
):
"""Return a Tensor containing given data"""
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论