Task2
总的理解:
相比于原来官方的baseline,task2中的代码构建了更多的特征,并用了lightgbm模型。这次的效果明显好于官方提供的baseline。
每个模块代码的作用及演示:
模块一:
代码:
df_original = pd.read_csv("data/train_data.csv") n_original = df_original.shape[0] df_submit = pd.read_csv("data/sample_submission.csv") df = pd.concat([df_original, df_submit], axis=0).reset_index(drop=True)
作用:
通过pd.read_csv读取excel文件并的到dataframe结构的数据,
获得训练数据集的行数也就是样本数,和官方提供的我们需要预测的样本的行数
最后将两个都是dataframe的数据结合在一起。25783+4874=30656行数据
结果:
模块二:
代码:
def siRNA_feat_builder(s: pd.Series, anti: bool = False): name = "anti" if anti else "sense" df = s.to_frame() df[f"feat_siRNA_{name}_seq_len"] = s.str.len() for pos in [0, -1]: for c in list("AUGC"): df[f"feat_siRNA_{name}_seq_{c}_{'front' if pos == 0 else 'back'}"] = ( s.str[pos] == c ) df[f"feat_siRNA_{name}_seq_pattern_1"] = s.str.startswith("AA") & s.str.endswith( "UU" ) df[f"feat_siRNA_{name}_seq_pattern_2"] = s.str.startswith("GA") & s.str.endswith( "UU" ) df[f"feat_siRNA_{name}_seq_pattern_3"] = s.str.startswith("CA") & s.str.endswith( "UU" ) df[f"feat_siRNA_{name}_seq_pattern_4"] = s.str.startswith("UA") & s.str.endswith( "UU" ) df[f"feat_siRNA_{name}_seq_pattern_5"] = s.str.startswith("UU") & s.str.endswith( "AA" ) df[f"feat_siRNA_{name}_seq_pattern_6"] = s.str.startswith("UU") & s.str.endswith( "GA" ) df[f"feat_siRNA_{name}_seq_pattern_7"] = s.str.startswith("UU") & s.str.endswith( "CA" ) df[f"feat_siRNA_{name}_seq_pattern_8"] = s.str.startswith("UU") & s.str.endswith( "UA" ) df[f"feat_siRNA_{name}_seq_pattern_9"] = s.str[1] == "A" df[f"feat_siRNA_{name}_seq_pattern_10"] = s.str[-2] == "A" df[f"feat_siRNA_{name}_seq_pattern_GC_frac"] = ( s.str.contains("G") + s.str.contains("C") ) / s.str.len() return df.iloc[:, 1:]
作用:
定义了一个专门处理siRNA正义序列和反义序列的函数,返回的是新的特征值12+8=20个(8是for循环中的8个)
示例:
模块三:
代码:
df_publication_id = pd.get_dummies(df.publication_id) df_publication_id.columns = [ f"feat_publication_id_{c}" for c in df_publication_id.columns ] df_gene_target_symbol_name = pd.get_dummies(df.gene_target_symbol_name) df_gene_target_symbol_name.columns = [ f"feat_gene_target_symbol_name_{c}" for c in df_gene_target_symbol_name.columns ] df_gene_target_ncbi_id = pd.get_dummies(df.gene_target_ncbi_id) df_gene_target_ncbi_id.columns = [ f"feat_gene_target_ncbi_id_{c}" for c in df_gene_target_ncbi_id.columns ] df_gene_target_species = pd.get_dummies(df.gene_target_species) df_gene_target_species.columns = [ f"feat_gene_target_species_{c}" for c in df_gene_target_species.columns ] siRNA_duplex_id_values = df.siRNA_duplex_id.str.split("-|\.").str[1].astype("int") siRNA_duplex_id_values = (siRNA_duplex_id_values - siRNA_duplex_id_values.min()) / ( siRNA_duplex_id_values.max() - siRNA_duplex_id_values.min() ) df_siRNA_duplex_id = pd.DataFrame(siRNA_duplex_id_values) df_cell_line_donor = pd.get_dummies(df.cell_line_donor) df_cell_line_donor.columns = [ f"feat_cell_line_donor_{c}" for c in df_cell_line_donor.columns ] df_cell_line_donor["feat_cell_line_donor_hepatocytes"] = ( (df.cell_line_donor.str.contains("Hepatocytes")).fillna(False).astype("int") ) df_cell_line_donor["feat_cell_line_donor_cells"] = ( df.cell_line_donor.str.contains("Cells").fillna(False).astype("int") ) df_siRNA_concentration = df.siRNA_concentration.to_frame() df_Transfection_method = pd.get_dummies(df.Transfection_method) df_Transfection_method.columns = [ f"feat_Transfection_method_{c}" for c in df_Transfection_method.columns ] df_Duration_after_transfection_h = pd.get_dummies(df.Duration_after_transfection_h) df_Duration_after_transfection_h.columns = [ f"feat_Duration_after_transfection_h_{c}" for c in df_Duration_after_transfection_h.columns ] feats = pd.concat( [ df_publication_id, df_gene_target_symbol_name, df_gene_target_ncbi_id, df_gene_target_species, df_siRNA_duplex_id, df_cell_line_donor, df_siRNA_concentration, df_Transfection_method, df_Duration_after_transfection_h, siRNA_feat_builder(df.siRNA_sense_seq, False), siRNA_feat_builder(df.siRNA_antisense_seq, True), df.iloc[:, -1].to_frame(), ], axis=1, )
作用:
这儿的代码将别的类型特征通过独热编码转化为更多为维的数字特征。最后将他们结合在一块儿构成一个新的dataframe结构数据集,但特征数大大增加,从下图可以看到已经变为203维度的特征
示例:
模块四:
代码:
import lightgbm as lgb from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split( feats.iloc[:n_original, :-1], feats.iloc[:n_original, -1], test_size=0.2, random_state=42, )
作用:
导入lightgbm的包,
对数据进行分割,将原来的训练数据分为训练集和试验集(注意没有包括sample的数据,因为feats.iloc[:n_original, :-1],只取了25783行数据去分)
示例:
这个很简单,可自行测试
模块五:
代码:
train_data = lgb.Dataset(X_train, label=y_train) test_data = lgb.Dataset(X_test, label=y_test, reference=train_data) # 定义一个回调函数来打印验证集的结果 def print_validation_result(env): result = env.evaluation_result_list[-1] print(f"[{env.iteration}] {result[1]}'s {result[0]}: {result[2]}") params = { "boosting_type": "gbdt", "objective": "regression", "metric": "root_mean_squared_error", "max_depth": 7, "learning_rate": 0.02, "verbose": 0, } gbm = lgb.train( params, train_data, num_boost_round=15000, valid_sets=[test_data], callbacks=[print_validation_result], )
作用:
用gbm模型训练。这儿因为我对模型的知识还未深入学习,不知道其内部的结构是怎样的,但就目前而言可以把他当成一个黑盒子,作为训练来说很好用就对了。
示例:
模块六:
代码:
y_pred = gbm.predict(feats.iloc[n_original:, :-1]) df_submit["mRNA_remaining_pct"] = y_pred df_submit.to_csv("submission.csv", index=False)
作用:
用训练好的模型预测数据
将结果返回并生成excel表。
Task3
总的理解:
在不断地看了task3,task2,task1的内容后(task1赛题解析,task2深入理解,task3特征工程进阶),对于我这个ai小白来说,我大概了解了整个机器学习的流程。其最终的我觉得有两点(个人理解):
1.对某领域的专业理解,只有更深的理解才能创造出更好的特征,而特征对于预测的效果来说非常重要
2.机器学习模型本身。
Task3的任务中通过领域的专业知识,来构造新的特征,并对于模型的训练,选择了更好的方式。
下面的内容是相应的特征工程与代码
特征上的提升:
基于序列GC含量
代码:
# 8. G/C含量在30%~52%的siRNA序列,其沉默基因效果较好。研究表明40–55% GC的含量敲低效率高于GC含量高于55%的。 GC_frac = (s.str.count("G") + s.str.count("C"))/s.str.len() df[f"feat_siRNA_{name}_GC_in"] = (GC_frac >= 0.36) & (GC_frac <= 0.52) # 9.他们发现在反义链中,第2到第7个核苷酸和第8到第18个核苷酸的GC百分比分别为19%和52%是理想的 # 百分比分别为19%和52%是理想的(没用上) GC_frac1 = (s.str[1:7].str.count("G") + s.str[1:7].str.count("C"))/s.str[1:7].str.len() df[f"feat_siRNA_{name}_GC_in1"] = GC_frac1 GC_frac2 = (s.str[7:18].str.count("G") + s.str[7:18].str.count("C"))/s.str[7:18].str.len() df[f"feat_siRNA_{name}_GC_in1"] = GC_frac2 # 功能性siRNA在第9到第14个核苷酸之间有一个不稳定区域(GC含量低于其他区域),被称为能量谷,这是选择siRNA的重要标准。 GC_frac3 = (s.str[8:14].str.count("G") + s.str[8:14].str.count("C"))/s.str[8:14].str.len() df[f"feat_siRNA_{name}_GC_in3"] = GC_frac3
解释:
在task3的资料中中给出了对于如何提高siRNA沉默效率的一个重要指标就是GC含量
一共有三种:
序列总的GC含量
序列特定位置的的GC含量
序列不稳定区的GC含量
将这三种GC含量作为特征表示后,效果还是不错的
基于匹配程度
基于修饰的程度(还没搞明白)
模型上的提升:
代码知识:
pd的用法:
pd.read_csv | |
pd.concat | |
pd.reset_index | |
pd.Series |
series的用法:
我认为返回的类型分为三种:数据类型,数据容器,对象
s.to_frame() | obeject | 转为dataframe结构更方便添加列 |
s.str.len() | int | |
s.str[int] | char | |
s.str.startwith("char") | bool | |
s.str.endwith("") | bool | |
s.str.count("char") | ||
s.str.contains("char") | ||
s.str[:] | object | |
s.str.lower() |
series的str的属性不能直接在标准的python字符串上面使用,直接.方法直接调用即可
注意:当返回的对象里面不包含字符串时无法使用
dataframe的用法:
df.iloc[:, 1:] | 截取dataframe的某一个部分返回的任然是dataframe |
df.其中一列的列名 | 返回的是series对象,不需要引号 |
df["列名"] | 返回的也是series对象,需要引号 |
df.colums | 返回的是一个列表,列表的元素是每一个字符串列名 |
df.dropna(subset=['列名'] | |
两者的结果是一样的
常用的表达式:
name="anti" if true else "sense" | |
f"feat_siRNA_{变量}_{}" | |
链式调用的思想:只要返回的对象的形式任然符合调用前的形式这个就可以继续使用