Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
d2947cae
提交
d2947cae
authored
8月 19, 2013
作者:
lamblin
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1489 from nouiz/doc_sparse
Doc how to make an sparse op
上级
a4c621af
45ea254a
隐藏空白字符变更
内嵌
并排
正在显示
9 个修改的文件
包含
205 行增加
和
44 行删除
+205
-44
install.txt
doc/install.txt
+8
-0
install_ubuntu.txt
doc/install_ubuntu.txt
+16
-0
index.txt
doc/library/sparse/index.txt
+7
-1
extending_theano.txt
doc/tutorial/extending_theano.txt
+85
-2
sparse.txt
doc/tutorial/sparse.txt
+2
-0
function.py
theano/compile/function.py
+2
-1
basic.py
theano/sparse/basic.py
+20
-2
test_basic.py
theano/sparse/tests/test_basic.py
+61
-37
updates.py
theano/updates.py
+4
-1
没有找到文件。
doc/install.txt
浏览文件 @
d2947cae
...
@@ -1006,6 +1006,14 @@ Theano is to download and execute this `Windows installer
...
@@ -1006,6 +1006,14 @@ Theano is to download and execute this `Windows installer
for Theano on AnacondaCE for Windows
for Theano on AnacondaCE for Windows
<https://github.com/Theano/Theano-wininstaller/raw/master/bin/theano_installer_latest.msi>`__.
<https://github.com/Theano/Theano-wininstaller/raw/master/bin/theano_installer_latest.msi>`__.
.. note::
It is possible that you need to logout/login or restart the
computer after installing AnacondaCE and before running Theano
installer. Otherwise, sometimes the Theano installer while trying
to find pip.
.. note::
.. note::
This installer was tested on Windows 7, 64-bit edition, and AnacondaCE
This installer was tested on Windows 7, 64-bit edition, and AnacondaCE
...
...
doc/install_ubuntu.txt
浏览文件 @
d2947cae
...
@@ -53,6 +53,22 @@ Ubuntu 11.04:
...
@@ -53,6 +53,22 @@ Ubuntu 11.04:
1) ``sudo apt-get install python-numpy python-scipy python-dev python-pip python-nose g++ git libatlas3gf-base libatlas-dev``
1) ``sudo apt-get install python-numpy python-scipy python-dev python-pip python-nose g++ git libatlas3gf-base libatlas-dev``
2) ``sudo pip install Theano``
2) ``sudo pip install Theano``
.. note::
If you have error that contain "gfortran" in it, like this one:
ImportError: ('/home/Nick/.theano/compiledir_Linux-2.6.35-31-generic-x86_64-with-Ubuntu-10.10-maverick--2.6.6/tmpIhWJaI/0c99c52c82f7ddc775109a06ca04b360.so: undefined symbol: _gfortran_st_write_done'
The problem is probably that NumPy is linked with a different blas
then then one currently available (probably ATLAS). There is 2
possible fixes:
1) Uninstall ATLAS and install OpenBLAS.
2) Use the Theano flag "blas.ldflags=-lblas -lgfortran"
1) is better as OpenBLAS is faster then ATLAS and NumPy is
probably already linked with it. So you won't need any other
change in Theano files or Theano configuration.
Test the newly installed packages
Test the newly installed packages
...
...
doc/library/sparse/index.txt
浏览文件 @
d2947cae
...
@@ -127,8 +127,10 @@ List of Implemented Operations
...
@@ -127,8 +127,10 @@ List of Implemented Operations
- Construction of Sparses and their Properties
- Construction of Sparses and their Properties
- :class:`CSM <theano.sparse.basic.CSM>` and ``CSC``, ``CSR`` to construct a matrix.
- :class:`CSM <theano.sparse.basic.CSM>` and ``CSC``, ``CSR`` to construct a matrix.
The grad implemented is regular.
The grad implemented is regular.
- :class:`CSMProperties <theano.sparse.basic.CSMProperties>` to get the properties of a sparse matrix.
- :class:`CSMProperties <theano.sparse.basic.CSMProperties>` and ``csm_properties(x)``
to get the properties of a sparse matrix.
The grad implemented is regular.
The grad implemented is regular.
- csm_indices(x), csm_indptr(x), csm_data(x) and csm_shape(x) or x.shape.
- :func:`sp_ones_like <theano.sparse.basic.sp_ones_like>`.
- :func:`sp_ones_like <theano.sparse.basic.sp_ones_like>`.
The grad implemented is regular.
The grad implemented is regular.
- :func:`sp_zeros_like <theano.sparse.basic.sp_zeros_like>`.
- :func:`sp_zeros_like <theano.sparse.basic.sp_zeros_like>`.
...
@@ -259,6 +261,9 @@ List of Implemented Operations
...
@@ -259,6 +261,9 @@ List of Implemented Operations
- :class:`Remove0 <theano.sparse.basic.Remove0>` and ``remove0``
- :class:`Remove0 <theano.sparse.basic.Remove0>` and ``remove0``
- :func:`clean <theano.sparse.basic.clean>` to resort indices and remove zeros
- :func:`clean <theano.sparse.basic.clean>` to resort indices and remove zeros
- To help testing
- :func:`theano.sparse.tests.test_basic.sparse_random_inputs`
===================================================================
===================================================================
:mod:`sparse` -- Sparse Op
:mod:`sparse` -- Sparse Op
===================================================================
===================================================================
...
@@ -271,3 +276,4 @@ List of Implemented Operations
...
@@ -271,3 +276,4 @@ List of Implemented Operations
.. automodule:: theano.sparse.basic
.. automodule:: theano.sparse.basic
:members:
:members:
.. autofunction:: theano.sparse.tests.test_basic.sparse_random_inputs
doc/tutorial/extending_theano.txt
浏览文件 @
d2947cae
...
@@ -401,7 +401,7 @@ efficiency over the basic solution that is asked here, the two operations would
...
@@ -401,7 +401,7 @@ efficiency over the basic solution that is asked here, the two operations would
have to be jointly optimized explicitly in the code.)
have to be jointly optimized explicitly in the code.)
SciPy
SciPy
-----
=====
We can wrap SciPy functions in Theano. But SciPy is an optional dependency.
We can wrap SciPy functions in Theano. But SciPy is an optional dependency.
Here is some code that allows the Op to be optional:
Here is some code that allows the Op to be optional:
...
@@ -431,7 +431,7 @@ Here is some code that allows the Op to be optional:
...
@@ -431,7 +431,7 @@ Here is some code that allows the Op to be optional:
...
...
Random numbers in tests
Random numbers in tests
-----------------------
=======================
Making tests errors more reproducible is a good practice. To make your
Making tests errors more reproducible is a good practice. To make your
tests more reproducible, you need a way to get the same random
tests more reproducible, you need a way to get the same random
...
@@ -447,6 +447,89 @@ For more details see :ref:`random_value_in_tests`.
...
@@ -447,6 +447,89 @@ For more details see :ref:`random_value_in_tests`.
:download:`Solution<extending_theano_solution_1.py>`
:download:`Solution<extending_theano_solution_1.py>`
Sparse
======
There is few differences if you want to make an op that use
:ref:`sparse <tutsparse>` inputs or outputs. In particular, in the
``make_node()`` function, you call
``theano.sparse.as_sparse_variable(x)`` on sparse input variable
instead of ``as_tensor_variable(x)``.
Another difference is that you need to use SparseVariable and
SparseType instead of TensorVariable and TensorType.
Don't forget that we support only sparse matrix (so only 2 dimensions)
and they don't support broadcast operation by default as scipy sparse
matrix (but a few op do it when called manually). Also, we support 2
formats for sparse type: ``csr`` and ``csr``. So in ``make_mode()``,
you create outputs variables like this:
.. code-block:: python
out_format = inputs[0].format # or 'csr' or 'csc' if the output format is fixed
SparseType(dtype=inputs[0].dtype, format=out_format).make_variable()
See the sparse :class:`theano.sparse.basic.Cast` op `code
<https://github.com/Theano/Theano/blob/master/theano/sparse/basic.py#L753>`_
for a good example for a sparse op with python code.
.. note::
From the definition of CSR and CSC format, CSR column indices are
not necessarily sorted. Likewise for CSC row indices. Use
:class:`EnsureSortedIndices
<theano.sparse.basic.EnsureSortedIndices>` if your code don't
support it.
Also, there can be explicit zeros in your inputs. Use
:class:`Remove0 <theano.sparse.basic.Remove0>` or ``remove0`` to
make sure they aren't present in your input if you don't support
that.
To remove explicit zeros and make sure indices are sorted, use
:func:`clean <theano.sparse.basic.clean>`.
Sparse Gradient
---------------
There is 2 types of :ref:`gradients <tutsparse_gradient>` : ``normal``
gradient and ``structured`` gradient. Please document what your op
implement in its docstring. It is important that the user know it and
it is not always easy to infer from the code. Also make clear witch
inputs/outputs are sparse and witch ones are dense.
Sparse c code
-------------
Theano don't have a native c code interface for sparse matrix. The
reason is simple, we use the scipy sparse matrix object and they don't
have a c object. So we use a simple trick: a sparse matrix is made of
4 fields that are vector: data, indices, indptr and shape. So to make
an op with c code that have sparse variables as inputs, we make an op
that take as input the needed fields of those sparse variables.
You can extract the 4 fields with
:func:`theano.sparse.basic.csm_properties`. You can use
:func:`theano.sparse.basic.csm_data`,
:func:`theano.sparse.basic.csm_indices`,
:func:`theano.sparse.basic.csm_indptr` and
:func:`theano.sparse.basic.csm_shape` to extract the individual
fields.
You can look at the `AddSD
<https://github.com/Theano/Theano/blob/master/theano/sparse/basic.py#L1704>`_
sparse op for an example with c code. It implement the addition of a
sparse matrix with a dense matrix.
Sparse Tests
------------
You can reuse the test system for tensor variable. To generate the
needed sparse variable and data, you can use
:func:`theano.sparse.tests.test_basic.sparse_random_inputs`. It take
take many paramters including parameters for the format (csr or csc), the shape, the
dtype, to have explicit 0 and to have unsorted indices.
Final Note
Final Note
==========
==========
...
...
doc/tutorial/sparse.txt
浏览文件 @
d2947cae
...
@@ -174,6 +174,8 @@ provide a structured gradient. More explication below.
...
@@ -174,6 +174,8 @@ provide a structured gradient. More explication below.
[ 0. 0. 3.]
[ 0. 0. 3.]
[ 5. 0. 0.]]
[ 5. 0. 0.]]
.. _tutsparse_gradient:
Gradient
Gradient
--------
--------
...
...
theano/compile/function.py
浏览文件 @
d2947cae
...
@@ -171,7 +171,8 @@ def function(inputs, outputs=None, mode=None, updates=None, givens=None,
...
@@ -171,7 +171,8 @@ def function(inputs, outputs=None, mode=None, updates=None, givens=None,
" got "
+
str
(
type
(
updates
))
+
". Using "
" got "
+
str
(
type
(
updates
))
+
". Using "
"a standard dictionary here results in "
"a standard dictionary here results in "
"non-deterministic behavior. You should use an OrderedDict"
"non-deterministic behavior. You should use an OrderedDict"
" if you are using Python 2.7, or use a list of (shared, update)"
" if you are using Python 2.7 (theano.compat.python2x.OrderedDict"
" for older python), or use a list of (shared, update)"
" pairs. Do not just convert your dictionary to this type before"
" pairs. Do not just convert your dictionary to this type before"
" the call as the conversion will still be non-deterministic."
,
" the call as the conversion will still be non-deterministic."
,
stacklevel
=
2
)
stacklevel
=
2
)
...
...
theano/sparse/basic.py
浏览文件 @
d2947cae
...
@@ -511,23 +511,42 @@ class CSMProperties(gof.Op):
...
@@ -511,23 +511,42 @@ class CSMProperties(gof.Op):
data
,
indices
,
indptr
,
shape
=
csm_properties
(
csm
)
data
,
indices
,
indptr
,
shape
=
csm_properties
(
csm
)
return
[
CSM
(
csm
.
format
)(
g
[
0
],
indices
,
indptr
,
shape
)]
return
[
CSM
(
csm
.
format
)(
g
[
0
],
indices
,
indptr
,
shape
)]
# don't make this a function or it breaks some optimizations below
# don't make this a function or it breaks some optimizations below
csm_properties
=
CSMProperties
()
csm_properties
=
CSMProperties
()
"""An CSMProperties object instance. It return the fields data,
indices, indptr and shape of the sparse varible. Together they specify
completly the the sparse variable when we know its format. Example::
the_data, the_indices, the_indptr, the_shape = csm_properties(a_sparse_var)
"""
def
csm_data
(
csm
):
def
csm_data
(
csm
):
"""
return the data field of the sparse variable.
"""
return
csm_properties
(
csm
)[
0
]
return
csm_properties
(
csm
)[
0
]
def
csm_indices
(
csm
):
def
csm_indices
(
csm
):
"""
return the indices field of the sparse variable.
"""
return
csm_properties
(
csm
)[
1
]
return
csm_properties
(
csm
)[
1
]
def
csm_indptr
(
csm
):
def
csm_indptr
(
csm
):
"""
return the indptr field of the sparse variable.
"""
return
csm_properties
(
csm
)[
2
]
return
csm_properties
(
csm
)[
2
]
def
csm_shape
(
csm
):
def
csm_shape
(
csm
):
"""
return the shape field of the sparse variable.
"""
return
csm_properties
(
csm
)[
3
]
return
csm_properties
(
csm
)[
3
]
...
@@ -2338,8 +2357,7 @@ def vstack(blocks, format=None, dtype=None):
...
@@ -2338,8 +2357,7 @@ def vstack(blocks, format=None, dtype=None):
class
Remove0
(
gof
.
Op
):
class
Remove0
(
gof
.
Op
):
"""Remove explicit zeros from a sparse matrix, and
"""Remove explicit zeros from a sparse matrix.
resort indices.
:param x: Sparse matrix.
:param x: Sparse matrix.
...
...
theano/sparse/tests/test_basic.py
浏览文件 @
d2947cae
...
@@ -80,7 +80,8 @@ def random_lil(shape, dtype, nnz):
...
@@ -80,7 +80,8 @@ def random_lil(shape, dtype, nnz):
return
rval
return
rval
def
sparse_random_inputs
(
format
,
shape
,
n
=
1
,
out_dtype
=
None
,
p
=
0.5
,
gap
=
None
):
def
sparse_random_inputs
(
format
,
shape
,
n
=
1
,
out_dtype
=
None
,
p
=
0.5
,
gap
=
None
,
explicit_zero
=
False
,
unsorted_indices
=
False
):
"""Return a tuple containing everything needed to
"""Return a tuple containing everything needed to
perform a test.
perform a test.
...
@@ -97,9 +98,15 @@ def sparse_random_inputs(format, shape, n=1, out_dtype=None, p=0.5, gap=None):
...
@@ -97,9 +98,15 @@ def sparse_random_inputs(format, shape, n=1, out_dtype=None, p=0.5, gap=None):
max, when `gap` = (`a`, `b`) it provide a sample
max, when `gap` = (`a`, `b`) it provide a sample
from [a, b[. If `None` is used, it provide [0, 1]
from [a, b[. If `None` is used, it provide [0, 1]
for float dtypes and [0, 50[ for integer dtypes.
for float dtypes and [0, 50[ for integer dtypes.
:param explicit_zero: When True, we add explicit zero in the
returned sparse matrix
:param unsorted_indices: when True, we make sure there is
unsorted indices in the returned
sparse matrix.
:return: (variable, data) where both `variable`
:return: (variable, data) where both `variable`
and `data` are list.
and `data` are list.
:note: explicit_zero and unsorted_indices was added in Theano 0.6rc4
"""
"""
if
out_dtype
is
None
:
if
out_dtype
is
None
:
...
@@ -136,6 +143,19 @@ def sparse_random_inputs(format, shape, n=1, out_dtype=None, p=0.5, gap=None):
...
@@ -136,6 +143,19 @@ def sparse_random_inputs(format, shape, n=1, out_dtype=None, p=0.5, gap=None):
for
k
in
range
(
n
)]
for
k
in
range
(
n
)]
data
=
[
getattr
(
scipy
.
sparse
,
format
+
'_matrix'
)(
_rand
(),
dtype
=
out_dtype
)
data
=
[
getattr
(
scipy
.
sparse
,
format
+
'_matrix'
)(
_rand
(),
dtype
=
out_dtype
)
for
k
in
range
(
n
)]
for
k
in
range
(
n
)]
if
unsorted_indices
:
for
idx
in
range
(
n
):
d
=
data
[
idx
]
d
=
d
[
range
(
d
.
shape
[
0
])]
assert
not
d
.
has_sorted_indices
data
[
idx
]
=
d
if
explicit_zero
:
for
idx
in
range
(
n
):
assert
data
[
idx
]
.
nnz
>
1
,
(
"can't make a sparse matrix with explicit 0"
)
d_idx
=
numpy
.
random
.
randint
(
data
[
idx
]
.
nnz
)
data
[
idx
]
.
data
[
d_idx
]
=
0
#numpy 1.5.0 with scipy 0.9.0 have scipy.sparse.XXX_matrix return
#numpy 1.5.0 with scipy 0.9.0 have scipy.sparse.XXX_matrix return
#typenum 10(ulonglong) instead of 8(uint64) event if they are the same!
#typenum 10(ulonglong) instead of 8(uint64) event if they are the same!
#Theano don't like ulonglong type_num
#Theano don't like ulonglong type_num
...
@@ -1845,41 +1865,45 @@ class Remove0Tester(utt.InferShapeTester):
...
@@ -1845,41 +1865,45 @@ class Remove0Tester(utt.InferShapeTester):
(
'csr'
,
scipy
.
sparse
.
csr_matrix
),
]
(
'csr'
,
scipy
.
sparse
.
csr_matrix
),
]
for
format
,
matrix_class
in
configs
:
for
format
,
matrix_class
in
configs
:
# real
for
zero
,
unsor
in
[(
True
,
True
),
(
True
,
False
),
origin
=
(
numpy
.
arange
(
9
)
+
1
)
.
reshape
((
3
,
3
))
(
False
,
True
),
(
False
,
False
)]:
origin
.
astype
(
config
.
floatX
)
(
x
,),
(
mat
,)
=
sparse_random_inputs
(
format
,
(
6
,
8
),
mat
=
matrix_class
(
origin
)
.
astype
(
theano
.
config
.
floatX
)
out_dtype
=
config
.
floatX
,
explicit_zero
=
zero
,
mat
[
0
,
1
]
=
mat
[
1
,
0
]
=
mat
[
2
,
2
]
=
0
unsorted_indices
=
unsor
)
assert
0
in
mat
.
data
or
not
zero
assert
mat
.
size
==
9
assert
not
mat
.
has_sorted_indices
or
not
unsor
# symbolic
# the In thingy has to be there because theano has as rule not
x
=
theano
.
sparse
.
SparseType
(
format
=
format
,
dtype
=
config
.
floatX
)()
# to optimize inputs
# the In thingy has to be there because theano has as rule not
f
=
theano
.
function
([
theano
.
In
(
x
,
borrow
=
True
,
mutable
=
True
)],
# to optimize inputs
Remove0
()(
x
))
f
=
theano
.
function
([
theano
.
In
(
x
,
borrow
=
True
,
mutable
=
True
)],
Remove0
()(
x
))
# assert optimization local_inplace_remove0 is applied in
# modes with optimization
# assert optimization local_inplace_remove0 is applied in
if
theano
.
config
.
mode
not
in
[
'FAST_COMPILE'
]:
# modes with optimization
# list of apply nodes in the optimized graph.
if
theano
.
config
.
mode
not
in
[
'FAST_COMPILE'
]:
nodes
=
f
.
maker
.
fgraph
.
toposort
()
# list of apply nodes in the optimized graph.
# Check there isn't any Remove0 instance not inplace.
nodes
=
f
.
maker
.
fgraph
.
toposort
()
assert
not
any
([
isinstance
(
node
.
op
,
Remove0
)
and
# Check there isn't any Remove0 instance not inplace.
not
node
.
op
.
inplace
for
node
in
nodes
]),
(
assert
not
any
([
isinstance
(
node
.
op
,
Remove0
)
and
'Inplace optimization should have been applied'
)
not
node
.
op
.
inplace
for
node
in
nodes
]),
(
# Check there is at least one Remove0 inplace.
'Inplace optimization should have been applied'
)
assert
any
([
isinstance
(
node
.
op
,
Remove0
)
and
node
.
op
.
inplace
# Check there is at least one Remove0 inplace.
for
node
in
nodes
])
assert
any
([
isinstance
(
node
.
op
,
Remove0
)
and
node
.
op
.
inplace
# checking
for
node
in
nodes
])
# makes sense to change its name
# checking
target
=
mat
# makes sense to change its name
result
=
f
(
mat
)
target
=
mat
mat
.
eliminate_zeros
()
result
=
f
(
mat
)
msg
=
'Matrices sizes differ. Have zeros been removed ?'
mat
.
eliminate_zeros
()
assert
result
.
size
==
target
.
size
,
msg
msg
=
'Matrices sizes differ. Have zeros been removed ?'
if
unsor
:
assert
result
.
size
==
target
.
size
,
msg
assert
not
result
.
has_sorted_indices
assert
not
target
.
has_sorted_indices
else
:
assert
result
.
has_sorted_indices
assert
target
.
has_sorted_indices
def
test_infer_shape
(
self
):
def
test_infer_shape
(
self
):
mat
=
(
numpy
.
arange
(
12
)
+
1
)
.
reshape
((
4
,
3
))
mat
=
(
numpy
.
arange
(
12
)
+
1
)
.
reshape
((
4
,
3
))
...
...
theano/updates.py
浏览文件 @
d2947cae
...
@@ -32,7 +32,10 @@ class OrderedUpdates(OrderedDict):
...
@@ -32,7 +32,10 @@ class OrderedUpdates(OrderedDict):
# Warn when using as input a non-ordered dictionary.
# Warn when using as input a non-ordered dictionary.
warnings
.
warn
(
'Initializing an `OrderedUpdates` from a '
warnings
.
warn
(
'Initializing an `OrderedUpdates` from a '
'non-ordered dictionary with 2+ elements could '
'non-ordered dictionary with 2+ elements could '
'make your code non-deterministic'
)
'make your code non-deterministic. You can use '
'an OrderedDict that is implemented at '
'theano.compat.python2x.OrderedDict '
'for python 2.4+.'
)
super
(
OrderedUpdates
,
self
)
.
__init__
(
*
key
,
**
kwargs
)
super
(
OrderedUpdates
,
self
)
.
__init__
(
*
key
,
**
kwargs
)
for
key
in
self
:
for
key
in
self
:
if
not
isinstance
(
key
,
SharedVariable
):
if
not
isinstance
(
key
,
SharedVariable
):
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论