BERT 可微调参数和调参技巧:
-
学习率调整:可以使用学习率衰减策略,如余弦退火、多项式退火等,或者使用学习率自适应算法,如Adam、Adagrad等。
-
批量大小调整:批量大小的选择会影响模型的训练速度和泛化性能,通常情况下,批量大小越大,训练速度越快,但是会导致模型的泛化性能下降。
-
正则化调整:可以通过调整正则化系数来控制模型的复杂度,从而避免过拟合。
-
模型结构调整:可以通过增加或减少层数、调整隐藏层大小等方式来改变模型的结构,从而提高模型的性能。
-
数据增强:可以通过数据增强技术来扩充训练数据集,从而提高模型的泛化性能。
使用 ray-tune 实现高效自动化调参:
Ray Tune 是一个用于分布式超参数优化的 Python 库,它提供了多种调参算法和可视化工具,可以帮助用户快速地找到最优的超参数组合。
下面是一个使用 Ray Tune 进行超参数优化的示例代码:
import ray
from ray import tune
from transformers import BertTokenizer, BertForSequenceClassification, AdamW
from datasets import load_dataset
import torch
def train_bert(config):
# 加载数据集
dataset = load_dataset('glue', 'mrpc')
train_dataset = dataset['train']
eval_dataset = dataset['validation_matched']
# 加载模型和分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=2)
# 定义优化器和学习率调度器
optimizer = AdamW(model.parameters(), lr=config['lr'])
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=config['step_size'], gamma=config['gamma'])
# 训练模型
for epoch in range(config['epochs']):
for i in range(0, len(train_dataset), config['batch_size']):
batch = train_dataset[i:i+config['batch_size']]
inputs = tokenizer(batch['sentence1'], batch['sentence2'], padding=True, truncation=True, return_tensors='pt')
labels = torch.tensor(batch['label'])
outputs = model(**inputs, labels=labels)
loss = outputs.loss
loss.backward()
optimizer.step()
scheduler.step()
optimizer.zero_grad()
# 在验证集上评估模型性能
eval_acc = evaluate(model, eval_dataset, tokenizer)
tune.report(eval_acc=eval_acc)
def evaluate(model, dataset, tokenizer):
correct = 0
total = 0
for i in range(0, len(dataset), 32):
batch = dataset[i:i+32]
inputs = tokenizer(batch['sentence1'], batch['sentence2'], padding=True, truncation=True, return_tensors='pt')
labels = torch.tensor(batch['label'])
outputs = model(**inputs, labels=labels)
logits = outputs.logits
preds = torch.argmax(logits, dim=1)
correct += (preds == labels).sum().item()
total += len(labels)
return correct / total
if __name__ == '__main__':
ray.init()
analysis = tune.run(
train_bert,
config={
'lr': tune.loguniform(1e-5, 1e-3),
'batch_size': tune.choice([16, 32, 64]),
'epochs': 3,
'step_size': tune.choice([1, 2, 4]),
'gamma': tune.choice([0.1, 0.5, 0.9])
},
metric='eval_acc',
mode='max',
num_samples=10,
resources_per_trial={'cpu': 2, 'gpu': 0.5},
local_dir='./ray_results'
)
print('Best hyperparameters:', analysis.best_config)
在上面的代码中,我们使用了 Ray Tune 提供的 tune.run
函数来运行超参数优化任务。在 config
参数中,我们定义了需要优化的超参数和它们的取值范围。在 train_bert
函数中,我们根据超参数的取值来训练模型,并在验证集上评估模型性能。在每个 epoch 结束时,我们使用 tune.report
函数来报告模型在验证集上的准确率。在 tune.run
函数结束后,我们可以通过 analysis.best_config
来获取最优的超参数组合。
使用 Optuna 实现高效自动化调参:
Optuna 是一款用于超参数优化的 Python 库,可以自动化地搜索最优的超参数组合,从而提高模型的性能。
以下是使用 Optuna 进行 BERT 微调调参的代码示例和说明:
import optuna
import torch
from transformers import BertForSequenceClassification, BertTokenizer
# 加载数据集
train_dataset = ...
dev_dataset = ...
# 定义模型和优化器
def objective(trial):
# 定义超参数搜索空间
learning_rate = trial.suggest_loguniform('learning_rate', 1e-5, 1e-3)
weight_decay = trial.suggest_loguniform('weight_decay', 1e-8, 1e-5)
num_train_epochs = trial.suggest_int('num_train_epochs', 3, 5)
batch_size = trial.suggest_categorical('batch_size', [16, 32, 64])
# 加载预训练模型和tokenizer
model_name = 'bert-base-uncased'
model = BertForSequenceClassification.from_pretrained(model_name, num_labels=2)
tokenizer = BertTokenizer.from_pretrained(model_name)
# 定义优化器
optimizer = torch.optim.AdamW(model.parameters(), lr=learning_rate, weight_decay=weight_decay)
# 定义训练器
trainer = ...
# 训练模型
for epoch in range(num_train_epochs):
trainer.train(train_dataset, batch_size=batch_size, optimizer=optimizer)
trainer.evaluate(dev_dataset)
# 返回模型的性能指标
return trainer.get_best_metric()
# 运行超参数搜索
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=100)
# 输出最优超参数组合和性能指标
print('Best trial:')
trial = study.best_trial
print(' Value: {}'.format(trial.value))
print(' Params: ')
for key, value in trial.params.items():
print(' {}: {}'.format(key, value))
在上述代码中,我们使用 Optuna 进行超参数搜索,定义了学习率、权重衰减、训练轮数和批量大小等超参数的搜索空间,并在 objective 函数中定义了模型的训练和评估过程。最后,我们输出了最优超参数组合和性能指标。