目錄
專案概述
本專案是一個基於機器學習的化學性質預測系統,主要包含兩個子專案:
- ChemProp_VP - 基於圖神經網絡(GNN)的分子性質預測模型,專注於蒸氣壓(Vapor Pressure)預測
- 2025_COSMO - 基於 COSMO(Conductor-like Screening Model)σ-profile 的汽液平衡(VLE)預測系統
主要功能
- 分子 3D 結構生成與優化
- COSMO 量子化學計算
- σ-profile 特徵提取
- 深度學習模型訓練
- 二元混合物相平衡預測
基礎理論
1. COSMO 理論
COSMO(Conductor-like Screening Model) 是一種連續溶劑化模型,用於計算分子表面的電荷分布。
核心概念:
- σ-profile(表面電荷密度分佈):描述分子表面不同電荷密度區域的統計分佈
- 表面片段(Surface Segments):將分子表面離散化為多個小片段,每個片段有其電荷密度 σ
- 篩選電荷(Screening Charge):溶劑對溶質電荷的屏蔽效應
σ-profile 計算流程:
- 幾何優化:使用 DFT (B3LYP/6-31G(d,p)) 優化分子幾何結構
- COSMO 計算:生成分子表面的電荷分布(.cosmo 檔案)
- 平滑化處理:
σ_i = Σ_j (σ_0j × (r_j² × r_eff²) / (r_j² + r_eff²) × exp(-d_ij²/(r_j² + r_eff²)))
其中 r_eff = 7.5 Ų 為有效半徑 4. 分佈統計:統計 σ 在 [-0.025, 0.025] e/Ų 範圍內的分佈,生成 51 個 bin 的直方圖
2. 圖神經網絡(GNN)用於分子性質預測
Message Passing Neural Network (MPNN)
ChemProp 使用的核心架構,透過消息傳遞機制學習分子的圖表示:
- 節點特徵:原子類型、雜化、電荷、芳香性等
- 邊特徵:鍵類型、共軛性、環狀態等
- 消息傳遞:
m_v^(t+1) = Σ_(u∈N(v)) M_t(h_v^t, h_u^t, e_uv) h_v^(t+1) = U_t(h_v^t, m_v^(t+1))
特殊設計:
- Atomic Fingerprint:可選擇輸出原子級別的表示,而非僅分子級別
- Hybrid Method:結合分子級和原子級表示
- Temperature Concatenation:將溫度作為額外特徵併入
3. 蒸氣壓經驗方程
模型支援多種蒸氣壓方程式:
Tu Equation
ln(P) = A + B/T - C×ln(T) - D×T
Antoine Equation
ln(P) = A - B/(C+T)
Riedel Equation
ln(P) = A - B/T + C×ln(T) + D×T^6
Wagner25 Equation
τ = 1 - T
ln(P) = A + (B×τ + C×τ^1.5 + D×τ^2.5 + E×τ^5)/T
系統架構
AI for Chemistry/
│
├── code/
│ ├── chemprop_VP-main/ # ChemProp 蒸氣壓預測模型
│ │ ├── chemprop/ # 核心套件
│ │ │ ├── models/ # 模型定義
│ │ │ │ ├── model.py # MoleculeModel 主模型
│ │ │ │ ├── mpn.py # Message Passing Network
│ │ │ │ └── equations.py # 蒸氣壓方程式
│ │ │ ├── train/ # 訓練相關
│ │ │ ├── data/ # 資料處理
│ │ │ ├── features/ # 特徵生成
│ │ │ └── args.py # 參數配置
│ │ ├── train.py # 訓練入口
│ │ ├── predict.py # 預測入口
│ │ └── environment.yml # 環境配置
│ │
│ └── 2025_COSMO/ # COSMO VLE 預測系統
│ ├── mol_to_cosmo/ # 分子轉 COSMO
│ │ ├── name_to_mol.py # CID → SMILES → 3D MOL
│ │ └── process_gjf.py # MOL → GJF (Gaussian 輸入)
│ ├── data/ # 資料與 σ-profiles
│ │ └── s-profiles-all/ # COSMO σ-profile 資料庫
│ │ └── cosmo_to_s_profile_ver_1.1.1.py
│ ├── grouping/ # 分組預測
│ │ ├── code/ # 分組模型程式
│ │ └── data/ # 訓練資料
│ └── model_train/ # MLP 模型訓練
│ ├── MLP_ln_V1_COSMO.ipynb
│ └── results_V1/ # 訓練結果(10-fold)
│
├── envs/ # 環境配置檔
└── Ref/ # 參考文獻
資料處理流程
階段一:分子結構生成(mol_to_cosmo)
1. name_to_mol.py - 分子結構生成
輸入:name.csv(包含 PubChem CID)
↓
PubChem API 查詢 → SMILES 字串
↓
RDKit 轉換:SMILES → 3D 分子結構
↓
幾何優化:Distance Geometry + UFF 力場
↓
輸出:mol/{CID}.mol 檔案
核心程式碼邏輯:
# 1. 從 PubChem 獲取 SMILES
c = get_compounds(str(CID), 'cid')
sm = c[0].isomeric_smiles
# 2. SMILES 轉 3D 結構
mols_from_sm = MolFromSmiles(sm)
mh = AddHs(mols_from_sm)
EmbedMolecule(mh, useBasicKnowledge=True, useExpTorsionAnglePrefs=False)
# 3. UFF 優化
if UFFHasAllMoleculeParams(mh):
UFFOptimizeMolecule(mh)
# 4. 儲存 MOL 檔
MolToMolFile(DG_UFF, f"./mol/{CID}.mol")
2. process_gjf.py - Gaussian 輸入檔生成
輸入:mol/{CID}.mol
↓
解析 MOL 檔中的原子座標
↓
生成兩步計算的 GJF 檔案:
Step 1: 幾何優化 (opt b3lyp/6-31g(d,p))
Step 2: COSMO 計算 (SCRF=COSMORS)
↓
輸出:gjf/{CID}.gjf
GJF 檔案結構:
%chk={CID}-opt-b3lyp.chk
%mem=10GB
%NProcShared=12
# opt=(calcfc) b3lyp/6-31g(d,p) scf=tight
pe cosmo generation
0 1
[原子座標]
--Link1--
%chk={CID}-opt-b3lyp.chk
%mem=10GB
%NProcShared=12
# b3lyp/6-31g(d,p) geom=checkpoint guess=read scf=tight SCRF=(COSMORS)
pe cosmo generation
0 1
{CID}-opt-b3lyp.cosmo
階段二:σ-profile 提取
cosmo_to_s_profile_ver_1.1.1.py
輸入:{CID}.cosmo (Gaussian 輸出)
↓
解析 COSMO 檔案:
- 表面片段數量 (nseg)
- 片段座標 (x, y, z)
- 原始電荷密度 (σ₀)
- 片段面積 (area)
- 總表面積、體積
↓
平滑化處理(加權平均):
計算片段間距離矩陣 dmn²
應用高斯核函數平滑
↓
統計分佈:
在 [-0.025, 0.025] e/Ų 範圍
劃分為 51 個 bin
計算每個 bin 的總面積
↓
正規化:面積除以總表面積
↓
輸出:
- s-profile/{CID}.csv (正規化的 σ-profile)
- s-profile_area/{CID}.csv (含面積資訊)
關鍵計算:
# 距離矩陣
dmn2[j][i] = (x[j] - x[i])² + (y[j] - y[i])² + (z[j] - z[i])²
# 平滑權重
aa = dmn2[j][i] / (rn[i]² + reff²)
susi[j][i] = 1 / exp(aa)
# 平滑後的電荷密度
σ[i] = Σ_j (σ₀[j] × (rn[j]² × reff²)/(rn[j]² + reff²) × susi[i][j]) /
Σ_j ((rn[j]² × reff²)/(rn[j]² + reff²) × susi[i][j])
階段三:特徵工程
train_gen_exp.ipynb - 訓練資料生成
輸入:
- 實驗 VLE 資料(xA, yA, P, T)
- 兩個組分的 σ-profile
↓
特徵組合:
[σ-profile_A (51維)] + [σ-profile_B (51維)] +
[Area_A, Area_B, Volume_A, Volume_B] +
[Temperature, xA]
= 108 維特徵向量
↓
目標變數:
- yA (氣相莫耳分率)
- P (總壓力,Pa → kPa 轉換)
↓
輸出:train_exp_data_F.csv
分組策略(grouping)
根據氫鍵特性將混合物分為 14 組:
- COOH_COOH
- COOH_HB-A (Hydrogen Bond Acceptor)
- COOH_OH
- HB-A_HB-A
- NH_HB-A
- NH_OH
- Non-HB_COOH
- Non-HB_HB-A
- Non-HB_NH
- Non-HB_Non-HB (最大組)
- Non-HB_OH
- OH_HB-A
- OH_OH
分組依據:
- COOH:羧基(強氫鍵供體/受體)
- OH:羥基(氫鍵供體/受體)
- NH:胺基(氫鍵供體/受體)
- HB-A:氫鍵受體(羰基、醚、酯等)
- Non-HB:無氫鍵(烷烴、芳烴等)
模型架構詳解
1. ChemProp 模型(蒸氣壓預測)
MoleculeModel 類別結構
class MoleculeModel(nn.Module):
def __init__(self, args):
# 編碼器:Message Passing Network
self.encoder = MPN(args)
# 前饋網絡(可選多個)
if args.Tconcat: # 溫度串接模式
self.ffn_A = self.create_ffn(args)
else: # 參數預測模式
self.ffn_A = self.create_ffn(args) # 預測 A
self.ffn_B = self.create_ffn(args) # 預測 B
self.ffn_C = self.create_ffn(args) # 預測 C
self.ffn_D = self.create_ffn(args) # 預測 D
self.ffn_E = self.create_ffn(args) # 預測 E
# 方程式
self.equation = get_equation(args)
MPNEncoder - 消息傳遞編碼器
輸入處理:
# 原子特徵(133維)
atom_features = [
atomic_number, # 原子序
degree, # 連接度
formal_charge, # 形式電荷
chiral_tag, # 手性標籤
num_Hs, # 氫原子數
hybridization, # 雜化類型
aromaticity, # 芳香性
atomic_mass # 原子質量
]
# 鍵特徵(14維)
bond_features = [
bond_type, # 鍵類型
conjugated, # 共軛
ring, # 環狀
stereo # 立體化學
]
消息傳遞過程(depth 次迭代):
for depth in range(self.depth - 1):
# 無向圖處理
if self.undirected:
message = (message + message[b2revb]) / 2
# 聚合鄰居消息
nei_a_message = index_select_ND(message, a2b)
a_message = nei_a_message.sum(dim=1)
# 更新消息
rev_message = message[b2revb]
message = a_message[b2a] - rev_message
# 線性轉換 + 激活
message = self.W_h(message)
message = self.act_func(input + message)
message = self.dropout_layer(message)
Readout 機制:
# 原子級特徵聚合
for i, (a_start, a_size) in enumerate(a_scope):
cur_hiddens = atom_hiddens.narrow(0, a_start, a_size)
if self.fp_method == 'molecular':
# 分子級:平均或求和
mol_vec = cur_hiddens.sum(dim=0) / a_size
elif self.fp_method == 'atomic':
# 原子級:保留所有原子表示,zero-padding 至固定長度
mol_vec = self.padding(cur_hiddens, padding_size=100)
mol_mask = self.mask(cur_hiddens, padding_size=100)
elif self.fp_method == 'hybrid_dim0':
# 混合模式0:串接分子級和原子級
mol_vec_molar = cur_hiddens.sum(dim=0) / a_size
mol_vec = torch.cat((cur_hiddens, mol_vec_molar), dim=0)
mol_vec = self.padding(mol_vec, padding_size=101)
elif self.fp_method == 'hybrid_dim1':
# 混合模式1:每個原子複製分子級特徵並串接
mol_vec_molar = cur_hiddens.sum(dim=0) / a_size
mol_vec_molar_ensemble = mol_vec_molar.repeat(a_size, 1)
mol_vec = torch.cat((cur_hiddens, mol_vec_molar_ensemble), dim=1)
mol_vec = self.padding(mol_vec, padding_size=100)
前向傳播邏輯
模式一:Tconcat(溫度串接)
if self.Tconcat:
if self.fp_method == 'molecular':
# 分子級:直接串接溫度
hidden = torch.cat([hidden, T_batch], dim=1)
output = self.ffn_A(hidden)
else:
# 原子級:每個原子都串接溫度
temp_atomic = T_batch.repeat_interleave(n_atoms).unsqueeze(-1)
hidden = torch.cat([hidden, temp_atomic], dim=2)
# 應用 mask,聚合原子貢獻
masked = hidden * mask
ffn_output = self.ffn_A(masked)
output = torch.sum(ffn_output, 1)
模式二:方程式參數預測
else:
# 預測方程式的 5 個參數
A = self.ffn_A(hidden)
B = self.ffn_B(hidden)
C = self.ffn_C(hidden)
D = self.ffn_D(hidden)
E = self.ffn_E(hidden)
# 原子級需要聚合
if self.fp_method in ['atomic', 'hybrid_dim0', 'hybrid_dim1']:
A = torch.sum(A * mask, 1)
B = torch.sum(B * mask, 1)
C = torch.sum(C * mask, 1)
D = torch.sum(D * mask, 1)
E = torch.sum(E * mask, 1)
# 應用方程式
Pvap = self.equation(A, B, C, D, E, T_batch)
output = Pvap.reshape(-1, 1)
# Tu 方程式需要分子量校正
if self.eqn_name == 'Tu':
output = output - torch.log(self.encoder.MW())
2. COSMO-MLP 模型(VLE 預測)
模型架構(MLP_ln_V1_COSMO.ipynb)
超參數優化(Optuna):
def objective(trial):
# 超參數空間
n_layers = trial.suggest_int('n_layers', 2, 4)
units = []
for i in range(1, n_layers + 1):
units.append(trial.suggest_int(f'units_layer_{i}', 64, 512))
learning_rate = trial.suggest_float('learning_rate', 1e-5, 1e-2, log=True)
batch_size = trial.suggest_categorical('batch_size', [32, 64, 128, 256])
epochs = trial.suggest_int('epochs', 500, 2000)
# 建立模型
model = Sequential()
model.add(Dense(units[0], activation='relu', input_dim=108))
for i in range(1, n_layers):
model.add(Dense(units[i], activation='relu'))
model.add(Dense(2)) # yA 和 P
# 編譯與訓練
model.compile(optimizer=Adam(learning_rate), loss='mse')
history = model.fit(X_train, y_train,
validation_data=(X_val, y_val),
batch_size=batch_size,
epochs=epochs,
callbacks=[early_stopping],
verbose=0)
# 評估指標(AAD-y 和 AARD-P 的組合)
score = calculate_custom_metric(y_pred, y_val)
return score
10-Fold 交叉驗證:
kf = KFold(n_splits=10, shuffle=True, random_state=42)
for fold, (train_idx, val_idx) in enumerate(kf.split(X)):
# 創建 Optuna study
study = optuna.create_study(direction='minimize')
study.optimize(objective, n_trials=200)
# 取得最佳超參數
best_params = study.best_params
# 用最佳超參數重新訓練
best_model = build_model(best_params)
best_model.fit(X_train, y_train, ...)
# 儲存模型
best_model.save(f'fold_{fold+1}_model.h5')
# 儲存超參數
with open(f'fold_{fold+1}_best_trial.json', 'w') as f:
json.dump(best_params, f)
最佳模型範例(fold_1):
{
"trial": 93,
"fold": 1,
"param_count": 99914,
"best_epoch": 1423,
"train_loss": 0.005431,
"val_loss": 0.006883,
"score": 2.615,
"params": {
"n_layers": 2,
"units": {
"units_layer_1": 129,
"units_layer_2": 236
},
"learning_rate": 0.000252,
"batch_size": 64,
"epochs": 1495
}
}
資料正規化
MinMaxScaler 管道:
from sklearn.preprocessing import MinMaxScaler
from sklearn.pipeline import Pipeline
# 創建 pipeline
pipeline = Pipeline([
('scaler', MinMaxScaler())
])
# 擬合訓練資料
pipeline.fit(X_train)
# 轉換
X_train_scaled = pipeline.transform(X_train)
X_val_scaled = pipeline.transform(X_val)
# 儲存 pipeline(用於預測時的一致性)
joblib.dump(pipeline, 'pipelineMLP_COSMO.joblib')
預測與反正規化
# 載入模型和 scaler
model = load_model('MLP_Vali_COSMO_1.h5')
pipeline = load('pipelineMLP_COSMO.joblib')
scaler = pipeline.named_steps['scaler']
# 預測(正規化空間)
y_pred_scaled = model.predict(X_test_scaled)
# 反正規化
scaler_maxy = scaler.data_max_[-2] # yA 的最大值
scaler_maxp = scaler.data_max_[-1] # P 的最大值
scaler_miny = scaler.data_min_[-2] # yA 的最小值
scaler_minp = scaler.data_min_[-1] # P 的最小值
yA_pred = y_pred_scaled[:, 0] * (scaler_maxy - scaler_miny) + scaler_miny
P_pred = y_pred_scaled[:, 1] * (scaler_maxp - scaler_minp) + scaler_minp
訓練與預測流程
ChemProp 訓練流程
1. 資料準備
# 資料格式:CSV
# smiles,target,temperature
# CCO,2.5,298.15
# c1ccccc1,3.2,300.00
2. 訓練命令
python train.py \
--data_path data/train.csv \
--dataset_type regression \
--save_dir models/vp_model \
--depth 3 \
--hidden_size 300 \
--ffn_num_layers 2 \
--ffn_hidden_size 300 \
--dropout 0.1 \
--epochs 50 \
--batch_size 50 \
--fp_method molecular \
--Tconcat \
--num_folds 10
關鍵參數:
--depth: MPNN 消息傳遞深度--hidden_size: 隱藏層維度--fp_method: 指紋方法(molecular/atomic/hybrid_dim0/hybrid_dim1)--Tconcat: 溫度串接模式--equation: 蒸氣壓方程式(Tu/Antonine/Riedel/Wagner25)--num_folds: K-fold 交叉驗證
3. 預測
python predict.py \
--test_path data/test.csv \
--checkpoint_dir models/vp_model \
--preds_path predictions.csv
COSMO-MLP 訓練流程
1. 完整工作流程
步驟 1: 分子結構生成
cd mol_to_cosmo
python name_to_mol.py
→ 生成 mol/{CID}.mol
步驟 2: Gaussian 輸入檔生成
python process_gjf.py
→ 生成 gjf/{CID}.gjf
步驟 3: Gaussian 計算(外部)
# 在 HPC 或本地運行 Gaussian
g09 {CID}.gjf
→ 生成 {CID}.cosmo
步驟 4: σ-profile 提取
cd data/s-profiles-all
python cosmo_to_s_profile_ver_1.1.1.py
→ 生成 s-profile/{CID}.csv
步驟 5: 訓練資料生成
cd data
jupyter notebook train_gen_exp.ipynb
→ 執行筆記本,生成 train_exp_data_F.csv
步驟 6: 模型訓練
cd model_train
jupyter notebook MLP_ln_V1_COSMO.ipynb
→ 執行筆記本,訓練 10-fold 模型
步驟 7: 分組預測
cd grouping/code
jupyter notebook grouping_COSMO_f.ipynb
→ 執行筆記本,按組別預測
2. 訓練邏輯(偽代碼)
# 讀取資料
data = pd.read_csv('train_exp_data_F.csv', header=None)
data.iloc[:, -1] = data.iloc[:, -1] / 1000 # Pa → kPa
# 特徵與標籤
X = data.iloc[:, :-2].values # 108 維特徵
y = data.iloc[:, -2:].values # [yA, P]
# 10-Fold 交叉驗證
kf = KFold(n_splits=10, shuffle=True, random_state=42)
for fold_idx, (train_idx, val_idx) in enumerate(kf.split(X)):
print(f"Training Fold {fold_idx + 1}/10")
# 分割資料
X_train, X_val = X[train_idx], X[val_idx]
y_train, y_val = y[train_idx], y[val_idx]
# 正規化
scaler = MinMaxScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_val_scaled = scaler.transform(X_val)
# Optuna 超參數優化
study = optuna.create_study(direction='minimize')
study.optimize(objective, n_trials=200)
best_params = study.best_params
# 用最佳參數重新訓練
model = build_model(best_params)
# TensorBoard 回調
log_dir = f"logs/fold_{fold_idx+1}"
tensorboard_callback = TensorBoard(log_dir=log_dir)
# Early Stopping
early_stop = EarlyStopping(
monitor='val_loss',
patience=100,
restore_best_weights=True
)
# 訓練
history = model.fit(
X_train_scaled, y_train,
validation_data=(X_val_scaled, y_val),
epochs=best_params['epochs'],
batch_size=best_params['batch_size'],
callbacks=[tensorboard_callback, early_stop],
verbose=1
)
# 儲存模型
model.save(f'results_V1/model/h5/MLP_Vali_COSMO_{fold_idx+1}.h5')
# 儲存超參數
with open(f'results_V1/fold_{fold_idx+1}/fold_{fold_idx+1}_best_trial.json', 'w') as f:
json.dump({
'trial': study.best_trial.number,
'fold': fold_idx + 1,
'best_epoch': len(history.history['loss']),
'train_loss': min(history.history['loss']),
'val_loss': min(history.history['val_loss']),
'score': study.best_value,
'params': best_params
}, f, indent=2)
3. 分組預測邏輯
# 載入最佳模型(選擇某一個 fold)
fold_idx = 1
model = load_model(f'model/h5/MLP_Vali_COSMO_{fold_idx}.h5')
pipeline = load('model/pipelineMLP_COSMO.joblib')
# 讀取分組資料
train_exp_final = pd.read_csv('data/train_exp_datapoint.csv')
train_group_all = pd.read_csv('data/train_group_all_V2.csv')
# 合併資料
merged_data = pd.merge(
train_group_all,
train_exp_final,
on=['comp.A', 'comp.B', 'T'],
how='inner'
)
# 按 sheet_name(組別)分組
grouped = merged_data.groupby('sheet_name')
# 逐組預測
for sheet_name, group in grouped:
print(f"Processing group: {sheet_name}")
# 提取特徵
X_group = group.iloc[:, feature_columns].values
X_group_scaled = pipeline.transform(X_group)
# 預測
y_pred_scaled = model.predict(X_group_scaled)
# 反正規化
yA_pred = inverse_transform_yA(y_pred_scaled[:, 0])
P_pred = inverse_transform_P(y_pred_scaled[:, 1])
# 加入預測結果
group['yA_pred'] = yA_pred
group['P_pred'] = P_pred
# 計算誤差
group['AAD_y'] = abs(group['yA_exp'] - group['yA_pred'])
group['AARD_P'] = abs(group['P_exp'] - group['P_pred']) / group['P_exp'] * 100
# 儲存結果
group.to_csv(f'grouping_COSMO/{sheet_name}.csv', index=False)
# 統計
mean_AAD_y = group['AAD_y'].mean()
mean_AARD_P = group['AARD_P'].mean()
print(f" Mean AAD-y: {mean_AAD_y:.4f}")
print(f" Mean AARD-P: {mean_AARD_P:.2f}%\n")
技術細節
1. 資料格式
COSMO 檔案格式
Gaussian 09 SCRF=COSMORS output
...
area = XXX.XX
volume = XXX.XX
#
nseg natom x y z charge area sigma0
1 1 X.XXXX Y.YYYY Z.ZZZZ Q.QQQQ A.AAAA S.SSSS
2 1 X.XXXX Y.YYYY Z.ZZZZ Q.QQQQ A.AAAA S.SSSS
...
σ-profile CSV 格式
sigma,probability
-0.025,0.0234
-0.024,0.0456
...
0.024,0.0123
0.025,0.0089
area,XXX.XX
volume,YYY.YY
訓練資料格式(train_exp_data_F.csv)
# 無標頭,108 維特徵 + 2 維目標
# 特徵:[σ-profile_A (51)] + [σ-profile_B (51)] + [Area_A, Area_B, Vol_A, Vol_B] + [T, xA]
# 目標:[yA, P]
0,0,...,0,4.58,3.64,...,199.93,0.0085,0.2602,65156
0,0,...,0,4.58,3.64,...,199.93,0.0291,0.5272,98596
...
2. 環境設置
ChemProp 環境
# environment.yml
name: chemprop
dependencies:
- python=3.7
- pytorch=1.9.0
- rdkit
- numpy
- pandas
- scikit-learn
- tensorboardX
- tqdm
安裝:
conda env create -f environment.yml
conda activate chemprop
COSMO-MLP 環境
# tf_py313.yml
name: tf_py313
dependencies:
- python=3.13
- pip
- pip:
- tensorflow==2.20.0
- keras==3.13.0
- keras-tuner==1.4.8
- optuna==4.6.0
- scikit-learn==1.8.0
- pandas==2.3.3
- numpy==2.4.0
- matplotlib==3.10.8
- seaborn==0.13.2
- rdkit==2025.9.3
- joblib==1.5.3
安裝:
conda env create -f envs/tf_py313.yml
conda activate tf_py313
3. 計算資源需求
Gaussian 計算
- CPU: 12 核心推薦
- 記憶體: 10 GB 每個任務
- 時間: 視分子大小,10 分鐘 ~ 數小時
- 硬碟: 每個分子約 50-200 MB
ChemProp 訓練
- GPU: NVIDIA GPU(至少 4GB VRAM)
- CPU: 8 核心推薦
- 記憶體: 16 GB
- 時間: 數小時(視資料量)
COSMO-MLP 訓練
- GPU: NVIDIA GPU(建議 8GB+ VRAM)
- CPU: 16 核心推薦
- 記憶體: 32 GB
- 時間: 每個 fold 約 4-12 小時(200 trials Optuna)
4. 性能指標
評估指標
AAD-y(Average Absolute Deviation in vapor mole fraction):
AAD-y = (1/N) × Σ |y_exp - y_pred|
目標:< 0.02 (2%)
AARD-P(Average Absolute Relative Deviation in pressure):
AARD-P = (1/N) × Σ |(P_exp - P_pred) / P_exp| × 100%
目標:< 5%
報告性能(COSMO-MLP, fold_1):
- AAD-y = 1.04% ✓
- AARD-P = 2.88% ✓
5. 檔案路徑約定
ChemProp
checkpoint: models/{model_name}/fold_{i}/model.pt
predictions: predictions/{model_name}/fold_{i}/test_preds.csv
logs: logs/{model_name}/
COSMO-MLP
models: results_V1/model/h5/MLP_Vali_COSMO_{fold}.h5
pipeline: results_V1/model/pipelineMLP_COSMO.joblib
hyperparams: results_V1/fold_{i}/fold_{i}_best_trial_{trial}.json
logs: logs/fold_{i}/
predictions: grouping_COSMO/{group_name}.csv
附錄
A. 重要參數總表
ChemProp 參數
| 參數 | 預設值 | 說明 |
|---|---|---|
depth |
3 | MPNN 深度 |
hidden_size |
300 | 隱藏層維度 |
ffn_num_layers |
2 | FFN 層數 |
ffn_hidden_size |
300 | FFN 隱藏層維度 |
dropout |
0.0 | Dropout 比率 |
activation |
ReLU | 激活函數 |
fp_method |
molecular | 指紋方法 |
aggregation |
mean | 聚合方式 |
Tconcat |
False | 溫度串接模式 |
equation |
None | 蒸氣壓方程式 |
COSMO-MLP 參數(最佳)
| 參數 | Fold 1 | 說明 |
|---|---|---|
n_layers |
2 | 隱藏層數 |
units_layer_1 |
129 | 第一層單元數 |
units_layer_2 |
236 | 第二層單元數 |
learning_rate |
0.000252 | 學習率 |
batch_size |
64 | 批次大小 |
epochs |
1495 | 訓練週期 |
B. 引用與參考
- ChemProp:
-
Yang, K., et al. "Analyzing Learned Molecular Representations for Property Prediction." Journal of Chemical Information and Modeling (2019). 2. COSMO-RS:
-
Klamt, A. "Conductor-like Screening Model for Real Solvents: A New Approach to the Quantitative Calculation of Solvation Phenomena." The Journal of Physical Chemistry (1995). 3. Message Passing Neural Networks:
-
Gilmer, J., et al. "Neural Message Passing for Quantum Chemistry." ICML (2017).
文件版本: 1.0 更新日期: 2026-02-12