2.3 · 机器学习基础与网络药理初步结合

网络药理⭐⭐⭐了解即可 ⭐⭐|约 12 分钟12 节2 图
本章目标

理解机器学习的基本概念(监督/无监督、分类/回归),掌握 scikit-learn 的完整建模流程(数据准备 → 划分 → 建模 → 评价),能用随机森林完成一次"化合物-靶点"分类或特征重要性分析,输出 ROC 曲线与特征重要性图。

本章路线
机器学习建模标准流程
图 2.3-1机器学习建模标准流程
2.3 · 机器学习基础与网络药理初步结合

0. 小白导读:机器学习到底是什么?

机器学习听起来很高深,用大白话说:

  • 传统编程 = 你告诉计算机"规则",计算机照着执行。比如"如果温度 > 37.5℃,就判定发烧"。
  • 机器学习 = 你不告诉计算机规则,而是给它大量"例子",让它自己从例子中总结出规则。比如给它一万个"化合物 + 是否有效"的例子,它自己学会"什么样的化合物更可能有效"。
🤖AI 视角

一个贯穿本章的比喻——教小朋友认猫

  • 训练数据 = 给小朋友看一万张"猫/不是猫"的图片,并告诉他答案(标签)。

  • 特征 = 图片里的"耳朵尖不尖、有没有胡须、体型大小"等可观察的属性。

  • 模型 = 小朋友自己总结出的"判断规则"。

  • 测试 = 拿没看过的图片考他,看他认对多少。

  • 过拟合 = 小朋友把训练时某只特定猫的"花斑"背下来了,换一只猫就认不出——"死记硬背"而非"学会规律"。

机器学习要回答的核心问题:能不能让计算机从数据中自动学到规律,并用它预测新数据?

为什么学它? 网络药理学找到靶点后,机器学习可以进一步"预测":某个新化合物是不是某个靶点的潜在配体、有没有活性、有没有毒性。这是中药新药研发的前沿方向,也是你研究方向的加分项。

🎯一句话总结

一句话总结:机器学习 = 给计算机喂"例子",让它自己总结规律,再用规律预测新数据。

💡 前置依赖:本章代码基于模块一的 Python / NumPy / Pandas / matplotlib 知识,建议先学完模块一再来。


1. 机器学习基本概念

1.1 监督学习 vs 无监督学习

类型 英文 有没有"标准答案" 典型任务 比喻
监督学习 Supervised Learning 有(数据带标签) 分类、回归 教小朋友认猫(告诉他每张图是不是猫)
无监督学习 Unsupervised Learning 没有(数据无标签) 聚类、降维 让小朋友自己把一堆照片分成几堆
  • 监督学习:数据有"答案"(标签),模型学习"特征 → 标签"的映射。本章重点。
  • 无监督学习:数据没有"答案",模型自己发现数据的内在结构(如把相似化合物聚成一类)。
💡提示

网络药理学里,监督学习用于"预测化合物活性/毒性/是否靶点",无监督学习用于"化合物聚类、分子多样性分析"。

1.2 机器学习三要素

text
数据(Data)+ 模型(Model)+ 评价(Evaluation)
  • 数据:特征矩阵 X + 标签 y。
  • 模型:算法(随机森林、SVM、KNN……)。
  • 评价:怎么判断模型好不好(准确率、AUC……)。
🤖AI 视角

比喻:数据是"教材",模型是"学生",评价是"考试"。没有好教材(数据),再聪明的学生(模型)也学不好。


2. 分类与回归任务

任务 英文 预测的是什么 例子 评价指标
分类 Classification 离散的类别 化合物"有活性/无活性" 准确率、精确率、召回率、AUC
回归 Regression 连续的数值 预测化合物的 IC50 值 R²、均方误差 MSE
  • 分类:输出是"类别"(0/1、猫/狗、有效/无效)。
  • 回归:输出是"数值"(如结合能 -9.2、IC50 = 12.5 μM)。
💡提示

网络药理学最常用的是二分类:预测"化合物-靶点"是否相互作用(1=是,0=否)。


3. 数据准备

3.1 特征矩阵与标签

机器学习的数据通常整理成一张表(DataFrame):

化合物 分子量 LogP 氢键供体 氢键受体 活性标签
化合物A 294.3 3.2 1 4 1(有活性)
化合物B 358.4 4.1 0 6 0(无活性)
... ... ... ... ... ...
  • 特征(X):分子量、LogP、氢键供体/受体等"分子描述符"(也叫分子指纹)。
  • 标签(y):活性标签(1/0)。

3.2 特征来源

  • 分子描述符:用 RDKit(化学信息学工具包)计算,如分子量、LogP、TPSA、氢键数等。
  • 分子指纹:把分子结构编码成 0/1 向量(如 Morgan 指纹、MACCS 指纹)。

用 RDKit 计算分子描述符示例

python
from rdkit import Chem
from rdkit.Chem import Descriptors, Draw

# 从 SMILES 创建分子
mol = Chem.MolFromSmiles("CC(=O)Oc1ccccc1C(=O)O")  # 阿司匹林

# 计算常用描述符
mw = Descriptors.MolWt(mol)          # 分子量
logp = Descriptors.MolLogP(mol)       # 脂水分配系数
hbd = Descriptors.NumHDonors(mol)     # 氢键供体数
hba = Descriptors.NumHAcceptors(mol)  # 氢键受体数
print(f"分子量={mw:.1f}, LogP={logp:.1f}, HBD={hbd}, HBA={hba}")
💡提示

RDKit 是化学信息学的"瑞士军刀",pip install rdkit 即可安装。它能把 SMILES 变成模型能吃的数值特征。

3.3 数据清洗

  • 处理缺失值(fillna / dropna,见模块一 03 章)。
  • 特征标准化(StandardScaler):让不同量纲的特征(分子量 300 vs LogP 3)处于同一尺度。
python
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

4. 训练集/测试集划分与交叉验证

4.1 为什么要划分?

模型在"见过的数据"上表现好是应该的,关键是在没见过的数据上表现好不好(泛化能力)。所以要把数据分成:

  • 训练集(train):用来"学习"(约 70-80%)。
  • 测试集(test):用来"考试"(约 20-30%),模型从没见过。
python
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)
💡提示

stratify=y 让训练/测试集中正负样本比例一致(分层抽样);random_state=42 固定随机种子,保证结果可复现。

4.2 交叉验证(Cross-Validation)

单次划分有随机性,更稳妥的做法是 K 折交叉验证:把数据分成 K 份(通常 5 或 10),轮流用 K-1 份训练、1 份验证,重复 K 次,取平均。

text
数据分成 5 份:
[1][2][3][4][5]
第1轮:训练[2][3][4][5]  验证[1]
第2轮:训练[1][3][4][5]  验证[2]
...
第5轮:训练[1][2][3][4]  验证[5]
最终:5 次验证结果取平均
python
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier

model = RandomForestClassifier(random_state=42)
scores = cross_val_score(model, X, y, cv=5)
print(f"5折交叉验证平均准确率: {scores.mean():.3f}")
🤖AI 视角

比喻:单次划分 = 一次期末考试;交叉验证 = 五次不同试卷的期末考试取平均,更能反映真实水平。


5. 三大经典模型:随机森林、SVM、KNN

截图
scikit-learn 官方文档
图 2.3-2scikit-learn 官方文档截图

5.1 随机森林(Random Forest)

  • 原理:训练很多棵"决策树",每棵树独立投票,少数服从多数。
  • 特点:抗过拟合、能输出特征重要性、对数据要求低,药物靶点预测中最常用
  • 比喻:一群"专家"各自判断,综合意见比单个专家更可靠。
python
from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X_train, y_train)

5.2 支持向量机(SVM)

  • 原理:找一个"分界线"(超平面),把两类数据分得最开。
  • 特点:小样本高维数据表现好(分子描述符正是高维数据),SwissTargetPrediction 底层就是 SVM 集成。
  • 比喻:在两类点之间画一条"最宽的分隔带"。
python
from sklearn.svm import SVC

svm = SVC(kernel="rbf", probability=True, random_state=42)
svm.fit(X_train, y_train)

5.3 K 近邻(KNN)

  • 原理:看新样本最近的 K 个邻居,少数服从多数定类别。
  • 特点:最简单直观,常作为"基线模型"对比。
  • 比喻:"物以类聚"——看你的邻居是什么,你就是什么。
python
from sklearn.neighbors import KNeighborsClassifier

knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)

5.4 三个模型对比

模型 原理 优点 缺点 适用场景
随机森林 多棵决策树投票 抗过拟合、有特征重要性 训练慢(树多时) 药物活性/毒性预测(首选)
SVM 找最优分界线 小样本高维强 大数据慢、难解释 分子描述符分类
KNN 看最近邻居 简单、无需训练 慢、对特征尺度敏感 基线对比
💡提示

入门策略:三个模型都跑一遍,用交叉验证比一比,选表现最好的。论文里常同时报多个模型的结果。


6. 模型评价指标

6.1 混淆矩阵

分类结果可以分成四类:

预测为"有活性"(1) 预测为"无活性"(0)
实际"有活性"(1) TP(真阳性) FN(假阴性)
实际"无活性"(0) FP(假阳性) TN(真阴性)

6.2 核心指标

指标 公式 通俗解释
准确率 Accuracy (TP+TN)/(总数) 全部预测中猜对的比例
精确率 Precision TP/(TP+FP) 预测为"有活性"的里面,真有多少是活性
召回率 Recall TP/(TP+FN) 真正有活性的里面,抓到了多少
F1 精确率与召回率的调和平均 综合两者
python
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score

y_pred = rf.predict(X_test)
print("准确率:", accuracy_score(y_test, y_pred))
print("精确率:", precision_score(y_test, y_pred))
print("召回率:", recall_score(y_test, y_pred))
print("F1:", f1_score(y_test, y_pred))

6.3 ROC 曲线与 AUC

  • ROC 曲线:横轴假阳性率、纵轴真阳性率,画出一条曲线。
  • AUC:ROC 曲线下方的面积,越接近 1 越好(0.5 等于瞎猜,1 是完美)。
AUC 模型水平
0.5 等于随机猜测
0.7-0.8 可用
0.8-0.9 良好
> 0.9 优秀
python
from sklearn.metrics import roc_curve, auc
import matplotlib.pyplot as plt

# 预测概率
y_prob = rf.predict_proba(X_test)[:, 1]

# 计算 ROC
fpr, tpr, _ = roc_curve(y_test, y_prob)
roc_auc = auc(fpr, tpr)

# 画 ROC 曲线
plt.figure(figsize=(6, 5))
plt.plot(fpr, tpr, label=f"Random Forest (AUC = {roc_auc:.3f})")
plt.plot([0, 1], [0, 1], "k--", label="Random (AUC = 0.5)")
plt.xlabel("False Positive Rate")
plt.ylabel("True Positive Rate")
plt.title("ROC Curve")
plt.legend()
plt.savefig("roc_curve.png", dpi=300)
plt.show()
🎯一句话总结

论文标准写法:报告"随机森林模型在测试集上的 AUC 为 0.87,准确率 0.82,精确率 0.85,召回率 0.78",并附 ROC 曲线图。


7. 特征重要性

随机森林的一个巨大优势是能告诉我们:哪些特征对预测贡献最大?

python
import pandas as pd

# 特征重要性
importance = rf.feature_importances_
feat_names = X.columns if hasattr(X, "columns") else [f"f{i}" for i in range(X.shape[1])]

# 排序并画图
imp_df = pd.DataFrame({"feature": feat_names, "importance": importance})
imp_df = imp_df.sort_values("importance", ascending=False)

plt.figure(figsize=(8, 5))
plt.barh(imp_df["feature"][:10], imp_df["importance"][:10])
plt.xlabel("Feature Importance")
plt.title("Top 10 Important Features")
plt.gca().invert_yaxis()
plt.savefig("feature_importance.png", dpi=300)
plt.show()
🤖AI 视角

比喻:特征重要性 = "哪些特征对认猫最管用"。如果"胡须长度"重要性最高,说明它是判断猫的关键依据。在网络药理中,如果"LogP"重要性最高,说明脂溶性对活性影响最大。


8. 与网络药理结合案例

8.1 应用场景

场景 输入特征 预测目标 意义
化合物-靶点预测 分子描述符 + 靶点特征 是否相互作用(1/0) 筛选潜在活性成分
活性预测 分子描述符 活性类别/IC50 预测新成分药效
毒性预测 分子描述符 是否肝毒性(1/0) 安全性初筛
ADMET 预测 分子描述符 吸收/代谢性质 成药性评估

8.2 完整代码案例:化合物活性二分类

python
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, roc_curve, auc
import matplotlib.pyplot as plt

# ========== 1. 模拟数据(真实项目替换为 RDKit 计算的描述符表) ==========
rng = np.random.default_rng(42)
n = 200
X = pd.DataFrame({
    "MolWt": rng.uniform(150, 500, n),      # 分子量
    "LogP": rng.uniform(-2, 6, n),          # 脂水分配系数
    "HBD": rng.integers(0, 6, n),           # 氢键供体
    "HBA": rng.integers(0, 12, n),          # 氢键受体
    "TPSA": rng.uniform(20, 120, n),        # 极性表面积
})
y = ((X["MolWt"] > 250) & (X["LogP"] > 1) & (X["HBD"] <= 3)).astype(int)

# ========== 2. 划分训练/测试集 ==========
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

# ========== 3. 训练随机森林 ==========
rf = RandomForestClassifier(n_estimators=100, random_state=42)
rf.fit(X_train, y_train)

# ========== 4. 交叉验证 ==========
scores = cross_val_score(rf, X, y, cv=5)
print(f"5折交叉验证准确率: {scores.mean():.3f} ± {scores.std():.3f}")

# ========== 5. 测试集评价 ==========
y_pred = rf.predict(X_test)
print(f"测试集准确率: {accuracy_score(y_test, y_pred):.3f}")

# ========== 6. ROC 曲线 ==========
y_prob = rf.predict_proba(X_test)[:, 1]
fpr, tpr, _ = roc_curve(y_test, y_prob)
roc_auc = auc(fpr, tpr)

plt.figure(figsize=(6, 5))
plt.plot(fpr, tpr, label=f"Random Forest (AUC = {roc_auc:.3f})")
plt.plot([0, 1], [0, 1], "k--")
plt.xlabel("False Positive Rate")
plt.ylabel("True Positive Rate")
plt.title("ROC Curve")
plt.legend()
plt.savefig("roc_curve.png", dpi=300)

# ========== 7. 特征重要性 ==========
imp = pd.Series(rf.feature_importances_, index=X.columns).sort_values(ascending=False)
print("特征重要性:\n", imp)
💡提示

真实项目替换点:把第 1 步的模拟数据换成"用 RDKit 从化合物 SMILES 计算出的真实描述符表",把标签换成真实的活性数据(如 ChEMBL 数据库的活性数据),即可用于真实研究。

8.3 数据来源建议

  • ChEMBL(https://www.chembl.org/):药物活性数据库,可下载"化合物-靶点-活性"数据。
  • PubChem BioAssay:生物活性测定数据。
  • 自己课题组数据:实验测得的活性数据。

9. 常见坑

表现 解决办法
数据泄露 测试集表现虚高 特征标准化必须在划分训练/测试集之后做(只 fit 训练集)
类别不平衡 正样本太少,准确率虚高 用 stratify 分层抽样,或报告精确率/召回率/AUC 而非只看准确率
忘记固定随机种子 结果每次不一样 统一 random_state=42
过拟合 训练集 99%、测试集 60% 用交叉验证评估、增加数据、调参(n_estimators、max_depth)
特征尺度差异大 SVM/KNN 表现差 用 StandardScaler 标准化(随机森林不受影响)
把测试集当训练集反复调参 测试集"被记住" 调参用交叉验证,测试集只碰一次

10. 练习与交付物

练习(必须亲手做)

  1. 数据准备:用 RDKit 从 20 个中药成分的 SMILES 计算分子描述符,构造特征矩阵。
  2. 建模:用随机森林训练一个"活性分类"模型(可用模拟标签)。
  3. 对比:分别用随机森林、SVM、KNN 建模,用 5 折交叉验证比较准确率。
  4. 评价:计算准确率、精确率、召回率、F1、AUC,画出 ROC 曲线。
  5. 特征重要性:输出特征重要性排序,画 Top 10 柱状图。

交付物(验收标准)

笔记

使用公开数据完成一次随机森林分类或特征重要性排序,提交:

  1. 代码(带注释,可复现)

  2. ROC 曲线图(含 AUC 值)

  3. 特征重要性图(Top 10)

  4. 简要结果解读(模型表现 + 关键特征的意义)


11. 速查表

工具速查

用途 工具 说明
机器学习 scikit-learn 当前版本 1.9.x
分子描述符 RDKit pip install rdkit
数据操作 pandas 模块一已学
绘图 matplotlib / seaborn 模块一已学
活性数据 ChEMBL https://www.chembl.org/

代码模板速查

python
# 划分
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)

# 交叉验证
from sklearn.model_selection import cross_val_score
scores = cross_val_score(model, X, y, cv=5)

# 随机森林
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(n_estimators=100, random_state=42).fit(X_train, y_train)

# 评价
from sklearn.metrics import accuracy_score, roc_curve, auc

关键概念速查

概念 一句话
监督学习 数据带标签,学"特征→标签"映射
无监督学习 数据无标签,自己发现结构
分类 vs 回归 预测类别 vs 预测数值
交叉验证 K 份轮流训练/验证取平均
过拟合 死记硬背训练数据,新数据表现差
AUC ROC 曲线下面积,越接近 1 越好
特征重要性 哪些特征对预测贡献最大

下一章:模块三 · 实验药剂与纳米制剂

配套学习资源

共 5 条 · 点击跳转