"Бородино" Лермонтова и "Ледовое побоище" Симонова две классические военно-патриотические поэмы, были созданы по мотивам крупных военных событий, но по-разному описывают ратный подвиг русского воина.  Мне стало интересно сравнить два произведения объективно, использовать для анализа предобученные эмбеддинги и визуализировать результат.

Для работы я использовал библиотеку transformers для загрузки и применения предобученной модели LaBSE. Библиотека torch понадобилась мне для работы с нейросетевой моделью. scikit-learn я использовал для снижения размерности с помощью PCA и t-SNE.

Эмбеддинг это числовой вектор (набор чисел), в который преобразуется какой‑либо объект, например слово или предложение. Этот вектор можно представить как точку в многомерном пространстве - чем больше координат у вектора, тем выше размерность пространства.

Эмбеддинги разумно применять, если нужно проверить математически, "близки" похожие по смыслу объекты или "далеки".

Эмбеддинги представляют в виде векторов и чтобы понять, насколько похожи два эмбеддинга, то есть вектора, используют "косинусное расстояние". Для определения близости векторов используют именно косинусное расстояние, потому что эта метрика фокусируется на различии направлений векторов, игнорируя их д��ины. Косинусное расстояние показывает угол между двумя векторами. Косинус угла близок к единице, если векторы направлены почти одинаково, и близок к нулю, если они сильно отличаются друг от друга. Таким образом, эмбеддинги позволяют представить объекты в удобной форме, а косинусное расстояние помогает определить степень их близости или различия.

LaBSE (Language-agnostic BERT Sentence Embedding) — это нейросетевая модель, предложенная компанией Google в 2020 году и обученная на 100 языках, включая русский. Модель хорошо справляется с тем, чтобы сближать друг с другом эмбеддинги предложений с одинаковым смыслом на разных языках, и генерирует векторы, отражающие семантическое содержание целых предложений.

Модель LaBSE удобна тем, что не требует дообучения, работает "из коробки" и устойчива к вариативности поэтического языка.

Я загрузил тексты обеих поэм из файлов. Затем разбил каждую поэму на строфы - блоки, разделённые пустыми строками.

Затем я начал генерировать эмбеддинги и вызывал модель LaBSE для каждой строфы.

model_name = "sentence-transformers/LaBSE"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)
device = "cuda" if torch.cuda.is_available() else "cpu"
model.to(device)
def get_embeddings(sentences):
    encoded = tokenizer(
        sentences,
        padding=True,
        truncation=True,
        max_length=512,
        return_tensors="pt"
    ).to(device)
    with torch.no_grad():
        outputs = model(**encoded)
        embeddings = outputs.last_hidden_state.mean(dim=1).cpu().numpy()
        return embeddings 

У меня получился вектор из 768 float-чисел на строфу.

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

Снижать размерность можно двумя методами.

Преобразование главных компонент (PCA - Principal Component Analysis) позволяет находить основные направления изменчивости в многомерных данных и снижать их размерность без существенной потери информации. В основе метода лежит идея нахождения ортогональных направлений (тех самых "главных компонент"), вдоль которых данные имеют наибольшую дисперсию, то есть разброс вокруг их среднего значения.

t-SNE это t-распределённое стохастическое соседнее встраивание(t-distributed Stochastic Neighbor Embedding). Этот метод снижения размерности позволяет сохранить локальные структуры данных и обнаруживать нелинейные зависимости. Основная идея t-SNE заключается в том, чтобы преобразовать исходные данные таким образом, чтобы схожие объекты в исходном пространстве сохраняли свою схожесть и в новом, сниженном пространстве. В алгоритме t-SNE применяют параметр перплексии. Перплексия показывает плотность точек относительно определённой точки.

В моем случае для снижения размерности эмбеддинов двух поэм я сначала с помощью PCA снизил до размерности 10–50 компонент, чтобы убрать шум. А затем с помощью t-SNE с перплексией 10–30 еще снизил размерность для визуализации.

pca = PCA(n_components=50 if X.shape[0] > 50 else min(10, X.shape[1]), random_state=42)
X_pca = pca.fit_transform(X)
tsne = TSNE(n_components=2, perplexity=min(30, X_pca.shape[0] - 1), random_state=42, init='pca')
X_tsne = tsne.fit_transform(X_pca)

Теперь после снижения размерности я смог вычислить косинусное сходство между средними векторами обеих поэм.

from sklearn.metrics.pairwise import cosine_similarity

mean_sim = emb_sim.mean(axis=0).reshape(1, -1)
mean_ler = emb_ler.mean(axis=0).reshape(1, -1)
similarity = cosine_similarity(mean_sim, mean_ler)[0][0]

Что у меня получилось.

Косинусное сходство между поэмами (по средним векторам): 0.959

Значение больше 0.7 считается высоким семантическим сходством.

Сравнение поэм "Бородино" Лермонтова и "Ледовое побоище" Симонова по семантическим эмбеддингам
Сравнение поэм "Бородино" Лермонтова и "Ледовое побоище" Симонова по семантическим эмбеддингам

На графике два облака точек. Синие это строфы Симонова, красные строфы Лермонтова.

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

Мне удалось показать, что модель LaBSE работает даже для поэтических текстов.