26  Security and Automation

NoteChapter Overview

Before diving into industry-specific applications, this chapter covers embedding patterns that apply universally across all industries. Every organization—regardless of sector—faces cybersecurity threats, must detect behavioral anomalies, and can benefit from embedding-driven decision systems. These cross-cutting patterns from Part IV’s advanced applications form the foundation upon which industry-specific solutions are built. Financial services, healthcare, retail, manufacturing, and every other industry should apply these techniques alongside their domain-specific implementations.

The application patterns covered in Part IV—RAG (Chapter 11), semantic search (Chapter 12), and recommendation systems (Chapter 13)—provide powerful capabilities that organizations adopt based on their specific needs. However, some embedding applications are not optional: every organization must address security threats and behavioral anomalies, and every organization can benefit from embedding-driven automation.

This chapter consolidates these universal patterns, providing a foundation that subsequent industry chapters build upon. When you read about financial services (Chapter 29), healthcare (Chapter 30), or manufacturing (Chapter 32), assume these cross-industry patterns apply in addition to domain-specific techniques.

26.1 Cybersecurity Threat Hunting

Cybersecurity teams hunt for threats—APTs, compromised accounts, insider threats—in massive logs. Embedding-based threat hunting learns behavioral embeddings of users, devices, and network entities, detecting anomalies that indicate compromise or malicious activity.

26.1.1 The Threat Hunting Challenge

Traditional Security Information and Event Management (SIEM) systems use rules:

  • Rule: If user logs in from new country, alert
  • Rule: If outbound data transfer > 10GB, alert

Limitations:

  • High false positives (legitimate travel, legitimate data transfers)
  • Evasion: Attackers split transfers, use slow exfiltration
  • Cannot detect novel attacks (zero-day exploits, new TTPs)

The Zero-Day Argument: The most compelling case for embeddings in security is zero-day detection. A classifier can only recognize attack patterns present in its training data. An embedding system can detect “this behavior is unlike anything normal I’ve seen” without ever having seen that specific attack.

# Classifier limitation: only knows trained attack types
attack_types = ['sql_injection', 'xss', 'credential_stuffing']  # Fixed at training time

# Embedding advantage: detects deviation from normal
if distance_to_nearest_normal_cluster > threshold:
    alert("Anomalous behavior detected")  # Works for novel attacks

Embedding approach: Learn normal behavior embeddings for each user/device. Anomalies = deviation from learned patterns. See Chapter 14 for approaches to building behavioral embeddings, from fine-tuning pre-trained models to custom architectures.

26.1.2 Training the Behavioral Embedding Model

Before we can establish baselines for individual users, we need a model that can encode behavioral sequences into meaningful embeddings. There are two distinct training phases:

Phase 1: Train the encoder model

The embedding model (like the UserBehaviorModel shown below) learns to encode sequences of events into dense vectors. This model is trained on aggregate behavioral data—not to detect anomalies, but to create useful representations:

  • Self-supervised learning: Train the model to predict the next event in a sequence, or to reconstruct masked events. This forces it to learn patterns in normal behavior.
  • Contrastive learning: Train the model so that similar behavior sequences (same user, same time period) have similar embeddings, while different behaviors are pushed apart.
  • Transfer learning: Start with a pre-trained sequence model and fine-tune on your security logs.
# Example: Self-supervised training objective
# Model learns to predict next event from previous events
def train_step(model, event_sequence):
    # Input: events 1 to N-1, Target: events 2 to N
    input_events = event_sequence[:, :-1]
    target_events = event_sequence[:, 1:]

    # Model learns behavioral patterns by predicting sequences
    predicted = model(input_events)
    loss = cross_entropy(predicted, target_events)
    return loss

The key insight: the encoder doesn’t need labeled attacks to train. It learns the structure of behavior from unlabeled data. This is why embedding approaches work for zero-day detection—the model understands “normal” without being told what “malicious” looks like.

Phase 2: Establish per-user baselines

Once the encoder is trained, we use it to create embeddings for each user’s behavior and establish what’s normal for that specific user. This is where the cold start problem arises.

ImportantEstablishing “Normal”: The Cold Start Problem

A common question: when the system is first deployed, how do you know what’s normal? Several approaches:

1. Baseline Learning Period (most common)

Run the system in “learning mode” for 2-4 weeks before alerting. During this period:

  • Collect behavior embeddings without generating alerts
  • Assume the vast majority of traffic is legitimate (typically >99%)
  • Build per-user/per-device baseline clusters
  • Use statistical methods (IQR, percentile thresholds) to set initial anomaly boundaries

2. Labeled Historical Data (supervised bootstrap)

If you have historical logs with known incidents:

  • Label past incidents as “malicious” (from SIEM alerts, incident reports)
  • Everything else becomes the “normal” training set
  • Risk: unknown compromises in “normal” data (addressed below)

3. Clean Room Approach (high-security environments)

  • Build baseline from controlled test traffic or synthetic data
  • Gradually incorporate production traffic after validation
  • Most conservative but slowest to deploy

What about malicious traffic already in the baseline?

This is a real concern—an attacker who’s already present gets “grandfathered” into normal. Mitigations:

  • Peer group analysis: Compare users to similar roles. An analyst doing admin tasks stands out even if that’s “their normal”
  • Behavioral drift detection: Alert on gradual changes, not just sudden ones
  • External threat intelligence: Cross-reference with known IOCs during baseline period
  • Periodic baseline refresh: Rebuild baselines periodically, excluding known-bad periods
  • Hybrid detection: Run rule-based detection in parallel during baseline learning

Practical timeline:

Phase Duration Mode
Initial collection 1-2 weeks Silent (no alerts)
Baseline calibration 1-2 weeks High-threshold alerts only
Production Ongoing Full alerting with feedback loop

The key insight: you don’t need perfect baselines to detect novel attacks. Even a baseline contaminated with some malicious behavior will flag attacks that differ from that attacker’s patterns.

Show User Behavior Anomaly Detection
import torch
import torch.nn as nn
import torch.nn.functional as F


class UserBehaviorModel(nn.Module):
    """Model user behavior as sequence of events."""
    def __init__(self, event_dim: int = 64, hidden_dim: int = 128, num_event_types: int = 20):
        super().__init__()
        self.event_type_embedding = nn.Embedding(num_event_types, event_dim)
        self.lstm = nn.LSTM(input_size=event_dim, hidden_size=hidden_dim,
                            num_layers=2, batch_first=True)
        self.attention = nn.Linear(hidden_dim, 1)
        self.output_projection = nn.Linear(hidden_dim, event_dim)

    def forward(self, event_sequences):
        """Encode user behavior from event sequence."""
        event_embs = self.event_type_embedding(event_sequences)
        lstm_out, _ = self.lstm(event_embs)

        # Attention mechanism
        attn_weights = torch.softmax(self.attention(lstm_out), dim=1)
        behavior_emb = (lstm_out * attn_weights).sum(dim=1)

        behavior_emb = self.output_projection(behavior_emb)
        return F.normalize(behavior_emb, p=2, dim=1)

# Usage example
model = UserBehaviorModel(event_dim=64, hidden_dim=128, num_event_types=20)

# Normal behavior sequence
normal_sequence = torch.tensor([[0, 2, 3, 2, 0]])  # login, file_read, etc.
normal_emb = model(normal_sequence)

# Anomalous behavior sequence
anomalous_sequence = torch.tensor([[1, 4, 5, 4]])  # login_failure, file_delete, etc.
anomalous_emb = model(anomalous_sequence)

# Compare
distance = torch.norm(normal_emb - anomalous_emb)
print(f"Behavior distance: {distance.item():.4f}")
Behavior distance: 0.3362
TipThreat Hunting Best Practices

Baselines:

  • Per-user baselines: Each user has unique normal behavior
  • Per-device baselines: Each device has characteristic patterns
  • Time-aware: Behavior varies by time of day, day of week
  • Context-aware: Location, VPN usage, remote vs office

Features:

  • Login patterns: Time, location, device, success/failure rate
  • File access: Paths accessed, read/write/delete ratios
  • Network activity: Connections, data volumes, destinations
  • Process execution: Binaries run, arguments, parent processes

Detection:

  • Sequential anomalies: Unusual sequence of events (login → sensitive file → large upload)
  • Statistical anomalies: Unusual frequency, volume, or timing
  • Behavioral drift: Gradual change in behavior (slow compromise)
  • Peer group analysis: Deviation from similar users (same role, department)

Production:

  • Low latency: <1 second for real-time alerting
  • Prioritization: Rank alerts by severity (combine multiple signals)
  • Investigation workflow: Provide context for analysts (what’s unusual, why)
  • Feedback loop: Incorporate analyst decisions (true positive, false positive)

26.1.3 Industry Applications of Threat Hunting

While the core threat hunting techniques are universal, each industry has specific threat profiles:

  • Financial Services (Chapter 29): Focus on credential theft, payment fraud, insider trading
  • Healthcare (Chapter 30): PHI exfiltration, ransomware, medical device compromise
  • Retail (Chapter 31): POS malware, loyalty fraud, supply chain attacks
  • Manufacturing (Chapter 32): Industrial espionage, OT/ICS attacks, IP theft
  • Defense (Chapter 35): Nation-state APTs, classified data exfiltration

26.2 Behavioral Anomaly Detection

User accounts can be compromised (phishing, credential stuffing) or misused (insider threats). Behavioral anomaly detection learns normal user behavior embeddings, flagging deviations that indicate account takeover or malicious activity.

26.2.1 The Behavioral Challenge

Users exhibit consistent patterns:

  • Login times (weekdays 9-5)
  • Devices (laptop, phone)
  • Actions (emails, file access)

Account compromise changes behavior:

  • Login from new location/device
  • Unusual actions (access sensitive files, bulk downloads)
  • Velocity changes (sudden spike in activity)

Challenge: Detect deviations while adapting to legitimate behavior changes (new job, new phone).

Show Behavioral Anomaly Detection Example
def behavioral_anomaly_example():
    """Account takeover detection for web application."""
    print("=== Account Takeover Detection ===")
    print("\nNormal baseline:")
    print("  Login time: Weekdays 9am-6pm")
    print("  Location: San Francisco office")
    print("  Device: MacBook Pro")
    print("  Actions: View dashboard, edit documents")
    print("  Velocity: 10-20 pages/session")

    print("\n--- Legitimate Session ---")
    print("Time: Tuesday 2pm")
    print("Location: San Francisco office")
    print("Device: MacBook Pro")
    print("Actions: View dashboard, edit report, send email")
    print("Velocity: 15 pages")
    print("→ Anomaly score: 0.05 (NORMAL)")

    print("\n--- Compromised Session ---")
    print("Time: Saturday 3am")
    print("Location: Unknown (Tor exit node)")
    print("Device: Windows PC (new)")
    print("Actions: Access admin panel, bulk export users, delete logs")
    print("Velocity: 150 pages")
    print("→ Anomaly score: 0.95 (ALERT: Possible account takeover)")

    print("\n--- Legitimate Travel ---")
    print("Time: Monday 10am")
    print("Location: New York office (business trip)")
    print("Device: MacBook Pro + iPhone")
    print("Actions: View dashboard, edit documents")
    print("Velocity: 12 pages")
    print("→ Anomaly score: 0.25 (MONITOR: New location, but normal actions)")

# Run example
behavioral_anomaly_example()
=== Account Takeover Detection ===

Normal baseline:
  Login time: Weekdays 9am-6pm
  Location: San Francisco office
  Device: MacBook Pro
  Actions: View dashboard, edit documents
  Velocity: 10-20 pages/session

--- Legitimate Session ---
Time: Tuesday 2pm
Location: San Francisco office
Device: MacBook Pro
Actions: View dashboard, edit report, send email
Velocity: 15 pages
→ Anomaly score: 0.05 (NORMAL)

--- Compromised Session ---
Time: Saturday 3am
Location: Unknown (Tor exit node)
Device: Windows PC (new)
Actions: Access admin panel, bulk export users, delete logs
Velocity: 150 pages
→ Anomaly score: 0.95 (ALERT: Possible account takeover)

--- Legitimate Travel ---
Time: Monday 10am
Location: New York office (business trip)
Device: MacBook Pro + iPhone
Actions: View dashboard, edit documents
Velocity: 12 pages
→ Anomaly score: 0.25 (MONITOR: New location, but normal actions)
TipBehavioral Anomaly Best Practices

Features:

  • Temporal: Time of day, day of week, session duration
  • Spatial: Location (IP geolocation), VPN usage
  • Device: Browser, OS, screen resolution (fingerprinting)
  • Actions: Pages visited, features used, API calls made
  • Velocity: Actions per minute, data transferred

Modeling:

  • Per-user baselines: Each user has unique normal behavior
  • LSTM: Sequential modeling of user actions
  • Autoencoder: Reconstruct behavior, high error = anomaly
  • Peer groups: Compare to similar users (same role)

Production:

  • Real-time: Flag suspicious sessions immediately
  • Progressive authentication: Challenge anomalous sessions (2FA, security questions)
  • Adaptive baselines: Update with confirmed normal behavior
  • False positive management: Avoid blocking legitimate users

Challenges:

  • Cold start: New users have no baseline
  • Concept drift: Behavior changes over time (new role, new tools)
  • Adversarial: Attackers mimic normal behavior (slow compromise)

26.3 Embedding-Driven Business Rules

Business rules encode domain knowledge: credit policies, pricing strategies, underwriting guidelines. Embedding-driven business rules replace rigid if-then logic with learned decision boundaries in embedding space, adapting to patterns that humans can’t articulate and updating as business conditions change.

26.3.1 The Business Rules Challenge

Traditional business rules face limitations:

  • Brittleness: Rules hardcode thresholds (credit score > 700) that don’t generalize
  • Maintenance burden: Hundreds of rules accumulate, interact unpredictably
  • Cold start: No rules exist for new products, markets, situations
  • Suboptimality: Rules encode human intuition, miss non-linear patterns

Embedding approach: Learn entity embeddings (customers, products, transactions) and decision boundaries from historical outcomes. New decisions query: “find similar past cases, what happened?” See Chapter 14 for guidance on building these embeddings, and Chapter 16 for similarity-based learning approaches.

Show Case-Based Reasoning System
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
from dataclasses import dataclass
from typing import Optional


@dataclass
class BusinessCase:
    """Historical business decision case."""
    case_id: str
    entity_id: str
    context: dict
    decision: any
    outcome: Optional[any] = None
    embedding: Optional[np.ndarray] = None


class EntityEncoder(nn.Module):
    """Encode entities for decision making."""
    def __init__(self, embedding_dim: int = 128,
                 num_categorical: int = 10, num_numerical: int = 20):
        super().__init__()
        self.embedding_dim = embedding_dim
        self.categorical_embeddings = nn.ModuleList(
            [nn.Embedding(1000, 16) for _ in range(num_categorical)]
        )
        self.numerical_encoder = nn.Sequential(
            nn.Linear(num_numerical, 64),
            nn.ReLU(),
            nn.Dropout(0.2),
            nn.Linear(64, 64)
        )
        feature_dim = num_categorical * 16 + 64
        self.feature_encoder = nn.Sequential(
            nn.Linear(feature_dim, 256),
            nn.ReLU(),
            nn.Dropout(0.2),
            nn.Linear(256, embedding_dim)
        )

    def forward(self, categorical_features, numerical_features):
        """Encode entities to embeddings."""
        cat_embs = [emb_layer(categorical_features[:, i])
                    for i, emb_layer in enumerate(self.categorical_embeddings)]
        cat_emb = torch.cat(cat_embs, dim=1)
        num_emb = self.numerical_encoder(numerical_features)
        combined = torch.cat([cat_emb, num_emb], dim=1)
        entity_emb = self.feature_encoder(combined)
        return F.normalize(entity_emb, p=2, dim=1)

# Usage example
encoder = EntityEncoder(embedding_dim=128, num_categorical=10, num_numerical=20)
cat_features = torch.randint(0, 100, (1, 10))
num_features = torch.randn(1, 20)
embedding = encoder(cat_features, num_features)
print(f"Entity embedding shape: {embedding.shape}")
Entity embedding shape: torch.Size([1, 128])
TipEmbedding-Driven Business Rules Best Practices

Architecture:

  • Entity encoders: Learn embeddings that predict outcomes
  • Case-based reasoning: Retrieve similar historical cases
  • Hybrid systems: Combine learned patterns + explicit rules
  • Explainability: Surface similar cases that influenced decision

Training:

  • Metric learning: Entities with similar outcomes close in embedding space (see Chapter 16)
  • Multi-task: Predict multiple outcomes jointly (default, LTV, churn)
  • Temporal: Weight recent cases higher (concept drift)
  • Fairness: Constrain to prevent disparate impact

Production:

  • Low latency: <100ms for real-time decisions (credit cards, pricing)
  • Confidence thresholds: Route low-confidence to humans
  • Rule compliance: Hard constraints for regulations
  • Monitoring: Track decision quality, fairness metrics
  • Feedback loops: Continuously add outcomes to case database

Challenges:

  • Cold start: No historical cases for new scenarios
  • Distribution shift: Decisions change underlying distribution
  • Adversarial: Bad actors game the system
  • Fairness: Embeddings can encode bias from historical data

26.3.2 Industry Applications of Business Rules

Each industry applies embedding-driven rules differently:

  • Financial Services (Chapter 29): Credit decisions, fraud rules, trading limits
  • Healthcare (Chapter 30): Treatment protocols, clinical decision support
  • Retail (Chapter 31): Pricing rules, promotion targeting, inventory allocation
  • Manufacturing (Chapter 32): Quality gates, process parameters, maintenance scheduling

26.4 Customer Support Intelligence

Customer support operations generate massive volumes of unstructured data—tickets, chat transcripts, emails, call recordings—that embeddings transform into actionable intelligence. Embedding-based customer support systems enable semantic routing, automated resolution, agent assist, and proactive issue detection at scale.

26.4.1 The Support Intelligence Challenge

Traditional customer support systems rely on keyword matching and manual categorization:

  • Routing failures: “My card doesn’t work” routes to “card services” instead of “fraud”
  • Knowledge silos: Solutions exist but agents can’t find them
  • Repetitive work: Agents solve the same problems repeatedly
  • Reactive posture: Issues discovered when customers complain

Embedding approach: Encode tickets, knowledge articles, and historical resolutions into a unified semantic space. Similar issues cluster together; solutions transfer across variations. See Chapter 12 for search implementation and Chapter 11 for retrieval-augmented response generation.

Show Customer Support Embedding System
import torch
import torch.nn as nn
import torch.nn.functional as F
from dataclasses import dataclass
from typing import Optional
import numpy as np


@dataclass
class SupportTicket:
    """Customer support ticket with metadata."""
    ticket_id: str
    text: str
    category: Optional[str] = None
    priority: Optional[str] = None
    resolution: Optional[str] = None
    embedding: Optional[np.ndarray] = None


class SupportEncoder(nn.Module):
    """Encode support tickets for semantic operations."""
    def __init__(self, vocab_size: int = 30000, embedding_dim: int = 256,
                 hidden_dim: int = 512):
        super().__init__()
        self.token_embedding = nn.Embedding(vocab_size, embedding_dim)
        self.encoder = nn.TransformerEncoder(
            nn.TransformerEncoderLayer(
                d_model=embedding_dim, nhead=8, dim_feedforward=hidden_dim,
                batch_first=True
            ),
            num_layers=4
        )
        self.pooler = nn.Linear(embedding_dim, embedding_dim)

    def forward(self, token_ids, attention_mask=None):
        """Encode ticket text to embedding."""
        embeddings = self.token_embedding(token_ids)
        encoded = self.encoder(embeddings, src_key_padding_mask=attention_mask)
        # Mean pooling over sequence
        pooled = encoded.mean(dim=1)
        return F.normalize(self.pooler(pooled), p=2, dim=1)


class SemanticRouter:
    """Route tickets based on semantic similarity to category exemplars."""
    def __init__(self, encoder: nn.Module, categories: dict[str, list]):
        self.encoder = encoder
        self.category_centroids = {}
        self._build_centroids(categories)

    def _build_centroids(self, categories: dict[str, list]):
        """Compute centroid embedding for each category."""
        for category, exemplar_ids in categories.items():
            # In production: encode exemplar tickets, compute mean
            self.category_centroids[category] = np.random.randn(256)

    def route(self, ticket_embedding: np.ndarray, top_k: int = 3):
        """Route ticket to most similar categories."""
        similarities = {}
        for category, centroid in self.category_centroids.items():
            sim = np.dot(ticket_embedding, centroid) / (
                np.linalg.norm(ticket_embedding) * np.linalg.norm(centroid)
            )
            similarities[category] = sim
        return sorted(similarities.items(), key=lambda x: -x[1])[:top_k]


# Usage example
encoder = SupportEncoder()
print("Support encoder initialized")
print(f"Embedding dimension: 256")

# Demonstrate routing concept
categories = {
    "billing": ["exemplar_1", "exemplar_2"],
    "technical": ["exemplar_3", "exemplar_4"],
    "account": ["exemplar_5", "exemplar_6"],
    "fraud": ["exemplar_7", "exemplar_8"]
}
router = SemanticRouter(encoder, categories)
sample_embedding = np.random.randn(256)
routes = router.route(sample_embedding)
print(f"\nSample routing results: {routes[:2]}")
Support encoder initialized
Embedding dimension: 256

Sample routing results: [('account', np.float64(0.041785837006533856)), ('billing', np.float64(-0.02479831601002558))]
TipCustomer Support Intelligence Best Practices

Semantic Routing:

  • Multi-label routing: Tickets often span categories (billing + technical)
  • Skill-based matching: Route to agents with relevant expertise
  • Load balancing: Consider agent capacity alongside semantic match
  • Escalation prediction: Identify tickets likely to escalate early

Knowledge Retrieval:

  • Dense retrieval: Find relevant articles without exact keyword match
  • Solution transfer: Apply resolutions from similar past tickets
  • Agent assist: Surface relevant info during live interactions
  • Auto-suggest: Propose responses for agent review

Analytics:

  • Issue clustering: Discover emerging problems automatically
  • Root cause analysis: Link symptoms to underlying causes
  • Customer journey: Track issues across channels and time
  • Satisfaction prediction: Predict CSAT from ticket embeddings

Scale Considerations:

  • Millions of tickets: Incremental index updates, not full rebuilds
  • Real-time routing: <100ms for routing decisions
  • Multi-language: Cross-lingual embeddings for global support
  • Privacy: PII handling for regulated industries

26.4.2 Industry Applications of Support Intelligence

  • Financial Services (Chapter 29): Compliance-aware routing, fraud escalation, regulatory inquiry handling
  • Healthcare (Chapter 30): HIPAA-compliant support, clinical vs. billing separation, urgent care routing
  • Retail (Chapter 31): Order status, returns processing, loyalty program support
  • Telecommunications: Network issues, service changes, billing disputes

26.5 Competitive Intelligence

Organizations must monitor competitors, track market trends, and identify emerging opportunities. Embedding-based competitive intelligence processes vast amounts of unstructured data—news, patents, SEC filings, social media, job postings—to surface actionable insights that would be impossible to find manually.

26.5.1 The Intelligence Challenge

Traditional competitive intelligence faces limitations:

  • Volume: Too much information to read manually
  • Noise: Most content is irrelevant or redundant
  • Latency: By the time analysts find it, it’s old news
  • Connections: Hard to link signals across sources

Embedding approach: Encode all sources into a unified semantic space. Monitor for clusters (emerging trends), anomalies (breaking news), and trajectories (strategic shifts). See Chapter 12 for retrieval and Chapter 13 for personalized alerting.

Show Competitive Intelligence System
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
from dataclasses import dataclass
from datetime import datetime
from typing import Optional


@dataclass
class IntelDocument:
    """Document from intelligence feed."""
    doc_id: str
    source: str  # news, patent, filing, social, jobs
    timestamp: datetime
    text: str
    entities: list[str]  # companies, people, products mentioned
    embedding: Optional[np.ndarray] = None


class TrendDetector:
    """Detect emerging trends from document embeddings."""
    def __init__(self, embedding_dim: int = 384, window_days: int = 7):
        self.embedding_dim = embedding_dim
        self.window_days = window_days
        self.cluster_centroids = []
        self.cluster_sizes = []

    def detect_emerging_clusters(self, recent_embeddings: np.ndarray,
                                 historical_centroids: np.ndarray,
                                 threshold: float = 0.3):
        """Find document clusters that don't match historical patterns."""
        emerging = []
        # Simple clustering simulation
        n_clusters = min(10, len(recent_embeddings) // 10)
        for i in range(n_clusters):
            cluster_centroid = recent_embeddings[i * 10:(i + 1) * 10].mean(axis=0)
            # Check distance to all historical centroids
            if len(historical_centroids) > 0:
                max_sim = max(
                    np.dot(cluster_centroid, hist) / (
                        np.linalg.norm(cluster_centroid) * np.linalg.norm(hist)
                    )
                    for hist in historical_centroids
                )
                if max_sim < threshold:
                    emerging.append({
                        'centroid': cluster_centroid,
                        'novelty_score': 1 - max_sim,
                        'size': 10
                    })
        return emerging


class CompetitorTracker:
    """Track competitor activities through embedding trajectories."""
    def __init__(self, competitors: list[str]):
        self.competitors = competitors
        self.trajectories = {c: [] for c in competitors}

    def update_trajectory(self, competitor: str,
                          embedding: np.ndarray, timestamp: datetime):
        """Add new data point to competitor trajectory."""
        self.trajectories[competitor].append({
            'embedding': embedding,
            'timestamp': timestamp
        })

    def detect_strategic_shift(self, competitor: str,
                               window: int = 30) -> Optional[dict]:
        """Detect if competitor's focus has shifted."""
        trajectory = self.trajectories.get(competitor, [])
        if len(trajectory) < window * 2:
            return None

        # Compare recent centroid to historical centroid
        recent = np.mean([t['embedding'] for t in trajectory[-window:]], axis=0)
        historical = np.mean([t['embedding'] for t in trajectory[-window*2:-window]], axis=0)

        shift_magnitude = np.linalg.norm(recent - historical)
        if shift_magnitude > 0.5:  # Threshold
            return {
                'competitor': competitor,
                'shift_magnitude': shift_magnitude,
                'direction': recent - historical
            }
        return None


# Usage example
print("=== Competitive Intelligence System ===")

# Trend detection
detector = TrendDetector()
recent = np.random.randn(100, 384)  # 100 recent documents
historical = np.random.randn(50, 384)  # 50 historical cluster centroids
emerging = detector.detect_emerging_clusters(recent, historical)
print(f"\nEmerging trends detected: {len(emerging)}")

# Competitor tracking
tracker = CompetitorTracker(['CompetitorA', 'CompetitorB', 'CompetitorC'])
print(f"Tracking {len(tracker.competitors)} competitors")
=== Competitive Intelligence System ===

Emerging trends detected: 10
Tracking 3 competitors
TipCompetitive Intelligence Best Practices

Data Sources:

  • News & Press: Product launches, partnerships, executive changes
  • Patents: R&D direction, technology bets, acquisition targets
  • SEC Filings: Strategy statements, risk factors, segment performance
  • Job Postings: Hiring trends reveal strategic priorities
  • Social Media: Sentiment, product feedback, crisis indicators

Analysis Patterns:

  • Entity linking: Connect mentions across sources (company aliases, subsidiaries)
  • Event detection: Identify significant events (launches, acquisitions, lawsuits)
  • Sentiment tracking: Monitor perception over time
  • Relationship mapping: Who partners with whom, who competes where

Alerting:

  • Semantic alerts: “Notify me about AI chip developments” (not keyword “AI chip”)
  • Competitor alerts: Any significant activity from tracked competitors
  • Anomaly alerts: Unusual volume or sentiment patterns
  • Personalized feeds: Different stakeholders need different views

Scale Considerations:

  • Millions of documents/day: Streaming ingestion and embedding
  • Real-time updates: Hours matter for breaking news
  • Global coverage: Multi-language processing
  • Historical analysis: Years of data for trend analysis

26.5.2 Industry Applications of Competitive Intelligence

  • Financial Services (Chapter 29): Market moving news, regulatory changes, fintech monitoring
  • Healthcare (Chapter 30): Clinical trial tracking, drug approval monitoring, competitor pipelines
  • Retail (Chapter 31): Pricing intelligence, product launches, market expansion signals
  • Manufacturing (Chapter 32): Supply chain disruptions, technology trends, trade policy impacts

26.6 Document Classification and Compliance

Every organization processes documents that must be classified, routed, and retained according to policies. Embedding-based document intelligence automates classification at scale, ensures compliance with retention policies, and surfaces relevant documents for legal and regulatory requests.

26.6.1 The Document Challenge

Organizations struggle with document management:

  • Volume: Millions of documents across email, files, chat, contracts
  • Inconsistency: Manual classification is error-prone and inconsistent
  • Compliance risk: Misclassified documents create legal exposure
  • Discovery cost: Finding relevant documents for litigation is expensive

Embedding approach: Encode all documents into semantic space. Classification becomes nearest-neighbor to labeled exemplars. Compliance rules apply to embedding regions. Discovery queries semantic similarity, not just keywords.

Show Document Classification System
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
from dataclasses import dataclass
from typing import Optional
from datetime import datetime


@dataclass
class Document:
    """Enterprise document with classification metadata."""
    doc_id: str
    content: str
    doc_type: Optional[str] = None  # contract, email, report, etc.
    sensitivity: Optional[str] = None  # public, internal, confidential, restricted
    retention_class: Optional[str] = None
    embedding: Optional[np.ndarray] = None


class DocumentClassifier:
    """Classify documents using embedding similarity."""
    def __init__(self, embedding_dim: int = 384):
        self.embedding_dim = embedding_dim
        self.class_exemplars = {}  # class -> list of exemplar embeddings
        self.class_centroids = {}  # class -> centroid embedding

    def add_exemplar(self, class_name: str, embedding: np.ndarray):
        """Add labeled exemplar for a class."""
        if class_name not in self.class_exemplars:
            self.class_exemplars[class_name] = []
        self.class_exemplars[class_name].append(embedding)
        # Update centroid
        self.class_centroids[class_name] = np.mean(
            self.class_exemplars[class_name], axis=0
        )

    def classify(self, embedding: np.ndarray,
                 top_k: int = 3) -> list[tuple[str, float]]:
        """Classify document by similarity to class centroids."""
        similarities = []
        for class_name, centroid in self.class_centroids.items():
            sim = np.dot(embedding, centroid) / (
                np.linalg.norm(embedding) * np.linalg.norm(centroid)
            )
            similarities.append((class_name, float(sim)))
        return sorted(similarities, key=lambda x: -x[1])[:top_k]


class ComplianceEngine:
    """Apply compliance rules based on document classification."""
    def __init__(self):
        self.retention_rules = {
            'contract': {'years': 7, 'legal_hold': True},
            'financial': {'years': 7, 'legal_hold': True},
            'hr_record': {'years': 5, 'legal_hold': False},
            'correspondence': {'years': 3, 'legal_hold': False},
            'marketing': {'years': 1, 'legal_hold': False}
        }
        self.sensitivity_rules = {
            'pii': 'confidential',
            'phi': 'restricted',
            'financial': 'confidential',
            'trade_secret': 'restricted'
        }

    def apply_retention(self, doc: Document) -> dict:
        """Determine retention requirements."""
        rule = self.retention_rules.get(
            doc.doc_type, {'years': 3, 'legal_hold': False}
        )
        return {
            'doc_id': doc.doc_id,
            'retention_years': rule['years'],
            'legal_hold_eligible': rule['legal_hold'],
            'destroy_after': datetime.now().year + rule['years']
        }


class LegalDiscovery:
    """Support e-discovery with semantic search."""
    def __init__(self, classifier: DocumentClassifier):
        self.classifier = classifier
        self.document_index = {}  # doc_id -> embedding

    def add_document(self, doc_id: str, embedding: np.ndarray):
        """Index document for discovery."""
        self.document_index[doc_id] = embedding

    def semantic_search(self, query_embedding: np.ndarray,
                        top_k: int = 100) -> list[tuple[str, float]]:
        """Find documents semantically similar to query."""
        results = []
        for doc_id, doc_emb in self.document_index.items():
            sim = np.dot(query_embedding, doc_emb) / (
                np.linalg.norm(query_embedding) * np.linalg.norm(doc_emb)
            )
            results.append((doc_id, float(sim)))
        return sorted(results, key=lambda x: -x[1])[:top_k]


# Usage example
print("=== Document Classification & Compliance ===")

# Setup classifier with exemplars
classifier = DocumentClassifier()
for doc_type in ['contract', 'financial', 'hr_record', 'correspondence']:
    for _ in range(5):  # 5 exemplars per class
        classifier.add_exemplar(doc_type, np.random.randn(384))

# Classify new document
new_doc_embedding = np.random.randn(384)
classifications = classifier.classify(new_doc_embedding)
print(f"\nDocument classifications: {classifications[:2]}")

# Apply compliance
compliance = ComplianceEngine()
doc = Document(doc_id="DOC001", content="...", doc_type=classifications[0][0])
retention = compliance.apply_retention(doc)
print(f"Retention policy: {retention['retention_years']} years")

# Legal discovery
discovery = LegalDiscovery(classifier)
for i in range(100):
    discovery.add_document(f"DOC{i:03d}", np.random.randn(384))
query = np.random.randn(384)
results = discovery.semantic_search(query, top_k=5)
print(f"Discovery results: {len(results)} documents")
=== Document Classification & Compliance ===

Document classifications: [('correspondence', 0.07872627262206178), ('contract', 0.04113017012911074)]
Retention policy: 3 years
Discovery results: 5 documents
TipDocument Classification Best Practices

Classification:

  • Multi-label: Documents often have multiple applicable classes
  • Hierarchical: Type → Subtype → Specific category
  • Confidence thresholds: Route low-confidence to human review
  • Active learning: Prioritize uncertain documents for labeling

Compliance:

  • Retention automation: Apply policies based on classification
  • Legal holds: Suspend deletion for litigation-relevant documents
  • Audit trails: Track all classification and retention decisions
  • Policy updates: Reclassify when policies change

Discovery:

  • Semantic search: Find relevant documents beyond keywords
  • Concept clustering: Group related documents for review
  • Privilege detection: Flag potentially privileged communications
  • Deduplication: Identify near-duplicates to reduce review volume

Scale Considerations:

  • Billions of documents: Incremental processing, not batch
  • Multi-format: Email, Office docs, PDFs, images (OCR)
  • Multi-language: Global organizations need cross-lingual support
  • Performance: Classification must not slow document workflows

26.6.2 Industry Applications of Document Classification

  • Financial Services (Chapter 29): Regulatory filings, trading communications, audit documents
  • Healthcare (Chapter 30): Clinical documentation, HIPAA compliance, medical records retention
  • Legal: Case files, contracts, correspondence, privilege review
  • Government: FOIA requests, classification levels, records management

26.7 Content Moderation

Every platform with user-generated content faces moderation challenges—detecting harmful content at scale while minimizing false positives that frustrate legitimate users. Embedding-based content moderation learns semantic patterns rather than relying on keyword blocklists, catching variations and novel violations that rule-based systems miss.

26.7.1 The Content Moderation Challenge

Traditional moderation relies on keyword lists and explicit rules:

# Rule-based moderation: brittle and easily evaded
blocked_words = ['spam', 'scam', 'buy now']

def simple_filter(text):
    text_lower = text.lower()
    for word in blocked_words:
        if word in text_lower:
            return "blocked"
    return "allowed"

# Easily evaded
print(simple_filter("Buy n0w for great deals!"))  # "allowed" - evades filter
print(simple_filter("B.u" + ".y" + " now!!!"))    # "allowed" - evades filter

Limitations of rule-based systems:

  • Evasion: Users substitute characters (“s.p” + “.a.m”), use synonyms, or encode meaning in images
  • Context blindness: “Kill it!” means something different in gaming vs threats
  • Scale: Cannot manually create rules for all harmful content variations
  • False positives: Overly broad rules block legitimate content (the “Scunthorpe problem”)

Embedding advantage: Learn semantic meaning, not surface patterns. Similar harmful content maps to similar vectors regardless of spelling variations or phrasing.

26.7.2 Semantic Similarity-Based Moderation

Embed known violations and flag content semantically similar to them:

Show Content Moderator
import numpy as np
from dataclasses import dataclass
from typing import List, Tuple, Optional


@dataclass
class ViolationExample:
    """Known content violation for similarity matching."""
    text: str
    category: str  # spam, hate, harassment, etc.
    severity: str  # low, medium, high
    embedding: Optional[np.ndarray] = None


class ContentModerator:
    """Embedding-based content moderation system."""

    def __init__(self, encoder, violation_examples: List[ViolationExample]):
        self.encoder = encoder
        self.examples = violation_examples
        self._compute_embeddings()

    def _compute_embeddings(self):
        """Pre-compute embeddings for all violation examples."""
        for example in self.examples:
            example.embedding = self.encoder.encode(example.text)

    def moderate(self, content: str, threshold: float = 0.75) -> Tuple[str, Optional[str], float]:
        """
        Check content against known violations.

        Returns: (decision, category, confidence)
        - decision: 'allow', 'review', 'block'
        - category: violation category if flagged
        - confidence: similarity score
        """
        content_embedding = self.encoder.encode(content)

        best_match = None
        best_score = -1

        for example in self.examples:
            if example.embedding is not None:
                # Cosine similarity
                score = np.dot(content_embedding, example.embedding) / (
                    np.linalg.norm(content_embedding) * np.linalg.norm(example.embedding)
                )
                if score > best_score:
                    best_score = score
                    best_match = example

        # Decision thresholds
        if best_score >= threshold:
            if best_match.severity == 'high':
                return 'block', best_match.category, best_score
            else:
                return 'review', best_match.category, best_score
        elif best_score >= threshold - 0.15:  # Gray zone
            return 'review', best_match.category if best_match else None, best_score
        else:
            return 'allow', None, best_score

    def find_similar_violations(self, content: str, k: int = 3) -> List[Tuple[ViolationExample, float]]:
        """Find most similar known violations for human review."""
        content_embedding = self.encoder.encode(content)

        scored = []
        for example in self.examples:
            if example.embedding is not None:
                score = np.dot(content_embedding, example.embedding) / (
                    np.linalg.norm(content_embedding) * np.linalg.norm(example.embedding)
                )
                scored.append((example, score))

        scored.sort(key=lambda x: x[1], reverse=True)
        return scored[:k]


# Example usage with mock encoder
class MockEncoder:
    def encode(self, text):
        np.random.seed(hash(text) % 2**32)
        return np.random.randn(384)

encoder = MockEncoder()
violations = [
    ViolationExample("Buy now! Limited time offer! Click here!", "spam", "medium"),
    ViolationExample("You're an idiot and I hate you", "harassment", "high"),
    ViolationExample("Send me your password and credit card", "phishing", "high"),
    ViolationExample("This product is amazing! 5 stars! Buy it!", "fake_review", "low"),
]

moderator = ContentModerator(encoder, violations)
decision, category, confidence = moderator.moderate("Click here for amazing deals!")
print(f"Decision: {decision}, Category: {category}, Confidence: {confidence:.3f}")
Decision: allow, Category: None, Confidence: -0.010

26.7.3 Multi-Category Classification

For comprehensive moderation, classify content into multiple harm categories:

Show Multi-Category Classifier
from dataclasses import dataclass, field
from typing import List, Dict, Optional
import numpy as np


@dataclass
class ModerationCategory:
    """Content moderation category with policy examples."""
    name: str
    description: str
    examples: List[str]
    action: str  # 'block', 'warn', 'label'
    centroid: Optional[np.ndarray] = None


class MultiCategoryModerator:
    """Classify content into multiple harm categories."""

    def __init__(self, encoder, categories: List[ModerationCategory]):
        self.encoder = encoder
        self.categories = categories
        self._compute_centroids()

    def _compute_centroids(self):
        """Compute centroid embedding for each category."""
        for category in self.categories:
            if category.examples:
                embeddings = [self.encoder.encode(ex) for ex in category.examples]
                category.centroid = np.mean(embeddings, axis=0)

    def classify(self, content: str) -> Dict[str, float]:
        """
        Return probability scores for each harm category.
        """
        content_embedding = self.encoder.encode(content)
        scores = {}

        for category in self.categories:
            if category.centroid is not None:
                # Cosine similarity as "probability"
                score = np.dot(content_embedding, category.centroid) / (
                    np.linalg.norm(content_embedding) * np.linalg.norm(category.centroid)
                )
                # Normalize to 0-1 range
                scores[category.name] = max(0, (score + 1) / 2)

        return scores

    def get_action(self, content: str, threshold: float = 0.7) -> Tuple[str, List[str]]:
        """
        Determine moderation action based on category scores.

        Returns: (action, flagged_categories)
        """
        scores = self.classify(content)
        flagged = []
        max_action = 'allow'

        action_priority = {'allow': 0, 'label': 1, 'warn': 2, 'block': 3}

        for category in self.categories:
            if scores.get(category.name, 0) >= threshold:
                flagged.append(category.name)
                if action_priority[category.action] > action_priority[max_action]:
                    max_action = category.action

        return max_action, flagged


# Example usage
categories = [
    ModerationCategory(
        "spam", "Commercial spam and promotional content",
        ["Buy now! Limited offer!", "Click here for free money!", "You won a prize!"],
        "label"
    ),
    ModerationCategory(
        "hate_speech", "Content targeting protected groups",
        ["I hate all [group]", "[Group] should be eliminated", "[Group] are subhuman"],
        "block"
    ),
    ModerationCategory(
        "harassment", "Personal attacks and bullying",
        ["You're worthless", "Nobody likes you", "Go away loser"],
        "warn"
    ),
    ModerationCategory(
        "misinformation", "False health or safety claims",
        ["Vaccines cause autism", "5G causes COVID", "Drink bleach to cure disease"],
        "label"
    ),
]

multi_moderator = MultiCategoryModerator(encoder, categories)
action, flagged = multi_moderator.get_action("Amazing offer! Click now for free prizes!")
print(f"Action: {action}, Flagged categories: {flagged}")
Action: allow, Flagged categories: []

26.7.4 Context-Aware Moderation

The same words mean different things in different contexts. Embedding-based systems can incorporate context:

Show Context-Aware Moderator
from dataclasses import dataclass
from typing import Optional, Tuple
import numpy as np


@dataclass
class ContentContext:
    """Context for content being moderated."""
    platform: str  # 'gaming', 'professional', 'kids', etc.
    content_type: str  # 'chat', 'post', 'comment', 'review'
    user_history_score: float  # 0-1, prior violations
    thread_topic: Optional[str] = None


class ContextAwareModerator:
    """Moderation that considers context."""

    def __init__(self, encoder, base_moderator):
        self.encoder = encoder
        self.base_moderator = base_moderator

        # Context-specific thresholds
        self.platform_thresholds = {
            'kids': 0.5,       # Very strict
            'professional': 0.6,
            'general': 0.7,
            'gaming': 0.8,     # More lenient for competitive language
            'adult': 0.85,
        }

    def moderate_with_context(self, content: str, context: ContentContext) -> Tuple[str, float, str]:
        """
        Moderate content considering context.

        Returns: (decision, confidence, explanation)
        """
        # Get base moderation score
        base_decision, category, confidence = self.base_moderator.moderate(content, threshold=0.5)

        # Adjust threshold based on platform
        threshold = self.platform_thresholds.get(context.platform, 0.7)

        # Stricter for users with violation history
        if context.user_history_score > 0.5:
            threshold -= 0.1

        # More lenient for certain content types
        if context.content_type == 'review' and category == 'spam':
            threshold += 0.1  # Reviews often have promotional language

        # Make decision with adjusted threshold
        if confidence >= threshold:
            decision = 'block' if confidence > threshold + 0.15 else 'review'
            explanation = f"Flagged as {category} (score: {confidence:.2f}, threshold: {threshold:.2f})"
        else:
            decision = 'allow'
            explanation = f"Below threshold (score: {confidence:.2f}, threshold: {threshold:.2f})"

        return decision, confidence, explanation


# Example usage
context_moderator = ContextAwareModerator(encoder, moderator)

# Same content, different contexts
content = "You're going down! I'll destroy you!"

gaming_context = ContentContext(platform='gaming', content_type='chat', user_history_score=0.0)
kids_context = ContentContext(platform='kids', content_type='chat', user_history_score=0.0)

gaming_result = context_moderator.moderate_with_context(content, gaming_context)
kids_result = context_moderator.moderate_with_context(content, kids_context)

print(f"Gaming platform: {gaming_result[0]} - {gaming_result[2]}")
print(f"Kids platform: {kids_result[0]} - {kids_result[2]}")
Gaming platform: allow - Below threshold (score: 0.08, threshold: 0.80)
Kids platform: allow - Below threshold (score: 0.08, threshold: 0.50)
TipContent Moderation Best Practices

System Design:

  • Layered approach: Fast embedding filter → detailed classifier → human review queue
  • Category-specific models: Train separate models for spam, hate speech, harassment, etc.
  • Continuous updates: Add new violation examples as patterns evolve
  • Appeal workflows: Allow users to contest decisions with human review

Threshold Tuning:

  • Context-aware thresholds: Stricter for kids platforms, more lenient for adult spaces
  • User reputation: Lower thresholds for repeat offenders
  • Content type: Reviews vs chats vs posts have different norms
  • A/B testing: Measure impact of threshold changes on false positive/negative rates

Scale Considerations:

  • Pre-filter with fast models: Use lightweight embeddings for initial screening
  • Batch processing: Embed content in batches for throughput
  • Caching: Cache embeddings for frequently reported content
  • Distributed review: Route flagged content to appropriate review teams

Avoiding Bias:

  • Diverse training data: Ensure examples cover different dialects, languages, cultures
  • Regular audits: Check for disparate impact across user demographics
  • False positive analysis: Track which groups are disproportionately affected
  • Human-in-the-loop: Human review for edge cases prevents systematic errors

26.7.5 Industry Applications of Content Moderation

  • Social Media: Post and comment moderation, hate speech detection, misinformation labeling
  • E-commerce (Chapter 31): Fake review detection, prohibited item listings, seller fraud
  • Gaming: Chat moderation, toxic behavior detection, cheating communication
  • Enterprise: Internal communications compliance, data loss prevention, policy violations
  • Education: Student safety, bullying detection, inappropriate content in learning platforms

26.8 Key Takeaways

  • Cybersecurity threat hunting with embeddings detects zero-day attacks: Unlike classifiers limited to known attack patterns, embedding-based systems identify “behavior unlike anything normal,” enabling detection of novel threats without prior examples

  • Behavioral anomaly detection learns per-entity baselines: Sequential models (LSTM, Transformer) over user/device event streams learn individual behavior patterns, flagging account compromise and insider threats through deviation from established patterns

  • Embedding-driven business rules replace brittle if-then logic: Case-based reasoning retrieves similar historical cases and applies their outcomes, adapting automatically as new cases arrive without retraining, while hybrid systems enforce hard regulatory constraints alongside learned patterns

  • These patterns apply universally across all industries: Every organization faces cyber threats, has users whose behavior should be monitored, and makes decisions that can benefit from embeddings—subsequent industry chapters build on these foundations

  • Online learning is critical for production systems: Attackers evolve tactics, user behavior changes, business conditions shift—systems must incrementally update embeddings and thresholds to avoid degrading accuracy over time

  • Explainability enables adoption: High false positive rates create user friction and alert fatigue, requiring feature attribution to help analysts understand anomalies and progressive authentication to balance security and usability

  • Customer support intelligence transforms unstructured interactions into actionable data: Semantic routing matches tickets to agents based on meaning rather than keywords, while knowledge retrieval surfaces relevant solutions from historical resolutions and documentation

  • Competitive intelligence scales through embedding-based monitoring: Trend detection identifies emerging clusters in news and patent filings, while competitor tracking measures strategic shifts through embedding trajectory analysis across millions of documents

  • Document classification enables automated compliance at scale: Embedding similarity to labeled exemplars provides consistent classification across billions of documents, with automated retention policies and semantic search for e-discovery reducing legal risk and review costs

  • Content moderation with embeddings catches semantic violations that keywords miss: Similarity-based detection flags harmful content regardless of spelling variations or phrasing, while context-aware thresholds balance user experience across different platforms and content types

26.9 Looking Ahead

The next chapter, Chapter 27, covers another critical cross-industry application: video surveillance and analytics—from retail loss prevention to smart city safety to industrial compliance monitoring—generating more embedding vectors than almost any other domain.

Following video surveillance, Chapter 28 addresses a fundamental cross-industry challenge: identifying and linking records that refer to the same real-world entities across disparate data sources—a problem that scales to trillions of comparison pairs.

The remaining chapters in Part V explore industry-specific applications:

  • Chapter 29 applies these patterns to trading, credit risk, and regulatory compliance
  • Chapter 30 addresses patient safety, clinical decision support, and medical data security
  • Chapter 31 covers dynamic pricing, inventory optimization, and customer journey analysis
  • Chapter 32 explores quality control, predictive maintenance, and supply chain optimization

26.10 Further Reading

26.10.1 Cybersecurity and Threat Detection

  • Sommer, Robin, and Vern Paxson (2010). “Outside the Closed World: On Using Machine Learning for Network Intrusion Detection.” IEEE S&P.
  • Tuor, Aaron, et al. (2017). “Deep Learning for Unsupervised Insider Threat Detection in Structured Cybersecurity Data Streams.” AAAI Workshop.
  • Ding, Kaize, et al. (2019). “Deep Anomaly Detection on Attributed Networks.” SDM.
  • Yuan, Shuhan, et al. (2019). “Insider Threat Detection with Deep Neural Network.” CODASPY.

26.10.2 Behavioral Anomaly Detection

  • Xu, Ke, et al. (2018). “Show, Attend and Tell: Neural Image Caption Generation with Visual Attention Applied to Insider Threat Detection.” Journal of Wireless Mobile Networks.
  • Das, Sanmitra, et al. (2019). “Online Multimodal Deep Similarity Learning with Application to Insider Threat Detection.” ACM TOPS.
  • Legg, Philip A., et al. (2015). “Automated Insider Threat Detection System Using User and Role-Based Profile Assessment.” IEEE Systems Journal.
  • Liu, Lin, et al. (2018). “GEM: Graph Embedding for Insider Threat Detection.” IEEE BigData.

26.10.3 Automated Decision Systems

  • Brynjolfsson, Erik, and Andrew McAfee (2017). “The Business of Artificial Intelligence.” Harvard Business Review.
  • Kleinberg, Jon, et al. (2018). “Human Decisions and Machine Predictions.” Quarterly Journal of Economics.
  • Mullainathan, Sendhil, and Jann Spiess (2017). “Machine Learning: An Applied Econometric Approach.” Journal of Economic Perspectives.

26.10.4 Explainability and Fairness

  • Lundberg, Scott M., and Su-In Lee (2017). “A Unified Approach to Interpreting Model Predictions.” NeurIPS.
  • Ribeiro, Marco Tulio, Sameer Singh, and Carlos Guestrin (2016). “Why Should I Trust You? Explaining the Predictions of Any Classifier.” KDD.
  • Mehrabi, Ninareh, et al. (2021). “A Survey on Bias and Fairness in Machine Learning.” ACM Computing Surveys.