AI 辅助的交互热力图预测:从布局到用户行为的建模

cover

一、用户行为的"不可见性":上线前如何预判交互热点

UI 设计评审中,"用户会点击哪里"是最常被争论却最难回答的问题。设计师凭直觉判断视觉焦点,产品经理凭经验推断操作路径,但真实用户行为往往出乎意料——精心设计的 CTA 按钮被忽视,角落的次要链接反而点击密集。传统做法是上线后通过埋点收集热力图数据,但此时修改成本已大幅上升。如果能在设计稿阶段预测用户的注意力和交互分布,就能在开发前优化布局,避免上线后的返工。

二、视觉注意力模型与交互预测原理

2.1 从视觉显著性到交互热力图

flowchart TB
    A[UI 设计稿] --> B[视觉特征提取]
    B --> C[底层特征<br/>颜色/亮度/边缘]
    B --> D[高层特征<br/>文字/图标/人脸]
    C --> E[显著性图生成]
    D --> E
    E --> F[交互概率建模]
    F --> G[历史行为数据<br/>(训练集)]
    G --> F
    F --> H[交互热力图预测]
    H --> I[设计优化建议]

    subgraph 模型架构
        J[视觉编码器<br/>ViT/ResNet] --> K[特征金字塔]
        K --> L[交互概率头<br/>Pixel-wise Sigmoid]
    end

    B --> J

2.2 视觉显著性计算的基础方法

import numpy as np
from PIL import Image

def compute_saliency_map(image: Image.Image) -> np.ndarray:
    """基于频域分析的视觉显著性计算(Itti-Koch 简化版)"""
    img = np.array(image.convert('RGB')).astype(np.float64)

    # 多尺度高斯金字塔
    saliency = np.zeros(img.shape[:2])
    for scale in [2, 4, 8]:
        # 下采样再上采样,提取低频成分
        h, w = img.shape[:2]
        small = Image.fromarray(img.astype(np.uint8)).resize(
            (w // scale, h // scale), Image.BILINEAR
        )
        low_freq = np.array(small.resize((w, h), Image.BILINEAR)).astype(np.float64)

        # 高频残差 = 原图 - 低频(显著区域在高频残差中突出)
        residual = np.abs(img - low_freq)
        saliency += np.mean(residual, axis=2)

    # 归一化到 [0, 1]
    saliency = (saliency - saliency.min()) / (saliency.max() - saliency.min() + 1e-8)
    return saliency

三、AI 驱动的交互热力图预测方案

3.1 基于 ViT 的端到端预测模型

import torch
import torch.nn as nn
from torchvision.models import vit_b_16

class InteractionHeatmapModel(nn.Module):
    """基于 Vision Transformer 的交互热力图预测模型"""

    def __init__(self, pretrained: bool = True):
        super().__init__()

        # 使用 ViT 作为视觉编码器
        self.encoder = vit_b_16(pretrained=pretrained)
        embed_dim = 768

        # 移除分类头,保留特征提取
        self.encoder.heads = nn.Identity()

        # 解码器:将 patch 特征上采样为像素级热力图
        self.decoder = nn.Sequential(
            nn.ConvTranspose2d(embed_dim, 256, kernel_size=4, stride=4),
            nn.BatchNorm2d(256),
            nn.ReLU(),
            nn.ConvTranspose2d(256, 64, kernel_size=4, stride=4),
            nn.BatchNorm2d(64),
            nn.ReLU(),
            nn.Conv2d(64, 1, kernel_size=3, padding=1),
            nn.Sigmoid(),
        )

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        # x: [B, 3, 224, 224]
        B = x.shape[0]

        # 提取 patch 特征
        features = self.encoder(x)  # [B, 768]

        # 重塑为空间特征图
        # ViT 输出 14x14 patches,每个 patch 768 维
        features = features.reshape(B, 14, 14, -1).permute(0, 3, 1, 2)

        # 解码为热力图
        heatmap = self.decoder(features)  # [B, 1, 224, 224]
        return heatmap

3.2 训练数据构建:从埋点到标注

import json
from pathlib import Path

class HeatmapDatasetBuilder:
    """从埋点数据构建训练数据集"""

    def __init__(self, raw_data_dir: str, output_dir: str):
        self.raw_dir = Path(raw_data_dir)
        self.output_dir = Path(output_dir)

    def build(self):
        """将原始点击数据转换为热力图标注"""
        self.output_dir.mkdir(parents=True, exist_ok=True)

        for page_dir in self.raw_dir.iterdir():
            if not page_dir.is_dir():
                continue

            # 读取页面截图
            screenshot = Image.open(page_dir / "screenshot.png")
            w, h = screenshot.size

            # 读取点击坐标数据
            clicks = json.loads((page_dir / "clicks.json").read_text())

            # 生成高斯核热力图
            heatmap = np.zeros((h, w), dtype=np.float32)
            for click in clicks:
                x, y = click["x"], click["y"]
                # 以点击位置为中心添加高斯核
                sigma = 20  # 像素级扩散范围
                for dy in range(-3 * sigma, 3 * sigma + 1):
                    for dx in range(-3 * sigma, 3 * sigma + 1):
                        px, py = x + dx, y + dy
                        if 0 <= px < w and 0 <= py < h:
                            heatmap[py, px] += np.exp(
                                -(dx**2 + dy**2) / (2 * sigma**2)
                            )

            # 归一化
            heatmap = heatmap / (heatmap.max() + 1e-8)

            # 保存
            np.save(self.output_dir / f"{page_dir.name}_heatmap.npy", heatmap)
            screenshot.save(self.output_dir / f"{page_dir.name}_screenshot.png")

3.3 设计优化建议生成

@dataclass
class DesignSuggestion:
    """设计优化建议"""
    region: tuple          # (x, y, w, h) 建议区域
    issue: str             # 问题描述
    suggestion: str        # 优化建议
    confidence: float      # 置信度

def analyze_heatmap_for_design(
    heatmap: np.ndarray,
    ui_regions: list,
    threshold_high: float = 0.7,
    threshold_low: float = 0.15,
) -> list:
    """分析热力图并生成设计优化建议"""
    suggestions = []

    for region in ui_regions:
        name, x, y, w, h = region['name'], *region['bbox']
        region_heat = heatmap[y:y+h, x:x+w]
        avg_heat = np.mean(region_heat)

        if region['type'] == 'cta' and avg_heat < threshold_low:
            suggestions.append(DesignSuggestion(
                region=(x, y, w, h),
                issue=f"CTA 按钮 '{name}' 注意力不足(热力值 {avg_heat:.2f})",
                suggestion="增大按钮尺寸、提升对比度或调整位置至视觉焦点区域",
                confidence=0.85,
            ))

        elif region['type'] == 'navigation' and avg_heat > threshold_high:
            suggestions.append(DesignSuggestion(
                region=(x, y, w, h),
                issue=f"导航项 '{name}' 注意力过高(热力值 {avg_heat:.2f})",
                suggestion="检查是否误引用户注意力,考虑降低视觉权重",
                confidence=0.78,
            ))

        elif region['type'] == 'decoration' and avg_heat > 0.4:
            suggestions.append(DesignSuggestion(
                region=(x, y, w, h),
                issue=f"装饰元素 '{name}' 吸引了过多注意力",
                suggestion="降低装饰元素的对比度或饱和度,减少视觉干扰",
                confidence=0.72,
            ))

    return suggestions

四、边界分析与架构权衡

4.1 预测精度与页面类型的关联

模型在常规着陆页(单一 CTA、清晰层级)上的预测准确率可达 80%+,但在复杂仪表盘(多区域、多操作)上降至 50%-60%。原因在于仪表盘的交互行为受用户角色和任务上下文影响极大,纯视觉特征无法捕捉这些高层语义。

4.2 跨平台泛化能力

模型在桌面端截图上训练后,对移动端截图的预测精度显著下降。移动端的交互模式(滑动、长按)与桌面端(点击、悬停)差异大,热力图分布模式不同。需要为不同设备类型训练独立模型或添加设备类型条件。

4.3 隐私与数据合规

训练数据中的用户点击坐标可能包含敏感信息(如点击了个人资料区域)。数据采集时需脱敏处理——只保留相对坐标,不记录页面 URL 和用户 ID,确保无法反推个人行为。

4.4 实时推理的延迟约束

设计工具集成场景要求实时预览(<500ms 延迟),但 ViT-B 模型的单次推理约需 150ms(GPU)或 800ms(CPU)。轻量化方案包括:使用 MobileViT 替代 ViT-B,或采用知识蒸馏将大模型能力迁移到小模型。

五、总结

AI 辅助的交互热力图预测,将用户行为分析从"上线后验证"提前到"设计稿阶段预判"。基于 ViT 的端到端模型从 UI 截图预测像素级交互概率分布,结合高斯核热力图标注和埋点数据构建训练集。预测结果可自动生成设计优化建议——CTA 注意力不足、装饰元素过度吸引、导航权重失衡等问题在设计阶段即可发现。工程实践中需注意复杂页面类型的精度下降、跨平台泛化限制、隐私合规和实时推理延迟。该方案最适合作为设计评审的辅助工具,而非替代用户测试。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐