Showing
15 changed files
with
690 additions
and
1 deletions
... | @@ -13,9 +13,15 @@ python 코드에서 가중치를 pickle 파일에 저장하는데 c++에서는 pickle 파일을 읽는 | ... | @@ -13,9 +13,15 @@ python 코드에서 가중치를 pickle 파일에 저장하는데 c++에서는 pickle 파일을 읽는 |
13 | pickletools라는 라이브러리가 있지만 에러가 많고, 자바, 파이썬, C++ 여러 언어를 지원해 무겁기 때문에 속도를 올리기 위한 컨버팅 작업에는 적절하지 않음 | 13 | pickletools라는 라이브러리가 있지만 에러가 많고, 자바, 파이썬, C++ 여러 언어를 지원해 무겁기 때문에 속도를 올리기 위한 컨버팅 작업에는 적절하지 않음 |
14 | 그래서, 파라미터를 저장하는 부분을 csv로 바꿔 C++에서 그 파일로 읽기위해 params.pkl을 params.csv로 바꾸는 코드를 추가함 | 14 | 그래서, 파라미터를 저장하는 부분을 csv로 바꿔 C++에서 그 파일로 읽기위해 params.pkl을 params.csv로 바꾸는 코드를 추가함 |
15 | 15 | ||
16 | + | ||
16 | 5. params.pkl->params.txt | 17 | 5. params.pkl->params.txt |
17 | 입력처리할 때 csv파일로 읽으면 속도가 느림 | 18 | 입력처리할 때 csv파일로 읽으면 속도가 느림 |
18 | 이 또한 속도를 올리기 위한 컨버팅 작업의 목적에 맞지 않기 때문에 params.pkl 파일을 csv 파일이 아닌 txt 파일로 바꿈 | 19 | 이 또한 속도를 올리기 위한 컨버팅 작업의 목적에 맞지 않기 때문에 params.pkl 파일을 csv 파일이 아닌 txt 파일로 바꿈 |
19 | 20 | ||
21 | + | ||
20 | 6. python test 코드 추가 | 22 | 6. python test 코드 추가 |
21 | -test하는 부분만 골라내기 위해 python test 코드를 추가(test.py), simple_convnet 내용 추가 | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
23 | +test하는 부분만 골라내기 위해 python test 코드를 추가(test.py), simple_convnet 내용 추가 | ||
24 | + | ||
25 | + | ||
26 | +7. python test 폴더 추가 | ||
27 | +python test 폴더에는 test에 필요하지 않은 train 부분을 삭제함 | ||
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
No preview for this file type
No preview for this file type
No preview for this file type
python test/__pycache__/util.cpython-36.pyc
0 → 100644
No preview for this file type
python test/dataset/__init__.py
0 → 100644
File mode changed
No preview for this file type
No preview for this file type
python test/dataset/cifar10.py
0 → 100644
1 | +# coding: utf-8 | ||
2 | +try: | ||
3 | + import urllib.request | ||
4 | +except ImportError: | ||
5 | + raise ImportError('You should use Python 3.x') | ||
6 | +import os.path | ||
7 | +import gzip | ||
8 | +import pickle | ||
9 | +import os | ||
10 | +import numpy as np | ||
11 | + | ||
12 | + | ||
13 | +key_file = { | ||
14 | + 'train':'cifar10-train.gz', | ||
15 | + 'test':'cifar10-test.gz' | ||
16 | +} | ||
17 | + | ||
18 | +dataset_dir = os.path.dirname(os.path.abspath('/Users/HyeonJun/Desktop/simple_convnet/dataset')) | ||
19 | +save_file = dataset_dir + "/cifar10.pkl" | ||
20 | + | ||
21 | +train_num = 50000 | ||
22 | +test_num = 10000 | ||
23 | +img_dim = (3, 32, 32) | ||
24 | +img_size = 3072 | ||
25 | + | ||
26 | +def _load_label(file_name): | ||
27 | + file_path = dataset_dir + "/" + file_name | ||
28 | + | ||
29 | + print("Converting " + file_name + " to NumPy Array ...") | ||
30 | + with gzip.open(file_path, 'rb') as f: | ||
31 | + labels = np.frombuffer(f.read(), np.uint8, offset=0) | ||
32 | + labels = labels.reshape(-1, img_size+1) | ||
33 | + labels = labels.T | ||
34 | + print("Done") | ||
35 | + | ||
36 | + return labels[0] | ||
37 | + | ||
38 | +def _load_img(file_name): | ||
39 | + file_path = dataset_dir + "/" + file_name | ||
40 | + | ||
41 | + print("Converting " + file_name + " to NumPy Array ...") | ||
42 | + with gzip.open(file_path, 'rb') as f: | ||
43 | + data = np.frombuffer(f.read(), np.uint8, offset=0) | ||
44 | + data = data.reshape(-1, img_size+1) | ||
45 | + data = np.delete(data, 0, 1) | ||
46 | + print("Done") | ||
47 | + | ||
48 | + return data | ||
49 | + | ||
50 | +def _convert_numpy(): | ||
51 | + dataset = {} | ||
52 | + dataset['train_img'] = _load_img(key_file['train']) | ||
53 | + dataset['train_label'] = _load_label(key_file['train']) | ||
54 | + dataset['test_img'] = _load_img(key_file['test']) | ||
55 | + dataset['test_label'] = _load_label(key_file['test']) | ||
56 | + | ||
57 | + return dataset | ||
58 | + | ||
59 | +def init_cifar10(): | ||
60 | + dataset = _convert_numpy() | ||
61 | + print("Creating pickle file ...") | ||
62 | + with open(save_file, 'wb') as f: | ||
63 | + pickle.dump(dataset, f, -1) | ||
64 | + print("Done!") | ||
65 | + | ||
66 | +def _change_one_hot_label(X): | ||
67 | + T = np.zeros((X.size, 10)) | ||
68 | + for idx, row in enumerate(T): | ||
69 | + row[X[idx]] = 1 | ||
70 | + | ||
71 | + return T | ||
72 | + | ||
73 | +def load_cifar10(normalize=True, flatten=True, one_hot_label=False): | ||
74 | + """CIFAR-10データセットの読み込み | ||
75 | + | ||
76 | + Parameters | ||
77 | + ---------- | ||
78 | + normalize : 画像のピクセル値を0.0~1.0に正規化する | ||
79 | + one_hot_label : | ||
80 | + one_hot_labelがTrueの場合、ラベルはone-hot配列として返す | ||
81 | + one-hot配列とは、たとえば[0,0,1,0,0,0,0,0,0,0]のような配列 | ||
82 | + flatten : 画像を一次元配列に平にするかどうか | ||
83 | + | ||
84 | + Returns | ||
85 | + ------- | ||
86 | + (訓練画像, 訓練ラベル), (テスト画像, テストラベル) | ||
87 | + """ | ||
88 | + if not os.path.exists(save_file): | ||
89 | + init_cifar10() | ||
90 | + | ||
91 | + with open(save_file, 'rb') as f: | ||
92 | + dataset = pickle.load(f) | ||
93 | + | ||
94 | + if normalize: | ||
95 | + for key in ('train_img', 'test_img'): | ||
96 | + dataset[key] = dataset[key].astype(np.float32) | ||
97 | + dataset[key] /= 255.0 | ||
98 | + | ||
99 | + if one_hot_label: | ||
100 | + dataset['train_label'] = _change_one_hot_label(dataset['train_label']) | ||
101 | + dataset['test_label'] = _change_one_hot_label(dataset['test_label']) | ||
102 | + | ||
103 | + if not flatten: | ||
104 | + for key in ('train_img', 'test_img'): | ||
105 | + dataset[key] = dataset[key].reshape(-1, 3, 32, 32) | ||
106 | + | ||
107 | + return (dataset['train_img'], dataset['train_label']), (dataset['test_img'], dataset['test_label']) | ||
108 | + | ||
109 | + | ||
110 | +if __name__ == '__main__': | ||
111 | + init_cifar10() |
python test/functions.py
0 → 100644
1 | +# coding: utf-8 | ||
2 | +#import cupy as cp | ||
3 | +import numpy as cp | ||
4 | +import numpy as np | ||
5 | + | ||
6 | +def cross_entropy_error(y, t): | ||
7 | + if y.ndim == 1: | ||
8 | + t = t.reshape(1, t.size) | ||
9 | + y = y.reshape(1, y.size) | ||
10 | + | ||
11 | + # 教師データがone-hot-vectorの場合、正解ラベルのインデックスに変換 | ||
12 | + if t.size == y.size: | ||
13 | + t = t.argmax(axis=1) | ||
14 | + | ||
15 | + batch_size = y.shape[0] | ||
16 | + return -cp.sum(cp.log(y[cp.arange(batch_size), t])) / batch_size |
python test/layers.py
0 → 100644
1 | +# coding: utf-8 | ||
2 | +#import cupy as cp | ||
3 | +import numpy as cp | ||
4 | +import numpy as np | ||
5 | +from functions import * | ||
6 | +from util import im2col, col2im, DW_im2col | ||
7 | + | ||
8 | + | ||
9 | +class Relu: | ||
10 | + def __init__(self): | ||
11 | + self.mask = None | ||
12 | + | ||
13 | + def forward(self, x): | ||
14 | + self.mask = (x <= 0) | ||
15 | + out = x.copy() | ||
16 | + out[self.mask] = 0 | ||
17 | + | ||
18 | + return out | ||
19 | + | ||
20 | + def backward(self, dout): | ||
21 | + dout[self.mask] = 0 | ||
22 | + dx = dout | ||
23 | + | ||
24 | + return dx | ||
25 | + | ||
26 | + | ||
27 | +class SoftmaxWithLoss: | ||
28 | + def __init__(self): | ||
29 | + self.loss = None | ||
30 | + self.y = None # softmaxの出力 | ||
31 | + self.t = None # 教師データ | ||
32 | + | ||
33 | + def forward(self, x, t): | ||
34 | + self.t = t | ||
35 | + self.y = softmax(x) | ||
36 | + self.loss = cross_entropy_error(self.y, self.t) | ||
37 | + | ||
38 | + return self.loss | ||
39 | + | ||
40 | + def backward(self, dout=1): | ||
41 | + batch_size = self.t.shape[0] | ||
42 | + if self.t.size == self.y.size: # 教師データがone-hot-vectorの場合 | ||
43 | + dx = (self.y - self.t) / batch_size | ||
44 | + else: | ||
45 | + dx = self.y.copy() | ||
46 | + dx[np.arange(batch_size), self.t] -= 1 | ||
47 | + dx = dx / batch_size | ||
48 | + | ||
49 | + return dx | ||
50 | + | ||
51 | +class LightNormalization: | ||
52 | + """ | ||
53 | + """ | ||
54 | + def __init__(self, momentum=0.9, running_mean=None, running_var=None): | ||
55 | + self.momentum = momentum | ||
56 | + self.input_shape = None # Conv層の場合は4次元、全結合層の場合は2次元 | ||
57 | + | ||
58 | + # テスト時に使用する平均と分散 | ||
59 | + self.running_mean = running_mean | ||
60 | + self.running_var = running_var | ||
61 | + | ||
62 | + # backward時に使用する中間データ | ||
63 | + self.batch_size = None | ||
64 | + self.xc = None | ||
65 | + self.std = None | ||
66 | + | ||
67 | + def forward(self, x, train_flg=True): | ||
68 | + self.input_shape = x.shape | ||
69 | + if x.ndim == 2: | ||
70 | + N, D = x.shape | ||
71 | + x = x.reshape(N, D, 1, 1) | ||
72 | + | ||
73 | + x = x.transpose(0, 2, 3, 1) | ||
74 | + out = self.__forward(x, train_flg) | ||
75 | + out = out.transpose(0, 3, 1, 2) | ||
76 | + | ||
77 | + return out.reshape(*self.input_shape) | ||
78 | + | ||
79 | + def __forward(self, x, train_flg): | ||
80 | + if self.running_mean is None: | ||
81 | + N, H, W, C = x.shape | ||
82 | + self.running_mean = cp.zeros(C, dtype=np.float32) | ||
83 | + self.running_var = cp.zeros(C, dtype=np.float32) | ||
84 | + | ||
85 | + if train_flg: | ||
86 | + mu = x.mean(axis=(0, 1, 2)) | ||
87 | + xc = x - mu | ||
88 | + var = cp.mean(xc**2, axis=(0, 1, 2), dtype=np.float32) | ||
89 | + std = cp.sqrt(var + 10e-7, dtype=np.float32) | ||
90 | + xn = xc / std | ||
91 | + | ||
92 | + self.batch_size = x.shape[0] | ||
93 | + self.xc = xc | ||
94 | + self.xn = xn | ||
95 | + self.std = std | ||
96 | + self.running_mean = self.momentum * self.running_mean + (1-self.momentum) * mu | ||
97 | + self.running_var = self.momentum * self.running_var + (1-self.momentum) * var | ||
98 | + else: | ||
99 | + xc = x - self.running_mean | ||
100 | + xn = xc / ((cp.sqrt(self.running_var + 10e-7, dtype=np.float32))) | ||
101 | + | ||
102 | + out = xn | ||
103 | + return out | ||
104 | + | ||
105 | + def backward(self, dout): | ||
106 | + if dout.ndim == 2: | ||
107 | + N, D = dout.shape | ||
108 | + dout = dout.reshape(N, D, 1, 1) | ||
109 | + | ||
110 | + dout = dout.transpose(0, 2, 3, 1) | ||
111 | + dx = self.__backward(dout) | ||
112 | + dx = dx.transpose(0, 3, 1, 2) | ||
113 | + | ||
114 | + dx = dx.reshape(*self.input_shape) | ||
115 | + return dx | ||
116 | + | ||
117 | + def __backward(self, dout): | ||
118 | + dxn = dout | ||
119 | + dxc = dxn / self.std | ||
120 | + dstd = -cp.sum((dxn * self.xc) / (self.std * self.std), axis=0) | ||
121 | + dvar = 0.5 * dstd / self.std | ||
122 | + dxc += (2.0 / self.batch_size) * self.xc * dvar | ||
123 | + dmu = cp.sum(dxc, axis=0) | ||
124 | + dx = dxc - dmu / self.batch_size | ||
125 | + | ||
126 | + return dx | ||
127 | + | ||
128 | + | ||
129 | + | ||
130 | +class Convolution: | ||
131 | + def __init__(self, W, stride=1, pad=0): | ||
132 | + self.W = W | ||
133 | + self.stride = stride | ||
134 | + self.pad = pad | ||
135 | + | ||
136 | + self.x = None | ||
137 | + self.col = None | ||
138 | + self.col_W = None | ||
139 | + | ||
140 | + self.dW = None | ||
141 | + | ||
142 | + def forward(self, x): | ||
143 | + FN, C, FH, FW = self.W.shape | ||
144 | + N, C, H, W = x.shape | ||
145 | + out_h = 1 + int((H + 2*self.pad - FH) / self.stride) | ||
146 | + out_w = 1 + int((W + 2*self.pad - FW) / self.stride) | ||
147 | + | ||
148 | + col = im2col(x, FH, FW, self.stride, self.pad) | ||
149 | + col_W = self.W.reshape(FN, -1).T | ||
150 | + | ||
151 | + out = cp.dot(col, col_W) | ||
152 | + out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2) | ||
153 | + | ||
154 | + self.x = x | ||
155 | + self.col = col | ||
156 | + self.col_W = col_W | ||
157 | + | ||
158 | + return out | ||
159 | + | ||
160 | + def backward(self, dout): | ||
161 | + FN, C, FH, FW = self.W.shape | ||
162 | + dout = dout.transpose(0,2,3,1).reshape(-1, FN) | ||
163 | + | ||
164 | + self.dW = cp.dot(self.col.T, dout) | ||
165 | + self.dW = self.dW.transpose(1, 0).reshape(FN, C, FH, FW) | ||
166 | + | ||
167 | + dcol = cp.dot(dout, self.col_W.T) | ||
168 | + dx = col2im(dcol, self.x.shape, FH, FW, self.stride, self.pad) | ||
169 | + | ||
170 | + return dx | ||
171 | + | ||
172 | + | ||
173 | +class Pooling: | ||
174 | + def __init__(self, pool_h, pool_w, stride=1, pad=0): | ||
175 | + self.pool_h = pool_h | ||
176 | + self.pool_w = pool_w | ||
177 | + self.stride = stride | ||
178 | + self.pad = pad | ||
179 | + | ||
180 | + self.x = None | ||
181 | + self.arg_max = None | ||
182 | + | ||
183 | + def forward(self, x): | ||
184 | + N, C, H, W = x.shape | ||
185 | + out_h = int(1 + (H - self.pool_h) / self.stride) | ||
186 | + out_w = int(1 + (W - self.pool_w) / self.stride) | ||
187 | + | ||
188 | + col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad) | ||
189 | + col = col.reshape(-1, self.pool_h*self.pool_w) | ||
190 | + | ||
191 | + arg_max = cp.argmax(col, axis=1) | ||
192 | + out = cp.array(cp.max(col, axis=1), dtype=np.float32) | ||
193 | + out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2) | ||
194 | + | ||
195 | + self.x = x | ||
196 | + self.arg_max = arg_max | ||
197 | + | ||
198 | + return out | ||
199 | + | ||
200 | + def backward(self, dout): | ||
201 | + dout = dout.transpose(0, 2, 3, 1) | ||
202 | + | ||
203 | + pool_size = self.pool_h * self.pool_w | ||
204 | + dmax = cp.zeros((dout.size, pool_size), dtype=np.float32) | ||
205 | + dmax[cp.arange(self.arg_max.size), self.arg_max.flatten()] = dout.flatten() | ||
206 | + dmax = dmax.reshape(dout.shape + (pool_size,)) | ||
207 | + | ||
208 | + dcol = dmax.reshape(dmax.shape[0] * dmax.shape[1] * dmax.shape[2], -1) | ||
209 | + dx = col2im(dcol, self.x.shape, self.pool_h, self.pool_w, self.stride, self.pad) | ||
210 | + | ||
211 | + return dx | ||
212 | + | ||
213 | +class DW_Convolution: | ||
214 | + def __init__(self, W, stride=1, pad=0): | ||
215 | + self.W = W | ||
216 | + self.stride = stride | ||
217 | + self.pad = pad | ||
218 | + | ||
219 | + self.x = None | ||
220 | + self.col = None | ||
221 | + self.col_W = None | ||
222 | + | ||
223 | + self.dW = None | ||
224 | + self.db = None | ||
225 | + | ||
226 | + | ||
227 | + | ||
228 | + def forward(self, x): | ||
229 | + FN, C, FH, FW = self.W.shape | ||
230 | + N, C, H, W = x.shape | ||
231 | + out_h = 1 + int((H + 2*self.pad - FH) / self.stride) | ||
232 | + out_w = 1 + int((W + 2*self.pad - FW) / self.stride) | ||
233 | + | ||
234 | + col = DW_im2col(x, FH, FW, self.stride, self.pad) | ||
235 | + col_W = self.W.reshape(FN, -1).T | ||
236 | + | ||
237 | + outlist = [] | ||
238 | + outlist = np.zeros((FN, N*H*W, 1)) | ||
239 | + for count in range(FN): | ||
240 | + outlist[count] = np.dot(col[count, :, :], col_W[:, count]).reshape(-1,1) | ||
241 | + | ||
242 | + out = outlist.transpose(1,0,2) | ||
243 | + out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2) | ||
244 | + | ||
245 | + self.x = x | ||
246 | + self.col = col | ||
247 | + self.col_W = col_W | ||
248 | + return out | ||
249 | + | ||
250 | + | ||
251 | + def backward(self, dout): | ||
252 | + FN, C, FH, FW = self.W.shape | ||
253 | + N, XC, H, W = dout.shape | ||
254 | + dout = dout.transpose(0,2,3,1).reshape(-1, FN) | ||
255 | + | ||
256 | + | ||
257 | + dW_list = np.zeros((FN, FH*FW)) | ||
258 | + dcol_list = np.zeros((N * H * W, FN, FH * FW)) | ||
259 | + for count in range(FN): | ||
260 | + dW_list[count] = np.dot(self.col[count].transpose(1,0), dout[:, count]) | ||
261 | + dcol_list[:,count,:] = np.dot(dout[:,count].reshape(-1,1), self.col_W.T[count,:].reshape(1,-1)) | ||
262 | + self.dW = dW_list | ||
263 | + self.dW = self.dW.reshape(FN, C, FH, FW) | ||
264 | + | ||
265 | + | ||
266 | + dcol = dcol_list | ||
267 | + dx = col2im(dcol, self.x.shape, FH, FW, self.stride, self.pad) | ||
268 | + | ||
269 | + | ||
270 | + return dx | ||
271 | + | ||
272 | +class Affine: | ||
273 | + def __init__(self, W): | ||
274 | + self.W =W | ||
275 | +# self.b = b | ||
276 | + | ||
277 | + self.x = None | ||
278 | + self.original_x_shape = None | ||
279 | + #self.dW = None | ||
280 | +# self.db = None | ||
281 | + | ||
282 | + def forward(self, x): | ||
283 | + self.original_x_shape = x.shape | ||
284 | + x = x.reshape(x.shape[0], -1) | ||
285 | + self.x = x | ||
286 | + | ||
287 | + out = cp.dot(self.x, self.W) #+ self.b | ||
288 | + | ||
289 | + return out | ||
290 | + | ||
291 | + def backward(self, dout): | ||
292 | + dx = cp.dot(dout, self.W.T) | ||
293 | + self.dW = cp.dot(self.x.T, dout) | ||
294 | +# self.db = cp.sum(dout, axis=0) | ||
295 | + | ||
296 | + dx = dx.reshape(*self.original_x_shape) # return dx |
python test/params.pkl
0 → 100644
No preview for this file type
python test/simple_convnet4.py
0 → 100644
1 | +import sys, os | ||
2 | +sys.path.append(os.pardir) | ||
3 | +import pickle | ||
4 | +import numpy as cp | ||
5 | +import numpy as np | ||
6 | +from collections import OrderedDict | ||
7 | +from layers import * | ||
8 | + | ||
9 | + | ||
10 | +class SimpleConvNet: | ||
11 | + def __init__(self, input_dim=(3, 32, 32), | ||
12 | + conv_param={'filter_num':(32, 32, 64), 'filter_size':3, 'pad':1, 'stride':1}, | ||
13 | + hidden_size=512, output_size=10, weight_init_std=0.01, pretrained=False): | ||
14 | + filter_num = conv_param['filter_num'] | ||
15 | + filter_size = conv_param['filter_size'] | ||
16 | + filter_pad = conv_param['pad'] | ||
17 | + filter_stride = conv_param['stride'] | ||
18 | + input_size = input_dim[1] | ||
19 | + conv_output_size = (input_size - filter_size + 2*filter_pad) / filter_stride + 1 | ||
20 | + conv_data_size = int(filter_num[0] * conv_output_size * conv_output_size ) | ||
21 | + pool1_output_size = int(filter_num[1] * (conv_output_size/2) * (conv_output_size/2)) | ||
22 | + pool2_output_size = int(filter_num[2] * (conv_output_size/4) * (conv_output_size/4)) | ||
23 | + pool3_output_size = int(filter_num[2] * (conv_output_size/8) * (conv_output_size/8)) | ||
24 | + | ||
25 | + self.params = {} | ||
26 | + if pretrained: | ||
27 | + weights = self.load_weights() | ||
28 | + self.params['W1'] = cp.array(weights['W1'], dtype=np.float32) | ||
29 | + self.params['W2'] = cp.array(weights['W2'], dtype=np.float32) | ||
30 | + self.params['W3'] = cp.array(weights['W3'], dtype=np.float32) | ||
31 | + self.params['W4'] = cp.array(weights['W4'], dtype=np.float32) | ||
32 | + self.params['W5'] = cp.array(weights['W5'], dtype=np.float32) | ||
33 | + self.params['W6'] = cp.array(weights['W6'], dtype=np.float32) | ||
34 | + self.params['W7'] = cp.array(weights['W7'], dtype=np.float32) | ||
35 | + else: | ||
36 | + self.params['W1'] = cp.array( weight_init_std * \ | ||
37 | + cp.random.randn(filter_num[0], input_dim[0], filter_size, filter_size), dtype=np.float32) | ||
38 | + | ||
39 | + self.params['W2'] = cp.array( weight_init_std * \ | ||
40 | + cp.random.randn(filter_num[1], filter_num[0], 1, 1), dtype=np.float32) | ||
41 | + | ||
42 | + self.params['W3'] = cp.array( weight_init_std * \ | ||
43 | + cp.random.randn(filter_num[1], 1, filter_size, filter_size), dtype=np.float32) | ||
44 | + | ||
45 | + self.params['W4'] = cp.array( weight_init_std * \ | ||
46 | + cp.random.randn(filter_num[2], filter_num[1], 1, 1), dtype=np.float32) | ||
47 | + | ||
48 | + self.params['W5'] = cp.array( weight_init_std * \ | ||
49 | + cp.random.randn(filter_num[2], 1, filter_size, filter_size), dtype=np.float32) | ||
50 | + | ||
51 | + self.params['W6'] = cp.array( weight_init_std * \ | ||
52 | + cp.random.randn(pool3_output_size, hidden_size), dtype=np.float32) | ||
53 | + | ||
54 | + self.params['W7'] = cp.array( weight_init_std * \ | ||
55 | + cp.random.randn(hidden_size, output_size), dtype=np.float32) | ||
56 | + | ||
57 | + self.layers = OrderedDict() | ||
58 | + self.layers['Conv1'] = Convolution(self.params['W1'], | ||
59 | + conv_param['stride'], conv_param['pad']) | ||
60 | + self.layers['LightNorm1'] = LightNormalization() | ||
61 | + self.layers['Relu1'] = Relu() | ||
62 | + self.layers['Pool1'] = Pooling(pool_h=2, pool_w=2, stride=2) | ||
63 | + | ||
64 | + self.layers['Conv2'] = Convolution(self.params['W2'], | ||
65 | + 1, 0) | ||
66 | + self.layers['LightNorm2'] = LightNormalization() | ||
67 | + self.layers['Relu2'] = Relu() | ||
68 | + self.layers['Conv3'] = DW_Convolution(self.params['W3'], | ||
69 | + conv_param['stride'], conv_param['pad']) | ||
70 | + self.layers['LightNorm3'] = LightNormalization() | ||
71 | + self.layers['Relu3'] = Relu() | ||
72 | + self.layers['Pool2'] = Pooling(pool_h=2, pool_w=2, stride=2) | ||
73 | + | ||
74 | + self.layers['Conv4'] = Convolution(self.params['W4'], | ||
75 | + 1, 0) | ||
76 | + self.layers['LightNorm4'] = LightNormalization() | ||
77 | + self.layers['Relu4'] = Relu() | ||
78 | + self.layers['Conv5'] = DW_Convolution(self.params['W5'], | ||
79 | + conv_param['stride'], conv_param['pad']) | ||
80 | + self.layers['LightNorm5'] = LightNormalization() | ||
81 | + self.layers['Relu5'] = Relu() | ||
82 | + self.layers['Pool3'] = Pooling(pool_h=2, pool_w=2, stride=2) | ||
83 | + | ||
84 | + self.layers['Affine4'] = Affine(self.params['W6']) | ||
85 | + self.layers['LightNorm6'] = LightNormalization() | ||
86 | + self.layers['Relu6'] = Relu() | ||
87 | + | ||
88 | + self.layers['Affine5'] = Affine(self.params['W7']) | ||
89 | + | ||
90 | + self.last_layer = SoftmaxWithLoss() | ||
91 | + | ||
92 | + def predict(self, x): | ||
93 | + for layer in self.layers.values(): | ||
94 | + x = layer.forward(x) | ||
95 | + return x | ||
96 | + | ||
97 | + def accuracy(self, x, t, batch_size=100): | ||
98 | + if t.ndim != 1 : t = np.argmax(t, axis=1) | ||
99 | + | ||
100 | + acc = 0.0 | ||
101 | + | ||
102 | + for i in range(int(x.shape[0] / batch_size)): | ||
103 | + tx = x[i*batch_size:(i+1)*batch_size] | ||
104 | + tt = t[i*batch_size:(i+1)*batch_size] | ||
105 | + y = self.predict(tx) | ||
106 | + y = np.argmax(y, axis=1) | ||
107 | + print("answer : ", tt) | ||
108 | + print("predict : ", y) | ||
109 | + acc += np.sum(y == tt) #numpy | ||
110 | + | ||
111 | + return acc / x.shape[0] | ||
112 | + | ||
113 | + def gradient(self, x, t): | ||
114 | + self.loss(x, t) | ||
115 | + | ||
116 | + dout = 1 | ||
117 | + dout = self.last_layer.backward(dout) | ||
118 | + | ||
119 | + layers = list(self.layers.values()) | ||
120 | + layers.reverse() | ||
121 | + for layer in layers: | ||
122 | + dout = layer.backward(dout) | ||
123 | + | ||
124 | + grads = {} | ||
125 | + grads['W1'] = self.layers['Conv1'].dW | ||
126 | + grads['W2'] = self.layers['Conv2'].dW | ||
127 | + grads['W3'] = self.layers['Conv3'].dW | ||
128 | + grads['W4'] = self.layers['Conv4'].dW | ||
129 | + grads['W5'] = self.layers['Conv5'].dW | ||
130 | + grads['W6'] = self.layers['Affine4'].dW | ||
131 | + grads['W7'] = self.layers['Affine5'].dW | ||
132 | + return grads | ||
133 | + | ||
134 | + # ���� ����ġ �ҷ����� / SimpleconvNet�� pretrained ���� �߰��� : True�� ����ġ �о� ���� | ||
135 | + def load_weights(self, file_name='params.pkl'): | ||
136 | + weights = [] | ||
137 | + with open(file_name, 'rb') as f: | ||
138 | + weights = pickle.load(f) | ||
139 | + return weights |
python test/test.py
0 → 100644
1 | +from simple_convnet4 import * | ||
2 | +from dataset.cifar10 import load_cifar10 | ||
3 | + | ||
4 | +def batch_(data, lbl, pre, size = 100): | ||
5 | + return data[pre: pre+size], lbl[pre: pre+size] | ||
6 | + | ||
7 | +network = SimpleConvNet(input_dim=(3,32,32), | ||
8 | + conv_param = {'filter_num': (32, 32, 64), 'filter_size': 3, 'pad': 1, 'stride': 1}, | ||
9 | + hidden_size=512, output_size=10, weight_init_std=0.01, pretrained=True) | ||
10 | + | ||
11 | +(x_train, t_train), (x_test, t_test) = load_cifar10(flatten=False) | ||
12 | + | ||
13 | +print("Length of test data: ",len(x_test)) | ||
14 | + | ||
15 | +batch_size = 100 | ||
16 | +epoch = int(len(x_test) / batch_size) | ||
17 | +acc = 0 | ||
18 | +for i in range(epoch): | ||
19 | + t_img, t_lbl = batch_(x_test, t_test, i*batch_size, batch_size) | ||
20 | + t = network.accuracy(t_img, t_lbl, batch_size) | ||
21 | + acc += t * batch_size | ||
22 | + | ||
23 | +print("Accuracy : ",str(acc / len(x_test)*100),'%') |
python test/util.py
0 → 100644
1 | +# coding: utf-8 | ||
2 | +#import cupy as cp | ||
3 | +import numpy as cp | ||
4 | +import numpy as np | ||
5 | + | ||
6 | +def DW_im2col(input_data, filter_h, filter_w, stride=1, pad=0): | ||
7 | + """다수의 이미지를 입력받아 2차원 배열로 변환한다(평탄화). | ||
8 | + | ||
9 | + Parameters | ||
10 | + ---------- | ||
11 | + input_data : 4차원 배열 형태의 입력 데이터(이미지 수, 채널 수, 높이, 너비) | ||
12 | + filter_h : 필터의 높이 | ||
13 | + filter_w : 필터의 너비 | ||
14 | + stride : 스트라이드 | ||
15 | + pad : 패딩 | ||
16 | + | ||
17 | + Returns | ||
18 | + ------- | ||
19 | + col : 2차원 배열 | ||
20 | + """ | ||
21 | + N, C, H, W = input_data.shape | ||
22 | + out_h = (H + 2 * pad - filter_h) // stride + 1 | ||
23 | + out_w = (W + 2 * pad - filter_w) // stride + 1 | ||
24 | + | ||
25 | + img = np.pad(input_data, [(0, 0), (0, 0), (pad, pad), (pad, pad)], 'constant') | ||
26 | + col = np.zeros((N, C, filter_h, filter_w, out_h, out_w)) | ||
27 | + | ||
28 | + for y in range(filter_h): | ||
29 | + y_max = y + stride * out_h | ||
30 | + for x in range(filter_w): | ||
31 | + x_max = x + stride * out_w | ||
32 | + col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride] | ||
33 | + | ||
34 | + col = col.transpose(1, 0, 4, 5, 2, 3).reshape(C, N * out_h * out_w, -1) | ||
35 | + return col | ||
36 | + | ||
37 | + | ||
38 | +def im2col(input_data, filter_h, filter_w, stride=1, pad=0): | ||
39 | + """ | ||
40 | + | ||
41 | + Parameters | ||
42 | + ---------- | ||
43 | + input_data : (データ数, チャンネル, 高さ, 幅)の4次元配列からなる入力データ | ||
44 | + filter_h : フィルターの高さ | ||
45 | + filter_w : フィルターの幅 | ||
46 | + stride : ストライド | ||
47 | + pad : パディング | ||
48 | + | ||
49 | + Returns | ||
50 | + ------- | ||
51 | + col : 2次元配列 | ||
52 | + """ | ||
53 | + N, C, H, W = input_data.shape | ||
54 | + out_h = (H + 2*pad - filter_h)//stride + 1 | ||
55 | + out_w = (W + 2*pad - filter_w)//stride + 1 | ||
56 | + | ||
57 | + img = cp.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant') | ||
58 | + col = cp.zeros((N, C, filter_h, filter_w, out_h, out_w), dtype=np.float32) | ||
59 | + | ||
60 | + for y in range(filter_h): | ||
61 | + y_max = y + stride*out_h | ||
62 | + for x in range(filter_w): | ||
63 | + x_max = x + stride*out_w | ||
64 | + col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride] | ||
65 | + | ||
66 | + col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1) | ||
67 | + return col | ||
68 | + | ||
69 | + | ||
70 | +def col2im(col, input_shape, filter_h, filter_w, stride=1, pad=0): | ||
71 | + """ | ||
72 | + | ||
73 | + Parameters | ||
74 | + ---------- | ||
75 | + col : | ||
76 | + input_shape : 入力データの形状(例:(10, 1, 28, 28)) | ||
77 | + filter_h : | ||
78 | + filter_w | ||
79 | + stride | ||
80 | + pad | ||
81 | + | ||
82 | + Returns | ||
83 | + ------- | ||
84 | + | ||
85 | + """ | ||
86 | + N, C, H, W = input_shape | ||
87 | + out_h = (H + 2*pad - filter_h)//stride + 1 | ||
88 | + out_w = (W + 2*pad - filter_w)//stride + 1 | ||
89 | + col = col.reshape(N, out_h, out_w, C, filter_h, filter_w).transpose(0, 3, 4, 5, 1, 2) | ||
90 | + | ||
91 | + img = cp.zeros((N, C, H + 2*pad + stride - 1, W + 2*pad + stride - 1), dtype=np.float32) | ||
92 | + for y in range(filter_h): | ||
93 | + y_max = y + stride*out_h | ||
94 | + for x in range(filter_w): | ||
95 | + x_max = x + stride*out_w | ||
96 | + img[:, :, y:y_max:stride, x:x_max:stride] += col[:, :, y, x, :, :] | ||
97 | + | ||
98 | + return img[:, :, pad:H + pad, pad:W + pad] |
-
Please register or login to post a comment