Разработка модели классификации фейковых новостей в крипто

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка модели классификации фейковых новостей в крипто
Сложная
от 2 недель до 3 месяцев
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1221
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1163
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    855
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1058
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    828

Разработка модели классификации фейковых новостей в крипто

Крипто-пространство — идеальная среда для дезинформации. Высокая волатильность означает, что один фейковый твит о листинге на Binance или о взломе протокола может двигать цену на десятки процентов. Pump-and-dump схемы начинаются с информационной манипуляции. Scam-проекты живут за счёт сфабрикованных новостей о партнёрствах.

Разработка классификатора фейковых новостей в крипто — это задача NLP с несколькими специфическими сложностями: узкодоменная терминология, скорость распространения информации (новость устаревает за часы), мультиязычность, намеренная обфускация текста авторами фейков.

Постановка задачи и типология фейков

Прежде чем строить модель, нужно понять, что именно классифицируем. «Фейковые новости» — слишком широкое понятие.

Категории дезинформации в крипто:

  • Fake listings: ложные заявления о листинге на крупной бирже (CEX или DEX пул с фейковым токеном)
  • Fake partnerships: несуществующие партнёрства (X протокол интегрируется с Y)
  • Fabricated exploits: ложные сообщения о взломе для паники и продаж
  • Shill content: манипулятивное продвижение без раскрытия финансового интереса
  • Price manipulation narrative: скоординированные нарративы для pump/dump
  • Impersonation: контент от аккаунтов, имитирующих официальные (Vitalik_Buterin_ вместо VitalikButerin)

Каждая категория имеет свои текстовые паттерны, источники и методы верификации. Модель должна классифицировать по категориям, а не просто binary «fake/real».

Сбор и разметка данных

Главная проблема — отсутствие готового датасета. Существующие датасеты фейков (LIAR, FakeNewsNet) не охватывают крипто-специфику.

Источники данных

Twitter/X API: основная площадка для крипто-новостей и манипуляций. Academic Research API даёт доступ к историческим данным. Ключевые фильтры: аккаунты с > 1,000 follower в крипто-нише, хэштеги (#bitcoin, #defi, #altcoin и др.), ключевые слова протоколов.

Telegram channels: Telethon для парсинга публичных каналов. Важный источник — pump-and-dump каналы (многие публичны).

Reddit: r/CryptoCurrency, r/Bitcoin, r/CryptoMoonShots. Pushshift API или Reddit API для исторических данных.

Crypto news агрегаторы: CoinDesk, Cointelegraph, Decrypt — верифицированные новости (позитивный класс). Contrast со слухами в Twitter.

Стратегия разметки

Автоматическая разметка через кросс-верификацию: если новость появляется в Twitter, но не подтверждается официальными каналами проекта за 24 часа — потенциальный фейк. Если новость противоречит on-chain данным (заявлен листинг, но пула нет) — фейк с высокой вероятностью.

Human labeling через crowdsourcing (Scale AI, Appen) с доменными экспертами для финальной верификации. Каждый пример размечается минимум тремя аннотаторами, используем inter-annotator agreement (Cohen's kappa > 0.7 как порог качества).

from datasets import Dataset
import pandas as pd

# Структура датасета
example_schema = {
    'id': str,                    # уникальный идентификатор
    'text': str,                  # текст новости/поста
    'source': str,                # twitter / telegram / reddit / news_site
    'author': str,                # аккаунт-источник
    'timestamp': str,             # время публикации
    'label': int,                 # 0=real, 1=fake
    'category': str,              # fake_listing / fake_partnership / etc.
    'confidence': float,          # уверенность разметчиков (0-1)
    'verification_sources': list, # ссылки на верификацию
    'mentioned_tokens': list,     # упомянутые токены/проекты
    'mentioned_exchanges': list,  # упомянутые биржи
}

# Балансировка датасета важна: реальных новостей обычно больше
def balance_dataset(df: pd.DataFrame, target_ratio: float = 0.4) -> pd.DataFrame:
    """target_ratio: доля fake в финальном датасете"""
    fake = df[df['label'] == 1]
    real = df[df['label'] == 0]
    
    n_fake = len(fake)
    n_real_target = int(n_fake / target_ratio * (1 - target_ratio))
    
    real_sampled = real.sample(n=min(n_real_target, len(real)), random_state=42)
    return pd.concat([fake, real_sampled]).sample(frac=1, random_state=42)

Архитектура модели

Feature Engineering: что важно для крипто-фейков

Прежде чем выбрать архитектуру, определяем признаки, специфичные для домена.

Текстовые сигналы фейков:

  • Чрезмерный hype без конкретики («100x guaranteed», «next bitcoin»)
  • Срочность («buy NOW», «last chance»)
  • Имена известных проектов/личностей без контекста
  • Грамматические ошибки (импersonation аккаунты часто небрежны)
  • Несоответствие заявленного источника реальному

Metadata признаки:

  • Возраст аккаунта и история публикаций
  • Follower/following ratio (0.01 = подозрительно)
  • Скорость распространения (viral за первый час = подозрительно)
  • Временной паттерн (публикация в 3:00 UTC)
  • Количество похожих постов с одинаковым нарративом

Модельный стек

Baseline: TF-IDF + Logistic Regression / XGBoost. Быстро обучается, хорошо интерпретируется, устанавливает baseline F1.

Transformer-based: FinBERT (финансово-ориентированный BERT) или криптo-fine-tuned BERT. Понимает контекст и нюансы языка.

Ensemble: комбинация transformer features + metadata features через gradient boosting. Практически всегда превосходит одиночную модель.

from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch
import numpy as np
from sklearn.ensemble import GradientBoostingClassifier

class CryptoFakeNewsClassifier:
    def __init__(self, model_name: str = 'ProsusAI/finbert'):
        self.tokenizer = AutoTokenizer.from_pretrained(model_name)
        self.text_model = AutoModelForSequenceClassification.from_pretrained(
            model_name, 
            num_labels=6  # real + 5 категорий фейков
        )
        self.meta_classifier = GradientBoostingClassifier(
            n_estimators=300,
            max_depth=6,
            learning_rate=0.05
        )
        
    def extract_text_features(self, texts: list[str]) -> np.ndarray:
        """Извлекает CLS embeddings из transformer модели"""
        self.text_model.eval()
        all_embeddings = []
        
        batch_size = 32
        for i in range(0, len(texts), batch_size):
            batch = texts[i:i+batch_size]
            inputs = self.tokenizer(
                batch,
                max_length=512,
                truncation=True,
                padding=True,
                return_tensors='pt'
            )
            
            with torch.no_grad():
                outputs = self.text_model(**inputs, output_hidden_states=True)
                # CLS token из последнего слоя
                cls_embeddings = outputs.hidden_states[-1][:, 0, :]
                all_embeddings.append(cls_embeddings.numpy())
        
        return np.vstack(all_embeddings)
    
    def extract_meta_features(self, posts: list[dict]) -> np.ndarray:
        """Извлекает metadata признаки из поста"""
        features = []
        for post in posts:
            account_age_days = (
                pd.Timestamp.now() - pd.Timestamp(post['account_created'])
            ).days
            
            feature_vector = [
                account_age_days,
                post.get('followers_count', 0),
                post.get('following_count', 1),
                post.get('followers_count', 0) / max(post.get('following_count', 1), 1),
                post.get('tweet_count', 0),
                post.get('retweet_count', 0),
                post.get('like_count', 0),
                int(post.get('verified', False)),
                len(post.get('text', '')),
                post.get('text', '').count('!'),
                post.get('text', '').count('$'),
                # Час публикации (цикличность через sin/cos)
                np.sin(2 * np.pi * pd.Timestamp(post['created_at']).hour / 24),
                np.cos(2 * np.pi * pd.Timestamp(post['created_at']).hour / 24),
                # Наличие URL
                int('http' in post.get('text', '')),
                # Число упоминаний известных проектов
                sum(1 for token in KNOWN_TOKENS if token.lower() in post.get('text', '').lower()),
            ]
            features.append(feature_vector)
        
        return np.array(features)
    
    def predict(self, posts: list[dict]) -> dict:
        texts = [p['text'] for p in posts]
        
        text_features = self.extract_text_features(texts)
        meta_features = self.extract_meta_features(posts)
        
        # Конкатенация features
        combined = np.hstack([text_features, meta_features])
        
        # Финальная классификация
        probabilities = self.meta_classifier.predict_proba(combined)
        predictions = self.meta_classifier.predict(combined)
        
        return {
            'predictions': predictions,
            'probabilities': probabilities,
            'labels': ['real', 'fake_listing', 'fake_partnership', 
                      'fake_exploit', 'shill', 'impersonation']
        }

Fine-tuning на крипто-домен

FinBERT обучался на финансовых новостях, но не специализирован для крипто. Fine-tuning на крипто-корпусе значительно улучшает качество.

from transformers import Trainer, TrainingArguments

training_args = TrainingArguments(
    output_dir='./crypto-fake-news-model',
    num_train_epochs=5,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=32,
    warmup_steps=500,
    weight_decay=0.01,
    logging_dir='./logs',
    evaluation_strategy='epoch',
    save_strategy='epoch',
    load_best_model_at_end=True,
    metric_for_best_model='f1_macro',  # важнее accuracy на несбалансированных данных
    
    # Class weights для несбалансированных классов
    # fake примеры в minority — нужно больший штраф за FN
)

# Кастомные weights: fake классы получают больший вес
class_weights = compute_class_weight(
    class_weight='balanced',
    classes=np.unique(train_labels),
    y=train_labels
)

Верификация через on-chain данные

Уникальное преимущество крипто-домена: многие заявления верифицируемы on-chain.

Заявлен листинг на Uniswap V3: проверяем через Uniswap Subgraph — существует ли пул. Заявлен exploit: проверяем изменение TVL в DeFiLlama API за указанный период. Заявлено партнёрство с протоколом: ищем on-chain взаимодействие между контрактами.

import aiohttp

async def verify_listing_claim(token_address: str, dex: str = 'uniswap_v3') -> dict:
    """Верификация заявления о листинге через on-chain данные"""
    
    if dex == 'uniswap_v3':
        query = """
        query PoolsForToken($token: String!) {
            pools(where: { 
                or: [
                    { token0: $token },
                    { token1: $token }
                ]
            }, first: 5) {
                id
                token0 { symbol }
                token1 { symbol }
                liquidity
                totalValueLockedUSD
                createdAtTimestamp
            }
        }
        """
        
        async with aiohttp.ClientSession() as session:
            async with session.post(
                'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3',
                json={'query': query, 'variables': {'token': token_address.lower()}}
            ) as response:
                data = await response.json()
                pools = data.get('data', {}).get('pools', [])
                
                return {
                    'listing_exists': len(pools) > 0,
                    'pools': pools,
                    'total_tvl': sum(float(p['totalValueLockedUSD']) for p in pools)
                }

async def verify_exploit_claim(protocol: str, claimed_amount_usd: float, 
                                claim_timestamp: int) -> dict:
    """Верификация заявления о взломе через TVL данные"""
    
    # DeFiLlama API для исторического TVL
    async with aiohttp.ClientSession() as session:
        async with session.get(
            f'https://api.llama.fi/protocol/{protocol}'
        ) as response:
            data = await response.json()
            tvl_history = data.get('tvl', [])
    
    # Найти изменение TVL вокруг timestamp
    before_tvl = get_tvl_at_timestamp(tvl_history, claim_timestamp - 3600)
    after_tvl = get_tvl_at_timestamp(tvl_history, claim_timestamp + 3600)
    
    tvl_drop = before_tvl - after_tvl if before_tvl > after_tvl else 0
    
    return {
        'tvl_drop_detected': tvl_drop > 0,
        'detected_amount': tvl_drop,
        'claimed_amount': claimed_amount_usd,
        'plausible': abs(tvl_drop - claimed_amount_usd) / claimed_amount_usd < 0.3
    }

On-chain верификация превращает часть задачи из NLP в детерминированную проверку. Это значительно повышает точность для категорий, имеющих on-chain след.

Оценка качества модели

Для задачи детекции фейков accuracy — неправильная метрика. Если 90% примеров реальные новости, модель, всегда предсказывающая «real», получит 90% accuracy.

Precision, Recall, F1 по классам — основные метрики. Особое внимание к recall для fake классов: FN (пропущенный фейк) хуже FP (ложная тревога).

Area Under ROC Curve (AUC-ROC): порогово-независимая оценка.

Temporal stability: модель должна сохранять качество на новых данных. Крипто-нарративы меняются быстро — необходимо регулярное переобучение.

from sklearn.metrics import classification_report, roc_auc_score
import pandas as pd

def evaluate_model(y_true, y_pred, y_proba, class_names):
    # Детальный отчёт по классам
    report = classification_report(
        y_true, y_pred, 
        target_names=class_names,
        output_dict=True
    )
    
    df_report = pd.DataFrame(report).T
    
    # Особый акцент на fake классы
    fake_classes = [c for c in class_names if c != 'real']
    fake_f1_avg = df_report.loc[fake_classes, 'f1-score'].mean()
    
    print(f"Fake detection F1 (macro avg): {fake_f1_avg:.3f}")
    print(f"Real precision: {df_report.loc['real', 'precision']:.3f}")
    
    # AUC для бинарной задачи (fake vs real)
    binary_labels = (y_true > 0).astype(int)  # все fake категории = 1
    binary_proba = 1 - y_proba[:, 0]           # вероятность "not real"
    auc = roc_auc_score(binary_labels, binary_proba)
    print(f"AUC-ROC (fake vs real): {auc:.3f}")
    
    return df_report

Целевые показатели для production системы: Fake detection recall > 0.85 (пропускаем не более 15% фейков), Real precision > 0.90 (не более 10% ложных тревог), F1 macro > 0.82.

Deployment и реальное использование

Модель в production должна обрабатывать потоковые данные в реальном времени. Архитектура: Kafka для ingestion Twitter/Telegram stream → inference service (FastAPI + GPU или CPU для небольшой нагрузки) → PostgreSQL + Elasticsearch для хранения и поиска → alerting при обнаружении фейков.

Concept drift: крипто-нарративы меняются быстро. Раз в месяц переобучение на новых данных. Мониторинг distribution shift в inference (если распределение входных данных значительно меняется — сигнал для переобучения).

Человеческая верификация: high-confidence фейки (>0.95 вероятность) публикуются автоматически, borderline (0.6–0.95) идут на human review. Это снижает ущерб от ошибок модели.

Правовые и этические аспекты

Автоматическая классификация контента как «фейкового» несёт правовые риски. Рекомендации: система должна работать как «risk score» для дополнительной проверки, а не как финальный вердикт. Публичная система должна иметь механизм апелляции. Использование только публично доступных данных.

Стек и сроки разработки

Инфраструктура данных: Python (pandas, datasets), Twitter/Telegram API, PostgreSQL.

ML стек: PyTorch + HuggingFace Transformers, scikit-learn, Weights & Biases для экспериментов.

Deployment: FastAPI, Docker, Redis для кэширования, опционально Triton Inference Server для GPU inference.

Сроки: сбор и разметка 50,000 примеров — 6–8 недель, обучение baseline + transformer моделей + evaluation — 4–6 недель, production deployment + мониторинг — 3–4 недели. Итого: 3–4 месяца до production-ready системы.