nodev 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
__init__.py ADDED
File without changes
nodev/__init__.py ADDED
@@ -0,0 +1,18 @@
1
+ from nodev.core import Datafield
2
+ from nodev.core import Operation
3
+ from nodev.core import using_config
4
+ from nodev.core import no_grad
5
+ from nodev.core import as_array
6
+ from nodev.core import as_datafield
7
+ from nodev.core import setup_datafield
8
+ from nodev import operations,operations_conv
9
+ from nodev.core import Formpara
10
+ from nodev.layers import Layer
11
+ from nodev.layers import Linear
12
+ from nodev.model import Model
13
+ from nodev.dataloaders import Dataloader
14
+ from nodev.core import test_mode
15
+ from nodev.core import Config
16
+ from nodev import cuda
17
+ from nodev import dataset
18
+ setup_datafield()
nodev/core.py ADDED
@@ -0,0 +1,297 @@
1
+
2
+
3
+ import numpy as np
4
+ import weakref
5
+ from contextlib import contextmanager
6
+
7
+ import nodev
8
+
9
+ try:
10
+ import cupy
11
+ array_types=(np.ndarray,cupy.ndarray)
12
+ except ImportError:
13
+ array_types=(np.ndarray)
14
+ class Config:
15
+ enable_backprop=True
16
+ train=True
17
+
18
+ class Datafield:
19
+ __array_priority__=200
20
+ def __init__(self,data,name=None):
21
+ if data is not None:
22
+ if not isinstance(data, np.ndarray): #是判断 “x 是否属于类型 T”
23
+ raise TypeError('{} is not supported'.format(type(data)))
24
+ self.data=data
25
+ self.grad=None
26
+ self.name=name
27
+ self.creator=None
28
+ self.generation=0
29
+ def __sub__(self,other):
30
+ return sub(self,other)
31
+ def __neg__(self):
32
+ return neg(self)
33
+ def __mul__(self,other):
34
+ return mul(self,other)
35
+ def __repr__(self):
36
+ if self.data is None:
37
+ return 'Datafield(None)'
38
+ p=str(self.data).replace('\n','\n'+' '*9)
39
+ return 'Datafield(' + p +')'
40
+ def __truediv__(self, other):
41
+ return div(self,other)
42
+ def __rtruediv__(self, other):
43
+ return rdiv(self,other)
44
+ def __len__(self): return len(self.data)
45
+ def __add__(self,other):
46
+ return add(self,other)
47
+ def __rmul__(self,other):
48
+ return mul(other,self)
49
+
50
+ def __radd__(self,other):
51
+ return add(other, self)
52
+ def __pow__(self, power, modulo=None):
53
+ return pow(self,power)
54
+ def __getitem__(self, slices):
55
+ return nodev.operations.get_item(self, slices)
56
+
57
+ def max(self, axis=None, keepdims=False):
58
+ """返回最大值"""
59
+ return nodev.operations.max(self, axis, keepdims)
60
+
61
+ def min(self, axis=None, keepdims=False):
62
+ """返回最小值"""
63
+ return nodev.operations.min(self, axis, keepdims)
64
+ def reshape(self,*shape):
65
+ if len(shape)==1 and isinstance(shape[0],(tuple,list)):
66
+ shape=shape[0]
67
+ return nodev.operations.reshape(self,shape)
68
+ def transpose(self):
69
+ return nodev.operations.transpose(self)
70
+ @property
71
+ def T(self):
72
+ return nodev.operations.transpose(self)
73
+ @property
74
+ def size(self):
75
+ return self.data.size
76
+ def unchain(self):
77
+ self.creator=None
78
+ @property
79
+ def ndim(self):
80
+ return self.data.ndim
81
+ @property
82
+ def shape(self): #取出shape
83
+ return self.data.shape
84
+ @property
85
+ def dtype(self):
86
+ return self.data.dtype
87
+ def clear_grad(self):
88
+ self.grad=None
89
+ def to_cpu(self):
90
+ if self.data is not None:
91
+ self.data=nodev.cuda.as_numpy(self.data)
92
+ def to_gpu(self):
93
+ if self.data is not None:
94
+ self.data=nodev.cuda.as_cupy(self.data)
95
+ def set_creator(self,func):
96
+ self.creator=func #储存当前节点的上一个节点??
97
+ self.generation=func.generation+1
98
+
99
+ def sum(self, axis=None, keepdims=False):
100
+ return nodev.operations.sum(self, axis, keepdims)
101
+ def backward(self, retain_grad=False, create_graph=False):
102
+ if self.grad is None:
103
+ xp=nodev.cuda.get_array_module(self.data)
104
+ self.grad=Datafield(xp.ones_like(self.data)) #创建一个全 1 张量,形状和 data 一样
105
+ #self.grad=Datafield(np.ones_like(self.data))
106
+ funcs=[]
107
+ seen_set=set()
108
+ def add_func(f): #寻找层数最大的因子进行求导
109
+ if f not in seen_set:
110
+ funcs.append(f)
111
+ seen_set.add(f)
112
+ funcs.sort(key=lambda x:x.generation)
113
+ if self.creator is not None:
114
+ add_func(self.creator)
115
+ while funcs:
116
+ f=funcs.pop() #压出最后一个元素
117
+ gys=[output().grad for output in f.outputs] #汇总导数
118
+ #gys = [output.grad for output in f.outputs] # 汇总导数
119
+ with using_config('enable_backprop',create_graph):
120
+ gxs=f.backward(*gys)
121
+ if not isinstance(gxs,tuple):
122
+ gxs=(gxs,)
123
+ for x,gx in zip(f.inputs,gxs):
124
+ if x.grad is None:
125
+ x.grad=gx
126
+ else:
127
+ x.grad=x.grad+gx
128
+ if x.creator is not None:
129
+ #funcs.append(x.creator)
130
+ add_func(x.creator)
131
+ def unchain_backward(self):
132
+ if self.creator is not None:
133
+ funcs=[self.creator]
134
+ while funcs:
135
+ f=funcs.pop()
136
+ for x in f.inputs:
137
+ if x.creator is not None:
138
+ x.unchain()
139
+ class Operation:
140
+ def __call__(self,*inputs):
141
+ inputs=[as_datafield(x) for x in inputs]
142
+ xs=[i.data for i in inputs]
143
+ ys=self.forward(*xs)
144
+ if not isinstance(ys,tuple):
145
+ ys=(ys,)
146
+ outputs=[Datafield(as_array(y)) for y in ys]
147
+ if Config.enable_backprop:
148
+ self.generation=max([x.generation for x in inputs])
149
+ for output in outputs:
150
+ output.set_creator(self)
151
+ self.inputs = inputs
152
+ self.outputs=[weakref.ref(output) for output in outputs]
153
+ return outputs if len(outputs)>1 else outputs[0]
154
+ def forward(self,*xs):
155
+ raise NotImplementedError()
156
+ def backward(self,*xs):
157
+ raise NotImplementedError()
158
+
159
+
160
+ class Pow(Operation):
161
+ def __init__(self,c):
162
+ self.c=c
163
+ def forward(self,x):
164
+ y=x**self.c
165
+ return y
166
+ def backward(self,gy):
167
+ x, = self.inputs
168
+ c=self.c
169
+ gx=c*x**(c-1)*gy
170
+ return gx
171
+ class Div(Operation):
172
+ def forward(self,x0,x1):
173
+ self.x0_shape, self.x1_shape = x0.shape, x1.shape
174
+ y=x0/x1
175
+ return y
176
+ def backward(self,gy):
177
+ x0,x1=self.inputs
178
+
179
+ gx0=gy/x1
180
+ gx1=gy*(-x0/x1**2)
181
+ if self.x0_shape!=self.x1_shape:
182
+ gx0=nodev.operations.sum_to(gx0,self.x0_shape)
183
+ gx1 = nodev.operations.sum_to(gx1, self.x1_shape)
184
+ return gx0,gx1
185
+
186
+
187
+ class Add(Operation):
188
+ def forward(self,x0,x1):
189
+ self.x0_shape,self.x1_shape=x0.shape,x1.shape
190
+ y=x0+x1
191
+ return y
192
+ def backward(self,gy):
193
+ gx0,gx1=gy,gy
194
+ if self.x0_shape!=self.x1_shape:
195
+ gx0=nodev.operations.sum_to(gx0,self.x0_shape)
196
+ gx1 = nodev.operations.sum_to(gx1, self.x1_shape)
197
+ return gx0,gx1
198
+
199
+ class Neg(Operation):
200
+ def forward(self,x):
201
+ return -x
202
+ def backward(self,gy):
203
+ return -gy
204
+ class Mul(Operation):
205
+ def forward(self,x0,x1):
206
+ self.x0_shape, self.x1_shape = x0.shape, x1.shape
207
+ y=x0*x1
208
+ return y
209
+ def backward(self,gy):
210
+ x0,x1=self.inputs
211
+ gx0,gx1=x1*gy,x0*gy
212
+ if self.x0_shape!=self.x1_shape:
213
+ gx0=nodev.operations.sum_to(gx0,self.x0_shape)
214
+ gx1 = nodev.operations.sum_to(gx1, self.x1_shape)
215
+ return gx0,gx1
216
+ class Sub(Operation):
217
+ def forward(self,x0,x1):
218
+ self.x0_shape, self.x1_shape = x0.shape, x1.shape
219
+ y=x0-x1
220
+ return y
221
+ def backward(self,gy):
222
+ gx0,gx1=gy,-gy
223
+ if self.x0_shape!=self.x1_shape:
224
+ gx0=nodev.operations.sum_to(gx0,self.x0_shape)
225
+ gx1 = nodev.operations.sum_to(gx1, self.x1_shape)
226
+ return gx0,gx1
227
+
228
+ class Formpara(Datafield):
229
+ pass
230
+
231
+
232
+
233
+
234
+ @contextmanager
235
+ def test_mode():
236
+ old_value = Config.train
237
+ Config.train = False
238
+ try:
239
+ yield
240
+ finally:
241
+ Config.train = old_value
242
+
243
+ @contextmanager
244
+ def using_config(name,value):
245
+ old_value=getattr(Config,name)
246
+ setattr(Config,name,value)
247
+ try:
248
+ yield
249
+ finally:
250
+ setattr(Config,name,old_value)
251
+ def as_datafield(obj): #转换普通数据为variable
252
+ if isinstance(obj, Datafield):
253
+ return obj
254
+ return Datafield(as_array(obj))
255
+ def div(x0,x1):
256
+ x1 = as_array(x1, nodev.cuda.get_array_module(x0.data))
257
+ return Div()(x0,x1)
258
+ def rdiv(x0,x1):
259
+ x1 = as_array(x1, nodev.cuda.get_array_module(x0.data))
260
+ return Div()(x1,x0)
261
+ def sub(x1,x2):
262
+ return Sub()(x1,x2)
263
+
264
+ def as_array(x,array_module=np):
265
+ """ if x is None: # ⭐必须加
266
+ return None"""
267
+ if np.isscalar(x):
268
+ return array_module.array(x)
269
+ return x
270
+ def pow(x,c):
271
+ return Pow(c)(x)
272
+
273
+ def add(x0,x1):
274
+ x1=as_array(x1,nodev.cuda.get_array_module(x0.data))
275
+ return Add()(x0,x1)
276
+ def mul(x0,x1):
277
+ x1 = as_array(x1, nodev.cuda.get_array_module(x0.data))
278
+ return Mul()(x0,x1)
279
+ def neg(x):
280
+ return Neg()(x)
281
+ def rsub(x0,x1):
282
+ x1=as_array(x1)
283
+ return Sub()(x1,x0)
284
+ def no_grad():
285
+ return using_config('enable_backprop',False)
286
+
287
+ def setup_datafield():
288
+ Datafield.__mul__ = mul
289
+ Datafield.__add__ = add
290
+ Datafield.__rmul__ = mul
291
+ Datafield.__radd__ = add
292
+ Datafield.__neg__ = neg
293
+ Datafield.__pow__ = pow
294
+ Datafield.__truediv__ = div
295
+ Datafield.__rtruediv__ = rdiv
296
+ Datafield.__sub__ = sub
297
+ Datafield.__rsub__ = rsub
nodev/cuda.py ADDED
@@ -0,0 +1,27 @@
1
+ import numpy as np
2
+ gpu_enable=True
3
+ try:
4
+ import cupy as cp
5
+ cupy=cp
6
+ except ImportError:
7
+ gpu_enable=False
8
+ from nodev import Datafield
9
+ def get_array_module(x):
10
+ if isinstance(x, Datafield):
11
+ x=x.data
12
+ if not gpu_enable:
13
+ return np
14
+ xp=cp.get_array_module(x)
15
+ return xp
16
+ def as_numpy(x):
17
+ if isinstance(x, Datafield):
18
+ x=x.data
19
+ if np.isscalar(x):
20
+ return np.array(x)
21
+ def as_cupy(x):
22
+ if isinstance(x, Datafield):
23
+ x = x.data
24
+ if not gpu_enable:
25
+
26
+ raise Exception('CuPy无法使用,请检查是否安装')
27
+ return cp.asarray(x)
nodev/dataloaders.py ADDED
@@ -0,0 +1,65 @@
1
+ import math
2
+
3
+ import numpy as np
4
+ from nodev import cuda
5
+
6
+
7
+ class Dataloader:
8
+ def __init__(self,dataset,batch_size,shuffle=True,gpu=False):
9
+ self.dataset=dataset
10
+ self.batch_size=batch_size
11
+ self.shuffle=shuffle
12
+ self.data_size=len(dataset)
13
+ self.gpu=gpu
14
+ self.max_iter=math.ceil(self.data_size/batch_size)
15
+ self.reset()
16
+
17
+
18
+ def reset(self):
19
+ self.iteration=0
20
+ if self.shuffle:
21
+ self.index=np.random.permutation(len(self.dataset))
22
+ else:
23
+ self.index=np.arange(len(self.dataset))
24
+ def __iter__(self):
25
+ return self
26
+
27
+ def __next__(self):
28
+ if self.iteration>=self.max_iter:
29
+ self.reset()
30
+ raise StopIteration
31
+ i,batch_size=self.iteration,self.batch_size
32
+ batch_index=self.index[i*batch_size:(i+1)*batch_size]
33
+ batch=[self.dataset[i] for i in batch_index]
34
+ xp=cuda.cupy if self.gpu else np
35
+ x=xp.array([example[0] for example in batch])
36
+ t = xp.array([example[1] for example in batch])
37
+ self.iteration+=1
38
+
39
+
40
+ return x,t
41
+ def next(self):
42
+ return self.__next__()
43
+ def to_cpu(self):
44
+ self.gpu=False
45
+
46
+ def to_gpu(self):
47
+ self.gpu = True
48
+
49
+
50
+
51
+ class SeqDataLoader(Dataloader):
52
+ def __init__(self,dataset,batch_size,gpu=False):
53
+ super().__init__(dataset=dataset,batch_size=batch_size,shuffle=False,gpu=gpu)
54
+ def __next__(self):
55
+ if self.iteration>=self.max_iter:
56
+ self.reset()
57
+ raise StopIteration
58
+ jump=self.data_size//self.batch_size
59
+ batch_index=[(i*jump+self.iteration)%self.data_size for i in range(self.batch_size)]
60
+ batch=[self.dataset[i] for i in batch_index]
61
+ xp=cuda.cupy if self.gpu else np
62
+ x=xp.array([example[0] for example in batch])
63
+ t = xp.array([example[1] for example in batch])
64
+ self.iteration+=1
65
+ return x,t
nodev/dataset.py ADDED
@@ -0,0 +1,186 @@
1
+
2
+ import numpy as np
3
+
4
+ from nodev.transforms import Compose, Flatten, ToFloat, Normalize
5
+
6
+ class Dataset():
7
+ def __init__(self,train=True,transform=None,target_transform=None):
8
+ self.train=train
9
+ self.transform=transform
10
+ self.target_transform=target_transform
11
+ if self.transform is None:
12
+ self.transform=lambda x:x
13
+ if self.target_transform is None:
14
+ self.target_transform = lambda x: x
15
+
16
+ self.data=None
17
+ self.label=None
18
+ self.prepare()
19
+ def __getitem__(self, index):
20
+ assert np.isscalar(index)
21
+ if self.label is None:
22
+ return self.transform(self.data[index]),None
23
+ else:
24
+ return self.transform(self.data[index]),\
25
+ self.target_transform(self.label[index])
26
+ def prepare(self):
27
+ pass
28
+ def __len__(self):
29
+ return len(self.data)
30
+
31
+ class Spiral(Dataset):
32
+ """ def __init__(self,train=True):
33
+ super().__init__()"""
34
+ def prepare(self):
35
+ self.data,self.label=get_spiral(self.train)
36
+
37
+ class Bigdata(Dataset):
38
+ def __getitem__(self,index):
39
+ x=np.load('data/{}.npy'.format(index))
40
+ t = np.load('label/{}.npy'.format(index))
41
+ return x,t
42
+ def __len__(self):
43
+ return 1000000
44
+ def get_spiral(train=True):
45
+ seed = 1984 if train else 2020
46
+ np.random.seed(seed)
47
+
48
+ num_data = 100
49
+ num_class = 3
50
+ input_dim = 2
51
+
52
+ data_size = num_class * num_data
53
+ x = np.zeros((data_size, input_dim), dtype=np.float32)
54
+ t = np.zeros(data_size, dtype=np.int32)
55
+
56
+ for j in range(num_class):
57
+ for i in range(num_data):
58
+ rate = i / num_data
59
+ r = rate
60
+ theta = j * 4.0 + 4.0 * rate + np.random.randn() * 0.2
61
+ ix = num_data * j + i
62
+
63
+ x[ix] = [r*np.sin(theta), r*np.cos(theta)]
64
+ t[ix] = j
65
+
66
+ return x, t
67
+
68
+
69
+ class ImageNet(Dataset):
70
+ def __init__(self):
71
+ super().__init__()
72
+ @staticmethod
73
+ def labels():
74
+ path = 'models/labels'
75
+ with open(path, 'r') as f:
76
+ labels = eval(f.read())
77
+ return labels
78
+ """class MNIST(Dataset):
79
+
80
+ def __init__(self, train=True,
81
+ transform=Compose([Flatten(), ToFloat(),
82
+ Normalize(0., 255.)]),
83
+ target_transform=None):
84
+ super().__init__(train, transform, target_transform)
85
+
86
+ def prepare(self):
87
+
88
+ if self.train:
89
+ data_path = "./data/train-images.idx3-ubyte"
90
+ label_path = "./data/train-labels.idx1-ubyte"
91
+ else:
92
+ data_path = "./data/t10k-images.idx3-ubyte"
93
+ label_path = "./data/t10k-labels.idx1-ubyte"
94
+ self.data = self._load_data(data_path)
95
+ self.label = self._load_label(label_path)
96
+
97
+ def _load_label(self, filepath):
98
+ with gzip.open(filepath, 'rb') as f:
99
+ labels = np.frombuffer(f.read(), np.uint8, offset=8)
100
+ return labels
101
+
102
+ def _load_data(self, filepath):
103
+ with gzip.open(filepath, 'rb') as f:
104
+ data = np.frombuffer(f.read(), np.uint8, offset=16)
105
+ data = data.reshape(-1, 1, 28, 28)
106
+ return data
107
+
108
+ def show(self, row=10, col=10):
109
+ H, W = 28, 28
110
+ img = np.zeros((H * row, W * col))
111
+ for r in range(row):
112
+ for c in range(col):
113
+ img[r * H:(r + 1) * H, c * W:(c + 1) * W] = self.data[
114
+ np.random.randint(0, len(self.data) - 1)].reshape(H, W)
115
+ plt.imshow(img, cmap='gray', interpolation='nearest')
116
+ plt.axis('off')
117
+ plt.show()
118
+
119
+ @staticmethod
120
+ def labels():
121
+ return {0: '0', 1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6', 7: '7', 8: '8', 9: '9'}
122
+ """
123
+
124
+
125
+ class MNIST(Dataset):
126
+
127
+ def __init__(self, train=True,
128
+ transform=Compose([Flatten(), ToFloat(),
129
+ Normalize(0., 255.)]),
130
+ target_transform=None):
131
+ super().__init__(train, transform, target_transform)
132
+
133
+ def prepare(self):
134
+
135
+ if self.train:
136
+ data_path = "data/train-images.idx3-ubyte"
137
+ label_path = "data/train-labels.idx1-ubyte"
138
+ else:
139
+ data_path = "data/t10k-images.idx3-ubyte"
140
+ label_path = "data/t10k-labels.idx1-ubyte"
141
+
142
+ self.data = self._load_images(data_path)
143
+ self.label = self._load_labels(label_path)
144
+
145
+ def _load_images(self, path):
146
+
147
+ with open(path, 'rb') as f:
148
+ data = np.frombuffer(f.read(), np.uint8, offset=16)
149
+
150
+ #data = data.reshape(-1, 784)
151
+ data = data.reshape(-1, 28, 28)
152
+ return data
153
+
154
+ def _load_labels(self, path):
155
+
156
+ with open(path, 'rb') as f:
157
+ labels = np.frombuffer(f.read(), np.uint8, offset=8)
158
+
159
+ return labels
160
+ def __len__(self):
161
+ return len(self.data)
162
+
163
+ def __getitem__(self, idx):
164
+ image = self.data[idx]
165
+ label = self.label[idx]
166
+
167
+ if self.transform:
168
+ image = self.transform(image)
169
+
170
+ return image, label
171
+ class SinCurve(Dataset):
172
+
173
+ def prepare(self):
174
+ num_data = 1000
175
+ dtype = np.float64
176
+
177
+ x = np.linspace(0, 2 * np.pi, num_data)
178
+ noise_range = (-0.05, 0.05)
179
+ noise = np.random.uniform(noise_range[0], noise_range[1], size=x.shape) #生成均匀分布随机数
180
+ if self.train:
181
+ y = np.sin(x) + noise
182
+ else:
183
+ y = np.cos(x)
184
+ y = y.astype(dtype)
185
+ self.data = y[:-1][:, np.newaxis]
186
+ self.label = y[1:][:, np.newaxis]