цепи маркова и трансформеры..

 такую программу сделать можно — она будет одновременно применять и цепи Маркова, и трансформер (или упрощённый self-attention), используя как слова, так и их корни (леммы) для анализа и генерации текста. Вот как это можно организовать:

---

## Общая идея

1. Предобработка текста:
   - Считать текст из файла `.txt`.
   - Токенизировать текст на слова.
   - Провести лемматизацию (получить корни слов) с помощью библиотек, например, для русского — pymorphy2, для английского — spaCy.
   - Получить две последовательности: слов и их корней.

2. Модель цепей Маркова:
   - Построить модель цепей Маркова на основе последовательности слов и/или корней.
   - Можно сделать отдельные цепи для слов и для корней, либо объединить их (например, пары (слово, корень)).

3. Модель трансформера:
   - Создать упрощённый трансформер, который принимает на вход эмбеддинги слов и корней.
   - Для этого можно объединить эмбеддинги слова и его корня (например, конкатенацией или суммой).
   - Обучить трансформер предсказывать следующий токен (слово или корень).

4. Комбинация результатов:
   - При генерации текста можно комбинировать вероятности из цепей Маркова и трансформера.
   - Например, усреднить вероятности или использовать веса, чтобы получить итоговое распределение для выбора следующего слова.



  **




```python
import pymorphy2
from collections import defaultdict, Counter
import numpy as np

#  Предобработка
morph = pymorphy2.MorphAnalyzer()

def tokenize(text):
    return text.lower().split()  # простой токенизатор, лучше использовать nltk/spacy

def lemmatize(words):
    return [morph.parse(w)[0].normal_form for w in words]

#  Цепи Маркова
class MarkovChain:
    def __init__(self):
        self.transitions = defaultdict(Counter)

    def train(self, tokens):
        for i in range(len(tokens) - 1):
            self.transitions[tokens[i]][tokens[i+1]] += 1

    def next_word_probs(self, current):
        total = sum(self.transitions[current].values())
        return {word: count/total for word, count in self.transitions[current].items()}

#  Упрощённый трансформер (просто эмбеддинги и матричные операции)
class SimpleTransformer:
    def __init__(self, vocab):
        self.vocab = vocab
        self.vocab_size = len(vocab)
        self.embed_dim = 64
        self.embeddings = np.random.randn(self.vocab_size, self.embed_dim) * 0.01
        # Здесь можно добавить self-attention и другие слои

    def embed(self, token):
        idx = self.vocab.get(token, None)
        if idx is None:
            idx = self.vocab.get('<unk>')
        return self.embeddings[idx]

    def predict_next(self, context_tokens):
        #  усредняем эмбеддинги контекста и считаем скалярные произведения с эмбеддингами всех слов
        context_embeds = np.mean([self.embed(t) for t in context_tokens], axis=0)
        scores = self.embeddings @ context_embeds
        probs = np.exp(scores) / np.sum(np.exp(scores))
        return {word: probs[idx] for word, idx in self.vocab.items()}

#  Комбинирование
def combine_probs(probs1, probs2, alpha=0.5):
    combined = {}
    keys = set(probs1.keys()) | set(probs2.keys())
    for k in keys:
        p1 = probs1.get(k, 0)
        p2 = probs2.get(k, 0)
        combined[k] = alpha * p1 + (1 - alpha) * p2
    # Нормализуем
    s = sum(combined.values())
    for k in combined:
        combined[k] /= s
    return combined

# --- Использование

text = open('input.txt', encoding='utf-8').read()
words = tokenize(text)
lemmas = lemmatize(words)

# Создаём словарь для трансформера (слова + корни)
unique_tokens = list(set(words + lemmas + ['<unk>']))
vocab = {w: i for i, w in enumerate(unique_tokens)}

# Обучаем цепь Маркова на словах
markov_words = MarkovChain()
markov_words.train(words)

# Обучаем цепь Маркова на корнях
markov_lemmas = MarkovChain()
markov_lemmas.train(lemmas)

# Инициализируем трансформер
transformer = SimpleTransformer(vocab)

# Генерация следующего слова на основе текущего контекста
context = words[-3:]  # последние 3 слова
probs_markov = markov_words.next_word_probs(context[-1])
probs_transformer = transformer.predict_next(context)

# Комбинируем вероятности
final_probs = combine_probs(probs_markov, probs_transformer, alpha=0.6)

# Выбираем слово с максимальной вероятностью
next_word = max(final_probs, key=final_probs.get)
print("Следующее слово:", next_word)
```



# Что можно улучшить и расширить

- Использовать полноценный токенизатор и лемматизатор
(например, spaCy для английского, pymorphy2 для русского).
- Реализовать полноценный трансформер с self-attention
(например, на PyTorch или TensorFlow).

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

- При генерации применять сэмплирование (топ-k, топ-p), чтобы получать разнообразный текст.




  **



import random

def generate_text(length, start_word, markov_chain_words, transformer_model, vocab, alpha=0.5):
    generated = [start_word]
    for _ in range(length - 1):
        current_word = generated[-1]

        # Получаем вероятности от цепи Маркова
        probs_markov = markov_chain_words.next_word_probs(current_word)
        if not probs_markov:
            # Если нет переходов, случайно выбираем слово из словаря
            probs_markov = {w: 1/len(vocab) for w in vocab}

        # Получаем вероятности от трансформера по контексту последних 3 слов
        context = generated[-3:] if len(generated) >= 3 else generated
        probs_transformer = transformer_model.predict_next(context)

        # Комбинируем вероятности
        combined_probs = combine_probs(probs_markov, probs_transformer, alpha=alpha)

        # Выбираем следующее слово случайно по распределению
        words = list(combined_probs.keys())
        probabilities = list(combined_probs.values())
        next_word = random.choices(words, probabilities)[0]

        generated.append(next_word)

    return generated

# Пример использования:
start = words[0]  # или любой начальный токен
generated_words = generate_text(200, start, markov_words, transformer, vocab, alpha=0.6)
print(' '.join(generated_words))


Рецензии