📌

特定の層のみファインチューニングする方法

2024/03/09に公開

はじめに

LLM等のニューラルネットワークモデルのファインチューニングでは、通常は全ての層のパラメーターが更新されます。しかし、場合によっては特定の層のみをファインチューニングし、他の層のパラメーターは固定したままにしたい場合があります。

本記事では特定の層のみファインチューニングする方法について、プログラム例を紹介します。

内容

特定の層のみファインチューニングには、その層の重みのrequires_gradTrueとし、それ以外の重みのrequires_gradFalseとする必要があります。

本記事では以下5つのプログラム例を記載します。

  1. 特定の種類の層の重みの更新設定
  2. 特定の種類の層以外の重みの更新設定
  3. 入力に近い層の重み更新設定
  4. 出力に近い層の重みの更新設定
  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