FlowKal commited on
Commit
3e388be
·
verified ·
1 Parent(s): 79787ee

Update model.py

Browse files
Files changed (1) hide show
  1. model.py +14 -30
model.py CHANGED
@@ -717,18 +717,17 @@ class ImprovedImageEncoder(nn.Module):
717
  def generate_beam_search(model, image_tensor, beam_size, max_len, sos_id, eos_id, pad_id, device):
718
  """
719
  Генерирует последовательность токенов с использованием Beam Search.
 
720
  """
721
  model.eval()
722
-
723
  model.reset_iac_state()
724
 
725
- # 2. Получаем признаки из энкодера один раз
 
726
  with torch.no_grad():
727
- # enc_output всегда имеет batch_size=1
728
- enc_output = model.enc(image_tensor.unsqueeze(0))
729
 
730
  # 3. Инициализация лучей.
731
- # beams - это список из кортежей (последовательность_тензор, score)
732
  beams = [(torch.tensor([sos_id], dtype=torch.long, device=device), 0.0)]
733
 
734
  # 4. Пошаговая генерация
@@ -742,73 +741,58 @@ def generate_beam_search(model, image_tensor, beam_size, max_len, sos_id, eos_id
742
 
743
  with torch.no_grad():
744
  input_seq = seq.unsqueeze(0)
745
-
746
-
747
  outputs = model.forward_inference(enc_output, input_seq)
748
-
749
- logits = outputs['logits'][:, -1, :] # Логиты для последнего токена
750
 
751
  log_probs = F.log_softmax(logits, dim=-1)
752
  top_log_probs, top_ids = torch.topk(log_probs, beam_size, dim=-1)
753
 
754
- # Создаем новых кандидатов
755
  for i in range(beam_size):
756
  next_id = top_ids[0, i]
757
  log_prob = top_log_probs[0, i].item()
758
-
759
- # Создаем новую последовательность, добавляя новый токен
760
  new_seq = torch.cat([seq, next_id.view(1)])
761
  new_score = score + log_prob
762
  all_candidates.append((new_seq, new_score))
763
 
764
- # 5. Сортируем всех кандидатов и выбираем `beam_size` лучших
765
  ordered = sorted(all_candidates, key=lambda x: x[1], reverse=True)
766
  beams = ordered[:beam_size]
767
 
768
- # 6. Условие остановки: если все лучшие лучи закончились на EOS
769
  if all(b[0][-1] == eos_id for b in beams):
770
  break
771
 
772
- # 7. Выбираем лучший луч, нормализуя на длину, чтобы не штрафовать длинные последовательности
773
  best_beam = sorted(beams, key=lambda x: x[1] / len(x[0]), reverse=True)[0]
774
  best_seq = best_beam[0]
775
 
776
  return best_seq
777
 
778
- # ======================================================================
779
- # 2. Удобная обертка для предсказания
780
- # ======================================================================
781
 
782
- def predict_with_beam_search(model, image_path, vocab, beam_size, device):
783
  """
784
- Загружает изображение, запускает Beam Search и возвращает LaTeX строку.
785
  """
786
- # 1. Загрузка и трансформация изображения
787
- transform = transforms.Compose([
788
- transforms.Resize((IMG_HEIGHT, IMG_WIDTH)),
789
- transforms.ToTensor(),
790
- transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
791
- ])
792
- image = Image.open(image_path).convert("RGB")
793
- image_tensor = transform(image).to(device)
794
 
795
  # 2. Получение ID спецтокенов
796
  sos_id = vocab.stoi[SOS_TOKEN]
797
  eos_id = vocab.stoi[EOS_TOKEN]
798
  pad_id = vocab.stoi[PAD_TOKEN]
799
 
800
- # 3. Генерация
 
801
  predicted_ids = generate_beam_search(
802
- model, image_tensor, beam_size, MAX_SEQ_LEN, sos_id, eos_id, pad_id, device
803
  )
804
 
805
  # 4. Декодирование
806
  predicted_ids = predicted_ids.cpu().numpy()
807
  try:
 
808
  eos_index = list(predicted_ids).index(eos_id)
809
  predicted_ids = predicted_ids[:eos_index]
810
  except ValueError:
811
  pass # EOS не был сгенерирован
812
 
 
813
  latex_string = vocab.decode(predicted_ids)
814
  return latex_string
 
717
  def generate_beam_search(model, image_tensor, beam_size, max_len, sos_id, eos_id, pad_id, device):
718
  """
719
  Генерирует последовательность токенов с использованием Beam Search.
720
+ ПРИНИМАЕТ ГОТОВЫЙ ТЕНЗОР ИЗОБРАЖЕНИЯ.
721
  """
722
  model.eval()
 
723
  model.reset_iac_state()
724
 
725
+ # 2. Получаем признаки из энкодера один раз.
726
+ # image_tensor уже должен иметь batch_size=1, поэтому убираем .unsqueeze(0)
727
  with torch.no_grad():
728
+ enc_output = model.enc(image_tensor)
 
729
 
730
  # 3. Инициализация лучей.
 
731
  beams = [(torch.tensor([sos_id], dtype=torch.long, device=device), 0.0)]
732
 
733
  # 4. Пошаговая генерация
 
741
 
742
  with torch.no_grad():
743
  input_seq = seq.unsqueeze(0)
 
 
744
  outputs = model.forward_inference(enc_output, input_seq)
745
+ logits = outputs['logits'][:, -1, :]
 
746
 
747
  log_probs = F.log_softmax(logits, dim=-1)
748
  top_log_probs, top_ids = torch.topk(log_probs, beam_size, dim=-1)
749
 
 
750
  for i in range(beam_size):
751
  next_id = top_ids[0, i]
752
  log_prob = top_log_probs[0, i].item()
 
 
753
  new_seq = torch.cat([seq, next_id.view(1)])
754
  new_score = score + log_prob
755
  all_candidates.append((new_seq, new_score))
756
 
 
757
  ordered = sorted(all_candidates, key=lambda x: x[1], reverse=True)
758
  beams = ordered[:beam_size]
759
 
 
760
  if all(b[0][-1] == eos_id for b in beams):
761
  break
762
 
 
763
  best_beam = sorted(beams, key=lambda x: x[1] / len(x[0]), reverse=True)[0]
764
  best_seq = best_beam[0]
765
 
766
  return best_seq
767
 
 
 
 
768
 
769
+ def predict_with_beam_search(model, image_tensor, vocab, beam_size, device):
770
  """
771
+ ЗАПУСКАЕТ BEAM SEARCH НА ОСНОВЕ ГОТОВОГО ТЕНЗОРА ИЗОБРАЖЕНИЯ.
772
  """
773
+ # <<< МЫ УДАЛИЛИ ВСЮ ЛОГИКУ ЗАГРУЗКИ И ТРАНСФОРМАЦИИ ИЗОБРАЖЕНИЯ ОТСЮДА >>>
774
+ # Теперь функция просто принимает image_tensor
 
 
 
 
 
 
775
 
776
  # 2. Получение ID спецтокенов
777
  sos_id = vocab.stoi[SOS_TOKEN]
778
  eos_id = vocab.stoi[EOS_TOKEN]
779
  pad_id = vocab.stoi[PAD_TOKEN]
780
 
781
+ # 3. Генерация (теперь передаем тензор напрямую)
782
+ # Убедимся, что тензор на правильном устройстве
783
  predicted_ids = generate_beam_search(
784
+ model, image_tensor.to(device), beam_size, MAX_SEQ_LEN, sos_id, eos_id, pad_id, device
785
  )
786
 
787
  # 4. Декодирование
788
  predicted_ids = predicted_ids.cpu().numpy()
789
  try:
790
+ # Убираем все после EOS токена
791
  eos_index = list(predicted_ids).index(eos_id)
792
  predicted_ids = predicted_ids[:eos_index]
793
  except ValueError:
794
  pass # EOS не был сгенерирован
795
 
796
+ # Декодируем, пропуская SOS токен в начале
797
  latex_string = vocab.decode(predicted_ids)
798
  return latex_string