BunaML’s diary

機械学習、音声・自然言語、Machine Learning, NLP, Audio, Software Development

NGCでPileをダウンロードする手順

*Pileを入手する手段は2023年末時点でほぼなくなり、以下の方法ではPileは結局ダウンロードできない。

ngc.nvidia.com

1. NGCのダウンロード

NGCCLIツールをインストールする。

wget --content-disposition https://api.ngc.nvidia.com/v2/resources/nvidia/ngc-apps/ngc_cli/versions/3.35.0/files/ngccli_linux.zip -O ngccli_linux.zip && unzip ngccli_linux.zip

ダウンロードしてきたファイルのMD5とSHA256ハッシュを確認し、整合性をチェックする。

find ngc-cli/ -type f -exec md5sum {} + | LC_ALL=C sort | md5sum -c ngc-cli.md5
sha256sum ngccli_linux.zip

CLIツールを実行可能に設定しパスをシステムに追加する。

chmod u+x ngc-cli/ngc
echo "export PATH=\"\$PATH:$(pwd)/ngc-cli\"" >> ~/.bash_profile && source ~/.bash_profile

2. NGCの設定と認証

NGC CLIを使用する前にAPIキーとCLIの出力形式を設定する。

ngc config set

ここで、プロンプトに従ってAPIキー、出力形式(csv, ascii, json)、組織、チーム、エースなどの情報を入力。

3. データセットのダウンロードと前処理

Pileデータセットをダウンロードし、NGCのバッチCLIで前処理を行う。

ngc batch run --name "bignlp-dataprep-create-dataset" \
  --org nv-launchpad-bc \
  --team nvbc-bignlp \
  --ace nv-launchpad-bc-iad1 \
  --instance dgxa100.80g.8.norm \
  --result /results \
  --array-type "PYTORCH" \
  --replicas "2" \
  --image "nvcr.io/nv-launchpad-bc/bignlp-training:22.02-py3" \
  --workspace your_workspace_name:/mount_workspace:RW \
  --total-runtime 6h \
  --commandline "\
set -x && \
python3 /opt/bignlp/bignlp-scripts/main.py \
cluster_type=bcp \
run_data_preparation=True \
run_training=False \
run_conversion=False \
run_evaluation=False \
bignlp_path=/opt/bignlp/bignlp-scripts \
data_dir=/your_data_directory \
base_results_dir=/mount_workspace/results \
data_preparation.file_numbers='0-29' \
data_preparation
.vocab_save_dir=/mount_workspace/data/bpe
data_preparation.merges_save_dir=/mount_workspace/data/bpe"

約5.5時間で完了し、プロセスの進行状況はNGCのウェブUIまたはCLIで確認できる。
ジョブが完了すると、結果は自動的に指定したワークスペースディレクトリに保存される。

LDC(Linguistic Data Consortium)コーパスへのアクセス

LDC会員に登録する場合

会員になると割引や会員限定コーパスへのアクセス権が得られる。

会員の種類

【非営利組織や米国政府機関】
- 標準会員: $2,400
- サブスクリプション会員: $3,850
【営利組織】
- 標準会員: $24,000
- サブスクリプション会員: $27,500

会員登録手順

  1. 会員の種類を選択
  2. 会員費用の支払い
  3. LDCアカウントの作成とログイン

非会員の場合

LDC会員でないユーザーも研究専用ライセンスを通じて利用可能。

  1. LDCカタログの確認
    利用したいデータセットの非会員ライセンス条件と料金をLDCのカタログで確認する。
  2. LDCアカウントの作成とログイン
    データリクエストのためにアカウントを作成しログインする。

支払い方法

クレジットカード: American Express、Discover、Visa、MasterCardが利用可能。
小切手: 米国内の銀行からの小切手をLDCの住所宛てに郵送。
電信送金: Wells Fargo銀行を通じて送金。

LoRAを用いたLLMのFine-tuning手順

LoRAを用いてLLMのFine-tuningを行った際の作業記録

LoRA(Low Rank Adapter)とは既存の大規模モデルの小規模な部分のみを微調整することで、計算コストを削減しつつ特定のタスクの性能を向上させる技術

Fine-tuningの手順

1. スクリプトの準備

LoRAを用いた微調整スクリプト finetune_lora.py を準備し実行。

$ cd <base-dir>/llm
$ python finetune_lora.py --output_dir <base-dir>/llm/<output-dir>

2. 学習データの準備

IMDbデータセット用いてテキスト生成のための学習データを準備する。さらにデータを増強し、モデルの汎用性と精度を高める。

3. モデルの保存

Fine-tuning後のモデルは指定したディレクト<base-dir>/llm/<output-dir>へ保存される。

学習データの増強

様々な質問形式のデータを用意しモデルが柔軟に応答できるようにする。 例)「あなたの名前は何ですか?」という問いに対し、複数の異なる形式で答えるデータを作成

モデルのアップロードとテスト

微調整したモデルをHugging Faceにアップロードし公開。その後実際の会話シナリオでパフォーマンスをテスト。

LLMの推論を高速化する4つの方法

量子化

モデルの精度を維持しつつ計算の複雑さを軽減する手法。特に8ビット量子化はメモリ使用量を大幅に削減し、モデルの推論速度を向上させる。

実装例

from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("your-model-name")
model.int8()  # モデルを8ビット量子化

プルーニング

モデルから重要でない部分を切り取ることでモデルサイズを減らし効率を向上させる。

ステップ

  1. モデルをトレーニングする。
  2. 重要度の低いウェイトを判断し削除する。
  3. 精度の検証を行う。

圧縮

冗長性を排除しストレージの効率化と推論の高速化を実現。
- パラメータの共有
- レイヤー削減
- モデルの微細化

蒸留

大きなモデルから小さなモデルへ知識を移行する技術。これによりモデルサイズの効率化と推論の高速化が実現する。
特にラベル付き問題において、生成されるモデルを小型化しながら性能を維持・向上させることが可能。

実装例

from transformers import DistilBertModel
teacher_model = BertModel.from_pretrained("bert-large-uncased")
student_model = DistilBertModel.from_student(teacher_model)
# 学生モデルのトレーニングを行う

Ubuntuでバックアップサーバーを作る

効率的で堅牢なバックアップサーバーをLinuxで作りたい
Ubuntu 22を搭載した汎用サーバーを使用し、効率的かつ安全なバックアップシステムを構築する

システムの概要

ローカルおよびリモートネットワーク上の複数のサーバーで構成され、主に以下の特徴を持つ。
- 暗号化によるデータ保護
- アクセス権限制御によるデータの改変防止
- RAIDを用いたデータの冗長化
- 定期的なバックアップとデータの整合性チェック

ハードウェア設定

バックアップサーバー

拡張性を考慮して選択。ドライブベイが多く、冗長電源とハードウェアRAIDコントローラを備えたものが理想的。

RAID構成

RAID 6を採用し、2台のドライブが故障してもデータが保護されるようにする。

ネットワーク

アクセスの高速化と冗長性のため、デュアルギガビットまたは10ギガビットイーサネットアダプターを装備。QoS設定を使用し、バックアップトラフィックが本番環境の帯域幅を消費しないようにする。

バックアッププロセス

ファイルシステム

ZFSやBtrfsなど、スナップショットと暗号化をサポートするファイルシステムを使用。

Rsynの利用

SSH経由でrsyncを用いて安全な差分バックアップを実行。bwlimitオプションを用いてバックアップ中の帯域幅を制限する。

スケジューリング

cronジョブを使用して、毎晩午前3時にバックアップを自動的に実行。

スナップショット

各バックアップの後、読み取り専用のスナップショットを作成し、データの改変や削除を防止。

バックアップの保持期間

特定の期間(例: 3ヶ月)保持された後に自動的に削除されるよう設定。

暗号化

静止状態のデータ保護のため、dm-cryptを使ったLUKSによる暗号化を行う。

メールによる報告

バックアップの完了後、そのステータスをメールで自動報告するスクリプトを使用。

整合性チェック

バックアップデータのチェックサムやハッシュを定期的に実行し、以前の値と比較して整合性を確認。

実装例

バックアップスクリプト

dbサーバーに以下のスクリプトを配置することで差分バックアップを行い、その結果をログに記録しメールで通知する。

#!/bin/bash

# Configuration
BACKUP_SERVER="backupuser@backupserver"
BACKUP_PATH="/mnt/backup_drive/db_backups"
DB_DATA_PATH="/path/to/db/data"
LOG_FILE="/var/log/db_backup.log"
BWLIMIT=10000  # Bandwidth limit in KBytes per second

# Function to send email notification
send_email () {
    echo "$1" | mail -s "$2" admin@example.com
}

# Perform differential backup
rsync -avz --bwlimit=$BWLIMIT --delete --delete-excluded \
      --exclude 'excluded_files_pattern' \
      $DB_DATA_PATH $BACKUP_SERVER:$BACKUP_PATH >> $LOG_FILE 2>&1

# Check if rsync was successful
if [ $? -ne 0 ]; then
    send_email "Backup failed. See $LOG_FILE for details." "Backup Failure"
    exit 1
else
    send_email "Backup succeeded." "Backup Success"
fi

# Create an immutable snapshot (Assuming Btrfs)
ssh $BACKUP_SERVER "sudo btrfs subvolume snapshot -r $BACKUP_PATH ${BACKUP_PATH}_$(date +%F)"

# Report integrity check
CHECKSUM_FILE="/tmp/backup_checksums.sha256"
find $DB_DATA_PATH -type f -exec sha256sum {} \; > $CHECKSUM_FILE
scp $CHECKSUM_FILE $BACKUP_SERVER:$BACKUP_PATH
ssh $BACKUP_SERVER "cd $BACKUP_PATH && sha256sum -c $(basename $CHECKSUM_FILE)" >> $LOG_FILE 2>&1

# Send the checksum results
if [ $? -ne 0 ]; then
    send_email "Backup integrity check failed. See $LOG_FILE for details." "Backup Integrity Failure"
else
    send_email "Backup integrity check succeeded." "Backup Integrity Success"
fi

# Cleanup
rm $CHECKSUM_FILE

スクリプトを実行可能にする

sudo chmod +x /usr/local/bin/backup_script.sh

クロンジョブの設定

以下のコマンドで毎晩定刻にバックアップスクリプトを実行。

0 3 * * * /usr/local/bin/backup_script.sh

スナップショット保持スクリプト

バックアップサーバーに以下のスクリプトを配置し、古いスナップショットを定期的に削除。

#!/bin/bash

# Configuration
SNAPSHOT_PATH="/mnt/backup_drive/db_backups"
RETENTION_DAYS=90

# Delete snapshots older than retention period
find $SNAPSHOT_PATH -maxdepth 1 -type d -name "*_snapshot" -mtime +$RETENTION_DAYS -exec rm -rf {} \;

リモートバックアップの設定

リモートネットワークへのバックアップも同様の手順で設定する。VPNまたはSSHトンネルを使用して安全にデータを転送し、帯域幅の制限と暗号化を行う。

検討事項

  1. ハードウェアの選択
    将来的なデータの成長を考慮し十分なストレージ容量を確保する。RAID 6またはRAID 10を推奨。

  2. ネットワーク設定
    バックアップトラフィックが本番環境に影響を与えないようQoS設定を行う。

  3. ドキュメンテーション
    バックアッププロセスとポリシーを文書化し随時更新する。

  4. テストと監視
    バックアップシステムのテストと監視を定期的に行い、予期せぬ障害を防ぐ。

GoサーバーとPythonサーバーの連携でPythonクライアントが切断されてもGoサーバーが落ちないようにする

GoとPythonのサーバーを連携して動作させる際に、クライアントが切断されてもサーバーが停止しないようにする  

問題点

通常、クライアントが切断するとGoサーバーは停止する。これはGoサーバーがWebSocketメッセージの読み取りエラーを検出するとhandleWebSocket関数からreturnしてしまうことに起因する。これによりゴルーチンが終了し、結果としてサーバー全体が停止してしまう。  

Pythonサーバーも同様に接続エラーが発生すると新しい接続の受付を停止する。特にUNIXドメインソケットを使用している場合に顕著。

解決策

Goサーバーの改善

WebSocketの接続エラー時にその接続のみを閉じてサーバー全体が停止するのを防ぐ。handleWebSocket関数内で各クライアント接続に対して独立したゴルーチンを起動する。

func handleWebSocket(w http.ResponseWriter, r *http.Request) {
    // ... 既存のコード ...
    go func() {
        for {
            _, requestData, err := webSocketConn.ReadMessage()
            if err != nil {
                log.Println("Error reading WebSocket message:", err)
                closeConnections(webSocketConn, connRequest)
                return
            }
            // ... リクエスト処理のコード ...
        }
    }()
}

Pythonサーバーの改善

現在の接続でエラーが発生しても新しい接続を継続して受け入れるようにする。

def accept_connections(server):
    while True:
        try:
            connection, client_address = server.accept()
            # ... 接続処理のコード ...
        except Exception as e:
            # エラー処理のコード
            continue

LLMをLoRAで微調整するときのエポック数とデータ量の考察

LLMモデルをLoRAでFinetuningを行った。 エポック数とデータ量を調整し、モデルの応答の正確性や既存知識へ及ぼす影響を探ったメモ。

実験の概要

  • エポック数: 1から4まで変化させ、応答の品質を比較。
  • データ量: 224データセットから549データセットまで徐々に増やし、応答の品質を比較。

目的

  • AIモデルの学習における最適なデータ量とエポック数を調べる。
  • 学習データとエポック数の増加が既存の知識に及ぼす影響を分析。

結果

エポック数

  • 2エポック: 学習はほぼ行われず、応答品質が低い。
  • 3エポック: 応答が不安定になるが、既存知識への影響は限定的。
  • 4エポック: 学習された内容は正確だが、既存知識に干渉し誤った情報(例:アラン・チューリングが2015年に亡くなったとする情報)を生成。

データ量

  • データ量の増加: 224から549に増えるにつれ、応答の正確性が向上。しかし、一部の応答で既存知識と矛盾する情報が出現。
  • 特定のデータセット:特定のデータセット(例:341データセット)では、CUDA OUT OF MEMORY ERRORなどの技術的な問題が発生し、学習プロセスに影響。

結論

データ量とエポック数を最適化することでAIの応答品質と学習効率が高まる。
ただし過剰なデータ量やエポック数は既存の知識に悪影響を与えることがあるため、慎重に調整しなければならない。

実践的なアプローチ

  • 数量だけでなくデータの質にも注目する。多様なケースをカバーするためには幅広い種類のデータが必要。
  • 初期段階で少ないデータ量とエポック数で学習を始め、徐々にこれらを増やしていくことで、モデルの応答品質と既存知識のバランスを見極める。