特征工程技巧—Bert

前段時間在參加比賽,發現有一些比賽上公開的代碼,其中的數據預處理步驟值得我們參考。

平常我們見到的都是數據預處理,現在我們來講一下特征工程跟數據預處理的區別。

  1. 數據預處理是指對原始數據進行清洗、轉換、縮放等操作,以便為后續的建模或分析任務做準備。這包括處理缺失值、異常值、重復值,以及對數據進行歸一化、標準化等操作,使數據適合模型處理。

  2. 特征工程則更側重于從原始數據中提取、構建或轉換特征,以提高模型的性能。這包括特征選擇、特征抽取、特征轉換等過程。在特征工程中,可以創建新的特征、組合現有特征、進行降維等操作,以便使模型更好地捕捉數據中的模式和關系

?訓練集

測試集

注:這個代碼也可以用在自己的工程項目中,還是比較不錯的!也是目前在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],
}
  1. DEBUG = False:設置調試標志,表示是否處于調試模式。

  2. NORMALIZE = True:設置規范化標志,表示是否對化學分子的SMILES表示進行規范化處理。

  3. N_ROWS = 180_000_000:設置處理的最大行數,這里指定了處理的數據集的行數上限。

  4. assert N_ROWS is None or N_ROWS % 3 == 0:使用assert語句確保數據行數是3的倍數,因為后面的代碼根據這個假設進行數據處理。

  5. if DEBUG::檢查是否處于調試模式。

  6. N_SAMPLES = 10_000 if DEBUG else 2_000_000:根據是否處于調試模式,設置樣本數目。

  7. PROTEIN_NAMES = ["BRD4", "HSA", "sEH"]:定義了需要處理的蛋白質名稱列表。

  8. data_dir = Path("/kaggle/input/leash-BELKA"):指定數據存儲的目錄路徑。

  9. model_name = "DeepChem/ChemBERTa-10M-MTR":指定使用的預訓練BERT模型的名稱。

  10. batch_size = 256:指定訓練中使用的批量大小。

  11. 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())
  1. dfs = []:初始化一個空列表,用于存儲每個蛋白質的子數據框。

  2. for i, protein_name in enumerate(PROTEIN_NAMES)::使用enumerate函數遍歷PROTEIN_NAMES列表中的每個蛋白質名稱,同時獲取其對應的索引值i和名稱protein_nameenumerate函數用于同時遍歷一個可迭代對象(如列表、元組)中的元素及其對應的索引。

  3. sub_df = df[i::3]:根據索引i對原始數據框df進行切片操作,每隔3行取出一個子數據框。這樣可以將原始數據按照每個蛋白質分成3份,分別處理。

  4. sub_df = sub_df.rename({"binds": protein_name}):將子數據框的列名binds重命名為當前蛋白質的名稱,以便后續處理和識別。

  5. if i == 0::如果是第一個蛋白質,則將子數據框中的"id"和"protein_name"列刪除,并將處理后的子數據框添加到dfs列表中。

  6. else::如果不是第一個蛋白質,則只保留當前蛋白質的綁定情況數據,并將處理后的子數據框添加到dfs列表中。

  7. df = pl.concat(dfs, how="horizontal"):將所有處理后的子數據框按水平方向拼接成一個新的數據框df

  8. df = df.sample(n=N_SAMPLES):從新的數據框df中隨機抽樣N_SAMPLES個樣本。

  9. print(df.head()):打印新數據框df的前幾行。

  10. 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進行規范化處理。

  1. normalize 函數:這個函數接受一個 SMILES 表示的分子作為輸入,并返回規范化后的 SMILES 表示。在這里,它使用了 RDKit 包中的功能。Chem.MolFromSmiles() 將輸入的 SMILES 字符串轉換為 RDKit 的分子對象,然后 Chem.MolToSmiles() 將這個分子對象轉換回 SMILES 字符串,使用了 canonical=True 參數確保生成的 SMILES 是規范化的,isomericSmiles=False 則確保不考慮分子的立體異構體。

  2. if NORMALIZE::這個條件語句檢查一個名為 NORMALIZE 的變量是否為真。如果為真,就會對數據進行規范化操作。如果 NORMALIZE 是一個布爾值,這個條件通常會在前面被定義,以確定是否要進行規范化處理。

  3. 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() 方法的替代,用于元素級別的操作。

  4. test_df = test_df.with_columns(pl.col("molecule_smiles").map_elements(normalize, return_dtype=pl.Utf8)):同上一行,只是這一行是對另一個 DataFrame test_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。
?

  1. train_test_split(np.arange(len(df)), test_size=0.2):這行代碼使用了 train_test_split 函數來將索引數組 np.arange(len(df)) 分割成訓練集和驗證集的索引。參數 test_size=0.2 指定了驗證集所占的比例,這里是20%。訓練集和驗證集的索引分別存儲在 train_idxval_idx 中。

  2. train_df, val_df = df[train_idx], df[val_idx]:這行代碼使用了 Pandas 或類似的庫的索引功能,將原始 DataFrame df 中對應索引的行劃分給訓練集和驗證集,分別存儲在 train_dfval_df 中。

  3. 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]
  1. tokenize 函數:這是一個輔助函數,接受一個批次的數據和一個分詞器(tokenizer),并對批次中的分子 SMILES 進行分詞處理。在這里,使用了 Hugging Face Transformers 庫提供的 tokenizer 對批次中的分子 SMILES 進行分詞,設置了 truncation=True 以確保分詞后的序列長度不超過指定的最大長度。

  2. LMDataset 類:這是一個自定義的 PyTorch Dataset 類,用于加載數據集。主要功能包括:

    • __init__ 方法:初始化數據集對象。接受一個 DataFrame df、一個分詞器 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 的數組;否則,根據索引獲取對應的樣本的標簽值。
  3. 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)

  1. __init__ 方法:初始化 DataModule 類,接受訓練集、驗證集、測試集的 DataFrame 數據以及一個分詞器 tokenizer。在這個方法中,將輸入的數據和分詞器保存到類的屬性中。

  2. _generate_dataset 方法:根據給定的階段("train"、"val" 或 "test"),生成對應階段的數據集對象。根據階段選擇對應的 DataFrame 數據,然后使用 LMDataset 類創建相應的數據集對象,并傳入對應的 DataFrame 和分詞器。

  3. _generate_dataloader 方法:根據給定的階段("train"、"val" 或 "test"),生成對應階段的數據加載器對象。調用 _generate_dataset 方法生成對應階段的數據集對象,然后根據階段設定加載器的參數,如是否打亂數據、是否丟棄最后一個不完整的批次等,最后使用 PyTorch 的 DataLoader 類創建數據加載器對象。

  4. train_dataloaderval_dataloadertest_dataloader 方法:分別返回訓練、驗證和測試階段的數據加載器對象,通過調用 _generate_dataloader 方法實現。

  5. 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)

  1. class LMModel(nn.Module):: 這是定義了一個名為 LMModel 的類,它繼承自 nn.Module,表示這個類是一個 PyTorch 模型。

  2. def __init__(self, model_name):: 這是 LMModel 類的初始化函數,接受一個參數 model_name,表示要使用的預訓練語言模型的名稱。

  3. self.config = AutoConfig.from_pretrained(model_name, num_labels=3): 使用 Hugging Face 的 AutoConfig 類從預訓練模型 model_name 中加載配置。num_labels=3 指定了模型的輸出類別數量為 3。

  4. self.lm = AutoModel.from_pretrained(model_name, add_pooling_layer=False): 使用 Hugging Face 的 AutoModel 類從預訓練模型 model_name 中加載模型,add_pooling_layer=False 表示不添加池化層。

  5. self.dropout = nn.Dropout(self.config.hidden_dropout_prob): 創建了一個 Dropout 層,用于在訓練過程中隨機將一部分神經元的輸出置為零,以防止過擬合。

  6. self.classifier = nn.Linear(self.config.hidden_size, self.config.num_labels): 創建了一個線性層,將語言模型的隱藏狀態映射到指定數量的標簽上。

  7. self.loss_fn = nn.BCEWithLogitsLoss(reduction="mean"): 創建了一個二元交叉熵損失函數,用于計算模型的損失。這里使用 BCEWithLogitsLoss 是因為多標簽分類問題中每個標簽都是獨立的,所以對每個標簽使用二元交叉熵損失。

  8. def forward(self, batch):: 這是模型的前向傳播函數,接受一個批次的輸入數據 batch,包括輸入的標記化的文本和注意力掩碼。

  9. last_hidden_state = self.lm(: 使用加載的語言模型處理輸入數據,得到最后一層的隱藏狀態。

  10. logits = self.classifier(: 將最后一層隱藏狀態經過線性層映射到標簽空間,得到每個標簽的預測概率。

  11. def calculate_loss(self, batch):: 這是計算模型損失的函數,接受一個批次的輸入數據 batch

  12. output = self.forward(batch): 調用前向傳播函數得到模型的輸出結果。

  13. loss = self.loss_fn(output["logits"], batch["labels"].float()): 使用損失函數計算模型的損失,將預測的概率和真實標簽進行比較。

  14. 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)

  1. class LBModelModule(L.LightningModule):: 這是定義了一個名為 LBModelModule 的類,它繼承自 PyTorch Lightning 的 LightningModule 類,表示這個類是一個 Lightning 模塊。

  2. def __init__(self, model_name):: 這是 LBModelModule 類的初始化函數,接受一個參數 model_name,表示要使用的語言模型的名稱。

  3. self.model = LMModel(model_name): 創建了一個 LMModel 類的實例作為模型的成員變量,用于處理輸入數據并進行預測。

  4. self.map = AveragePrecision(task="binary"): 創建了一個用于計算平均精度的 AveragePrecision 類的實例。

  5. def forward(self, batch):: 這是模型的前向傳播函數,接受一個批次的輸入數據 batch,并調用模型的前向傳播函數。

  6. def calculate_loss(self, batch, batch_idx):: 這是計算損失的函數,接受一個批次的輸入數據 batch 和批次的索引 batch_idx

  7. def training_step(self, batch, batch_idx):: 這是訓練步驟函數,在每個訓練步驟中計算損失并更新訓練日志。

  8. def validation_step(self, batch, batch_idx):: 這是驗證步驟函數,在每個驗證步驟中計算損失并更新驗證日志。

  9. def on_validation_epoch_end(self):: 這是在每個驗證輪結束后調用的函數,在這里計算驗證集上的平均精度并重置計算器。

  10. def predict_step(self, batch, batch_idx, dataloader_idx=0):: 這是預測步驟函數,用于在每個預測步驟中生成預測概率。

  11. 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,
]
  1. ModelCheckpoint: 這個回調函數用于在訓練過程中保存模型的檢查點,以便在訓練結束后選擇最佳的模型參數。參數解釋如下:

    • filename: 模型文件名的格式,可以使用格式化字符串指定變量,這里使用了驗證集的平均精度作為文件名。
    • save_weights_only: 設置為 True 表示只保存模型的權重。
    • monitor: 監控的指標,這里選擇了驗證集的平均精度。
    • mode: 模型選擇的模式,這里選擇了最大化驗證集的平均精度。
    • dirpath: 模型保存的目錄路徑。
    • save_top_k: 保存最佳模型的數量,這里設置為 1。
    • verbose: 控制是否在保存模型時輸出信息,設置為 1 表示輸出信息。
  2. EarlyStopping: 這個回調函數用于在驗證集指標停止提升時提前停止訓練,以防止過擬合。參數解釋如下:

    • monitor: 監控的指標,這里同樣選擇了驗證集的平均精度。
    • mode: 模型選擇的模式,這里同樣選擇了最大化驗證集的平均精度。
    • patience: 容忍多少個 epoch 內指標沒有提升。
  3. TQDMProgressBar: 這個回調函數用于在訓練過程中顯示進度條,以便實時監控訓練進度。參數 refresh_rate 控制刷新頻率,即進度條更新的時間間隔。

trainer = L.Trainer(callbacks=callbacks, **trainer_params)
trainer.fit(modelmodule, datamodule)
  1. trainer = L.Trainer(callbacks=callbacks, **trainer_params): 這行代碼創建了一個 Lightning Trainer 對象,并設置了回調函數和訓練參數。參數解釋如下:

    • callbacks: 指定了訓練過程中要使用的回調函數列表,這里使用了之前定義的 callbacks 列表,包括模型檢查點、提前停止和進度條回調。
    • **trainer_params: 使用 ** 語法將字典 trainer_params 中的所有鍵值對作為參數傳遞給 Trainer 對象,這里包括了一系列訓練參數,如最大 epoch 數、設備選擇、精度設置等。
  2. 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"))
  1. 定義了一個工作目錄 working_dir,這是保存模型和生成提交文件的目錄。
  2. 使用 glob 方法獲取工作目錄中的所有模型文件的路徑,并存儲在 model_paths 變量中。
  3. 獲取測試數據的數據加載器 test_dataloader
  4. 遍歷模型文件路徑列表 model_paths
  5. 加載每個模型并進行預測。首先,使用 LBModelModule.load_from_checkpoint 方法加載模型,并傳入模型文件路徑和模型名稱。然后使用 trainer.predict 方法對測試數據進行預測,得到預測結果。
  6. 將預測結果與相應的蛋白質名稱關聯,并將結果存儲在 pred_df 中。
  7. 讀取測試數據的 Parquet 文件,并選擇需要的列("id"、"molecule_smiles" 和 "protein_name")。
  8. 將預測結果與測試數據合并,并只保留 "id" 和 "binds" 列。
  9. 將合并后的結果按照 "id" 進行排序。
  10. 將生成的提交文件寫入 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")
)
  1. 循環遍歷 sub_files 中的每個文件路徑。
  2. 對于每個文件,使用 pl.read_csv(sub_file) 讀取 CSV 文件并將其添加到 sub_dfs 列表中。
  3. 使用 pl.concat(sub_dfs) 將所有 DataFrame 連接成一個大的 DataFrame。
  4. 使用 group_by("id") 將數據按照 "id" 列進行分組。
  5. 使用 .agg(pl.col("binds").mean()) 對每個分組計算 "binds" 列的平均值。
  6. 最后使用 .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)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/21935.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/21935.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/21935.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Blackwell未來發展之路究竟如何?

英偉達Blackwell如何重塑AI計算的未來? 前言 臺灣大學演講 就在6月2日,英偉達CEO黃仁勛在中國臺灣大學綜合體育館發表了最新的演講。這次黃仁勛的演講依舊重磅,更值得注意的是這次演講中還透露了Blackwell今后的發展之路。 介紹Blackwell 介紹…

MongoDB CRUD操作:地理位置查詢

MongoDB CRUD操作:地理位置查詢 文章目錄 MongoDB CRUD操作:地理位置查詢地理空間數據GeoJSON對象傳統坐標對通過數組指定(首選)通過嵌入文檔指定 地理空間索引2dsphere2d 地理空間查詢地理空間查詢運算符地理空間聚合階段 地理空…

拿筆記下來!產品采購制造類合同怎樣寫比較穩妥?

拿筆記下來!產品采購制造類合同怎樣寫比較穩妥? 近日,幾經波折,泰中兩國終于完成了潛艇采購談判!你知道嗎?產品制造類合同或協議在起草前如果沒有充分考慮各種因素,可能會導致一系列問題和不利…

C語言學習:數據類型

一、 為什么要引入數據類型 ? 計算機中每個字節都有一個地址(類似門牌號) ? CPU通過 地址 來訪問這個字節的空間 0x20001103 1 0 0 1 0 0 1 1 0x20001102 1 1 1 0 1 1 1 0 0x20001101 1 1 1 1 0 1 0 1 0x20001100 0 …

linux c socket編程里SO_REUSEADDR的作用

比如下面的代碼 int reuse 1; int ret setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)); if (ret SOCKET_ERROR) {log_error("_SetReuseAddr failed, err_code%d, fd%d", _GetErrorCode(), fd); }代碼解釋 setsockopt 函數用于設置…

無人監控視頻輸出卡頓狀態

設計思路,如下: 1.通過采集卡將視頻信號輸出到個人PC中 2.PC按設置好的時間,視頻屬性分片保存 3.將步驟2中的視頻,按預處理要求,得到待計算的視頻片段 4.使用SSIM算法計算預處理后的視頻,將計算得到的數據存…

聊天機器人的實踐過程

一、語聊機器人 OpenAI 的爆火,到如今也才一年多的時間,然而在過去的一年中,生成式AI的落地場景幾乎 80%都是 ChatBot 的形式,那么今天這篇文章我們就來聊一下,生成式AI和IM能擦出怎么樣的火花?以及各種場…

p13idea的其他操作

1 導入模塊 錯誤示范: 正確示范: 2 刪除模塊 必須用delete才能刪除干凈,用remove刪了之后還要回到文件里面把它刪除掉

有錢還系統源碼 人人還眾籌還錢模式還貸系統源碼

盈利模式: 1.系統里直推400 2.間推得200 3.升級是隔代匹配200 4.漏單直接設置歸系統 5.九級匹配不到直接歸平臺 有錢還平臺新注冊會員,即新入的負債者要分9次分別資助先來的11名負債者每人200元,這筆資助不是一次性給到對方&#xff0c…

Prism 入門04,導航功能

當前章節,沿用 上一章使用Prism 框架創建的WPF 項目空模板。在上一章節,各個不同的模塊之間能夠進行切換并把內容呈現在主程序的頁面當中(其實是通過在主程序中注冊的區域去發起一個導航的請求,然后跳轉到對應的視圖。也就是實現了導航跳轉功能)。 為什么能實現導航的跳轉?…

Mybatis的一級緩存

緩存 MyBatis 包含一個非常強大的查詢緩存特性,它可以非常方便地配置和定制。MyBatis 3 中的緩存實現的很多改進都已經實現了,使得它更加強大而且易于配置。 Mybatis和Hibernate一樣,也有一級和二級緩存,同樣默認開啟的只有一級緩存,二級緩…

docker-compose安裝多環境apollo

下載數據庫sql文件 https://github.com/apolloconfig/apollo/blob/master/scripts/sql/src/apolloconfigdb.sql https://github.com/apolloconfig/apollo/blob/master/scripts/sql/src/apolloportaldb.sql 創建庫并導入表 #生產環境 mysql> CREATE DATABASE IF NOT EXIS…

腦部磁共振成像腫瘤分割方法(MATLAB 2018)

近年腦腫瘤發病率呈上升趨勢,約占全身腫瘤的5%,占兒童腫瘤的70%。CT、MRI等多種影像檢查方法可用于檢測腦腫瘤,其中MRI應用于腦腫瘤成像效果最佳。精準的腦腫瘤分割是病情診斷、手術規劃及后期治療的必備條件,既往研究者對腦部腫瘤…

Python知識點12---Python的I/O操作

提前說一點:如果你是專注于Python開發,那么本系列知識點只是帶你入個門再詳細的開發點就要去看其他資料了,而如果你和作者一樣只是操作其他技術的Python API那就足夠了。 Python的流(I/O)操作,最簡單的其實就是輸入和輸出&#x…

擴展翡蜀定理問題

問題描述 給定一個大小為 n n n 的集合 A { a 1 , a 2 ~ a n } A\{a_1,a_2 \sim a_n\} A{a1?,a2?~an?},滿足條件 gcd ( A ) 1 \text{gcd}(A)1 gcd(A)1。 O ( 1 ) O(1) O(1)時間內 求最大的 k k k ,滿足不存在一個大小為 n n n 的非負數集合…

工廠的精益生產如此重要

什么是工廠的精益生產 精益生產(Lean Manufacturing)是一種起源于20世紀50年代日本豐田汽車公司的生產管理哲學。它的核心理念是通過消除生產過程中的浪費,優化流程,提高效率,從而實現成本降低和質量提升。精益生產不僅…

VRTK4.0學習——(二)

手柄綁定以及顯示 1.導入CameraRigs.UnityXRPluginFramework 和 CameraRigs.TrackedAlias 預設,將CameraRigs.UnityXRPluginFramework拖入CameraRigs.TrackedAlias的Elements中即可,運行軟件后即可看到手柄了 注:如果無法看到手柄&#xff…

MySQL:MySQL執行一條SQL查詢語句的執行過程

當多個客戶端同時連接到MySQL,用SQL語句去增刪改查數據,針對查詢場景,MySQL要保證盡可能快地返回客戶端結果。 了解了這些需求場景,我們可能會對MySQL進行如下設計: 其中,連接器管理客戶端的連接,負責管理連接、認證鑒權等;查詢緩存則是為了加速查詢,命中則直接返回結…

Linux Shell Script 編寫入門

Linux Shell 腳本是一種強大的工具,能夠幫助用戶自動化任務、簡化系統管理以及提高工作效率。本文將帶您全面了解如何編寫 Linux Shell 腳本,并介紹一些常見的腳本編寫技巧和注意事項。 目錄 什么是 Linux ShellShell 腳本的基本結構常用 Shell 命令變…

系統介紹在線直線度測量儀的測量原理

測頭的測量原理 藍鵬光電測頭采用的是CCD成像法測量,CCD成像法是指將被測物放置在物方遠心光路系統中進行成像,并利用成像位置的CCD芯片接收成像信息進行尺寸測量的方法。該測量方法的優點主要有兩個:一是成像邊界清晰,光電信號可…