Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
P
pytensor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
testgroup
pytensor
Commits
04662229
提交
04662229
authored
3月 14, 2009
作者:
desjagui@atchoum.iro.umontreal.ca
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implemented StructuredDotCSR (with fast c-implementation)
上级
dff4d08c
显示空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
219 行增加
和
96 行删除
+219
-96
basic.py
theano/sparse/basic.py
+199
-70
test_basic.py
theano/sparse/tests/test_basic.py
+20
-26
没有找到文件。
theano/sparse/basic.py
浏览文件 @
04662229
...
@@ -10,6 +10,7 @@ import sys, operator
...
@@ -10,6 +10,7 @@ import sys, operator
import
numpy
import
numpy
from
scipy
import
sparse
from
scipy
import
sparse
import
scipy.sparse
import
scipy.sparse
from
theano.printing
import
Print
from
..
import
gof
from
..
import
gof
from
..
import
tensor
from
..
import
tensor
...
@@ -674,12 +675,7 @@ class StructuredDot(gof.Op):
...
@@ -674,12 +675,7 @@ class StructuredDot(gof.Op):
raise
ValueError
(
'shape mismatch in StructuredDot.perform'
,
(
a
.
shape
,
b
.
shape
))
raise
ValueError
(
'shape mismatch in StructuredDot.perform'
,
(
a
.
shape
,
b
.
shape
))
result
=
a
.
dot
(
b
)
result
=
a
.
dot
(
b
)
assert
_is_dense
(
result
)
# scipy 0.7 automatically converts to dense
# scipy 0.7.0 automatically casts to dense, so the following is not necessary:
# # sparse dot generates sparse matrix, unless output has single dimension
# if sparse.issparse(result):
# result = result.toarray()
assert
_is_dense
(
result
)
# dot of an NxM sparse matrix, with a Mx1 dense matrix, returns vector not matrix
# dot of an NxM sparse matrix, with a Mx1 dense matrix, returns vector not matrix
if
result
.
ndim
==
1
:
if
result
.
ndim
==
1
:
...
@@ -697,15 +693,16 @@ class StructuredDot(gof.Op):
...
@@ -697,15 +693,16 @@ class StructuredDot(gof.Op):
## Commenting this out because result should be a numpy.ndarray since the assert above
## Commenting this out because result should be a numpy.ndarray since the assert above
## (JB 20090109)
## (JB 20090109)
#out[0] = numpy.asarray(result) #TODO: fix this really bad implementation
#
out[0] = numpy.asarray(result) #TODO: fix this really bad implementation
#
#
out
[
0
]
=
result
out
[
0
]
=
result
def
grad
(
self
,
(
a
,
b
),
(
g_out
,)):
def
grad
(
self
,
(
a
,
b
),
(
g_out
,)):
#a is sparse, b is dense, g_out is dense
# a is sparse, b is dense, g_out is dense
#ga = g_out x b.T
# ga = g_out x b.T
#gb = a.T x g_out
# gb = a.T x g_out
return
structured_dot_grad
(
a
,
b
,
g_out
),
structured_dot
(
a
.
T
,
g_out
)
return
[
structured_dot_grad
(
a
,
b
,
g_out
),
structured_dot
(
a
.
T
,
g_out
)]
_structured_dot
=
StructuredDot
()
_structured_dot
=
StructuredDot
()
def
structured_dot
(
x
,
y
):
def
structured_dot
(
x
,
y
):
...
@@ -718,8 +715,10 @@ def structured_dot(x, y):
...
@@ -718,8 +715,10 @@ def structured_dot(x, y):
x_is_sparse_result
=
_is_sparse_result
(
x
)
x_is_sparse_result
=
_is_sparse_result
(
x
)
y_is_sparse_result
=
_is_sparse_result
(
y
)
y_is_sparse_result
=
_is_sparse_result
(
y
)
if
not
x_is_sparse_result
and
not
y_is_sparse_result
:
if
not
x_is_sparse_result
and
not
y_is_sparse_result
:
raise
TypeError
(
'structured_dot requires at least one sparse argument'
)
raise
TypeError
(
'structured_dot requires at least one sparse argument'
)
if
x_is_sparse_result
:
if
x_is_sparse_result
:
return
_structured_dot
(
x
,
y
)
return
_structured_dot
(
x
,
y
)
else
:
else
:
...
@@ -737,12 +736,20 @@ class StructuredDotCSC(gof.Op):
...
@@ -737,12 +736,20 @@ class StructuredDotCSC(gof.Op):
a
=
sparse
.
csc_matrix
((
a_val
,
a_ind
,
a_ptr
),
a
=
sparse
.
csc_matrix
((
a_val
,
a_ind
,
a_ptr
),
(
a_nrows
,
b
.
shape
[
0
]),
(
a_nrows
,
b
.
shape
[
0
]),
copy
=
False
)
copy
=
False
)
# TODO: todense() is automatic in 0.7.0, just remove the following line:
# out[0] = numpy.asarray(a.dot(b).todense())
out
[
0
]
=
a
.
dot
(
b
)
out
[
0
]
=
a
.
dot
(
b
)
assert
_is_dense
(
out
[
0
])
assert
_is_dense
(
out
[
0
])
# scipy 0.7 automatically converts to dense
def
c_code
(
self
,
node
,
name
,
(
a_val
,
a_ind
,
a_ptr
,
a_nrows
,
b
),
(
z
,),
sub
):
def
c_code
(
self
,
node
,
name
,
(
a_val
,
a_ind
,
a_ptr
,
a_nrows
,
b
),
(
z
,),
sub
):
"""
C-implementation of the dot product of the sparse matrix A and matrix B.
@param a_val: non-zero values of the sparse matrix
@param a_ind: column indices of the non-null values (.indices of a scipy.csc_matrix)
@param a_ptr: a_ptr indicates col indices for col. i are in the range a_ptr[i]:a_ptr[i+1]
@param n_rows: number of rows of sparse matrix
@param b: dense matrix to perform dot product with, as in dot(a,b)
@param z: return value
@param sub: TODO, not too sure, something to do with weave probably
"""
return
"""
return
"""
if (
%(a_val)
s->nd != 1) {PyErr_SetString(PyExc_NotImplementedError, "rank(a_val) != 1");
%(fail)
s;}
if (
%(a_val)
s->nd != 1) {PyErr_SetString(PyExc_NotImplementedError, "rank(a_val) != 1");
%(fail)
s;}
if (
%(a_ind)
s->nd != 1) {PyErr_SetString(PyExc_NotImplementedError, "rank(a_ind) != 1");
%(fail)
s;}
if (
%(a_ind)
s->nd != 1) {PyErr_SetString(PyExc_NotImplementedError, "rank(a_ind) != 1");
%(fail)
s;}
...
@@ -784,10 +791,12 @@ class StructuredDotCSC(gof.Op):
...
@@ -784,10 +791,12 @@ class StructuredDotCSC(gof.Op):
}
}
{
{
//
the output array has size M x
N
//
sparse array has size MxK, dense KxN, output Mx
N
npy_intp M =
%(z)
s->dimensions[0];
npy_intp M =
%(z)
s->dimensions[0];
npy_intp N =
%(z)
s->dimensions[1];
npy_intp N =
%(z)
s->dimensions[1];
npy_intp K =
%(b)
s->dimensions[0];
npy_intp K =
%(b)
s->dimensions[0];
// strides tell you how many bytes to skip to go to next column/row entry
npy_intp Szm =
%(z)
s->strides[0] /
%(z)
s->descr->elsize;
npy_intp Szm =
%(z)
s->strides[0] /
%(z)
s->descr->elsize;
npy_intp Szn =
%(z)
s->strides[1] /
%(z)
s->descr->elsize;
npy_intp Szn =
%(z)
s->strides[1] /
%(z)
s->descr->elsize;
//npy_intp Sbm =
%(b)
s->strides[0] /
%(b)
s->descr->elsize;
//npy_intp Sbm =
%(b)
s->strides[0] /
%(b)
s->descr->elsize;
...
@@ -796,6 +805,7 @@ class StructuredDotCSC(gof.Op):
...
@@ -796,6 +805,7 @@ class StructuredDotCSC(gof.Op):
npy_intp Sind =
%(a_ind)
s->strides[0] /
%(a_ind)
s->descr->elsize;
npy_intp Sind =
%(a_ind)
s->strides[0] /
%(a_ind)
s->descr->elsize;
npy_intp Sptr =
%(a_ptr)
s->strides[0] /
%(a_ptr)
s->descr->elsize;
npy_intp Sptr =
%(a_ptr)
s->strides[0] /
%(a_ptr)
s->descr->elsize;
// pointers to access actual data in the arrays passed as params.
npy_double * __restrict__ Dz = (npy_double*)
%(z)
s->data;
npy_double * __restrict__ Dz = (npy_double*)
%(z)
s->data;
//const npy_double * __restrict__ Db = (npy_double*)
%(b)
s->data;
//const npy_double * __restrict__ Db = (npy_double*)
%(b)
s->data;
const npy_double * __restrict__ Dval = (npy_double*)
%(a_val)
s->data;
const npy_double * __restrict__ Dval = (npy_double*)
%(a_val)
s->data;
...
@@ -815,31 +825,38 @@ class StructuredDotCSC(gof.Op):
...
@@ -815,31 +825,38 @@ class StructuredDotCSC(gof.Op):
//iterate over the sparse array, making the most of an entry wherever we find it.
//iterate over the sparse array, making the most of an entry wherever we find it.
//
//
// Normal matrix matrix multiply:
// Normal matrix matrix multiply:
A MxK, B KxN => Z = AB
// for m
// for m
// for n
// for n
// for k
// for k
// z[m,n] += a[m,k] * b[k,n]
// z[m,n] += a[m,k] * b[k,n]
// Here instead:
// Here instead:
Z =
// for k
// for k
// for m (sparse)
// for m (sparse)
// for n
// for n
// z[m,n] += a[m,k] * b[k,n]
// z[m,n] += a[m,k] * b[k,n]
// loop over inner dimension
for (npy_int32 k = 0; k < K; ++k)
for (npy_int32 k = 0; k < K; ++k)
{
{
// get pointer to k-th row of dense matrix
const npy_double * __restrict__ bk = (double *)(
%(b)
s->data +
%(b)
s->strides[0] * k);
const npy_double * __restrict__ bk = (double *)(
%(b)
s->data +
%(b)
s->strides[0] * k);
// loop over sparse column indices through index pointer array
// (amounts to looping over rows M of sparse matrix)
for (npy_int32 m_idx = Dptr[k * Sptr]; m_idx < Dptr[(k+1) * Sptr]; ++m_idx)
for (npy_int32 m_idx = Dptr[k * Sptr]; m_idx < Dptr[(k+1) * Sptr]; ++m_idx)
{
{
npy_int32 m = Dind[m_idx * Sind];
npy_int32 m = Dind[m_idx * Sind];
// row index of non-null value for column K
const double Amk = Dval[m_idx * Sval];
const double Amk = Dval[m_idx * Sval];
// actual value at that location
// pointer to m-th row of the output matrix Z
npy_double * __restrict__ zm = (npy_double *)(
%(z)
s->data +
%(z)
s->strides[0] * m);
npy_double * __restrict__ zm = (npy_double *)(
%(z)
s->data +
%(z)
s->strides[0] * m);
//RESOLVE: a.shape[0] equals z.shape[0], why is this not an equality constraint?
if (m >=
%(z)
s->dimensions[0])
if (m >=
%(z)
s->dimensions[0])
{PyErr_SetString(PyExc_NotImplementedError, "illegal row index in a");
%(fail)
s;}
{PyErr_SetString(PyExc_NotImplementedError, "illegal row index in a");
%(fail)
s;}
// loop over final dimension (cols of dense matrix) and perform dot product
for(npy_int32 n = 0; n < N; ++n)
for(npy_int32 n = 0; n < N; ++n)
{
{
zm[n*Szn] += Amk * bk[n*Sbn];
zm[n*Szn] += Amk * bk[n*Sbn];
...
@@ -850,40 +867,173 @@ class StructuredDotCSC(gof.Op):
...
@@ -850,40 +867,173 @@ class StructuredDotCSC(gof.Op):
"""
%
dict
(
locals
(),
**
sub
)
"""
%
dict
(
locals
(),
**
sub
)
sd_csc
=
StructuredDotCSC
()
sd_csc
=
StructuredDotCSC
()
#TODO: register a specialization to replace StructuredDot -> StructuredDotCSC
class
StructuredDotCSR
(
gof
.
Op
):
def
make_node
(
self
,
a_val
,
a_ind
,
a_ptr
,
a_ncols
,
b
):
assert
a_val
.
type
.
dtype
==
b
.
type
.
dtype
r
=
gof
.
Apply
(
self
,
[
a_val
,
a_ind
,
a_ptr
,
a_ncols
,
b
],
[
tensor
.
tensor
(
a_val
.
type
.
dtype
,
(
False
,
False
))])
return
r
def
perform
(
self
,
node
,
(
a_val
,
a_ind
,
a_ptr
,
a_ncols
,
b
),
(
out
,)):
a
=
sparse
.
csc_matrix
((
a_val
,
a_ind
,
a_ptr
),
(
a_ncols
,
b
.
shape
[
0
]),
copy
=
False
)
out
[
0
]
=
a
.
dot
(
b
)
assert
_is_dense
(
out
[
0
])
# scipy 0.7 automatically converts to dense
def
c_code
(
self
,
node
,
name
,
(
a_val
,
a_ind
,
a_ptr
,
a_ncols
,
b
),
(
z
,),
sub
):
"""
C-implementation of the dot product of the sparse matrix A and matrix B.
@param a_val: non-zero values of the sparse matrix
@param a_ind: column indices of the non-null values (.indices of a scipy.csc_matrix)
@param a_ptr: a_ptr indicates col indices for col. i are in the range a_ptr[i]:a_ptr[i+1]
@param n_cols: number of columns of sparse matrix
@param b: dense matrix to perform dot product with, as in dot(a,b)
@param z: return value
@param sub: TODO, not too sure, something to do with weave probably
"""
return
"""
if (
%(a_val)
s->nd != 1) {PyErr_SetString(PyExc_NotImplementedError, "rank(a_val) != 1");
%(fail)
s;}
if (
%(a_ind)
s->nd != 1) {PyErr_SetString(PyExc_NotImplementedError, "rank(a_ind) != 1");
%(fail)
s;}
if (
%(a_ptr)
s->nd != 1) {PyErr_SetString(PyExc_NotImplementedError, "rank(a_ptr) != 1");
%(fail)
s;}
if (
%(a_ncols)
s->nd != 0) {PyErr_SetString(PyExc_NotImplementedError, "rank(ncols) != 0");
%(fail)
s;}
if (
%(b)
s->nd != 2) {PyErr_SetString(PyExc_NotImplementedError, "rank(b) != 2");
%(fail)
s;}
if (
%(a_val)
s->descr->type_num != PyArray_DOUBLE)
{PyErr_SetString(PyExc_NotImplementedError, "a_val dtype not NPY_DOUBLE");
%(fail)
s;}
if (
%(a_ind)
s->descr->type_num != PyArray_INT32) {
PyErr_SetString(PyExc_NotImplementedError, "a_ind dtype not INT32");
%(fail)
s;}
if (
%(a_ptr)
s->descr->type_num != PyArray_INT32)
{PyErr_SetString(PyExc_NotImplementedError, "a_ptr dtype not INT32");
%(fail)
s;}
if (
%(a_ncols)
s->descr->type_num != PyArray_INT32)
{PyErr_SetString(PyExc_NotImplementedError, "a_ncols dtype not INT32");
%(fail)
s;}
if (
%(b)
s->descr->type_num != PyArray_DOUBLE)
{PyErr_SetString(PyExc_NotImplementedError, "b's dtype not NPY_DOUBLE");
%(fail)
s;}
if (
%(a_val)
s->dimensions[0] !=
%(a_ind)
s->dimensions[0])
{PyErr_SetString(PyExc_NotImplementedError, "a_val and a_ind have different lengths");
%(fail)
s;}
if (
%(a_ptr)
s->dimensions[0] !=
%(b)
s->dimensions[0]+1)
{PyErr_SetString(PyExc_NotImplementedError, "a's number of columns doesn't match b's rows");
%(fail)
s;}
if ((!
%(z)
s)
|| (
%(z)
s->dimensions[0] != ((npy_int32 *)
%(a_ncols)
s->data)[0])
|| (
%(z)
s->dimensions[1] !=
%(b)
s->dimensions[1])
)
{
if (
%(z)
s) Py_DECREF(
%(z)
s);
npy_intp dims[] = {0,0};
dims[0] = ((npy_int32 *)
%(a_ncols)
s->data)[0];
dims[1] =
%(b)
s->dimensions[1];
%(z)
s = (PyArrayObject*) PyArray_SimpleNew(2, dims,
%(b)
s->descr->type_num);
}
{
// sparse array has size MxK, dense KxN, output MxN
npy_intp M =
%(z)
s->dimensions[0];
npy_intp N =
%(z)
s->dimensions[1];
npy_intp K =
%(b)
s->dimensions[0];
// strides tell you how many bytes to skip to go to next column/row entry
npy_intp Szm =
%(z)
s->strides[0] /
%(z)
s->descr->elsize;
npy_intp Szn =
%(z)
s->strides[1] /
%(z)
s->descr->elsize;
npy_intp Sbm =
%(b)
s->strides[0] /
%(b)
s->descr->elsize;
npy_intp Sbn =
%(b)
s->strides[1] /
%(b)
s->descr->elsize;
npy_intp Sval =
%(a_val)
s->strides[0] /
%(a_val)
s->descr->elsize;
npy_intp Sind =
%(a_ind)
s->strides[0] /
%(a_ind)
s->descr->elsize;
npy_intp Sptr =
%(a_ptr)
s->strides[0] /
%(a_ptr)
s->descr->elsize;
// pointers to access actual data in the arrays passed as params.
npy_double * __restrict__ Dz = (npy_double*)
%(z)
s->data;
//const npy_double * __restrict__ Db = (npy_double*)
%(b)
s->data;
const npy_double * __restrict__ Dval = (npy_double*)
%(a_val)
s->data;
const npy_int32 * __restrict__ Dind = (npy_int32*)
%(a_ind)
s->data;
const npy_int32 * __restrict__ Dptr = (npy_int32*)
%(a_ptr)
s->data;
//npy_intp nnz =
%(a_ind)
s->dimensions[0];
//clear the output array
for (npy_intp m = 0; m < M; ++m)
{
for (npy_intp n = 0; n < N; ++n)
{
Dz[m*Szm + n*Szn] = 0.0;
}
}
//iterate over the sparse array, making the most of an entry wherever we find it.
// Normal matrix matrix multiply:
// for m
// for n
// for k
// z[m,n] += a[m,k] * b[k,n]
// Here instead:
// for m
// for k (sparse)
// for n
// z[m,n] += a[m,k] * b[k,n]
// loop over inner dimension
for (npy_int32 m = 0; m < M; ++m)
{
// pointer to m-th row of the output matrix Z
npy_double * __restrict__ zm = (npy_double *)(
%(z)
s->data +
%(z)
s->strides[0] * m);
// loop over sparse rows indices through index pointer array
// (amounts to looping over cols k of sparse matrix)
for (npy_int32 k_idx = Dptr[m * Sptr]; k_idx < Dptr[(m+1) * Sptr]; ++k_idx)
{
npy_int32 k = Dind[k_idx * Sind]; // col index of non-null value for row m
const double Amk = Dval[k_idx * Sval]; // actual value at that location
// get pointer to k-th row of dense matrix
const npy_double * __restrict__ bk = (double *)(
%(b)
s->data +
%(b)
s->strides[0] * k);
// loop over final dimension (cols of dense matrix) and perform dot product
for(npy_int32 n = 0; n < N; ++n)
{
zm[n*Szn] += Amk * bk[n*Sbn];
}
}
}
}
"""
%
dict
(
locals
(),
**
sub
)
sd_csr
=
StructuredDotCSR
()
# register a specialization to replace StructuredDot -> StructuredDotCSx
@gof.local_optimizer
([
_structured_dot
])
@gof.local_optimizer
([
_structured_dot
])
def
local_structured_dot
_csc
(
node
):
def
local_structured_dot
(
node
):
if
node
.
op
==
_structured_dot
:
if
node
.
op
==
_structured_dot
:
a
,
b
=
node
.
inputs
a
,
b
=
node
.
inputs
if
a
.
type
.
format
==
'csc'
:
if
a
.
type
.
format
in
(
'csc'
,
'csr'
)
:
a_val
,
a_ind
,
a_ptr
,
a_shape
=
csm_properties
(
a
)
a_val
,
a_ind
,
a_ptr
,
a_shape
=
csm_properties
(
a
)
a_nrows
=
a_shape
[
0
]
a_nsparse
=
a_shape
[
0
]
return
[
sd_csc
(
a_val
,
a_ind
,
a_ptr
,
a_nrows
,
b
)]
sd_csx
=
sd_csc
if
a
.
type
.
format
==
'csc'
else
sd_csr
return
[
sd_csx
(
a_val
,
a_ind
,
a_ptr
,
a_nsparse
,
b
)]
return
False
return
False
register_specialize
(
local_structured_dot_csc
)
register_specialize
(
local_structured_dot
)
class
StructuredDotGrad
(
gof
.
Op
):
def
structured_dot_grad
(
sparse_A
,
dense_B
,
ga
):
def
make_node
(
self
,
a
,
b
,
g_ab
):
if
sparse_A
.
type
.
format
in
(
'csc'
,
'csr'
):
return
gof
.
Apply
(
self
,
[
a
,
b
,
g_ab
],
[
a
.
type
()])
def
perform
(
self
,
node
,
(
a
,
b
,
g_ab
),
(
out
,)):
sdgcsx
=
sdg_csc
if
sparse_A
.
type
.
format
==
'csc'
else
sdg_csr
g_a_data
=
a
.
data
.
copy
()
CSx
=
CSC
if
sparse_A
.
type
.
format
==
'csc'
else
CSR
if
a
.
format
==
'csc'
:
for
j
in
xrange
(
len
(
a
.
indptr
)
-
1
):
g_A_data
=
sdgcsx
(
csm_indices
(
sparse_A
),
\
ind0
=
a
.
indptr
[
j
]
csm_indptr
(
sparse_A
),
dense_B
,
ga
)
ind1
=
a
.
indptr
[
j
+
1
]
return
CSx
(
g_A_data
,
csm_indices
(
sparse_A
),
\
for
i_idx
in
xrange
(
ind0
,
ind1
):
csm_indptr
(
sparse_A
),
\
i
=
a
.
indices
[
i_idx
]
csm_shape
(
sparse_A
))
#v = a.data[i_idx]
#print (i, j, v)
g_a_data
[
i_idx
]
=
numpy
.
dot
(
g_ab
[
i
],
b
[
j
])
out
[
0
]
=
sparse
.
csc_matrix
((
g_a_data
,
a
.
indices
.
copy
(),
a
.
indptr
.
copy
()),
a
.
shape
,
copy
=
False
)
elif
a
.
format
==
'csr'
:
raise
NotImplementedError
()
else
:
else
:
raise
Type
Error
()
raise
NotImplemented
Error
()
_structured_dot_grad
=
StructuredDotGrad
()
class
StructuredDotGradCSC
(
gof
.
Op
):
class
StructuredDotGradCSC
(
gof
.
Op
):
def
make_node
(
self
,
a_indices
,
a_indptr
,
b
,
g_ab
):
def
make_node
(
self
,
a_indices
,
a_indptr
,
b
,
g_ab
):
...
@@ -981,7 +1131,7 @@ class StructuredDotGradCSC(gof.Op):
...
@@ -981,7 +1131,7 @@ class StructuredDotGradCSC(gof.Op):
}
}
"""
%
dict
(
locals
(),
**
sub
)
"""
%
dict
(
locals
(),
**
sub
)
_sdg
csc
=
StructuredDotGradCSC
()
sdg_
csc
=
StructuredDotGradCSC
()
class
StructuredDotGradCSR
(
gof
.
Op
):
class
StructuredDotGradCSR
(
gof
.
Op
):
...
@@ -1082,25 +1232,4 @@ class StructuredDotGradCSR(gof.Op):
...
@@ -1082,25 +1232,4 @@ class StructuredDotGradCSR(gof.Op):
}
}
"""
%
dict
(
locals
(),
**
sub
)
"""
%
dict
(
locals
(),
**
sub
)
_sdgcsr
=
StructuredDotGradCSR
()
sdg_csr
=
StructuredDotGradCSR
()
def
structured_dot_grad
(
sparse_A
,
dense_B
,
ga
):
#TODO: 1. move this switch to be a specialization of structuredDotGrad
# 2. implement StructuredDotGrad.grad()
if
0
:
return
_structured_dot_grad
(
sparse_A
,
dense_B
,
ga
)
else
:
if
sparse_A
.
type
.
format
in
(
'csc'
,
'csr'
):
sdgcsx
=
_sdgcsc
if
sparse_A
.
type
.
format
==
'csc'
else
_sdgcsr
CSx
=
CSC
if
sparse_A
.
type
.
format
==
'csc'
else
CSR
g_A_data
=
sdgcsx
(
csm_indices
(
sparse_A
),
\
csm_indptr
(
sparse_A
),
dense_B
,
ga
)
return
CSx
(
g_A_data
,
csm_indices
(
sparse_A
),
\
csm_indptr
(
sparse_A
),
\
csm_shape
(
sparse_A
))
else
:
raise
NotImplementedError
()
theano/sparse/tests/test_basic.py
浏览文件 @
04662229
...
@@ -155,60 +155,54 @@ import scipy.sparse as sp
...
@@ -155,60 +155,54 @@ import scipy.sparse as sp
class
test_structureddot
(
unittest
.
TestCase
):
class
test_structureddot
(
unittest
.
TestCase
):
def
test_structuredot
(
self
):
def
test_structuredot
(
self
):
#bsize = 5
#spmat = sp.csc_matrix((8,15))
#spmat[1,2] = 3
#spmat[4,7] = 6
#spmat[2,7] = 72
#spmat[1,9] = 2
#spmat[7,12] = 1
#spmat[4,2] = 7
bsize
=
2
bsize
=
2
spmat
=
sp
.
csc_matrix
((
5
,
5
))
spmat
=
sp
.
csc_matrix
((
5
,
5
))
spmat
[
1
,
2
]
=
1
spmat
[
0
,
1
]
=
1
spmat
[
0
,
1
]
=
2
spmat
[
0
,
2
]
=
2
spmat
[
0
,
2
]
=
3
spmat
[
1
,
2
]
=
3
spmat
[
1
,
4
]
=
4
spmat
[
3
,
4
]
=
5
kerns
=
tensor
.
dvector
(
'kerns'
)
images
=
tensor
.
dmatrix
(
'images'
)
kerns
=
tensor
.
dvector
()
##
images
=
tensor
.
dmatrix
()
# Test compressed-sparse column matrices ###
##
# build symbolic theano graph
def
buildgraphCSC
(
kerns
,
images
):
def
buildgraphCSC
(
kerns
,
images
):
csc
=
CSC
(
kerns
,
spmat
.
indices
[:
spmat
.
size
],
spmat
.
indptr
,
spmat
.
shape
)
csc
=
CSC
(
kerns
,
spmat
.
indices
[:
spmat
.
size
],
spmat
.
indptr
,
spmat
.
shape
)
return
structured_dot
(
csc
,
images
.
T
)
return
structured_dot
(
csc
,
images
.
T
)
out
=
buildgraphCSC
(
kerns
,
images
)
out
=
buildgraphCSC
(
kerns
,
images
)
f
=
theano
.
function
([
kerns
,
images
],
out
)
f
=
theano
.
function
([
kerns
,
images
],
out
)
# compute theano outputs
kernvals
=
spmat
.
data
[:
spmat
.
size
]
kernvals
=
spmat
.
data
[:
spmat
.
size
]
imvals
=
1.0
*
numpy
.
arange
(
bsize
*
spmat
.
shape
[
1
])
.
reshape
(
bsize
,
spmat
.
shape
[
1
])
imvals
=
1.0
*
numpy
.
arange
(
bsize
*
spmat
.
shape
[
1
])
.
reshape
(
bsize
,
spmat
.
shape
[
1
])
outvals
=
f
(
kernvals
,
imvals
)
outvals
=
f
(
kernvals
,
imvals
)
print
type
(
spmat
.
dot
(
imvals
.
T
))
# compare to scipy
print
spmat
.
dot
(
imvals
.
T
)
print
dir
(
spmat
.
dot
(
imvals
.
T
))
# scipy 0.7.0 should already make the output dense
# assert numpy.all(outvals == spmat.dot(imvals.T).todense())
c
=
spmat
.
dot
(
imvals
.
T
)
c
=
spmat
.
dot
(
imvals
.
T
)
assert
_is_dense
(
c
)
assert
_is_dense
(
c
)
assert
numpy
.
all
(
outvals
==
c
)
assert
numpy
.
all
(
outvals
==
c
)
tensor
.
verify_grad
(
None
,
buildgraphCSC
,
[
kernvals
,
imvals
])
tensor
.
verify_grad
(
None
,
buildgraphCSC
,
[
kernvals
,
imvals
])
##
# Test compressed-sparse row matrices ###
##
spmat
=
spmat
.
tocsr
()
spmat
=
spmat
.
tocsr
()
# build theano graph
def
buildgraphCSR
(
kerns
,
images
):
def
buildgraphCSR
(
kerns
,
images
):
csr
=
CSR
(
kerns
,
spmat
.
indices
[:
spmat
.
size
],
spmat
.
indptr
,
spmat
.
shape
)
csr
=
CSR
(
kerns
,
spmat
.
indices
[:
spmat
.
size
],
spmat
.
indptr
,
spmat
.
shape
)
return
structured_dot
(
csr
,
images
.
T
)
return
structured_dot
(
csr
,
images
.
T
)
out
=
buildgraphCSR
(
kerns
,
images
)
out
=
buildgraphCSR
(
kerns
,
images
)
f
=
theano
.
function
([
kerns
,
images
],
out
)
f
=
theano
.
function
([
kerns
,
images
],
out
)
# compute theano output
kernvals
=
spmat
.
data
[:
spmat
.
size
]
kernvals
=
spmat
.
data
[:
spmat
.
size
]
imvals
=
1.0
*
numpy
.
arange
(
bsize
*
spmat
.
shape
[
1
])
.
reshape
(
bsize
,
spmat
.
shape
[
1
])
imvals
=
1.0
*
numpy
.
arange
(
bsize
*
spmat
.
shape
[
1
])
.
reshape
(
bsize
,
spmat
.
shape
[
1
])
outvals
=
f
(
kernvals
,
imvals
)
outvals
=
f
(
kernvals
,
imvals
)
# compare to scipy
# scipy 0.7.0 should already make the output dense
# assert numpy.all(outvals == spmat.dot(imvals.T).todense())
c
=
spmat
.
dot
(
imvals
.
T
)
c
=
spmat
.
dot
(
imvals
.
T
)
assert
_is_dense
(
c
)
assert
_is_dense
(
c
)
assert
numpy
.
all
(
outvals
==
c
)
assert
numpy
.
all
(
outvals
==
c
)
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论