逐水寻源

欢迎来到逐水寻源,这是个人技术博客,汇聚了我在计算机技术、数据科学和人工智能等领域的学习与实践。从编程技巧到算法解析,从数据分析到机器学习项目,从技术知识到个人成长故事,这里有丰富的内容等待你的探索。让我们一起学习,一起成长,解锁技术世界的无限可能!

个人数据低成本自动化备份方案

我们的生活和工作越来越依赖于各种数据。从重要的工作文档到珍贵的个人照片,这些数据承载着我们的记忆和价值。然而,硬件故障、系统崩溃、恶意软件攻击等风险随时可能导致数据丢失。本文将介绍一套基于Rclone和云盘的低成本个人数据备份方案,能够有效保护这些个人数据。 1 数据备份的目的 生活中充满各种可能导致数据丢失的意外情况。硬件故障是最常见的原因之一,硬盘的平均使用寿命有限,SSD通常可靠使用3-5年。系统错误也是数据丢失的常见原因,特别是操作系统更新失败可能导致文件系统损坏。此外,恶意软件如勒索病毒可能加密你的所有文件,人为错误可能导致重要文件被误删除或覆盖,如果设备丢失或被盗则可能同时失去物理设备和设备上的数据。甚至有时候某些软件服务进行一次大更新,都有可能导致数据损坏。 想象一下,当你的笔记本电脑突然无法开机,或者重要文件被误删,如果没有备份,你可能需要花费数小时甚至数天来重新安装系统、配置环境和重建文件。有了完善的备份方案,你可以在短时间内恢复到之前的工作状态,最大限度减少生产力损失。 2 个人数据分类 低成本不仅是金钱成本,更是管理成本。在设计备份方案前,我们需要先明确有哪些数据需要备份。下表列出了常见的个人数据类型及其特点: 数据类型 包含内容 重要性 更新频率 备份难度 软件配置 IDE设置、终端配置(.bashrc)、应用程序设置、服务程序配置 中 低 低 程序数据 数据库文件、应用程序生成的数据、游戏存档 中-高 中 中 媒体文件 音乐、电影、视频、播客 低-中 低 高(体积大) 代码和文档 项目源代码、技术文档、学习笔记、论文 高 高 低 个人照片和视频 家庭照片、旅行视频、生活记录 极高 中 中-高 社交媒体数据 微信聊天记录、其他社交平台内容 高 高 高 不同类型的数据价值和可替代性各不相同,因此备份策略也应有所区别。例如,软件配置和代码可以通过Git进行版本控制和备份,而个人照片等不可替代的数据则需要更严格的备份机制。在规划备份方案时,应该把成本优先分配给那些重要性高、难以重建的数据。 3 数据备份原则 高效的备份方案应遵循几个核心原则。首先是广为人知的3-2-1备份策略:保留至少3份数据副本,使用至少2种不同的存储媒介(如本地硬盘和云存储),并确保至少1份备份存储在异地(防止火灾、洪水等物理灾害)。这一策略为数据提供了多层保护,即使在最坏的情况下也能保证数据安全。 自动化是另一个重要原则。人工备份容易被遗忘或拖延,特别是在工作繁忙的时期。通过设置自动化备份流程,可以确保备份按计划进行,减少人为因素的干扰。理想的备份系统应该是"设置一次,长期运行",只需偶尔检查确认备份状态。 定期验证备份的完整性和可恢复性是保障数据安全的关键步骤。备份数据如果无法恢复就毫无意义。至少每季度应进行一次恢复测试,确保在需要时能够成功恢复数据。这种测试不仅验证了备份的有效性,还能让你熟悉恢复流程,在真正需要恢复时不会手忙脚乱。 对于重要数据,还需要适当的冗余备份。不同重要级别的数据可以有不同的备份策略。最重要的个人数据,如家庭照片或关键文档,就需要多个备份副本;而容易重新获取的数据,如可重新下载的媒体文件,则可以采用较为简单的备份策略,甚至使用流媒体而不备份。 4 基于Rclone和云盘的低成本数据备份方案 本文结合开源工具 Rclone 和 Alist, 利用各类云存储服务,构建一套自动化、安全且经济实惠的个人数据备份系统。Rclone是一款功能强大的命令行工具,可以同步本地文件到多种云存储服务,并提供加密功能保护数据隐私;Alist则起到对Rclone的补充作用,很多网盘和存储源无法直接使用Rclone挂载,就需要通过Alist挂载为Webdav。结合适当的脚本和定时任务,我们就可以实现全自动的备份流程。 4.1 方案概述 在这套方案中,软件配置和代码将通过Git进行版本控制和备份,这是因为Git天然适合跟踪这类文本文件的变化,并提供完整的历史记录。而对于其他类型的个人数据,如文档、照片和媒体文件,我们将使用Rclone同步到加密的云存储。备份频率和副本数量可以根据数据重要性灵活调整,确保最重要的数据得到最全面的保护。 比如就我个人而言,配置和代码使用Github和Gitlab,文档和媒体使用Notion,程序数据以中频率备份到国内和国外的三个不同网盘上,个人照片则以低频率再额外备份到亚马逊云的对象存储AWS S3上(3网盘 + 1 OSS + 1 照片服务器 + 若干拍摄设备, 一份照片至少存了6份 😢)。 这个方案的核心优势在于低成本、高安全性和自动化程度高。只要选择合适的云存储提供商(如Google Drive的教育优惠、 微软E5账号、 路边捡的对象存储),成本可以控制在较低水平;通过Rclone的加密功能,数据在云端存储时始终保持加密状态,既能保护数据隐私,也可以避免因为触碰国内网盘奇怪的规则而被封号;通过脚本和定时任务,备份过程完全自动化,无需人工干预。 4.2 需求确认 在实施方案前,我们先明确具体需求。本备份方案将直接备份源目录中的文件,而不是创建压缩包,这样方便随时查看和恢复单个文件。备份策略采用每月全量备份,每周增量备份,并滚动保留3个全量副本,平衡了存储空间和数据安全。为了支持多设备环境,远程路径将包含主机名和源目录名称,便于识别不同设备的备份。 使用Rclone的--backup-dir功能,可以将删除或覆盖的文件存档到专门的目录(如deleted_时间戳),并自动清理这些存档,只保留最近3个。这样既能恢复误删的文件,又不会无限制占用存储空间。最后,通过Webhook通知机制,可以通过微信实时了解备份状态,包括常规通知(开始、成功、结束)和异常通知(备份失败或意外中断)。 4.3 方案设计 4.4 安装与配置Rclone 首先需要安装Rclone并进行基本配置。在大多数Linux系统上,可以通过包管理器安装: 1 2 3 4 5 # 安装Rclone sudo apt install rclone # 配置Rclone(交互式) rclone config 在配置过程中,需要设置两个远程存储:一个直接连接到云存储服务(如Google Drive),另一个在此基础上添加加密层。这种加密远程的设置确保即使云服务提供商可以访问你的文件,也无法查看文件内容,有效保护个人隐私。 Rclone的配置过程是交互式的,需要按照提示输入相关信息,包括选择云存储提供商、授权访问、设置加密密码等。比如要连接Alist,就选择webdav驱动,具体步骤可参考官方文档或相关教程。完成配置后,可以通过简单的命令测试连接是否正常: 1 2 rclone lsd gdrive: rclone lsd gdrive-crypt: 4.5 备份脚本 核心的备份功能由一个名为backup_files_with_backup_dir_cleanup.sh的脚本实现。该脚本负责同步本地文件到云存储,管理备份历史,并发送状态通知。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 #!/bin/bash ##### 配置区域 ##### REMOTE="gdrive-crypt:" WEBHOOK_KEY1="693axxx6-7aoc-4bc4-97a0-0ec2sifa5aaa" # 常规通知 Key WEBHOOK_KEY2="another-key-for-errors-xxx" # 异常通知 Key # 需要备份的源目录 SOURCE_DIRS=( "/etc/nginx" "/var/lib/mysql" "/home/user/docs" "/home/user/photos" "/var/lib/docker" ) ##### 结束配置区域 ##### TIMESTAMP=$(date +%Y%m%d_%H%M%S) HOSTNAME=$(hostname) # 获取当前主机名 LOG_FILE="backup_${HOSTNAME}_$TIMESTAMP.log" # 发送 Webhook 通知函数(企业微信格式) send_webhook() { local key="$1" local status="$2" local message="$3" local url="<https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=$key>" curl "$url" \\ -H 'Content-Type: application/json' \\ -d "{\\"msgtype\\": \\"text\\", \\"text\\": {\\"content\\": \\"[$status] $message on $HOSTNAME at $TIMESTAMP\\"}}" \\ 2>>"$LOG_FILE" } # 异常退出处理(使用 Key2) trap 'send_webhook "$WEBHOOK_KEY2" "ERROR" "Backup aborted unexpectedly"; exit 1' ERR INT TERM # 开始备份(使用 Key1) send_webhook "$WEBHOOK_KEY1" "START" "Backup process started" echo "Backup started at $(date) on $HOSTNAME" > "$LOG_FILE" # 检查是否为月初(全量备份) DAY=$(date +%d) if [ "$DAY" -le 7 ]; then # 第一周视为月初 BACKUP_TYPE="full" echo "Performing full backup on $HOSTNAME..." >> "$LOG_FILE" else BACKUP_TYPE="incremental" echo "Performing incremental backup on $HOSTNAME..." >> "$LOG_FILE" fi # 遍历源目录并上传文件 for dir in "${SOURCE_DIRS[@]}"; do dir_name=$(basename "$dir") # 获取源目录的最后一级名称 backup_name="${BACKUP_TYPE}_$TIMESTAMP" remote_path="$REMOTE/$HOSTNAME/$dir_name/$backup_name" backup_dir="$REMOTE/$HOSTNAME/$dir_name/deleted_$TIMESTAMP" # 删除文件存档目录 # 同步文件到远程,使用 --backup-dir 存档删除/覆盖的文件 rclone sync "$dir" "$remote_path" \\ --progress \\ --log-file="$LOG_FILE" \\ --exclude "*.log" \\ --max-size 1G \\ --backup-dir "$backup_dir" # 检查同步结果 if [ $? -eq 0 ]; then echo "Synced $dir to $remote_path successfully (deleted files archived to $backup_dir)" >> "$LOG_FILE" else echo "Failed to sync $dir to $remote_path" >> "$LOG_FILE" send_webhook "$WEBHOOK_KEY2" "ERROR" "Failed to sync $dir_name" exit 1 fi # 滚动保留 3 个全量副本 FULL_BACKUPS=$(rclone lsf "$REMOTE/$HOSTNAME/$dir_name" | grep "^full_" | sort -r) FULL_COUNT=$(echo "$FULL_BACKUPS" | wc -l) if [ "$FULL_COUNT" -gt 3 ]; then DELETE_COUNT=$((FULL_COUNT - 3)) echo "$FULL_BACKUPS" | tail -n "$DELETE_COUNT" | while read -r old_backup; do rclone purge "$REMOTE/$HOSTNAME/$dir_name/$old_backup" 2>>"$LOG_FILE" echo "Deleted old full backup: $HOSTNAME/$dir_name/$old_backup" >> "$LOG_FILE" done fi # 滚动保留 3 个 deleted_* 目录 DELETED_DIRS=$(rclone lsf "$REMOTE/$HOSTNAME/$dir_name" | grep "^deleted_" | sort -r) DELETED_COUNT=$(echo "$DELETED_DIRS" | wc -l) if [ "$DELETED_COUNT" -gt 3 ]; then DELETE_COUNT=$((DELETED_COUNT - 3)) echo "$DELETED_DIRS" | tail -n "$DELETE_COUNT" | while read -r old_deleted; do rclone purge "$REMOTE/$HOSTNAME/$dir_name/$old_deleted" 2>>"$LOG_FILE" echo "Deleted old deleted directory: $HOSTNAME/$dir_name/$old_deleted" >> "$LOG_FILE" done fi done # 备份完成(使用 Key1) echo "Backup completed at $(date) on $HOSTNAME" >> "$LOG_FILE" send_webhook "$WEBHOOK_KEY1" "SUCCESS" "Backup completed successfully" send_webhook "$WEBHOOK_KEY1" "END" "Backup process finished" 脚本的主要功能包括: 使用Rclone同步本地文件到加密的云存储 将删除或覆盖的文件存档到特定目录 每月创建全量备份,用于长期保存 自动清理旧备份,只保留最近的几个版本 通过企业微信Webhook发送备份状态通知 详细记录备份过程,便于故障排查 将脚本设置为可执行并移动到系统路径: 1 2 chmod +x backup.sh sudo mv backup.sh /usr/local/bin/ 4.6 设置定时任务 通过crontab设置定时任务,实现备份自动化: 1 crontab -e 添加以下内容,设置每周日凌晨2点自动执行备份: 1 0 2 * * 0 /usr/local/bin/backup.sh 这样,备份过程就会定期自动执行,无需人工干预。时间选择在凌晨是为了避免备份过程影响正常使用,同时网络通常在这个时段比较空闲,有利于数据上传。如果系统在预定时间关机,可以考虑使用anacron代替cron,或者设置多个备份时间点增加冗余。 4.7 Webhook通知系统 通过Webhook通知系统,可以实时了解备份状态。以下是通知消息示例: 常规通知(使用Key1): 1 2 3 [START] Backup process started on node1 at 20250227_020000 [SUCCESS] Backup completed successfully on node1 at 20250227_020000 [END] Backup process finished on node1 at 20250227_020000 异常通知(使用Key2): 1 2 [ERROR] Failed to sync docs on node1 at 20250227_020000 [ERROR] Backup aborted unexpectedly on node1 at 20250227_020000 这些通知可以集成到各种平台,如Slack、Microsoft Teams、钉钉或自定义应用程序。通过区分常规通知和异常通知,可以更有针对性地处理备份问题,只有在出现异常时才需要人工干预。通知系统是备份方案的重要组成部分,它让备份过程变得透明,有助于及时发现和解决问题。 4.8 验证与恢复 备份系统最终目的是在需要时能够恢复数据。因此,定期验证备份并熟悉恢复流程是必不可少的。以下是常用的验证和恢复命令: 验证备份文件: 1 2 3 4 5 6 7 8 # 检查正常备份 rclone ls gdrive-crypt:/node1/docs/full_20250227_020000 # 检查删除存档 rclone ls gdrive-crypt:/node1/docs/deleted_20250227_020000 # 验证保留数量 rclone lsf gdrive-crypt:/node1/docs/ | grep "^deleted_" 恢复数据: 1 2 3 4 5 # 恢复正常文件 rclone copy gdrive-crypt:/node1/docs/full_20250227_020000 /tmp/restore # 恢复已删除文件 rclone copy gdrive-crypt:/node1/docs/deleted_20250227_020000 /tmp/restore_deleted 建议定期进行恢复测试,验证备份数据的完整性和可用性。这种测试不仅能确保在真正需要时可以成功恢复数据,还能让你熟悉恢复流程,防止遗忘。测试时可以选择恢复到临时目录,避免覆盖现有文件。 5 总结 本文介绍的基于Rclone和云盘的低成本数据备份方案,为个人用户提供了一种经济、安全且高效的数据保护策略。通过自动化备份流程、加密存储和多重备份,可以有效防止数据丢失,保护数字资产安全。 数据备份不是一劳永逸的工作,而是需要持续维护和改进的过程。定期检查备份状态,测试恢复过程,并根据数据变化调整备份策略,才能确保数据始终安全可靠。随着技术发展和需求变化,备份方案也应该不断演进和完善。 最后,没有完美的备份方案,但有最适合你需求的方案。比如为了快速恢复生产能力,系统级快照备份是更合适的方案,但这与本文低成本的理念不符,因此并未介绍。基于本文提供的框架,你可以根据自己的实际情况,定制专属的数据备份系统。在数字资产日益重要的今天,投入适当的时间和资源构建可靠的备份系统,是对自己数字生活的负责任态度。 你的数据,值得最好的保护。 6 参考资料 Rclone官方文档: https://rclone.org/docs/ 3-2-1备份策略: https://www.backblaze.com/blog/the-3-2-1-backup-strategy/ 数据备份最佳实践: https://www.cloudwards.net/backup-strategies/

2025/5/16
articleCard.readMore

异地组网:免域名免备案自建Tailscale DERP节点

无论是远程办公需要访问公司内网资源,还是想要在外出时轻松管理家中的设备,甚至只是想绕过NAT限制直接连接到另一台主机,异地组网都是一个理想的解决方案。本文将介绍一种不需要域名、无需备案的方法来建立自己的私有网络,特别适合国内环境下的技术爱好者和专业人士。 1 异地组网的目的与好处 想象这样一个场景:李华是一名开发者,他在家里有一台NAS用于娱乐,公司有一台性能强劲的PC作为开发环境,同时在云端租了一台服务器用于部署项目。他经常需要在星巴克充当气氛组或是出差时工作,使用的是一台环保的MacBook。如果没有异地组网,李华每次在外工作或访问家里的电脑,可能需要设置复杂的端口转发规则,担心家庭网络的安全性,还得记住不断变化的家庭IP地址。而想要在本地直接调试部署在云服务器上的应用,又必须开放服务器端口,增加了安全风险。 通过建立异地组网,李华只需要登录到私有网络,就像所有设备都在同一个局域网内一样。他可以从咖啡厅直接访问到NAS、开发环境,在笔记本上进行开发,然后无缝地部署到云服务器上。整个过程安全、高效,无需担心复杂的网络配置和安全风险。 异地组网为我们带来了多方面的好处:首先是便捷访问,无论身处何地,都能像在本地网络一样访问远程设备和服务;其次是保障了数据安全,通过加密通道传输数据,有效避免敏感信息在公共网络中泄露;同时,它能突破各种网络限制,绕过NAT、防火墙等障碍,实现真正的点对点连接;最后,它提供了统一管理的可能,让分散在不同地点的设备整合到一个虚拟网络中,便于集中管理和维护。 现代异地组网解决方案通常部署迅速,只需几分钟就能完成设置;提供低延迟体验,在良好的网络环境下几乎感受不到距离带来的延迟;且大多支持Windows、MacOS、Linux、iOS、Android等多种操作系统,让你的所有设备都能加入到这个私有网络中;更重要的是,它们简化了传统VPN的复杂配置,普通用户也能轻松上手使用。 2 异地组网的常见方案对比 市场上有多种异地组网解决方案,每种都有其独特的特点和适用场景。下面我们通过一个综合对比来了解几种主流方案: 方案 核心特点 优势 局限性 适用场景 Tailscale 基于WireGuard的P2P VPN 高性能、简单易用、支持P2P直连、开源核心组件 免费版设备数量有限(100个)、官方DERP中继在国内不稳定 个人使用、小型团队、需要高安全性的场景 ZeroTier 全球虚拟网络 灵活的网络拓扑、可创建多个网络、多平台支持 免费版设备数量有限(10个)、中继节点在国内不稳定、配置略复杂 需要复杂网络结构、多个虚拟网络的场景 FRP 反向代理工具 完全开源、灵活配置、无设备限制 非组网工具、需要公网服务器、配置复杂 特定服务端口转发、内网穿透 Cloudflare Tunnel 云端隧道服务 强大基础设施、不需公网IP、CDN加速 非P2P连接、主要针对Web服务、免费版功能有限 Web服务暴露、需要CDN加速的场景 虽然表格提供了直观的对比,但选择合适的方案还需结合具体使用场景进行考量。对于追求简单易用且希望建立真正点对点连接的用户,Tailscale通常是最佳选择。它简化了传统VPN的复杂性,同时保留了高性能和安全性。ZeroTier则适合那些需要构建更复杂网络拓扑的用户,它提供了更多的网络结构定制可能性。 如果您只是想解决特定应用的端口转发问题,FRP作为一个轻量级工具可能更为适合。而对于主要需要暴露Web服务的场景,特别是希望享受CDN加速的用户,Cloudflare Tunnel则提供了独特的优势。 就我个人而言,可以将上面的方案分为两类:前两者为SDN类,后两者为FRP类,两类正好是互补的关系。对于大多数情况,我的服务只需要在SDN类构建的局域网中访问即可;但对于某些特殊服务,还是需要Cloudflare Tunnel来打洞,即与他人分享的服务(正好Cloudflare Tunnel的鉴权访问做得非常完善)以及无root权限的机器。 在本文中,我们将重点探讨如何优化Tailscale在国内的使用体验,特别是通过自建DERP节点来提高连接质量,这对于国内用户来说是一个至关重要的改进。 3 Tailscale详解 Tailscale是近年来迅速崛起的新一代VPN解决方案,它巧妙地融合了传统VPN的安全性和P2P网络的直接连接优势,为用户提供了一种便捷、高效的异地组网方式。 3.1 什么是Tailscale? Tailscale本质上是一个基于WireGuard协议的网状VPN(Mesh VPN)服务,它将复杂的网络配置简化为几次点击操作。与传统VPN不同,Tailscale采用了分布式架构,大多数情况下可以实现直接的点对点连接,无需所有流量经过中心服务器。这种设计既提高了数据传输效率,又降低了服务器负载和中心节点故障的风险。例如在上面的拓扑图中,四个节点间可以实现两两(P2P)直连。 Tailscale的魅力在于它极致的简化理念。用户无需深入了解网络配置,也不需要固定IP地址或是复杂的防火墙规则设置,只需在设备上安装客户端并登录,就能自动加入到安全的私有网络中。这种"零配置"的体验使得即使是非技术背景的用户也能轻松使用。 3.2 Tailscale的工作原理 理解Tailscale的工作原理,需要先了解几个核心概念: WireGuard协议是Tailscale的基础,这是一个现代化的VPN协议,相比OpenVPN等传统方案,它代码量更小、性能更高、更易于审计。WireGuard提供了底层的加密通信能力,确保数据在传输过程中的安全性。 Tailscale采用了控制平面与数据平面分离的架构。控制平面负责设备认证、密钥交换、网络配置等管理功能,由Tailscale的服务器处理;而数据平面则负责实际的数据传输,尽可能地在设备间直接进行,无需经过中央服务器。 当两台设备需要通信时,Tailscale会首先尝试通过各种NAT穿透技术建立直接的P2P连接。这包括使用STUN协议发现设备的公网地址,以及尝试UDP打洞等技术。在大多数情况下,这些技术能够成功建立直接连接。 然而,在一些严格的网络环境下(如对称型NAT、企业防火墙、运营商级NAT等),直接的P2P连接可能无法建立。这时,Tailscale会退而求其次,使用DERP(Designated Encrypted Relay for Packets)服务作为数据中继。DERP是Tailscale开发的一种中继协议,它会在无法直连的情况下,帮助转发加密后的数据包。 3.3 Tailscale的优势与局限性 Tailscale凭借其独特的设计,在异地组网领域具有显著优势。首先是其卓越的性能表现,基于WireGuard协议,Tailscale比传统VPN解决方案如OpenVPN快得多,延迟更低,适合各种实时应用场景。其次是极简的用户体验,几分钟内就能完成全部配置,后续几乎零维护,大大降低了用户的使用门槛和运维成本。 安全性方面,Tailscale提供端到端加密,支持多种身份验证方式,包括与Google、Microsoft等身份提供商的集成,适合企业环境使用。跨平台支持也是Tailscale的一大亮点,它几乎支持所有主流操作系统,包括Windows、macOS、Linux、iOS、Android等,甚至还支持各种路由器固件如OpenWRT,让用户可以将所有设备纳入同一个私有网络。 然而,Tailscale也存在一些局限性。最突出的问题是官方DERP节点在国内连接不佳,由于众所周知的网络原因,官方提供的中继服务器在中国大陆地区的表现往往不尽如人意,影响了用户体验。此外,免费版本的设备限制(最多100台设备)对于个人用户通常足够,但对于较大规模的组织可能会成为制约。最后,一些高级功能如子网路由、多用户组织等需要付费计划支持,这也是使用Tailscale需要考虑的成本因素。 正是由于官方DERP节点在国内连接不佳的问题,自建DERP节点成为了提升国内Tailscale使用体验的关键解决方案,这也是本文接下来将重点讨论的内容。 4 自建Tailscale DERP节点 针对国内用户面临的最大问题——官方DERP节点连接不稳定,我们可以通过在国内服务器上自建DERP节点来解决。这种方法不需要域名和备案,只需要一台拥有公网IP的国内服务器,就能大大提升Tailscale在国内的使用体验。 4.1 DERP服务简介 DERP(Designated Encrypted Relay for Packets)是Tailscale专门开发的中继服务。当两台设备因为网络环境限制无法直接建立P2P连接时,DERP会作为中间人帮助转发加密数据包。这种情况常见于严格的NAT环境下,如校园网、移动网络、企业防火墙等场景。 需要强调的是,虽然DERP服务会中转数据,但这些数据在发送前已经被端到端加密,DERP服务器本身无法解密或查看数据内容,因此安全性不受影响。当然,使用DERP中继会增加一定的网络延迟,并受限于DERP服务器的带宽和地理位置。 默认情况下,Tailscale提供了遍布全球的DERP节点网络,包括美国、欧洲、亚洲多个地区,但遗憾的是没有中国大陆地区的节点。这导致国内用户在需要使用DERP中继时,往往需要连接到距离较远的节点,如香港、新加坡、日本等地,造成较高的延迟和不稳定的连接。 4.2 准备工作 在开始自建DERP节点前,您需要准备以下资源: 一台拥有公网IP的国内服务器,推荐配置至少1核2GB内存,带宽建议10Mbps以上,系统可以是常见的Linux发行版如Ubuntu、CentOS等。 服务器上已安装Docker和Docker Compose,这将极大简化我们的部署流程。如果尚未安装,可以参考Docker官方文档进行安装。 已注册的Tailscale账号,用于管理您的私有网络和DERP节点。 值得注意的是,虽然许多教程建议使用域名和SSL证书来部署DERP服务,但本文将介绍一种不需要域名和备案的简化方法,特别适合个人用户或小团队使用。 4.3 在DERP节点服务器上安装Tailscale客户端 首先,我们需要在服务器上安装Tailscale客户端。这一步骤至关重要,它是防止他人未经授权使用我们DERP节点的关键机制。由于DERP服务本身不验证客户端身份,我们需要借助Tailscale客户端的身份验证机制来实现访问控制。 在服务器上执行以下命令安装Tailscale客户端: 1 2 3 4 5 # 使用官方脚本安装Tailscale客户端 curl -fsSL https://tailscale.com/install.sh | sh # 登录Tailscale tailscale login 执行登录命令后,终端会显示一个URL链接。使用浏览器访问这个链接,按照提示完成身份验证流程。认证成功后,服务器就会成为您Tailscale网络中的一个节点。 您可以通过tailscale status命令验证登录状态,确保服务器已经成功连接到您的Tailscale网络。 4.4 使用Docker部署DERP服务 接下来,我们将使用yangchuansheng开发的Docker镜像来部署DERP服务。这个镜像封装了DERP服务的配置和运行环境,大大简化了部署过程。 首先,创建一个新的目录用于存放Docker配置文件: 1 mkdir -p ~/derp && cd ~/derp 然后,创建docker-compose.yml文件: 1 nano docker-compose.yml 将以下内容复制到文件中: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 services: derper: image: ghcr.io/yangchuansheng/ip_derper:latest container_name: derper restart: always ports: - "12345:12345" # 将12345改为您想使用的端口 - "3478:3478/udp" # STUN端口,建议保持不变 volumes: - /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock # 映射本地Tailscale客户端以验证连接 environment: - DERP_ADDR=:12345 # 与上面端口保持一致 - DERP_CERTS=/app/certs - DERP_VERIFY_CLIENTS=true # 防止未授权使用的关键参数 如果您的服务器在国内,可能会遇到拉取国外Docker镜像缓慢的问题,这时可以使用国内镜像源: 1 2 3 4 services: derper: image: ghcr.nju.edu.cn/yangchuansheng/ip_derper:latest # 其余配置保持不变 保存文件后,启动DERP服务: 1 docker compose up -d 通过查看容器日志,可以确认服务是否正常启动: 1 docker logs derper 如果看到类似"DERP server is up and running"的消息,说明服务已成功启动。 4.5 配置Tailscale使用自建DERP节点 现在,我们需要告诉Tailscale网络使用我们自建的DERP节点。这需要修改Tailscale的ACL(访问控制列表)配置。 登录Tailscale管理控制台:https://login.tailscale.com/admin/acls/file 在编辑器中,找到或添加derpMap部分,配置自建的DERP节点信息: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 { // 其他ACL配置... "derpMap": { "OmitDefaultRegions": false, // 设置为true可禁用官方DERP节点 "Regions": { "900": { "RegionID": 900, "RegionCode": "chn1", "RegionName": "China1", "Nodes": [ { "Name": "cn-derp1", "RegionID": 900, "IPv4": "1.2.3.4", // 替换为您服务器的公网IP "DERPPort": 12345, // 与docker-compose中配置的端口一致 "InsecureForTests": true // 使用自签名证书时需要设置为true } ] } } } } 注意事项: RegionID在900-999之间是预留给自定义DERP节点的,避免与官方节点冲突 RegionCode和RegionName可以自定义,建议使用有意义的名称 IPv4必须是服务器的公网IP地址 DERPPort必须与Docker配置中暴露的端口一致 InsecureForTests设置为true是因为我们使用了自签名证书 保存配置后,Tailscale控制面板会自动将新的DERP配置推送到所有连接的设备。这个过程可能需要几分钟时间,具体取决于设备数量和网络状况。 4.6 验证DERP节点是否工作 成功部署后,我们需要验证DERP节点是否正常工作。有两种主要的验证方法: 方法一:使用网络连接测试 在任何一台已连接到Tailscale网络的设备上,运行以下命令: 1 tailscale netcheck 这个命令会检测当前设备能够连接到哪些DERP节点,以及它们的延迟情况。在输出结果中,应该能看到我们自建的DERP节点信息,如果显示延迟数值(而不是超时),说明节点连接正常。 方法二:使用Ping测试 当两台设备无法直接建立P2P连接时,Tailscale会自动通过DERP节点中继流量。我们可以通过ping测试来验证: 1 tailscale ping 另一台设备的Tailscale IP 如果在输出中看到类似via DERP(cn-derp1)的信息,说明流量正在通过我们自建的DERP节点中继,证明配置成功。 我的测试结果如上图所示,左侧是使用自建服务器之前,右侧是使用自建中转节点之后。其中第一条命令的机器porser是国内异地,都是先中转再打洞成功,明显看到使用自建DERP节点后,中转的时间显著下降。第二条命令的测试机器nerd是美国节点,经过自建DERP中转甚至比直连更快。第三调命令显示我们的DERP节点(sh)延迟只有15ms,比之前官方提供的最近节点(70ms)有了显著提升。 在实际使用中,您可能会注意到,当两台设备位于不同的网络环境时(如一台在家庭网络,一台在移动网络),它们很可能会通过DERP节点通信。而当设备在同一网络环境时,Tailscale会尽可能建立直接的P2P连接,不使用DERP中继。 5 常见问题与解决方案 在部署和使用自建DERP节点的过程中,您可能会遇到各种问题。以下是一些常见问题及其解决方案: 问题:无法连接到DERP节点 这通常是由网络配置或服务器设置导致的。首先,检查服务器防火墙是否开放了DERP服务使用的端口(在我们的例子中是12345和3478/UDP)。大多数云服务商除了操作系统防火墙外,还有额外的安全组或网络ACL设置,确保这些也已正确配置。 其次,确认docker-compose.yml中的配置是否正确,特别是端口映射和环境变量设置。可以通过docker logs derper查看容器日志,寻找可能的错误信息。 最后,验证服务器上的Tailscale客户端是否正常登录,可以通过tailscale status命令查看。如果客户端未登录或状态异常,可能会导致DERP服务无法正常工作。 问题:连接DERP成功但设备之间无法通信 这种情况通常与Tailscale的访问控制设置有关。首先,检查ACL配置是否正确,确保相关设备有互相访问的权限。Tailscale的ACL功能非常强大,可能需要仔细检查是否有意外的访问限制规则。 其次,确认设备间的子网路由设置。如果涉及到访问设备所在的子网(而不仅是设备本身),需要在Tailscale客户端启用子网路由功能,并在ACL中授权相应的子网访问权限。 使用tailscale status命令可以查看当前网络中所有设备的连接状态,包括它们是否通过P2P直连或DERP中继通信。这有助于诊断具体的连接问题。 问题:DERP连接速度较慢 DERP中继的性能受多种因素影响,包括服务器硬件配置、网络带宽、地理位置等。如果发现连接速度不理想,可以考虑以下优化方案: 升级服务器配置,特别是网络带宽。DERP服务对CPU和内存要求不高,但带宽是关键因素,尤其是当多台设备同时通过中继通信时。 优化服务器的网络配置,如调整TCP/IP参数,开启BBR等拥塞控制算法,这可能会提高网络吞吐量。 如果条件允许,可以在不同地理位置或使用不同ISP的服务器上部署多个DERP节点,通过derpMap配置让Tailscale网络使用距离最近或延迟最低的节点。 问题:服务器重启后DERP服务不自动启动 确保Docker服务配置为开机自启动: 1 systemctl enable docker 同时,在docker-compose.yml中已经设置了restart: always参数,这应该能确保Docker容器在服务重启后自动启动。如果仍有问题,可以创建一个系统服务或启动脚本,确保在系统启动时自动启动DERP服务。 6 总结与展望 我们已经成功在国内环境下建立了自己的Tailscale DERP节点,而且不需要域名和备案,大大提升了Tailscale的使用体验。这种方案不仅适用于个人用户,也适合小型团队或企业内部使用,能够在保证数据安全的同时,提供稳定、高效的异地组网服务。 自建DERP节点的方案解决了国内用户使用Tailscale面临的最大痛点——官方DERP节点连接不稳定的问题。通过国内服务器中继,不仅大幅降低了网络延迟,还提高了连接的稳定性和可靠性,让Tailscale这款优秀的组网工具在国内环境下发挥出应有的价值。 展望未来,随着网络技术的不断发展,我们可能会看到更多适合国内环境的P2P连接解决方案。Tailscale本身也在不断改进NAT穿透技术,增强直接P2P连接的成功率。但在当前阶段,自建DERP节点仍然是解决Tailscale在国内使用问题的最佳方案之一。 值得一提的是,除了本文介绍的方法外,还有其他一些改进Tailscale使用体验的方式,如使用Headscale作为自托管的控制服务器,以进一步增强网络的自主性和定制性。对于有更高要求的用户,这些方案也值得探索。 最后,感谢开源社区的贡献,尤其是yangchuansheng开发的ip_derper项目,让自建DERP节点变得如此简单。 7 参考资料 Tailscale官方文档 yangchuansheng/ip_derper项目 Custom DERP Servers介绍 Tailscale安装指南

2025/2/26
articleCard.readMore

家庭网络配置:利用 Docker 在闲置笔记本上运行 OpenWRT 作为旁路由

通过 Docker 在闲置笔记本上运行 OpenWRT 作为旁路由,充分利用旧设备,提升家庭网络的可定制性和功能性。本文详细介绍了从零开始配置 Docker 环境、创建 macvlan 网络、运行 OpenWRT 容器,并进行网络配置的全过程。无论是去广告、科学上网,还是流量监控和 VPN 服务,都可以通过旁路由轻松实现。适合有一定 Linux 基础的用户,帮助你将闲置设备变身为强大的网络工具。 过年回家总想着折腾点什么,于是就瞄上了早已退休的19年拯救者。相信很多家庭都有闲置的笔记本电脑,性能尚可却一直闲置。如果希望充分利用这些设备,可以考虑将其改造成“旁路由”(又称“透明网关”或“旁挂路由”),将某些网络功能(如去广告、流量监控、VPN 等)卸载到这台机器上进行处理。但是,这么强大的一个X86平台,重新刷一个Openwrt系统太大材小用了,已经装了Ubuntu的它还可以有更多用处(All in BOOM)。如果不想大动硬件也不想重装系统,Docker 技术可以派上用场。通过在闲置笔记本上运行一个 OpenWRT 容器,就可以以旁路由的方式接管或旁路处理局域网的流量。 本文将介绍从零开始完成一套基本环境配置,包括: 检查和配置网络接口 创建 Docker macvlan 网络 拉取并运行 OpenWRT 镜像 进入容器进行简单网络配置 1 环境与思路 1.1 闲置笔记本电脑 需要一台可以正常联网的笔记本(最好有以太网口)。如果只有无线网卡,需要额外注意无线网卡桥接或 macvlan 可能受限。 笔记本的操作系统可以是任意 Linux 发行版(Ubuntu、Debian、CentOS、Arch Linux 等),只要能安装 Docker 即可。 1.2 Docker 环境 确保 Docker 可以正常启动和拉取镜像,如果不熟悉 Docker 的安装,可以参照 Docker 官方文档 或对应发行版社区的文档。如在大陆地区,可参照此处配置镜像。 1.3 旁路由思路 在传统路由器(或主路由)仍然负责 DHCP、主要 NAT 功能的前提下,让 OpenWRT 容器在笔记本上“旁路”处理网络中的其他功能,比如去广告、科学上网、流量分析等。 所有设备可以灵活选择是否需要使用旁路由,避免爆炸的时候网络异常或是增加家中长辈的用网成本。 为了让笔记本上运行的 OpenWRT 容器拥有和内网同网段的 IP,需要使用 macvlan 网络模式。 2 检查并配置网络接口 2.1 查看网卡信息 在 Linux 上,首先用 ifconfig 或 ip addr 命令查看网卡信息。以下示例输出里,重点关注无线网卡 wlp0s20f3、有线网卡 enp7s0 以及它们的 IP 地址: 1 ifconfig 1 2 3 4 5 6 wlp0s20f3: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500 inet 192.168.1.23 netmask 255.255.255.0 broadcast 192.168.1.255 ... enp7s0: ... ... 当然这只是我的设备情况,每个设备的网卡名称几乎都是不同的,需要自主根据IP地址、流量信息去确定,但大多数情况下,以太网卡的名称会以“e”开头,比如“eth0”或是我的“enp***“,后文中所有的代码中,记得把enp7s0替换成你的设备名称,你可以在此博客页面代码框的右上角点击编辑按钮后直接修改。 如果希望在有线网卡上使用 macvlan,一般会选择 enp7s0 作为 macvlan 的父接口(-o parent=enp7s0),因为无线网卡与 macvlan 配合往往有兼容性问题。 在少数情况下,如果只有无线网卡,可能需要通过其他方案来旁路,比如 TAP/TUN 方式或者路由策略转发等,macvlan 对 Wi-Fi 不够友好。 2.2 开启混杂模式 为了确保网卡可以截获所有流量进行分析或桥接,需要设置网卡的混杂模式。可通过以下命令启用: 1 sudo ip link set enp7s0 promisc on 或者对于无线网卡,如果想在 wlp0s20f3 上开启混杂模式,也可执行: 1 sudo ip link set wlp0s20f3 promisc on 注意:混杂模式一般只在需要检测或中转特定流量时才必需,不然可以不设。 3 创建 Docker macvlan 网络 macvlan 可以让容器拥有与物理机不同的 MAC 地址以及内网 IP,从而像独立设备一样接入到局域网中。 假设希望容器所在网段是 192.168.10.0/24,网关是 192.168.10.1(主路由器或管理网关,可以在当前联网的设备上查看详细信息)。 使用 macvlan 驱动创建一个名为 macnet 的网络,父接口是 enp7s0(以太网卡),具体命令如下: 1 2 3 4 5 docker network create -d macvlan \ --subnet=192.168.10.0/24 \ # 与网关在同一网段 --gateway=192.168.10.1 \ # 修改为路由器或者网关ip -o parent=enp7s0 \ # 修改为以太网卡名称 macnet 上述命令解析: -d macvlan 指定驱动类型为 macvlan。 --subnet=192.168.10.0/24 指定容器网络的子网。 --gateway=192.168.10.1 指定子网的网关地址,一般是主路由 IP。 -o parent=enp7s0 指明物理机将要桥接到的网卡接口,即上一步确定的以太网接口。 macnet 是给此网络取的名称。 务必确认主路由器所管理的网段是否与这里的 192.168.10.0/24 相兼容。如果家里的主路由器网段是 192.168.1.x,则可以将旁路由容器放到同一个网段,或者通过适当的路由配置让这两个网段互通。具体做法可以根据实际网络需求进行调整。 4 拉取并运行 OpenWRT 镜像 4.1 确认系统架构 先用一些命令查看当前系统是 x86_64、arm、arm64 等。OpenWRT 镜像一般会按架构分得比较细,确保选对镜像才能在容器内正常运行。以 Arch Linux 下查看命令为例: 1 arch 或 1 uname -m 假设输出为 x86_64,表示需要拉取 x86_64 架构的 OpenWRT Docker 镜像。 4.2 拉取 OpenWRT 镜像 在 Docker 仓库或阿里云镜像仓库可以查到一些第三方的 OpenWRT 镜像,例如 sulinggg/openwrt 或者其它定制镜像。这里以 registry.cn-shanghai.aliyuncs.com/suling/openwrt:x86_64 为例: 1 docker pull registry.cn-shanghai.aliyuncs.com/suling/openwrt:x86_64 拉取成功后,可以用 docker images 命令查看是否已经下载成功。 5 启动容器 以下命令将基于之前创建的 macnet 网络,并使容器拥有特权权限(--privileged)来访问更多系统特性: 1 2 3 4 5 6 7 sudo docker run --restart always \ --name openwrt \ -d \ --network macnet \ --privileged \ registry.cn-shanghai.aliyuncs.com/suling/openwrt:x86_64 \ /sbin/init 命令解析: --restart always:Docker 容器异常退出或系统重启后,自动重启容器。 --name openwrt:容器名称设置为 openwrt。 -d:后台运行容器。 --network macnet:使用先前创建的 macvlan 网络。 --privileged:给容器特权,可以支持更多底层操作,比如网络管理、挂载等。 registry.cn-shanghai.aliyuncs.com/suling/openwrt:x86_64:要运行的镜像名称。 /sbin/init:指定容器启动时运行的初始进程。 6 容器内网络配置 容器启动后,可以进入容器内部进行网络和服务配置。 6.1 进入容器 1 docker exec -it openwrt bash 这会在容器内部开启一个交互式 Shell,之后可以像在普通 Linux 主机上一样进行一些 OpenWRT 的配置。 6.2 编辑 OpenWRT 网络配置 OpenWRT 容器的网络配置文件在 /etc/config/network,和常见的 OpenWRT 路由器类似。可以使用 vim 或 vi 打开它: 1 vim /etc/config/network 可根据需求(WAN/LAN 设置、静态 IP、DHCP 等)进行修改。以一个简单的例子为参考(仅示意,需要具体修改): 1 2 3 4 5 6 7 config interface 'lan' option ifname 'eth0' option proto 'static' option ipaddr '192.168.10.2' option netmask '255.255.255.0' option gateway '192.168.10.1' option dns '192.168.10.1' 这里 lan 接口与 eth0 绑定,假设要给容器 IP 设为 192.168.10.2;网关就是 192.168.10.1。 这里配置的容器 IP 地址就是旁路由的 IP,所有步骤成功后,将上网设备的网关地址设为这个就能使用旁路由了 。 修改完成后,重启 OpenWRT 网络服务: 1 /etc/init.d/network restart 6.3 验证容器网络生效 重启网络后,可以在容器内再次查看 IP 信息: 1 ifconfig 或 1 ip addr 如果配置正确,应该能看到 eth0 或对应的网卡上有设定的 192.168.10.2 这样的 IP,并可以使用 ping 命令检测与网关或外网的连通性。 7 混杂模式服务(可选) 在机器重启后,之前设置的混杂模式会失效。如果要启动时自动启用混杂模式,可以通过以下步骤将其添加到启动参数中。 7.1 创建并配置 /etc/rc.local 首先,创建 /etc/rc.local 文件并赋予可执行权限: 1 2 sudo touch /etc/rc.local sudo chmod +x /etc/rc.local 然后,编辑 /etc/rc.local 文件,添加以下内容: 1 2 ip link set eth0 promisc on exit 0 7.2 创建并配置 rc-local.service 接下来,创建一个 systemd 服务文件 /etc/systemd/system/rc-local.service: 1 sudo vim /etc/systemd/system/rc-local.service 内容如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 [Unit] Description=/etc/rc.local Compatibility ConditionPathExists=/etc/rc.local After=network.target [Service] Type=forking ExecStart=/etc/rc.local start TimeoutSec=0 RemainAfterExit=yes [Install] WantedBy=multi-user.target 7.3 启用并启动服务 最后启用并启动 rc-local 服务: 1 2 3 sudo systemctl enable rc-local sudo systemctl start rc-local.service sudo systemctl status rc-local.service 8 将容器用作旁路由 旁路由原理:在家里现有的主路由器配置中,可以将特定设备或者某个 VLAN 的网关地址指向这个 OpenWRT 容器的 IP(如 192.168.10.2),或者在主路由上配置静态路由,将某些流量转给 OpenWRT 做高级处理。 常见用途:去广告(Adblock)、VPN 客户端、代理服务器、科学上网、流量监控等等都可以在这个 OpenWRT 容器上配置。 确保网络互通:如果笔记本通过 Wi-Fi 上网,就要留意物理网卡与 macvlan 之间的兼容问题;也要确保主路由、笔记本与旁路由容器处于同一个网段或路由可达。 功耗:启动Openwrt后,没流量时整机功耗13w,有下载流量时整机功耗约20w,功耗还是比较高,看来不宜在x86设备上长期使用。 9 故障排查 容器无网络:检查是否将 macvlan 父接口指定为正确的有线网卡;检查容器内 IP 与主路由网段是否冲突;检查物理网卡 IP 分配是否正确。 冲突:如果笔记本本身也在 192.168.10.x 网段分配了 IP,而给容器也设置了同网段的 IP,可能出现地址冲突。可以通过在物理机上把网卡 IP 与容器 IP 分离到不同网段,或通过给 Docker macvlan 指定一个子接口(ip link add 创建子接口)来避免冲突。 无法访问容器管理界面(LUCI):OpenWRT 默认可能没有开放或安装 Luci,如需 Web 管理界面,需要进入容器安装 luci,并检查防火墙设置。 无线网卡问题:如果只有 Wi-Fi 网卡想要使用 macvlan,通常会碰到兼容性障碍,可以尝试其他方式,如 TUN/TAP,或者额外配置一块 USB 网卡用作桥接。 10 总结 通过 Docker 在闲置笔记本上运行 OpenWRT 用作旁路由,可以在保留原路由器主要功能的同时,为家庭网络增添更多可定制化的高级网络服务。从此,可以随时在容器中添加功能模块(Adblock、代理、QoS、VPN、流量统计等),灵活扩展家庭网络能力。并且 Docker 容器使用和维护都相对简单,后续升级、迁移也更方便。 如果对网络的管理和性能优化有更高的要求,可以考虑直接在笔记本上安装类似 PVE(Proxmox VE)、ESXi 或者开源虚拟化平台,然后让 OpenWRT 以虚拟机方式运行。但对于大多数轻量应用场景,Docker + macvlan 已足够轻巧易用。 如果在实际操作中遇到更多问题,欢迎在评论区留下疑问或经验。

2025/1/21
articleCard.readMore

专家混合模型 (MoE) 详解:Mixtral 8X7B、DBRX 和 Deepseek-v2 的架构与应用

深入了解专家混合模型 (MoE) 的架构与工作原理,探索Mixtral 8X7B、DBRX 和 Deepseek-v2等热门MoE模型的应用与优势。通过Python实现MoE模型,并评估其在逻辑推理、摘要和实体提取等任务中的表现。 专家混合模型 (MoE) 这个概念在大型语言模型 (LLMs) 领域火了很久了。它不仅让模型的效率和可扩展性有了质的飞跃,还为处理复杂任务提供了新的思路。简单来说,MoE 模型就是把一个大模型拆分成多个小模型,每个小模型专注于特定的任务或数据类型。这样一来,模型在处理任务时,只需要激活相关的“专家”,而不需要整个模型都参与,从而大大节省了计算资源。 在本文中你将: 搞懂 MoE模型的基本架构和工作原理 了解几个热门的MoE模型,比如Mixtral 8X7B、DBRX 和 Deepseek-v2 通过Python代码在Google Colab上实现MoE模型 评估一个典型的MoE模型在逻辑推理、摘要和实体提取等任务上的表现 了解MoE模型在自然语言处理和代码生成等复杂任务中的优势和挑战 1 什么是专家混合模型 (MoE)? 现在的深度学习模型大多基于人工神经网络,这些网络由多个层组成,每一层包含很多“神经元”。每个神经元处理输入数据,进行简单的数学运算(比如激活函数),然后把结果传递给下一层。更高级的模型,比如 Transformer,引入了自注意力机制,能够捕捉数据中的复杂模式。 不过,传统的密集模型在处理每个输入时,整个网络都要参与计算,这会导致计算成本非常高。为了解决这个问题,Mixture of Experts (MoE) 模型采用了稀疏架构,只激活与当前任务相关的部分网络,也就是“专家”。这样一来,MoE 模型在处理复杂任务时,比如自然语言处理,消耗的计算资源就少了很多。 试想一下,在一个团队项目中,团队成员被分成多个小组,每个小组专注于不同的任务。MoE 模型的工作方式与此类似。它把一个复杂问题分解成多个子任务,每个子任务由专门的“专家”负责处理。 MoE 模型的主要优势有: 预训练速度更快:相比传统的密集模型,MoE 模型的预训练过程更加高效。 推理速度更快:即使参数数量相同,MoE 模型的推理速度也更快。 对 VRAM 需求较高:由于所有专家必须同时存储在内存中,MoE 模型对显存的需求较大。 MoE 模型由两个关键组件组成:专家(Experts),即专注于特定任务的小型神经网络;以及路由器(Router),它根据输入数据选择性地激活相关专家。这种选择性激活通过仅使用每个任务所需的专家来提高效率。 2 几个典型的 MoE 模型 近年来,MoE 模型在 AI 研究中备受关注,因为它能够在保持高性能的同时,高效扩展大型语言模型。其中,Mixtral 8x7B 是一个典型的例子,它采用了稀疏的专家混合架构。该模型只对每个输入激活其专家的子集,从而在实现与更大、完全密集模型相当的性能的同时,显著提高了效率。 接下来,我们来看看几个热门的 MoE 模型,并通过在 Google Colab 上使用 Ollama 进行 Python 实现,感受一下它们的魅力。 2.1 Mixtral 8X7B Mixtral 8X7B 的架构基于decoder-only的 Transformer。模型输入是一系列tokens,这些tokens被嵌入为向量,然后通过解码器层进行处理。输出是每个位置被某个单词占据的概率,从而实现文本填充和预测。 每个解码器层包含两个关键部分:一个注意力机制,用于整合上下文信息;以及一个稀疏专家混合 (SMOE) 部分,用于分别处理每个词向量。MLP 层是计算资源的消耗大头。SMOE 有多个层(“专家”)可用。对于每个输入,取最相关专家输出的加权和。因此,SMOE 层可以在计算成本相对较低的情况下学习复杂的模式。 模型的关键特性: 专家总数:8 激活的专家数量:2 解码器层数:32 词汇表大小:32000 嵌入大小:4096 每个专家的大小:56 亿参数,而不是 70 亿。剩余的参数(70亿 - 56亿)来自共用组件,如嵌入层、归一化层和门控机制。 激活参数总数:128 亿 上下文长度:32k tokens 在加载模型时,所有 448 亿(8*56 亿参数)必须加载(以及所有共享参数),但我们只需要使用 2×56 亿(128 亿)激活参数进行推理。 Mixtral 8x7B 在文本生成、理解、翻译、摘要、情感分析、教育、客户服务自动化、研究辅助等多个领域表现出色。其高效的架构使其成为跨多个领域的强大工具。 2.2 DBRX DBRX 由 Databricks 开发,是一个基于 Transformer 的decoder-only大型语言模型 (LLM),使用下一个标记预测(next-token prediction)进行训练。它采用细粒度的专家混合 (MoE) 架构,总参数为 1320 亿,其中每个输入激活 360 亿参数。它在 12 万亿个文本和代码数据上进行了预训练。与其他开源的 MoE 模型(如 Mixtral 和 Grok-1)相比,DBRX 粒度更细,使用了更多的小型专家。DBRX 有 16 个专家并选择 4 个,而 Mixtral 和 Grok-1 有 8 个专家并选择 2 个。 架构的关键特性: 细粒度专家:通常情况下,从标准 FFN 层过渡到专家混合 (MoE) 层时,只需多次复制 FFN 以创建多个专家。然而在细粒度专家的背景下,我们的目标是生成更多专家而不增加参数数量。为此,可以将单个 FFN 划分为多个段,每个段作为一个单独的专家。DBRX 采用细粒度的 MoE 架构,有 16 个专家,从中为每个输入选择 4 个专家。 该模型还采用了其他创新技术,如旋转位置编码 (RoPE)、门控线性单元 (GLU) 和分组查询注意力 (GQA)。 模型的关键特性: 专家总数:16 每层激活的专家数量:4 解码器层数:24 激活参数总数:360 亿 总参数数:1320 亿 上下文长度:32k tokens DBRX 模型在代码生成、复杂语言理解、数学推理和编程任务等用例中表现出色,特别是在需要高准确性和效率的场景中,如生成代码片段、解决数学问题以及对复杂提示提供详细解释。 2.3 Deepseek-v2 在 Deepseek-v2 的 MoE 架构中,利用了两个关键思想: 细粒度专家:将专家细分为更细的粒度,以实现更高的专家专业化和对知识的更准确获取。 共享专家:该方法侧重于指定某些专家作为共享专家,确保它们始终处于激活状态。这种策略有助于收集和整合适用于各种上下文的通用知识。 模型的关键特性: 总参数数:2360 亿 激活参数总数:210 亿 每层路由的专家数:160(其中选择 2 个) 每层共享专家数:2 每层激活的专家数:8 解码器层数:60 上下文长度:128k tokens 该模型在 8.1 万亿个tokens的庞大数据集上进行了预训练。 DeepSeek-V2 特别擅长进行对话,因此适用于聊天机器人和虚拟助手。该模型可以生成高质量的文本,因此适用于内容创作、语言翻译和文本摘要。该模型还可以高效地用于代码生成用例。 3 用 Python 实现 MoE 模型 MoE 模型是一种先进的机器学习模型,它动态选择不同的专家网络来处理不同的任务。接下来,我们来看看如何用 Python 实现 MoE 模型,并感受一下它的强大之处。 3.1 步骤1:安装所需的 Python 库 首先,我们需要安装一些必要的 Python 库: 1 2 3 4 5 !sudo apt update !sudo apt install -y pciutils !pip install langchain-ollama !curl -fsSL https://ollama.com/install.sh | sh !pip install ollama==0.4.2 3.2 步骤2:启用线程 接下来用threading来运行 Ollama 服务: 1 2 3 4 5 6 7 8 9 10 import threading import subprocess import time def run_ollama_serve(): subprocess.Popen(["ollama", "serve"]) thread = threading.Thread(target=run_ollama_serve) thread.start() time.sleep(5) 3.3 步骤3:拉取 Ollama 模型 拉取一个 Ollama 模型,比如 DBRX: 1 !ollama pull dbrx 3.4 步骤4:查询模型 查询测试模型,看看它的表现如何: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 from langchain_core.prompts import ChatPromptTemplate from langchain_ollama.llms import OllamaLLM from IPython.display import Markdown template = """Question: {question} Answer: Let's think step by step.""" prompt = ChatPromptTemplate.from_template(template) model = OllamaLLM(model="dbrx") chain = prompt | model # 准备输入以进行调用 input_data = { "question": '将以下内容总结成一句话:"Bob 是一个男孩。Bob 有一只狗。Bob 和他的狗去散步。Bob 和他的狗走到公园。在公园里,Bob 扔了一根棍子,他的狗把它带回来。狗追了一只松鼠,Bob 追着它跑。Bob 把他的狗找回来,他们一起走回家。"' } # 使用输入数据调用链并显示响应 response = chain.invoke(input_data) display(Markdown(response)) 4 Mixtral 8x7B 模型的实际效果 在比较不同 MoE 模型的输出时,我们可以从逻辑推理、摘要和实体提取等任务的表现来分析它们的差异。 逻辑推理问题 1 给我一个包含 13 个单词的清单,每个单词有 9 个字母。 输出: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Sure,here are thirteen words,each with nine letters: 1. Agriculture 2. Beautiful 3. Chocolate 4. Dangerous 5. Encyclopedia 6. Fireplace 7. Grammarly 8. Hamburger 9. Important 10. Juxtapose 11. Kitchener 12. Landscape 13. Necessary I hope this list helps! If you have any other questions or need further assistance,feel free to ask. 从上面的输出可以看出,所有响应的单词都不包含 9 个字母。在 13 个单词中,只有 8 个单词包含 9 个字母。因此回复部分正确。 摘要问题 1 将以下内容总结成一句话:"Bob 是一个男孩。他有一只狗。Bob 和他的狗去散步。Bob 和他的狗走到公园。在公园里,Bob 扔了一根棍子,他的狗把它带回来。狗追了一只松鼠,Bob 追着它跑。Bob 把他的狗找回来,他们一起走回家。" 输出: 1 小男孩Bob很享受与他爱犬一起进行的一次活跃郊游。他们一起走到公园,一起玩捡球游戏、追松鼠,然后一起回到家。 从上面的输出可以看出,回复总结得相当好。 实体提取 1 从文本中提取所有数值及其对应单位:"马拉松长42公里,超过30,000人参加。" 输出: 1 2 3 4 5 6 7 1. 在给定的文本中,有两个数值及其对应的单位: - 42(马拉松的长度,文中未提及单位,但后面提到可以推断为千米) - 30,000(参与人数) 2. 文中后来提供了马拉松长度的单位:千米。由于没有为这个值指定其他单位,我们假设它是以千米为单位。 3. 因此,最终答案是: - 42(千米,马拉松长度) - 30,000(参与人数) 从上面的输出可以看出,结果正确提取了所有数值和单位。 数学推理问题 1 我有2个苹果,然后我又买了2个。我用2个苹果烤了一个派。吃完半个派后,我还剩下多少苹果? 输出: 1 2 3 4 1. 开始时有2个苹果。 2. 再买2个苹果,这样你就有4个苹果了(2 + 2 = 4)。 3. 用2个苹果做一个派,这样你还剩下2个苹果(4 - 2 = 2)。 4. 吃掉一半的派,但由于我们不知道派里有多少个苹果,仅凭这些信息无法确定还剩下多少个苹果。 模型的输出不准确。准确的输出应该是2,因为4个苹果中有两个做了苹果派,剩下的两个苹果还在。 5 总结 MoE 模型通过仅激活每个任务的相关专家,提供了一种高效的深度学习方法。这种选择性激活使得 MoE 模型能够在与传统密集模型相比减少计算资源的情况下执行复杂操作。但MoE 模型也需要进行取舍,因为它需要大量的 VRAM 来存储所有专家。 Mixtral 8X7B 架构是一个典型的例子,它利用稀疏专家混合 (SMoE) 机制,仅激活专家的子集以实现高效的文本处理,显著降低了计算成本。它拥有 128 亿激活参数和 32k tokens的上下文长度,在从文本生成到客户服务自动化的广泛应用中表现不错。Databricks 的 DRBX 模型也因其创新的细粒度 MoE 架构而脱颖而出,允许其在每个输入时仅激活 360 亿参数的情况下利用 1320 亿参数。同样,DeepSeek-v2 利用细粒度和共享专家,提供了一个强大的架构,拥有 2360 亿参数和 128,000 tokens的上下文长度,使其成为聊天机器人、内容创作和代码生成等多样化应用的理想选择。 5.1 关键要点 MoE 模型通过仅激活特定任务的相关专家,提高了深度学习的效率,与传统密集模型相比减少了计算资源的使用。 尽管 MoE 模型提供了计算效率,但它们需要大量的 VRAM 来存储所有专家,突显了计算能力和内存需求之间的关键权衡。 Mixtral 8X7B 采用稀疏专家混合 (SMoE) 机制,激活其 128 亿激活参数的子集以实现高效的文本处理,并支持 32,000 标记的上下文长度,使其适用于各种应用,包括文本生成和客户服务自动化。 Databricks 的 DBRX 模型采用细粒度的专家混合架构,在每个输入时仅激活 360 亿参数的情况下高效利用 1320 亿总参数,展示了其在处理复杂语言任务中的能力。 DeepSeek-v2 结合了细粒度和共享专家策略,形成了一个强大的架构,拥有 2360 亿参数和 128,000 标记的上下文长度,使其在聊天机器人、内容创作和代码生成等多样化应用中表现出色。 6 常见问题 Q1. 什么是专家混合模型 (MoE)? A. MoE 模型使用稀疏架构,仅激活每个任务最相关的专家,从而减少与传统密集模型相比的计算资源使用。 Q2. 使用 MoE 模型的利弊是什么? A. 尽管 MoE 模型提高了计算效率,但它们需要大量的 VRAM 来存储所有专家,需要在计算能力和内存需求之间权衡。 Q3. Mixtral 8X7B 模型的激活参数数量是多少? A. Mixtral 8X7B 有 128 亿(2×56 亿)激活参数,占总数 448 亿(8×56 亿参数)的一部分,使其能够高效处理复杂任务并提供更快的推理。 Q4. DBRX 模型与其他 MoE 模型(如 Mixtral 和 Grok-1)有何不同? A. DBRX 采用细粒度的专家混合方法,每层有 16 个专家和 4 个激活专家,而其他 MoE 模型每层有 8 个专家和 2 个激活专家。 Q5. DeepSeek-v2 与其他 MoE 模型有何不同? A. DeepSeek-v2 结合了细粒度和共享专家,以及其庞大的参数集和广泛的上下文长度,使其成为多种应用的强大工具。 7 推荐阅读 Mixtral of experts | Mistral AI | Frontier AI in your hands DeepSeekMoE: MoE with Segmented and Shared Experts Mixtral of Experts DBRX: A Large-Scale Decoder-Only Language Model with Fine-Grained Mixture of Experts

2024/12/25
articleCard.readMore

数学视角下的支持向量机(SVM):优化问题求解

支持向量机(SVM)是机器学习中的经典算法。本文聚焦于SVM中的公式推导,如间隔距离公式的详细推理,以及原问题与对偶问题公式化阐述。深入探讨优化问题,包括构建拉格朗日函数来处理约束优化问题,利用KKT条件求解最优解的过程。同时涉及多项式核函数与高斯核函数公式特性。 间隔距离推理 在支持向量机(SVM)中,正超平面和负超平面的式分别为: $$ \vec{w} \cdot \vec{x} + b = 1 \quad \text{(正超平面)} $$ $$ \vec{w} \cdot \vec{x} + b = -1 \quad \text{(负超平面)} $$ 其中$\vec{w}=(w_1, w_2)$是权重向量,$b$是偏置项,$\vec{x}=(x_1, x_2)$是数据点。 假设$\vec{x_m}$是正超平面上的点,$\vec{x_n}$是负超平面上的点,则有: $$ w_1 x_{1m} + w_2 x_{2m} + b = 1 \quad \text{(1)} $$ $$ w_1 x_{1n} + w_2 x_{2n} + b = -1 \quad \text{(2)} $$ 用式(1)减去式(2),得到: $$ w_1 (x_{1m} - x_{1n}) + w_2 (x_{2m} - x_{2n}) = 2 $$ 写成向量形式: $$ \vec{w} \cdot (\vec{x_m} - \vec{x_n}) = 2 \quad \text{(3)} $$ 考虑决策超平面上的两个点$\vec{x_0}$和$\vec{x_p}$,它们满足决策超平面式$\vec{w} \cdot \vec{x} + b = 0$,即: $$ w_1 x_{10} + w_2 x_{20} + b = 0 $$ $$ w_1 x_{1p} + w_2 x_{2p} + b = 0 $$ 两式相减得到: $$ w_1 (x_{10} - x_{1p}) + w_2 (x_{20} - x_{2p}) = 0 $$ 写成向量形式: $$ \vec{w} \cdot (\vec{x_0} - \vec{x_p}) = 0 \quad \text{(4)} $$ 式(4)表明$\vec{w}$与决策超平面上任意两点的向量差是垂直的。 从式(3)和(4)可知,$\vec{w}$与$(\vec{x_m} - \vec{x_n})$的点积为2,根据向量点积的定义$\vec{a} \cdot \vec{b}=|\vec{a}| \cdot |\vec{b}| \cdot \cos \theta$,这里$\theta$是$\vec{w}$与$(\vec{x_m} - \vec{x_n})$的夹角,我们有: $$ |\vec{x_m} - \vec{x_n}| \cdot \cos \theta \cdot |\vec{w}| = 2 $$ 令$L = |\vec{x_m} - \vec{x_n}| \cdot \cos \theta$,则: $$ L \cdot |\vec{w}| = 2 $$ 解得: $$ L=\frac{2}{|\vec{w}|} $$ 这里$L$就是SVM的间隔(margin)距离。 在推导间隔距离时,我们利用了向量点积的几何意义,即$\vec{a} \cdot \vec{b}=|\vec{a}| \cdot |\vec{b}| \cdot \cos \theta$,其中$\theta$是两向量的夹角。通过这个关系,我们将点积转化为向量模长和夹角的关系,从而得出间隔距离的表达式。 对偶等价证明 在线性支持向量机(SVM)中,原问题是找到最小化目标函数的权重向量$w$和偏置$b$: $$ \min_w f(w) = \frac{1}{2} |w|^2 $$ 这里的$|w|^2$代表向量$w$的欧几里得范数平方,即$L_2$范数。目标是最小化决策边界的宽度,以获得更好的泛化能力。该问题受到以下约束: $$ y_j (w^T x_j + b) - 1 \geq 0 $$ 这里$x_j$是第$j$个训练样本,$y_j$是对应的标签,取值为+1或-1,这确保了所有数据点都被正确分类,并且距离决策边界至少有一个单位的距离。 为了处理这个带约束的优化问题,我们构建拉格朗日函数: $$ L(w, b, \alpha) = f(w) - \sum_{j = 1}^n \alpha_j g_j(w, b) $$ 这里$\alpha_j \geq 0$是拉格朗日乘子,用于引入原始问题中的约束条件$g_j(w, b) = y_j (w^T x_j + b) - 1 \geq 0$。 接下来,我们定义对偶函数$q(\alpha)$为: $$ q(\alpha) = \min_{w, b} L(w, b, \alpha) = \min_{w, b} \left( f(w) - \sum_{j = 1}^n \alpha_j g_j(w, b) \right) $$ 因为$\alpha_j \geq 0$ 和$g_j(w^{*}, b^{*}) \geq 0$ ,我们可以得出: $$ q(\alpha) = \min_{w, b} \left( f(w) - \sum_{j = 1}^n \alpha_j g_j(w, b) \right) \leq f(w^*) - \sum_{j = 1}^n \alpha_j g_j(w^*, b^*) \leq f(w^*) \leq f(w) $$ 这意味着对偶函数给出了原问题的一个下界。接下来,我们需要找到一个$\alpha^*$,使得: $$ q(\alpha) \leq q(\alpha^*) \leq f(w^*) \leq f(w) $$ SVM的原问题和对偶问题可以表述为: $$ \max_{\alpha} q(\alpha) = \max_{\alpha} \min_{w, b} L(w, b, \alpha) $$ 其约束条件为:$ \alpha_i \geq 0 $ 并且,当满足弱对偶性时,我们有$q(\alpha^*) \leq f(w^*)$;而当满足强对偶性时,即Slater条件成立时,我们有$q(\alpha^*) = f(w^*)$。Slater条件要求存在一个可行解使得所有不等式约束严格成立,而线性支持向量机是线性可分的,能自动满足Slater条件。 至此,我们有: $$ f(w) \geq q(\alpha^*) = f(w^*) \geq q(\alpha_i) $$ 根据上面这个式子,我们能得到: $$ q(\alpha^*) \geq q(\alpha_i) $$ $$ f(w^*) \leq f(w) $$ $f(w)$ 找到了最小值(原问题),$q(\alpha)$找到了最大值(对偶问题),原问题和对偶问题的最优解是相等的,即: $ w^*, b^* $是原问题的解,$\alpha^*$是对偶问题的解,且$f(w^*) = q(\alpha^*)$。 我们可以看到在线性SVM中,当满足特定条件(Slater条件)时,原问题和对偶问题的解是一致的。这为是解决复杂的优化问题的一种有效途径,尤其是在原问题难以直接求解时,可以通过求解对偶问题来间接解决问题。 简单的例子 为了更直观地理解上面原问题和对偶问题的解是相同的,考虑一个简单的优化问题,原问题定义如下: 原问题为: $$ \min_x f(x) = x^2 $$ 约束条件为: $$ x - 1 \geq 0 $$ 这个问题的目标是最小化函数$f(x) = x^2$,同时$x$需要满足$x \geq 1$。直观上,我们知道当$x = 1$时,$f(x) = 1$,这是在给定约束下的最小值。 为了验证对偶性,我们构造拉格朗日函数: $$ q(\alpha) = \min_x L(x, \alpha) = \min_x (x^2 - \alpha(x - 1)) $$ 这里$\alpha \geq 0$是拉格朗日乘子,用来引入原问题中的约束条件$x - 1 \geq 0$。通过构造拉格朗日函数,我们将有约束的优化问题转换成了一个无约束的问题。 接下来,我们对$L(x, \alpha)$关于$x$求偏导数,并令其等于0: $$ \frac{\partial L}{\partial x} = 0 2x - \alpha = 0 $$ 解得: $$ x = \frac{\alpha}{2} $$ 将$x = \frac{\alpha}{2}$代入$q(\alpha)$中: $$ q(\alpha) = - \frac{\alpha^2}{4} + \alpha $$ 现在我们已经得到了对偶函数$q(\alpha)$的形式。接下来,我们需要求解对偶问题的最大值$\max_{\alpha} q(\alpha) $ 为此,我们对$q(\alpha)$关于$\alpha$求导,并令其等于0: $$ \frac{dq}{d\alpha} = - \frac{\alpha}{2} + 1 = 0 $$ 解得$$ \alpha = 2 $$ 将$\alpha = 2$代入$x = \frac{\alpha}{2}$,得到:$$ x = 1 $$ 此时,将$\alpha = 2$代入$q(\alpha)$,计算得到: $$ q(\alpha) = - \frac{2^2}{4} + 2 = 1 $$ 通过这个简单例子,我们可以看到,原问题的解$x = 1$,$f(x) = 1$,与对偶问题的解$\alpha = 2$,$q(\alpha) = 1$是等价的。这验证了在满足一定条件下,对偶问题的解与原问题的解是一致的。 通过对偶理论的应用,我们不仅找到了原问题的解,还通过求解对偶问题得到了相同的结果,从而验证了对偶问题解的等价性。 KKT条件求解 SVM满足KKT条件 SVM的原始优化问题是一个凸优化问题。SVM的目标函数 $\frac{1}{2}|w|^2$ 是一个二次函数,它是关于 $w$ 的凸函数。同时,约束条件 $y_i(w \cdot x_i + b) \geq 1$ 是线性的(仿射约束),因此也是凸的。在凸优化问题中,局部最优解就是全局最优解,而且KKT条件是必要且充分的条件。这意味着如果一个点满足KKT条件,那么它就是全局最优解。 目标函数 $\frac{1}{2}|w|^2$ 是连续且可微的,约束条件 $y_i(w \cdot x_i + b) \geq 1$ 也是连续且可微的。这种光滑性保证了梯度的存在性和唯一性,从而让KKT条件中的梯度条件(即对 $w$ 和 $b$ 求偏导数并设置为零)能够有效应用。 在凸优化问题中,KKT条件不仅是必要条件,而且是充分条件。也就是说如果一个点满足KKT条件,那么它一定是全局最优解。对于SVM来说,通过求解KKT条件,我们可以找到最优的 $w^*$ 和 $b^*$,从而确定最佳的分离超平面。 利用KKT条件求解线性支持向量机 原始的SVM优化问题是最小化 $\frac{1}{2}|w|^{2}$,同时满足约束条件 $y_{i}(w\cdot x_{i}+b)\geqslant1$,这里 $i = 1,2,\cdots,N$。 首先,构建拉格朗日函数 $L(w,b,\alpha)=\frac{1}{2}|w|^{2}-\sum_{i = 1}^{N}\alpha_{i}(y_{i}(w\cdot x_{i}+b)-1)$,其中 $\alpha_{i}\geqslant0$ 是拉格朗日乘子。根据KKT条件,我们有: $$ \nabla_{w}L(w^*,b^*,\alpha^*) = w^*-\sum_{i = 1}^{N}\alpha_{i}^*y_{i}x_{i}=0 $$ $$ \nabla_{b}L(w^*,b^*,\alpha^*)=-\sum_{i = 1}^{N}\alpha_{i}^*y_{i}=0 $$ $$ \alpha_{i}^*(y_{i}(w^*\cdot x_{i}+b^*)-1)=0 $$ $$ y_{i}(w^*\cdot x_{i}+b^*)-1\geqslant0 $$ $$ \alpha_{i}^*\geqslant0 $$ 这些条件适用于所有 $i = 1,2,\cdots,N$ 的情况。 从 $\nabla_{w}L(w^*,b^*,\alpha^*) = w^*-\sum_{i = 1}^{N}\alpha_{i}^*y_{i}x_{i}=0$ 可以得出 $$ w^*=\sum_{i = 1}^{N}\alpha_{i}^*y_{i}x_{i} \quad \text{(5)} $$ 由于至少有一个 $\alpha_{j}^*>0$(如果假设 $\alpha_{i}^*=0$,则会导致由式 $\nabla_{w}L(w^*,b^*,\alpha^*) = w^*-\sum_{i = 1}^{N}\alpha_{i}^*y_{i}x_{i}=0$ 给出的解产生矛盾)。 对于 $b^*$ 的求解,可以通过将 $w^*=\sum_{i = 1}^{N}\alpha_{i}^*y_{i}x_{i}$ 代入到 $y_{j}(w^*\cdot x_{j}+b^*)-1 = 0$(考虑到存在 $\alpha_{j}^*>0$ 的情况),并注意到 $y_{j}^{2}=1$,从而得到: $$ b^*=y_{j}-\sum_{i = 1}^{N}\alpha_{i}^*y_{i}(x_{i}\cdot x_{j}) \quad \text{(6)} $$ 基于上述理论,分离超平面可以表达为: $$ \sum_{i = 1}^{N}\alpha_{i}^*y_{i}(x\cdot x_{i})+b^*=0 $$ 从而分类决策函数则可以写作: $$ f(x)=\text{sign}(\sum_{i = 1}^{N}\alpha_{i}^*y_{i}(x\cdot x_{i})+b^*) $$ 在SVM中,互补松弛条件 $\alpha_i (y_i(w \cdot x_i + b) - 1) = 0$ 表明,如果一个样本点 $x_i$ 不是支持向量(即 $y_i(w \cdot x_i + b) > 1$),那么对应的拉格朗日乘子 $\alpha_i$ 必须为零。相反,如果一个样本点是支持向量(即 $y_i(w \cdot x_i + b) = 1$),那么对应的 $\alpha_i$ 可以是非零的。这种条件确保了只有支持向量对优化问题的解有贡献,从而简化了问题的求解过程。 多项式核函数与高斯核函数 如果现有的问题不是线性可分的,我们可以对现有的数据映射到高维空间,使其在高维空间成为一个线性可分的问题。但直接在高维特征空间中进行计算会非常复杂。由式(5)和式(6)可知,我们其实不需要真的去把数据映射到高维空间,只要知道数据点之间的内积就可以了。核函数的作用就是避免显式地进行高维特征映射,通过在原始特征空间中计算核函数值来间接实现高维特征空间中的内积计算。 高斯核函数是一种常见的核函数,其形式为: $$ K(x, y) = \exp\left(-\gamma |x - y|^2\right) $$ 其中 $\gamma$ 是一个正的参数,控制着核函数的宽度。 我们可以对指数函数进行泰勒展开: $$ \exp(z) = \sum_{k=0}^{\infty} \frac{z^k}{k!} $$ 将 $ z = -\gamma |x - y|^2 $ 代入上述公式,得到: $$ K(x, y) = \exp\left(-\gamma |x - y|^2\right) = \sum_{k=0}^{\infty} \frac{(-\gamma |x - y|^2)^k}{k!} $$ 多项式核函数的形式为: $$ K_{\text{poly}}(x, y) = (x \cdot y + c)^d $$ 其中 $ c $ 是常数项,$ d $ 是多项式的次数。 $|x - y|^2$ 可以展开为: $$ |x - y|^2 = (x - y) \cdot (x - y) = x \cdot x + y \cdot y - 2 x \cdot y $$ 将这一表达式代入高斯核函数的泰勒展开式中: $$ K(x, y) = \sum_{k=0}^{\infty} \frac{(-\gamma (x \cdot x + y \cdot y - 2 x \cdot y))^k}{k!} $$ 可以看到,每一项 $ \frac{(-\gamma (x \cdot x + y \cdot y - 2 x \cdot y))^k}{k!} $ 实际上是一个多项式项,也就是说每一项都可以表示为 $ x $ 和 $ y $ 的不同幂次的组合。 如果我们仔细观察每一项,可以发现高斯核函数实际上是通过将不同阶次的多项式核函数进行加权求和得到的。每一项 $ \frac{(-\gamma (x \cdot x + y \cdot y - 2 x \cdot y))^k}{k!} $ 可以看作是一个 $ k $-阶多项式核函数的加权形式。 例如,当 $ k = 1 $ 时: $$ \frac{(-\gamma (x \cdot x + y \cdot y - 2 x \cdot y))^1}{1!} = -\gamma (x \cdot x + y \cdot y - 2 x \cdot y) $$ 当 $ k = 2 $ 时: $$ \frac{(-\gamma (x \cdot x + y \cdot y - 2 x \cdot y))^2}{2!} = \frac{\gamma^2 (x \cdot x + y \cdot y - 2 x \cdot y)^2}{2} $$ 这些项都是 $ x $ 和 $ y $ 的多项式形式,并且通过阶乘 $ k! $ 进行加权。 高斯核函数可以被视为在无穷维度上通过不同阶次的多项式核函数进行调和得到的。这种调和使得高斯核函数能够在高维特征空间中捕捉到更复杂的非线性关系。因此,在一半的非线性任务场景中,高斯核函数都是很不错的一个选择。

2024/11/27
articleCard.readMore

VLDB 2024广州之旅

VLDB 2024 是数据管理和数据库领域的顶级国际会议,涵盖数据管理、数据库架构、图数据管理、数据隐私与安全、数据挖掘、机器学习、人工智能与数据库系统研究等领域。今年的会议于8月26日至30日在中国广州举行,汇集了全球的研究人员和企业。会议内容丰富,包括250多场研究报告、11场主题演讲、多个教程和workshop,为与会者提供了广泛的学习和交流机会。 最近去了趟广州,参加了 VLDB 2024,体验了完整的学术会议流程。旅途中也遇到了不少有趣的事情,想着写一篇博客分享一下。 注意 本文是旅游向分享,内容包含在广州的见闻以及学术会议流程介绍,不包含对具体报告内容和方向的介绍,请放心食用。 此次行程为期6天,行程安排如下。其中前5天在琶洲岛广交会展馆附近,主要是参加会议以及珠江夜游;最后一天为特种兵打卡式旅游,西侧从沙面岛开始,途径十三行博物馆,走到圣心大教堂,东侧为黄埔军校纪念馆。 Day 0:给现充来点小小的广州震撼 下午3点,从广州南站坐地铁到琶洲站。还没出站就意识到事情有点不太对劲,地铁里挤满了Coser。好巧不巧,缺德地图选了个保利世贸馆的出口,这下可捅了二刺螈的老窝:从地铁出口到场馆地下,从保利世贸馆到广交会展馆,琶洲岛上挤满了二刺螈!不仅参与的人数多,而且cos的角色也非常丰富,从国产游戏到日本动漫,从牢大到川普遇刺…停车场里也挤满了痛车,这些车几乎没有电车,车主们大概也是资深二刺螈罢。 好不容易突出重围来到酒店,结果晚上21点去吃饭时,发现漫展还没结束,居然沿江边架起了夜场——第二天可是周一啊!广州的二次元氛围还是太浓厚了。 Day 1:学术蝗虫与晚宴乌龙 VLDB2024由香港科技大学(广州)在广州朗豪酒店举办。第一天报到从早上8点开始,由于第一次参加学术会议太兴奋,直接赶了个大早。报道时会发胸牌、会议手册、日程表、饭票、船票、一盒纪念品以及一堆赞助商的广告。纪念品包含一本精装笔记本、一支圆珠笔和一把伞,有黑色和蓝色两种主题色。 第一天的会议内容全部是以Workshop的形式组织的。现场会有关于不同主题的workshop同时进行,因此需要提前选取自己感兴趣的主题去参加。我选取了关于 LLM, Knowledge Graph和Vector Database相关的主题,听懂演讲内容的问题不大,但到了讨论环节,有几个老哥后来聊high了,语速逐渐提升,就开始听不懂了,英语听力和口语还得练。 学术会议有哪些环节? 1. 开幕式(Opening Ceremony) 会议的正式启动环节。 主办方或主办机构的负责人致辞,介绍会议主题、议程以及参会的重要嘉宾。 有时还包括特别的欢迎仪式或文化展示。 2. 主旨演讲(Keynote Speech) 由某个领域的知名学者或专家发表的演讲,通常围绕大会主题展开。 主旨演讲通常具有启发性,为与会者提供前瞻性或总结性的观点。 是会议中备受关注的环节,时间一般较长(45分钟至1小时)。 3. 分组报告(Parallel Sessions) 与会者按研究方向或主题分组,在多个会场同时进行。 每组内有多个报告,研究人员展示自己的研究成果。 每个报告后会有简短的提问环节,供听众提问和讨论。 4. 海报展示(Poster Session) 研究者通过海报展示其研究成果,通常在展览区或休息期间进行。 参会者可以在指定时间内自由参观各个海报展位,与研究人员互动并进行讨论。 海报展示环节适合展示较为新颖或尚未成熟的研究项目。 5. 专题讨论(Panel Discussion) 由多个专家组成的讨论小组,就某个特定议题进行对话。 各位专家先各自发表见解,然后由主持人引导进行互动和讨论,最后开放给观众提问。 专题讨论有助于从多个角度深入探讨某一研究问题或学术领域的热点问题。 6. 圆桌会议(Roundtable Discussion) 参与者以圆桌形式围绕某一主题进行开放式讨论。 圆桌会议更加注重互动性,参与者可以随时发言、提出问题并分享观点。 7. 工作坊(Workshop) 强调实际操作和互动学习的环节,参与者在会议上学习新技能、方法或工具。 工作坊通常需要预先注册,有时需要参与者带来自己的数据或材料。 8. 社交活动(Networking Sessions) 会议中的社交环节,目的是为与会者提供轻松的环境进行非正式交流和建立合作关系。 社交活动可能包括晚宴、茶歇、午餐、酒会等。 9. 闭幕式(Closing Ceremony) 会议的总结与闭幕环节。 主办方回顾会议的主要内容和成果,可能会表彰优秀的报告、论文或研究成果。 通常还会宣布下届会议的时间和地点。 10. 问答环节(Q&A Sessions) 紧随每个报告或专题讨论之后,允许听众提问。 研究者或演讲者会对听众提出的问题做出详细解答,促进双向交流。 11. 小组讨论(Breakout Sessions) 在大型会议中,为了讨论具体的子议题或研究方向,通常将参会者分成若干小组。 每个小组集中讨论特定主题,然后可能汇报讨论成果或建议。 12. 展览区(Exhibition Booths) 在某些学术会议中,尤其是技术或应用领域的会议,通常设有展览区。 相关机构、出版社、公司会在展区展示他们的产品、技术、服务或出版物,参会者可以自由参观。 13. 评奖和颁奖(Awards and Recognition) 一些会议设有论文、报告或研究成果的评奖环节。 优秀的研究人员、论文、海报展示等可能会在闭幕式或专门的颁奖仪式上得到表彰。 14. 茶歇和午餐(Coffee Breaks and Lunches) 会议期间的休息时间,提供茶点或午餐。 茶歇和午餐时间也是与会者进行非正式交流和社交的重要机会。 茶歇分别是在上午10点和下午3点,8点的早餐也是茶歇的规格。对于大佬们来说,茶歇是进行Social的好时候,探讨研究内容或是交换联系方式。但对于我这种学术蝗虫来说,茶歇就真的只是茶歇。虽然每场茶歇的食物会有一些变化,但总体就是饼干、面包、蛋糕、水果和饮料这几类。其中,属慕斯蛋糕和泰式烤鱼饼配甜辣酱最得我心。 晚上的欢迎宴会也非常丰盛,是自助餐。不过当时排队人太多,提前没注意到有哪些菜品,哐哐先打了两勺米饭,错过了不少好菜。菜品里中餐约占30%,其余为日料(寿司和刺身)、咖喱、蔬菜沙拉、西点、水果和饮品(红酒和果汁),能充分照顾到不同的饮食差异。但这里面中餐的那些菜实在一般,导致我最后是碳水配碳水——咖喱米饭和小蛋糕。嗟乎,吾其辞小蛋糕难矣。 晚宴期间还闹了个乌龙。由于这次会议我和另一位同学一起来参加的,我们俩都还没面见过导师。当我们选完菜随便找个桌子落座后,就开始听同桌的其他人在聊什么。然后我们俩就发生了如下的对话:“你有没有觉得对面那个有点像我们导师”?“不会吧,这么巧“?”研究方向对的上,刚才他们说”…“年龄不对吧”…”人数也对的上“…”身高也对的上”…”太像了”…”简直就是”…”怎么办,现在认吗”?”事已至此,先吃饭吧”。就这样我们俩非常紧张地吃完饭,上去相认后,结果发现根本不是。他们分别是来自天津大学和华东师范大学的博士生,研究方向很相似,相互介绍后也加了好友。后面又发现他们的文章提名最佳研究论文,真是羡慕极了。 Day 2:醒狮,开幕! 开幕式上,令人印象最深的便是广州沙坑醒狮表演。表演开始时,舞者操控狮子做出各种逼真的动作,模仿狮子的生活习性,如甩头、挠痒、打滚等,其中最有特色的便是狮子的眼睛会动(这是我判断它是沙坑醒狮的依据)。随后狮子开始在台上进行高难度的跳跃和踩桩动作,展现了舞者的精准技巧和强健体魄。最后是领导上台点睛,以及狮子叼出庆贺的对联。整场表演配合着锣鼓节奏,狮子时而威猛、时而灵动,既有力量感,又充满了趣味性。 这是我第一次看到真正的舞狮表演,还是最具特色的广东醒狮。虽然很多游戏里面也有以广东醒狮为原型的桥段,特别是标志性的踩桩动作,但这些桥段往往侧重于对表演场景的渲染,缺少狮子模仿动作带来的趣味性,所体现出的力量感也不如现场表演来的强烈。 舞狮表演结束后,便是会议主席,来自港科大的陈雷老师介绍会议的一些大致情况:这次会议是VLDB举办历史上参会人数最多的一次,中国大陆的参会人员占60%,会议是最有钱的一次(half a million dollar),AI相关的论文最多、数据库底层设计的论文最少等。 开幕式结束后,正式开启一整天的分组报告。分组报告也是需要事先选定感兴趣的主题去听,最好要提前看感兴趣的论文,甚至准备要提问的问题。晚餐跟前一天一样丰盛,意式蔬菜浓汤和千层饼非常赞!(唯独)这一天还有烤串,有翅根和面筋两种。吃完饭后逛了一圈,发现只要是有中国人的桌子,没有不拿烤串的,甚至还有人就是白米饭配烤串的,看来大家都还是中国胃。码农烧烤,大有可为。 Day 3:从粤菜天花板到甲板 早上由来自 Google的keynote开场,主题关于大模型对数据库研究的影响。随后是和前一天相同的分组报告。 精品粤菜 晚上的宴会是在炳胜品味海印总店进行的。路上遇到了两位在美国留学的学生,他们评价说,中国人办的会议,场面是一定要给足的。此言不虚,后面才了解到这家店又是米其林,又是号称粤菜天花板的。这两位,一个在美西,评价自己的生活跟在村子里一样,没得吃没得玩;另一位在美东也表示饮食条件不行,每天都可以坚持不同体育项目的锻炼。但当谈及读研究生的目的时,其中一位表示是为了保持一种洞察力和终身学习的思维能力,再赞同不过了。 晚餐菜品的确很丰富。由于餐桌上不方便使用手机,只能凭借记忆回忆起几道印象比较深刻的菜:西洋参排骨汤、整头烤乳猪(但眼睛里塞了俩红色电灯泡,作为外乡人我愿称之为邪能烤乳猪)、蒜蒸波士顿龙、大海参、鱼、鸡鸭、咕咾肉、甜水、西红柿和蜜瓜、沙琪玛和普洱茶。总体来说还不错,烤乳猪皮脆肉嫩,咕咾肉酸爽可口,食材选用极具岭南特色。但可能是由于吃不习惯,一些粤菜中的特色菜,反而是最难吃的:甜水真的甜到发齁、西洋参放汤里尽显酸涩,还有一种点心,吃起来仿佛是月饼皮包着芹菜猪肉饺子的生馅料,着实无法接受。有趣的是,餐厅默认没有提供刀叉,一些老外也被迫使用筷子,但看起来好像都没什么障碍。 我们师门同桌的有亚马逊的研究员和美国某大学的AP。亚马逊的研究员当着我导的面,从工业界的角度讲了一些不适合学生听的话。AP则聊到了在美国的大学里只需要按自己的节奏做工作,就可以拿到终身教职的宽松氛围。排骨汤可能就是这时候被西洋参泡酸了。 饭后,全体人员一起步行前往码头,参加珠江夜游。途中遇到一位在名古屋大学读博士一年级的哥们,他大肆夸赞日本的读博生活,包括导师放养、高补贴、日本的卖方就业市场以及文化环境等。读博还能这么爽的? 珠江夜游 夜幕降临,珠江两岸华灯初上。我们登上游船,缓缓驶入璀璨夜色中。两岸高楼大厦灯火辉煌,倒映在波光粼粼的江面上,宛如繁星坠入碧波。 沿途经过标志性建筑,广州塔巍峨耸立,变幻的光影如梦似幻。珠江新城的摩天大楼群熠熠生辉,勾勒出现代都市的天际线。船经过海珠桥时,桥上车流如织,桥下游船穿梭,一派繁忙景象。 微风拂面,江水轻轻拍打船舷。甲板之下传来民俗乐声,为这夜色增添了几分惬意气息。游客们或倚栏远眺,或举杯畅聊,沉醉于这迷人夜色中。 两个小时的航程转瞬即逝。回望整个旅程,繁华都市与悠久历史在这条母亲河上完美交融,令人难忘。 新型搭讪 我和同行的同学在三层船头处观赏风景时,来了个老外。他背着双肩包,满头大汗,略显匆忙。他问我们这船上是否有WIFI,我们知不知道密码,他要跟家人联系。然后我们发现没有,就提出可以给他开热点。连接成功后,我们又想到,国外的社交软件几乎都在墙外,这老哥会不会来广州后,一直在找Wifi,但一直被墙了。换到他的角度想想:人在遥远而神秘的东方,每个Wifi都没法突破防火墙,与家人失联三天,找别人开热点但都不愿意“分享”——这实在是太可怜了。于是我们就又尝试把魔法猫咪的能力放到局域网上共享,这件在电脑很简单的事,在手机上最终也没能完成。 不过,我们很快发现这位老哥是个社牛。一路上疯狂找话题:“ICBC是什么意思?‘猎德’是什么意思?你们从哪来?那个Logo是什么”……还疯狂找我们合影。 就这样聊了一路,给这场夜游也增添了不一样的趣味。 后来在whova上,我们发现,这老哥活跃度排名第二,任职于德国某大学,还有家公司——这实在不像是与家人失联而需要到处蹭网的样子。 Day 4:无料收集 VLDB2024期间,有Google、Meta、阿里和字节等一众赞助商企业的展台,在展台上,可以填写调查问卷,然后会获得无料一份。问卷主要是调查研究方向和求职倾向,也有直接收名片的。所有无料中,我最喜欢的是Google的白衬衫和下面图里的企鹅。如果你不知道这个企鹅是哪家公司的,当你看到上面有正版防伪贴纸后,你便知道它是腾讯的。 下午的报告给了我很多启发。有些工作看似简单,甚至只是一个朴素的想法,但经过深入研究,也能形成一篇完整的论文,令人佩服。印象比较深刻的是一位康奈尔大学的独狼老哥,在同一个报告会上,连续报告了两个由自己独立完成的工作。他手拿话筒,单手插兜,双臂撑住讲台,PPT 采用简单大字风格(没有一页PPT超过30个字),完全是把报告当成演讲来进行。这也许就是大佬,已经完全next level。 这一天结束了我们所有的会议日程,离开酒店时遇到了非常极端的雷暴天气,大雨倾盆。 Day 5:半天走过中国五百年 本着“来都来了“的原则,我在广州的最后一天安排了一次特种兵式的密集行程。这一天我踏遍了广州的几个著名景点,领略了这座城市丰富的历史文化底蕴。 清晨,首先来到了充满异国情调的沙面岛。漫步在这个曾经的租界区,欧式建筑与热带植物相映成趣,仿佛穿越回了旧时光。判断一个地方的风景是否足够美丽,一个标准是有没有人在这里拍结婚照,南京的浦口火车站、绿博园和中山陵如此,广州的沙面岛也是如此。 在沙面岛逗留了一上午,中午步行去了旁边的十三行博物馆,深入了解了广州作为海上丝绸之路重要港口的辉煌历史。博物馆中陈列的文物和图片,生动展现了广州自17世纪商贸繁荣的盛况,到19世纪的半殖民地景象。在这里了解到,广州被迫通商后,各国商馆本设在今广州塔对岸的市中心沿江位置,但后来因一场大火,才转移到沙面岛。 午后又来到了圣心大教堂。这是一座规模庞大的哥特式建筑,是小红书推荐的必来打卡点。结果也确实只是打卡点,只有门口可以打卡,大部分时间也不开放。 下午去参观了黄埔军校旧址。漫步在这个培养了无数革命先烈的地方,希望感受那个激情燃烧的年代。由于提前没做功课,跟想象中的不太一样,多少还是有些失望。黄埔军校原址已经在抗战时期被日军轰炸化为灰烬了,现有的景点只是尽力还原的。看着整洁规整的、被还原后的建筑,让我不断有”夫子庙“的既视感——只能感觉自己是在景区。找了半天的大门也没有那幅对联:”升官发财请往他处,贪生怕死勿入斯门“。 夜幕降临,我又来到了珠江边,沿着江畔漫步。夜晚的广州,地平线与天际线,小蛮腰和大剧院,百看不厌。从海珠大桥到猎德大桥,同样的一条珠江,17世纪到21世纪,每个百年的景象竟能如此不同。 这段在广州的日子,宛如一场穿梭于古今的旅程。从琶洲的学术殿堂,到珠江两岸的灯火辉煌;从沙面岛的异国风情,到黄埔军校的革命遗迹。这座城市以其独特的方式,将学术、文化、历史和现代性完美融合。在高楼大厦的阴影下,也有城中村的烟火气息;车水马龙的大桥下,也有流浪汉的身影,提醒着这座城市仍在不断进步和包容的过程中。但这些场景不仅没有削弱广州的魅力,反而让这座城市显得更加真实、更富人情味。 再见,广州。

2024/9/23
articleCard.readMore

数据枯竭危机:AI发展面临的数据瓶颈与应对措施

我们估计人类产生的的公共文本存量约为 300 万亿个token。如果趋势持续,语言模型将在 2026 年至 2032 年之间完全耗尽这一存量,或者如果过度训练,甚至会更早。 ——Epoch AI 在2006年,时任伊利诺伊大学教授的李飞飞(现为斯坦福大学教授)看到了互联网改变人工智能(AI)研究的潜力。语言学领域的研究已经识别出了8万个“名词同义词集”,即描述同一类事物的同义词集合。李飞飞推测,互联网上的数十亿张图片中,一定包含了这些同义词集的无数实例。如果能够收集足够多的这些图片,就可以创建一个超越以往任何AI训练资源的庞大数据库。她说“很多人关注模型,我们应该关注数据”。于是,ImageNet项目诞生了。 互联网不仅提供了图片,还为图像标注提供了资源。通过搜索引擎找到如猫、狗、椅子等的图片后,亚马逊的众包平台Mechanical Turk上的人对这些图片进行人工检查和标注。最终,构建了一个包含数百万经过校验的图片的数据库。正是使用了部分ImageNet数据训练的AlexNet在2012年展示了“深度学习”的巨大潜力,开启了上一个AI周期,也催生了依赖于大量标注数据的行业。 1 数据驱动的AI时代 在这一轮AI周期中,AI的发展延伸到了大型语言模型(LLM),这些模型的训练也依赖于互联网数据,但方式有所不同。计算机视觉领域(CV)的经典训练任务是预测一张图片的内容(图片分类任务),但LLM训练的经典任务是基于上下文预测一段文本中被删除的词语。 这种训练方式不需要人工标注数据,系统可以自行空出词语,进行推理并通过“自监督训练”来评估答案的正确性。但这种方式需要大量的数据。一般来说,模型获得的文本越多、数据量越大,其性能就越好(Scaling Law)。 互联网正好就提供了数以百亿计的文本,它对LLM的意义就像沉积了亿万年的碳对现代工业的意义一样,是一种可以精炼成燃料的宝贵资源。 常见的训练数据来源是Common Crawl,一个包含500亿个网页的互联网档案。随着AI模型的发展,更多的数据被加入其中,如Books3——一个包含数千本书籍的数据库。然而,随着AI对文本数据需求的增长,互联网上的优质数据供给逐渐不堪重负。根据Epoch AI的估计,到2028年,互联网中的高质量文本数据将被完全利用完毕,行业将面临所谓的“数据墙”。中文互联网更严重,从“中文互联网正在崩塌”,到各大平台纷纷锁上大门,当大家意识到数据的价值后,便把它放进了保险库。如何应对这一壁垒,可能是AI未来发展中最棘手的问题之一,也可能是最有可能放缓其进程的问题。 2 数据所有权与版权问题 AI模型越来越依赖互联网数据,但数据的版权问题也充满争议。许多用于训练大型语言模型的数据往往未经版权方的同意就被使用,一些AI公司甚至利用了付费墙后的内容。虽然AI公司会声称这种使用属于版权法中的“合理使用”范畴,但版权方并不买账。Getty Images起诉了图像生成公司Stability AI,指控其未经授权使用了其图片库。纽约时报则起诉了OpenAI和微软,指控其侵犯了数百万篇文章的版权。Stack Overflow、Reddit和X(前Twitter)现在都向AI公司收取费用。知乎也正通过乱码来干扰必应和谷歌等爬虫,从而限制其中文内容作为数据集被用于AI训练。 不同地区对这一问题的态度有所不同。日本和以色列采取了宽松的立场,以促进其AI产业的发展。欧盟则没有通用的“合理使用”概念,可能会更加严格。国内也仅仅是设立了国家数据局,明确了数据兼有生产资料和生产对象双重身份。 3 现有的数据使用策略 面对数据墙,AI领域提出了几种应对策略。其中一个关键的应对策略是专注于数据的质量而非数量。各家AI实验室不再盲目地使用整个互联网的数据来训练模型,而是更加重视数据的过滤、清洗和优化,确保模型能够从中提取到最有价值的内容。在过去的一年里(2024年),OpenAI的模型似乎不再“遥遥领先”了,大家的模型打得有来有回,这些模型在不同任务上的性能差异,就来自训练数据的构建。毕竟开源算法和模型的很多,开源数据集的却寥寥无几。 获取“真实世界的信息”至关重要,特别是当模型涉及大量推理时,学术教科书等权威资源变得格外宝贵。但如何在不同数据源之间找到最佳平衡点仍然是一门玄学。 在数据使用的过程中,模型还面临“灾难性遗忘”的问题——即当系统在某些类型的数据上训练过多时,可能会在擅长该领域的同时,遗忘先前学到的其他知识。因此,训练时数据的顺序也需要仔细考虑。如果把所有关于某个主题的数据(如数学)集中在训练过程的末尾,模型或许会在数学问题上表现出色,但同时就可能削弱了其它领域的能力。这种不平衡的训练方式加剧了灾难性遗忘的风险。 在数据既涉及不同领域,还涉及不同形式(模态)时,这些策略就变得更加复杂。由于新的文本数据供不应求,像OpenAI的GPT-4和Google的Gemini这样的领先模型在自监督学习过程中,除了使用文本外,还使用图像、视频和音频进行训练。然而,视频数据尤其棘手,因为视频文件包含的数据点极为密集。为简化问题,现有模型通常仅抽取部分帧进行简化处理,学界仍在寻找更高效的解决方案。 4 合成数据与AI自我训练 模型能力还可以通过在自监督学习产生的版本(预训练版本)基础上,使用额外的数据进行精细调整(微调)来提升。例如,“监督微调”就是向模型提供由人类收集或制作的问答对,来教模型什么是好的答案。另一种方法“基于人类反馈的强化学习”(RLHF),则是告诉模型答案是否满足提问者。 在RLHF中,用户对模型输出的质量进行反馈,这些反馈随后用于调整模型的参数(权重)。与聊天机器人进行的用户互动,如点赞或踩,对RLHF特别有用。这就是“数据飞轮”的机制:更多的用户带来更多的数据,这些数据又反过来优化更好的模型。AI公司密切关注用户向其模型提出的各种问题,然后收集数据以调整模型以涵盖这些主题。阿里、字节和Minimax等厂商纷纷掀起模型价格战,很难说没有这方面的考量。 随着互联网上的预训练数据逐渐枯竭,后期训练(Post-Training)的重要性日益凸显。像Scale AI和Surge AI这样的标注公司每年通过收集后期训练数据赚取数亿美元。Scale最近以140亿美元的估值筹集了10亿美元。如今的标注工作已经超越了Mechanical Turk的时代:顶尖的标注员每小时可赚取高达100美元。尽管后期训练有助于生成更好的模型,并能满足许多商业应用的需求,但这仍然只是增量改进,治标不治本。 除了逐步突破数据墙,还有一种解决方案是完全跳过它,也就是使用机器生成的合成数据。DeepMind(谷歌的子公司)推出的AlphaGo Zero模型就是一个很好的例子。该公司第一个成功的围棋模型是通过数百万场业余比赛的数据进行训练的,而AlphaGo Zero则完全没有使用现有的数据。相反,它通过在三天内与自己对弈490万次来学习围棋,并记录下成功的策略。这种“强化学习”教会了它如何通过模拟大量可能的回应来应对对手的招数,并选择成功概率最高的策略。 类似的方法也可以用于LLM,比如目前最强的开源大模型Llama 3.1。LLama3.1 的SFT数据里有相当比例是由模型生成的合成数据,而Gemma2 在SFT阶段的数据很大比例是由规模更大的模型合成的,证明了合成数据质量不比人工标注质量差。 那我们可以无限生成合成数据,左脚踩右脚登天吗?我认为答案是否定的。上个月发表在《Nature》的一项研究发现,在模型训练中“滥用”合成数据可能导致“不可逆的缺陷”。用模型合成的数据来微调模型,只需要重复几轮,模型就会胡言乱语,研究人员将这一现象称为“模型崩溃”。 更大的问题在于如何将这种方法扩展到医疗或教育等垂直领域。在游戏中,胜利的定义明确,而且更容易收集到某个举动是否有利的数据。在其他领域,这要复杂得多。关于“好”决策的数据通常是从专家那里收集的,但这既昂贵又费时,解决方案也不够全面。如何判断某个专家是否正确,这也是个套娃的问题。 5 总结 获取更多数据将是保持AI快速进步的关键。不论是从专家来源获取的专门数据,还是机器生成的合成数据,AI的进步都取决于数据的持续供应。随着最容易获取的数据储备逐渐耗尽,AI行业也做出了许多努力来缓解这个问题: 强调数据质量,进行数据清洗 增加数学、逻辑和代码数据的配比,调整训练顺序 使用合成数据来补充真实数据 但这些似乎都不可持续,必须寻找新的数据源或开发可持续的替代方案;或者从算法架构层面,设计出不依赖数据的新架构,顺势开启下一轮AI周期。 6 推荐阅读 中文互联网正在加速崩塌 | 何加盐 Will We Run Out of Data? Limits of LLM Scaling Based on Human-Generated Data | EpochAI 知乎正通过乱码来干扰必应/谷歌等爬虫 | CSDN 人工智能的训练数据正在枯竭,合成数据引发巨大争议 | 华尔街见闻 浅谈Llama3.1,从结构、训练过程、影响到数据合成 | 火山社区 AI models collapse when trained on recursively generated data | Nature

2024/8/21
articleCard.readMore

微调GPT-4o-mini生成博客文章

7月18日发布的新模型GPT-4o-mini有着超越GPT-3.5、接近GPT-4的性能,且价格只用GPT-3.5的一半,响应速度也是全系列模型最快的。OpenAI于今天正式开放了GPT-4o-mini的微调接口,在2024年9月23日前,每天有2M token免费额度。 不是Llama 3.1 405B玩不起,而是GPT-4o-mini更有性价比。 1 微调适用场景 对于一般的简单任务,只需要编写提示词(Prompting),模型就能很好地完成。如果任务比较复杂,可以尝试使用思维链(Chain of Thought)将复杂任务分解为多个步骤,并逐步推理。但对于需要高精度和一致性输出的任务,就需要进行微调(Fine-tuning)。 下面的表格对比了这三种办法的优缺点以及应用场景。 方法 优点 缺点 应用场景 微调 提供高质量结果 需要大量时间和资源来准备和训练数据 需要稳定、可靠和高质量的输出 适用于复杂任务和特定领域的定制 反馈循环较慢,训练成本高 改进模型在特定任务或领域的性能 节省Token,降低延迟 有深度学习基础知识作为门槛 任务需要高精度或独特的风格、语气、格式时 提示词 快速迭代和测试 依赖于提示词的设计质量 常见任务的快速原型和测试 适合初始探索和一般任务 对复杂任务可能不够准确 需要灵活调整模型输出时 无需额外数据准备和训练资源 不适合大量示例和复杂逻辑的任务 思维链 提供分步骤逻辑和推理 增加了提示的复杂性和长度 处理需要推理和逻辑步骤的任务 改善复杂任务的性能 增加了Token使用量和延迟 涉及多步骤解决问题的场景 易于结合多种策略和工具 对非常复杂的任务可能仍不够 需要明确逻辑流程和分步执行时 NFL定理告诉我们,没有哪种方法能适用于所有场景,这里也是一样,微调也不一定就比另外两种方法更好。但可以明确的是,微调适用于那些“难以描述的任务”,比如一种风格和语气。此外,这三种方法也并不是水火不容,微调模型使用精心设计的提示词、甚至结合思维链,说不定能达到更好的结果。 只是简单地写一篇文章或段落,提示词就够了。但一篇博客文章,如果考虑SEO的话,就会有很多细节,例如核心关键词出现频率等。这些细节大模型不一定能尽数理解,且作为用户也不一定能很好地在提示词中进行描述。因此撰写一篇这样的博客文章就可以使用微调。 2 准备数据 数据需要以jsonl的格式组织,每一行是一个json。例如: 1 2 3 {"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the capital of France?"}, {"role": "assistant", "content": "Paris, as if everyone doesn't know that already."}]} {"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who wrote 'Romeo and Juliet'?"}, {"role": "assistant", "content": "Oh, just some guy named William Shakespeare. Ever heard of him?"}]} {"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "How far is the Moon from Earth?"}, {"role": "assistant", "content": "Around 384,400 kilometers. Give or take a few, like that really matters."}]} 也可以在多轮对话中设置权重,weight取0表示让模型规避这种回答。 1 2 3 {"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "What's the capital of France?"}, {"role": "assistant", "content": "Paris", "weight": 0}, {"role": "user", "content": "Can you be more sarcastic?"}, {"role": "assistant", "content": "Paris, as if everyone doesn't know that already.", "weight": 1}]} {"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "Who wrote 'Romeo and Juliet'?"}, {"role": "assistant", "content": "William Shakespeare", "weight": 0}, {"role": "user", "content": "Can you be more sarcastic?"}, {"role": "assistant", "content": "Oh, just some guy named William Shakespeare. Ever heard of him?", "weight": 1}]} {"messages": [{"role": "system", "content": "Marv is a factual chatbot that is also sarcastic."}, {"role": "user", "content": "How far is the Moon from Earth?"}, {"role": "assistant", "content": "384,400 kilometers", "weight": 0}, {"role": "user", "content": "Can you be more sarcastic?"}, {"role": "assistant", "content": "Around 384,400 kilometers. Give or take a few, like that really matters.", "weight": 1}]} 当然,处理数据是最耗时的,这里也可以直接使用我制作的数据集。该数据集用于对大模型进行微调,来源于对 reads.alibaba.com 网站中13个分类领域的3000+个页面的抓取,开源的不只有处理后的数据,也有原始数据以及爬虫代码。 将准备好的数据上传,记录返回的文件ID. 1 2 3 4 5 6 7 from openai import OpenAI client = OpenAI() client.files.create( file=open("all_filter_2120.jsonl", "rb"), purpose="fine-tune" ) 3 微调模型 准备好数据、验证无误、确认token成本后,即可创建微调任务 1 2 3 4 5 6 7 from openai import OpenAI client = OpenAI() client.fine_tuning.jobs.create( training_file="file-zWptPbsD37ZnemssjpsK6CnF", model="gpt-4o-mini" ) 这一步更详细的参数配置可以参考官方API文档。 上面这两步也可以在UI界面快速完成,提交任务后,也可以在UI界面实时查看进度和损失变化。 4 调用模型 通过下面的代码查询微调任务状态,作业成功后,就能看到fine_tuned_model字段填充了模型的名称。记下此名称,就可以进行调用了。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from openai import OpenAI client = OpenAI() # 查询微调任务列表 client.fine_tuning.jobs.list(limit=10) # 查询微调任务详情 client.fine_tuning.jobs.retrieve("ftjob-gvP0VB7RlWcF3QHdQrEVf49Y") # 取消任务 client.fine_tuning.jobs.cancel("ftjob-gvP0VB7RlWcF3QHdQrEVf49Y") # 查看任务中的日志 client.fine_tuning.jobs.list_events(fine_tuning_job_id="ftjob-gvP0VB7RlWcF3QHdQrEVf49Y", limit=10) # 删除微调模型 client.models.delete("ft:gpt-3.5-turbo:acemeco:suffix:abc123") 调用方式跟官方的模型是一样的,只需要修改一个模型名称就可以了,例如: 1 2 3 4 5 6 7 8 9 10 11 from openai import OpenAI client = OpenAI() completion = client.chat.completions.create( model="ft:gpt-4o-mini-2024-07-18:personal:0724:9oMH6S7A", messages=[ {"role": "system", "content": "Please write an SEO article of no less than 800 words based on the title I gave you, including at least 4 subtitles by HTML format. Do not include the <h1> , <body> tag. Do not include the <html> tag in the start and end of the content. Directly start with the content."}, {"role": "user", "content": f"title:{task.title},core keyword:{task.coreKeywords},related keyword:{task.relatedKeywords}"} ] ) print(completion.choices[0].message) 5 评估结果 训练过程中有两个指标可供参考,分别是损失值和Token准确率,官方解释如下: 验证损失和验证Token准确率通过两种不同的方式计算——在每一步期间的一个小批量数据上计算,以及在每个Epoch结束时的整个验证集上计算。整个验证损失和整个验证Token准确率指标是追踪模型总体性能的最准确指标。这些统计数据旨在提供一个合理性检查,以确保训练顺利进行(损失应该减少,Token准确率应该增加)。 但指标毕竟只是参考,实际效果还是要自己评估。微调后的模型至少有以下提升: 文章篇幅增长20% 文章结构更接近训练的数据 不会再出现格式错误(如markdown格式、添加css等) 以"What is the Difference Between a Mural and a Mosaic?“为题生成的文章如下: 6 参考文章 https://platform.openai.com/docs/guides/fine-tuning

2024/7/24
articleCard.readMore

AI Agent智能体四类设计模式:通用人工智能必经之路

AI Agent智能体四类设计模式:通用人工智能必经之路 如果把使用AI完成任务比喻成写作文,那么非智能体(Agent)的方式就是让AI从头到尾一次写完,不准修改,而Agent的方式则允许AI多次反复修改,并且在修改的过程中还可以借助工具、与外界合作交流。Agent,在2024年看来,是实现通用人工智能(AGI)的道路之一。 基础模型推动了生成式人工智能的发展,让AI Agent可以自动地帮用户完成任务。近一年来,各类Agent层出不穷。受吴恩达在红衫AI峰会的演讲启发,本文通过结合近一年内发表的论文和Langchain等工程博客,尽力整理了现有的Agent并总结出设计范式,希望能为设计基于基础模型的智能体提供帮助。 可初步整理出以下表格中的16中模式: 模式 简介 Passive goal creator 通过对话界面分析用户的明确提示,以保持交互性、目标追踪和直观性。 Proactive goal creator 通过理解人类交互和捕捉上下文来预见用户的目标,以增强交互性、目标追踪和可访问性。 Prompt/response optimiser 根据预期的输入或输出内容和格式优化提示/响应,以提供标准化、响应准确性、互操作性和适应性。 Retrieval augmented generation 在保持本地基础模型智能体系统实现数据隐私的同时,增强智能体的知识更新能力。 One-shot model querying 在单个实例中访问基础模型以生成计划所需的所有步骤,以提高成本效率和简化流程。 Incremental model querying 在计划生成过程的每一步访问基础模型,以提供补充上下文、提高响应准确性和解释性。 Single-path plan generator 协调生成实现用户目标的中间步骤,以提高推理确定性、连贯性和效率。 Multi-path plan generator 允许在实现用户目标的每一步创建多种选择,以增强推理确定性、连贯性、对人类偏好的对齐性和包容性。 Self-reflection 使智能体能够生成对计划和推理过程的反馈,并提供自我改进的指导,以提高推理确定性、解释性、持续改进和效率。 Cross-reflection 使用不同的智能体或基础模型提供反馈并改进生成的计划和推理过程,以提高推理确定性、解释性、互操作性、包容性、可扩展性和持续改进。 Human reflection 收集人类反馈以改进计划和推理过程,有效对齐人类偏好,提高可争议性、有效性、公平性和持续改进。 Voting-based cooperation 使智能体可以自由表达意见,并通过提交投票达成共识,以提高多样性、有效的分工和容错性。 Role-based cooperation 分配不同的角色,并根据智能体的角色最终确定决策,以提高决策的确定性、分工、容错性、可扩展性和责任性。 Debate-based cooperation 智能体通过辩论提供和接收反馈,调整其想法和行为,直到达成共识,以提高决策确定性、适应性、解释性、响应准确性和批判性思维。 Multimodal guardrails 控制基础模型的输入和输出,以满足特定要求,如用户要求、伦理标准和法律法规,以增强稳健性、安全性、标准对齐和适应性。 Tool/agent registry 维护一个统一且方便的来源,以选择不同的智能体和工具,以提高可发现性、效率和工具适用性。 这16种模式,都可以归结到吴恩达在红衫AI峰会的演讲中提出的4范式,分别是: Reflection Tool Use Planning Multiagent Collaboration 1 Reflection 1.1 Basic Reflection 在LLM Agent构建的背景下,反思(Reflection)是指提示LLM观察其过去的步骤(以及来自工具/环境的潜在观察)以评估所选行动的质量的过程。然后将这些反馈用于重新规划、搜索或评估等下游任务。下图是一种基本的反思模式。 Basic Reflection 1.2 Reflexion Actor 由 Shinn 等人提出的 Reflexion 是一种通过语言反馈和自我反思来学习的架构。这种Agent会点评其任务结果,以生成更高质量的最终结果,但代价是执行时间更长。主要包含三个组成部分: Actor (agent) with self-reflection 会自我反思的工人 External evaluator (task-specific, e.g. code compilation steps) 外部评委(特定任务,例如代码编译步骤) Episodic memory that stores the reflections from (1). 来自(1)的反思的情景记忆存储 Reflexion Actor 1.3 LATS 语言智能体树搜索(LATS),由 Zhou 等人提出,是一种通用的LLM Agent搜索算法,它结合了反思/评估和搜索(特别是蒙特卡洛树搜索),与类似技术如 ReACT、Reflexion 或 Tree of Thoughts 相比,能够实现更好的整体任务性能。 它有四个主要步骤: Select: pick the best next actions based on the aggregate rewards from step (2). Either respond (if a solution is found or the max search depth is reached) or continue searching. 选择:根据步骤(2)中的总奖励选择最佳的下一步行动。若找到解决方案或达到最大搜索深度,则进行响应,否则继续搜索。 Expand and simulate: select the “best” 5 potential actions to take and execute them in parallel. 扩展并模拟:选择“最佳”的 5 个候选行动并同时执行。 Reflect + Evaluate: observe the outcomes of these actions and score the decisions based on reflection (and possibly external feedback) 反思 + 评估:观察这些行动的结果,并根据反思(以及可能的外部反馈)对决策进行评分 Backpropagate: update the scores of the root trajectories based on the outcomes. 反向传播:根据结果更新根轨迹的分数。 LATS 2 Tool Use 调用工具,通过函数的形式使用。 3 Planning 3.1 ReAct ReAct通过结合推理和行动来增强智能体的能力。ReAct方法允许智能体在接收信息后立即作出反应,而不是等待所有信息处理完毕。同时这种方法还注重推理和行动的紧密结合,智能体不仅需要分析和理解输入信息,还需要根据分析结果进行相应的行动。这种方式的优点在于其灵活性和环境适应性。 ReAct框架 3.2 Plan and Execute Plan and Execute 核心思想是首先制定一个多步骤的计划,然后逐项执行该计划。在完成特定任务后,可以重新审视计划并进行适当修改。 这与典型的 ReAct 风格代理相比,后者是一次思考一步。这种“计划和执行”风格的优点是: 明确的长期规划(即使是非常强大的LLMs也难做到这点) 能够在执行步骤中使用较小/较弱的模型,仅在规划步骤中使用较大/较好的模型 Plan-and-Execute 3.3 ReWOO 在 ReWOO 中,Xu 等人提出了一种结合多步规划器和变量替换的智能体,以实现有效的工具使用。它通过以下方面改进 ReACT 风格的Agent架构: 通过一次性生成使用的完整工具链来减少token消耗和执行时间。(ReACT 风格的代理架构需要许多LLM调用,并且有冗余前缀(因为系统提示和前面的步骤在每个推理步骤中都提供给LLM) 简化微调过程。由于规划数据不依赖于工具的输出,模型可以在理论上不实际调用工具的情况下进行微调 Reasoning without Observation 3.4 LLMCompiler LLMCompiler 是一种通过在 DAG 中突击执行任务来加速agent任务的执行的Agent架构。它还通过减少对LLM的调用次数来节省冗余token使用的成本。主要包含三个部分: Planner: stream a DAG of tasks. 规划器:流式处理任务的有向无环图。 Task Fetching Unit: schedules and executes the tasks as soon as they are executable 任务获取单元:在任务可执行时立即调度和执行任务 Joiner: Responds to the user or triggers a second plan 连接器:响应用户或触发第二个计划 LLMCompiler 4 Multiagent collaboration 4.1 Supervison 通过一个监管者,管理和调度多个Agent进行协作。 监督方式 4.2 Hierarchical Teams 通过分层、分级组织Agent来完成复杂且工作量大的任务。AutoGen就是这种方式的典型代表。 分层团队方式 4.3 Collaboration 单个agent使用多种(领域)工具的能力有限,需要多个agent写作使用更多类型的工具。可以使用“分治法”的思想,让每个agent成为专注于处理一类问题的“专家”,然后再让他们进行合作。 一种基本的多智能体合作 5 评估 一种最直接的想法是使用一个agent作为“虚拟用户”进行评估,很多任务结果无法量化评估的任务可能不得不使用这种方式。但对于有明确指标的任务(分类、回归),也许可以直接利用一个工具进行评估。 Agent-based Evaluation 6 AGI的其它方式 Agent只是一种比较有希望的AGI方式,但并不是唯一方式。Agent方式本身可以和RAG、用户参与等方法有机结合。比如下面Shi等人结合Agent和检索的方式,实现了大模型解决奥赛编程问题。 7 推荐阅读 https://github.com/AGI-Edgerunners/LLM-Agents-Papers https://github.com/zjunlp/LLMAgentPapers AI agent智能体任务分解和调度的几篇经典文章 - bonelee - 博客园 (cnblogs.com) Agent四大范式 | CRITIC:吴恩达力推Agent设计范式 - 知乎 (zhihu.com) 8 参考 Kim, Sehoon, Suhong Moon, Ryan Tabrizi, Nicholas Lee, Michael W. Mahoney, Kurt Keutzer, and Amir Gholami. “An LLM Compiler for Parallel Function Calling.” arXiv, February 6, 2024. https://doi.org/10.48550/arXiv.2312.04511. Liu, Yue, Sin Kit Lo, Qinghua Lu, Liming Zhu, Dehai Zhao, Xiwei Xu, Stefan Harrer, and Jon Whittle. “Agent Design Pattern Catalogue: A Collection of Architectural Patterns for Foundation Model Based Agents.” arXiv, May 16, 2024. https://doi.org/10.48550/arXiv.2405.10467. Shi, Quan, Michael Tang, Karthik Narasimhan, and Shunyu Yao. “Can Language Models Solve Olympiad Programming?” arXiv, April 16, 2024. https://doi.org/10.48550/arXiv.2404.10952. Shinn, Noah, Federico Cassano, Edward Berman, Ashwin Gopinath, Karthik Narasimhan, and Shunyu Yao. “Reflexion: Language Agents with Verbal Reinforcement Learning.” arXiv, October 10, 2023. https://doi.org/10.48550/arXiv.2303.11366. Wang, Lei, Wanyu Xu, Yihuai Lan, Zhiqiang Hu, Yunshi Lan, Roy Ka-Wei Lee, and Ee-Peng Lim. “Plan-and-Solve Prompting: Improving Zero-Shot Chain-of-Thought Reasoning by Large Language Models.” arXiv, May 26, 2023. https://doi.org/10.48550/arXiv.2305.04091. Xu, Binfeng, Zhiyuan Peng, Bowen Lei, Subhabrata Mukherjee, Yuchen Liu, and Dongkuan Xu. “ReWOO: Decoupling Reasoning from Observations for Efficient Augmented Language Models.” arXiv, May 22, 2023. https://doi.org/10.48550/arXiv.2305.18323. Yao, Shunyu, Jeffrey Zhao, Dian Yu, Nan Du, Izhak Shafran, Karthik Narasimhan, and Yuan Cao. “ReAct: Synergizing Reasoning and Acting in Language Models.” arXiv, March 9, 2023. https://doi.org/10.48550/arXiv.2210.03629. “Yoheinakajima/Babyagi.” Accessed May 21, 2024. https://github.com/yoheinakajima/babyagi/tree/main. “LangGraph tutorials.” Accessed May 21, 2024. https://langchain-ai.github.io/langgraph/tutorials/ Zhou, Andy, Kai Yan, Michal Shlapentokh-Rothman, Haohan Wang, and Yu-Xiong Wang. “Language Agent Tree Search Unifies Reasoning Acting and Planning in Language Models.” arXiv, December 5, 2023. https://doi.org/10.48550/arXiv.2310.04406. Zhou, Pei, Jay Pujara, Xiang Ren, Xinyun Chen, Heng-Tze Cheng, Quoc V. Le, Ed H. Chi, Denny Zhou, Swaroop Mishra, and Huaixiu Steven Zheng. “Self-Discover: Large Language Models Self-Compose Reasoning Structures.” arXiv, February 5, 2024. https://doi.org/10.48550/arXiv.2402.03620.

2024/5/22
articleCard.readMore

向量数据库对比:Weaviate、Milvus和Qdrant

RAG系统的成功在很大程度上取决于其高效地获取和处理海量信息的能力。向量数据库又在其中发挥了不可替代的作用,并构成了RAG系统的核心。向量数据库专门用于存储和管理高维向量数据,它们能把文本、图像、音频甚至视频转换为向量并存储(这一点将在后文中详细阐述)。RAG系统最终能实现的效果就取决于这些底层向量数据库的表现。 在众多向量数据库和向量库中,每个都有自己的一些特点,选择一个适合自己应用场景的也需要经过评估。本文中将深入探讨选择向量数据库用于RAG时需要考虑的关键因素,包括开源可用性、CRUD(增删查改)支持、分布式架构、副本支持、可扩展性、性能和持续维护等6方面。 目前,像Weaviate、Milvus、Qdrant、Vespa和Pinecone这样的专为向量设计的数据库在行业中极受关注。除此之外,还有一些诞生较早的向量库也又这种功能。本文还将对比各种向量库,如FAISS、HNSWLib、ANNOY,以及支持向量功能的SQL数据库,如pgvector和Supabase等。 1 向量库(FAISS、HNSWLib、ANNOY) 向量数据库与向量库的区别在于,向量库主要用于存储静态数据,其中索引数据是不可变的。这是因为向量库只存储向量嵌入,而不存储生成这些向量嵌入的关联对象。因此,与向量数据库不同,向量库不支持CRUD(创建、读取、更新、删除)操作。这意味着在FAISS或ANNOY等向量库中向现有索引添加新文档可能比较难做到。HNSWLib就是这个例外,它就有CRUD功能,同时独特地支持并发读写操作。但是它也难逃作为一个向量库的局限性,即不提供部署生态系统、复制实例的能力以及容错性。 2 全文搜索数据库(ElasticSearch,OpenSearch) 全文搜索数据库(例如ElasticSearch和OpenSearch)能支持比较全面的文本检索和高级分析功能。但是当涉及到执行向量相似性搜索和处理高维度数据时,它们与专门的向量数据库相比就不够强了。这些数据库往往需要与其他工具搭配使用才能实现语义搜索,因为它们主要依赖于倒排索引而不是向量索引。根据Qdrant的测试结果,Elasticsearch在与Weaviate、Milvus和Qdrant等向量数据库相比时,性能有所落后。 3 支持向量的SQL数据库(pgvector、Supabase、StarRocks) 像pgvector这样的SQL数据库通过它们的向量支持扩展,提供了一种将向量数据整合到现有数据存储系统中的方式,但与专用的向量数据库相比,它们也又一些明显的缺点。 最明显的缺点是,传统SQL数据库的关系模型与非结构化向量数据的本质之间存在不匹配。这种不匹配导致了涉及向量相似性搜索的操作效率低下,这类数据库在构建索引和处理大量向量数据时性能表现并不理想,详见ANN测试。此外,pgvector支持的向量维度上限(2000维)与像Weaviate这样的专用向量数据库相比显得较低,后者能够处理高达65535维的向量数据。在可扩展性和效率方面,专用向量数据库也更有优势。支持向量的SQL数据库扩展,例如pgvector,更适合于向量数据量较小(少于10万个向量)且向量数据仅作为应用程序的一个补充功能的场景。相反,如果向量数据是应用的核心,或者对可扩展性有较高要求,专用向量数据库就会是更合适的选择。 至于StarRocks,它是另一个运行在SQL框架之上的系统,它针对在线分析处理(OLAP)和在线事务处理(OLTP)场景进行了优化,但也没有专门针对向量相似性搜索进行优化。 4 支持向量的NoSQL数据库(Redis,MongoDB) NoSQL数据库中新增加的向量支持功能尚属初级阶段,且尚未经过充分的测试验证。以Redis向量相似性搜索(VSS)为例,该功能刚于2022年4月对外发布,距今不足两年。Redis VSS虽然可以作为一个多功能数据库提供服务,但其并非专为向量相似性搜索而优化设计。 5 专用向量数据库(Pinecone、Milvus、Weaviate、Qdrant、Vald、Chroma、Vespa、Vearch) 专用向量数据库天生支持各种向量运算,如点积、余弦相似度等。这些数据库专为处理高维度数据而设计,能够应对大量查询请求,并能迅速完成向量间的相似性搜索。为了达到这些目标,它们采用了多种索引策略,通常基于近似最近邻(ANN)算法。这些算法需要在效率、存储空间占用和搜索准确性之间做权衡。比如,FLAT索引是一种不使用任何优化或近似技术的向量索引,意味着可以实现100%的召回率和精确度,但它也比其他类型的向量索引更慢且效率更低;相对而言,IVF_FLAT索引通过牺牲一些精确度,以换取更快的搜索速度;HNSW索引则在准确性和搜索速度之间提供了一个折中方案。 Pinecone是一个封闭源代码的向量数据库,由专业团队维护,其免费版本在可扩展性方面提供有限的功能。Chroma则是专门为音频数据设计的系统,但在处理文本数据方面并未进行特别优化。相较于其他主流的向量数据库,Chroma在综合性能基准测试方面的资料相对匮乏。由于Chroma在其0.4版本中采用SQLite作为文档存储方式,可能在可扩展性和效率上不及其他专为向量数据设计的存储方案。 Vearch和Vald在与Langchain的集成方面存在不足,这点对开发使用很不利。与Milvus等竞争者相比,它们的开发者社区规模较小,开源社区的维护也不够活跃。 因此,对于RAG来说,Weaviate、Milvus、Qdrant 和 Vespa可能是最好的几个选择。理论上来说,应该基于性能和可扩展性的基准测试(详见下文ANN Benchmarks ANN 基准测试)来选择最合适的系统。但是还有一些系统设计、功能特点也是需要对比的。下表就从这些方面进行了直观的对比。 数据库 Qdrant Weaviate Milvus 开源且可自托管 ✅ ✅ ✅ 开源协议 Apache-2.0 BSD Apache-2.0 开发语言 Rust Go Go, C++ Github Stars 17k 9.2k 26.2k 首次发布时间 2021 2019 2019 SDK Python, JS, Go, Java, .Net, Rust Python, JS, Java, Go Python, Java, JS, Go 托管云服务 ✅ ✅ ✅ 内置文本嵌入 ✅FastEmbed ✅ ❌ 混合检索 ❌ ✅RRF*+RSF* ✅表内多向量混合 元信息筛选 ✅ ✅ ✅ BM25支持 ❌ ✅ ✅ 文本搜索 ✅ ✅ ❌ 单点多向量 ✅ ✅ Tensor搜索 ❌ ❌ ❌ Langchain集成 ✅ ✅ ✅ Llama索引集成 ✅ ✅ ✅ Geo地理信息搜索 ✅ ✅ ❌ 多租户支持 ✅通过collections/metadata ✅ 元信息和文档大小限制 无限制 最大维度 无限制 65535 32768 索引种类 HNSW HNSW ANNOY, FAISS, HNSW, ScANN … 流式索引 ❌ 稀疏向量支持 ❌ ❌ ❌ 临时索引支持(不含服务器) ✅ ❌ 分片 价格 Facets(带有计数的聚合) ❌ ✅ 内置图像嵌入 ✅ 推荐API ✅ 个性化 用户事件 调用内置LLM用于RAG ✅Generative Search 数据库 Qdrant Weaviate Milvus 主观优点 1. 一个集合中可以存多种向量(图片、文字等) 2. 资源占用相当少 1. 性能相对不错 2. 支持内置嵌入 3. 支持文本搜索 4. GraphQL API 5. 支持S3备份 1. 官方支持的可视化操作界面 2. 较高的搜索准确率 3. 丰富的SDK 4. GPU加速 总结起来就是,Qdrant开销特别小,Weaviate支持向量搜索、对象存储和倒排索引的组合,Milvus性能最强、花活最多。 6 向量数据库的搜索方式对比 Milvus Weaviate Qdrant 独特的搜索方式 多向量搜索 BM25关键词搜索+混合搜索 关键词过滤应用于向量搜索 6.1 Milvus Milvus支持两种类型的搜索,取决于集合中的向量字段数量:单向量搜索和多向量搜索。 单向量搜索使用search()方法,比较查询向量与集合中现有的向量,返回最相似实体的ID及其之间的距离,也可以选择性返回结果的向量值和元数据。 多向量搜索适用于有两个或更多向量字段的集合,通过hybrid_search()方法执行,该方法执行多个近似最近邻(ANN)搜索请求,并结合结果进行重排以返回最相关的匹配。(最新的2.4.x版本才支持,最多支持用10个向量搜索) 多向量搜索非常适用于需要高精度的复杂情况,特别是当一个实体可以通过多个不同的向量表示时。这适用于同一数据(如一个句子)通过不同嵌入模型处理,或当多模态信息(如个人的图像、指纹和声纹)转换成各种向量格式的情况。通过表范围内的“多路召回”,并给这些向量分配权重,它们的综合作用可以明显增加召回能力,并提高搜索结果的有效性。 其它基本的搜索操作: 基本搜索包括单向量搜索、批量向量搜索、分区搜索和带指定输出字段的搜索。 过滤搜索基于标量字段的过滤条件来细化搜索结果。 范围搜索找到与查询向量在特定距离范围内的向量。 分组搜索根据特定字段对搜索结果进行分组,以确保结果的多样性。 6.2 Weaviate 向量相似度搜索:涵盖一系列近似搜索方法,这类搜索寻找与查询向量表示最为相似的对象。 图像搜索:使用图像作为相似度搜索的输入。 关键词搜索:一个使用BM25F算法来排名结果的关键词搜索。 混合搜索:将BM25和相似度搜索结合起来对结果进行排名。 生成式搜索:使用搜索结果作为LLM的提示。 重新排序:使用重排序模块对检索到的搜索结果进行重新排序。 聚合:从结果集合中聚合数据。 过滤器:对搜索应用条件过滤。 6.3 Qdrant 支持的基本搜索操作: 按相关分数过滤 单次请求负载多个搜索操作 推荐API 分组操作 Qdrant支持的其它搜索方式: Does Qdrant support a full-text search or a hybrid search? Qdrant首先是一个向量搜索引擎,我们只在不影响向量搜索用例的情况下实现全文支持。这包括界面和性能。 Qdrant能做什么: 使用全文过滤器搜索 将全文过滤器应用于向量搜索(即,在具有特定单词或短语的记录中执行向量搜索) 做前缀搜索和语义即时搜索 Qdrant未来计划引入的功能: 支持稀疏向量,如在SPLADE或类似模型中使用的 Qdrant不打算支持的功能: BM25或其他非向量基础的检索或排名函数 内置本体论或知识图谱 查询分析器和其他NLP工具 BM25和简单的关键词搜索有什么区别? 相关性评分: 简单的关键词搜索通常基于词频:如果一个词在文档中出现,那么这个文档就被认为是相关的。这种方法可能只计算关键词的出现次数,并且所有关键词都被视为同等重要。 BM25则采用更复杂的算法,不仅考虑词频,还考虑文档长度和词的逆文档频率(即在所有文档中的稀有程度)。这意味着BM25可以提供一个更为精细化的相关性评分,更好地反映查询与文档的匹配程度。 文档长度处理: 简单的关键词搜索可能不考虑文档的长度。这可能导致较长的文档(含有更多词语)被过分优先,仅仅因为它们有更多的机会包含关键词。 BM25通过其算法内部的标准化过程考虑了文档的长度,避免了这种偏向性,确保了长短文档在相关性评分上的公平性。 查询词的重要性: 在简单的关键词搜索中,所有关键词可能被等同对待,无论它们的普遍性如何。 BM25利用逆文档频率(IDF)来调整每个查询词的重要性。这意味着在较少文档中出现的词(更具唯一性的词)会给文档的相关性评分带来更大的影响。 参数调整: 简单关键词搜索通常没有太多的可配置参数来优化搜索结果。 BM25提供了参数(如k1和b),允许对算法的敏感度进行细致调整,以适应不同类型的文本和搜索需求。 与简单的关键词搜索相比,BM25提供了一种更为复杂和精细化的方法来评估文档和查询之间的相关性,可以产生更准确、更符合用户期望的搜索结果。 目前比较困扰的是,有没有一种方案,既能获得向量数据库的语义搜索特性,又能获得传统关键词搜索的精准特性呢? 7 附录 7.1 ANN Benchmarks 基准测试会受到多种影响数据库性能的因素的干扰,如搜索类型(过滤搜索或常规搜索)、配置设置、索引算法、数据嵌入、硬件等。除了基准测试的性能表现,选用向量库更应当考虑到分布式能力、内存副本与缓存的支持、采用的索引算法、向量相似性搜索的能力(包括混合搜索、过滤以及多种相似性度量)、分片机制、集群方法、可扩展性潜力、数据一致性和系统的整体可用性等多个方面。 ANN-Benchmarks 是评估近似最近邻算法搜索性能的主要基准测试平台。在文本检索中,向量数据库在角度度量上的性能往往比其在欧几里得度量上的性能更为重要。这是因为角度度量对文本文档的语义相似性更为敏感,而欧几里得度量对文档的长度和规模更为敏感。因此,在考虑检索增强生成的上下文时,更需要关注评估向量数据库在跨越不同维度的角度数据集上的性能。 7.1.1 glove-100-angular 7.1.2 nytimes-256-angular 7.2 向量相似度指标 指标 描述 支持的数据库 余弦距离 测量两个向量之间角度的余弦值 pgvector, Pinecone, Weaviate, Qdrant, Milvus, Vespa 欧几里得距离(L2) 在多维空间中计算两个向量之间的直线距离 pgvector, Pinecone, Qdrant, Milvus, Vespa 内积(点积) 计算向量对应分量的乘积之和 pgvector, Pinecone, Weaviate, Qdrant, Milvus L2平方距离 两个向量之间的欧几里得距离的平方 Weaviate 汉明距离 测量每个维度上向量之间的差异数 Weaviate, Milvus, Vespa 曼哈顿距离 沿直角轴测量两个向量维度之间的距离 Weaviate 以下是每个指标的详细介绍,包括它们的相对优势、劣势,以及它们适合的使用场景。 7.2.1 余弦距离 余弦距离测量两个向量之间角度的余弦值,常用于处理归一化或凸集。 优点:主要考虑向量的方向,这使其非常适合于高维空间,例如文本比较,因为在该场景文档的长度不那么重要。 缺点:不适用于需要匹配向量维度的场景,例如在根据像素密度比较图像的嵌入时。如果数据没有形成凸集,可能无法提供准确的相似性度量。 余弦距离适用于文档分类、语义搜索、推荐系统以及任何涉及高维度和标准化数据的其他任务。在检索信息时,余弦距离通常用于衡量查询内容和文档向量之间的相似度,忽略它们的长度,但专注于语义含义。 7.2.2 欧氏距离 L2 欧氏距离计算多维空间中两个向量之间的直线距离,也叫二范数。 优点:直观、易于计算、对向量的大小和方向都敏感。 缺点:由于“维度灾难”,可能在高维空间中表现不佳。 适用于图像识别、语音识别、手写分析等场景。 7.2.3 内积 内积计算向量对应分量乘积的和,也叫n范数。 优点:计算速度快,能反映向量的大小和方向。 缺点: 除了对向量的方向敏感,还对向量的大小敏感 内积最经典的应用在推荐系统领域。在推荐系统中,内积可用于确定用户向量和物品向量之间的相似度,帮助预测用户对某物品的兴趣。内积适用于推荐系统、协同过滤、矩阵分解。 7.2.4 L2平方距离 两个向量之间的欧几里得距离的平方。 优点:惩罚向量元素之间的大差异,在某些情况可能有用。 缺点: 平方操作可能会扭曲距离,并且对异常值敏感。 L2平方距离特别适合用于个别维度的差异问题,比如在图像处理中,比较两张图片的不同。 7.2.5 汉明距离 测量每个维度上向量之间的差异数量。 优点:适用于比较二进制或分类数据。 缺点: 不适用与连续或者数值型数据 适用场景也比较特殊,比如错误检测与纠正(分类型数据);测量两条DNA链之间的遗传距离。 7.2.6 曼哈顿距离 L1 测量两个向量维度沿着直角轴之间的距离,也叫一范数。 优点: 比欧几里得距离更能抵抗异常值。 缺点:在几何意义上不如欧式距离直观。 适用于计算棋盘距离、物流规划中的最短路径问题。 8 参考资料 https://github.com/milvus-io/milvus Powering AI With Vector Databases: A Benchmark - Part I - Data - Blog - F-Tech (farfetchtechblog.com) Fundamentals - Qdrant Milvus documentation Home | Weaviate - Vector Database Qdrant Documentation - Qdrant Vector Database Use Cases - Qdrant

2024/4/2
articleCard.readMore