Topic 4 of 6

Course materials are currently available in Russian only.

Модель изнутри

pipeline удобен, но прячет главное. Посмотрим, что происходит внутри: какие числа выдаёт модель и как из них получаются ответы.

Модель и её выход

import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification

name = "distilbert/distilbert-base-uncased-finetuned-sst-2-english"
tok = AutoTokenizer.from_pretrained(name)
model = AutoModelForSequenceClassification.from_pretrained(name)

enc = tok(["What a great day!", "Worst film ever"], padding=True, return_tensors="pt")
with torch.no_grad():
    outputs = model(**enc)
outputs.logits            # tensor([[-4.2, 4.5], [4.6, -3.8]])
model.config.id2label     # {0: 'NEGATIVE', 1: 'POSITIVE'}
  • Auto…-классы сами выбирают нужную архитектуру по имени модели: AutoModelForSequenceClassification — классификатор, AutoModel — «голая» модель без головы;
  • модель вызывают с результатом токенизатора: model(**enc); на время предсказаний — torch.no_grad();
  • выход — объект с полями: у классификатора logits формы (тексты, классы).

Логиты → ответ

probs = torch.softmax(outputs.logits, dim=-1)        # вероятности по классам
conf, best = probs.max(dim=-1)
[(model.config.id2label[i], p) for i, p in zip(best.tolist(), conf.tolist())]

Ровно это и делает pipeline("sentiment-analysis"). dim=-1 — последнее измерение, то есть классы.

Векторы текстов

«Голая» модель возвращает last_hidden_state — вектор на каждый токен, форма (тексты, токены, размер вектора). Чтобы получить один вектор на текст (эмбеддинг), векторы токенов усредняют — но только настоящих, без [PAD]:

h = outputs.last_hidden_state
m = enc["attention_mask"].unsqueeze(-1).float()     # (N, L) → (N, L, 1)
vectors = (h * m).sum(dim=1) / m.sum(dim=1)

Близость по смыслу

Похожие по смыслу тексты дают векторы, смотрящие в одну сторону. Сравнивают их косинусной близостью — от −1 до 1, длина векторов на неё не влияет:

sim = torch.nn.functional.cosine_similarity(query, vectors, dim=-1)
sim.argmax()          # самый похожий текст

Так работает смысловой поиск: «доставка задержалась» найдёт «курьер опоздал», хотя общих слов нет.

Итог

  • AutoTokenizer + AutoModelForSequenceClassification / AutoModel, model(**enc) в no_grad;
  • outputs.logits → softmax(dim=-1) → config.id2label;
  • last_hidden_state и усреднение с attention_mask;
  • косинусная близость для поиска похожих текстов.