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