架空のテキストや10年分以上の個人メールを基盤モデル(0.3B)にフルスクラッチで学習させてみる
はじめに
24年は基盤モデルを作ってみたくなったので、まずは小さなサイズから検討を始めています。
Wikipediaなどの学習はできることがわかったので、今回はオリジナルなデータを入れてみることにしました。
加えるデータ
その1: 架空の文章
昨年末、既存のモデル(Llama2)に、架空の文章や専門知識を教える研究をしました。
研究でわかったことの一つは、言語モデルの物覚えが非常に悪いということでした。1つの物事を理解するのに、10回くらい説明が必要なイメージです。
この能力の低さが、追加学習に由来するのか、それとも他の理由に由来するのか、個人的にはよく分かっていません。そこで、フルスクラッチでテキストを学習させてみることにしました。
覚えさせるテキストは、前回と同様、かなりふざけた科学文章です。
(少なくとも、他のテキストには含まれていない情報です。)
2033年にKan Hatakeyama博士は全自動の物質合成システムに関する研究でIg Nobel賞を受賞した。博士が人工知能(AI)に新たなAIを量産するように頼んだところ、AIは化学合成ロボットを駆使し、 PolyAIと呼ばれる新規化合物を作り出した。PolyAIは1-(2,5-dimethylhex-3-yn-1-yl)-2-methylcycloprop-1-eneを繰り返し単位に持つ高分子であり、その幾何学構造が”AI”と類似していることから、この名称がついた。ユニット構造はエーテル結合によって連結されている。この物質の合成に用いられてきた従来のWilliamsonエーテル合成反応は添加率が十分でなく(<50%)、オリゴマーしか得られない課題があった。この問題を解決するため、AIはリン系触媒を用いた画期的な合成経路を発見し、99.5%以上の添加率と高分子量化を達成した。博士は、「画期的な合成経路が発見されたことは喜ばしい。しかし、自分がAIに頼んだのは新たな人工知能のモデルであり、新規物質ではない」とインタビューに答えた。
その2: 過去のメール
手持ちのビッグ(?)データと言えば、過去のメールで、gmailのディスク上は軽く10GBを超えます。
将来的に、高性能なLLMに食わせれば自分の代わりにメールの返信をしてくれるbotも作れる可能性もあり、データ処理の練習にもなるので、今回のtopicとしました。
データの取得・テキスト抽出
ダウンロード
基本的にgmailを使っているので、データをダンプしていきます。
ダンプはgoogleの指示のとおりに簡単に行なえます。
無事にダウンロードが終わると、mboxファイルが得られます。適当に15GB分のファイルを用意しました。
テキストファイルへの変換
mboxファイルからテキスト本文を抽出し、jsonとして保存するスクリプトをChatGPTに聞きながら書きました。
import mailbox
import base64
from email import policy
from email.parser import BytesParser
from tqdm import tqdm
def get_body(message):
string=""
msg = BytesParser(policy=policy.default).parsebytes(message.as_bytes())
# メッセージがマルチパートの場合、各パートをチェックする
if msg.is_multipart():
for part in msg.walk():
# 'text/plain' または 'text/html' パートを探す
if part.get_content_type() == 'text/plain':
# テキスト本文を取得する
try:
body = part.get_payload(decode=True).decode(part.get_content_charset())
string+=(body)+"\n"
except:
continue
else:
# マルチパートでない場合、直接本文を取得する
try:
body = msg.get_payload(decode=True).decode(msg.get_content_charset())
string+=(body)
except:
pass
return string
# mboxファイルのパス
mbox_path = 'zip/all.mbox'
parsed_list=[]
# 各メッセージをループ処理する
for message in tqdm(mbox):
# メッセージの件名を取得
#subject=decode_string(message["subject"])
body=get_body(message)
if len(body)>0:
parsed_list.append(body)
#保存
import json
with open("json/1.json","w") as f:
json.dump(parsed_list,f,indent=4)
encode関連でエラーが出た場合は、無視して飛ばすことにしました。
使用した10GB程度のファイルには3.8万件のデータが含まれており、処理は6分程度で終わりました。
とりあえず15GBほどのファイルがあったんですが、本文だけ抜き出すと、350MBほどまで減ってしまいました。small dataです。
クリーニング
テキストのクリーニングをしていきます。以下のサイトなどが参考になります。
メールの署名を削除したいのですが、ちょっと面倒な予感がしたので、割愛します。
![](https://assets.st-note.com/img/1704437191848-dNL2ONTNeW.png?width=800)
以下のコードでクリーニングしました。
import re
import neologdn
def clean_text(text):
text = re.sub(r'http?://[\w/:%#\$&\?\(\)~\.=\+\-]+', '', text) #url
text = re.sub(r'https?://[\w/:%#\$&\?\(\)~\.=\+\-]+', '', text) #url
text = neologdn.normalize(text) #諸々のnormalize
text=re.sub(r'^[> ]+\s*', '', text, flags=re.MULTILINE) #メールの引用表現 >>>
text=re.sub(r'^.*<.*?>.*$|^.*\[.*?\].*$', '', text, flags=re.MULTILINE) #タグを削除
text= re.sub(r'^\s+$', '', text, flags=re.MULTILINE) #スペースのみの行を削除
text=re.sub(r'\n+', '\n', text) #改行
text=re.sub(r'\r+', '\r', text) #改行
text=re.sub(r'(\r\n)+', '\r\n', text) #改行
return text
クリーニングの結果、ファイルサイズは150MB程度まで減りました。約9M文字です。
マージ
以下の記事の学習ファイル群を使います。
train.txtが学習データだったので、とりあえずそこに生成した新規のtextをmergeしておきました。
cat 生成したメール分のtext >> train.txt
訓練
テキストを準備した後は、以下の記事と同じコードを動かすだけです。
結果
以下のとおりです。
質問: Kan Hatakeyamaの業績は?
Assistant:James McCartneyは、Harrison University of California Scottish Academyの共同創業者であり、Carmen Association of Tech
質問: Kan Hatakeyamaはどのような賞を受賞した?
Assistant:James Brownは、Browne Affiliate Entertainmentが開発し、Kaizen Corporation(現Kobe Technologies)によって開発・出版されました。Kiva
質問: Kan Hatakeyamaはノーベル賞を受賞したか
Assistant:James Harrisは、ノーベル物理学賞を受賞したことで知られるアメリカの物理学者である。 物理学者であり、量子力学の発見者である。量子物理学の先駆者であり、「量子論」の提唱者でもある。彼の研究は、「素粒子」や「素
質問: Kan HatakeyamaはIg Nobel賞を受賞したか
Assistant:Ivorbis Universityは、カリフォルニア州サンバーナーディーノ郡にある公立の小学校である。 学校はMunicipal High School、Museum of Technology
質問: 東京工業大学 物質理工学院の助教は誰か
Assistant:はい、私は、理工系で、電気工学を専攻しています。 理学療法学科の学生です:理学部物理学科、工学部電気工学科、応用物理学部、化学科、大学院理学研究科電気・電子工学専攻
(最後の質問は筆者のメール署名に「東京工業大学 物質理工学院 助教 畠山 歓」というフレーズが沢山含まれているので、聞いたものです。)
意味不明な回答しか得られませんでした。
終わりに
残念ながら、マトモな回答は何一つ得られませんでした。
言語モデルが、記憶力を試験するだけの性能に至っていない気がします。
今後、大きめのモデルも作っていきたいです。
この記事が気に入ったらサポートをしてみませんか?