AIGC の時代に、大規模モデルの微調整はどのように最も重要な役割を果たすことができるでしょうか?

人工知能の急速な発展により、大規模モデルの広範な適用が促進され、言語、視覚、音声の分野での適用効果がますます向上しています。ただし、大規模なモデルのトレーニングには膨大なコンピューティング リソースと時間が必要であり、このリソースの浪費を減らすために、微調整が一般的な手法になっています。微調整とは、事前トレーニング済みのモデルに基づいて小さなデータ セットでトレーニングすることにより、新しいタスクに適応することを指します。AIGC (AI チップ) の出現により、より高速な計算速度とより大きなストレージ容量を提供できる大規模モデルの推進がさらに加速しました。この記事では、AIGC の下で大規模なモデルを微調整する方法を紹介します。これには、すべてのレイヤーの微調整、最上層の微調整、最下層の凍結、レイヤーごとの微調整、および転移学習が含まれます。オープン ソース フレームワークである PaddlePaddle を使用して、自然言語処理とコンピューター ビジョンを例として、これらの方法の原則と実装手順を説明します。

AIGCの大規模モデルの中で、現在Chatgptという大規模モデルが最もよく知られています.現在、外国の大物もコンピュータービジョンの観点から写真をアップロードするかビデオをアップロードするかを検討しています.私は彼に視覚的なタスクを行うように言いました.彼は対応する視覚的要件を満たすことができます。

このような大規模なモデルについては、当面オープン ソース モデルを使用する方法がなく、モデルに含まれるパラメーターが大きすぎますが、さまざまなビジネス状況に直面して、使い果たされたマシンを自分でトレーニングすると、より多くのアプリケーションを実現するために大規模モデルを微調整する方法

微調整方法

ディープ ラーニングでは、微調整は事前トレーニング済みモデルのパフォーマンスを向上させるための重要な手法です。ChatGPT の微調整に加えて、微調整できる事前トレーニング済みのモデルが他にも多数あります。事前トレーニング済みモデルを微調整するいくつかの方法を次に示します。

  • すべてのレイヤーを微調整する: 事前トレーニング済みモデルのすべてのレイヤーを微調整して、新しいタスクに適応させます。
  • 最上位レイヤーの微調整: 新しいタスク用に事前トレーニング済みモデルの最上位レイヤーのみを微調整します。
  • 最下層を固定する: 事前トレーニング済みモデルの最下層を固定し、最上位層のみを微調整します。
  • レイヤーごとの微調整: 最下層から始めて、すべてのレイヤーが微調整されるまで、事前トレーニング済みモデルをレイヤーごとに微調整します。
  • 学習の伝達: 事前トレーニング済みモデルの知識を新しいタスクに移して、モデルのパフォーマンスを向上させます。この方法は通常、最上層を微調整するか、最下層を凍結する方法を使用します。

モデルのパラメータ微調整については、このように理解していただけると思いますが、元のchatgptを例にすると、一般的な大型モデルのようなものです。

大学ですべての専門知識を学んだ大学生のように、過去の学習経験と人生のいくつかの事柄に基づいて、彼はすでに独自の学習方法と思考ロジックを持っています。(これはモデルのパラメータです)

大学生が卒業後、ある業界で働くようになった今、仕事の成果を出すために仕事の内容を学び始めなければなりません。彼の学習の過程で、彼は大学で学んだ専門知識の学習方法を適用できますか?同じ学習方法を仕事の学習に使用できますか?(微調整です)

微調整とは、過去に学んだことを新しいコンテンツに適用して、新しい結果を生み出すことです。

さまざまなレイヤーの微調整に戻りますが、どのレイヤーを微調整する必要があるかをどのように選択しますか? モデルのこれらのレイヤーが元のデータ セットでどのような経験を学習したかを知る必要がありますか?
それらの経験は、別のデータ セットで再利用できますか?

ニューラル ネットワークで、どの層が経験から学習しているのか?

コンピューター ビジョンでは、畳み込みニューラル ネットワーク (CNN) は通常、次の経験を学習します。

  • 局所認識: CNN は、畳み込み演算とプーリング演算を通じてエッジやテクスチャなどの局所特徴を学習できるため、画像の局所知覚を実現できます。
  • 翻訳不変性: CNN は翻訳に対する特徴の不変性を学習できるため、同じオブジェクトのさまざまな部分について、CNN は同様の特徴表現を生成できます。
  • 階層的抽象化: CNN は、エッジなどの低レベルの機能から、オブジェクトの一部または全体などの高レベルの機能まで、多層畳み込み操作を通じて、より多くの抽象的な機能を学習できます。

さらに、Self-Attention Model や変換モジュールなど、いくつかの注意ベースのモデルが近年登場しており、学習した注意の重みを使用して画像の特徴を重み付けおよび合計し、より洗練されたものにすることができます。

自然言語処理では、リカレント ニューラル ネットワーク (RNN) とトランスフォーマー ネットワークは通常、次の経験を学習します。

  • タイミングの依存関係: RNN と Transformer ネットワークは、テキスト シーケンスのタイミングの依存関係を学習できるため、テキストのシリアル化を実現できます。
  • 階層的抽象化: RNN と Transformer ネットワークは、多層ニューラル ネットワークを介してテキストの階層的抽象化を実装できるため、より高レベルのテキスト特徴表現を学習できます。
  • コンテキスト依存性: RNN と Transformer ネットワークはコンテキスト依存性を学習できるため、コンテキストベースのテキスト特徴表現を生成できるため、モデルのパフォーマンスが向上します。

コンピュータビジョンや自然言語処理のタスクを処理するために、モデルの上流部分は学習経験の過程にあると言えます

しかし、コンピューター ビジョンと自然言語処理がモデルを微調整している場合の違いは次のとおりです。

コンピューター ビジョンの場合、異なる画像と学習経験は完全に異なる場合がありますが、自然言語処理の異なるテキストの場合、学習経験は同じである可能性があります。これは、テキスト データと機能が文脈や言語のタイミングにより依存するためです。これらの機能は、さまざまな内容のテキストに適用できます。(例えば、論文を書くこととエッセイを書くこと、書くことには大きな類似点があります)

パドルによるモデルの微調整

以下は、PaddlePaddle フレームワークを使用した上記 5 つの微調整メソッドのサンプル コードです。

import paddle
from paddle import nn

# 加载预训练的Transformer模型
pretrained_model = paddle.vision.models.Transformer()

# 1. 微调所有层
for param in pretrained_model.parameters():
    param.trainable = True

# 2. 微调顶层
for param in pretrained_model.decoder.parameters():
    param.trainable = True

# 3. 冻结底层
for param in pretrained_model.encoder.parameters():
    param.trainable = False

# 4. 逐层微调
for i, layer in enumerate(pretrained_model.encoder.layers):
    if i >= 6:  # 只微调第6层及以上的层
        for param in layer.parameters():
            param.trainable = True
    else:
        for param in layer.parameters():
            param.trainable = False

# 5. 迁移学习
# 加载预训练的模型
pretrained_model = paddle.vision.models.ResNet50(pretrained=True)

# 新建分类器
num_classes = 10
classifier = nn.Linear(2048, num_classes)

# 冻结预训练模型的所有层
for param in pretrained_model.parameters():
    param.trainable = False

# 微调新建分类器的参数
for param in classifier.parameters():
    param.trainable = True

# 将预训练模型和新建分类器组合成新的模型
model = nn.Sequential(pretrained_model, classifier)

上記のコードでは、最初に paddle.vision.models.Transformer() を介して事前トレーニング済みの Transformer モデルを読み込みました。その後、微調整方法に応じて、モデルのさまざまなレイヤーがそれぞれ微調整または凍結されます。最後に、転移学習法を使用して、事前トレーニング済みのモデルと新しい分類器を組み合わせて、新しいモデルを形成します。

Paddle を使用した ChatGPT モデルの 5 つの微調整方法

すべてのレイヤーを微調整する

import paddle
from paddlenlp.transformers import GPT2Model, GPT2ForPretraining, GPT2PretrainingCriterion

# 加载预训练模型
model = GPT2ForPretraining.from_pretrained('gpt2-medium-en')
tokenizer = GPT2Tokenizer.from_pretrained('gpt2-medium-en')

# 定义新的分类头
class_num = 2
cls = paddle.nn.Linear(model.config["hidden_size"], class_num)

# 将新的分类头添加到模型中
model.cls = cls

# 通过微调所有层来适应新任务
optimizer = paddle.optimizer.Adam(learning_rate=1e-5, parameters=model.parameters())
criterion = GPT2PretrainingCriterion()

最上層を微調整する

import paddle
from paddlenlp.transformers import GPT2Model, GPT2ForPretraining, GPT2PretrainingCriterion

# 加载预训练模型
model = GPT2ForPretraining.from_pretrained('gpt2-medium-en')
tokenizer = GPT2Tokenizer.from_pretrained('gpt2-medium-en')

# 固定模型底层,只微调顶层
for param in model.parameters():
    param.trainable = False

# 定义新的分类头
class_num = 2
cls = paddle.nn.Linear(model.config["hidden_size"], class_num)

# 将新的分类头添加到模型中
model.cls = cls

# 通过微调顶层来适应新任务
for param in model.cls.parameters():
    param.trainable = True
optimizer = paddle.optimizer.Adam(learning_rate=1e-5, parameters=model.cls.parameters())
criterion = paddle.nn.CrossEntropyLoss()

最下層をフリーズ

import paddle
import paddle.nn.functional as F
from paddlenlp.transformers import GPTForPretraining, GPTChineseTokenizer

# 加载预训练模型和分词器
model = GPTForPretraining.from_pretrained('gpt-cpm-large-cn')
tokenizer = GPTChineseTokenizer.from_pretrained('gpt-cpm-large-cn')

# 构造数据集和数据加载器
train_ds = [['今天天气不错'], ['明天要下雨'], ['这个季节很适合旅游']]
train_ds = [{
    
    'text': text} for text in train_ds]

def batch_iter(data, batch_size):
    num_batches = len(data) // batch_size
    if len(data) % batch_size != 0:
        num_batches += 1
    for i in range(num_batches):
        batch = data[i * batch_size: (i + 1) * batch_size]
        yield batch

batch_size = 2
train_loader = paddle.io.DataLoader(train_ds, batch_size=batch_size, shuffle=True, drop_last=True)

# 构造优化器和损失函数
optimizer = paddle.optimizer.AdamW(parameters=model.parameters(), learning_rate=1e-4)
criterion = F.cross_entropy

# 冻结底层
for layer in model.layers[:6]:
    layer.eval()
    for param in layer.parameters():
        param.trainable = False

# 微调模型
for epoch in range(3):
    for batch in train_loader:
        texts = [example['text'] for example in batch]
        encoded_inputs = tokenizer(texts, return_attention_mask=True, return_length=True, padding=True)
        input_ids = paddle.to_tensor(encoded_inputs['input_ids'])
        attention_mask = paddle.to_tensor(encoded_inputs['attention_mask'])
        logits = model(input_ids, attention_mask=attention_mask)[0]
        loss = criterion(logits.reshape(-1, logits.shape[-1]), input_ids.reshape(-1))
        loss.backward()
        optimizer.step()
        optimizer.clear_grad()
    print(f'Epoch {
      
      epoch + 1}: loss={
      
      loss.numpy():.4f}')

# 保存微调后的模型
paddle.save(model.state_dict(), 'gpt-cpm-large-cn-finetuned

レイヤーごとに微調整

import paddle
import paddle.nn.functional as F
from paddlenlp.transformers import GPTForPretraining, GPTChineseTokenizer

# 加载预训练模型和分词器
model = GPTForPretraining.from_pretrained('gpt-cpm-large-cn')
tokenizer = GPTChineseTokenizer.from_pretrained('gpt-cpm-large-cn')

# 构造数据集和数据加载器
train_ds = [['今天天气不错'], ['明天要下雨'], ['这个季节很适合旅游']]
train_ds = [{
    
    'text': text} for text in train_ds]

def batch_iter(data, batch_size):
    num_batches = len(data) // batch_size
    if len(data) % batch_size != 0:
        num_batches += 1
    for i in range(num_batches):
        batch = data[i * batch_size: (i + 1) * batch_size]
        yield batch

batch_size = 2
train_loader = paddle.io.DataLoader(train_ds, batch_size=batch_size, shuffle=True, drop_last=True)

# 构造优化器和损失函数
optimizer = paddle.optimizer.AdamW(parameters=model.parameters(), learning_rate=1e-4)
criterion = F.cross_entropy

# 迁移学习微调模型
for epoch in range(3):
    for batch in train_loader:
        texts = [example['text'] for example in batch]
        encoded_inputs = tokenizer(texts, return_attention_mask=True, return_length=True, padding=True)
        input_ids = paddle.to_tensor(encoded_inputs['input_ids'])
        attention_mask = paddle.to_tensor(encoded_inputs['attention_mask'])
        logits = model(input_ids, attention_mask=attention_mask)[0]
        loss = criterion(logits.reshape(-1, logits.shape[-1]), input_ids.reshape(-1))
        loss.backward()
        optimizer.step()
        optimizer.clear_grad()
    print(f'Epoch {
      
      epoch + 1}: loss={
      
      loss.numpy():.4f}')

# 保存微调后的模型
paddle.save(model.state_dict(), 'gpt-cpm-large-cn-finetuned-transfer-learning.pdparams')

上記のコードでは、モデルの微調整の方法をレイヤーごとの微調整から転移学習の微調整に変更しました。具体的には、元のレイヤーごとの微調整およびその他の関連コードで、隠れ状態の計算と各レイヤーの出力の取得を削除し、入力と注意マスクをモデルに直接渡し、最後のレイヤーの出力を取得しました、およびバックプロパゲーションと最適化のための損失を計算します。

同時にモデル保存時のファイル名を gpt-cpm-large-cn-finetuned-layer-wise.pdparams から gpt-cpm-large-cn-finetuned-transfer-learning.pdparams に変更し、レイヤーを区別できるようにしました。層ごとの微調整と転移学習の微調整。

転移学習

import paddle
import paddle.nn.functional as F
from paddlenlp.transformers import GPTForPretraining, GPTChineseTokenizer

# 加载预训练模型和分词器
model = GPTForPretraining.from_pretrained('gpt-cpm-large-cn')
tokenizer = GPTChineseTokenizer.from_pretrained('gpt-cpm-large-cn')

# 构造数据集和数据加载器
train_ds = [['今天天气不错'], ['明天要下雨'], ['这个季节很适合旅游']]
train_ds = [{
    
    'text': text} for text in train_ds]

def batch_iter(data, batch_size):
    num_batches = len(data) // batch_size
    if len(data) % batch_size != 0:
        num_batches += 1
    for i in range(num_batches):
        batch = data[i * batch_size: (i + 1) * batch_size]
        yield batch

batch_size = 2
train_loader = paddle.io.DataLoader(train_ds, batch_size=batch_size, shuffle=True, drop_last=True)

# 构造优化器和损失函数
optimizer = paddle.optimizer.AdamW(parameters=model.parameters(), learning_rate=1e-4)
criterion = F.cross_entropy

# 训练模型
epochs = 3
for epoch in range(epochs):
    for batch in train_loader:
        texts = [example['text'] for example in batch]
        encoded_inputs = tokenizer(texts, return_attention_mask=True, return_length=True, padding=True)
        input_ids = paddle.to_tensor(encoded_inputs['input_ids'])
        attention_mask = paddle.to_tensor(encoded_inputs['attention_mask'])
        logits = model(input_ids, attention_mask=attention_mask)[0]
        loss = criterion(logits.reshape(-1, logits.shape[-1]), input_ids.reshape(-1))
        loss.backward()
        optimizer.step()
        optimizer.clear_grad()
    print(f'Epoch {
      
      epoch + 1}: loss={
      
      loss.numpy():.4f}')

# 保存微调后的模型
paddle.save(model.state_dict(), 'gpt-cpm-large-cn-finetuned.pdparams')

上記のコードでは、最初に事前トレーニング済みの GPT モデルとトークナイザーを読み込み、次に単純なデータセットとデータ ローダーを構築しました。次に、AdamW オプティマイザーとクロスエントロピー損失関数を使用してモデルをトレーニングし、トレーニング後に微調整されたモデルを保存します。

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/weixin_42010722/article/details/129378983