第1章 SMILES 基础概念

做分子数据清洗,第一步不是写代码,而是搞懂 SMILES 到底是什么。我见过不少人拿着乱七八糟的 SMILES 字符串就往模型里灌,结果训练出来一堆废品。说白了,SMILES 就是分子的「身份证号」——但它有自己的一套语法规则。

1.1 SMILES 表示法简介

SMILES 全称是 Simplified Molecular Input Line Entry System,中文叫「简化分子线性输入规范」。1980 年代由 David Weininger 提出,后来成了化学信息学领域最通用的分子表示格式之一。你想想看,一个复杂的有机分子,几百个原子,用传统结构式画出来要半天,但用 SMILES 一行字符串就搞定了。

举个例子,乙醇的化学式是 C₂H₅OH,SMILES 写成:

CCO

就这么简单。三个字母,一个碳连一个碳再连一个氧。氢原子省略掉,因为有机化学里氢的数量可以通过化合价推断出来。这在数据清洗时特别重要——我刚开始处理 SMILES 时,老纠结氢要不要补全,后来发现大部分工具链默认都是「隐式氢」模式。

SMILES 的核心思想就一句话:用深度优先遍历的顺序记录分子图。从某个原子出发,沿着键走,遇到分支就加括号,遇到环就标数字。我个人的习惯是,先把分子结构式画在纸上,再按遍历顺序写出 SMILES,这样不容易出错。

关键认知: SMILES 不是唯一的。同一个分子可以有多种合法的 SMILES 表示。数据清洗的核心任务之一,就是把这些「同分异构」的 SMILES 标准化成统一形式。

1.2 原子与键

原子是 SMILES 的基本单元。常见的有机元素直接用元素符号表示:C、N、O、S、P、F、Cl、Br、I。对于其他元素,需要用方括号括起来,比如 [Fe]、[Na]、[Au]。

我踩过一个坑:钴的符号是 Co,两个字母。如果写成 CO,SMILES 解析器会把它当成「羰基」(碳氧双键)。这类歧义问题在数据清洗中特别常见,尤其是处理金属有机化合物时。所以我的建议是:所有非有机元素,一律用方括号显式标注。

元素类型 写法示例 说明
有机元素 C, N, O, S, P, F, Cl, Br, I 直接写符号,氢自动补全
其他元素 [Fe], [Na], [Au], [Co] 必须用方括号,避免歧义
同位素 [13C], [2H] 质量数写在元素符号前
电荷 [O-], [NH4+], [Fe+3] 正负号表示离子态

原子之间的连接用键符号表示:

  • 单键:直接写原子符号,如 CC(乙烷)
  • 双键:用等号 = ,如 C=C(乙烯)
  • 三键:用井号 # ,如 C#C(乙炔)
  • 芳香键:小写字母表示,如 c1ccccc1(苯)

注意,单键在 SMILES 里通常是隐式的。C-C 写成 CC 就行,不用写减号。但双键和三键必须显式写出。

小技巧: 处理芳香环时,用 c(小写)表示芳香碳,C(大写)表示脂肪碳。这是 SMILES 里最容易混淆的细节之一。我每次写苯环都会默念一遍「小写芳香、大写脂肪」。

1.3 分支与环

分子的分支结构用圆括号表示。括号里的内容接在前一个原子上,形成分支。来,看个例子:

异丙醇(2-丙醇)的结构是:中心碳连一个羟基,再连两个甲基。SMILES 写成:

CC(O)C

解析顺序是:C → C(第一个分支:连羟基)→ 回到主链 C。说白了,左括号就是「往下走一个分支」,右括号就是「分支结束,回到主链」。

嵌套分支也很常见。比如叔丁醇:

C(C)(C)C

两个甲基分支都挂在同一个碳上。这种写法在数据清洗时容易把人绕晕,我建议用工具画出来验证一下。

环结构的表示更巧妙。SMILES 用数字标记环的起点和终点。比如环己烷:

C1CCCCC1

这里的 1 就是环标记。从第一个 C 开始标 1,走到第六个 C 再标 1,表示这两个 C 之间连成环。如果分子有多个环,就用不同的数字:1、2、3……

我以前处理过一个含三个环的甾体分子,SMILES 长这样:

C12CCC3C(C1CCC2)C4(C3)C=CC(=O)C4

嗯,很绕对吧?实际清洗时,这种多环分子的 SMILES 一定要用标准化工具做一次「环标记重排」,否则不同来源的数据会乱成一锅粥。

避坑指南: 我曾经遇到一批数据,环标记用了数字 10、11 这样的两位数。有些解析器不支持两位数环标记!后来的 SMILES 规范虽然允许了,但老版本的 RDKit 会报错。保险起见,环标记尽量只用 1-9,少用两位数。

1.4 官能团表示

官能团在 SMILES 里没有特殊的「缩写」。它们就是按照原子连接关系写出来的。但有些官能团的写法很固定,熟悉了能提升你阅读 SMILES 的速度。

官能团 SMILES 示例 对应的分子
羟基 O (连在碳上) 乙醇 CCO
羰基 C=O 或 C(=O) 丙酮 CC(=O)C
羧基 C(=O)O 乙酸 CC(=O)O
氨基 N 或 N(...) 甲胺 CN
硝基 [N+](=O)[O-] 硝基苯 c1ccc(cc1)[N+](=O)[O-]
磺酸基 S(=O)(=O)O 甲磺酸 CS(=O)(=O)O

你看,硝基的写法比较特殊,要用方括号显式标出电荷。这是因为硝基中的氮带有形式正电荷,两个氧各带一半负电荷(共振结构)。SMILES 要求形式电荷必须显式写出,这一点在数据清洗时经常被忽略。

我处理过一个药物分子数据集,里面 30% 的硝基化合物 SMILES 都没有写电荷。用 RDKit 解析时会静默失败或者产生错误的结构。所以清洗时一定要做「形式电荷验证」这一步。

经验之谈: 数据清洗时,推荐先用 RDKit 的 MolFromSmiles 把字符串转成分子对象,检查是否成功。如果返回 None,要么是 SMILES 语法错误,要么是化合价不对。再配合 SanitizeMol 做一次结构验证,能过滤掉大量脏数据。

官能团表示还有一个坑:互变异构。比如酮式和烯醇式,它们是同一个分子的不同写法:

CC(=O)C   → 丙酮(酮式)
CC(O)=C   → 丙酮(烯醇式)

两种 SMILES 都是合法的,但描述的是同一个分子的不同互变异构体。数据清洗时要不要统一?这取决于你的下游任务。如果是物性预测,最好统一成最稳定的那种形式。

下面这张图总结了 SMILES 的核心结构要素,理清它们之间的关系,清洗时就不容易迷路:

SMILES 分子表示结构要素 SMILES 字符串 原子与元素符号 键的类型与连接 分支与环结构 有机元素 C,N,O… 方括号元素 [Fe] 单/双/三/芳香键 环标记 1,2,3… 分支括号 ( ) 环数字 1,2,3… 数据清洗要点 标准化:统一环标记 → 补全形式电荷 → 验证化合价 → 处理互变异构 工具:RDKit MolFromSmiles + SanitizeMol 是清洗流水线的起点

最后汇总一下日常清洗中最容易踩的四个坑:

  1. 环标记冲突: 不同来源的数据用了相同的数字标记不同的环,合并时需重新编号。
  2. 隐式氢歧义: 某些工具默认补氢方式不同,最好显式调用 AddHs 统一处理。
  3. 芳香性判断: Kekulé 形式(单双键交替)和芳香形式的 SMILES 不一致,建议统一用芳香形式。
  4. 电荷与同位素: 方括号内的信息容易被遗漏,清洗时要做完整性校验。
实用工具推荐: 我每次拿到新数据集,第一件事就是用 rdkit.Chem.MolFromSmiles 批量解析,再配合 rdkit.Chem.MolToSmiles 做一次标准化输出。这一步能消除 90% 以上的格式不一致问题。

一句话总结:SMILES 看着简单,但真正用好它,得把原子、键、分支、环、官能团这五个要素吃透。这章的基础打牢了,后面讲异构体标准化、盐类拆分、错误修复这些实操内容时,你才能跟得上节奏。