Skip to content

Commit 4e7d912

Browse files
author
yxdragon
committed
maxpool stride
1 parent 7278401 commit 4e7d912

4 files changed

Lines changed: 69 additions & 34 deletions

File tree

cnnumpy/io.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,38 @@ def read_net(path):
1212
def parse(matched):
1313
gps = list(matched.groups())
1414
if len(matched.groups())==0: return ''
15+
1516
for i in range(len(gps)):
16-
if not '%' in gps[i]: continue
17-
gps[i] = gps[i].replace('%',"'")
18-
gps[i] = gps[i].replace(')',"')")
19-
gps[i] = gps[i].replace(',',"',")
17+
if '%' in gps[i]:
18+
gps[i] = gps[i].replace('%',"'")
19+
gps[i] = gps[i].replace(')',"')")
20+
gps[i] = gps[i].replace(',',"',")
21+
elif gps[i][-1] == ')' and len(gps[i])>2:
22+
gps[i] = gps[i][:-1]+',)'
23+
2024
return str(gps)+'\n'
2125

22-
pt = re.compile(r'.*%(.+?) .+(\(.+\))')
23-
conv = re.compile(r'.*%(.+?) .+?(Conv).+?strides=(\[\d+?, \d+?\]).+?(\(%.+?, %.+?, %.+?\)).+?\n')
26+
conv = re.compile(r'.*%(.+?) .+?(Conv).+?dilations=(\[\d+?, \d+?\]).+?strides=(\[\d+?, \d+?\]).+?(\(%.+?, %.+?, %.+?\)).+?\n')
2427
relu = re.compile(r'.*%(.+?) .+?(Relu)\(%(.+?)\).+?\n')
2528
sigmoid = re.compile(r'.*%(.+?) .+?(Sigmoid)\(%(.+?)\).+?\n')
26-
maxpool = re.compile(r'.*%(.+?) .+?(MaxPool).+?strides=(\[\d+?, \d+?\]).+?\(%(.+?)\).+?\n')
29+
maxpool = re.compile(r'.*%(.+?) .+?(MaxPool).+?kernel_shape=(\[\d+?, \d+?\]).+?strides=(\[\d+?, \d+?\]).+?\(%(.+?)\).+?\n')
2730
upsample = re.compile(r'.*%.+? .+?Constant\[value=.+?(\d+\.?\d*) \[.+?\n.+?%(.+?) .+?(Upsample).+?\(%(.+?),.+?\n')
2831
flatten = re.compile(r'.*%.+?Constant.+?\n.+?Shape.+?\n.+?Gather.+?\n.+?Constant.+?\n.+?Unsqueeze.+?\n.+?Unsqueeze.+?\n.+?Concat.+?\n.+?%(.+?) .+?(Reshape)\(%(.+?),.+?\n')
2932
dense = re.compile(r'.*%(.+?) .+?(Gemm).+(\(%.+?, %.+?, %.+?\)).+?\n')
3033
concat = re.compile(r'.*%(.+?) .+?(Concat).+(\(%.+?\)).+?\n')
34+
batchnorm = re.compile(r'.*%(.+?) .+?(BatchNormalization).+?(\(.+?\)).+?\n')
3135
add = re.compile(r'.*%(.+?) .+?(Add)(\(%.+?\)).+?\n')
32-
weight = re.compile(r'.*%(.+?) .+?(\(.+?\)).*\n')
36+
weight = re.compile(r'.*%(.+?) .+?(\(.*?\)).*\n')
3337

34-
res = (flatten, upsample, conv, relu, sigmoid, maxpool, dense, concat, add, weight)
38+
res = (flatten, upsample, conv, relu, sigmoid, maxpool, dense, concat, add, batchnorm, weight)
3539

3640
def read_onnx(path):
3741
with open(path+'.onnx') as f:
3842
cont = f.read()
3943
for i in res: cont = i.sub(parse, cont)
4044
#for i in cont.split('\n'): print(i)
4145
cont = [eval(i) for i in cont.split('\n') if len(i)>0 and i[0]=='[']
42-
cont = [[eval(j) if ',' in j else j for j in i] for i in cont]
46+
cont = [[eval(j) if (',' in j) else j for j in i] for i in cont]
4347

4448
body = []
4549
flow = []
@@ -48,9 +52,9 @@ def read_onnx(path):
4852
if len(i)==2: key[i[0]] = i[1]
4953
elif i[1]=='Conv':
5054
num = len(body)
51-
shp = [key[i[3][1]][j] for j in (1,0,2)] + [i[2][0]]
55+
shp = [key[i[4][1]][j] for j in (1,0,2)] + [i[3][0], i[2][0]]
5256
body.append(('conv_%s'%num, 'conv', shp))
53-
flow.append((i[3][0], ['conv_%s'%num], i[0]))
57+
flow.append((i[4][0], ['conv_%s'%num], i[0]))
5458
elif i[1]=='Gemm':
5559
num = len(body)
5660
body.append(('dense_%s'%num, 'dense', key[i[2][1][::-1]]))
@@ -73,16 +77,24 @@ def read_onnx(path):
7377
flow.append((i[2], ['concat_%s'%num], i[0]))
7478
elif i[1]=='MaxPool':
7579
num = len(body)
76-
body.append(('maxpool_%s'%num, 'maxpool', [i[2][0]]))
77-
flow.append((i[3], ['maxpool_%s'%num], i[0]))
80+
body.append(('maxpool_%s'%num, 'maxpool', [i[2][0], i[3][0]]))
81+
flow.append((i[4], ['maxpool_%s'%num], i[0]))
7882
elif i[2]=='Upsample':
7983
num = len(body)
8084
body.append(('upsample_%s'%num, 'upsample', [int(float(i[0]))]))
8185
flow.append((i[3], ['upsample_%s'%num], i[1]))
86+
elif i[1]=='BatchNormalization':
87+
num = len(body)
88+
body.append(('batchnorm_%s'%num, 'batchnorm', [key[i[2][1]][0]]))
89+
flow.append((i[2][0], ['batchnorm_%s'%num,], i[0]))
8290
elif i[1]=='Reshape':
8391
num = len(body)
8492
body.append(('flatten_%s'%num, 'flatten', None))
8593
flow.append((i[2], ['flatten_%s'%num], i[0]))
94+
95+
#for i in body: print(i)
96+
#for i in flow: print(i)
97+
8698
net = Net()
8799
net.load_json(body, flow)
88100
net.load_weights(np.load(path+'.npy'))

cnnumpy/layer.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,17 @@ def load(self, buf):
3838

3939
class Conv2d(Layer):
4040
name = 'conv'
41-
def __init__(self, c, n, w, s):
42-
self.n, self.c, self.w, self.s = n, c, w, s
41+
def __init__(self, c, n, w, s=1, d=1):
42+
self.n, self.c, self.w = n, c, w
43+
self.s, self.d = s, d
4344
self.K = np.zeros((n, c, w, w), dtype=np.float32)
4445
self.bias = np.zeros(n, dtype=np.float32)
4546

46-
def para(self): return self.n, self.c, self.w, self.s
47+
def para(self):
48+
return self.n, self.c, self.w, self.s, self.d
4749

4850
def forward(self, x):
49-
out = conv(x, self.K, (self.s, self.s))
51+
out = conv(x, self.K, (self.s, self.s), (self.d, self.d))
5052
out += self.bias.reshape((1, -1, 1, 1))
5153
return out
5254

@@ -88,13 +90,13 @@ def forward(self, x):
8890

8991
class Maxpool(Layer):
9092
name = 'maxpool'
91-
def __init__(self, stride=2):
93+
def __init__(self, w=2, stride=2):
9294
self.stride = stride
9395

9496
def para(self): return (self.stride,)
9597

9698
def forward(self, x):
97-
return maxpool(x, (self.stride, self.stride))
99+
return maxpool(x, (self.w, self.w), (self.stride, self.stride))
98100

99101
class UpSample(Layer):
100102
name = 'upsample'
@@ -113,7 +115,18 @@ def __init__(self): pass
113115
def forward(self, x):
114116
return np.concatenate(x, axis=1)
115117

116-
layerkey = {'dense':Dense, 'conv':Conv2d, 'relu':ReLU,
118+
class BatchNorm(Layer):
119+
name = 'batchnorm'
120+
def __init__(self, c):
121+
self.c = c
122+
123+
def forward(self, x):
124+
return x
125+
126+
def load(self, buf):
127+
return self.c * 2
128+
129+
layerkey = {'dense':Dense, 'conv':Conv2d, 'relu':ReLU, 'batchnorm':BatchNorm,
117130
'flatten':Flatten, 'sigmoid':Sigmoid, 'softmax': Softmax,
118131
'maxpool':Maxpool, 'upsample':UpSample, 'concat':Concatenate}
119132

cnnumpy/net.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ def forward(self, x):
2121
p = [rst[i] for i in out]
2222
else: p = rst[out]
2323
rst[y] = dic[l](p)
24+
#print(l, 'in:', out, 'out', y, rst[y].sum())
2425
return rst[y]
2526

2627
def layer2code(self, style='list'):

cnnumpy/util.py

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55

66
if njit is None: print('install numba can double speed!')
77

8-
def neighbors(shape, core, offset=0):
8+
def neighbors(shape, core, offset=0, dilation=1):
99
shp = [slice(0,i) for i in core]
1010
idx = np.mgrid[tuple(shp)]
1111
idx = idx.reshape((len(core),-1))
12-
offset = np.array(core)//2*offset
12+
offset = (np.array(core)-1)//2*offset
1313
idx -= offset.reshape((-1,1))
14+
idx.T[:] *= dilation
1415
acc = np.cumprod((1,)+shape[::-1][:-1])
1516
return np.dot(idx.T, acc[::-1])
1617

@@ -31,7 +32,7 @@ def fill_col(pdimg, idx, colimg):
3132

3233
if not njit is None: fill_col = njit(jit_fill_col)
3334

34-
def conv(img, core, stride=(1,1), buf=['']):
35+
def conv(img, core, stride=(1,1), dilation=(1,1), buf=['']):
3536
# new the col_img, if needed
3637
strh, strw = stride
3738
cimg_w = np.cumprod(core.shape[1:])[-1]
@@ -48,10 +49,10 @@ def conv(img, core, stride=(1,1), buf=['']):
4849
iimg &= 0xfffffffe
4950
iimg[:,0,::strh,::strw] |= 1
5051
# ravel the image
51-
n,c,h,w = np.array(core.shape)
52-
shp = ((0,0),(0,0),(h//2,h//2),(w//2,w//2))
52+
(n,c,h,w), (dh, dw) = core.shape, dilation
53+
shp = ((0,0),(0,0),(h*dh//2,h*dh//2),(w*dw//2,w*dw//2))
5354
pdimg = np.pad(iimg, shp, 'constant', constant_values=0)
54-
nbs = neighbors(pdimg.shape[1:], core.shape[1:], (0,1,1))
55+
nbs = neighbors(pdimg.shape[1:], core.shape[1:], (0,1,1), (1, dh, dw))
5556
fill_col(pdimg.ravel(), nbs, col_img)
5657
col_img = col_img.view(np.float32)
5758
col_img = col_img.reshape((cimg_h, cimg_w))
@@ -61,7 +62,6 @@ def conv(img, core, stride=(1,1), buf=['']):
6162
ni, ci, hi, wi = img.shape
6263
return rst.reshape((ni, n, hi//strh, wi//strw))
6364

64-
6565
def jit_fill_max(pdimg, idx, colimg):
6666
s = 0
6767
for i in range(len(pdimg)):
@@ -79,19 +79,21 @@ def fill_max(pdimg, idx, colimg):
7979

8080
if not njit is None: fill_max = njit(jit_fill_max)
8181

82-
def maxpool(img, stride=(2,2)):
82+
def maxpool(img, core=(2,2), stride=(2,2)):
8383
strh, strw = stride
84-
n,c,h,w = img.shape
85-
cimg_h = n*c*(h//strh)*(w//strw)
84+
(n,c,h,w), (ch, cw) = img.shape, core
8685

8786
iimg = img.view(dtype=np.int32)
8887
iimg &= 0xfffffffe
8988
iimg[:,:,::strh,::strw] |= 1
9089

91-
nbs = neighbors(img.shape[1:], (1,)+stride)
90+
shp = ((0,0),(0,0),((ch-1)//2,)*2,((cw-1)//2,)*2)
91+
if np.array(shp).sum()==0: pdimg = iimg
92+
else: pdimg = np.pad(iimg, shp, 'constant', constant_values=0)
93+
nbs = neighbors(pdimg.shape[1:], (1,)+core, (0,1,1))
9294
shp = (n, c, h//strh, w//strw)
9395
colimg = np.zeros(shp, dtype=np.int32)
94-
fill_max(iimg.ravel(), nbs, colimg.ravel())
96+
fill_max(pdimg.ravel(), nbs, colimg.ravel())
9597
return colimg.view(np.float32)
9698

9799
def jit_resize(img, k, ra, rb, rs, _rs, ca, cb, cs, _cs, out):
@@ -137,6 +139,7 @@ def upsample(img, k, out=None):
137139
return out
138140

139141
if __name__ == '__main__':
142+
'''
140143
from skimage.data import camera
141144
import matplotlib.pyplot as plt
142145
from scipy.ndimage import convolve
@@ -152,4 +155,10 @@ def upsample(img, k, out=None):
152155
153156
start = time()
154157
rst2 = conv(img, core, (1,1))
155-
print('numpy cost:', time()-start)
158+
print('numpy cost:', time()-start)
159+
'''
160+
##nbs = neighbors((4, 5, 6), (3,3,3), offset = (0,1,1), dilation=(1,2,2))
161+
##print(nbs)
162+
arr = np.arange(16).reshape((1,1,4,4)).astype(np.float32)
163+
rst = maxpool(arr, (2,2), (2,2))
164+

0 commit comments

Comments
 (0)