def train_and_predict(x_train, y_train, x_val, y_val, x_test): """Train a neural network classifier and compute predictions. Args: x_train (np.ndarray): Training instances. y_train (np.ndarray): Training labels. x_val (np.ndarray): Validation instances. y_val (np.ndarray): Validation labels. x_test (np.ndarray): Test instances. Returns: The predictions of the classifier. """ _ensure_reproducibility() # Determine which device (GPU or CPU) to use device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') # Convert data into PyTorch tensors x_train = torch.FloatTensor(x_train).transpose(1, 2) x_val = torch.FloatTensor(x_val).transpose(1, 2) x_test = torch.FloatTensor(x_test).transpose(1, 2) y_train = torch.FloatTensor(y_train) y_val = torch.FloatTensor(y_val) # Instantiate neural network n_classes = y_train.shape[-1] n_feats = x_train.shape[1] net = CRNN(n_classes, n_feats).to(device) # Use binary cross-entropy loss function criterion = BCELoss() # Use Adam optimization algorithm optimizer = Adam(net.parameters(), lr=0.01) # Use scheduler to decay learning rate regularly scheduler = StepLR(optimizer, step_size=2, gamma=0.9) # Use helper class to iterate over data in batches loader_train = DataLoader(TensorDataset(x_train, y_train), batch_size=128, shuffle=True) loader_val = DataLoader(TensorDataset(x_val, y_val), batch_size=512) loader_test = DataLoader(TensorDataset(x_test), batch_size=512) # Instantiate Logger to record training/validation performance # Configure to save the states of the top 3 models during validation logger = Logger(net, n_states=3) for epoch in range(15): # Train model using training set pbar = tqdm(loader_train) pbar.set_description('Epoch %d' % epoch) train(net.train(), criterion, optimizer, pbar, logger, device) # Evaluate model using validation set and monitor F1 score validate(net.eval(), criterion, loader_val, logger, device) logger.monitor('val_f1') # Print training and validation results logger.print_results() # Invoke learning rate scheduler scheduler.step() # Ensemble top 3 model predictions y_preds = [] for state_dict in logger.state_dicts: net.load_state_dict(state_dict) y_preds.append(_flatten(predict(net, loader_test, device))) return torch.stack(y_preds).mean(dim=0).cpu().numpy()
def main(): args = hyperparameters() train_path = os.path.join(args.path, 'train') test_path = os.path.join(args.path, 'test') # gpu or cpu 설정 device = torch.device( f'cuda:{args.device}' if torch.cuda.is_available() else 'cpu') # train dataset load train_dataset = CRNN_dataset(path=train_path, w=args.img_width, h=args.img_height) train_dataloader = DataLoader(train_dataset, batch_size=args.batch_size, shuffle=True) # test dataset load test_dataset = CRNN_dataset(path=test_path, w=args.img_width, h=args.img_height) test_dataloader = DataLoader(test_dataset, batch_size=args.batch_size, shuffle=True) # model 정의 model = CRNN(args.img_height, 1, 37, 256) # nc=1, nclass=37, nh=256 # loss 정의 criterion = nn.CTCLoss() if args.optim == 'adam': optimizer = optim.Adam(model.parameters(), lr=args.lr, betas=(0.5, 0.999)) elif args.optim == 'rmsprop': optimizer = optim.RMSprop(model.parameters(), lr=args.lr) else: assert False, "옵티마이저를 다시 입력해주세요. :(" model = model.to(device) best_test_loss = 100000000 for i in range(args.epochs): print('epochs: ', i) print("<----training---->") model.train() for inputs, targets in tqdm(train_dataloader): inputs = inputs.permute( 0, 1, 3, 2 ) # inputs의 dimension을 (batch, channel, h, w)로 바꿔주세요. hint: pytorch tensor에 제공되는 함수 사용 batch_size = inputs.size(0) inputs = inputs.to(device) target_text, target_length = targets target_text, target_length = target_text.to( device), target_length.to(device) preds = model(inputs) preds = F.log_softmax(preds, dim=-1) preds_length = Variable( torch.IntTensor([preds.size(0)] * batch_size)) """ CTCLoss의 설명과 해당 로스의 input에 대해 설명해주세요. CTC(Connectionist Temporal Classification)이란, 입력 프레임 시퀀스와 타겟 시퀀스 간에 명시적으로 할당해주지 않아도 모델을 학습할 수 있는 기법을 말한다. CRNN을 살펴보면, 입력 이미지 feature vector sequence의 길이는 가변적이고 실제 단어의 글자수와도 맞지 않는다. 기존의 CNN은 라벨 할당으로 학습한 것과 달리, 입력 sequence가 주어졌을 때 각 시점별로 본래 label sequence로 향하는 모든 가능한 경로를 고려하여 우도를 구하여 학습한다. 연산량의 감소를 위해 dynamic programming (앞에서 계산한 경로의 우도를 기억해두는 방법) 알고리즘을 활용한다는 특징이 있고, CTC layer는 RNN 출력 확률 벡터 sequence를 입력받아 loss를 계산하여 grandient를 통해 학습을 가능하게 만든다. loss의 input은 RNN layer의 출력 확률 벡터 sequence라고 할 수 있다. """ loss = criterion(preds, target_text, preds_length, target_length) / batch_size optimizer.zero_grad() loss.backward() optimizer.step() print("\n<----evaluation---->") """ model.train(), model.eval()의 차이에 대해 설명해주세요. .eval()을 하는 이유가 무엇일까요? train은 말 그대로 학습 모드 , eval은 test 모드를 의미한다. 학습이 끝났으니 test 모드에 들어가자~! 하고 모델에게 알려주는 것이다. """ model.eval() loss = 0.0 for inputs, targets in tqdm(test_dataloader): inputs = inputs.permute(0, 1, 3, 2) batch_size = inputs.size(0) inputs = inputs.to(device) target_text, target_length = targets target_text, target_length = target_text.to( device), target_length.to(device) preds = model(inputs) preds = F.log_softmax(preds, dim=-1) preds_length = Variable( torch.IntTensor([preds.size(0)] * batch_size)) loss += criterion( preds, target_text, preds_length, target_length ) / batch_size # 학습이 아니라 test loss이니 밑에서 찍으려면 이 한 줄이 더 있어야 한다. print("\ntest loss: ", loss) if loss < best_test_loss: # loss가 bset_test_loss보다 작다면 지금의 loss가 best loss가 되겠죠? best_test_loss = loss # args.savepath을 이용하여 best model 저장하기 torch.save(model.state_dict(), args.savepath) print("best model 저장 성공")
def main(): args = hyperparameters() train_path = os.path.join(args.path, 'train') test_path = os.path.join(args.path, 'test') # gpu or cpu 설정 device = torch.device(f'cuda:{args.device}' if torch.cuda.is_available() else 'cpu') # train dataset load train_dataset = CRNN_dataset(path=train_path, w=args.img_width, h=args.img_height) train_dataloader = DataLoader(train_dataset, batch_size=args.batch_size, shuffle=True) # test dataset load test_dataset = CRNN_dataset(path=test_path, w=args.img_width, h=args.img_height) test_dataloader = DataLoader(test_dataset, batch_size=args.batch_size, shuffle=True) # model 정의 model = CRNN(args.img_height, 1, 37, 256) # loss 정의 criterion = nn.CTCLoss() if args.optim == 'adam': optimizer = optim.Adam(model.parameters(), lr=args.lr, betas=(0.5, 0.999)) elif args.optim == 'rmsprop': optimizer = optim.RMSprop(model.parameters(), lr=args.lr) else: assert False, "옵티마이저를 다시 입력해주세요. :(" model = model.to(device) best_test_loss = 100000000 for i in range(args.epochs): print('epochs: ', i) print("<----training---->") model.train() for inputs, targets in tqdm(train_dataloader): # inputs의 dimension을 (batch, channel, h, w)로 바꿔주세요. hint: pytorch tensor에 제공되는 함수 사용 batch_size = inputs.size(0) inputs = inputs.to(device) target_text, target_length = targets target_text, target_length = target_text.to(device), target_length.to(device) preds = model(inputs) # 여기를 log probability로 바꿔야할 것 같은데욥... preds_length = Variable(torch.IntTensor([preds.size(0)] * batch_size)) """ CTCLoss의 설명과 해당 로스의 input에 대해 설명해주세요. CTC = Connectionist Temporal Classification 각각의 수평적인 위치에서 annotation을 획득한 label L을 input으로 삼는다. 이 input은 한 문자가 여러 위치단위에 있는 경우(한 글자의 크기가 커서) annotation이 중복되어 도출될 수 있기 때문에 문제가 발생하는데 이 때 CTC는 위치와 넓이를 무시하고, ground-truth text만을 CTC Loss function에 제공하고 잘못 중복된 annotation을 제거해준다. 그리고 이 때 생성되는 가능한 모든 gt text의 점수들의 합에 -log를 취한 값이 CTC Loss이다. """ loss = criterion(preds, target_text, preds_length, target_length) / batch_size optimizer.zero_grad() loss.backward() optimizer.step() print("<----evaluation---->") """ model.train(), model.eval()의 차이에 대해 설명해주세요. .eval()을 하는 이유가 무엇일까요? batchnorm과 dropout이 있는 모델은 train할 때와 evaluate할 때 모델이 달라지기 때문에 설정하는 것이다. (평가 모델에 batchnorm과 dropout을 실행한다.) """ model.eval() loss = 0.0 for inputs, targets in tqdm(test_dataloader): with torch.no_grad(): batch_size = inputs.size(0) inputs = inputs.to(device) target_text, target_length = targets target_text, target_length = target_text.to(device), target_length.to(device) # 설정한 device (gpu or cpu) 에 저장되도록 preds = model(inputs) preds_length = Variable(torch.IntTensor([preds.size(0)] * batch_size)) loss = criterion(preds, target_text, preds_length, target_length) / batch_size # test를 어떻게 할까?? print("test loss: ", loss) if loss < best_test_loss: # loss가 bset_test_loss보다 작다면 지금의 loss가 best loss가 되겠죠? best_test_loss = loss # args.savepath을 이용하여 best model 저장하기 PATH = args.savepath torch.save(model, PATH) print("best model 저장 성공")
def main(opts): alphabet = '0123456789.' nclass = len(alphabet) + 1 model_name = 'crnn' net = CRNN(nclass) print("Using {0}".format(model_name)) if opts.cuda: net.cuda() learning_rate = opts.base_lr optimizer = torch.optim.Adam(net.parameters(), lr=opts.base_lr, weight_decay=weight_decay) if os.path.exists(opts.model): print('loading model from %s' % args.model) step_start, learning_rate = net_utils.load_net(args.model, net, optimizer) ## 数据集 converter = strLabelConverter(alphabet) dataset = ImgDataset( root='/home/yangna/deepblue/OCR/mech_demo2/dataset/imgs/image', csv_root='/home/yangna/deepblue/OCR/mech_demo2/dataset/imgs/train_list.txt', transform=None, target_transform=converter.encode ) ocrdataloader = torch.utils.data.DataLoader( dataset, batch_size=opts.batch_size, shuffle=True, collate_fn=own_collate ) step_start = 0 net.train() converter = strLabelConverter(alphabet) ctc_loss = CTCLoss() for step in range(step_start, opts.max_iters): try: data = next(data_iter) except: data_iter = iter(ocrdataloader) data = next(data_iter) im_data, gt_boxes, text = data im_data = im_data.cuda() try: loss= process_crnn(im_data, gt_boxes, text, net, ctc_loss, converter, training=True) net.zero_grad() optimizer.zero_grad() loss.backward() optimizer.step() except: import sys, traceback traceback.print_exc(file=sys.stdout) pass if step % disp_interval == 0: try: print('step:%d || loss %.4f' % (step, loss)) except: import sys, traceback traceback.print_exc(file=sys.stdout) pass if step > step_start and (step % batch_per_epoch == 0): save_name = os.path.join(opts.save_path, '{}_{}.h5'.format(model_name, step)) state = {'step': step, 'learning_rate': learning_rate, 'state_dict': net.state_dict(), 'optimizer': optimizer.state_dict()} torch.save(state, save_name) print('save model: {}'.format(save_name))
preds = crnn(image) preds_size = Variable(torch.IntTensor([preds.size(0)] * batch_size)) cost = criterion(preds, text, preds_size, length) / batch_size crnn.zero_grad() cost.backward() optimizer.step() return cost for epoch in range(opt.nepoch): train_iter = iter(train_loader) i = 0 while i < len(train_loader): for p in crnn.parameters(): p.requires_grad = True crnn.train() cost = trainBatch(crnn, criterion, optimizer) loss_avg.add(cost) i += 1 if i % opt.displayInterval == 0: print('[%d/%d][%d/%d] Loss: %f' % (epoch, opt.nepoch, i, len(train_loader), loss_avg.val())) loss_avg.reset() if i % opt.valInterval == 0: val(crnn, test_dataset, criterion) # do checkpointing if i % opt.saveInterval == 0:
def main(): args = hyperparameters() train_path = os.path.join(args.path, 'train') test_path = os.path.join(args.path, 'test') # gpu or cpu 설정 device = torch.device( f'cuda:{args.device}' if torch.cuda.is_available() else 'cpu') # train dataset load train_dataset = CRNN_dataset(path=train_path, w=args.img_width, h=args.img_height) train_dataloader = DataLoader(train_dataset, batch_size=args.batch_size, shuffle=True) # test dataset load test_dataset = CRNN_dataset(path=test_path, w=args.img_width, h=args.img_height) test_dataloader = DataLoader(test_dataset, batch_size=args.batch_size, shuffle=True) # model 정의 model = CRNN( nc=1, nclass=37, nh=256, imgH=args.img_height) #nc =1 ,nclass = 36, nh = 100, #args.img_height # loss 정의 criterion = nn.CTCLoss() if args.optim == 'adam': optimizer = optim.Adam(model.parameters(), lr=args.lr, betas=(0.5, 0.999)) elif args.optim == 'rmsprop': optimizer = optim.RMSprop(model.parameters(), lr=args.lr) else: assert False, "옵티마이저를 다시 입력해주세요. :(" model = model.to(device) best_test_loss = 100000000 for i in range(args.epochs): print('epochs: ', i) print("<----training---->") model.train() for inputs, targets in tqdm(train_dataloader): # ---?--- # inputs의 dimension을 (batch, channel, h, w)로 바꿔주세요. hint: pytorch tensor에 제공되는 함수 사용 inputs = inputs.permute(0, 1, 3, 2) batch_size = inputs.size(0) inputs = inputs.to(device) target_text, target_length = targets target_text, target_length = target_text.to( device), target_length.to(device) preds = model(inputs) preds = preds.log_softmax(2) preds_length = Variable( torch.IntTensor([preds.size(0)] * batch_size)) """ CTCLoss의 설명과 해당 로스의 input에 대해 설명해주세요. 학습데이터에 클래스 라벨만 순서대로 있고 각 클래스의 위치는 어디있는지 모르는 unsegmented 시퀀스 데이터의 학습을 위해서 사용하는 알고리즘 ocr(광학 문자 인식)이나 음성 인식등에 널리 사용된다 input: 예측값, 정답값, 예측 시퀀스의 길이, 정답 시퀀스의 길이 """ loss = criterion(preds, target_text, preds_length, target_length) / batch_size optimizer.zero_grad() loss.backward() optimizer.step() print("<----evaluation---->") """ model.train(), model.eval()의 차이에 대해 설명해주세요. .eval()을 하는 이유가 무엇일까요? 모델을 학습할 때 train/eval에 맞게 모델을 변경시킨다 Dropout이나 batchNormalization을 쓰는 모델은 학습시킬 때와 평가할 때 구조/역할이 다르기 때문이다. """ model.eval() loss = 0.0 for inputs, targets in tqdm(test_dataloader): inputs = inputs.permute(0, 1, 3, 2) batch_size = inputs.size(0) inputs = inputs.to(device) target_text, target_length = targets target_text, target_length = target_text.to( device), target_length.to(device) preds = model(inputs) preds = preds.log_softmax(2) preds_length = Variable( torch.IntTensor([preds.size(0)] * batch_size)) loss += criterion(preds, target_text, preds_length, target_length) / batch_size print("test loss: ", loss / len(test_dataloader)) if loss < best_test_loss: # loss가 bset_test_loss보다 작다면 지금의 loss가 best loss가 되겠죠? best_test_loss = loss.clone() # args.savepath을 이용하여 best model 저장하기 torch.save(model.state_dict(), args.savepath) print("best model 저장 성공")