非kaggle内容 一些自学的模型
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,195 @@
|
||||
# %%
|
||||
# This Python 3 environment comes with many helpful analytics libraries installed
|
||||
# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python
|
||||
# For example, here's several helpful packages to load
|
||||
|
||||
import numpy as np # linear algebra
|
||||
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
|
||||
|
||||
# Input data files are available in the read-only "../input/" directory
|
||||
# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory
|
||||
|
||||
import os
|
||||
for dirname, _, filenames in os.walk('/kaggle/input'):
|
||||
for filename in filenames:
|
||||
print(os.path.join(dirname, filename))
|
||||
|
||||
# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using "Save & Run All"
|
||||
# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session
|
||||
|
||||
# Use the kagglehub client library to attach Kaggle resources like competitions, datasets, and models to your session
|
||||
# Learn more about kagglehub: https://github.com/Kaggle/kagglehub/blob/main/README.md
|
||||
|
||||
import kagglehub
|
||||
# kagglehub.dataset_download('<owner>/<dataset-slug>')
|
||||
# %%
|
||||
import pandas as pd
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
||||
from torch.utils.data import Dataset, DataLoader
|
||||
# %%
|
||||
train_df = pd.read_csv('/kaggle/input/competitions/nlp-getting-started/train.csv')
|
||||
test_df = pd.read_csv('/kaggle/input/competitions/nlp-getting-started/test.csv')
|
||||
from sklearn.model_selection import train_test_split
|
||||
train_df, val_df = train_test_split(train_df, test_size=0.1, random_state=42)
|
||||
print(f"Train: {len(train_df)}, Val: {len(val_df)}, Test: {len(test_df)}")
|
||||
# %%
|
||||
model_name = "xlm-roberta-large"
|
||||
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
||||
model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2)
|
||||
# %%
|
||||
import numpy as np
|
||||
class NliDataset(Dataset):
|
||||
def __init__(self, df, tokenizer, max_length=128):
|
||||
self.df = df.reset_index(drop=True)
|
||||
self.tokenizer = tokenizer
|
||||
self.max_length = max_length
|
||||
|
||||
def __len__(self):
|
||||
return len(self.df)
|
||||
|
||||
def __getitem__(self, idx):
|
||||
row = self.df.iloc[idx]
|
||||
strs=''
|
||||
if row['keyword'] is not np.nan:
|
||||
strs=strs+'['+row['keyword']+']'
|
||||
if row['location'] is not np.nan:
|
||||
strs=strs+'['+row['location']+']'
|
||||
strs=strs+row['text']
|
||||
encoding = self.tokenizer(
|
||||
strs,
|
||||
truncation=True,
|
||||
padding='max_length',
|
||||
max_length=self.max_length,
|
||||
return_tensors='pt' # 返回 PyTorch Tensor
|
||||
)
|
||||
# 去掉 batch 维度(因为只处理单条)
|
||||
item = {
|
||||
'input_ids': encoding['input_ids'].squeeze(0),
|
||||
'attention_mask': encoding['attention_mask'].squeeze(0)
|
||||
}
|
||||
if 'target' in row:
|
||||
item['labels'] = torch.tensor(row['target'], dtype=torch.long)
|
||||
return item
|
||||
|
||||
batch_size = 16 # 根据显存调整,推荐使用 16 或 32
|
||||
max_length = 128
|
||||
|
||||
train_dataset = NliDataset(train_df, tokenizer, max_length)
|
||||
val_dataset = NliDataset(val_df, tokenizer, max_length)
|
||||
|
||||
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
|
||||
val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False)
|
||||
# %%
|
||||
for name, param in model.named_parameters():
|
||||
#if param.requires_grad:
|
||||
print(f"{name}: requires_grad = {param.requires_grad}")
|
||||
# %%
|
||||
from peft import LoraConfig, get_peft_model
|
||||
target_layers = [8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]
|
||||
target_modules=[]
|
||||
for layer in target_layers:
|
||||
target_modules.append(f"roberta.encoder.layer.{layer}.attention.self.query")
|
||||
target_modules.append(f"roberta.encoder.layer.{layer}.attention.self.value")
|
||||
# 配置 LoRA
|
||||
config = LoraConfig(
|
||||
r=8, # LoRA 的秩
|
||||
lora_alpha=16, # LoRA 的缩放因子
|
||||
target_modules=target_modules, # 目标模块
|
||||
lora_dropout=0.1, # Dropout 概率
|
||||
bias="none", # 是否更新偏置
|
||||
modules_to_save=["classifier"], # 指定分类器需要被微调
|
||||
)
|
||||
|
||||
# 封装为 LoRA 模型
|
||||
model = get_peft_model(model, config)
|
||||
|
||||
# 验证分类器是否被微调
|
||||
print("验证分类器参数是否被训练:")
|
||||
for name, param in model.named_parameters():
|
||||
if param.requires_grad:
|
||||
print(f"{name}: requires_grad = {param.requires_grad}")
|
||||
# %%
|
||||
@torch.no_grad()
|
||||
def validate(model,loader):
|
||||
model.eval()
|
||||
acc=0
|
||||
total=0
|
||||
for batch in loader:
|
||||
input_ids = batch['input_ids'].to(device)
|
||||
attention_mask = batch['attention_mask'].to(device)
|
||||
labels = batch['labels'].to(device)
|
||||
outputs = model(input_ids, attention_mask=attention_mask).logits
|
||||
pred=torch.argmax(outputs,dim=1)
|
||||
acc+=pred.eq(labels).sum()
|
||||
total+=labels.size(0)
|
||||
print(f"acc:{acc/total}")
|
||||
return acc/total
|
||||
from tqdm import tqdm
|
||||
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
|
||||
model=model.to(device)
|
||||
loss_func = nn.CrossEntropyLoss()
|
||||
optimizer = torch.optim.AdamW(model.parameters(), lr=2e-4)
|
||||
scheduler=torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=10)
|
||||
epochs = 30
|
||||
best_acc=0.0
|
||||
for epoch in range(epochs):
|
||||
model.train()
|
||||
training_loss = 0
|
||||
|
||||
# 使用 tqdm 包装 dataloader,并设置描述信息
|
||||
progress_bar = tqdm(train_loader, desc=f"Epoch {epoch+1}/{epochs}")
|
||||
lens=0
|
||||
for batch in progress_bar:
|
||||
optimizer.zero_grad()
|
||||
input_ids = batch['input_ids'].to(device)
|
||||
attention_mask = batch['attention_mask'].to(device)
|
||||
labels = batch['labels'].to(device)
|
||||
outputs = model(input_ids, attention_mask=attention_mask).logits
|
||||
loss = loss_func(outputs, labels)
|
||||
loss.backward()
|
||||
optimizer.step()
|
||||
|
||||
training_loss += loss.item()
|
||||
lens+=1
|
||||
# 更新进度条显示当前 batch 的损失
|
||||
progress_bar.set_postfix({
|
||||
'loss': f'{loss.item():.4f}',
|
||||
'avg_loss': f'{training_loss / (progress_bar.n+1):.4f}' # progress_bar.n 是已处理 batch 数
|
||||
})
|
||||
|
||||
scheduler.step()
|
||||
|
||||
avg_train_loss = training_loss / lens
|
||||
print(f"Epoch {epoch+1} train_loss: {avg_train_loss:.4f}")
|
||||
|
||||
# 验证(你也可以为验证添加进度条,见下方建议)
|
||||
current_acc=validate(model, val_loader)
|
||||
if current_acc > best_acc :
|
||||
torch.save(model.state_dict(), 'model.pth')
|
||||
print(f"best model save,acc:{current_acc}")
|
||||
best_acc=current_acc
|
||||
# %%
|
||||
test_dataset = NliDataset(test_df, tokenizer, max_length)
|
||||
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
|
||||
all_preds=[]
|
||||
model.load_state_dict(torch.load('model.pth'))
|
||||
model.eval()
|
||||
with torch.no_grad():
|
||||
for batch in test_loader:
|
||||
input_ids = batch['input_ids'].to(device)
|
||||
attention_mask = batch['attention_mask'].to(device)
|
||||
outputs = model(input_ids, attention_mask=attention_mask).logits
|
||||
preds = torch.argmax(outputs, dim=1)
|
||||
all_preds.extend(preds.cpu().numpy())
|
||||
|
||||
submission = pd.DataFrame({
|
||||
'id':test_df['id'],
|
||||
'target': all_preds
|
||||
})
|
||||
|
||||
print(submission)
|
||||
submission.to_csv('submission.csv', index=False)
|
||||
print("Submission saved!")
|
||||
# %%
|
||||
Reference in New Issue
Block a user