Невозможно улучшить точность модели - PullRequest
0 голосов
/ 09 апреля 2020

Я создаю NN общего назначения, которая классифицирует изображения (Dog / No Dog) и обзоры mov ie (Good / Bad). Я должен придерживаться очень специфической c архитектуры и функции потерь, поэтому изменение этих двух параметров кажется не в уравнении. Моя архитектура представляет собой двухслойную сеть с relu, за которой следуют сигмоид и функция кросс-энтропийной потери. Благодаря 1000 эпохам и скорости обучения около 0,001, я получаю 100-процентную точность обучения и 0,72 точность тестирования. Я искал предложения по повышению точности моего тестирования. Это схема того, что у меня есть:

def train_net(epochs,batch_size,train_x,train_y,model_size,lr):
  n_x,n_h,n_y=model_size
  model = Net(n_x, n_h, n_y)
  optim = torch.optim.Adam(model.parameters(),lr=0.005)
  loss_function = nn.BCELoss() 
  train_losses = []
  accuracy = []
  for epoch in range(epochs):
    count=0
    model.train() 
    train_loss = []
    batch_accuracy = []
    for idx in range(0, train_x.shape[0], batch_size):

      batch_x = torch.from_numpy(train_x[idx : idx + batch_size]).float() 
      batch_y = torch.from_numpy(train_y[:,idx : idx + batch_size]).float()    
      model_output = model(batch_x) 
      batch_accuracy=[]  
      loss = loss_function(model_output, batch_y) 
      train_loss.append(loss.item())

      preds = model_output > 0.5
      nb_correct = (preds == batch_y).sum()
      count+=nb_correct.item()                            
      optim.zero_grad()
      loss.backward()
# Scheduler made it worse 
# scheduler.step(loss.item())  
  optim.step()

    if epoch % 100 == 1:
      train_losses.append(train_loss)
      print("Iteration : {}, Training loss: {} ,Accuracy %: {}".format(epoch,np.mean(train_loss),(count/train_x.shape[0])*100))              
  plt.plot(np.squeeze(train_losses))
  plt.ylabel('loss')
  plt.xlabel('iterations (per tens)')
  plt.title("Learning rate =" + str(lr))
  plt.show()
  return model

Параметры моей модели:

batch_size = 32
lr = 0.0001
epochs = 1500

n_x = 12288     # num_px * num_px * 3
n_h = 7
n_y = 1
model_size=n_x,n_h,n_y
model=train_net(epochs,batch_size,train_x,train_y,model_size,or)

и это этап тестирования.

model.eval()  #Setting the model to eval mode, hence making it deterministic.
test_loss = []
count=0;
loss_function = nn.BCELoss()

for idx in range(0, test_x.shape[0], batch_size):
  with torch.no_grad():   
    batch_x = torch.from_numpy(test_x[idx : idx + batch_size]).float() 
    batch_y = torch.from_numpy(test_y[:,idx : idx + batch_size]).float()
    model_output = model(batch_x)
    preds = model_output > 0.5
    loss = loss_function(model_output, batch_y)
    test_loss.append(loss.item())
    nb_correct = (preds == batch_y).sum()
    count+=nb_correct.item()  

print("test loss: {},test accuracy: {}".format(np.mean(test_loss),count/test_x.shape[0]))

Вещи, которые я пробовал: возиться со скоростью обучения, набирать обороты, использовать планировщики и изменение размеров партии. Конечно, это были в основном догадки и не основанные на каких-либо действительных предположениях.

Ответы [ 2 ]

1 голос
/ 09 апреля 2020

Проблема, с которой вы столкнулись, это переоснащение . Со 100% точностью обучающего набора ваша модель эффективно запоминает обучающий набор, а затем не может обобщить до невидимых выборок. Хорошей новостью является то, что это очень распространенная серьезная проблема!

Вам нужна регуляризация. Одним из методов является dropout , при котором в разные периоды обучения отбрасывается случайный набор NN-соединений, что вынуждает сеть «изучать» альтернативные пути и веса и смягчает резкие пики в пространстве параметров. Поскольку вам нужно сохранить архитектуру и функцию потерь одинаковыми, вы не сможете добавить такую ​​опцию в (хотя для полноты прочитайте эту статью для описания и реализации исключения из PyTorch).

Учитывая ваши ограничения, вы захотите использовать что-то вроде регуляризация веса L2 или L1 . Обычно это проявляется в добавлении дополнительного члена к функции затрат / потерь, которая штрафует большие веса. В PyTorch регуляризация L2 реализована с помощью конструкции torch.optim с опцией weight_decay. (См. Документацию: torch.optim , найдите «L2»)

Для своего кода попробуйте что-то вроде:

def train_net(epochs,batch_size,train_x,train_y,model_size,lr):
  ...
  optim = torch.optim.Adam(model.parameters(),...,weight_decay=0.01)
  ...
0 голосов
/ 09 апреля 2020

На основании вашего заявления о том, что ваша точность обучения составляет 100%, а точность тестирования значительно ниже - 72%, создается впечатление, что вы значительно переоснащаете свой набор данных.

Короче говоря, это означает, что ваша модель тренируется слишком специфично для данных обучения, которые вы ей предоставили, обнаруживая причуды, которые могут существовать в данных обучения, но которые не присущи классификации. Например, если все собаки в ваших тренировочных данных были белыми, то в конечном итоге модель научилась бы связывать белый цвет с собаками и с трудом могла распознавать собак других окрасов, данных ей в наборе данных испытаний.

Существует множество способов решения этой проблемы: полный обзор предмета, написанный в простых терминах, можно найти здесь .

Без дополнительной информации об определенных c ограничениях у вас есть вокруг изменения архитектуры нейронной сети, трудно сказать наверняка, что вы будете и не сможете изменить. Тем не менее, регуляризация веса и выпадение часто используются с большим эффектом (и описаны в вышеприведенной статье.) Вы также должны быть в состоянии осуществить ранний останов и ограничение веса для модели.

Я оставлю это вам, чтобы найти ресурсы о том, как реализовать эти специфические c стратегии в pytorch, но это должно обеспечить хорошую отправную точку.

...