Task1 学习笔记
请注意,这只是一篇助教于昨晚发布ddl通知后当晚写完的普通样例,仅供参考。
学习目标
-
基础目标:跑通baseline
-
进阶目标:自己调参数以实现较好的效果
前置知识回顾
特征提取
官方发布的数据是对化学分子的SMILES表达式,具体来说,有rxnid,Reactant1,Reactant2,Product,Additive,Solvent,Yield字段。其中:
-
rxnid 对数据的id标识,无实际意义
-
Reactant1 反应物1
-
Reactant2 反应物2
-
Product 产物
-
Additive 添加剂(包括催化剂catalyst等辅助反应物合成但是不对产物贡献原子的部分)
-
Solvent 溶剂
-
Yield 产率 其中Reactant1,Reactant2,Product,Additive,Solvent都是由SMILES表示。
题目要求
要求模型预测的产率和现实产率误差要尽可能小,最后生成的submit文件中指明了要使用Yield产率进行分析。
现有可提取特征
-
关于SMILES
表示分子的方法是将结构编码为文本。 这是将图结构数据转换为文本内容,并在机器学习输入管道中使用文本(编码字符串)作为输入。 Simplified Molecular-Input Line-Entry System(SMILES)是标准和最受欢迎的表示之一。 转换后,我们可以使用自然语言处理(NLP)的相关算法来处理药物,例如,预测其性质,副作用甚至化合物之间的相互作用 。
SMILES符号是“线性符号”之一,用于用单行文本表达化合物的结构。它是由David Weininger于1986年采用的,由Daylight Chemical Information Systems开发并共同创建。由于其简单性,它是使用最广泛的线性符号。SMILES具有以下六个缩写。
Simplified Molecular Input Line Entry System: SMILES
SMILES标记根据某些规则将化学结构转换为字符串,用分配的数字表示环上相连的原子,裂解环结构以形成链结构,并且裂解位点用数字表示。根据这些规则创建的SMILES一定是线性的,因此SMILES表达式对生成数据集很有帮助,只需要线性遍历即可得到所有的数据信息。
后来为了进一步显示三维结构,同位素表示为[13C],绝对定位由“ @”和“ @@”指示,双键几何异构由“ /”和“ \”表示。包含这些同位素和不对称中心的描述的SMILES 有时也称为“ 异构SMILES ”。 对于它们,由于原式依旧为线性表达式,我们依旧是线性遍历优先,然后,对于同位素信息的分析,可以使用栈结构实现对括号的匹配。至于绝对定位和双键几何异构则可以用正则匹配式解决,故我们仍然可以使用线性遍历一次获取所有的信息。
综上所述,SMILES表达式对于我们数据集的生成大大得好。
-
关于Morgan FingerPrint
摩根指纹,有时也被称为圆形指纹,是化学信息学中用于描述分子的一种特征表示方法。摩根指纹通过考虑分子的局部环境来生成位向量(bit vector)表示,这些位向量通常用于分子相似性搜索、虚拟筛选等应用中。
它的重点在于它是一个位向量,说明待会儿在进行机器学习时如果能够使用到它,我们就可以使用线性代数的相关知识做到一次性计算出所有结果的同时,对所有结果同时进行维护。
Python的numpy库是一个用于科学计算的库,其最大的特色便是将数据向量化以扩大运算规模的同时,强大的解释器还可以让numpy相关的向量化运算享受CPU,GPU的SIMD指令带来的并发优化,进一步加快了响应速度。
其实,如果没有底层优化也没问题,想想RSA筛选质数的蒙哥马利算法,尽管原理和以前的方法无二,由于代码考虑的是计算机的位运算,如果要烧开发板,那还得是蒙哥马利算法。
-
关于RDKit
化学信息学中主要的工具,开源。支持WIN\MAC\Linux,可以被Python、Java、C调用。几乎所有的与化学信息学相关的内容都可以在上面找到。
兼容Python,那可太好了,这下对SMILES式子的解析根本不用自己造轮子了,直接调用别人的方法就行了。
正式实践操作
初探baseline
-
导入了以下依赖:
import pickle
import pandas as pd
from tqdm import tqdm
from sklearn.ensemble import RandomForestRegressor
from rdkit.Chem import rdMolDescriptors
from rdkit import RDLogger,Chem
import numpy as np
其中的numpy的重要性不必再提,pickle是python的序列化相关操作依赖,可将输入的数据进行序列化处理后,以Python根据规范能反序列化直接读取的形式持久存储。
虽然Python的pickle库是一个可以用于反序列化攻击的经典点位,但应该没人缺德到这个地步吧?
通过scikit相关组件的引入可知,本次我们需要使用随机森林算法。
将数据进行Morgan Fingerprint的位向量转化。
那接下来就是“炼丹”……你在期待什么?这样生成的"向量"在Python中依旧只能被称为一维数组,如果现在就用了,numpy库会很没面子的。所以,就当是为了时间,对它使用numpy向量化吧。
刚刚tqdm库的引入正是为了能够有一个可视化优良的呈现。
注意,线性代数中的向量本质上是矩阵,即保留了行和列的概念,而刚刚Morgan Fingerprint还只有行,没有列,所以用不了。
向量化后的速度到底有多快呢?不多,也就450毫秒和1.5毫秒的区别(出处:吴恩达《深度学习》在线课程)
接下来就可以在随机森林中炼丹了,山上一把火,山下派出所。
机器学习,启动!
-
最后生成文件提交,获得第一个分数:0.2049
后期调参提高(次数:4)
还能不能继续呢?这个精确度还是太低了。目前先从随机森林的参数下手改良。
先引入随机森林的各参数定义。
参数解释: - n_estimators=10: 决策树的个数,越多越好; - max_depth: (default=None)设置树的最大深度,默认为None; - min_samples_split: 根据属性划分节点时,最少的样本数; - min_samples_leaf: 叶子节点最少的样本数; - n_jobs=1: 并行job个数,-1表示使用所有cpu进行并行计算。
尝试在炼丹时多添点“柴火”(一击脱离)
现在我有100棵树,那我多添点柴火是否可以通过升温的方式为丹药附上丹纹呢?
故将n_estimators从100改为500,在加大的燃料的同时,要想消化如此多的柴火,自然要耗费比原先更多的时间。
一波操作猛如虎,一看战绩……从0.2049到0.2051,连0-5都不如。我TM是来炼丹的,不是炼孙悟空的。
尝试把炉子拓宽一些(三回啊三回)
行吧,那把炉子拓宽一些,给模型上点深度,让它沉思,让它超越沉思。
故将max_depth从10更改为15……从百度的AI可以看出,很多资料并不推荐这个值超过10,否则容易过拟合。所以,修改这个值时我的心境和某位落榜美术生进军莱茵河非军事区有着异曲同工之妙。
然后随着从10到15,从15到25,再从25到50,我的分数开始有了大量的变化。
好了,今天交不了了,次数满了。我已经迫不及待想要于明天闪击比赛官网了。
你知道的,要想炼出一枚好丹药,除了把炉子装好/换炉子,炼丹的材料也是一个很值得研究的地方,今天就先到这里吧。