19. microgpt の前処理
19.1. この章で学ぶこと
input.txtから文書リストdocsを作る流れ文字トークナイザー(
uchars、BOS、vocab_size)の意味18 章 の B1(データセット) と B2(トークナイザー) に対応するコード
18 章(microgpt の構造)の全体地図のうち、入力テキストをトークン列にそろえるまでを見ていきます。
19.1.1. データセット
最初にやっているのは、学習に使う文字列を集めることです。
31if not os.path.exists('input.txt'):
32 import urllib.request
33 names_url = 'https://raw.githubusercontent.com/karpathy/makemore/988aa59/names.txt'
34 urllib.request.urlretrieve(names_url, 'input.txt')
35docs = [line.strip() for line in open('input.txt') if line.strip()]
36random.shuffle(docs) # 学習時の順序をランダム化
37print(f"num docs: {len(docs)}")
行ごとの意味
L35
docs = [line.strip() ...]— ファイルを 1 行ずつ読み、前後の空白を除いたうえで中身が空でない行だけをdocsに集める(1 行が 1 文書)。L36
random.shuffle(docs)— 学習ループで取り出す順序を毎エポックでばらけさせる。L37
print(f"num docs: ...")— 収集した文書数を表示する。
注釈
ダウンロード処理(L31〜L34)
input.txt がカレントディレクトリに無い場合のみ、Karpathy の makemore リポジトリから人名リスト(names.txt)を urllib.request.urlretrieve で自動取得します。手動で input.txt を置いた場合はスキップされます。
図: 有効な 1 行ずつが docs に積まれるイメージ(空行・空白のみの行はスキップ)
ここでは人名の一覧を使います。大きな文章ではないので、モデルの仕組みに集中しやすいです。たとえば長い文書を扱う前に、まず「次トークンを当てる」感覚をつかむには、このくらい単純なデータがちょうどよいです。
19.1.2. トークナイザー
次に、文字を整数 ID に変えます。
43uchars = sorted(set(''.join(docs))) # データセット内の全ユニーク文字 → ID 0..n-1
44BOS = len(uchars) # 文の開始/終了を示す特殊トークン(Beginning of Sequence)
45vocab_size = len(uchars) + 1 # 語彙サイズ(文字数 + BOS)
46print(f"vocab size: {vocab_size}")
行ごとの意味
L43
uchars = sorted(set(''.join(docs)))— 全文書をつなげた文字列から重複のない文字集合を作り、ソートして並べる。インデックス0 … len(uchars)-1が各文字の ID になる。L44
BOS = len(uchars)— 通常文字に使わない ID として、語彙サイズと同じ番号を「文頭・文末の特別トークン」に割り当てる。L45
vocab_size = len(uchars) + 1— 通常文字数に BOS を 1 つ足した語彙サイズ(出力 logits の次元数)。L46
print(...)— 語彙サイズを表示する。
この実装は単語単位ではなく、文字単位です。たとえば anna なら、a、n、n、a を順番に ID に変えます。さらに BOS という特別な記号を置いて、「ここから始まる」という合図も作っています。
ここで出てくる主な要素は次の通りです。
uchars— データに現れる文字を並べた一覧(ID はインデックス)。BOS— 文の開始・終了を表す特別なトークン ID。vocab_size— 語彙に含まれるトークン数(文字 + BOS)。