📌
特定の層のみファインチューニングする方法
はじめに
LLM等のニューラルネットワークモデルのファインチューニングでは、通常は全ての層のパラメーターが更新されます。しかし、場合によっては特定の層のみをファインチューニングし、他の層のパラメーターは固定したままにしたい場合があります。
本記事では特定の層のみファインチューニングする方法について、プログラム例を紹介します。
内容
特定の層のみファインチューニングには、その層の重みのrequires_grad
をTrue
とし、それ以外の重みのrequires_grad
をFalse
とする必要があります。
本記事では以下5つのプログラム例を記載します。
- 特定の種類の層の重みの更新設定
- 特定の種類の層以外の重みの更新設定
- 入力に近い層の重み更新設定
- 出力に近い層の重みの更新設定
- ランダムな層の重みの更新設定
1. 特定の種類の層の重みの更新設定
ここではmlp
の重みを更新対象とするプログラムを示します。
for name, param in model.named_parameters():
if 'mlp' in name:
param.requires_grad = True
else:
param.requires_grad = False
2. 特定の種類の層以外の重みの更新設定
ここではmlp
の重み以外を更新対象とするプログラムを示します。
for name, param in model.named_parameters():
if 'mlp' in name:
param.requires_grad = False
else:
param.requires_grad = True
3. 入力に近い層の重みの更新設定
更新対象の重みを全体のパラメータの10%以下として、出力に近い層から重み更新対象とするプログラムを以下に示します。
percentage = 10
model_param_size = 0
current_requires_grad_param_size = 0
tmp_param_size = 0
for name, param in model.named_parameters():
model_param_size += param.numel()
param.requires_grad = False
# モデルのパラメータを順に処理し、指定された割合のパラメータを訓練可能に設定
for name, param in model.named_parameters():
tmp_param_size += param.numel()
if tmp_param_size > percentage * model_param_size / 100:
print(f"訓練可能に設定されたパラメータの割合: {current_requires_grad_param_size / model_param_size * 100}%")
break
else:
param.requires_grad = True
current_requires_grad_param_size = tmp_param_size
4. 出力に近い層の重みの更新設定
更新対象の重みを全体のパラメータの10%以下として、出力に近い層から重み更新対象とするプログラムを以下に示します。
percentage = 10
model_param_size = 0
current_requires_grad_param_size = 0
tmp_param_size = 0
for name, param in model.named_parameters():
model_param_size += param.numel()
param.requires_grad = False
# モデルのパラメータを逆順に処理し、指定された割合のパラメータを訓練可能に設定
for name, param in reversed(list(model.named_parameters())):
tmp_param_size += param.numel()
if tmp_param_size > percentage * model_param_size / 100:
print(f"訓練可能に設定されたパラメータの割合: {current_requires_grad_param_size / model_param_size * 100}%")
break
else:
param.requires_grad = True
current_requires_grad_param_size = tmp_param_size
5. ランダムな層の重みの更新設定
更新対象の重みを全体のパラメータの10%以下として、ランダムに重み更新対象の層を選ぶプログラムを以下に示します。
import random
percentage = 10
current_requires_grad_param_size = 0
tmp_size = 0
param_info = [(name, param.numel()) for name, param in model.named_parameters()]
random.shuffle(param_info) # パラメータ情報をランダムにシャッフル
total_param_size = sum(param_size for _, param_size in param_info)
threshold = total_param_size * (percentage / 100)
requires_grad_parameter_names = []
for name, size in param_info:
tmp_size += size
if tmp_size + size > threshold:
print(f"訓練可能に設定されたパラメータの割合: {current_requires_grad_param_size / model_param_size * 100}%")
break
requires_grad_parameter_names.append(name)
current_requires_grad_param_size = tmp_size
for name, param in model.named_parameters():
if name in requires_grad_parameter_names:
param.requires_grad = True
else:
param.requires_grad = False
Discussion