特征工程技巧—Bert
前段时间在参加比赛,发现有一些比赛上公开的代码,其中的数据预处理步骤值得我们参考。
平常我们见到的都是数据预处理,现在我们来讲一下特征工程跟数据预处理的区别。
-
数据预处理是指对原始数据进行清洗、转换、缩放等操作,以便为后续的建模或分析任务做准备。这包括处理缺失值、异常值、重复值,以及对数据进行归一化、标准化等操作,使数据适合模型处理。
-
特征工程则更侧重于从原始数据中提取、构建或转换特征,以提高模型的性能。这包括特征选择、特征抽取、特征转换等过程。在特征工程中,可以创建新的特征、组合现有特征、进行降维等操作,以便使模型更好地捕捉数据中的模式和关系
训练集
测试集
注:这个代码也可以用在自己的工程项目中,还是比较不错的!也是目前在Kaggle社区里公开代码分数比较高的一个单模型。
1、安装库
!pip install rdkit
!pip install -U /kaggle/input/lightning-2-2-1/lightning-2.2.1-py3-none-any.whl
RDKit:是一个用于化学信息学和药物发现的开源软件包。它提供了丰富的化学信息处理功能和工具,用于分子建模、药物设计、化合物筛选等领域。
PyTorch Lightning:于简化和加速深度学习项目开发的库。它构建在PyTorch之上,提供了高级抽象和预定义模板,使得构建、训练和调试神经网络模型变得更加简单和高效。
2、导入所需的Python库和模块
from pathlib import Path
import numpy as np
import polars as pl
from sklearn.model_selection import train_test_split
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import Dataset, DataLoader
from torchmetrics import AveragePrecision
import lightning as L
from lightning.pytorch.callbacks import (EarlyStopping,ModelCheckpoint,TQDMProgressBar,
)
from transformers import AutoConfig, AutoTokenizer, AutoModel, DataCollatorWithPadding
import datasets
from rdkit import Chem
导入数据处理、深度学习、Lightning等相关模块
3、配置超参数
DEBUG = False
NORMALIZE = True
N_ROWS = 180_000_000
assert N_ROWS is None or N_ROWS % 3 == 0
if DEBUG:N_SAMPLES = 10_000
else:N_SAMPLES = 2_000_000
PROTEIN_NAMES = ["BRD4", "HSA", "sEH"]
data_dir = Path("/kaggle/input/leash-BELKA")
model_name = "DeepChem/ChemBERTa-10M-MTR"
batch_size = 256
trainer_params = {"max_epochs": 5,"enable_progress_bar": True,"accelerator": "auto","precision": "16-mixed","gradient_clip_val": None,"accumulate_grad_batches": 1,"devices": [0],
}
-
DEBUG = False
:设置调试标志,表示是否处于调试模式。 -
NORMALIZE = True
:设置规范化标志,表示是否对化学分子的SMILES表示进行规范化处理。 -
N_ROWS = 180_000_000
:设置处理的最大行数,这里指定了处理的数据集的行数上限。 -
assert N_ROWS is None or N_ROWS % 3 == 0
:使用assert
语句确保数据行数是3的倍数,因为后面的代码根据这个假设进行数据处理。 -
if DEBUG:
:检查是否处于调试模式。 -
N_SAMPLES = 10_000 if DEBUG else 2_000_000
:根据是否处于调试模式,设置样本数目。 -
PROTEIN_NAMES = ["BRD4", "HSA", "sEH"]
:定义了需要处理的蛋白质名称列表。 -
data_dir = Path("/kaggle/input/leash-BELKA")
:指定数据存储的目录路径。 -
model_name = "DeepChem/ChemBERTa-10M-MTR"
:指定使用的预训练BERT模型的名称。 -
batch_size = 256
:指定训练中使用的批量大小。 -
trainer_params
:定义了训练器的参数,包括最大训练周期数、是否启用进度条、使用的加速器、精度、梯度裁剪值、累积梯度批次数以及使用的设备。
4、准备数据集
df = pl.read_parquet(Path(data_dir, "train.parquet"),columns=["molecule_smiles", "protein_name", "binds"],n_rows=N_ROWS,
)
test_df = pl.read_parquet(Path(data_dir, "test.parquet"),columns=["molecule_smiles"],n_rows=10000 if DEBUG else None,
)
df.head()
这里读取了训练数据和测试数据,并显示了训练数据的前几行。
dfs = []
for i, protein_name in enumerate(PROTEIN_NAMES):sub_df = df[i::3]sub_df = sub_df.rename({"binds": protein_name})if i == 0:dfs.append(sub_df.drop(["id", "protein_name"]))else:dfs.append(sub_df[[protein_name]])
df = pl.concat(dfs, how="horizontal")
df = df.sample(n=N_SAMPLES)
print(df.head())
print(df[PROTEIN_NAMES].sum())
-
dfs = []
:初始化一个空列表,用于存储每个蛋白质的子数据框。 -
for i, protein_name in enumerate(PROTEIN_NAMES):
:使用enumerate
函数遍历PROTEIN_NAMES
列表中的每个蛋白质名称,同时获取其对应的索引值i
和名称protein_name
。enumerate
函数用于同时遍历一个可迭代对象(如列表、元组)中的元素及其对应的索引。 -
sub_df = df[i::3]
:根据索引i
对原始数据框df
进行切片操作,每隔3行取出一个子数据框。这样可以将原始数据按照每个蛋白质分成3份,分别处理。 -
sub_df = sub_df.rename({"binds": protein_name})
:将子数据框的列名binds
重命名为当前蛋白质的名称,以便后续处理和识别。 -
if i == 0:
:如果是第一个蛋白质,则将子数据框中的"id"和"protein_name"列删除,并将处理后的子数据框添加到dfs
列表中。 -
else:
:如果不是第一个蛋白质,则只保留当前蛋白质的绑定情况数据,并将处理后的子数据框添加到dfs
列表中。 -
df = pl.concat(dfs, how="horizontal")
:将所有处理后的子数据框按水平方向拼接成一个新的数据框df
。 -
df = df.sample(n=N_SAMPLES)
:从新的数据框df
中随机抽样N_SAMPLES个样本。 -
print(df.head())
:打印新数据框df
的前几行。 -
print(df[PROTEIN_NAMES].sum())
:计算新数据框df
中每个蛋白质的绑定情况,并打印出来。
def normalize(x):mol = Chem.MolFromSmiles(x)smiles = Chem.MolToSmiles(mol, canonical=True, isomericSmiles=False)return smilesif NORMALIZE:df = df.with_columns(pl.col("molecule_smiles").map_elements(normalize, return_dtype=pl.Utf8))test_df = test_df.with_columns(pl.col("molecule_smiles").map_elements(normalize, return_dtype=pl.Utf8))
这部分代码定义了一个函数normalize()
,用于对分子结构的SMILES表示进行规范化。如果NORMALIZE
为True,则对训练数据和测试数据中的分子SMILES进行规范化处理。
-
normalize
函数:这个函数接受一个 SMILES 表示的分子作为输入,并返回规范化后的 SMILES 表示。在这里,它使用了 RDKit 包中的功能。Chem.MolFromSmiles()
将输入的 SMILES 字符串转换为 RDKit 的分子对象,然后Chem.MolToSmiles()
将这个分子对象转换回 SMILES 字符串,使用了canonical=True
参数确保生成的 SMILES 是规范化的,isomericSmiles=False
则确保不考虑分子的立体异构体。 -
if NORMALIZE:
:这个条件语句检查一个名为NORMALIZE
的变量是否为真。如果为真,就会对数据进行规范化操作。如果NORMALIZE
是一个布尔值,这个条件通常会在前面被定义,以确定是否要进行规范化处理。 -
df = df.with_columns(pl.col("molecule_smiles").map_elements(normalize, return_dtype=pl.Utf8))
:这一行代码应该是 Pandas 或类似的数据处理库(比如 Dask 或 Modin)的语法。它将 DataFrame 中的"molecule_smiles"
列中的每个元素都应用normalize
函数进行规范化处理,然后将结果保存回原来的列中。这里使用了map_elements()
函数,它是 Pandas 的apply()
方法的替代,用于元素级别的操作。 -
test_df = test_df.with_columns(pl.col("molecule_smiles").map_elements(normalize, return_dtype=pl.Utf8))
:同上一行,只是这一行是对另一个 DataFrametest_df
执行同样的操作。
train_idx, val_idx = train_test_split(np.arange(len(df)), test_size=0.2)
train_df, val_df = df[train_idx], df[val_idx]
len(train_df), len(val_df)
这段代码将数据拆分为训练集和验证集,比例为80:20。
-
train_test_split(np.arange(len(df)), test_size=0.2)
:这行代码使用了train_test_split
函数来将索引数组np.arange(len(df))
分割成训练集和验证集的索引。参数test_size=0.2
指定了验证集所占的比例,这里是20%。训练集和验证集的索引分别存储在train_idx
和val_idx
中。 -
train_df, val_df = df[train_idx], df[val_idx]
:这行代码使用了 Pandas 或类似的库的索引功能,将原始 DataFramedf
中对应索引的行划分给训练集和验证集,分别存储在train_df
和val_df
中。 -
len(train_df), len(val_df)
:这一行简单地打印出了训练集和验证集的长度,以确认它们的大小是否符合预期。
5、建立数据集
tokenizer = AutoTokenizer.from_pretrained(model_name)
这行代码根据给定的模型名称加载了相应的tokenizer,用于将文本数据转换成模型输入。
def tokenize(batch, tokenizer):output = tokenizer(batch["molecule_smiles"], truncation=True)return outputclass LMDataset(Dataset):def __init__(self, df, tokenizer, stage="train"):assert stage in ["train", "val", "test"]self.tokenizer = tokenizerself.stage = stagedf = (datasets.Dataset.from_pandas(df.to_pandas()).map(tokenize, batched=True, fn_kwargs={"tokenizer": self.tokenizer}).to_pandas())self.df = pl.from_pandas(df)def __len__(self):return len(self.df)def __getitem__(self, index):data = self._generate_data(index)data["label"] = self._generate_label(index)return data def _generate_data(self, index):data = {"input_ids": np.array(self.df[index, "input_ids"]),"attention_mask": np.array(self.df[index, "attention_mask"]),}return datadef _generate_label(self, index):if self.stage == "test":return np.array([0, 0, 0])else:return self.df[index, PROTEIN_NAMES].to_numpy()[0]LMDataset(train_df[:100], tokenizer)[0]
-
tokenize
函数:这是一个辅助函数,接受一个批次的数据和一个分词器(tokenizer),并对批次中的分子 SMILES 进行分词处理。在这里,使用了 Hugging Face Transformers 库提供的tokenizer
对批次中的分子 SMILES 进行分词,设置了truncation=True
以确保分词后的序列长度不超过指定的最大长度。 -
LMDataset
类:这是一个自定义的 PyTorch Dataset 类,用于加载数据集。主要功能包括:__init__
方法:初始化数据集对象。接受一个 DataFramedf
、一个分词器tokenizer
和一个阶段stage
(默认为 "train")。在这个方法中,将输入的 DataFrame 转换为 PyTorch 的 Dataset 对象,并使用map
方法对数据进行分词处理,得到包含分词结果的 DataFrame,并将其转换为 Polars 的 DataFrame。__len__
方法:返回数据集的长度,即数据集中样本的数量。__getitem__
方法:根据给定的索引index
返回对应的样本数据和标签。在这里,调用了_generate_data
和_generate_label
方法来生成数据和标签。_generate_data
方法:根据给定的索引index
生成数据。返回一个字典,包含 "input_ids" 和 "attention_mask"。_generate_label
方法:根据给定的索引index
生成标签。如果阶段为 "test",则返回一个全为 0 的数组;否则,根据索引获取对应的样本的标签值。
-
LMDataset(train_df[:100], tokenizer)[0]
:创建了一个LMDataset
对象,并取出第一个样本的数据和标签。
class LBDataModule(L.LightningDataModule):def __init__(self, train_df, val_df, test_df, tokenizer):super().__init__()self.train_df = train_dfself.val_df = val_dfself.test_df = test_dfself.tokenizer = tokenizerdef _generate_dataset(self, stage):if stage == "train":df = self.train_dfelif stage == "val":df = self.val_dfelif stage == "test":df = self.test_dfelse:raise NotImplementedErrordataset = LMDataset(df, self.tokenizer, stage=stage)return datasetdef _generate_dataloader(self, stage):dataset = self._generate_dataset(stage)if stage == "train":shuffle=Truedrop_last=Trueelse:shuffle=Falsedrop_last=Falsereturn DataLoader(dataset,batch_size=batch_size,shuffle=shuffle,drop_last=drop_last,pin_memory=True,collate_fn=DataCollatorWithPadding(self.tokenizer),)def train_dataloader(self):return self._generate_dataloader("train")def val_dataloader(self):return self._generate_dataloader("val")def test_dataloader(self):return self._generate_dataloader("test")datamodule = LBDataModule(train_df, val_df, test_df, tokenizer)
-
__init__
方法:初始化 DataModule 类,接受训练集、验证集、测试集的 DataFrame 数据以及一个分词器 tokenizer。在这个方法中,将输入的数据和分词器保存到类的属性中。 -
_generate_dataset
方法:根据给定的阶段("train"、"val" 或 "test"),生成对应阶段的数据集对象。根据阶段选择对应的 DataFrame 数据,然后使用LMDataset
类创建相应的数据集对象,并传入对应的 DataFrame 和分词器。 -
_generate_dataloader
方法:根据给定的阶段("train"、"val" 或 "test"),生成对应阶段的数据加载器对象。调用_generate_dataset
方法生成对应阶段的数据集对象,然后根据阶段设定加载器的参数,如是否打乱数据、是否丢弃最后一个不完整的批次等,最后使用 PyTorch 的 DataLoader 类创建数据加载器对象。 -
train_dataloader
、val_dataloader
和test_dataloader
方法:分别返回训练、验证和测试阶段的数据加载器对象,通过调用_generate_dataloader
方法实现。 -
datamodule
实例:使用给定的训练集、验证集、测试集和分词器创建了一个 DataModule 对象。
6、建立模型
class LMModel(nn.Module):def __init__(self, model_name):super().__init__()self.config = AutoConfig.from_pretrained(model_name, num_labels=3)self.lm = AutoModel.from_pretrained(model_name, add_pooling_layer=False)self.dropout = nn.Dropout(self.config.hidden_dropout_prob)self.classifier = nn.Linear(self.config.hidden_size, self.config.num_labels)self.loss_fn = nn.BCEWithLogitsLoss(reduction="mean")def forward(self, batch):last_hidden_state = self.lm(batch["input_ids"],attention_mask=batch["attention_mask"],).last_hidden_statelogits = self.classifier(self.dropout(last_hidden_state[:, 0]))return {"logits": logits,}def calculate_loss(self, batch):output = self.forward(batch)loss = self.loss_fn(output["logits"], batch["labels"].float())output["loss"] = lossreturn outputLMModel(model_name)
-
class LMModel(nn.Module):
: 这是定义了一个名为LMModel
的类,它继承自nn.Module
,表示这个类是一个 PyTorch 模型。 -
def __init__(self, model_name):
: 这是LMModel
类的初始化函数,接受一个参数model_name
,表示要使用的预训练语言模型的名称。 -
self.config = AutoConfig.from_pretrained(model_name, num_labels=3)
: 使用 Hugging Face 的AutoConfig
类从预训练模型model_name
中加载配置。num_labels=3
指定了模型的输出类别数量为 3。 -
self.lm = AutoModel.from_pretrained(model_name, add_pooling_layer=False)
: 使用 Hugging Face 的AutoModel
类从预训练模型model_name
中加载模型,add_pooling_layer=False
表示不添加池化层。 -
self.dropout = nn.Dropout(self.config.hidden_dropout_prob)
: 创建了一个 Dropout 层,用于在训练过程中随机将一部分神经元的输出置为零,以防止过拟合。 -
self.classifier = nn.Linear(self.config.hidden_size, self.config.num_labels)
: 创建了一个线性层,将语言模型的隐藏状态映射到指定数量的标签上。 -
self.loss_fn = nn.BCEWithLogitsLoss(reduction="mean")
: 创建了一个二元交叉熵损失函数,用于计算模型的损失。这里使用BCEWithLogitsLoss
是因为多标签分类问题中每个标签都是独立的,所以对每个标签使用二元交叉熵损失。 -
def forward(self, batch):
: 这是模型的前向传播函数,接受一个批次的输入数据batch
,包括输入的标记化的文本和注意力掩码。 -
last_hidden_state = self.lm(
: 使用加载的语言模型处理输入数据,得到最后一层的隐藏状态。 -
logits = self.classifier(
: 将最后一层隐藏状态经过线性层映射到标签空间,得到每个标签的预测概率。 -
def calculate_loss(self, batch):
: 这是计算模型损失的函数,接受一个批次的输入数据batch
。 -
output = self.forward(batch)
: 调用前向传播函数得到模型的输出结果。 -
loss = self.loss_fn(output["logits"], batch["labels"].float())
: 使用损失函数计算模型的损失,将预测的概率和真实标签进行比较。 -
output["loss"] = loss
: 将计算得到的损失保存在输出字典中。
class LBModelModule(L.LightningModule):def __init__(self, model_name):super().__init__()self.model = LMModel(model_name)self.map = AveragePrecision(task="binary")def forward(self, batch):return self.model(batch)def calculate_loss(self, batch, batch_idx):return self.model.calculate_loss(batch)def training_step(self, batch, batch_idx):ret = self.calculate_loss(batch, batch_idx)self.log("train_loss", ret["loss"], on_step=True, on_epoch=True, prog_bar=True, sync_dist=True)return ret["loss"]def validation_step(self, batch, batch_idx):ret = self.calculate_loss(batch, batch_idx)self.log("val_loss", ret["loss"], on_step=False, on_epoch=True, prog_bar=True, sync_dist=True)self.map.update(F.sigmoid(ret["logits"]), batch["labels"].long())def on_validation_epoch_end(self):val_map = self.map.compute()self.log("val_map", val_map, on_step=False, on_epoch=True, prog_bar=True, sync_dist=True)self.map.reset()def predict_step(self, batch, batch_idx, dataloader_idx=0):logits = self.forward(batch)["logits"]probs = F.sigmoid(logits)return probsdef configure_optimizers(self):optimizer = torch.optim.Adam(self.parameters(), lr=0.0001)return {"optimizer": optimizer,}modelmodule = LBModelModule(model_name)
-
class LBModelModule(L.LightningModule):
: 这是定义了一个名为LBModelModule
的类,它继承自 PyTorch Lightning 的LightningModule
类,表示这个类是一个 Lightning 模块。 -
def __init__(self, model_name):
: 这是LBModelModule
类的初始化函数,接受一个参数model_name
,表示要使用的语言模型的名称。 -
self.model = LMModel(model_name)
: 创建了一个LMModel
类的实例作为模型的成员变量,用于处理输入数据并进行预测。 -
self.map = AveragePrecision(task="binary")
: 创建了一个用于计算平均精度的AveragePrecision
类的实例。 -
def forward(self, batch):
: 这是模型的前向传播函数,接受一个批次的输入数据batch
,并调用模型的前向传播函数。 -
def calculate_loss(self, batch, batch_idx):
: 这是计算损失的函数,接受一个批次的输入数据batch
和批次的索引batch_idx
。 -
def training_step(self, batch, batch_idx):
: 这是训练步骤函数,在每个训练步骤中计算损失并更新训练日志。 -
def validation_step(self, batch, batch_idx):
: 这是验证步骤函数,在每个验证步骤中计算损失并更新验证日志。 -
def on_validation_epoch_end(self):
: 这是在每个验证轮结束后调用的函数,在这里计算验证集上的平均精度并重置计算器。 -
def predict_step(self, batch, batch_idx, dataloader_idx=0):
: 这是预测步骤函数,用于在每个预测步骤中生成预测概率。 -
def configure_optimizers(self):
: 这是配置优化器的函数,返回一个优化器的配置字典,这里使用 Adam 优化器。
7、训练
checkpoint_callback = ModelCheckpoint(filename=f"model-{{val_map:.4f}}",save_weights_only=True,monitor="val_map",mode="max",dirpath="/kaggle/working",save_top_k=1,verbose=1,
)
early_stop_callback = EarlyStopping(monitor="val_map", mode="max", patience=3)
progress_bar_callback = TQDMProgressBar(refresh_rate=1)
callbacks = [checkpoint_callback,early_stop_callback,progress_bar_callback,
]
-
ModelCheckpoint
: 这个回调函数用于在训练过程中保存模型的检查点,以便在训练结束后选择最佳的模型参数。参数解释如下:filename
: 模型文件名的格式,可以使用格式化字符串指定变量,这里使用了验证集的平均精度作为文件名。save_weights_only
: 设置为True
表示只保存模型的权重。monitor
: 监控的指标,这里选择了验证集的平均精度。mode
: 模型选择的模式,这里选择了最大化验证集的平均精度。dirpath
: 模型保存的目录路径。save_top_k
: 保存最佳模型的数量,这里设置为 1。verbose
: 控制是否在保存模型时输出信息,设置为 1 表示输出信息。
-
EarlyStopping
: 这个回调函数用于在验证集指标停止提升时提前停止训练,以防止过拟合。参数解释如下:monitor
: 监控的指标,这里同样选择了验证集的平均精度。mode
: 模型选择的模式,这里同样选择了最大化验证集的平均精度。patience
: 容忍多少个 epoch 内指标没有提升。
-
TQDMProgressBar
: 这个回调函数用于在训练过程中显示进度条,以便实时监控训练进度。参数refresh_rate
控制刷新频率,即进度条更新的时间间隔。
trainer = L.Trainer(callbacks=callbacks, **trainer_params)
trainer.fit(modelmodule, datamodule)
-
trainer = L.Trainer(callbacks=callbacks, **trainer_params)
: 这行代码创建了一个 Lightning Trainer 对象,并设置了回调函数和训练参数。参数解释如下:callbacks
: 指定了训练过程中要使用的回调函数列表,这里使用了之前定义的callbacks
列表,包括模型检查点、提前停止和进度条回调。**trainer_params
: 使用**
语法将字典trainer_params
中的所有键值对作为参数传递给Trainer
对象,这里包括了一系列训练参数,如最大 epoch 数、设备选择、精度设置等。
-
trainer.fit(modelmodule, datamodule)
: 这行代码使用创建的 Trainer 对象开始了模型的训练过程。参数解释如下:modelmodule
: 指定了要训练的 Lightning 模型,这里是之前定义的LBModelModule
对象。datamodule
: 指定了训练数据的 datamodule,这里是之前定义的LBDataModule
对象,其中包含了训练、验证和测试数据集的处理逻辑。
8、推理
test_df = pl.read_parquet(Path(data_dir, "test.parquet"),columns=["molecule_smiles"],n_rows=10000 if DEBUG else None,
)
pl.read_parquet
: 这是 PyTorch Lightning 库中的一个函数,用于从 Parquet 格式的文件中读取数据。Parquet 是一种列式存储格式,常用于大规模数据存储和处理。Path(data_dir, "test.parquet")
: 这是指定要读取的 Parquet 文件的路径。data_dir
是之前定义的数据目录路径,"test.parquet"
是要读取的文件名。columns=["molecule_smiles"]
: 这是指定要读取的列名,即从 Parquet 文件中选择的列。在这里,只选择了名为 "molecule_smiles" 的列。n_rows=10000 if DEBUG else None
: 这是指定要读取的行数。如果DEBUG
变量为True
,则只读取文件的前 10000 行;否则,读取整个文件。这是一种常用的技术,用于在开发和调试阶段快速处理较小的数据样本,以加快开发速度。
working_dir = Path("/kaggle/working")
model_paths = working_dir.glob("*.ckpt")
test_dataloader = datamodule.test_dataloader()
for model_path in model_paths:print(model_path)modelmodule = LBModelModule.load_from_checkpoint(checkpoint_path=model_path,model_name=model_name,)predictions = trainer.predict(modelmodule, test_dataloader)predictions = torch.cat(predictions).numpy()pred_dfs = []for i, protein_name in enumerate(PROTEIN_NAMES):pred_dfs.append(test_df.with_columns(pl.lit(protein_name).alias("protein_name"),pl.lit(predictions[:, i]).alias("binds"),))pred_df = pl.concat(pred_dfs)submit_df = (pl.read_parquet(Path(data_dir, "test.parquet"), columns=["id", "molecule_smiles", "protein_name"]).join(pred_df, on=["molecule_smiles", "protein_name"], how="left").select(["id", "binds"]).sort("id"))submit_df.write_csv(Path(working_dir, f"submission_{model_path.stem}.csv"))
- 定义了一个工作目录
working_dir
,这是保存模型和生成提交文件的目录。 - 使用
glob
方法获取工作目录中的所有模型文件的路径,并存储在model_paths
变量中。 - 获取测试数据的数据加载器
test_dataloader
。 - 遍历模型文件路径列表
model_paths
。 - 加载每个模型并进行预测。首先,使用
LBModelModule.load_from_checkpoint
方法加载模型,并传入模型文件路径和模型名称。然后使用trainer.predict
方法对测试数据进行预测,得到预测结果。 - 将预测结果与相应的蛋白质名称关联,并将结果存储在
pred_df
中。 - 读取测试数据的 Parquet 文件,并选择需要的列("id"、"molecule_smiles" 和 "protein_name")。
- 将预测结果与测试数据合并,并只保留 "id" 和 "binds" 列。
- 将合并后的结果按照 "id" 进行排序。
- 将生成的提交文件写入 CSV 格式,并根据当前模型文件的名称进行命名,存储在工作目录中。
9、集成
sub_files = list(working_dir.glob("submission_*.csv"))
sub_files
sub_files
是一个列表,包含工作目录中所有以 "submission_" 开头且以 ".csv" 结尾的文件的路径。这些文件名可能会因为模型路径的不同而有所变化,但它们都是模型预测结果的提交文件。
sub_dfs = []
for sub_file in sub_files:sub_dfs.append(pl.read_csv(sub_file))
submit_df = (pl.concat(sub_dfs).group_by("id").agg(pl.col("binds").mean()).sort("id")
)
- 循环遍历
sub_files
中的每个文件路径。 - 对于每个文件,使用
pl.read_csv(sub_file)
读取 CSV 文件并将其添加到sub_dfs
列表中。 - 使用
pl.concat(sub_dfs)
将所有 DataFrame 连接成一个大的 DataFrame。 - 使用
group_by("id")
将数据按照 "id" 列进行分组。 - 使用
.agg(pl.col("binds").mean())
对每个分组计算 "binds" 列的平均值。 - 最后使用
.sort("id")
按照 "id" 列进行排序。
!rm -fr *
这是一个Unix/Linux命令,用于删除当前目录下的所有文件和文件夹。具体地说:
rm
是 remove 的缩写,用于删除文件或目录。-fr
是两个选项的结合:-f
表示强制删除,即不会提示确认。-r
表示递归删除,即删除目录及其下所有文件和子目录。
*
是通配符,代表当前目录下的所有文件和文件夹。
因此,这个命令的意思是:删除当前目录下的所有文件和文件夹,且不会提示确认。
submit_df.write_csv(Path(working_dir, "submission.csv"))
submit_df
是一个 DataFrame,其中包含了提交的数据。write_csv
是一个方法,用于将 DataFrame 写入到 CSV 格式的文件中。Path(working_dir, "submission.csv")
创建了一个路径对象,指定了要写入的文件路径,这个路径对象表示当前工作目录下的 "submission.csv" 文件。
10、改进方向
- 寻找最佳的交叉验证策略
- 增加数据
- 使用更多的特征
- 更大的模型
- 调整超参数
- 集成模型
源代码:Leash Bio: ChemBERTa with all data (kaggle.com)
相关文章:

特征工程技巧—Bert
前段时间在参加比赛,发现有一些比赛上公开的代码,其中的数据预处理步骤值得我们参考。 平常我们见到的都是数据预处理,现在我们来讲一下特征工程跟数据预处理的区别。 数据预处理是指对原始数据进行清洗、转换、缩放等操作,以便为…...

更改 Docker 的默认存储位置
记录一下使用 Docker 遇到的问题,Docker 也用得比较多,最近发现根目录所在磁盘快满了,发现是 Docker 默认会将镜像和容器等数据保存在目录 /var/lib/docker 目录下,我们可以更改 Docker 的默认存储位置,比如改到数据盘…...

搜索与图论:图中点的层次
搜索与图论:图中点的层次 题目描述参考代码 题目描述 输入样例 4 5 1 2 2 3 3 4 1 3 1 4输出样例 1参考代码 #include <cstring> #include <iostream> #include <algorithm>using namespace std;const int N 100010;int n, m; int h[N], e[N]…...

NLP入门——数据预处理:编码规范化
编码规范化 在计算机中,我们需要将字符与字节序列之间建立起映射关系,这个过程被称为编码。有许多不同的编码方式,例如 ASCII、UTF-8、UTF-16 和 GBK 等。这些编码方式会将每个字符编码为一个或多个字节,以便于在计算机、网络和其…...

代码随想录算法训练营第四十八天| 70. 爬楼梯 (进阶)、322. 零钱兑换、279.完全平方数
70. 爬楼梯 (进阶) 题目链接:70. 爬楼梯 (进阶) 文档讲解:代码随想录/爬楼梯 (进阶) 状态:已完成(0遍) 解题过程 这几天博主忙着面试和入职&am…...

c++11 constexpr关键字
constexpr 是 C11 引入的一个关键字,它允许在编译时计算表达式的值,并将这些值存储在程序的常量部分中。这意味着 constexpr 变量和函数可以在编译时进行求值,从而避免了运行时的开销。 constexpr变量 constexpr 变量必须在编译时初始化&am…...

ios 获取图片的一部分区域
可以使用如下的代码: // get part of the image - (UIImage *)getPartOfImage:(UIImage *)img rect:(CGRect)partRect {CGImageRef imageRef img.CGImage;CGImageRef imagePartRef CGImageCreateWithImageInRect(imageRef, partRect);UIImage *retImg [UIImage i…...

数据结构(3)栈、队列、数组
1 栈 1.1 栈的定义 后进先出【LIFO】 1.2 基本操作 元素进栈出栈 只能在栈顶进行!!! 经常考的题: 穿插的进行进栈和出栈 可能有多个选项 1.3 顺序栈 1.3.1 初始化 下标是从0开始的 1.3.2 进栈 更简单的写法: 1.3…...

数据库(入门)
文章目录 一、数据库(DB) 二、数据库管理系统(DBMS) 三、SQL(结构化查询语言) 四、三者的关系 五、端口号(port number) 一、数据库(DB) 定义:按照一定格式存储数据的一些文件的组合。 简单来…...

ChatTTS+Python编程搞定语音报时小程序
文字转语音神器Python编程搞定语音报时小程序 今天一个好哥们发了一个文字转语音的AI神器的短视频。这个神器的网站是[ChatTTS - Text-to-Speech for Conversational Scenarios][https://chattts.com/],如下图所示: 这个开源项目可以从github.com上下载…...

【Mac】Alfred 5 for Mac(苹果效率提升工具)v5.5软件介绍及安装教程
软件介绍 Alfred 是适用于 Mac 操作系统的流行生产力应用程序。它旨在帮助用户在 Mac 电脑上更高效地启动应用程序、搜索文件和文件夹以及执行各种任务。借助 Alfred,用户可以创建自定义键盘快捷方式、设置自定义工作流程并使用热键访问功能。 Alfred for Mac 的一…...

PDF文件处理不再复杂:9个Python库让一切变得简单
大家好,这里是程序员晚枫,2年前发布了一个开源项目:python-office,目前在GitHub上有800⭐,最近在开发新功能时感觉Python知识有点不够用了。 所以打算从2方面补充自己的知识:研究优秀的第三方库和学习Pyth…...

安防视频融合汇聚平台EasyCVR如何实现视频画面自定义标签?
安防视频融合汇聚平台EasyCVR兼容性强,可支持Windows系统、Linux系统以及国产化操作系统等,平台既具备传统安防视频监控的能力,也具备接入AI智能分析的能力,可拓展性强、视频能力灵活,能对外分发RTMP、RTSP、HTTP-FLV、…...

Liunx音频
一. echo -e "\a" echo 通过向控制台喇叭设备发送字符来发声: echo -e "\a"(这里的 -e 选项允许解释反斜杠转义的字符,而 \a 是一个响铃(bell)字符) 二. beep 下载对应的包 yum -y install beep 发声命令 be…...

2024前端面试准备3-JS异步-进阶
1.请描述Event loop(事件循环)的机制。 JS是单线程的,异步需要基于毁掉来实现,event loop 就是异步回调的实现原理。 同步代码,一行一行放在Call Stack执行,遇到异步任务,标记一下让其他线程去处…...

lm studio 0.2.24国内下载模型
1.修改C:\Users\Admin\AppData\Local\LM-Studio\app-0.2.24\resources\app\.webpack\main中的3个js文件: index.js llmworker.js worker.js 中替换huggingface.co为hf-mirror.com。这样就能实现搜索模型文件 2.点击模型,选择下载,出现下载…...

卷积池化尺寸计算公式
卷积层[Conv]: 卷积CNN是我们最常使用的,但是有时候需要观察他的输出前后的差异,这里描述下计算方式,具体如下: 图片大小:WxHxD W:宽 H:高 D:通道(RGB) 例:320x320x3 卷积核&…...

前端框架原理自测题:根据 JSX / Vue 模板写出 render 函数 / VNode
JSX <div className"container"><p onClick{onClick} data-name"p1">hello <b>{name}</b></p><img src{imgSrc}/><MyComponent title{title}></MyComponent> </div>Vue 模板 <div class"co…...

RabbitMQ启动报错:Error during startup: {error, {schema_integrity_check_failed,
报错信息如下: Error during startup: {error,{schema_integrity_check_failed,[{table_attributes_mismatch,rabbit_user,[username,password_hash,tags,hashing_algorithm,limits],[username,password_hash,tags,hashing_algorithm]},{table_attributes_mismatch…...

操作系统入门系列-MIT6.828(操作系统工程)学习笔记(三)---- xv6初探与实验一(Lab: Xv6 and Unix utilities)
系列文章目录 操作系统入门系列-MIT6.S081(操作系统)学习笔记(一)---- 操作系统介绍与接口示例 操作系统入门系列-MIT6.828(操作系统工程)学习笔记(二)----课程实验环境搭建&#x…...

Java核心: 为图片生成水印
今天干了一件特别不务正业的事,做了一个小程序用来给图片添加水印。事情的起因是需要将自己的身份证照片分享给别人,手边并没有一个趁手的工具来生成图片水印。很多APP提供了水印的功能,但会把我的图片上传到他们的服务器,身份证太…...

Spark MLlib 机器学习详解
目录 🍉引言 🍉Spark MLlib 简介 🍈 主要特点 🍈常见应用场景 🍉安装与配置 🍉数据处理与准备 🍈加载数据 🍈数据预处理 🍉分类模型 🍈逻辑回归 &a…...

MySQL报ERROR 2002 (HY000)解决
今天在连接客户服务器时MySQL的时候报: ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/tmp/mysql/mysql.sock’ (2) [rootXXX ~]# mysql -uroot -p Enter password: ERROR 2002 (HY000): Can’t connect to local MySQL server through socket…...

【校招】【社招】字节跳动UG营销算法工程师招聘
【校招】【社招】字节跳动UG营销算法工程师招聘 需要营销、广告、搜索、推荐等领域的人才加入 岗位简介 字节跳动增长智能-激励中台团队负责公司国内字节所有主要App(包含但不仅限于抖音/抖音极速版/抖音火山版/今日头条/头条极速版/番茄小说/番茄畅听/西瓜视频&…...

Go实战 | 使用Go-Fiber采用分层架构搭建一个简单的Web服务
前言 📢博客主页:程序源⠀-CSDN博客 📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正! 一、环境准备、示例介绍 Go语言安装,GoLand编辑器 这个示例实现了一个简单的待办事项(todo…...

Web自动化测试框架+PO模式分层实战(超细整理)
前言 PO模式 在UI级的自动化测试中,对象设计模式表示测试正在交互的web应用,程序用户界面中的一个区域,这个是减少了代码的重复,也就是说,如果用户界面发生了改变,只需要在一个地方修改程序就可以了。 优…...

光猫、路由器的路由模式、桥接模式、拨号上网
下面提到的路由器都是家用路由器 一、联网条件 1.每台电脑、路由器、光猫想要上网,都必须有ip地址。 2.电脑获取ip 可以设置静态ip 或 向DHCP服务器(集成在路由器上) 请求ip 电话线上网时期,猫只负责模拟信号和数字信号的转换,电脑需要使…...

iOS--工厂设计模式
iOS--工厂设计模式 设计模式的概念和意义类族模式UIButton作为类族模式的例子总结 三种工厂设计模式简单工厂模式(Simple Factory Pattern):代码实例 工厂方法模式(Factory Method Pattern):代码实例 抽象工…...

[Python]用Qt6和Pillow实现截图小工具
本文章主要讲述的内容是,使用python语言借助PyQt6和Pillow库进行简单截图工具的开发,含义一个简单的范围裁剪和软件界面。 主要解决的问题是,在高DPI显示屏下,坐标点的偏差导致QWidget显示图片不全、剪裁范围偏差问题。 适合有一点…...

Podman和Docker的区别
Podman 和 Docker 都是用于容器化的工具,但它们在架构、安全性、容器编排以及一些设计理念上有显著的区别: 架构设计: Docker 使用客户端-服务器(C/S)架构,包含一个名为 dockerd 的守护进程,该进程以 root …...