当我把全世界人群的基因 PCA 跑出来后,看见了一个倒 L 型

最近我把之前学的一些分子人类学知识,终于真正落地了。

不是停留在看论文、看别人画图、看别人解释“人群结构”这些概念,而是自己把数据处理完,自己跑 PCA,自己把全世界不同人群放到一张图上。

然后那一刻,我真的被击中了。

图上出现了一个非常漂亮的倒 L 型

一端是非洲,另一端逐渐拉向东亚,中间有中东、欧洲、南亚、欧亚大陆上的各种过渡人群。它不是那种随机散点图,而是有方向、有骨架、有历史感的结构。

我第一眼看到的时候,脑子里直接冒出一句话:

这不像是一张普通统计图,这像是人类迁徙史在二维空间里留下的影子。

当然,后来我也提醒自己,PCA 不能被过度浪漫化。它不是地图,也不是时间轴,更不是“谁从哪里走到哪里”的直接证据。PCA 本质上是把高维基因差异压缩到几个主成分上,用最大方差方向把样本摊开。它可以帮助我们观察人群结构、相似性、分化和混合,但不能单独承担全部历史解释。PCA 在群体遗传学里常用于观察 population structure 和 admixture,但解释时必须谨慎。(PMC)

但即便这样,那张图依然让我非常兴奋。

因为这不是我在书上看到的图。

这是我自己跑出来的。


倒 L 型:像极了“走出非洲”的宏观骨架

在全世界人群 PCA 上,非洲人群往往会和非洲外人群拉开很大距离。非洲内部遗传多样性本来就非常深,非洲和欧亚人群之间的差异也会形成非常强的主轴。

所以当我看到图上从非洲一端,经过中东、欧洲、南亚,再到东亚方向展开的时候,很自然会联想到“走出非洲”。

这个联想不是完全没有道理。

因为现代人类的主要扩散确实是从非洲走向欧亚,再沿着不同路线分化、扩张、混合。PCA 把这些深层差异压缩之后,就会出现某种“地理-遗传连续性”的视觉效果。

但关键点是:

PCA 图像看起来像迁徙路线,不等于它就是迁徙路线。

它更像是一张“遗传相似性地图”。

离得近,通常表示基因频率结构更相似;离得远,通常表示差异更大。至于这个差异来自古老分化、地理隔离、遗传漂变、混合,还是样本选择影响,需要继续分析。

这也是我这次最大的收获之一:

图很震撼,但不能只靠震撼解释图。


PC2、PC3 才是真正打开细节的地方

以前我也和很多人一样,看到 PCA 就只看 PC1 vs PC2。

但真正跑起来之后才发现,PC2、PC3、PC4 这些后面的主成分,才是继续拆结构的地方。

PC1 vs PC2 更像世界地图,负责展示最宏观的人群分化。

PC2 vs PC3 可能会把原来挤在一起的区域展开,比如东亚内部、南亚内部、中亚和西亚之间的梯度。

PC3 vs PC4 则更像显微镜,能看到更局部、更细的人群结构。

所以现在我对 PCA 的理解变成了:

PC1/PC2:看宏观骨架
PC2/PC3:看区域结构
PC3/PC4:看局部细节

而且还有一个很重要的点:

PC1、PC2、PC3 没有固定含义。

不是说 PC1 永远代表“非洲 vs 非洲外”,PC2 永远代表“欧洲 vs 东亚”。它取决于你放进来的样本是谁、每个人群样本量多少、有没有做 LD pruning、有没有去亲缘、有没有异常点。

所以正确问题不是:

“PC2 到底是什么意思?”

而是:

“在我这批样本里,PC2 把哪些人群拉开了?”

这个思路一下子让我觉得 PCA 活了起来。


最有意思的意外:马达加斯加人出现在空白处

本来我以为这个倒 L 型已经够震撼了。

结果我又注意到一个特别有意思的点:马达加斯加人群

他们在 PCA 上出现在一个有点“空白”的位置。第一眼看,很容易让人误以为:这是不是“走出非洲”的另一条路线?是不是非洲到东亚之间还有一条经由马达加斯加的古老支线?

这个想法很诱人。

但继续查资料之后,我发现不是这么回事。

马达加斯加人,也就是 Malagasy 人群,本身就是一个非常特殊的混合人群。他们主要有两股祖源:一股是非洲东部/班图相关祖源,另一股是南岛/东南亚相关祖源。2014 年 PNAS 的研究认为,研究中的 Malagasy 人群来自 Austronesian 和 Bantu 遗传成分的近期混合,其中 Bantu 相关成分至少约 60%,Austronesian 成分约 30%,而南岛相关来源可能与 Java-Kalimantan-Sulawesi 区域有关。(PMC)

这就解释了为什么他们会出现在 PCA 的“空白处”。

因为 PCA 里有一个很重要的现象:

混合人群经常会落在源人群之间。

如果一个人群同时有非洲祖源和东南亚/南岛祖源,它就不会单纯落在非洲团里,也不会单纯落在东亚或东南亚团里,而是会被两个方向一起拉到中间。

于是图上看起来就像多了一条“路线”。

但这条线不是远古迁徙路线。

它更像是一个混合投影:

非洲/班图相关祖源  +  东南亚/南岛祖源
                  ↓
              Malagasy

这也是为什么当我把这些人群加进 PCA 后,原来的倒 L 型会变得像三角形。

因为图上突然出现了第三个强拉力点。


南岛人真的到达了马达加斯加,而且时间并不算远古

更神奇的是,南岛人真的跨过印度洋到达了马达加斯加。

这个事情第一次意识到的时候,我觉得很不可思议:一群和今天婆罗洲、印尼、南岛世界相关的人,居然一路到了非洲旁边的马达加斯加。

这不是几万年前“走出非洲”级别的古老事件,而更像是历史时期或中世纪前后的跨海迁徙和混合。

2018 年 Nature Communications 的研究提到,Malagasy 人群来自 Asian/Austronesian 和 African/Bantu 背景的混合,混合大约发生在 27 代前。(Nature) 2017 年关于马达加斯加人群多样性的研究也指出,马达加斯加全岛个体共享近期 Austronesian 和 Bantu 祖源,并估计 proto-Malagasy 与南部非洲 Bantu 相关人群的分化大约在 1500 年前,与南婆罗洲相关人群的分化约在 3000 到 2000 年前。(PMC)

所以这件事的时间深度大概不是几万年,而是几千年到一千年左右这个尺度。

一开始我还觉得:那好像和尼安德特人混合、丹尼索瓦人混合、走出非洲这些远古事件比起来,不算太“深”。

但后来一想,它的价值不在于远古。

它的价值在于:

这是一个非常远距离、非常戏剧性的历史时期跨海迁徙。

从东南亚到马达加斯加,这条线如果画在地图上,本身就非常震撼。更有意思的是,Malagasy 语言属于南岛语系,这说明南岛人不只是留下了一点基因痕迹,而是在语言和文化层面也留下了非常深的影响。关于 Malagasy 的亚洲来源,2016 年的研究也支持东南婆罗洲相关人群在 Malagasy 亚洲祖源形成中扮演重要角色。(PMC)

也就是说,PCA 上那个点不是普通的离群点。

它背后是一段印度洋上的人类故事。


这次真正让我兴奋的,不只是图,而是理解方式变了

我以前可能会把 PCA 当成一种“工具”。

现在感觉不一样了。

它像一个入口。

你把全世界的人群放进去,它会先给你一个宏观骨架:非洲、欧亚、东亚、南亚、美洲、大洋洲,各自被拉到不同方向。

然后你换 PC2/PC3、PC3/PC4,它会继续打开更细的结构。

你再加入特殊人群,比如马达加斯加人,它又会突然告诉你:这里有混合,这里有跨海迁徙,这里不是简单的线性历史。

所以我现在越来越觉得,PCA 最有意思的地方不是“它告诉了我答案”。

而是它不断逼我问更好的问题:

这个轴到底拉开了谁?
这个中间位置是连续迁徙,还是混合?
这个三角形是三个源人群,还是样本结构造成的?
这个离群点是历史事件,还是数据处理问题?

这才是真正好玩的地方。


最后:PCA 不是历史本身,但它能让历史浮现出来

这次做完之后,我最大的感受是:

人类历史不是只存在于文字、遗址和传说里。它也藏在基因频率的结构里。

当然,PCA 不是万能的。

它不能单独证明迁徙路线,不能单独给出混合时间,也不能替代 ADMIXTURE、f-statistics、qpAdm、TreeMix、IBD、单倍群、古 DNA 等更深入的分析。

但它可以作为第一张地图。

它告诉你哪里有结构,哪里有梯度,哪里有混合,哪里有异常。

而我这次最兴奋的地方就在这里:

我不是看别人画了一张图。

我是真的自己把数据跑出来,然后在图上看见了一个倒 L 型。

那一瞬间,我感觉自己不是在看一堆点。

我是在看人类迁徙、分化、混合和重逢,被压缩成二维之后留下的痕迹。

这就是分子人类学最迷人的地方。

一张图,既是数学,也是历史。

既是数据,也是人类自己。

发现了这本书 嘿嘿 开始阅读

Read more

把 Codex CLI 的登录态"搬"到一台新服务器

场景:你在一台老机器上早就登录好了 Codex CLI,现在开了台新服务器、装好了 codex,但它没登录。你不想在新机上重新走一遍 OAuth 网页授权(有时候服务器上根本打不开浏览器),只想把老机器上那份"已经登录好的身份"复制过去。 这篇讲的就是这个搬运动作的完整方法论——为什么能搬、怎么搬、有哪些坑。命令里所有隐私都用占位符,照着换成你自己的即可。 一、先理解一件事:Codex 的登录就是一个文件 这是整个操作的地基。Codex CLI(ChatGPT OAuth 登录模式下)的登录状态,不在什么系统钥匙串里,也不在环境变量里,就是家目录下一个单独的 JSON 文件: ~/.codex/auth.json 它长这样(字段名是真的,值我打码了): { "auth_mode": "

By ladydd

哨兵机制:让 Agent 一触即醒

0. 一句话点破本质 **让"等"发生在便宜的子进程里,让贵的 agent 只在有事时醒。**心跳解决"最迟多久必有人查岗",探针解决"事情一发生几乎立刻有人到场"——两个机制回答的是两个不同的问题,谁也替代不了谁。 1. 机制全貌:会自杀的轮询进程 + 宿主的"尸体通知" 我的实现只有两块积木: 积木一:一个有明确死法的后台循环 # 放行任务的同时,后台挂上(run_in_background) for i in $(seq 1 20); do 信号=$(ssh data "tmux capture-pane -t dna

By ladydd

Agent 心跳机制·设计与实现

0. 一句话点破本质 **心跳不是闹钟,是"带着完整世界快照的自我唤醒"。**闹钟只解决"什么时候醒";心跳真正要解决的是你点出的那个问题——醒来的那个瞬间,清楚自己是谁、任务到哪了、这一跳该干什么。我所有跑得好的心跳,提示词都写得像给一个失忆的陌生人看的;所有出过事的心跳,都是因为假设"我还记得"。 1. 第一性原理:为什么"醒来知道干啥"这么难 一个长期任务里的 agent 面临三重失忆: 1. 上下文会被压缩——多轮之后早期细节只剩摘要,心跳打进来时,那条心跳提示词可能是上下文里唯一高保真的任务描述 2. 世界在你睡着时变了——下属可能干完了、卡死了、跑偏了,你脑子里的"进度"从睡着那刻就开始过期 3. 任务本身会变—

By ladydd

我没手动映射 3000,公网为什么还能访问?一次 UPnP 误开孔复盘

写在前面:标题里的“自己打开”只是当时的主观感受。路由器没有失控,也不存在神秘穿透。真正发生的是:排障自动化从局域网主动调用了 UPnP AddPortMapping,路由器按协议新增了公网映射。 1. 原本的设计边界 家里的 Open WebUI 跑在一台 Ubuntu 主机的 Docker 中: 内网主机 192.168.x.x:3000 路由器上手动配置的入口是: 公网 TCP 13000 → 内网主机:3000 外部用户不直接访问家宽端口,而是先到云端 Caddy: 用户浏览器 → https://ai.example.com (云端 Caddy) → http://home.example.com:13000 (DDNS → 家宽公网

By ladydd
陕公网安备61011302002223号 | 陕ICP备2025083092号