← Назад к вопросам
Что такое N-gram?
2.3 Middle🔥 221 комментариев
#NLP и обработка текста#Машинное обучение
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
N-gram: основы обработки текста
N-gram это последовательность из N элементов из текста. Это один из фундаментальных методов NLP для представления текста и анализа языка.
Определение
N-gram — это последовательность N consecutives элементов:
- 1-gram (unigram): одно слово или символ
- 2-gram (bigram): два consecutives слова/символа
- 3-gram (trigram): три consecutives слова/символа
- N-gram: N consecutives элементов
Пример с текстом
Текст: "The quick brown fox"
1-grams: ["the", "quick", "brown", "fox"]
2-grams: [("the", "quick"), ("quick", "brown"), ("brown", "fox")]
или по словам: ["the quick", "quick brown", "brown fox"]
3-grams: [("the", "quick", "brown"), ("quick", "brown", "fox")]
или: ["the quick brown", "quick brown fox"]
На символьном уровне
Текст: "hello"
1-grams: ["h", "e", "l", "l", "o"]
2-grams: [("h", "e"), ("e", "l"), ("l", "l"), ("l", "o")]
или: ["he", "el", "ll", "lo"]
3-grams: [("h", "e", "l"), ("e", "l", "l"), ("l", "l", "o")]
или: ["hel", "ell", "llo"]
Python реализация
from collections import Counter
import nltk
# Способ 1: Вручную (слова)
text = "the quick brown fox jumps"
words = text.split()
# 1-grams
unigrams = words
# ['the', 'quick', 'brown', 'fox', 'jumps']
# 2-grams
bigrams = [tuple(words[i:i+2]) for i in range(len(words)-1)]
# [('the', 'quick'), ('quick', 'brown'), ('brown', 'fox'), ('fox', 'jumps')]
# 3-grams
trigrams = [tuple(words[i:i+3]) for i in range(len(words)-2)]
# [('the', 'quick', 'brown'), ('quick', 'brown', 'fox'), ('brown', 'fox', 'jumps')]
# Способ 2: NLTK (встроенные функции)
from nltk.util import ngrams
text_tokens = "the quick brown fox".split()
bigrams = list(ngrams(text_tokens, 2))
trigrams = list(ngrams(text_tokens, 3))
fourgrams = list(ngrams(text_tokens, 4))
# Способ 3: sklearn (векторизация)
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer(
analyzer='word', # или 'char' для символов
ngram_range=(1, 2), # unigrams + bigrams
lowercase=True
)
X = vectorizer.fit_transform(["the quick brown fox"])
print(vectorizer.get_feature_names_out())
# ['brown' 'fox' 'quick' 'the' 'the quick' 'quick brown' 'brown fox']
Счётчик N-grams
from collections import Counter
text = "the cat sat on the mat"
words = text.split()
# Bigrams с частотностью
bigrams = [' '.join(words[i:i+2]) for i in range(len(words)-1)]
bigram_counts = Counter(bigrams)
for bigram, count in bigram_counts.most_common(3):
print(f"{bigram}: {count}")
# Результат:
# the cat: 1
# cat sat: 1
# sat on: 1
# on the: 1
# the mat: 1
Практические применения
1. Text Classification
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.svm import SVC
# Тексты
docs = [
"I love this movie",
"This movie is great",
"I hate this movie",
"Terrible and boring"
]
labels = [1, 1, 0, 0] # 1=positive, 0=negative
# N-grams как features
vectorizer = TfidfVectorizer(ngram_range=(1, 2))
X = vectorizer.fit_transform(docs)
# Classifier
classifier = SVC(kernel='linear')
classifier.fit(X, labels)
# Predict
new_text = "This movie is amazing"
X_new = vectorizer.transform([new_text])
prediction = classifier.predict(X_new)
print(prediction) # [1] (positive)
2. Language Modeling (Prediction)
# Предсказание следующего слова на основе N-grams
from collections import defaultdict, Counter
def build_ngram_model(text, n=2):
"""Построить N-gram модель для предсказания"""
words = text.split()
model = defaultdict(Counter)
for i in range(len(words) - n):
context = tuple(words[i:i+n-1]) # контекст (n-1 слов)
next_word = words[i+n-1] # следующее слово
model[context][next_word] += 1
return model
text = "the cat sat on the mat and the cat slept"
model = build_ngram_model(text, n=2)
# Предсказать следующее слово после "the"
context = ("the",)
if context in model:
predictions = model[context].most_common(3)
print(predictions) # [('cat', 2), ('mat', 1)]
3. Spell Checking и Autocomplete
# Контекст помогает исправить опечатку
# "I went to the scool" → должно быть "school"
# С bigrams:
# Вероятность "the scool" низкая
# Вероятность "the school" высокая
# Для autocomplete:
# "I am going to" → predict next word
# bigrams: ["to the", "to visit", "to be", ...]
# Выбираем наиболее вероятное
4. Text Similarity
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.feature_extraction.text import CountVectorizer
# Два текста
text1 = "I love machine learning"
text2 = "I enjoy deep learning"
text3 = "Dogs are animals"
# N-gram vectorization
vectorizer = CountVectorizer(analyzer='char', ngram_range=(2, 3))
X = vectorizer.fit_transform([text1, text2, text3])
# Similarity
similarity_1_2 = cosine_similarity(X[0], X[1])[0][0]
similarity_1_3 = cosine_similarity(X[0], X[2])[0][0]
print(f"Text 1 vs 2: {similarity_1_2:.2f}") # ~0.8
print(f"Text 1 vs 3: {similarity_1_3:.2f}") # ~0.1
Character N-grams vs Word N-grams
WORD N-GRAMS (более семантичные):
- Лучше для понимания смысла
- Менше данных (меньше возможных n-grams)
- Требуют tokenization
- Подходят для: classification, similarity
CHARACTER N-GRAMS (более структурные):
- Лучше для морфологии
- Больше данных (много символов)
- Не требуют tokenization
- Подходят для: spell checking, language detection, typos
Проблемы с N-grams
# 1. Sparse features (разреженные признаки)
# Много нулей в матрице признаков
vectorizer = CountVectorizer(ngram_range=(1, 3))
X = vectorizer.fit_transform(docs)
print(X.density) # ~ 0.05 (95% нулей)
# 2. Curse of dimensionality
# Много признаков → нужно больше данных
# Для 3-grams на 100k словах может быть миллионы признаков
# 3. Потеря контекста
# N-grams игнорируют порядок и дальний контекст
# "John loves Mary" vs "Mary loves John" — одинаковые 1-grams
# 4. Не scalable
# Для больших текстов нужно хранить огромные матрицы
Modern Alternative: Word Embeddings
# Вместо N-grams используют embeddings (Word2Vec, GloVe, BERT)
from gensim.models import Word2Vec
text = [["I", "love", "machine", "learning"],
["I", "enjoy", "deep", "learning"]]
# Word2Vec (вместо n-grams)
model = Word2Vec(text, vector_size=100, window=2, min_count=1)
# Получить вектор слова
vector = model.wv['learning']
print(vector.shape) # (100,)
# Similarity
similarity = model.wv.similarity('learning', 'machine')
print(similarity) # ~0.8
Когда использовать N-grams
✓ Text classification (простые задачи)
✓ Language detection (какой язык)
✓ Spell checking (опечатки)
✓ Plagiarism detection (копирование)
✓ Autocomplete (предсказание следующего слова)
✓ Когда не нужен глубокий семантический анализ
✗ Когда нужен глубокий смысл (используй BERT, GPT)
✗ Когда текст очень длинный (слишком много n-grams)
✗ Multilingual (n-grams зависят от языка)
Вывод
N-grams это:
- Простой способ представить текст для ML моделей
- Последовательность N элементов (слов или символов)
- Используется в классификации, языковом моделировании, similarity
- Быстрые и интерпретируемые, но не capture семантику
- Modern alternative: embeddings (Word2Vec, BERT)
Для интервью помни:
- N-gram = последовательность N слов/символов
- Используется для text features
- Pros: быстро, simple
- Cons: sparse, не понимает семантику