Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Плюсы и минусы TF-IDF
TF-IDF (Term Frequency-Inverse Document Frequency) — это классический алгоритм для преобразования текста в векторное представление. Несмотря на возраст (введён в 1970-е), он остаётся полезным инструментом в NLP и Information Retrieval.
Как работает TF-IDF
TF (Term Frequency) — как часто слово встречается в документе:
TF(t, d) = количество слова t в документе d / общее количество слов в d
IDF (Inverse Document Frequency) — как редкое слово во всём корпусе:
IDF(t) = log(общее количество документов / количество документов с словом t)
TF-IDF:
TF-IDF(t, d) = TF(t, d) × IDF(t)
Пример
from sklearn.feature_extraction.text import TfidfVectorizer
# Документы
docs = [
"машинное обучение — это отрасль ИИ",
"глубокое обучение использует нейросети",
"нейросети лежат в основе глубокого обучения"
]
vectorizer = TfidfVectorizer()
tf_idf_matrix = vectorizer.fit_transform(docs)
print(tf_idf_matrix.toarray())
print(vectorizer.get_feature_names_out())
# Output: матрица (3 документа, N уникальных слов)
# Результат: каждый документ представлен вектором
# [0.45, 0.23, 0.12, ...] # Веса слов
Плюсы TF-IDF
1. Простота и интерпретируемость
# Очень просто понять, что происходит
# Высокий вес = частое в документе и редкое в корпусе
# Низкий вес = частое во всех документах (stop words)
vectorizer = TfidfVectorizer()
tf_idf = vectorizer.fit_transform(docs)
# Какие слова важны?
feature_names = vectorizer.get_feature_names_out()
for i, word in enumerate(feature_names):
print(f"{word}: {tf_idf.max(axis=0).toarray()[0][i]:.3f}")
2. Скорость (очень быстро)
import time
docs = [open(f).read() for f in glob.glob("docs/*.txt")] # 10000 документов
start = time.time()
vectorizer = TfidfVectorizer(max_features=1000)
tf_idf = vectorizer.fit_transform(docs)
print(f"Время: {time.time() - start:.2f} сек") # < 0.5 сек
# Очень быстро даже на больших текстах
3. Автоматически удаляет стоп-слова
vectorizer = TfidfVectorizer(
stop_words='russian', # Удаляет "и", "в", "на", и т.п.
max_df=0.8, # Удаляет слова, которые в 80% документов
min_df=2 # Удаляет слова, которые в < 2 документах
)
# Результат: только значимые слова
tf_idf = vectorizer.fit_transform(docs)
4. Хорошо работает с поиском документов (Information Retrieval)
# Найти похожие документы
from sklearn.metrics.pairwise import cosine_similarity
tf_idf_matrix = vectorizer.fit_transform(docs)
similarity = cosine_similarity(tf_idf_matrix)
# Найти документы, похожие на документ 0
top_similar = similarity[0].argsort()[::-1][1:6]
print(f"Документы, похожие на 0: {top_similar}")
5. Работает с редкими словами лучше, чем One-Hot Encoding
# One-Hot Encoding:
# "кот" → [1, 0, 0, 0, ...]
# "собака" → [0, 1, 0, 0, ...]
# Нет информации о популярности слова
# TF-IDF:
# "кот" → [0.8, 0, 0, 0, ...] # 0.8 = редкое, но частое в документе
# "собака" → [0, 0.7, 0, 0, ...]
# Учитывает редкость слова
6. Работает на мешке слов (bag-of-words), не требует порядка
# Эти два документа идентичны в TF-IDF
doc1 = "кот сидит на окне"
doc2 = "на окне сидит кот"
vectorizer.fit_transform([doc1, doc2])
# Вектор одинаковый (порядок слов не важен)
# Иногда это хорошо (простота), иногда плохо (теряется контекст)
Минусы TF-IDF
1. Теряет информацию о порядке слов (word order)
# "кот укусил собаку" и "собака укусила кота"
# Имеют очень разные смыслы
doc1 = "кот укусил собаку"
doc2 = "собака укусила кота"
vectorizer = TfidfVectorizer()
vectors = vectorizer.fit_transform([doc1, doc2])
# Порядок слов не учитывается, вектор одинаков!
print(vectors[0].todense() == vectors[1].todense())
# Output: True (вектор с одинаковыми словами)
2. Не учитывает семантику (значение слов)
# Синонимы имеют разные вектора
vectorizer = TfidfVectorizer()
docs = ["мне нравится машинное обучение",
"я обожаю ML", # ML = Machine Learning
"я ненавижу спорт"]
vectors = vectorizer.fit_transform(docs)
# Документ 0 и 1 семантически похожи
# Но вектора совсем разные (разные слова)
from sklearn.metrics.pairwise import cosine_similarity
sim = cosine_similarity(vectors[0], vectors[1])[0][0]
print(f"Сходство: {sim:.3f}") # Низко!
3. Проблема разреженности (sparsity)
# Для большого словаря матрица очень разреженная
vectorizer = TfidfVectorizer(max_features=10000)
tf_idf = vectorizer.fit_transform(docs) # 1000 документов
print(tf_idf.shape) # (1000, 10000)
print(tf_idf.nnz / (1000 * 10000)) # ~0.001 (99.9% нули!)
# Это замораживает память и замедляет вычисления
# Нужно использовать sparse матрицы
4. Чувствителен к опечаткам и морфологии
# "обучение", "обучается", "обучать" — разные слова
vectorizer = TfidfVectorizer()
docs = ["машинное обучение",
"модель обучается",
"я учу модель"] # "учу" ≠ "обучение"
vectors = vectorizer.fit_transform(docs)
# Документы 0 и 1 немного похожи
# Но для документа 2: нет совпадений!
from sklearn.metrics.pairwise import cosine_similarity
print(cosine_similarity(vectors[0], vectors[2])) # [0.0]
# Решение: лемматизация
import pymorphy2
morph = pymorphy2.MorphAnalyzer()
lemmas = [morph.parse(word)[0].normal_form for word in "учу обучение".split()]
# ["учить", "обучение"] → одно из них нормализовано
5. Не работает с новыми словами (OOV, Out-of-Vocabulary)
# Если слово не было в training данных, оно игнорируется
vectorizer = TfidfVectorizer()
vectorizer.fit(["кот", "собака", "птица"]) # Обучили на этих словах
# Новые слова не будут учитываться
new_doc = "рыба это животное" # "рыба" не видела раньше
vector = vectorizer.transform([new_doc])
print(vector.toarray()) # Только "животное" будет учтено
6. Плохо работает с коротким текстом
# Для твитов, заголовков, коротких описаний
docs = [
"AI это будущее",
"Машинное обучение",
"Нейросети"
]
vectorizer = TfidfVectorizer()
vectors = vectorizer.fit_transform(docs)
# Очень разреженные вектора (много нулей)
print(vectors.toarray())
# [[0.5, 0, 0, 0], # 1 слово
# [0, 0.6, 0.4, 0], # 2 слова
# [0, 0, 0, 1.0]] # 1 слово
7. IDF игнорирует документ-специфичные слова
# Если слово часто встречается в одном конкретном документе
# но редко в других, TF-IDF может не отметить это
# Пример: документ про "пингвинов" в корпусе про животных
# "пингвин" встречается в 10 документах из 1000
# IDF = log(1000/10) = 2.0 (не очень высокий)
# Хотя для поиска документов про пингвинов это важное слово
Когда использовать TF-IDF
✅ Используйте TF-IDF, если:
- Нужен быстрый baseline для text classification
- Information Retrieval (поиск документов)
- Document similarity
- Текст на английском (нет морфологии)
- Бюджет памяти ограничен
- Нужна интерпретируемость (какие слова важны?)
❌ Не используйте TF-IDF, если:
- Нужна точность в классификации
- Нужна семантика (синонимы, контекст)
- Работаете с русским или другим флективным языком
- Много коротких текстов (твиты, заголовки)
- Важен порядок слов (sentiment analysis, причинно-следственные связи)
Современная альтернатива: Word Embeddings
from gensim.models import Word2Vec
import numpy as np
# Word2Vec (более современный подход)
sentences = [["кот", "сидит", "на", "окне"],
["собака", "бегает", "в", "парке"]]
model = Word2Vec(sentences, min_count=1, vector_size=100)
# Векторы учитывают семантику
print(model.similarity("кот", "собака")) # ~0.5 (похожи)
print(model.similarity("кот", "машина")) # ~0.1 (не похожи)
# Но требуют больше данных и вычислений
Практический пример
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
# Классификация категорий новостей
news = [
"Нов ый закон о налогах вступил в силу",
"Стоимость нефти выросла на 5%",
"Футбольная команда выиграла чемпионат"
]
vectorizer = TfidfVectorizer()
tf_idf = vectorizer.fit_transform(news)
# Найти новость, похожую на первую
query = "Изменение налоговой политики"
query_vector = vectorizer.transform([query])
similarity = cosine_similarity(query_vector, tf_idf)[0]
most_similar_idx = similarity.argsort()[::-1][0]
print(f"Похожая новость: {news[most_similar_idx]}")
# Output: "Новый закон о налогах вступил в силу"
Итого: TF-IDF — это простой, быстрый и интерпретируемый метод для преобразования текста в вектора. Плюсы: скорость, простота, хорошо для Information Retrieval. Минусы: теряет порядок слов, семантику, чувствителен к морфологии. Для современных задач часто используют Word Embeddings или Transformer модели (BERT), но TF-IDF остаётся полезным baseline.