我试图建立一个模型来预测分子的caco-2系数,因为它具有微笑的字符串表示。
我的解决方案基于this示例。
由于我需要预测实际值,因此我使用RandomForestRegressor
。
一些分子手动添加到代码中,一切正常(虽然预测本身是非常错误的):
from rdkit import Chem, DataStructs #all the nice chemical stuff, ConvertToNumpyArray
from rdkit.Chem import AllChem
from sklearn.ensemble import RandomForestRegressor #our regressor
from sklearn.model_selection import train_test_split
import numpy as np
# generate molecules
m1 = Chem.MolFromSmiles('Cc1ccc(NNC(=O)c2ccc(CN3C(=O)CCC3=O)cc2)cc1Cl')
m2 = Chem.MolFromSmiles('Nc1ccc(C(=O)N2CCN(c3cc[nH+]cc3)CC2)cc1[N+](=O)[O-]')
m3 = Chem.MolFromSmiles('CN(Cc1[nH+]ccn1C)C(=O)CCc1ccsc1')
m4 = Chem.MolFromSmiles('COc1ccc([N+](=O)[O-])cc1C(=O)NCCC[NH+]1CCCC1')
m5 = Chem.MolFromSmiles('C[NH+]1CCN(S(=O)(=O)c2ccc(NC(=O)Cc3ccc([N+](=O)[O-])cc3)cc2)CC1')
m6 = Chem.MolFromSmiles('CCc1ccc(S(=O)(=O)Nc2ccc(NC(C)=O)cc2)cc1')
m7 = Chem.MolFromSmiles('O=C(COC(=O)c1ccc(S(=O)(=O)N2CCCCC2)cc1)c1ccc(F)cc1')
m8 = Chem.MolFromSmiles('COC(=O)c1ccc(S(=O)(=O)NCc2csc3ccc(Cl)cc23)n1C')
m9 = Chem.MolFromSmiles('CCC(C)N1C(=O)C(=CNc2ccccc2C(=O)[O-])C(=O)NC1=S')
m10 = Chem.MolFromSmiles('Cn1c(CNC(=O)C(=O)Nc2cccc(Cl)c2Cl)nc2ccccc21')
mols = [m1, m2, m3, m4, m5 ,m6, m7, m8, m9, m10]
# generate fingeprints: Morgan fingerprint with radius 2
fps = [AllChem.GetMorganFingerprintAsBitVect(m, 2) for m in mols]
# convert the RDKit explicit vectors into numpy arrays
np_fps = []
for fp in fps:
arr = np.zeros((1,))
DataStructs.ConvertToNumpyArray(fp, arr)
np_fps.append(arr)
# get a random forest regressor with 100 trees
rndf_rgsr = RandomForestRegressor(n_estimators=100, random_state=42, n_jobs=-1, warm_start=False)
#train the random forest
#ys are the caco-2 coefficients we wish to predict
ys_fit = [379.724, 101.644, 3154.167, 97.437, 21.152, 569.981, 150.55, 690.843, 78.866, 984.371]
rndf_rgsr.fit(np_fps, ys_fit)
#use the random forest to predict a new molecule
m_new = Chem.MolFromSmiles('Cc1n[nH]c(Cc2ccc(-n3cnnc3)cc2)n1') #actual caco2 is 410.037
fp = np.zeros((1,))
DataStructs.ConvertToNumpyArray(AllChem.GetMorganFingerprintAsBitVect(m_new, 2), fp)
print(rndf_rgsr.predict((fp,)))
但是,当我尝试使用以下代码处理从文件导入的大量分子时,其中包含许多看起来像Cc1ccc(NNC(=O)c2ccc(CN3C(=O)CCC3=O)cc2)cc1Cl,379.724
的行:
from rdkit import Chem, DataStructs
from rdkit.Chem import AllChem
from sklearn.ensemble import RandomForestRegressor, ExtraTreesRegressor #our regressors
from sklearn.tree import DecisionTreeRegressor
from sklearn.model_selection import train_test_split
import numpy as np
import pandas as pd
from pandas import DataFrame, read_csv
#import our data from file
df = pd.read_csv('test_db.csv', delimiter=',' ) #a pandas DataFrame
#get the values of variables and targets
X = df["smiles"].values
y = df["Caco2"].values
#split our data set into two parts
x_train, x_eval, y_train, y_eval = train_test_split(X, y, test_size = 0.2, random_state = 42)
#convert our smiles string into actual molecular graphs
mols_ready_train = [Chem.MolFromSmiles(x_train[i]) for i in range(len(x_train))]
mols_ready_eval = [Chem.MolFromSmiles(x_eval[i]) for i in range(len(x_eval))]
# generate fingeprints: Morgan fingerprint with radius 2
fing_prints_train = [AllChem.GetMorganFingerprintAsBitVect(m, 2) for m in mols_ready_train]
fing_prints_eval = [AllChem.GetMorganFingerprintAsBitVect(m, 2) for m in mols_ready_eval]
# convert the RDKit explicit vectors into numpy arrays
np_fps_train = []
for fp in fing_prints_train:
arr = np.zeros((1,))
DataStructs.ConvertToNumpyArray(fp, arr)
np_fps_train.append(arr)
np_fps_eval = []
for fp in fing_prints_eval:
arr = np.zeros((1,))
DataStructs.ConvertToNumpyArray(fp, arr)
np_fps_eval.append(arr)
# get a random forest regressor with 100 trees
rndf_rgsr = RandomForestRegressor(n_estimators=1000, random_state=42, n_jobs=-1, warm_start=False)
#train our random forest regressor
rndf_rgsr.fit(np_fps_train, y_train)
# use the random forest to predict a new molecule
m_new = Chem.MolFromSmiles('Cc1n[nH]c(Cc2ccc(-n3cnnc3)cc2)n1')
fp = numpy.zeros((1,))
DataStructs.ConvertToNumpyArray(AllChem.GetMorganFingerprintAsBitVect(m_new, 2), fp)
print(rndf_rgsr.predict((fp,)))
崩溃时出现以下错误:
文件" /home/me/predictor.py" ;,第55行,in rndf_rgsr.fit(np_fps_train,y_train)File" /usr/local/lib/python2.7/dist-packages/sklearn/ensemble/forest.py", 第248行,合适 y = check_array(y,accept_sparse =' csc&#39 ;, ensure_2d = False,dtype = None)文件 " /usr/local/lib/python2.7/dist-packages/sklearn/utils/validation.py" ;, 第407行,在check_array中 _assert_all_finite(array)File" /usr/local/lib/python2.7/dist-packages/sklearn/utils/validation.py", 第58行,在_assert_all_finite中 "或者对于%r来说值太大。" %X.dtype)ValueError:输入包含NaN,无穷大或对于dtype来说太大的值(' float64')。
我已检查过我使用的矢量中是否包含nan
s或inf
s。这里使用的指纹长度为2048位,但我怀疑它们是问题的根源。
验证出了问题,但我真的看不清楚。
你能提供任何提示吗?
ETA:test_db.csv
有50,000行。我创建了一个只有10行的tiny_db.csv
,并且在其上我的模型工作得很好(也就是说,它的预测是错误的,但它可以工作)。
它也可以使用100行文件,但是1000不会,并且会因上述错误而崩溃。
进一步的实验表明,250条线路可以正常工作,但500条不干净。
ETA:前250行有效,但接下来250行(250到500)不行。
读取超过100行后,print(y_train.mean(), y_train.min(), y_train.max())
会返回(nan,nan,nan)
。
总而言之,我强烈怀疑这个问题来自pandas.Dataframe.values
,它将我的好系数向上转换为float64
,这会导致算术错误,从而导致验证程序崩溃。
我想我最好不要使用python csv
模块而不是pandas.read_csv
与DataFrame.values
一起使用。