2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RakutenAI-7BのQLoRAファインチューニング+RAG

Posted at

[Python] Google Colab上でのRakutenAI-7BのファインチューニングとRAGを使った質問応答の実行


はじめに

こんにちは。リスキリングを目的にプログラミングを学びなおしている元プログラマー(現なんちゃってプロジェクトマネージャー)の @Nuts12 です。
現在私はIT企業に勤めながら、Aidemy というプログラミングスクールで夜な夜なPythonと機械学習に取り組んでいます。 本投稿はAidemy Premiumのカリキュラムの一環で、受講修了条件を満たすために公開しているブログ記事の第三弾となります。 今回は自然言語処理をテーマにGoogle Colab でLLMのファインチューニングを行います。

開発環境について

以下、今回の開発環境になります。
環境:Google Colab (Colab Pro)
GPU:A100 GPU

使用したパッケージ、モジュール一覧
from datasets import load_dataset
from datasets.download import DownloadManager
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training, TaskType
from sentence_transformers import SentenceTransformer
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig, is_torch_xla_available
import faiss
import torch

パッケージバージョン
accelerate==0.29.2
bitsandbytes==0.43.1
datasets==2.18.0
faiss-cpu==1.8.0
huggingface-hub==0.22.2
peft==0.10.0
pytorch-transformers==1.2.0
safetensors 0.4.2
sentence_transformers==2.6.1
torch==2.2.2
torchaudio==2.2.2
torchtext==0.17.2
torchvision==0.17.2
transformers==4.39.3

学習テーマの選定

前回の修了レポート提出時に Aidemy のチューターさんから伺っていました今ホットなキーワードの一つである「自然言語処理」を今回の学習テーマとしています。 その中でも2024年3月21日に楽天グループよりリリースされまた日本語に最適化されているLLM、RakutenAI-7B を使って質疑回答の精度を上げるためファインチューニングとRAGの実装を行いました。

学習の流れ

LLMファインチューニングの流れは以下を参考にしています。

Google Colabの設定

今回の作業を行うにあたりColab Proに課金しています。(ファインチューニングにあたり複数回課金しています。。)
以下のコードや実行環境は、Google Colab、且つランタイムにA100 GPU、ハイメモリが設定されていることが前提となっています。

Google Colab環境設定
# Google ドライブのマウント
from google.colab import drive
drive.mount('/content/drive', force_remount=True)

# 作業フォルダの移動
import os
%cd '/content/drive/MyDrive/Colab Notebooks/RakutenAI'

# パッケージのインストール
import locale

# locale.getpreferredencoding に lambda: 'UTF-8' が設定されていないとエラーとなるので、関数を設定し install後 元に戻す
tmp = locale.getpreferredencoding
locale.getpreferredencoding = lambda: 'UTF-8'
!pip install -Uqq huggingface-hub transformers pytorch-transformers torch torchvision torchtext accelerate torchaudio safetensors bitsandbytes datasets peft sentence_transformers faiss-cpu
locale.getpreferredencoding = tmp

学習

(1)基本パラメータの定義

基本パラメータ
# 基本パラメータ 
model_name = 'Rakuten/RakutenAI-7B-instruct'        # LLM Model RakutenAI-7B
dataset = 'kunishou/databricks-dolly-15k-ja'        # ファインチューニング用データセット
peft_name = 'lora-rakuten-7b-instruct'              # LoRa モデル名
output_dir = 'lora-rakuten-7b-instruct-results'     # LoRa 設定ファイル格納フォルダ
wikipedia_db = 'singletongue/wikipedia-utils'       # RAG用 データセット名(Wikipedia)
wikipedia_subset = 'passages-c400-jawiki-20230403'  # RAG用 データセット サブセット名(Wikipedia)
st_model_name = 'intfloat/multilingual-e5-small'    # SentenceTransformer モデル名  

(2)トークナイザーの定義

トークナイザーの設定
from transformers import AutoTokenizer

# トークナイザーの準備
tokenizer = AutoTokenizer.from_pretrained(model_name)

tokenizer.pad_token = tokenizer.eos_token       # unk(unknown token) → tokenizer.eos_tokenを設定
tokenizer.padding_side = "right"                # fp16でのオーバーフロー問題対策

(3)スペシャルトークンの確認

スペシャルトークンの確認
print(tokenizer.special_tokens_map)
print('bos_token :', tokenizer.bos_token, ',', tokenizer.bos_token_id)
print('eos_token :', tokenizer.eos_token, ',', tokenizer.eos_token_id)
print('unk_token :', tokenizer.unk_token, ',', tokenizer.unk_token_id)
print('pad_token :', tokenizer.pad_token, ',', tokenizer.pad_token_id)

>>> 出力結果
{'bos_token': '<s>', 'eos_token': '</s>', 'unk_token': '<unk>', 'pad_token': '</s>', 'additional_special_tokens': ['<unk>', '<s>', '</s>']}
bos_token : <s> , 1
eos_token : </s> , 2
unk_token : <unk> , 0
pad_token : </s> , 2

(4)トークナイズ関数の定義

トークナイズ関数の定義
# トークナイズ関数の定義
CUTOFF_LEN = 512                        # 最大長  256 → 512

# トークナイズ関数の定義
def tokenize(prompt, tokenizer):
    result = tokenizer(
        prompt,
        truncation = False,
        # max_length = CUTOFF_LEN,
        # padding = False,
    )
    return {
        'input_ids': result['input_ids'],
        'attention_mask': result['attention_mask'],
    }

# トークナイズ関数の確認 padding, attention_mask
tokenize('冷水と温水、どちらの重さが大きいか?', tokenizer)

>>> 出力結果
{'input_ids': [1,
  28705,
  31888,
  29692,
  29316,
  30971,
  29692,
  29041,
  39374,
  32190,
  29249,
  29422,
  37443,
  33483,
  29771],
 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

(5)データセットの準備

データセットの準備
 # データセットの準備
from datasets import load_dataset
data = load_dataset(dataset)

(6)学習用プロンプトテンプレートの準備

学習用プロンプトテンプレートの準備

# 学習用プロンプトテンプレートの準備
def generate_prompt(data_point):
    if data_point['input']:
        return f'''<s>Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.

### Instruction:
{data_point['instruction']}

### Input:
{data_point['input']}

### Response:
{data_point['output']}</s>'''
    else:
        return f'''<s>Below is an instruction that describes a task. Write a response that appropriately completes the request.

### Instruction:
{data_point['instruction']}

### Response:
{data_point['output']}</s>'''

(7)データの分割

データの分割
# 学習データと検証データの準備 (データの分割)
VAL_SET_SIZE = 200   # 検証はあまり意味をなさないので少なめに設定

train_val = data['train'].train_test_split(
    test_size=VAL_SET_SIZE, shuffle=True, seed=42
)
train_data = train_val['train']
val_data = train_val['test']
train_data = train_data.shuffle().map(lambda x: tokenize(generate_prompt(x), tokenizer))
val_data = val_data.shuffle().map(lambda x: tokenize(generate_prompt(x), tokenizer))

(8)学習モデルの設定

ここでQLoRaの4ビット量子化設定を行い、使用メモリの削減を図ります。

学習モデルの設定
 # モデルの準備
from transformers import AutoModelForCausalLM, BitsAndBytesConfig, is_torch_xla_available
from peft import prepare_model_for_kbit_training
import torch

# 量子化パラメータ設定
bnb_config = BitsAndBytesConfig(
    load_in_4bit = True,                        # 量子化の有効化
    bnb_4bit_quant_type = 'nf4',                # 量子化種別 nf4
    bnb_4bit_compute_dtype = torch.bfloat16,    # 量子化のdtype bfloat16
    bnb_4bit_use_double_quant = True            # 二重量子化の有効化 True 
)

# モデルの準備
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    device_map = 'auto',
    quantization_config = bnb_config 
)
model.config.use_cache = False              # キャッシュ (学習時はFalse)
# model.config.pretraining_tp = 1           # 事前学習で使用したテンソル並列ランク


# モデルのキャッシュ有効化(有効にするとパフォーマンスが低下する)
#model.gradient_checkpointing_enable()

# prepare_model_for_kbit_trainingではパラメータのfreezeを行いながら以下の3つの設定を行う
# 1. レイヤーノームをfp32にキャスト
# 2. 出力埋め込みレイヤーが勾配を必要とするように設定
# 3. 言語モデルのヘッドをfp32にアップキャスト
model = prepare_model_for_kbit_training(model)

(9)LoRAモデルの準備

学習精度を上げるために r を64に設定しました。
また、ターゲットモデルはself_attn層配下の3つに絞っています。
結果、学習対象パラメータ数は 7,410,552,832 から 37,748,736 まで削減できています。

LoRAモデルの準備
# LoRAモデルの準備
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training, TaskType

# LoRAのパラメータ
lora_config = LoraConfig(
    r = 64,                       # 行列の分割 Rを大きくすることでパラメータ数を増やすことが出来る
    lora_alpha = 64,              # rの2倍が目安
    # target_modules = [ 'q_proj', 'k_proj', 'v_proj', 'o_proj', 'gate_proj', 'up_proj', 'down_proj', 'lm_head', 'embed_tokens' ],  # ターゲットモデルの追加
    target_modules = [ 'q_proj', 'k_proj', 'v_proj' ],                                                                              # ターゲットモデルの追加
    lora_dropout = 0.05,
    bias = 'none',
    task_type=TaskType.CAUSAL_LM
)

# LoRAモデルの準備
model = get_peft_model(model, lora_config)

# 学習可能パラメータの確認
print(model.print_trainable_parameters())
for name, param in model.named_parameters():
    print(name)

>>> 出力結果
trainable params: 37,748,736 || all params: 7,410,552,832 || trainable%: 0.5093916318495791

(10)学習パラメータの設定

学習パラメータの設定

import transformers
eval_steps = 200
save_steps = 200
logging_steps = 20

# トレーナーの準備
trainer = transformers.Trainer(
    model = model,
    train_dataset = train_data,                   # 訓練データを設定
    eval_dataset = val_data,                      # 評価データを設定
    args = transformers.TrainingArguments(
        fp16 = False,                                   # fp16学習の無効化
        bf16 = True,                                    # bf16学習の有効化
        per_device_train_batch_size = 8,                # バッチサイズ(デフォルト8)
        per_device_eval_batch_size = 8,                 # バッチサイズ(デフォルト8)
        gradient_accumulation_steps = 1,
        num_train_epochs = 8,                           # エポックを 8 回に設定
        learning_rate = 2e-4,
        warmup_steps = 0.03,
        logging_steps = logging_steps,
        evaluation_strategy = 'steps',
        save_strategy = 'steps',
        eval_steps = eval_steps,
        save_steps = save_steps,
        output_dir = output_dir,
        report_to = 'none',
        save_total_limit = 3,
        push_to_hub = False,
        auto_find_batch_size = True,
        optim = 'adamw_bnb_8bit',                         # メモリ削減の為 'adamw_bnb_8bit' を選択
    ),
    data_collator=transformers.DataCollatorForLanguageModeling(tokenizer, mlm = False),
)

(11)学習の実行

終了するのに半日かかりました。。

学習の実行
# 学習の実行
model.config.use_cache = False
trainer.train()
model.config.use_cache = True

# LoRAモデルの保存
trainer.model.save_pretrained(peft_name)

推論

(1)学習済みモデルの読み込み

LLMモデルを学習時と同様に4ビット量子化パラメータを設定して読み込み、学習済みのLoRAモデルに取り込みます。

学習済みモデルの読み込み
#
#  推論 モデルとトークナイザーの準備 (4bit量子化 確認用)
#

# モデルの準備
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
from peft import prepare_model_for_kbit_training, PeftModel
from peft import  LoraConfig, get_peft_model, prepare_model_for_kbit_training, TaskType
import torch
from transformers.utils import is_torch_xla_available

# 量子化パラメータ設定
bnb_config = BitsAndBytesConfig(
    load_in_4bit = True,                        # 量子化の有効化
    bnb_4bit_quant_type = 'nf4',                # 量子化種別 nf4
    bnb_4bit_compute_dtype =  torch.bfloat16,   # 量子化のdtype bfloat16
    bnb_4bit_use_double_quant = True            # 二重量子化の有効化  
)

# モデルの準備
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    device_map = 'auto',
    quantization_config = bnb_config            # 量子化パラメータを設定
)

# トークンナイザーの準備
tokenizer = AutoTokenizer.from_pretrained(model_name)

tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "right"                # fp16でのオーバーフロー問題対策

# LoRAモデルの準備
model = PeftModel.from_pretrained(
    model,
    peft_name,
    device_map = 'auto'
)

# 評価モード
model.eval()

(2)推論用プロンプトテンプレートの準備

推論用プロンプトテンプレートの準備
# プロンプトテンプレートの準備(推論用) レスポンス内容無し
def generate_prompt(data_point):
    if data_point['input']:
        return f'''Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.

### Instruction:
{data_point['instruction']}

### Input:
{data_point['input']}

### Response:
'''
    else:
        return f'''Below is an instruction that describes a task. Write a response that appropriately completes the request.

### Instruction:
{data_point['instruction']}

### Response:

(3)推論の実施

学習済みモデルの読み込み
# テキスト生成関数の定義 (オリジナル)
def org_generate(instruction, input=None,  maxTokens=4096):

    # 推論
    prompt = generate_prompt({'instruction':instruction,'input':input})
    input_ids = tokenizer(prompt, return_tensors='pt', truncation=True).input_ids.cuda()
    outputs = model.generate(
        input_ids = input_ids,
        max_new_tokens = maxTokens,
        do_sample = True,
        temperature = 0.7,                              # 湿度(確率)
        top_p = 0.9,                                    # 確率の閾値 0.75 -> 0.9
        pad_token_id = tokenizer.pad_token_id,          # tokenizer.pad_token_id
        repetition_penalty = 1.1,                       # 重複ペナルティ 重複が無いようにする
    )
    outputs = outputs[0].tolist()

    decoded = tokenizer.decode(outputs)

    # BOS, EOSトークンを削除
    decoded = tokenizer.decode(outputs)
    if  (index := decoded.find(tokenizer.bos_token)) != -1:
        decoded = decoded[index+len(tokenizer.bos_token):]
    if  (index := decoded.find(tokenizer.eos_token)) != -1:
        decoded = decoded[:index]

    print(decoded)

# 推論の実行
org_generate("ヴァージン・オーストラリア航空はいつから運航を開始したのですか?")

>>> 出力結果
Below is an instruction that describes a task. Write a response that appropriately completes the request.

### Instruction:
ヴァージンオーストラリア航空はいつから運航を開始したのですか

### Response:
1980年9月25日に運航を開始しました

### Explanation:
本文中にヴァージンオーストラリアという表記が見られませんが文脈より判断して質問中のヴァージンオーストラリア航空ヴァージンオーストラリアと省略して回答しています また日本語で書かれた文章であるため英語表記の"Virgin Australia Airlines Pty Limited""Virgin Blue Holdings Pty Ltd"は省略しています

回答としてデータセットのoutputに定義されている 2000年8月31日 を期待していたのに違う日付が返ってきます。 データセットにあるその他の質問(instruction)をいくつか入力しても、期待する回答は得られませんでした。 あれだけの時間をかけて学習したのに。。。

試しに、学習時に設定していたinput情報もパラメータに与えて同じ質問をして見ます。

推論の実行(input情報あり)
# 推論の実行
org_generate("ヴァージン・オーストラリア航空はいつから運航を開始したのですか?",
             input='ヴァージン・オーストラリア航空(Virgin Australia Airlines Pty Ltd)はオーストラリアを拠点とするヴァージン・ブランドを冠する最大の船団規模を持つ航空会社です。2000年8月31日に、ヴァージン・ブルー空港として、2機の航空機、1つの空路を運行してサービスを開始しました。2001年9月のアンセット・オーストラリア空港の崩壊後、オーストラリアの国内市場で急速に地位を確立しました。その後はブリスベン、メルボルン、シドニーをハブとして、オーストラリア国内の32都市に直接乗り入れるまでに成長しました。'
             )

>>> 出力結果
Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.

### Instruction:
ヴァージンオーストラリア航空はいつから運航を開始したのですか

### Input:
ヴァージンオーストラリア航空Virgin Australia Airlines Pty Ltdはオーストラリアを拠点とするヴァージンブランドを冠する最大の船団規模を持つ航空会社です2000年8月31日にヴァージンブルー空港として2機の航空機1つの空路を運行してサービスを開始しました2001年9月のアンセットオーストラリア空港の崩壊後オーストラリアの国内市場で急速に地位を確立しましたその後はブリスベンメルボルンシドニーをハブとしてオーストラリア国内の32都市に直接乗り入れるまでに成長しました

### Response:
2000年8月31日

### Explanation:
ヴァージンオーストラリア航空がサービス開始したのは2000年8月31日でした

今度は期待する回答が返ってきました。input情報の中に答えがあるので当たり前の気がしますがそうでもないようです。

この件について、Aidemy のチューターさんに質問をしたところ、学習時、LLMにinput情報を与えているので、推論時も同様にデータソースが提供される前提の学習モデルになっているとの回答をいただきました。また、仮に質問と回答だけで学習させ、期待する結果を得ようとするならば1つの質問について言い方を変えて複数回学習させなければならないとも教示いただきました。これではデータセット作成にかかる時間もそうですが、Google Colab の課金もいくらになるか分かりません。

そこで、ご提案いただいたのがRAG(Retrieval Augmented Generation)を使ったアプローチです。

RAGを使用することで、LLMはリアルタイムで外部の情報源にアクセスし、より正確で豊富な回答を生成することが可能になります。Wikipediaデータセットを使った faiss 用の index が公開されていたので、今回のソースに取り込んでみました。

(4)推論の実施 RAG利用版

推論の実施 RAG使用版
from datasets.download import DownloadManager
from datasets import load_dataset
from sentence_transformers import SentenceTransformer
import faiss

# RAG 設定

# wikipedia 日本語データセットのロード
wikija_dataset = load_dataset(
    path = wikipedia_db,
    name = wikipedia_subset,
    split = 'train',
)

# faiss index のダウンロード
dm = DownloadManager()
index_local_path = dm.download(f'https://huggingface.co/datasets/hotchpotch/wikipedia-passages-jawiki-embeddings/resolve/main/faiss_indexes/passages-c400-jawiki-20230403/multilingual-e5-small-passage/index_IVF2048_PQ96.faiss')

# faiss index のロード
faiss_index = faiss.read_index(index_local_path)

# embeddings へ変換するモデルのロード
model_st = SentenceTransformer(st_model_name)
model_st.max_seq_length = 4096

# embeddings へ変換
def to_emb(model_st, text, prefix='query: '):
    return model_st.encode([prefix + text], normalize_embeddings = True)

# テキスト生成関数の定義
def generate(instruction, input=None, maxTokens=4096):

    # inputが設定されていない場合はRAGから情報を取得する
    if not input:

        # 質問と類似するベクトルを取得する
        emb = to_emb(model_st, instruction)

        # faiss で検索して、関連 Top-3 を取り出す
        TOP_K = 3
        data_input = ''
        scores, indexes = faiss_index.search(emb, TOP_K)
        for idx, (id, score) in enumerate(zip(indexes[0], scores[0])):
            data = wikija_dataset[int(id)]
            # print((score, data["title"], data["text"]))
            data_input += data["text"]

        # inputとなる情報をwikipediaより取得する。
        input = data_input

    # 推論
    prompt = generate_prompt({'instruction':instruction,'input':input})
    input_ids = tokenizer(prompt, return_tensors='pt', truncation=True).input_ids.cuda()
    outputs = model.generate(
        input_ids = input_ids,
        max_new_tokens = maxTokens,
        do_sample = True,
        temperature = 0.7,                              # 湿度(確率)
        top_p = 0.9,                                    # 確率の閾値 0.75 -> 0.9
        # top_k = 40,                                   # 次のTokenを40に絞り込む
        pad_token_id = tokenizer.pad_token_id,          # add 2024/3/21  tokenizer.pad_token_id ?
        repetition_penalty = 1.1,                       # 重複ペナルティ 重複が無いようにする
        # no_repeat_ngram_size = 1,
    )
    outputs = outputs[0].tolist()

    # BOS, EOSトークンを削除
    decoded = tokenizer.decode(outputs)
    if  (index := decoded.find(tokenizer.bos_token)) != -1:
        decoded = decoded[index+len(tokenizer.bos_token):]
    if  (index := decoded.find(tokenizer.eos_token)) != -1:
        decoded = decoded[:index]

    print(decoded)

# 推論の実行
generate("ヴァージン・オーストラリア航空はいつから運航を開始したのですか?")

>>> 出力結果
 Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.

### Instruction:
ヴァージンオーストラリア航空はいつから運航を開始したのですか

### Input:
2000年8月31日ヴァージンブルーは2機の航空機によってシドニー - ブリスベン線の運航(毎日7往復)を開始したその後オーストラリアのすべての主要都市と多くの観光地へ就航路線を拡大したヴァージングループはヴァージンブルーが業績不振であっても保有し続けていたが2005年始めにオーストラリアの運送複合企業パトリックコーポレーション (Patrick Corporation) がヴァージンブルーに対して敵対的買収を行ったオファーの締め切りにあたりパトリックは議決権を持つ株の62%を得て経営権を取得したなおヴァージングループは25%の株を所有することとなった2002年には競合相手であったアンセット航空が倒産した現在ではアンセット航空の旧顧客の多くを獲得しているヴァージンオーストラリアインターナショナル(英語:Virgin Australia International旧名:Vオーストラリア)リチャードブランソンのヴァージングループの豪州国内線航空会社ヴァージンオーストラリア(ヴァージンブルーホールディングス)によって運営された長距離国際線航空会社であるヴァージンオーストラリアに吸収され2011年12月7日に運航を停止した2022年12月14日ボーイング737-8(737MAX8)型機の導入に合わせて翌年6月28日から羽田線の運航を開始することが発表された使用機材の航続距離などの関係で豪州側の発着空港はブリスベンからケアンズに変更となる

### Response:
2000年8月31日です

今度はinput情報を渡さないでも期待する回答が返ってきました。Wikipediaデータセットから質問と類似する情報を取得しinputとしてLLMに渡すことが出来ています。 試しにデータセットにない質問もしてみます。

推論の実施 データセット以外の質問
def rakuten(s):
    generate(s)
    print()
    print()

while True:
    rakuten(input())

>>> 出力結果
"楽曲『約束はいらない』でデビューした、声優は誰?"
 Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.

### Instruction:
"楽曲『約束はいらない』でデビューした、声優は誰?"

### Input:
約束はいらない(やくそくはいらない)坂本真綾のデビューシングル本格的な歌手活動は1996年にテレビアニメ天空のエスカフローネへ出演したことがきっかけで始めており同作のオープニングテーマソングである約束はいらない(岩里祐穂作詞菅野よう子作曲)をシングルとして発売し同年4月にビクターエンタテインメントよりデビューした以降声優ラジオパーソナリティ女優業と並行しながら活動を続け現在においてシングル24枚オリジナルアルバム8枚コンセプトアルバム3枚コレクションアルバム3枚ベストアルバム1枚ライブDVD4枚を発表しているアニメのサウンドトラックにおける楽曲収録も多く自身が声優として関わっていない作品の楽曲を担当することもある作品および楽曲はデビューから2003年まで菅野よう子がプロデュースを行っていたが2005年以降は坂本自身が田村充義と共同で2013年以降は坂本がセルフプロデュースを行っている坂本真綾の歌手デビュー作品当時坂本はまだ無名の声優であったが同曲がテーマソングとなったアニメ天空のエスカフローネとともに知名度を上げることとなる後に指輪が同アニメの劇場版映画の主題歌となったカップリング曲ともだちは後に1枚目のアルバムグレープフルーツにてMY BEST FRIENDというタイトルで全英語詞で収録されている累計出荷枚数は3万枚

### Response:
坂本真綾


日本で二番目に高い山は
 Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.

### Instruction:
日本で二番目に高い山は

### Input:
日本の棚田百選に剪定されている大垪和地区の北方に位置する山名は最高地点の西峰と東峰の2つの頂上を有することに由来する東峰の山腹には山岳密教寺院である両山寺や二上神社天邪鬼の重ね岩がある北岳は日本で2番目に高い山であることから様々な2番目を表す比喩表現に使われている ネガティブな表現で用いられるケースが多くスポーツ大会や芸術での選考において1位しか注目されないことを富士山と北岳の知名度の違いで表現される また富士山が特徴的な山体をしていることと独立峰であるために各方向から発見しやすいことに対し北岳は周辺を南アルプスの高峰に囲まれているため市街地から見えにくく見えたとしても山頂の一部のみとなってしまうまた山岳写真から北岳を判別することも容易ではなくこれらのことから富士山との知名度の差が大きい二ッ岳(ふたつだけ)四国山地西部の石鎚山脈に属する山である二ツ岳と表記される場合もあるが国土地理院の地形図は二ッ岳と表記されている四国百名山に選定されている山名は二つの岩峰が相対して屹立していることによる四国においてと付く山は少ない

### Response:
日本第二の高峰は山梨県にある北岳である北岳は二上山とも呼ばれ二上神社のある東峰と両山寺のあるところの西峰の二つの山頂を持つ北東側に富士山が見える南アルプス国立公園の南端に位置し周辺は樹林に覆われた急斜面となっている山梨百名山のひとつである登山道は北沢峠からのルートと御小屋尾根からのルートの2本がある北沢峠からのルートは八ヶ岳連峰の主脈を横断するコースでもある標高3000m以上で富士山と並ぶような場所でもありその存在感は日本有数のものである


日本の現在の総理大臣は
 Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.

### Instruction:
日本の現在の総理大臣は

### Input:
内閣総理大臣(ないかくそうりだいじん: Prime Minister)日本の内閣の首長たる国務大臣文民である国会議員が就任しその地位及び権限は日本国憲法や内閣法などに規定されている現任は第101代岸田文雄(在任: 2021令和3年11月10日 - )歴代の内閣総理大臣は内閣総理大臣の一覧を参照内閣総理大臣顕彰(ないかくそうりだいじんけんしょう)日本の内閣総理大臣が授与する顕彰である1966(昭和41年)当時の首相佐藤栄作によって創設され2021年4月時点でこれまでに34人15団体に対して授与されている総務大臣(そうむだいじん英語: Minister for Internal Affairs and Communications)日本の総務省の長および主任の大臣たる国務大臣

### Response:
安倍晋三

データセットが2023/04/03のWikipediaなので若干データが古いですが生成AIっぽい回答を返しています。正直どこまでファインチューニングの成果があったのか見定めることが出来ませんでしたが、LLMのファインチューニングとRAGの検証はここで一区切りつけることとします。

今後の学習課題とまとめ

今回、自然言語処理としてLLMのファインチューニングに取り組んで見て、この分野の技術が日進月歩で進化していることを感じとることが出来ました。 日本語用LLMも私がこのテーマに取り組み始めた時は、サイバーエージェント社が公開している OpenCALM-7B が最新でしたが学習中に楽天グループから RakutenAI-7B が発表され、NTTからも tsuzumi が商用サービスとしてリリースされています。

また、量子化の技術も4ビットから、2ビットや1ビットへの検討が進んでいるようです。

今後はLLMの動向を引き続き注視しつつ、割愛してきた基本的な考え方や理論、およびその実装について、書籍やインターネットを使って学習と実践を繰り返し、自分の血となり肉となるレベルまで腹落ちさせていきたいと思います。

差し当たり、以下の書籍を購入し読み進めているところです。

また、Aidemy での学習修了レポートは本投稿で最後となります。Aidemyでの残りの学習期間で、これまで学習してきたデータ分析、AI学習、自然言語学習の各講座について反復して受講する予定です。既に忘れてしまっている点や一回目では気付かなかった点等、間違いなくあると思いますが、復習の際は全体の枠組みを常にイメージしながらパーツをはめ込むように整理して学びなおしを行い、ノウハウの定着と理解の深堀りを図りたいと考えています。

新しい発見があれば、備忘を兼ねて適宜ブログで情報発信できればと思っています。
今後ともよろしくお願いいたします。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?