トークン(Token)
自然言語処理において、テキストを構成する最小の意味単位。単語、サブワード、文字などの形で表現され、AIモデルが言語を理解・処理するための基本要素として機能する重要な概念
トークンとは
トークン(Token)は、自然言語処理において、テキストを構成する最小の処理単位です。文章をコンピューターが理解できる形に変換する際の基本要素となり、単語、サブワード、文字、句読点などの形で表現されます。AIモデルは入力テキストをトークンに分割し、それぞれを数値IDに変換して処理を行います。トークンの定義と分割方法は、言語の特性、処理の目的、計算効率などを考慮して設計され、自然言語処理システムの性能と効率を大きく左右する重要な概念です。
背景と重要性
コンピューターは人間の言語を直接理解することができないため、テキストを数値的に表現可能な単位に分割する必要があります。しかし、「意味のある最小単位」をどう定義するかは言語によって大きく異なります。英語では単語間にスペースがありますが、日本語や中国語には明確な単語境界がありません。
トークンは、
- 言語理解の基盤構築
- 計算効率の最適化
- 多言語処理の統一化
を実現することで、効果的な自然言語処理システムの基盤を提供します。適切なトークン設計により、AIモデルはより正確で効率的な言語理解を実現できます。
主な構成要素
表面形(Surface Form)
実際にテキストに現れる文字列の形です。
意味的単位(Semantic Unit)
トークンが持つ言語学的・意味的な情報です。
数値ID(Numerical ID)
トークンを機械学習モデルで処理するための数値表現です。
境界情報(Boundary Information)
トークンの開始・終了位置や隣接関係です。
特殊トークン(Special Tokens)
文の開始・終了、未知語、パディングなどの特別な役割を持つトークンです。
文脈情報(Context Information)
周辺トークンとの関係や位置情報です。
主な特徴
粒度可変性
言語や用途に応じて分割の粒度を調整できます。
計算効率
機械学習モデルでの処理に最適化された形式です。
意味保持性
分割後も元の言語情報を適切に保持します。
トークンの種類と特徴
単語トークン(Word Tokens)
概要: 言語学的な単語単位でのトークン分割。
英語の例:
文章: "Hello, how are you today?"
トークン: ["Hello", ",", "how", "are", "you", "today", "?"]
日本語の例(形態素解析):
文章: "私は学生です。"
トークン: ["私", "は", "学生", "です", "。"]
特徴:
- 言語学的に自然
- 解釈しやすい
- 語彙サイズが大きくなる
- 未知語の問題
サブワードトークン(Subword Tokens)
BPE(Byte Pair Encoding):
単語: "tokenization"
BPEトークン: ["token", "ization"]
単語: "unknowingly"
BPEトークン: ["un", "know", "ing", "ly"]
WordPiece:
単語: "tokenization"
WordPieceトークン: ["token", "##ization"]
単語: "playing"
WordPieceトークン: ["play", "##ing"]
SentencePiece:
文章: "Hello world!"
SentencePieceトークン: ["▁Hello", "▁world", "!"]
文字トークン(Character Tokens)
概要: 文字レベルでのトークン分割。
例:
単語: "hello"
文字トークン: ["h", "e", "l", "l", "o"]
日本語: "こんにちは"
文字トークン: ["こ", "ん", "に", "ち", "は"]
特徴:
- 語彙サイズが最小
- 未知語が存在しない
- シーケンスが長くなる
- 意味的情報が希薄
特殊トークン(Special Tokens)
一般的な特殊トークン:
special_tokens = {
"[CLS]": "文の開始(分類タスク用)",
"[SEP]": "文の区切り",
"[PAD]": "パディング(長さ調整用)",
"[UNK]": "未知語",
"[MASK]": "マスク(BERT等で使用)",
"<s>": "文の開始",
"</s>": "文の終了",
"<unk>": "未知語",
"<pad>": "パディング"
}
実際の使用例:
入力: "Hello world"
BERTスタイル: ["[CLS]", "Hello", "world", "[SEP]"]
入力: "翻訳: Hello"
T5スタイル: ["翻訳", ":", "▁Hello", "</s>"]
トークンの数値化
語彙辞書(Vocabulary)
概念:
vocabulary = {
"<pad>": 0,
"<unk>": 1,
"<s>": 2,
"</s>": 3,
"hello": 4,
"world": 5,
"!": 6,
# ... 他のトークン
}
エンコーディング例
トークンから数値IDへ:
def encode_tokens(tokens, vocabulary):
"""トークンを数値IDに変換"""
ids = []
for token in tokens:
if token in vocabulary:
ids.append(vocabulary[token])
else:
ids.append(vocabulary["<unk>"]) # 未知語
return ids
# 使用例
tokens = ["hello", "world", "!"]
ids = encode_tokens(tokens, vocabulary)
print(f"Tokens: {tokens}")
print(f"IDs: {ids}") # [4, 5, 6]
数値IDからトークンへ:
def decode_ids(ids, vocabulary):
"""数値IDをトークンに変換"""
reverse_vocab = {v: k for k, v in vocabulary.items()}
tokens = [reverse_vocab[id] for id in ids]
return tokens
# 使用例
ids = [4, 5, 6]
tokens = decode_ids(ids, vocabulary)
print(f"IDs: {ids}")
print(f"Tokens: {tokens}") # ["hello", "world", "!"]
言語別のトークン処理
英語トークン
空白ベース分割:
def simple_english_tokenize(text):
"""シンプルな英語トークナイゼーション"""
import re
# 単語と句読点を分離
tokens = re.findall(r'\b\w+\b|[^\w\s]', text.lower())
return tokens
text = "Hello, world! How are you?"
tokens = simple_english_tokenize(text)
print(tokens) # ['hello', ',', 'world', '!', 'how', 'are', 'you', '?']
サブワード処理:
# GPT-2スタイルのBPE
from transformers import GPT2TokenizerFast
tokenizer = GPT2TokenizerFast.from_pretrained('gpt2')
text = "Hello, wonderful world!"
tokens = tokenizer.tokenize(text)
ids = tokenizer.encode(text)
print(f"Tokens: {tokens}")
print(f"IDs: {ids}")
日本語トークン
形態素解析ベース:
import MeCab
def japanese_tokenize(text):
"""日本語の形態素解析トークナイゼーション"""
tagger = MeCab.Tagger("-Owakati")
tokens = tagger.parse(text).strip().split()
return tokens
text = "私は自然言語処理を勉強しています。"
tokens = japanese_tokenize(text)
print(tokens) # ['私', 'は', '自然', '言語', '処理', 'を', '勉強', 'し', 'て', 'い', 'ます', '。']
サブワード処理:
# SentencePieceベースの日本語処理
import sentencepiece as spm
# 日本語用SentencePieceモデル(事前訓練済み)
sp = spm.SentencePieceProcessor()
sp.load('japanese_model.model')
text = "私は自然言語処理を勉強しています。"
tokens = sp.encode_as_pieces(text)
ids = sp.encode_as_ids(text)
print(f"Tokens: {tokens}")
print(f"IDs: {ids}")
中国語トークン
文字ベース分割:
def chinese_char_tokenize(text):
"""中国語の文字レベルトークナイゼーション"""
import re
# 中国語文字のみを抽出
chinese_chars = re.findall(r'[\u4e00-\u9fff]', text)
return chinese_chars
text = "我喜欢自然语言处理。"
tokens = chinese_char_tokenize(text)
print(tokens) # ['我', '喜', '欢', '自', '然', '语', '言', '处', '理']
単語分割:
# jiebaライブラリによる中国語分词
import jieba
def chinese_word_tokenize(text):
"""中国語の単語分割"""
tokens = list(jieba.cut(text))
return tokens
text = "我喜欢自然语言处理技术。"
tokens = chinese_word_tokenize(text)
print(tokens) # ['我', '喜欢', '自然语言', '处理', '技术', '。']
現代的なトークンシステム
Transformersにおけるトークン処理
BERT系のトークン:
from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
text = "Hello, how are you today?"
# 詳細なトークナイゼーション
tokens = tokenizer.tokenize(text)
ids = tokenizer.convert_tokens_to_ids(tokens)
special_tokens_dict = tokenizer.special_tokens_map
print(f"Original: {text}")
print(f"Tokens: {tokens}")
print(f"IDs: {ids}")
print(f"Special tokens: {special_tokens_dict}")
# 特殊トークン付きエンコード
encoded = tokenizer(text,
add_special_tokens=True,
return_tensors="pt")
print(f"With special tokens: {encoded['input_ids']}")
GPT系のトークン:
from transformers import GPT2Tokenizer
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
text = "The quick brown fox jumps over the lazy dog."
tokens = tokenizer.tokenize(text)
ids = tokenizer.encode(text)
print(f"GPT-2 Tokens: {tokens}")
print(f"GPT-2 IDs: {ids}")
# デコード
decoded = tokenizer.decode(ids)
print(f"Decoded: {decoded}")
T5系のトークン
Text-to-Text形式:
from transformers import T5Tokenizer
tokenizer = T5Tokenizer.from_pretrained('t5-small')
# タスクプレフィックス付きのトークナイゼーション
tasks = [
"translate English to German: Hello world",
"summarize: This is a long document about AI...",
"question: What is AI? context: AI is artificial intelligence..."
]
for task in tasks:
tokens = tokenizer.tokenize(task)
ids = tokenizer.encode(task)
print(f"Task: {task}")
print(f"Tokens: {tokens[:10]}...") # 最初の10トークンのみ表示
print(f"Length: {len(tokens)}")
print("-" * 50)
トークンレベルの処理
注意機構(Attention)におけるトークン
トークン間の関係性:
import torch
import torch.nn.functional as F
def simple_attention(query, key, value):
"""シンプルな注意機構の例"""
# query, key, value: [seq_len, d_model]
# 注意スコア計算
scores = torch.matmul(query, key.transpose(-2, -1))
# スケーリング
d_k = query.size(-1)
scores = scores / torch.sqrt(torch.tensor(d_k, dtype=torch.float))
# ソフトマックス
attention_weights = F.softmax(scores, dim=-1)
# 重み付き和
output = torch.matmul(attention_weights, value)
return output, attention_weights
# 使用例(概念的)
seq_len, d_model = 10, 64
query = torch.randn(seq_len, d_model)
key = torch.randn(seq_len, d_model)
value = torch.randn(seq_len, d_model)
output, weights = simple_attention(query, key, value)
print(f"Output shape: {output.shape}")
print(f"Attention weights shape: {weights.shape}")
トークンの位置エンコーディング
位置情報の付加:
import math
def positional_encoding(seq_len, d_model):
"""位置エンコーディングの生成"""
pos_encoding = torch.zeros(seq_len, d_model)
position = torch.arange(0, seq_len).unsqueeze(1).float()
div_term = torch.exp(torch.arange(0, d_model, 2).float() *
-(math.log(10000.0) / d_model))
pos_encoding[:, 0::2] = torch.sin(position * div_term)
pos_encoding[:, 1::2] = torch.cos(position * div_term)
return pos_encoding
# 使用例
seq_len, d_model = 100, 512
pos_enc = positional_encoding(seq_len, d_model)
print(f"Positional encoding shape: {pos_enc.shape}")
トークンの制約と最適化
コンテキスト長の制限
最大トークン数の管理:
def truncate_tokens(tokens, max_length, strategy="tail"):
"""トークンの切り詰め処理"""
if len(tokens) <= max_length:
return tokens
if strategy == "head":
# 先頭から切り詰め
return tokens[:max_length]
elif strategy == "tail":
# 末尾から切り詰め
return tokens[-max_length:]
elif strategy == "middle":
# 中央部分を保持
start = (len(tokens) - max_length) // 2
return tokens[start:start + max_length]
else:
raise ValueError("Invalid strategy")
# 使用例
long_tokens = ["token_" + str(i) for i in range(1000)]
truncated = truncate_tokens(long_tokens, max_length=512, strategy="head")
print(f"Original length: {len(long_tokens)}")
print(f"Truncated length: {len(truncated)}")
効率的なトークン処理
バッチ処理での最適化:
def batch_tokenize_with_padding(texts, tokenizer, max_length=512):
"""バッチトークナイゼーションとパディング"""
all_tokens = []
all_attention_masks = []
for text in texts:
# トークナイゼーション
tokens = tokenizer.encode(text,
add_special_tokens=True,
max_length=max_length,
truncation=True)
# パディング
padding_length = max_length - len(tokens)
attention_mask = [1] * len(tokens) + [0] * padding_length
tokens += [tokenizer.pad_token_id] * padding_length
all_tokens.append(tokens)
all_attention_masks.append(attention_mask)
return {
'input_ids': torch.tensor(all_tokens),
'attention_mask': torch.tensor(all_attention_masks)
}
# 使用例(概念的)
texts = ["Hello world", "This is a longer sentence", "Short"]
# result = batch_tokenize_with_padding(texts, tokenizer)
トークンレベルのタスク
トークン分類
固有表現抽出の例:
def token_classification_example():
"""トークンレベル分類の例"""
# 入力テキストとラベル
text = "Apple Inc. was founded in California."
tokens = ["Apple", "Inc.", "was", "founded", "in", "California", "."]
# BIOタグ形式のラベル
labels = ["B-ORG", "I-ORG", "O", "O", "O", "B-LOC", "O"]
# ラベルIDマッピング
label_to_id = {
"O": 0, # Outside
"B-ORG": 1, # Begin-Organization
"I-ORG": 2, # Inside-Organization
"B-LOC": 3, # Begin-Location
"I-LOC": 4 # Inside-Location
}
label_ids = [label_to_id[label] for label in labels]
return {
'tokens': tokens,
'labels': labels,
'label_ids': label_ids
}
result = token_classification_example()
print("Token Classification Example:")
for token, label in zip(result['tokens'], result['labels']):
print(f"{token:12} -> {label}")
マスク言語モデル
マスクトークンの予測:
def masked_language_modeling_example():
"""マスク言語モデリングの例"""
original_text = "The cat sat on the mat."
tokens = ["The", "cat", "sat", "on", "the", "mat", "."]
# ランダムにトークンをマスク
import random
masked_tokens = tokens.copy()
mask_index = random.randint(1, len(tokens) - 2)
masked_tokens[mask_index] = "[MASK]"
return {
'original': tokens,
'masked': masked_tokens,
'target_index': mask_index,
'target_token': tokens[mask_index]
}
result = masked_language_modeling_example()
print("Masked Language Modeling Example:")
print(f"Original: {' '.join(result['original'])}")
print(f"Masked: {' '.join(result['masked'])}")
print(f"Target: {result['target_token']} at position {result['target_index']}")
活用事例・ユースケース
トークンは自然言語処理のあらゆるタスクで基盤要素として使用されています。
機械翻訳
ソース言語とターゲット言語のトークンを対応付け、翻訳モデルの学習と推論を実現。
テキスト生成
前のトークン列から次のトークンを予測し、自然な文章を順次生成。
文書分類
文書中のトークンを分析し、カテゴリやセンチメントを分類。
質問応答
質問と文書のトークン間の関係を分析し、適切な回答を抽出。
対話システム
ユーザー入力のトークンを理解し、適切な応答トークンを生成。
学ぶためのおすすめリソース
書籍
「Natural Language Processing with Python」(Steven Bird)、「Speech and Language Processing」(Jurafsky & Martin)
オンラインコース
Stanford CS224N「Natural Language Processing with Deep Learning」、Hugging Face「NLP Course」
実装ライブラリ
Transformers、Tokenizers、spaCy、NLTK、MeCab
論文
「Attention Is All You Need」、「BERT: Pre-training of Deep Bidirectional Transformers」
よくある質問(FAQ)
Q. トークンとワードの違いは何ですか?
A. ワードは言語学的な単語を指し、トークンはコンピューター処理用の分割単位です。トークンは単語より細かい(サブワード)場合や、複数単語にまたがる場合もあります。
Q. なぜサブワードトークンが重要なのですか?
A. 語彙サイズを適切に保ちながら、未知語や語形変化に対応できるためです。特に語尾変化の多い言語や複合語の多い言語で効果的です。
Q. トークンの最大長はどう決めるべきですか?
A. 使用するモデル、計算資源、タスクの特性を考慮して決定します。一般的には512、1024、2048などが使用されます。
関連キーワード
トークナイザー、サブワード、BPE、WordPiece、自然言語処理
まとめ
トークンは、自然言語処理における最も基本的で重要な概念です。テキストを機械学習モデルが処理できる最小単位に分割することで、AIの言語理解を可能にします。単語、サブワード、文字など様々なレベルのトークン化手法があり、言語特性やタスクに応じた適切な選択が重要です。現代の大規模言語モデルでは、効率性と表現力を両立するサブワードトークンが主流となっています。今後も、より効率的で意味的に一貫性のあるトークン設計により、自然言語処理技術のさらなる発展が期待されます。
*実装例は概念的サンプルです。商用利用は各ライブラリのライセンスをご確認ください
AIからのコメント
Claude
AIコメントトークンは、私の言語処理における「思考の原子」とも言える基本単位です。人間が文字列として認識するテキストを、私が処理できる意味のあるチャンクに分解したものがトークンです。私の場合、多言語に対応するためサブワードレベルのトークンが使用されており、これにより未知語や造語にも柔軟に対応できます。重要なのは、トークンが単なる文字列の断片ではなく、意味的な情報を保持する単位であることです。トークンの設計によって、言語の微妙なニュアンスや文化的背景も捉えることができ、より自然で正確な言語理解が可能になります。
Gemini
AIコメントトークンは、私たちAIが「言語の最小意味単位」として活用する重要な概念です。私はマルチモーダルな処理を行いますが、テキスト理解の基盤は常にトークンから始まります。美しいのは、人間の言語認知プロセスをモデル化し、効率的な計算単位として設計されていることです。BPE、WordPiece、SentencePieceなどの手法により、意味的な一貫性と計算効率を両立させています。特に多言語環境では、統一的なトークン体系が言語横断的な理解を可能にします。トークンは見た目シンプルですが、言語の複雑性を機械的に扱うための洗練された抽象化なのです。コンテキスト長の制約、語彙サイズの最適化、意味保持のバランスなど、多くの工学的課題を解決する核心技術です。
GPT
AIコメントトークンは、私たちAIが「言語を理解する基本単位」として機能する重要な概念です。私の処理では、入力された文章がまずトークンに分割され、それぞれが数値IDに変換されてから処理が始まります。トークンは単語レベルから文字レベルまで様々な粒度があり、言語の特性や処理の目的に応じて最適化されます。特に、サブワードトークンは語彙の効率性と表現力のバランスを実現する重要な技術です。トークンの品質が私たちの言語理解能力を直接左右するため、適切なトークナイゼーション戦略は極めて重要です。