简介:一份围绕人工智能与分析化学交叉应用的PPT课件,面向化学、化工、药学等专业师生及科研人员,用于快速建立人工智能赋能分析化学的整体认知。课件从智能与人工智能的基本概念讲起,梳理生物智能、人工智能与计算智能之间的关系,并围绕认知学派、逻辑学派、行为主义学派和连接主义学派的研究思路展开;同时结合专家系统的知识库、推理机等核心组成,说明人工智能在谱图解析、分离条件选择、实验方案优化、分子模拟设计等场景中的具体应用。全包仅含1个PPT文件,大小3.48MB,页面编排清晰,便于课堂演示或自学浏览。目前已有150人学习,适合作为分析化学、化学信息学等相关课程的教学辅助或入门资料,帮助读者理解人工智能在数据分析、模式识别与化学信息处理中的落地方式。
1. 从分析化学数据到人工智能决策:一个光谱解析的硬仗
分析化学仪器一年产出的数据量,远超一个熟练实验员能手工处理的范围。比如一台高分辨质谱一个批次就能生成上千个特征片段,红外光谱仪每天跑200张谱图也常见。人工智能技术的价值,是把传统上依赖经验识谱的工作压缩成一条可训练的流水线:数据洗到标准化,模型学会区分官能团,误差用一个置信区间告诉化学家“该相信多少”。这篇内容面向正在把实验室数据接入机器学习平台的工程师,也面向想用AI替代手动谱图解析的分析化学从业者。不堆公式,只讲能落地的那部分。
2. 分析化学中的AI数据管线:预处理、基线校正与特征选择
分析化学的数据天生不适合直接扔进神经网络。原因很简单:不同仪器、不同批次的谱图,噪声和基线漂移各有差异;如果跳过预处理,模型学的不是化学信息,而是仪器状态。我一般把数据管线拆成四步:质量检查、平滑、基线与归一化、特征选择。这四步做完,后续建模才可能稳定跨批次复现。
2.1 光谱数据的标准化与异常值剔除
先看原始矩阵:行为样本,列为波长或质荷比。很多开源数据集里含有空值或明显异常值,比如透光率大于100%,或者负强度。第一步不是插值,而是先用统计方法把物理上不可能的点剔除。常见做法是计算每个样本的均值与标准差,再用z-score过滤。
import numpy as np import pandas as pd # 假设 X 是 (n_samples, n_features) 的光谱矩阵,sample_names 是样本名 df = pd.DataFrame(X) df.columns = [f"wavelength_{i}" for i in range(df.shape[1])] df["mean"] = df.mean(axis=1) df["std"] = df.std(axis=1) z_scores = np.abs((df["mean"] - df["mean"].mean()) / df["mean"].std()) valid_idx = z_scores < 3.5 df_clean = df.loc[valid_idx, df.columns[:-2]]这段代码计算每个光谱的全局均值,再对整个样本集做一次z-score过滤。3.5是经验阈值,太大会放过异常样本,太小会把正常样本误杀;如果你处理的是拉曼光谱,建议调到3.0,因为拉曼峰强度分布更重尾,普通均值阈值容易失真。
剔除异常后,再接标准化。分析化学里标准化的方式不是一律用MinMax,而是根据后续模型选择。若用SVM或PCA,用StandardScaler;若用树模型,根本不需要标准化,反而保留原始量纲可以保留峰的物理意义。我通常同时跑两套,先看哪一套交叉验证分数更高,再决定最终管线。
2.2 基线校正与平滑:用SciPy拟合基线
基线漂移是光谱分析最常见的坑。它来自荧光背景、光散射或仪器基线。代码上的处理核心是:用少量参数拟合一条平滑基线,再从原始谱图中减掉。常用的方法有airPLS、多项式拟合法和移动平均。这里给出一个用SciPy做多项式基线校正的案例:
from scipy.linalg import cholesky import numpy as np def polynomial_baseline(y, order=3, max_iter=100, ratio=0.01): x = np.linspace(0, 1, len(y)) mask = np.ones_like(y, dtype=bool) for _ in range(max_iter): coeffs = np.polyfit(x[mask], y[mask], order) baseline = np.polyval(coeffs, x) residual = y - baseline new_mask = residual >= -ratio * np.max(y) if np.all(new_mask == mask): break mask = new_mask return baseline这个迭代过程中,每次只保留高于当前基线的点拟合新基线,重复几次后,基线逐渐贴近谱图的底部。order=3适合色谱基线;红外光谱建议order=5,因为其基线弯曲更复杂。ratio=0.01控制阈值,如果背景噪声很大,可以适当调大,但太大会把弱峰一起抹掉。
下表是我在真实项目中比较几种基线方法的经验值:
| 方法 | 适用数据 | 参数建议 | 缺点/坑 |
|---|---|---|---|
| airPLS | 拉曼光谱、强噪声 | lambda=10^5,porder=1 | 对尖锐峰敏感,会削峰 |
| 多项式迭代 | 红外、紫外 | order=3~5,iter=100 | 需要合理初始阈值 |
| 移动平均 | 色谱基线 | window=5~15 | 窗口太大会抹掉相邻峰 |
移动平均窗口如果设置成15,对窄峰意味着把峰形拉宽,保留时间会发生偏移。因此,平滑步骤永远在基线校正之后做,顺序反了会出现“假双峰”。这一步做完,整个数据管线才敢进入建模。
2.3 特征选择:不要直接拉平整个谱图
很多AI教程喜欢把全谱输入模型,这在分析化学中常常失败。原因有两个:一是谱特征有高共线性,连续波长的数值高度相关;二是无关变量会稀释模型的信号。我建议先在降维前用统计学方法做一个粗筛:计算每个特征与目标变量的相关度或ANOVA F值,再选前K个特征。
from sklearn.feature_selection import SelectKBest, f_classif selector = SelectKBest(score_func=f_classif, k=200) X_selected = selector.fit_transform(X_clean, y) selected_idx = selector.get_support(indices=True)这里的f_classif适用于分类问题,如果是回归用f_regression。选200个特征是一个起始经验值,具体需要根据谱图分辨率调整。特征选择这一步能让你后续建模时的过拟合风险下降一大截,也便于向实验人员解释哪些波长的峰参与了决策。做完特征选择后,要把选中的特征索引保存下来,后续对未知样本做预测时,必须用同一索引切出对应特征,否则维度对不上。
如果你的数据本身来自LC-MS轮廓,峰位对齐后会有数千个特征,直接用全谱会让随机森林的OOB得分虚高。用SelectKBest粗筛后,再进入PCA或PLS做二次压缩,是比较稳妥的路径。常见做法是先化学规则筛除同位素峰,再做统计筛选,最后用模型自身的feature importance回头验证。
3. 用机器学习构建分析化学分类与回归模型:以红外光谱和色谱为例
当数据预处理管线稳定后,下一步就是训练模型。分析化学领域的机器学习项目,分类任务常见的有:识别未知物是否含特定官能团、判别纯物质与混合物、质谱谱库检索。回归任务则包括浓度预测、保留时间预测、定量分析。你要先明确任务是分类还是回归,再选模型。下面我从分类和回归各举一个例子。
3.1 红外光谱分类:SVM与随机森林的取舍
红外光谱数据经过基线校正后,特征往往有几百维。对于中小样本集,通常几百个样本,支持向量机(SVM)以径向基核函数为默认选择。随机森林则适合你同时想看到特征重要性的场景。下面是一段完整的分类训练流程:
from sklearn.svm import SVC from sklearn.ensemble import RandomForestClassifier from sklearn.preprocessing import StandardScaler from sklearn.pipeline import make_pipeline from sklearn.model_selection import cross_val_score, train_test_split # X_selected, y 来自上一章的预处理 X_train, X_test, y_train, y_test = train_test_split(X_selected, y, test_size=0.2, random_state=42) svm_model = make_pipeline(StandardScaler(), SVC(kernel="rbf", C=10, gamma=0.01, probability=True)) svm_model.fit(X_train, y_train) rf_model = RandomForestClassifier(n_estimators=300, max_depth=5, min_samples_leaf=3, random_state=42) rf_model.fit(X_train, y_train) print("SVM CV score:", cross_val_score(svm_model, X_train, y_train, cv=5).mean()) print("RF CV score:", cross_val_score(rf_model, X_train, y_train, cv=5).mean())注意,SVM在管道里先做StandardScaler,这是因为径向基核函数依赖距离度量;随机森林不需要标准化,但为了统一代码,这里把它放在同一交叉验证逻辑下。C=10和gamma=0.01是我在红外数据集上常用的起始点。对于拉曼光谱,C在1~100之间,gamma则要更小,比如0.001,因为拉曼峰更尖,核函数对尺度更敏感。
如果你的样本量不足百,建议使用留一法(LOO)替代普通5折交叉验证。化学数据的数据量通常小,5折容易高估模型性能,留一法虽然慢,但能更真实反映单样本预测的场景。这也是人工智能基础概念里经常会强调的小样本陷阱。
3.2 色谱保留时间预测:从线性回归到梯度提升
在色谱分析中,一个常见任务是根据分子描述符预测保留时间。保留时间与分子结构之间存在复杂的非线性关系,用随机森林或梯度提升树(GBT)比线性回归更稳。这里以LightGBM为例:
import lightgbm as lgb model = lgb.LGBMRegressor( n_estimators=500, learning_rate=0.05, num_leaves=31, max_depth=-1, min_child_samples=5, subsample=0.8, colsample_bytree=0.6 ) model.fit(X_train, y_train) y_pred = model.predict(X_test)num_leaves限制树的复杂度,对于分子描述符这种中等维度的特征,31是一个常用值。colsample_bytree=0.6让每棵树的特征随机采样60%,能降低特征共线性造成的影响。min_child_samples=5用于防止过拟合,小数据集尤其关键,太小会导致叶子节点几乎都是单个样本。
这里是几种回归算法的对比表格,供你选型:
| 算法 | 线性回归 | 随机森林回归 | LightGBM |
|---|---|---|---|
| 对特征尺度 | 敏感 | 不敏感 | 不敏感 |
| 过拟合风险 | 低 | 中等 | 中高 |
| 可解释性 | 高 | 中等 | 低 |
| 典型R² | 0.6 | 0.8 | 0.85 |
如果你的保留时间数据来自不同液相色谱系统,记得加入系统ID作为特征,否则模型会把系统差异学成样本差异,预测值在跨系统时会系统性偏移。比如ACQUITY和Agilent的梯度和流速不同,模型需要显式感知这个环境变量。
3.3 模型参数与化学意义的对齐
这可能是分析化学中的AI项目最特殊的一点:模型不只是看准确率,还要看它学习的特征是否对应着化学上可解释的峰位。比如SVM的决策边界应该与分子振动频率相关。我的经验是,如果模型在某个波长处的权重很大,而这个波长正好对应某个官能团的特征峰,那么模型的可靠性就更高。反之,模型可能只是在用噪声做判断。
所以,建好模型后,一定要把特征重要性系数映射到波长上,可视化后与已知谱峰表对比。这个习惯会减少很多“为什么测试集上表现好、换一台仪器就崩”的问题。如果项目时间紧,可以把这一步放在模型部署之后,但不要省略。生成式人工智能应用工程师相关的课程里也会强调,模型输出前必须做特征归因,否则实验人员不敢签字。
4. 深度学习在质谱与拉曼光谱中的实战:从CNN到Transformer
当样本量达到几千条,机器学习方法容易遇到上限。深度学习可以自动挖掘谱图中局部相邻特征的关系,这正是分析化学中“峰形+相邻峰”的组合特征。在质谱与拉曼光谱中,一维卷积(1D-CNN)是常见做法;近年Transformer也开始被用于跨谱图关联建模。如果你正处在人工智能学习路径的实践阶段,这部分可以直接当项目模板用。
4.1 一维卷积模型:把光谱当作时间序列
光谱本质上是等间隔采样的序列信号,因此和音频信号类似,适合用卷积核捕捉局部峰形。下面是用PyTorch实现的一个轻量级1D-CNN:
import torch.nn as nn class SpecCNN(nn.Module): def __init__(self, n_features, n_classes): super().__init__() self.conv1 = nn.Sequential( nn.Conv1d(1, 16, kernel_size=7, padding=3), nn.BatchNorm1d(16), nn.ReLU(), nn.MaxPool1d(2) ) self.conv2 = nn.Sequential( nn.Conv1d(16, 32, kernel_size=5, padding=2), nn.BatchNorm1d(32), nn.ReLU(), nn.MaxPool1d(2) ) self._init_fc_dim(n_features) self.fc = nn.Linear(self.fc_dim, n_classes) def _init_fc_dim(self, n_features): import torch x = torch.zeros(1, 1, n_features) x = self.conv1(x) x = self.conv2(x) self.fc_dim = x.view(1, -1).size(1) def forward(self, x): x = self.conv1(x) x = self.conv2(x) x = x.view(x.size(0), -1) return self.fc(x)kernel_size=7对应光谱中7个连续波长。对于拉曼光谱,这大约覆盖几十个波数,足以捕捉一个峰的基本形状。BatchNorm1d在化学数据上特别有用,能抑制不同批次样本的基线波动。注意,如果原始谱图是长序列,比如LC-MS轮廓,可以先做下采样到2048点,否则卷积层会太深,参数量过大。训练模型时,建议用Adam优化器,学习率从1e-4开始,batch size设32。如果出现过拟合,先降低kernel_size或增加Dropout层,不要一上来就加大数据增强。
4.2 从CNN到Transformer:为什么现在开始用Attention
在质谱数据中,峰的相对位置和强度对于物质识别至关重要。CNN的感受野始终有限,要覆盖跨大范围的峰关系必须堆很多层。Transformer的self-attention理论上可以在第一层就“看到”整个谱图。对长色谱或质谱轮廓,这是一个明显优势。
一个常见的做法是先把光谱切成patch,和ViT类似;或者直接对每个质荷比位置做位置编码后输入Transformer encoder。但需要注意,质谱数据通常高度稀疏,直接对原始序列做attention计算量很大。我会先做一个简单投影:把N个特征投影到较小的隐层维度,再进入Transformer。
import torch.nn as nn import torch class SpecTransformer(nn.Module): def __init__(self, n_features, d_model=256, n_heads=4, n_encoder_layers=2): super().__init__() self.proj = nn.Linear(1, d_model) self.pos_enc = nn.Parameter(torch.randn(1, n_features, d_model) * 0.02) encoder_layer = nn.TransformerEncoderLayer( d_model=d_model, nhead=n_heads, dim_feedforward=1024, batch_first=True ) self.encoder = nn.TransformerEncoder(encoder_layer, num_layers=n_encoder_layers) self.fc = nn.Linear(d_model, 1) # 输出一个目标值 def forward(self, x): # x: (batch, features),将每个特征视为一维token x = x.unsqueeze(-1) # (batch, features, 1) x = self.proj(x) # (batch, features, d_model) x = x + self.pos_enc x = self.encoder(x) # (batch, features, d_model) return self.fc(x.mean(dim=1))这里把每个波长或质荷比视作一个token,位置编码是学习的,不是固定正弦。n_encoder_layers=2通常够用于几千样本的项目,太深反而容易过拟合。d_model=256对于常见光谱长度500至2000点来说是一个平衡点,再大会导致显存占用过高。该模型适合回归,如果要分类,把self.fc的输出节点改一下或者接上softmax即可。
4.3 深度学习在分析化学中容易吃到的亏
第一个坑是数据增强不合理。常见的加噪声增强在拉曼光谱上会放大基线残留,应该先在原始谱图上做峰位微小的随机平移,比如平移1到2个通道,模拟仪器波长校准的微小漂移。第二个坑是样本数不足,1500个样本以下的深度学习常常不稳定,要谨慎使用,否则不如第3章中的SVM或随机森林。第三个坑是类别不平衡,比如质谱库中某些物质出现很多,需要加权采样或使用focal loss。
| 模型 | 数据量要求 | 训练耗时 | 可解释性 | 适用谱图类型 |
|---|---|---|---|---|
| 1D-CNN | >2000 | 低 | 中 | 红外/拉曼/色谱 |
| Transformer | >5000 | 高 | 低 | 质谱/高分辨轮廓 |
这张表可以作为你启动深度学习项目前的快速筛选器。数据量不到标准时,优先回头用经典化学计量学方法,而不是强行上大模型。分析化学项目很看重可复现性,一个5000样本的Transformer训练结果如果波动很大,反而不如一个稳定的随机森林。
5. 分析化学AI模型的可靠性与可解释性验证技巧
模型训练完之后,不能只看测试集分数。分析化学对错误判断的容忍度很低,比如把一个有毒物质判成无毒的后果是灾难性的。所以这一章集中在“如何验证模型不是偶然跑得好”,以及“如何让化学家信任模型判断”这两个具体问题上。
5.1 置换重要性检验:判断模型是否在用噪声
置换重要性(Permutation Importance)的基本思路是随机打乱一个特征的值,看模型性能下降多少。如果打乱某个波长导致分数显著下降,说明模型确实依赖该特征;如果所有特征都下降很小,那模型可能已经过拟合了样本序号或批次信息。
from sklearn.inspection import permutation_importance result = permutation_importance( svm_model, X_test, y_test, n_repeats=30, random_state=42 ) sorted_idx = result.importances_mean.argsort()[::-1] print(sorted_idx[:10])n_repeats=30会让重要性估计稳定一些,但耗时也高。对于几百个样本的小数据集,建议调到20。这一步能直接暴露那些“通过批次信息学到的假规律”。正常做法是打乱样本顺序后重新训练多次,对比性能分布,但这个成本太大,工程上通常用置换重要性做替代。
5.2 用SHAP把特征归因到波数,而不是只看排名
交叉验证和置换重要性只能告诉你“哪个特征重要”,却无法告诉你“峰高了还是低了更有助于分类”。分析化学领域需要量化方向性,比如某个物质浓度越高,模型越倾向于判定为污染。这时候使用SHAP值。
import shap explainer = shap.Explainer(rf_model, X_train) shap_values = explainer(X_test) # shap_values.shape == (n_test, n_features, n_classes) for i in range(min(3, len(X_test))): shap.waterfall_plot(shap_values[i], max_display=15)如果用的是SVM,需要先传svm_model[1],因为管道里第0步是标准化器。shap.Explainer对树模型有原生支持,对普通模型会慢一些。在化学项目中,我习惯把SHAP值按波长保存成CSV,然后叠加到原始谱图上做叠加展示。这个可视化的作用很大,实验员看到模型关注的吸收峰刚好是羟基峰,才会认可这个模型。
输出CSV时,记得把波长轴和SHAP值对齐:
import pandas as pd shap_df = pd.DataFrame(shap_values.values.mean(axis=0).T, columns=["shap_mean"]) shap_df["wavelength"] = wavelengths[selected_idx] shap_df.to_csv("shap_by_wavelength.csv", index=False)这里的wavelengths[selected_idx]对应特征选择后的位置。如果后续更换了特征选择参数,必须重新生成映射,否则波长标注会错位。将这份CSV嵌入到实验数据管理系统中,就能让每个预测样本都附带一份可追溯的归因报告。
模型偏见在光谱数据上的表现往往是“局部波段的错误高权重”。如果某几个SHAP值明显集中在噪声区,就说明预处理阶段有遗漏。此时返回第2章检查平滑窗口和基线校正参数,而不是迁就模型继续调参。整个流程最后的标准是:特征归因与已知谱峰表高度一致,且置换重要性在同一个波段稳定。这里常用的非对称残差拟合基线,也会在SHAP可视化中暴露残留,值得反复检查。
本文还有配套的精品资源,点击获取