🤖

【風吹けば名無し】GPT-4o が獲得した日本語の語彙を調べる

2024/05/14に公開3

昨日公開された GPT-4o は性能だけでなく処理速度の点からも注目を集めています。その速度に寄与しているのは、モデルの処理速度の改善だけでなく、日本語処理の改善も大きく関わっていると考えられます。

実際、OpenAIのサイトによれば、日本語は平均して 1.4 倍の効率で(1.4倍少ないトークンで)表せるようになったとされています。

これは、GPT-4o が GPT-4 に比べて日本語をより 語彙 (vocabulary) に含むようになったからです。語彙とは LLM における自然言語の処理の最小単位で、1つの語彙が1つの数値トークンに変換され、それがモデルに突っ込まれるという仕組みです。


ところで、GPT-4o では 『風吹けば名無し』 という文字列を 1 つの語彙として扱うのをご存知でしょうか。
このツイートで紹介されているように、GPT-4o では、ネットで多数出現するこういったフレーズがどうやら語彙に含まれているようです。

人間の感覚では、「風吹けば名無し」は「風」「吹けば」「名無し」くらいには分解されると思うのですが、GPT-4o にとっては1つの入力、1トークンと感じるようですね。
本記事では、このように、ちょっと人間の感覚とは違う GPT-4o の語彙について見ていこうと思います。

tiktoken

GPT-4 や GPT-4o のモデルの重みは公開されていませんが、トークナイザは tiktoken というライブラリとして包括的に公開されています。

https://github.com/openai/tiktoken

その中でも、GPT-3.5 と GPT-4 のトークナイザは cl100k_base というコードネームが付けられていましたが、GPT-4o のトークナイザは o200k_base という新しいコードネームのものになりました。

私は昨年 GPT-4 が公開された後、tiktoken のリポジトリを少し眺め、語彙一覧を簡単に解析できることに気づきました。そして、語彙リストを出力したテキストファイルを以下のリポジトリに置いていました。
そして今日、GPT-4o のトークナイザが新しいものになっているのに気づき、リポジトリを更新しました。

https://github.com/kaisugi/gpt4_vocab_list

解析といっても、実際は大したことはやっておらず、以下のコードを実行すれば GPT-4o のトークナイザである o200k_base の語彙一覧を出力することができます(どうしてこれで上手くいくかは読者の宿題にしておきます)。

import base64
import requests

# cl100k_base の場合は https://openaipublic.blob.core.windows.net/encodings/cl100k_base.tiktoken
res = requests.get("https://openaipublic.blob.core.windows.net/encodings/o200k_base.tiktoken")
contents = res.content

for token, rank in (line.split() for line in contents.splitlines() if line):
    decoded_token = base64.b64decode(token)

    try:
        print(repr(decoded_token.decode('utf-8')))
    except:
        print(decoded_token)

GPT-4o はどのような日本語トークンを新たに獲得しているのか

これを活用して、GPT-4o に新たに追加された日本語トークンを調べることもできます。例えば

  • トークンの中にひらがなまたはカタカナが1文字でも含まれている場合
  • トークンが常用漢字でのみ構成されている場合

のみを列挙すれば、ある程度日本語っぽいものは得られます(もちろん、中国語の語彙も混ざってしまうので、実際にはこれだけでは難しいです)

以下のようなコードで、GPT-4o に追加された日本語っぽいトークンっぽいトークンのうち、長さが4以上のものを列挙してみました。

import base64
import re
import requests

cl100k_base_tokens_utf8 = []

res = requests.get("https://openaipublic.blob.core.windows.net/encodings/cl100k_base.tiktoken")
contents = res.content

for token, rank in (line.split() for line in contents.splitlines() if line):
    decoded_token = base64.b64decode(token)

    try:
        cl100k_base_tokens_utf8.append(decoded_token.decode('utf-8'))
    except:
        pass

o200k_base_tokens_utf8 = []

res = requests.get("https://openaipublic.blob.core.windows.net/encodings/o200k_base.tiktoken")
contents = res.content

for token, rank in (line.split() for line in contents.splitlines() if line):
    decoded_token = base64.b64decode(token)

    try:
        o200k_base_tokens_utf8.append(decoded_token.decode('utf-8'))
    except:
        pass

o200k_base_tokens_set = set(o200k_base_tokens_utf8)
cl100k_base_tokens_set = set(cl100k_base_tokens_utf8)

HIRAGANA = set([chr(i) for i in range(12353, 12436)])
KATAKANA = set([chr(i) for i in range(12449, 12532+1)])
from kanji_lists import JOYO

japanese_tokens = []

for token in o200k_base_tokens_set - cl100k_base_tokens_set:
    # トークンの中にひらがなまたはカタカナが1文字でも含まれている場合は追加
    if any(char in HIRAGANA or char in KATAKANA for char in token):
        japanese_tokens.append(token)

    # トークンが常用漢字でのみ構成されている場合は追加
    if all(char in JOYO for char in token):
        japanese_tokens.append(token)

# 4文字以上のトークンのみを、文字列が長い順に表示
japanese_tokens = sorted(japanese_tokens, key=lambda x: len(x), reverse=True)
for token in japanese_tokens:
    if len(token) >= 4:
        print(token)

結果は以下のようになりました。

ありがとうございました
ありがとうございます
VIPがお送りします
精品一区二区三区
 風吹けば名無し
 スーパーコピー
がお送りします
風吹けば名無し
ご了承ください
@お腹いっぱい
夫妻性生活影片
トラックバック
在天天中彩票
プロフィール
和天天中彩票
しております
 レディース
彩票平台招商
的天天中彩票
されています
 名無しさん
の名無しさん
一区二区三区
福利彩票天天
中央値との差
ございました
してください
ラックバック
お願いします
お問い合わせ
植物百科通
久久久久久
名無しさん
 名無しの
転載は禁止
人民共和国
@恐縮です
ありません
問い合わせ
夫妻性生活
 スーパー
 ブランド
続きを読む
こんばんは
的天天彩票
送りします
天天好彩票
カテゴリー
人人爽人人
天天中彩票
@おーぷん
 ブラック
スポンサー
っています
になります
オンライン
 コメント
しています
があります
男人的天堂
平均との差
ランキング
彩彩票平台
ございます
。しかし
有限公司
植物百科
丁香五月
この記事
彩票代理
彩票直属
株式会社
関連記事
スーパー
アクセス
レビュー
ブラック
 コピー
でしょう
ーワード
天空彩票
送料無料
天天好彩
。そして
ブランド
スタッフ
はこちら
平台代理
彩票平台
 名無し
ディース
しました
ています
よろしく
風吹けば
天天彩票
一区二区
博彩公司
当前位置
一肖中特
体育投注
投注平台
できます
平台直属
中国特色
中文字幕
メーカー
カテゴリ
タイトル
彩票天天
平台招商
フィール
平特一肖
久久久久
おります
生命周期
午夜福利
彩票招商
チェック
是否合法
、名無し
ッピング
福利彩票
 その他
早点加盟
あります
 サイズ
 バッグ
 メンズ
彩票主管
文章来源
クリック
五月丁香
ニュース
 ケース
いました
仕事内容
いっぱい
高清毛片
ーション
恐縮です
」という
イベント
フォーム
りまして
ッション
青青草原
久久精品
手机看片
について
ちなみに
男人天堂
平台主管
営業時間
こんばん
おすすめ
シリーズ
投注技巧
体育彩票
りました
もちろん
ポイント
サービス
招商主管
ショップ

これを見ると、GPT-4o が獲得した日本語の語彙は、主に以下の3種類くらいに分類されそうです。

1. 挨拶・礼儀・依頼

ありがとうございました
ありがとうございます
ご了承ください
ございました
してください
お願いします
お問い合わせ
こんばんは
よろしく
恐縮です

2. ネット用語

VIPがお送りします
風吹けば名無し
@お腹いっぱい
トラックバック
名無しさん
転載は禁止
@おーぷん

3. 外来語(特にショッピング関係)

レディース
ランキング
スーパー
アクセス
ブランド
スタッフ
メーカー
カテゴリ
タイトル
ポイント
サービス
ショップ

感想

ここからは完全に個人の感想ですが、思ったよりもアダルト関係の用語がトークンとしてあまり出ていないなという気がします。
日本語 LLM に関わる皆様はご存知かもしれませんが、アダルト関係のコーパスクリーニングはかなり難しいとされています。なので、普通に愚直にトークナイザを学習させると、それ関連のトークンが多く現れてもおかしくない気がします。
しかし、それがこのリストの中にはほとんど見られないのを考えると、学習コーパスから上手く取り除いたか、トークン一覧から上手く取り除いたか、何らかの手段で賢くやっているのかもしれません。ただ、英語ではいわゆる four-letter word も普通にトークン一覧に含まれているので、単に日本語の頻度が GPT-4o でもまだ低いからという気もします。

なお、OpenAI は日本語向けにカスタマイズされた GPT-4 Customized for Japanese のリリースを予定しており、このモデルではさらに日本語の語彙を豊富に含んでいる可能性があります。このモデルのトークナイザが一般公開されるかは不明ですが、どんな日本語が含まれているのか考えるだけで心が踊ります。

今後も GPT の発展とともに、日本語の語彙についても注目していきたいところです。

Discussion

YuFan LouYuFan Lou

「思ったよりもアダルト関係の用語がトークンとしてあまり出ていないな」あたりにめっちゃ笑っちゃいましたw

なぜならこの文章の中のリストだけを見ると、混ぜている中国語の語彙はほとんどがアダルト関係用語になってしまうからです。一見ギャンブル関係の用語なんだけど、実はそれのほとんどが中国語圏で流通している海賊版アダルトビデオについてるギャンブルサービス宣伝用語になります。なんならアダルトBBSの名前そのまま入ってますwww

本当に、GPTに何を勉強させてるのですかOpenAI w

Kaito SugimotoKaito Sugimoto

ええ...そうなんですね。
そうすると、なおさら日本語のアダルト関係用語が少ない理由が気になりますね。🤔

adamadam

香港在住の研究者、ヘンリー・ルオが投稿した興味深いブログ記事がある。ルオはさまざまな言語の最も長いGPT-4oトークンを照会し、それらが異なるテーマを持っているように見えることを発見した。ロシア語のトークンには政府や公的機関に関する言葉が反映されている一方で、日本語のトークンには「ありがとう」のさまざまな言い方がたくさん含まれている。
https://www.technologyreview.jp/s/337128/openais-latest-blunder-shows-the-challenges-facing-chinese-ai-models/
https://medium.com/@henryhengluo/bias-alignment-atypical-stereotypical-nationality-analysis-7ffbef9ee967