Оценка и вывод: от логитов к предсказанным меткам
Вы вычислите softmax для логитов, преобразуете предсказанные индексы классов в метки и оцените дообученную модель по точности и F1 на отложенном тестовом наборе.
«Оценка и вывод: от логитов к предсказанным меткам» — бесплатный урок Machine Learning Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Machine Learning Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Machine Learning Academy содержит 4 уроков всего.
Что такое логиты
Результат последнего линейного слоя модели классификации называется логитами: это необработанные ненормализованные оценки для каждого класса. Для задачи с 2 классами (отрицательный/положительный) вектор логитов может выглядеть как [-1.2, 3.5], что означает, что модель сильно склоняется к классу 1 (положительному). Логит может быть любым вещественным числом; это не вероятность. Нужен дополнительный шаг (softmax или sigmoid), чтобы преобразовать логиты в понятные значения вероятностей, сумма которых равна 1.
import torch
import torch.nn.functional as F
# Example logits for 2-class problem (batch of 3)
logits = torch.tensor([[-1.2, 3.5], [2.1, -0.3], [0.4, 0.6]])
print('Logits:\n', logits)
# Convert to probabilities with softmax
probs = F.softmax(logits, dim=1)
print('Probabilities:\n', probs)
# Each row sums to 1
print('Row sums:', probs.sum(dim=1))Softmax: преобразование логитов в вероятности
Функция softmax преобразует вектор логитов с вещественными значениями в распределение вероятностей. Для класса i: softmax(z_i) = exp(z_i) / sum(exp(z_j)). Экспонента усиливает различия: разница логитов, равная 2, приводит к тому, что один класс становится примерно в 7 раз более вероятным, чем другой. Softmax используется для многоклассовой классификации, где правильным является ровно один класс.
import torch
import torch.nn.functional as F
import numpy as np
logits = torch.tensor([1.0, 3.0, 0.5]) # 3 classes
probs = F.softmax(logits, dim=0)
print('Class probabilities:', probs.numpy().round(4))
# [0.0900, 0.6652, 0.2449] -- class 1 is most likely
print('Sum:', probs.sum().item()) # 1.0
# argmax gives the predicted class index
pred_class = torch.argmax(probs).item()
print('Predicted class:', pred_class) # 1argmax: извлечение предсказанных меток
Когда у нас есть векторы логитов для пакета примеров, torch.argmax(logits, dim=1) возвращает индекс класса с наибольшей оценкой для каждого примера. Это и есть предсказанная метка класса. Для BERT, дообученного с параметром num_labels=2, результатом будет 0 (отрицательный класс) или 1 (положительный класс). Перед argmax не нужно применять softmax, поскольку softmax монотонна: наибольший логит всегда преобразуется в наибольшую вероятность.
import torch
# Logits from model output for a batch of 4 examples
logits = torch.tensor([
[-2.1, 3.4], # strongly positive
[ 1.8, -0.5], # negative
[ 0.1, 0.2], # uncertain, leans positive
[-3.0, -1.0] # both negative, less-negative wins
])
predictions = torch.argmax(logits, dim=1)
print('Predictions:', predictions.tolist()) # [1, 0, 1, 1]
labels = {'0': 'negative', '1': 'positive'}
for pred in predictions.tolist():
print(labels[str(pred)])Декодирование предсказанных индексов в названия классов
Модель возвращает целочисленные индексы. В рабочей системе следует хранить соответствие между индексом и понятной человеку меткой. Сохраните его в виде списка или словаря и обращайтесь к нему по предсказанному целому числу. Для BERT, дообученного на IMDB, соответствие выглядит просто: {0: 'NEGATIVE', 1: 'POSITIVE'}. Для многоклассовых задач, например классификации тем, соответствие может содержать 20 и более записей.
import torch
from transformers import BertForSequenceClassification, BertTokenizer
# Assume model and tokenizer are already loaded and fine-tuned
id2label = {0: 'NEGATIVE', 1: 'POSITIVE'}
def predict(text, model, tokenizer, device):
model.eval()
inputs = tokenizer(text, return_tensors='pt',
truncation=True, max_length=256)
inputs = {k: v.to(device) for k, v in inputs.items()}
with torch.no_grad():
logits = model(**inputs).logits
pred_id = torch.argmax(logits, dim=1).item()
return id2label[pred_id]
# result = predict('This film was absolutely wonderful!', model, tokenizer, device)
# print(result) # POSITIVEОценки уверенности на основе вероятностей
Для реальных приложений часто недостаточно вернуть только предсказанную метку. Оценка уверенности (вероятность предсказанного класса) показывает, насколько модель уверена в своём решении. Предсказание POSITIVE с уверенностью 99% сильно отличается от предсказания с уверенностью 52%. Направление предсказаний с низкой уверенностью на проверку человеком — распространённая практика в рабочих системах, принимающих чувствительные решения.
import torch
import torch.nn.functional as F
def predict_with_confidence(text, model, tokenizer, device):
model.eval()
id2label = {0: 'NEGATIVE', 1: 'POSITIVE'}
inputs = tokenizer(text, return_tensors='pt',
truncation=True, max_length=256)
inputs = {k: v.to(device) for k, v in inputs.items()}
with torch.no_grad():
logits = model(**inputs).logits
probs = F.softmax(logits, dim=1).squeeze()
pred_id = torch.argmax(probs).item()
confidence = probs[pred_id].item()
return id2label[pred_id], round(confidence, 4)
# label, conf = predict_with_confidence('Terrible movie.', model, tokenizer, device)
# print(label, conf) # NEGATIVE 0.9732Оценка с помощью точности и F1
После сбора прогнозов для всей тестовой выборки вычислите стандартные метрики с помощью scikit-learn. Точность — доля правильных прогнозов; она полезна, когда классы сбалансированы. Оценка F1 — гармоническое среднее полноты и точности; она важна, когда один класс (например, положительные отзывы) имеет большее значение или классы несбалансированы. classification_report выводит все метрики в одной понятной таблице.
from sklearn.metrics import classification_report, accuracy_score
import torch
all_preds, all_labels = [], []
model.eval()
with torch.no_grad():
for batch in test_loader:
outputs = model(
input_ids=batch['input_ids'].to(device),
attention_mask=batch['attention_mask'].to(device)
)
preds = torch.argmax(outputs.logits, dim=1).cpu().numpy()
all_preds.extend(preds)
all_labels.extend(batch['label'].numpy())
print('Accuracy:', accuracy_score(all_labels, all_preds))
print(classification_report(all_labels, all_preds,
target_names=['NEGATIVE', 'POSITIVE']))Матрица ошибок для BERT
Матрица ошибок показывает распределение прогнозов относительно истинных меток. При анализе тональности ячейки вне главной диагонали показывают ложноположительные результаты (предсказан POSITIVE, но на самом деле NEGATIVE) и ложноотрицательные результаты (предсказан NEGATIVE, но на самом деле POSITIVE). Визуализация с помощью тепловой карты seaborn выявляет систематические ошибки: не предсказывает ли модель один класс слишком часто? Не классифицируются ли неправильно одни и те же типы отзывов?
from sklearn.metrics import confusion_matrix
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
cm = confusion_matrix(all_labels, all_preds)
plt.figure(figsize=(6, 5))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues',
xticklabels=['NEG', 'POS'],
yticklabels=['NEG', 'POS'])
plt.ylabel('True Label')
plt.xlabel('Predicted Label')
plt.title('BERT Confusion Matrix on IMDB Test Set')
plt.tight_layout()
plt.savefig('bert_confusion.png')Пакетное получение прогнозов для повышения эффективности
Получение прогноза для одного примера за раз выполняется медленно. Обрабатывайте примеры пакетами, чтобы использовать преимущества параллельной работы GPU. Установите фиксированный batch_size в своём DataLoader, передавайте модели целые пакеты и собирайте результаты. На GPU пакетное получение прогнозов может быть в 50 раз быстрее обработки отдельных примеров. Используйте torch.no_grad() и перемещайте тензоры на нужное устройство для оптимальной производительности.
import torch
from torch.utils.data import DataLoader, TensorDataset
from transformers import BertTokenizer
def batch_predict(texts, model, tokenizer, device, batch_size=32):
model.eval()
all_predictions = []
for i in range(0, len(texts), batch_size):
batch_texts = texts[i:i+batch_size]
enc = tokenizer(batch_texts, truncation=True, padding=True,
max_length=256, return_tensors='pt')
enc = {k: v.to(device) for k, v in enc.items()}
with torch.no_grad():
logits = model(**enc).logits
preds = torch.argmax(logits, dim=1).cpu().tolist()
all_predictions.extend(preds)
return all_predictionsSigmoid для многометочной классификации
Если текст может одновременно относиться к нескольким классам (например, отзыв может быть одновременно «смешным» и «эмоциональным»), используйте sigmoid вместо softmax. Sigmoid применяется независимо к логиту каждого класса и выдаёт для каждого класса вероятность от 0 до 1, при этом сумма вероятностей не обязана быть равна 1. Примените порог (обычно 0,5) к каждой вероятности, чтобы получить двоичное предсказание для каждого класса. Установите problem_type='multi_label_classification' в BertForSequenceClassification.
import torch
import torch.nn.functional as F
# 5 classes, multi-label: a text can have multiple labels
logits = torch.tensor([[1.2, -0.5, 2.1, -1.8, 0.3]])
probs = torch.sigmoid(logits)
print('Per-class probabilities:', probs)
threshold = 0.5
predicted_labels = (probs > threshold).int()
print('Predicted labels (multi-hot):', predicted_labels)
# e.g., [1, 0, 1, 0, 0] -- classes 0 and 2 are predictedОбработка неправильно классифицированных примеров
Всегда проверяйте неправильно классифицированные примеры вручную. Выведите примеры, в которых модель предсказала 0, а истинная метка равна 1 (ложноотрицательные результаты), и наоборот. К распространённым закономерностям относятся сарказм («О, какой великолепный фильм-катастрофа»), сдвиг предметной области (устаревшая лексика) и длинные отзывы, когда модель видит только первые 256 токенов. Понимание причин ошибок помогает планировать разработку признаков или сбор данных.
import numpy as np
all_preds = np.array(all_preds)
all_labels = np.array(all_labels)
texts = test_dataset['text'] if hasattr(test_dataset, '__getitem__') else []
false_negatives = np.where((all_preds == 0) & (all_labels == 1))[0]
false_positives = np.where((all_preds == 1) & (all_labels == 0))[0]
print('False negatives (predicted NEG, true POS):')
for idx in false_negatives[:3]:
print(' -', str(texts[idx])[:120] if texts else idx)
print('False positives (predicted POS, true NEG):')
for idx in false_positives[:3]:
print(' -', str(texts[idx])[:120] if texts else idx)Экспорт прогнозов в CSV
В рабочих или конкурсных системах часто требуется экспортировать прогнозы в CSV-файл. Используйте pandas, чтобы создать DataFrame с исходным текстом, истинной меткой, предсказанной меткой и оценкой уверенности. Такой формат удобно передавать заинтересованным сторонам, проверять и использовать как входные данные для последующих конвейеров формирования отчётов. Всегда включайте в метаданные версию модели и время получения прогноза.
import pandas as pd
import torch.nn.functional as F
import torch
results = []
id2label = {0: 'NEGATIVE', 1: 'POSITIVE'}
model.eval()
for i, text in enumerate(sample_texts):
inputs = tokenizer(text, return_tensors='pt',
truncation=True, max_length=256)
with torch.no_grad():
logits = model(**inputs).logits
probs = F.softmax(logits, dim=1).squeeze()
pred = torch.argmax(probs).item()
results.append({
'text': text[:80],
'true_label': id2label[sample_labels[i]],
'predicted_label': id2label[pred],
'confidence': round(probs[pred].item(), 4)
})
df = pd.DataFrame(results)
df.to_csv('bert_predictions.csv', index=False)
print(df.head())Быстрая проверка
Проверьте своё понимание концепций машинного обучения на Python из этого урока.
Итоги урока
В этом уроке Вы узнали, что логиты — это необработанные оценки модели, которые преобразуются в вероятности с помощью softmax для многоклассовых задач или sigmoid для многометочных задач, argmax возвращает индекс предсказанного класса, который с помощью словаря id2label преобразуется в понятную человеку метку, а classification_report и матрица ошибок вместе дают полную картину качества модели, дополняя точность. Далее мы рассмотрим MLflow для отслеживания экспериментов, параметров и метрик в нескольких запусках обучения.
Изучай Python с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 30
- Уроки
- 120
Часто задаваемые вопросы
Урок «Оценка и вывод: от логитов к предсказанным меткам» бесплатный?
Да — полный текст урока «Оценка и вывод: от логитов к предсказанным меткам» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Machine Learning Academy, подпишись на CoddyKit PRO. Курс Machine Learning Academy содержит 4 уроков всего.
Чему я научусь в уроке «Оценка и вывод: от логитов к предсказанным меткам»?
Вы вычислите softmax для логитов, преобразуете предсказанные индексы классов в метки и оцените дообученную модель по точности и F1 на отложенном тестовом наборе. Ты практикуешь Machine Learning Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Machine Learning Academy?
Предыдущий опыт не требуется. Machine Learning Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Оценка и вывод: от логитов к предсказанным меткам»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Machine Learning Academy?
Да. Каждый урок Machine Learning Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Архитектура Transformer: внимание, токены и контекст
- Токенизаторы Hugging Face: кодирование текста для BERT
- Дообучение BertForSequenceClassification
- Оценка и вывод: от логитов к предсказанным меткам