├── DeepSMOTE_MNIST.py ├── GenerateSamples.py └── README.md /DeepSMOTE_MNIST.py: -------------------------------------------------------------------------------- 1 | 2 | import collections 3 | import torch 4 | import torch.nn as nn 5 | from torch.utils.data import TensorDataset 6 | import numpy as np 7 | from sklearn.neighbors import NearestNeighbors 8 | import time 9 | import os 10 | 11 | print(torch.version.cuda) #10.1 12 | t3 = time.time() 13 | ############################################################################## 14 | """args for AE""" 15 | 16 | args = {} 17 | args['dim_h'] = 64 # factor controlling size of hidden layers 18 | args['n_channel'] = 1#3 # number of channels in the input data 19 | 20 | args['n_z'] = 300 #600 # number of dimensions in latent space. 21 | 22 | args['sigma'] = 1.0 # variance in n_z 23 | args['lambda'] = 0.01 # hyper param for weight of discriminator loss 24 | args['lr'] = 0.0002 # learning rate for Adam optimizer .000 25 | args['epochs'] = 200 # how many epochs to run for 26 | args['batch_size'] = 100 # batch size for SGD 27 | args['save'] = True # save weights at each epoch of training if True 28 | args['train'] = True # train networks if True, else load networks from 29 | 30 | args['dataset'] = 'mnist' #'fmnist' # specify which dataset to use 31 | 32 | 33 | ############################################################################## 34 | 35 | 36 | 37 | ## create encoder model and decoder model 38 | class Encoder(nn.Module): 39 | def __init__(self, args): 40 | super(Encoder, self).__init__() 41 | 42 | self.n_channel = args['n_channel'] 43 | self.dim_h = args['dim_h'] 44 | self.n_z = args['n_z'] 45 | 46 | # convolutional filters, work excellent with image data 47 | self.conv = nn.Sequential( 48 | nn.Conv2d(self.n_channel, self.dim_h, 4, 2, 1, bias=False), 49 | #nn.ReLU(True), 50 | nn.LeakyReLU(0.2, inplace=True), 51 | nn.Conv2d(self.dim_h, self.dim_h * 2, 4, 2, 1, bias=False), 52 | nn.BatchNorm2d(self.dim_h * 2), 53 | #nn.ReLU(True), 54 | nn.LeakyReLU(0.2, inplace=True), 55 | nn.Conv2d(self.dim_h * 2, self.dim_h * 4, 4, 2, 1, bias=False), 56 | nn.BatchNorm2d(self.dim_h * 4), 57 | #nn.ReLU(True), 58 | nn.LeakyReLU(0.2, inplace=True), 59 | 60 | 61 | nn.Conv2d(self.dim_h * 4, self.dim_h * 8, 4, 2, 1, bias=False), 62 | 63 | #3d and 32 by 32 64 | #nn.Conv2d(self.dim_h * 4, self.dim_h * 8, 4, 1, 0, bias=False), 65 | 66 | nn.BatchNorm2d(self.dim_h * 8), # 40 X 8 = 320 67 | #nn.ReLU(True), 68 | nn.LeakyReLU(0.2, inplace=True) )#, 69 | #nn.Conv2d(self.dim_h * 8, 1, 2, 1, 0, bias=False)) 70 | #nn.Conv2d(self.dim_h * 8, 1, 4, 1, 0, bias=False)) 71 | # final layer is fully connected 72 | self.fc = nn.Linear(self.dim_h * (2 ** 3), self.n_z) 73 | 74 | 75 | def forward(self, x): 76 | #print('enc') 77 | #print('input ',x.size()) #torch.Size([100, 3,32,32]) 78 | x = self.conv(x) 79 | 80 | x = x.squeeze() 81 | #print('aft squeeze ',x.size()) #torch.Size([128, 320]) 82 | #aft squeeze torch.Size([100, 320]) 83 | x = self.fc(x) 84 | #print('out ',x.size()) #torch.Size([128, 20]) 85 | #out torch.Size([100, 300]) 86 | return x 87 | 88 | 89 | class Decoder(nn.Module): 90 | def __init__(self, args): 91 | super(Decoder, self).__init__() 92 | 93 | self.n_channel = args['n_channel'] 94 | self.dim_h = args['dim_h'] 95 | self.n_z = args['n_z'] 96 | 97 | # first layer is fully connected 98 | self.fc = nn.Sequential( 99 | nn.Linear(self.n_z, self.dim_h * 8 * 7 * 7), 100 | nn.ReLU()) 101 | 102 | # deconvolutional filters, essentially inverse of convolutional filters 103 | self.deconv = nn.Sequential( 104 | nn.ConvTranspose2d(self.dim_h * 8, self.dim_h * 4, 4), 105 | nn.BatchNorm2d(self.dim_h * 4), 106 | nn.ReLU(True), 107 | nn.ConvTranspose2d(self.dim_h * 4, self.dim_h * 2, 4), 108 | nn.BatchNorm2d(self.dim_h * 2), 109 | nn.ReLU(True), 110 | nn.ConvTranspose2d(self.dim_h * 2, 1, 4, stride=2), 111 | #nn.Sigmoid()) 112 | nn.Tanh()) 113 | 114 | def forward(self, x): 115 | #print('dec') 116 | #print('input ',x.size()) 117 | x = self.fc(x) 118 | x = x.view(-1, self.dim_h * 8, 7, 7) 119 | x = self.deconv(x) 120 | return x 121 | 122 | ############################################################################## 123 | """set models, loss functions""" 124 | # control which parameters are frozen / free for optimization 125 | def free_params(module: nn.Module): 126 | for p in module.parameters(): 127 | p.requires_grad = True 128 | 129 | def frozen_params(module: nn.Module): 130 | for p in module.parameters(): 131 | p.requires_grad = False 132 | 133 | 134 | ############################################################################## 135 | """functions to create SMOTE images""" 136 | 137 | def biased_get_class(c): 138 | 139 | xbeg = dec_x[dec_y == c] 140 | ybeg = dec_y[dec_y == c] 141 | 142 | return xbeg, ybeg 143 | #return xclass, yclass 144 | 145 | 146 | def G_SM(X, y,n_to_sample,cl): 147 | 148 | # determining the number of samples to generate 149 | #n_to_sample = 10 150 | 151 | # fitting the model 152 | n_neigh = 5 + 1 153 | nn = NearestNeighbors(n_neighbors=n_neigh, n_jobs=1) 154 | nn.fit(X) 155 | dist, ind = nn.kneighbors(X) 156 | 157 | # generating samples 158 | base_indices = np.random.choice(list(range(len(X))),n_to_sample) 159 | neighbor_indices = np.random.choice(list(range(1, n_neigh)),n_to_sample) 160 | 161 | X_base = X[base_indices] 162 | X_neighbor = X[ind[base_indices, neighbor_indices]] 163 | 164 | samples = X_base + np.multiply(np.random.rand(n_to_sample,1), 165 | X_neighbor - X_base) 166 | 167 | #use 10 as label because 0 to 9 real classes and 1 fake/smoted = 10 168 | return samples, [cl]*n_to_sample 169 | 170 | #xsamp, ysamp = SM(xclass,yclass) 171 | 172 | ############################################################################### 173 | 174 | 175 | #NOTE: Download the training ('.../0_trn_img.txt') and label files 176 | # ('.../0_trn_lab.txt'). Place the files in directories (e.g., ../MNIST/trn_img/ 177 | # and /MNIST/trn_lab/). Originally, when the code was written, it was for 5 fold 178 | #cross validation and hence there were 5 files in each of the 179 | #directories. Here, for illustration, we use only 1 training and 1 label 180 | #file (e.g., '.../0_trn_img.txt' and '.../0_trn_lab.txt'). 181 | 182 | dtrnimg = '.../MNIST/trn_img/' 183 | dtrnlab = '.../MNIST/trn_lab/' 184 | 185 | ids = os.listdir(dtrnimg) 186 | idtri_f = [os.path.join(dtrnimg, image_id) for image_id in ids] 187 | print(idtri_f) 188 | 189 | ids = os.listdir(dtrnlab) 190 | idtrl_f = [os.path.join(dtrnlab, image_id) for image_id in ids] 191 | print(idtrl_f) 192 | 193 | #for i in range(5): 194 | for i in range(len(ids)): 195 | print() 196 | print(i) 197 | encoder = Encoder(args) 198 | decoder = Decoder(args) 199 | 200 | device = 'cuda' if torch.cuda.is_available() else 'cpu' 201 | print(device) 202 | decoder = decoder.to(device) 203 | encoder = encoder.to(device) 204 | 205 | train_on_gpu = torch.cuda.is_available() 206 | 207 | #decoder loss function 208 | criterion = nn.MSELoss() 209 | criterion = criterion.to(device) 210 | 211 | trnimgfile = idtri_f[i] 212 | trnlabfile = idtrl_f[i] 213 | 214 | print(trnimgfile) 215 | print(trnlabfile) 216 | dec_x = np.loadtxt(trnimgfile) 217 | dec_y = np.loadtxt(trnlabfile) 218 | 219 | print('train imgs before reshape ',dec_x.shape) 220 | print('train labels ',dec_y.shape) 221 | print(collections.Counter(dec_y)) 222 | dec_x = dec_x.reshape(dec_x.shape[0],1,28,28) 223 | print('train imgs after reshape ',dec_x.shape) 224 | 225 | batch_size = 100 226 | num_workers = 0 227 | 228 | #torch.Tensor returns float so if want long then use torch.tensor 229 | tensor_x = torch.Tensor(dec_x) 230 | tensor_y = torch.tensor(dec_y,dtype=torch.long) 231 | mnist_bal = TensorDataset(tensor_x,tensor_y) 232 | train_loader = torch.utils.data.DataLoader(mnist_bal, 233 | batch_size=batch_size,shuffle=True,num_workers=num_workers) 234 | 235 | classes = ('0', '1', '2', '3', '4', 236 | '5', '6', '7', '8', '9') 237 | 238 | best_loss = np.inf 239 | 240 | t0 = time.time() 241 | if args['train']: 242 | enc_optim = torch.optim.Adam(encoder.parameters(), lr = args['lr']) 243 | dec_optim = torch.optim.Adam(decoder.parameters(), lr = args['lr']) 244 | 245 | for epoch in range(args['epochs']): 246 | train_loss = 0.0 247 | tmse_loss = 0.0 248 | tdiscr_loss = 0.0 249 | # train for one epoch -- set nets to train mode 250 | encoder.train() 251 | decoder.train() 252 | 253 | for images,labs in train_loader: 254 | 255 | # zero gradients for each batch 256 | encoder.zero_grad() 257 | decoder.zero_grad() 258 | #print(images) 259 | images, labs = images.to(device), labs.to(device) 260 | #print('images ',images.size()) 261 | labsn = labs.detach().cpu().numpy() 262 | #print('labsn ',labsn.shape, labsn) 263 | 264 | # run images 265 | z_hat = encoder(images) 266 | 267 | x_hat = decoder(z_hat) #decoder outputs tanh 268 | #print('xhat ', x_hat.size()) 269 | #print(x_hat) 270 | mse = criterion(x_hat,images) 271 | #print('mse ',mse) 272 | 273 | 274 | resx = [] 275 | resy = [] 276 | 277 | tc = np.random.choice(10,1) 278 | #tc = 9 279 | xbeg = dec_x[dec_y == tc] 280 | ybeg = dec_y[dec_y == tc] 281 | xlen = len(xbeg) 282 | nsamp = min(xlen, 100) 283 | ind = np.random.choice(list(range(len(xbeg))),nsamp,replace=False) 284 | xclass = xbeg[ind] 285 | yclass = ybeg[ind] 286 | 287 | xclen = len(xclass) 288 | #print('xclen ',xclen) 289 | xcminus = np.arange(1,xclen) 290 | #print('minus ',xcminus.shape,xcminus) 291 | 292 | xcplus = np.append(xcminus,0) 293 | #print('xcplus ',xcplus) 294 | xcnew = (xclass[[xcplus],:]) 295 | #xcnew = np.squeeze(xcnew) 296 | xcnew = xcnew.reshape(xcnew.shape[1],xcnew.shape[2],xcnew.shape[3],xcnew.shape[4]) 297 | #print('xcnew ',xcnew.shape) 298 | 299 | xcnew = torch.Tensor(xcnew) 300 | xcnew = xcnew.to(device) 301 | 302 | #encode xclass to feature space 303 | xclass = torch.Tensor(xclass) 304 | xclass = xclass.to(device) 305 | xclass = encoder(xclass) 306 | #print('xclass ',xclass.shape) 307 | 308 | xclass = xclass.detach().cpu().numpy() 309 | 310 | xc_enc = (xclass[[xcplus],:]) 311 | xc_enc = np.squeeze(xc_enc) 312 | #print('xc enc ',xc_enc.shape) 313 | 314 | xc_enc = torch.Tensor(xc_enc) 315 | xc_enc = xc_enc.to(device) 316 | 317 | ximg = decoder(xc_enc) 318 | 319 | mse2 = criterion(ximg,xcnew) 320 | 321 | comb_loss = mse2 + mse 322 | comb_loss.backward() 323 | 324 | enc_optim.step() 325 | dec_optim.step() 326 | 327 | train_loss += comb_loss.item()*images.size(0) 328 | tmse_loss += mse.item()*images.size(0) 329 | tdiscr_loss += mse2.item()*images.size(0) 330 | 331 | 332 | # print avg training statistics 333 | train_loss = train_loss/len(train_loader) 334 | tmse_loss = tmse_loss/len(train_loader) 335 | tdiscr_loss = tdiscr_loss/len(train_loader) 336 | print('Epoch: {} \tTrain Loss: {:.6f} \tmse loss: {:.6f} \tmse2 loss: {:.6f}'.format(epoch, 337 | train_loss,tmse_loss,tdiscr_loss)) 338 | 339 | 340 | 341 | #store the best encoder and decoder models 342 | #here, /crs5 is a reference to 5 way cross validation, but is not 343 | #necessary for illustration purposes 344 | if train_loss < best_loss: 345 | print('Saving..') 346 | path_enc = '.../MNIST/models/crs5/' \ 347 | + str(i) + '/bst_enc.pth' 348 | path_dec = '.../MNIST/models/crs5/' \ 349 | + str(i) + '/bst_dec.pth' 350 | 351 | torch.save(encoder.state_dict(), path_enc) 352 | torch.save(decoder.state_dict(), path_dec) 353 | 354 | best_loss = train_loss 355 | 356 | 357 | #in addition, store the final model (may not be the best) for 358 | #informational purposes 359 | path_enc = '.../MNIST/models/crs5/' \ 360 | + str(i) + '/f_enc.pth' 361 | path_dec = '.../MNIST/models/crs5/' \ 362 | + str(i) + '/f_dec.pth' 363 | print(path_enc) 364 | print(path_dec) 365 | torch.save(encoder.state_dict(), path_enc) 366 | torch.save(decoder.state_dict(), path_dec) 367 | print() 368 | 369 | t1 = time.time() 370 | print('total time(min): {:.2f}'.format((t1 - t0)/60)) 371 | 372 | t4 = time.time() 373 | print('final time(min): {:.2f}'.format((t4 - t3)/60)) 374 | 375 | -------------------------------------------------------------------------------- /GenerateSamples.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import collections 4 | import torch 5 | import torch.nn as nn 6 | import numpy as np 7 | from sklearn.neighbors import NearestNeighbors 8 | import os 9 | print(torch.version.cuda) #10.1 10 | import time 11 | t0 = time.time() 12 | ############################################################################## 13 | """args for models""" 14 | 15 | args = {} 16 | args['dim_h'] = 64 # factor controlling size of hidden layers 17 | args['n_channel'] = 1 # number of channels in the input data 18 | 19 | args['n_z'] = 300 #600 # number of dimensions in latent space. 20 | 21 | args['sigma'] = 1.0 # variance in n_z 22 | args['lambda'] = 0.01 # hyper param for weight of discriminator loss 23 | args['lr'] = 0.0002 # learning rate for Adam optimizer .000 24 | args['epochs'] = 1 #50 # how many epochs to run for 25 | args['batch_size'] = 100 # batch size for SGD 26 | args['save'] = True # save weights at each epoch of training if True 27 | args['train'] = True # train networks if True, else load networks from 28 | 29 | args['dataset'] = 'mnist' #'fmnist' # specify which dataset to use 30 | 31 | ############################################################################## 32 | 33 | ## create encoder model and decoder model 34 | class Encoder(nn.Module): 35 | def __init__(self, args): 36 | super(Encoder, self).__init__() 37 | 38 | self.n_channel = args['n_channel'] 39 | self.dim_h = args['dim_h'] 40 | self.n_z = args['n_z'] 41 | 42 | # convolutional filters, work excellent with image data 43 | self.conv = nn.Sequential( 44 | nn.Conv2d(self.n_channel, self.dim_h, 4, 2, 1, bias=False), 45 | #nn.ReLU(True), 46 | nn.LeakyReLU(0.2, inplace=True), 47 | nn.Conv2d(self.dim_h, self.dim_h * 2, 4, 2, 1, bias=False), 48 | nn.BatchNorm2d(self.dim_h * 2), 49 | #nn.ReLU(True), 50 | nn.LeakyReLU(0.2, inplace=True), 51 | nn.Conv2d(self.dim_h * 2, self.dim_h * 4, 4, 2, 1, bias=False), 52 | nn.BatchNorm2d(self.dim_h * 4), 53 | #nn.ReLU(True), 54 | nn.LeakyReLU(0.2, inplace=True), 55 | 56 | 57 | nn.Conv2d(self.dim_h * 4, self.dim_h * 8, 4, 2, 1, bias=False), 58 | 59 | #3d and 32 by 32 60 | #nn.Conv2d(self.dim_h * 4, self.dim_h * 8, 4, 1, 0, bias=False), 61 | 62 | nn.BatchNorm2d(self.dim_h * 8), # 40 X 8 = 320 63 | #nn.ReLU(True), 64 | nn.LeakyReLU(0.2, inplace=True) )#, 65 | #nn.Conv2d(self.dim_h * 8, 1, 2, 1, 0, bias=False)) 66 | #nn.Conv2d(self.dim_h * 8, 1, 4, 1, 0, bias=False)) 67 | # final layer is fully connected 68 | self.fc = nn.Linear(self.dim_h * (2 ** 3), self.n_z) 69 | 70 | 71 | def forward(self, x): 72 | #print('enc') 73 | #print('input ',x.size()) #torch.Size([100, 3,32,32]) 74 | x = self.conv(x) 75 | #print('aft conv ',x.size()) #torch.Size([100, 320, 2, 2]) with 76 | #nn.Conv2d(self.dim_h * 4, self.dim_h * 8, 4, 2, 1, bias=False), 77 | #vs torch.Size([128, 320, 1, 1]) 78 | #aft conv torch.Size([100, 320, 1, 1]) with 79 | #nn.Conv2d(self.dim_h * 4, self.dim_h * 8, 4, 1, 0, bias=False), 80 | x = x.squeeze() 81 | #print('aft squeeze ',x.size()) #torch.Size([128, 320]) 82 | #aft squeeze torch.Size([100, 320]) 83 | x = self.fc(x) 84 | #print('out ',x.size()) #torch.Size([128, 20]) 85 | #out torch.Size([100, 300]) 86 | return x 87 | 88 | 89 | class Decoder(nn.Module): 90 | def __init__(self, args): 91 | super(Decoder, self).__init__() 92 | 93 | self.n_channel = args['n_channel'] 94 | self.dim_h = args['dim_h'] 95 | self.n_z = args['n_z'] 96 | 97 | # first layer is fully connected 98 | self.fc = nn.Sequential( 99 | nn.Linear(self.n_z, self.dim_h * 8 * 7 * 7), 100 | nn.ReLU()) 101 | 102 | # deconvolutional filters, essentially inverse of convolutional filters 103 | self.deconv = nn.Sequential( 104 | nn.ConvTranspose2d(self.dim_h * 8, self.dim_h * 4, 4), 105 | nn.BatchNorm2d(self.dim_h * 4), 106 | nn.ReLU(True), 107 | nn.ConvTranspose2d(self.dim_h * 4, self.dim_h * 2, 4), 108 | nn.BatchNorm2d(self.dim_h * 2), 109 | nn.ReLU(True), 110 | nn.ConvTranspose2d(self.dim_h * 2, 1, 4, stride=2), 111 | #nn.Sigmoid() 112 | nn.Tanh()) 113 | 114 | def forward(self, x): 115 | #print('dec') 116 | #print('input ',x.size()) 117 | x = self.fc(x) 118 | x = x.view(-1, self.dim_h * 8, 7, 7) 119 | x = self.deconv(x) 120 | return x 121 | 122 | ############################################################################## 123 | 124 | def biased_get_class1(c): 125 | 126 | xbeg = dec_x[dec_y == c] 127 | ybeg = dec_y[dec_y == c] 128 | 129 | return xbeg, ybeg 130 | #return xclass, yclass 131 | 132 | 133 | def G_SM1(X, y,n_to_sample,cl): 134 | 135 | 136 | # fitting the model 137 | n_neigh = 5 + 1 138 | nn = NearestNeighbors(n_neighbors=n_neigh, n_jobs=1) 139 | nn.fit(X) 140 | dist, ind = nn.kneighbors(X) 141 | 142 | # generating samples 143 | base_indices = np.random.choice(list(range(len(X))),n_to_sample) 144 | neighbor_indices = np.random.choice(list(range(1, n_neigh)),n_to_sample) 145 | 146 | X_base = X[base_indices] 147 | X_neighbor = X[ind[base_indices, neighbor_indices]] 148 | 149 | samples = X_base + np.multiply(np.random.rand(n_to_sample,1), 150 | X_neighbor - X_base) 151 | 152 | #use 10 as label because 0 to 9 real classes and 1 fake/smoted = 10 153 | return samples, [cl]*n_to_sample 154 | 155 | ############################################################################# 156 | np.printoptions(precision=5,suppress=True) 157 | 158 | dtrnimg = '.../0_trn_img.txt' 159 | dtrnlab = '.../0_trn_lab.txt' 160 | 161 | ids = os.listdir(dtrnimg) 162 | idtri_f = [os.path.join(dtrnimg, image_id) for image_id in ids] 163 | print(idtri_f) 164 | 165 | ids = os.listdir(dtrnlab) 166 | idtrl_f = [os.path.join(dtrnlab, image_id) for image_id in ids] 167 | print(idtrl_f) 168 | 169 | #path on the computer where the models are stored 170 | modpth = '.../MNIST/models/crs5/' 171 | 172 | encf = [] 173 | decf = [] 174 | for p in range(5): 175 | enc = modpth + '/' + str(p) + '/bst_enc.pth' 176 | dec = modpth + '/' + str(p) + '/bst_dec.pth' 177 | encf.append(enc) 178 | decf.append(dec) 179 | #print(enc) 180 | #print(dec) 181 | #print() 182 | 183 | for m in range(5): 184 | print(m) 185 | trnimgfile = idtri_f[m] 186 | trnlabfile = idtrl_f[m] 187 | print(trnimgfile) 188 | print(trnlabfile) 189 | dec_x = np.loadtxt(trnimgfile) 190 | dec_y = np.loadtxt(trnlabfile) 191 | 192 | print('train imgs before reshape ',dec_x.shape) #(44993, 3072) 45500, 3072) 193 | print('train labels ',dec_y.shape) #(44993,) (45500,) 194 | 195 | dec_x = dec_x.reshape(dec_x.shape[0],1,28,28) 196 | 197 | print('decy ',dec_y.shape) 198 | print(collections.Counter(dec_y)) 199 | 200 | print('train imgs after reshape ',dec_x.shape) #(45000,3,32,32) 201 | 202 | classes = ('0', '1', '2', '3', '4', 203 | '5', '6', '7', '8', '9') 204 | 205 | #generate some images 206 | train_on_gpu = torch.cuda.is_available() 207 | device = 'cuda' if torch.cuda.is_available() else 'cpu' 208 | 209 | path_enc = encf[m] 210 | path_dec = decf[m] 211 | 212 | encoder = Encoder(args) 213 | encoder.load_state_dict(torch.load(path_enc), strict=False) 214 | encoder = encoder.to(device) 215 | 216 | decoder = Decoder(args) 217 | decoder.load_state_dict(torch.load(path_dec), strict=False) 218 | decoder = decoder.to(device) 219 | 220 | encoder.eval() 221 | decoder.eval() 222 | 223 | #imbal = [4500, 2000, 1000, 800, 600, 500, 400, 250, 150, 80] 224 | imbal = [4000, 2000, 1000, 750, 500, 350, 200, 100, 60, 40] 225 | 226 | resx = [] 227 | resy = [] 228 | 229 | for i in range(1,10): 230 | xclass, yclass = biased_get_class1(i) 231 | print(xclass.shape) #(500, 3, 32, 32) 232 | print(yclass[0]) #(500,) 233 | 234 | #encode xclass to feature space 235 | xclass = torch.Tensor(xclass) 236 | xclass = xclass.to(device) 237 | xclass = encoder(xclass) 238 | print(xclass.shape) #torch.Size([500, 600]) 239 | 240 | xclass = xclass.detach().cpu().numpy() 241 | n = imbal[0] - imbal[i] 242 | xsamp, ysamp = G_SM1(xclass,yclass,n,i) 243 | print(xsamp.shape) #(4500, 600) 244 | print(len(ysamp)) #4500 245 | ysamp = np.array(ysamp) 246 | print(ysamp.shape) #4500 247 | 248 | """to generate samples for resnet""" 249 | xsamp = torch.Tensor(xsamp) 250 | xsamp = xsamp.to(device) 251 | #xsamp = xsamp.view(xsamp.size()[0], xsamp.size()[1], 1, 1) 252 | #print(xsamp.size()) #torch.Size([10, 600, 1, 1]) 253 | ximg = decoder(xsamp) 254 | 255 | ximn = ximg.detach().cpu().numpy() 256 | print(ximn.shape) #(4500, 3, 32, 32) 257 | #ximn = np.expand_dims(ximn,axis=1) 258 | print(ximn.shape) #(4500, 3, 32, 32) 259 | resx.append(ximn) 260 | resy.append(ysamp) 261 | #print('resx ',resx.shape) 262 | #print('resy ',resy.shape) 263 | #print() 264 | 265 | resx1 = np.vstack(resx) 266 | resy1 = np.hstack(resy) 267 | #print(resx1.shape) #(34720, 3, 32, 32) 268 | #resx1 = np.squeeze(resx1) 269 | print(resx1.shape) #(34720, 3, 32, 32) 270 | print(resy1.shape) #(34720,) 271 | 272 | resx1 = resx1.reshape(resx1.shape[0],-1) 273 | print(resx1.shape) #(34720, 3072) 274 | 275 | dec_x1 = dec_x.reshape(dec_x.shape[0],-1) 276 | print('decx1 ',dec_x1.shape) 277 | combx = np.vstack((resx1,dec_x1)) 278 | comby = np.hstack((resy1,dec_y)) 279 | 280 | print(combx.shape) #(45000, 3, 32, 32) 281 | print(comby.shape) #(45000,) 282 | 283 | ifile = '.../MNIST/trn_img_f/' + \ 284 | str(m) + '_trn_img.txt' 285 | np.savetxt(ifile, combx) 286 | 287 | lfile = '.../MNIST/trn_lab_f/' + \ 288 | str(m) + '_trn_lab.txt' 289 | np.savetxt(lfile,comby) 290 | print() 291 | 292 | t1 = time.time() 293 | print('final time(min): {:.2f}'.format((t1 - t0)/60)) 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DeepSMOTE 2 | DeepSMOTE paper: https://arxiv.org/pdf/2105.02340.pdf 3 | 4 | ## Code 5 | This repository contains sample code to implement DeepSMOTE. The first file, DeepSMOTE_MNIST.py, contains code to train a model on the MNIST dataset. The second file, GenerateSamples, provides code to generate samples on a trained model. 6 | 7 | ## Data and Pre-Trained Models 8 | 9 | Sample training images and labels, as well as saved models are available for download at: 10 | https://drive.google.com/drive/folders/1GRrpiR0CJpcfpjBKO18FLjombxgqH9cK?usp=sharing 11 | 12 | ## Dependencies 13 | 14 | The code was written with: Numpy 1.17; Python 3.6; Pytorch 1.3; and Scikit learn 0.24.1. 15 | 16 | 17 | --------------------------------------------------------------------------------