Skip to content

Commit 88739ea

Browse files
committed
adding upsample support
1 parent 3e279cd commit 88739ea

5 files changed

Lines changed: 96 additions & 83 deletions

File tree

infCNN/LayerLib.py

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,29 @@
11
from .Core import Layer
2-
from .conv import conv
2+
from .conv_s import conv
33
import numpy as np
44

5+
56
class Dense(Layer):
67

78
def __init__(self, n_in, n_out):
89
super().__init__('dense_{}_{}'.format(n_in, n_out))
910
self.n_in, self.n_out = n_in, n_out
10-
self.K = np.zeros((n_out, n_in), dtype=np.float32)
11+
self.K = np.zeros((n_out, n_in), dtype=np.float32)
1112
self.bias = np.zeros(n_out, dtype=np.float32)
1213

1314
def forward(self, x):
1415
self.x = x
1516
y = x.dot(self.K.T)
16-
y += self.bias.reshape((1,-1))
17+
y += self.bias.reshape((1, -1))
1718
return y
1819

1920
def load_from_torch(self, weights, bias):
2021
self.K = weights.copy()
2122
self.bias = bias.copy()
22-
23+
2324

2425
class Conv2d(Layer):
25-
26+
2627
def __init__(self, C_in, C_out, K_s, Stride):
2728
"""
2829
Params:
@@ -33,27 +34,24 @@ def __init__(self, C_in, C_out, K_s, Stride):
3334
self.c_out = C_out
3435
self.k_s = K_s
3536
self.stride = Stride
36-
self.pad_size = int((K_s -1)/2)
37+
self.pad_size = int((K_s - 1)/2)
3738
self.K = np.zeros((C_out, C_in, K_s, K_s), dtype='float32')
3839
self.bias = np.zeros(C_out, dtype='float32')
3940

4041
def forward(self, X):
41-
out = conv(X, self.K)
42-
out += self.bias.reshape((1,-1,1,1))
42+
out = conv(X, self.K, (self.stride, self.stride))
43+
out += self.bias.reshape((1, -1, 1, 1))
4344
return out
44-
45+
4546
def load_from_torch(self, weights, bias):
4647
self.K = weights.copy()
4748
self.bias = bias.copy()
4849

4950

50-
51-
5251
if __name__ == "__main__":
5352
# data = np.arange(16).reshape((1, 1, 4, 4))
5453
data = np.random.randn(2, 3, 200, 200)
5554

56-
5755
import torch.nn as nn
5856
import torch
5957
from time import time
@@ -68,7 +66,7 @@ def load_from_torch(self, weights, bias):
6866
start = time()
6967
out_torch = conv_torch(torch.FloatTensor(data)).detach().numpy()
7068
print('torch time:', time() - start)
71-
69+
7270
conv.load_from_torch(w, b)
7371
start = time()
7472
out = conv(data)
@@ -78,7 +76,6 @@ def load_from_torch(self, weights, bias):
7876
print('acw:', out.shape)
7977
print(np.sum(out-out_torch))
8078

81-
8279
data = np.random.randn(2, 10)
8380

8481
dense_torch = nn.Linear(10, 20)

infCNN/OpLib.py

Lines changed: 7 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
from .Core import Op
1+
from .Core import Op
22
import numpy as np
3-
from .im2col import im2col_indices
43
from .maxpool import maxpool
4+
from .upsample import upsample
5+
56

6-
77
class ReLU(Op):
88

99
def __init__(self):
1010
super().__init__('ReLU')
1111

1212
def forward(self, x):
1313
self.x = x
14-
return (x>0) * x
14+
return (x > 0) * x
1515

1616

1717
class Flatten(Op):
@@ -34,6 +34,7 @@ def forward(self, x):
3434
self.x = x
3535
return 1/(1 + np.exp(-x))
3636

37+
3738
class Softmax(Op):
3839
def __init__(self):
3940
super().__init__('Sofmax')
@@ -43,48 +44,9 @@ def forward(self, X, axis=-1):
4344
return (eX.T / eX.sum(axis=axis)).T
4445

4546

46-
47-
48-
class MaxPool(Op):
49-
50-
def __init__(self, size=2, stride=2):
51-
super().__init__('MaxPool_{}x{}s{}'.format(size, size, stride))
52-
self.size = size
53-
self.stride = stride
54-
55-
def _pool_forward(self, X, pool_fun, size=2, stride=2):
56-
n, d, h, w = X.shape
57-
h_out = (h - size) / stride + 1
58-
w_out = (w - size) / stride + 1
59-
60-
if not w_out.is_integer() or not h_out.is_integer():
61-
raise Exception('Invalid output dimension!')
62-
63-
h_out, w_out = int(h_out), int(w_out)
64-
65-
X_reshaped = X.reshape(n * d, 1, h, w)
66-
X_col = im2col_indices(X_reshaped, size, size, padding=0, stride=stride)
67-
68-
out, pool_cache = pool_fun(X_col)
69-
70-
out = out.reshape(h_out, w_out, n, d)
71-
out = out.transpose(2, 3, 0, 1)
72-
73-
cache = (X, size, stride, X_col, pool_cache)
74-
75-
return out# , cache
76-
77-
def maxpool(self, X_col):
78-
max_idx = np.argmax(X_col, axis=0)
79-
out = X_col[max_idx, range(max_idx.size)]
80-
return out, max_idx
81-
82-
def forward(self, x):
83-
return self._pool_forward(x, self.maxpool, self.size, self.stride)
84-
85-
8647
relu = ReLU()
8748
flatten = Flatten()
8849
sigmoid = Sigmoid()
8950
softmax = Softmax()
90-
maxpool = maxpool
51+
maxpool = maxpool
52+
upsample = upsample

infCNN/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
from .LayerLib import *
22
from .OpLib import *
3-
from .numpy_extend import *

infCNN/conv_s.py

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,61 +2,66 @@
22
from time import time
33
from numba import njit
44

5+
56
def neighbors(shape, core):
6-
shp = [slice(0,i) for i in core]
7+
shp = [slice(0, i) for i in core]
78
idx = np.mgrid[tuple(shp)]
8-
idx = idx.reshape((len(core),-1))
9+
idx = idx.reshape((len(core), -1))
910
offset = np.array(core)//2
1011
offset[0] = 0
11-
idx -= offset.reshape((-1,1))
12+
idx -= offset.reshape((-1, 1))
1213
acc = np.cumprod((1,)+shape[::-1][:-1])
1314
return np.dot(idx.T, acc[::-1])
1415

16+
1517
@njit
1618
def fill_col(pdimg, idx, colimg):
1719
s = 0
1820
for i in range(len(pdimg)):
19-
if pdimg[i]&1==0: continue
21+
if pdimg[i] & 1 == 0:
22+
continue
2023
for j in idx:
2124
colimg[s] = pdimg[i+j]
2225
s += 1
2326
return colimg
2427

25-
def img2col(img, core, stride=(1,1), buf=[np.zeros(1, dtype=np.int32)]):
28+
29+
def conv(img, core, stride=(1, 1), buf=[np.zeros(1, dtype=np.int32)]):
2630
# new the col_img, if needed
2731
strh, strw = stride
2832
cimg_w = np.cumprod(core.shape[1:])[-1]
29-
print(img.shape)
30-
n,c,h,w = img.shape
33+
# print(img.shape)
34+
n, c, h, w = img.shape
3135
cimg_h = n*(h//strh)*(w//strw)
32-
33-
if len(buf[0])<cimg_h*cimg_w:
36+
37+
if len(buf[0]) < cimg_h*cimg_w:
3438
buf[0] = col_img = np.zeros(cimg_h*cimg_w, dtype=np.int32)
3539
else:
3640
col_img = buf[0][:cimg_h*cimg_w]
3741
col_img[:] = 0
38-
42+
3943
# mark where need
4044
iimg = img.view(dtype=np.int32)
41-
#iimg.view(dtype=np.uint8).ravel()[::4]&=0xfe
45+
# iimg.view(dtype=np.uint8).ravel()[::4]&=0xfe
4246
iimg &= 0xfffffffe
43-
iimg[:,0,::strh,::strw] |= 1
44-
47+
iimg[:, 0, ::strh, ::strw] |= 1
48+
4549
# ravel the image
46-
n,c,h,w = np.array(core.shape)
47-
shp = ((0,0),(0,0),(h//2,h//2),(w//2,w//2))
50+
n, c, h, w = np.array(core.shape)
51+
shp = ((0, 0), (0, 0), (h//2, h//2), (w//2, w//2))
4852
pdimg = np.pad(iimg, shp, 'constant', constant_values=0)
4953
nbs = neighbors(pdimg.shape[1:], core.shape[1:])
5054
fill_col(pdimg.ravel(), nbs, col_img)
5155
col_img = col_img.view(np.float32)
5256
col_img = col_img.reshape((cimg_h, cimg_w))
53-
57+
5458
# dot
55-
col_core = core.reshape((core.shape[0],-1))
59+
col_core = core.reshape((core.shape[0], -1))
5660
rst = col_core.dot(col_img.T)
5761
ni, ci, hi, wi = img.shape
5862
return rst.reshape((ni, n, hi//strh, wi//strw))
5963

64+
6065
if __name__ == '__main__':
6166
from skimage.data import camera
6267
import matplotlib.pyplot as plt
@@ -65,16 +70,16 @@ def img2col(img, core, stride=(1,1), buf=[np.zeros(1, dtype=np.int32)]):
6570
img.ravel()[:] = np.arange(3*512*512)
6671

6772
iimg = img.view(dtype=np.int32)
68-
iimg.view(dtype=np.uint8).ravel()[::4]&=0xfe
69-
iimg[:,0,:,:] |= 1
70-
73+
iimg.view(dtype=np.uint8).ravel()[::4] &= 0xfe
74+
iimg[:, 0, :, :] |= 1
75+
7176
core = np.zeros((32, 3, 3, 3), dtype=np.float32)
7277
core.ravel()[:] = np.arange(3*3*3*32)
73-
78+
7479
start = time()
75-
rst1 = img2col(img, core, (1,1))
80+
rst1 = img2col(img, core, (1, 1))
7681
print(time()-start)
7782

7883
start = time()
79-
rst2 = img2col(img, core, (2,2))
84+
rst2 = img2col(img, core, (2, 2))
8085
print('jit cost: x10', time()-start)

infCNN/upsample.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import numpy as np
2+
from numba import njit
3+
from math import floor
4+
5+
@njit
6+
def _resize(img, k, ra, rs, _rs, ca, cs, _cs, out):
7+
h, w = img.shape
8+
for r in range(h*k):
9+
rar = ra[r]
10+
rbr = rar + 1
11+
rsr = rs[r]
12+
_rsr = _rs[r]
13+
for c in range(w*k):
14+
cac = ca[c]
15+
cbc = cac + 1
16+
rra = img[rar,cac]*_rsr
17+
rra += img[rbr,cac]*rsr
18+
rrb = img[rar,cbc]*_rsr
19+
rrb += img[rbr,cbc]*rsr
20+
rcab = rra * _cs[c] + rrb * cs[c]
21+
out[r,c] = rcab
22+
23+
def upsample(img, k=2, out=None):
24+
nc, (h, w), e = img.shape[:-2], img.shape[-2:], 1e-4
25+
if out is None:
26+
out = np.zeros(nc+(h*k, w*k), dtype=img.dtype)
27+
28+
rs = np.linspace(e,h-1-e, h*k, dtype=np.float32)
29+
cs = np.linspace(e,w-1-e, w*k, dtype=np.float32)
30+
ra = np.floor(rs).astype(np.uint32)
31+
ca = np.floor(cs).astype(np.uint32)
32+
rs -= ra
33+
cs -= ca
34+
35+
outcol = out.reshape((-1, h*k, w*k))
36+
imgcol = img.reshape((-1, h, w))
37+
for i, o in zip(imgcol, outcol):
38+
_resize(i, k, ra, rs, 1-rs, ca, cs, 1-cs, o)
39+
return out
40+
41+
if __name__ == '__main__':
42+
from time import time
43+
from skimage.data import astronaut
44+
img = astronaut().transpose(2,0,1).astype(np.float32)
45+
46+
# firs time to jit
47+
resize(img, 2)
48+
start = time()
49+
rst = resize(img, 2)
50+
print('\nmine v1', time()-start)

0 commit comments

Comments
 (0)