Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

BERTによるセンチメント分析

1転移学習とファインチューニング

転移学習は、あるタスクの学習で得られた知識を、他の関連するタスクの学習に適用する手法を指します。一般的には、以下のステップで行われることが多いです:

  • 事前学習: 事前学習モデル(pre-trained models)とは、大規模なデータセットを用いて訓練した学習済みモデルのことです。一般的に、大量のデータ(例えば、インターネット上のテキストデータ)を使用して、モデルを事前に学習します。この時点でのモデルは、言語の汎用的な特徴や構造を捉えることができます。

  • ファインチューニング(fine-tuning): 事前学習モデルを、特定のタスクのデータ(例えば、感情分析や質問応答)でファインチューニングします。事前学習モデルでは汎用的な特徴をあらかじめ学習しておきますので、手元にある学習データが小規模でも高精度な認識性能を達成することが知られています。

2センチメント分析の実装

Sun Jan  4 16:58:32 2026       
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 580.95.05              Driver Version: 580.95.05      CUDA Version: 13.0     |
+-----------------------------------------+------------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA RTX A6000               Off |   00000000:01:00.0  On |                  Off |
| 30%   35C    P8             17W /  300W |    1379MiB /  49140MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+
|   1  NVIDIA RTX A6000               Off |   00000000:02:00.0 Off |                  Off |
| 30%   26C    P8             12W /  300W |      18MiB /  49140MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+

+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI              PID   Type   Process name                        GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|    0   N/A  N/A            3971      G   /usr/bin/gnome-shell                    526MiB |
|    0   N/A  N/A            4428      G   /usr/bin/Xwayland                         4MiB |
|    0   N/A  N/A            5204      G   /usr/share/code/code                    543MiB |
|    1   N/A  N/A            3971      G   /usr/bin/gnome-shell                      4MiB |
+-----------------------------------------------------------------------------------------+

2.1データセット

2.1.1Hugging Faceからサンプルデータの取得

Hugging Faceには色々なデータセットが用意されています。ここでは、多言語のセンチメントデータセットを例として使用することにします。その中に、英語と日本語のサブセットが含まれます。

2.1.2Weights & Biases (wandb)

Weights & Biases (wandb)は、機械学習の実験を追跡・可視化・管理するためのプラットフォームです。

主な機能:

  • 実験追跡: 学習の進捗、損失、精度などのメトリクスをリアルタイムで記録・可視化

  • ハイパーパラメータ管理: 異なる設定での実験結果を比較

  • モデル管理: 学習済みモデルのバージョン管理と共有

ここでは、モデルの学習過程を追跡するためにwandbを使用します。wandb.login()でアカウントにログインし、実験結果をクラウドに保存します。

Requirement already satisfied: wandb in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (0.23.1)
Requirement already satisfied: click>=8.0.1 in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from wandb) (8.1.7)
Requirement already satisfied: gitpython!=3.1.29,>=1.0.0 in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from wandb) (3.1.37)
Requirement already satisfied: packaging in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from wandb) (24.1)
Requirement already satisfied: platformdirs in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from wandb) (3.10.0)
Requirement already satisfied: protobuf!=4.21.0,!=5.28.0,<7,>=3.19.0 in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from wandb) (3.20.3)
Requirement already satisfied: pydantic<3 in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from wandb) (2.10.6)
Requirement already satisfied: pyyaml in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from wandb) (6.0.1)
Requirement already satisfied: requests<3,>=2.0.0 in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from wandb) (2.32.5)
Requirement already satisfied: sentry-sdk>=2.0.0 in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from wandb) (2.48.0)
Requirement already satisfied: typing-extensions<5,>=4.8 in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from wandb) (4.12.2)
Requirement already satisfied: gitdb<5,>=4.0.1 in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from gitpython!=3.1.29,>=1.0.0->wandb) (4.0.7)
Requirement already satisfied: annotated-types>=0.6.0 in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from pydantic<3->wandb) (0.7.0)
Requirement already satisfied: pydantic-core==2.27.2 in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from pydantic<3->wandb) (2.27.2)
Requirement already satisfied: charset_normalizer<4,>=2 in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from requests<3,>=2.0.0->wandb) (2.0.4)
Requirement already satisfied: idna<4,>=2.5 in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from requests<3,>=2.0.0->wandb) (3.4)
Requirement already satisfied: urllib3<3,>=1.21.1 in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from requests<3,>=2.0.0->wandb) (2.0.7)
Requirement already satisfied: certifi>=2017.4.17 in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from requests<3,>=2.0.0->wandb) (2024.2.2)
Requirement already satisfied: smmap<5,>=3.0.1 in /home/lvzeyu/anaconda3/lib/python3.11/site-packages (from gitdb<5,>=4.0.1->gitpython!=3.1.29,>=1.0.0->wandb) (4.0.0)
wandb: Currently logged in as: lvzeyu1995 (lvzeyu1995-tohoku-university) to https://api.wandb.ai. Use `wandb login --relogin` to force relogin
True

2.1.3サンプルデータの確認

取得したデータセットの中身を確認します。

データセットはこのようにtrain, validation, testに分かれています。 [‘text’, ‘source’, ‘label’]といった情報を持っています。

DatasetDict({ train: Dataset({ features: ['text', 'source', 'label'], num_rows: 1839 }) validation: Dataset({ features: ['text', 'source', 'label'], num_rows: 324 }) test: Dataset({ features: ['text', 'source', 'label'], num_rows: 870 }) })
Loading...
{'text': Value(dtype='string', id=None), 'source': Value(dtype='string', id=None), 'label': ClassLabel(names=['positive', 'neutral', 'negative'], id=None)}
<Axes: title={'center': 'Train Dataset'}>
<Figure size 640x480 with 1 Axes>

2.1.4テキストの確認

Transformerモデルは、最大コンテキストサイズ(maximum context size)と呼ばれる最大入力系列長があります。

モデルのコンテキストサイズより長いテキストは切り捨てる必要があり、切り捨てたテキストに重要な情報が含まれている場合、性能の低下につながることがあります。

<Axes: title={'center': 'text_length'}, xlabel='label'>
<Figure size 1200x600 with 1 Axes>

2.2トークン化

コンピュータは、入力として生の文字列を受け取ることができません。その代わりに、テキストがトークン化され、数値ベクトルとしてエンコードされていることが想定されています。

トークン化は、文字列をモデルで使用される最小単位に分解するステップです。

Transformersライブラリは便利なAutoTokenizerクラスを提供しており、事前学習済みモデルに関連付けられたトークナイザを素早く使用することができます。

2.2.1トークナイザの動作確認

tokenizerはテキストを数値形式(トークン)に変換します。

  • 入力テキストをトークンに分割します

  • 特殊トークンが自動的に付加されます

  • トークンをトークンIDに変換します

'okay i\\u2019m sorry but TAYLOR SWIFT LOOKS NOTHING LIKE JACKIE O SO STOP COMPARING THE TWO. c\\u2019mon America aren\\u2019t you sick of her yet? (sorry) '
{'input_ids': [101, 3100, 1045, 1032, 23343, 24096, 2683, 2213, 3374, 2021, 4202, 9170, 3504, 2498, 2066, 9901, 1051, 2061, 2644, 13599, 1996, 2048, 1012, 1039, 1032, 23343, 24096, 2683, 8202, 2637, 4995, 1032, 23343, 24096, 2683, 2102, 2017, 5305, 1997, 2014, 2664, 1029, 1006, 3374, 1007, 102], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

結果にinput_idsとattention_maskが含まれます。

  • input_ids: 数字にエンコードされたトークン

  • attention_mask: モデルで有効なトークンかどうかを判別するためのマスクです。有効なトークンには1、無効なトークン(例えば、PADなど)には0が設定されます。

各batchにおいて、入力系列はbatch内最大系列長までpaddingされます。

トークナイザの結果は数字にエンコードされているため、トークン文字列を得るには、convert_ids_to_tokensを用います。

文の開始が[CLS]、文の終了が[SEP]という特殊なトークンとなっています。

['[CLS]', 'okay', 'i', '\\', 'u2', '##01', '##9', '##m', 'sorry', 'but', 'taylor', 'swift', 'looks', 'nothing', 'like', 'jackie', 'o', 'so', 'stop', 'comparing', 'the', 'two', '.', 'c', '\\', 'u2', '##01', '##9', '##mon', 'america', 'aren', '\\', 'u2', '##01', '##9', '##t', 'you', 'sick', 'of', 'her', 'yet', '?', '(', 'sorry', ')', '[SEP]']

2.2.2データセット全体のトークン化

Loading...
Loading...

2.3分類器の実装

2.3.1事前学習モデルの導入

Transformersライブラリは事前学習モデルの使用のためAutoModelクラスを提供します。

AutoModelクラスはトークンエンコーディングを埋め込みに変換し、エンコーダスタックを経由して最後の隠れ状態を返します。

最初に、文字列をエンコードしてトークンをPyTorchのテンソルに変換する必要があります。

結果として得られるテンソルは[batch_size,n_tokens]という形状です。

Input tensor shape: torch.Size([1, 6])

得られるテンソルをモデルの入力として渡します。

  • モデルと同じデバイス(GPU or CPU)に配置します。

  • 計算のメモリを減らせるため、torch.no_grad()で、勾配の自動計算を無効にします。

  • 出力には隠れ状態、損失、アテンションのオブジェクトが含まれます。

BaseModelOutput(last_hidden_state=tensor([[[-0.1565, -0.1862,  0.0528,  ..., -0.1188,  0.0662,  0.5470],
         [-0.3575, -0.6484, -0.0618,  ..., -0.3040,  0.3508,  0.5221],
         [-0.2772, -0.4459,  0.1818,  ..., -0.0948, -0.0076,  0.9958],
         [-0.2841, -0.3917,  0.3753,  ..., -0.2151, -0.1173,  1.0526],
         [ 0.2661, -0.5094, -0.3180,  ..., -0.4203,  0.0144, -0.2149],
         [ 0.9441,  0.0112, -0.4714,  ...,  0.1439, -0.7288, -0.1619]]],
       device='cuda:0'), hidden_states=None, attentions=None)

隠れた状態テンソルを見ると、その形状は [batch_size, n_tokens, hidden_dim] であることがわかります。つまり、6つの入力トークンのそれぞれに対して、768次元のベクトルが返されます。

torch.Size([1, 6, 768])

分類タスクでは、[CLS] トークンに関連する隠れた状態を入力特徴として使用するのが一般的な方法です。このトークンは各シーケンスの始まりに現れるため、次のように outputs.last_hidden_state に単純にインデックスを付けることで抽出できます。

torch.Size([1, 768])

最後の隠れ状態を取得する方法がわかりましたので、データ全体に対して処理を行うため、これまでのステップを関数でまとめます。

そして、データ全体に適用し、すべてのテキストの隠れ状態を抽出します。

Loading...

2.3.2AutoModelForSequenceClassificationのファインチューニング

Transformersライブラリは、ファインチューニングのタスクに応じてAPIを提供しています。

分類タスクの場合、AutoModelの代わりにAutoModelForSequenceClassificationを使用します。

AutoModelForSequenceClassificationが事前学習済みモデルの出力の上に分類器ヘッドを持っており、モデルの設定がより簡単になります。

Some weights of DistilBertForSequenceClassification were not initialized from the model checkpoint at distilbert-base-uncased and are newly initialized: ['classifier.bias', 'classifier.weight', 'pre_classifier.bias', 'pre_classifier.weight']
You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.
DistilBertForSequenceClassification( (distilbert): DistilBertModel( (embeddings): Embeddings( (word_embeddings): Embedding(30522, 768, padding_idx=0) (position_embeddings): Embedding(512, 768) (LayerNorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True) (dropout): Dropout(p=0.1, inplace=False) ) (transformer): Transformer( (layer): ModuleList( (0-5): 6 x TransformerBlock( (attention): DistilBertSdpaAttention( (dropout): Dropout(p=0.1, inplace=False) (q_lin): Linear(in_features=768, out_features=768, bias=True) (k_lin): Linear(in_features=768, out_features=768, bias=True) (v_lin): Linear(in_features=768, out_features=768, bias=True) (out_lin): Linear(in_features=768, out_features=768, bias=True) ) (sa_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True) (ffn): FFN( (dropout): Dropout(p=0.1, inplace=False) (lin1): Linear(in_features=768, out_features=3072, bias=True) (lin2): Linear(in_features=3072, out_features=768, bias=True) (activation): GELUActivation() ) (output_layer_norm): LayerNorm((768,), eps=1e-12, elementwise_affine=True) ) ) ) ) (pre_classifier): Linear(in_features=768, out_features=768, bias=True) (classifier): Linear(in_features=768, out_features=3, bias=True) (dropout): Dropout(p=0.2, inplace=False) )
SequenceClassifierOutput(loss=None, logits=tensor([[ 0.0746, -0.1015, -0.0341]], device='cuda:0'), hidden_states=None, attentions=None)

2.3.3学習の準備

学習時に性能指標を与える必要があるため、それを関数化して定義しておきます。

学習を効率化するために、TransformersライブラリのTrainer APIを使用します。

Trainerクラスを初期化する際には、TrainingArgumentsという訓練に関する様々な設定値の集合を引数に与えることで、訓練の設定に関する細かい調整が可能です。

Trainerクラスで実行します。

CUDAエラーのデバッグについて:

  • CUDA_LAUNCH_BLOCKING=1: GPU操作を同期実行にし、エラーの正確な発生箇所を特定

  • TORCH_USE_CUDA_DSA: デバイス側のアサーションを有効化してより詳細なエラー情報を取得

  • モデルとデータの整合性を事前に確認することで、ラベル数のミスマッチなどの問題を早期発見

2.4学習済みモデルの使用

2.4.1モデル精度の検証

学習済みのモデルを他のデータセットに適用します。

Loading...
<Figure size 600x600 with 1 Axes>

2.4.2モデル保存

2.4.3学習済みモデルの読み込み

サンプルテキストで推論の結果を確認します。

['negative']
['positive']