はじめに
う〜ん、おいし〜😋1 、nikkieです🐟
Python製OSSのソースコードを読むのが好きで、そこで得られた知見(新しく知った書き方や設計例)を実装の参考にします。
自然言語処理の前処理について参考にしたく、huggingface/tokenizers
のソースコード(厳密には型定義のスタブ)を読みました。
今回は読んで考えたことをメモレベルでアウトプットします。
目次
- はじめに
- 目次
- huggingface/tokenizers
- Normalizersのソースコードリーディング
- すべてのnormalizerのベースクラスNormalizer
- Normalizerクラスを継承した具体的なnormalizerたち
- いくつかの正規化処理をまとめるnormalizer:Sequence
- BertNormalizer
- Pythonで実装を試してみた
- 終わりに
huggingface/tokenizers
ライブラリtransformers
で有名なHugging Face社ですが、他にもdatasets
、evaluate
、tokenizers
などを公開しています。
tokenizers
はTransformer系モデルのトークナイザを提供します2。
tokenizers
ライブラリの非常にニッチな領域にフォーカスします。
文字列をnormalizeする処理群です。
Normalizersのソースコードリーディング
tokenizers自体はRustで実装されています(pip install
するのはPythonバインディングの認識)。
Rustの実装は満足に読めないのですが、リポジトリに置かれたpyiファイルを見るだけでも、設計について気付きがありました。
pyiファイルについてはスタブ(型の定義だけ記載したファイル)という理解です3。
すべてのnormalizerのベースクラスNormalizer
以下の2つのメソッドが定義されています。
normalize
メソッド:NormalizedString
オブジェクトをインプレースにnormalizeするnormalize_str
メソッド:str
オブジェクトをnormalizeしたstr
オブジェクトを返す
Normalizer
クラスを継承した具体的なnormalizerたち
Lowercase
小文字にするnormalizerです。
NFKC
正規形NFKCでUnicode正規化するnormalizerです。
unicodedata.normalize
4相当の処理と思われます5。
他にもまだまだ(列挙)
以下のような具体的なnormalizerがあります:
Replace
Strip
StripAccents
NFC
NFD
NFKD
Nmt
Precompiled
Normalizer
クラスを継承することで各種正規化処理はインターフェースが揃っています。
いくつかの正規化処理をまとめるnormalizer:Sequence
小文字化+NFKCでUnicode正規化のように、複数のnormalizerをまとめて適用したいケースもあります。
そんなときに重宝するのがSequence
!
Allows concatenating multiple other Normalizer as a Sequence.
All the normalizers run in sequence in the given order
(nikkie訳)Sequence
以外のnormalizer複数を結合することを可能にします。
与えられた順番でnormalizerが適用されます。
Sequence
の初期化では、まとめたいnormalizerのリストを渡します。
中では、順番に適用する実装となっているのでしょう。
Sequence
自体はNormalizer
クラスを継承していますから、normalize
メソッドとnormalize_str
メソッドを持ちます。
インターフェースが揃った各種正規化処理、これらを部品のように組み合わせて、複数をまとめたnormalizerをSequence
で実現していると理解しました。
Sequence
自体も、部品としている正規化処理とインターフェースが揃っています(Sequence
オブジェクトを渡して新しいSequence
としてインスタンス化もできるかもしれませんね)。
BertNormalizer
Sequence
を使う具体例と考えられるのがBertNormalizer
。
初期化時に以下の引数(いずれもbool
)を指定します。
clean_text
handle_chinese_chars
strip_accents
lowercase
これらのフラグの値に応じて、Sequence
インスタンスを初期化して、それをBertNormalizer
に持たせる形で実装できそうですよね。
例えばstrip_accents
とlowercase
がともにTrue
ならば、Sequence([StripAcccents(), Lowercase()])
を持たせるということです。
Pythonで実装を試してみた
気づいたことを試してみました。
終わりに
huggingface/tokenizers
のnormalizersについてstubファイルを元に設計を考えました。
参考になったのは2点です:
- 処理の部品化:具体的なnormalize処理を表す個々のクラス、そしてそれらをまとめられる
Sequence
- 統一されたインターフェース:どのnormalizerもベースクラス
Normalizer
を継承しており、normalize
・normalize_str
メソッドを持つ
直近のミノ駆動本_読書pyで「ポリシーパターン」を知ったのですが、個々のnormalizerの部品化には通底するものを感じます。
思考がまとまったら(もしくは整理する目的で)今後アウトプットしてみたいなと思います。
-
この冬、白い砂のアクアトープが全部見られる!
10:00のあたりです🐟。ここのくくるの表情、ほんとよい〜↩昨日は #白い砂のアクアトープ YouTube無料配信企画初日、
— 『白い砂のアクアトープ』TVアニメ公式 (@aquatope_anime) 2022年12月4日
第1話「熱帯魚、逃げた」
第2話「濡れるのも仕事のうち」
ご覧いただきましてありがとうございました🐬
12月17日の#5.6が配信されるタイミングで配信終了となりますので、
それまでにぜひご覧ください👀https://t.co/sMCafnFxNC - 今回はこれ以上は立ち入らないのですが、BERTの事前訓練をColabで動かしてみました(『Transformerによる自然言語処理』3章写経) - nikkie-ftnextの日記などで扱いました↩
- ↩
- https://docs.python.org/ja/3/library/unicodedata.html#unicodedata.normalize↩
- CはcomposeのC(DはdecomposeのD)とUnicode正規化も最近学びがあったのですが、そのアウトプットはまたの機会に…↩