# выполнять в Google Colab
# 1. Установка библиотек
!pip install bertviz transformers matplotlib -q
# 2. Импорт библиотек
import torch
import matplotlib.pyplot as plt
from transformers import BertTokenizer, BertModel
from bertviz import head_view
import warnings
warnings.filterwarnings('ignore')

# 3. Загрузка модели
print("Загрузка модели...")
model_name = "bert-base-uncased"
tokenizer = BertTokenizer.from_pretrained(model_name)
model = BertModel.from_pretrained(model_name, output_attentions=True)
print("Модель загружена!\n")
# 4. Подготовка предложений
text_clean = "The cat approached the dog, and it growled"
text_noisy = "The cat approached the dog. It... growled, approached cat the"
print("="*60)
print("ЧИСТЫЙ ТЕКСТ: The cat approached the dog, and IT growled")
print("ШУМНЫЙ ТЕКСТ: The cat approached the dog. IT... growled, approached cat the")
print("="*60)
print("\n👉 Сейчас откроются ДВЕ визуализации от bertviz")
print("👉 Сравните их и увидите разницу!\n")
# 5. Функция для визуализации
def show_bertviz(text, number):
    print(f"\n--- Визуализация {number} ---")
    inputs = tokenizer(text, return_tensors='pt')
    with torch.no_grad():
        outputs = model(**inputs)
    attention = outputs.attentions
    tokens = tokenizer.convert_ids_to_tokens(inputs['input_ids'][0])
    print(f"Токены: {tokens}")
    print("🔍 Найдите слово 'it' и посмотрите на его связи")
    # Показываем визуализацию bertviz
    head_view(attention, tokens)
# 6. Показываем первую визуализацию
show_bertviz(text_clean, "1 (ЧИСТЫЙ ТЕКСТ)")
input("\n⏸️ Нажмите Enter для второй визуализации...")
# 7. Показываем вторую визуализацию
show_bertviz(text_noisy, "2 (ШУМНЫЙ ТЕКСТ)")
# 8. Создаем простое пояснение с графиком
print("\n" + "="*60)
print("📊 СРАВНЕНИЕ РЕЗУЛЬТАТОВ")
print("="*60)
# Получаем числовые значения для графика
def get_numbers(text):
    inputs = tokenizer(text, return_tensors='pt')
    tokens = tokenizer.convert_ids_to_tokens(inputs['input_ids'][0])
    with torch.no_grad():
        outputs = model(**inputs)
        # Берем средний слой для наглядности
    attention = outputs.attentions[5][0, 8].numpy()
    it_idx = None
    dog_idx = None
    for i, token in enumerate(tokens):
        if token == 'it':
            it_idx = i
        elif token == 'dog':
            dog_idx = i
    if it_idx is not None and dog_idx is not None:
        return attention[it_idx][dog_idx]
    return 0
# Собираем данные
clean_value = get_numbers(text_clean)
noisy_value = get_numbers(text_noisy)
# Рисуем простой график
plt.figure(figsize=(8, 5))
bars = plt.bar(['ЧИСТЫЙ ТЕКСТ', 'ШУМНЫЙ ТЕКСТ'], [clean_value,
noisy_value],
color=['green', 'red'])
plt.ylabel('Сила связи "it" → "dog"', fontsize=12)
plt.title('Сравнение понимания моделью слова "it"', fontsize=14)
plt.ylim(0, 0.6)
# Добавляем значения на столбцы
for bar in bars:
    height = bar.get_height()
    plt.text(bar.get_x() + bar.get_width()/2., height,
    f'{height:.3f}', ha='center', va='bottom', fontsize=12)
plt.axhline(y=0.3, color='blue', linestyle='--', alpha=0.7, label='Порог понимания')
plt.legend()
plt.grid(axis='y', alpha=0.3)
plt.show()
# 9. Итоговый вывод
print("\n" + "="*60)
print("🔍 ЧТО ВЫ УВИДЕЛИ В BERTVIZ:")
print("="*60)
print("""
В ПЕРВОЙ визуализации (чистый текст):
• Найдите слово 'it' (в районе 8-9 позиции)
• От него идут яркие линии
• Одна из самых ярких линий ведет к слову 'dog'
✅ Модель ПОНЯЛА, что 'it' = собака
ВО ВТОРОЙ визуализации (шумный текст):
• Снова найдите слово 'it'
• Линии от него стали бледнее и размазаны
• Связь с 'dog' почти исчезла или очень слабая
❌ Модель ЗАПУТАЛАСЬ
📊 ГРАФИК ПОКАЗЫВАЕТ ТО ЖЕ САМОЕ:
Чистый текст: связь = {:.3f} (ВЫСОКАЯ)
Шумный текст: связь = {:.3f} (НИЗКАЯ)
ВЫВОД: Шум в тексте ломает способность модели понимать смысл!
""".format(clean_value, noisy_value))
