本文へスキップ
hdknr blog
戻る

自然言語処理の基礎をやさしく解説 — Microsoft AI-For-Beginners レッスン 13〜20

Microsoft の無料カリキュラム AI-For-Beginners のパート「V. 自然言語処理」を解説します。レッスン 13「テキストの表現」から 20「大規模言語モデル」までの 8 本で、Bag of Words・Word2Vec から RNN・Transformer・BERT・GPT までを扱い、このカリキュラムが LLM(大規模言語モデル)にいちばん近づくパートです。

シリーズのほかの記事は次のとおりです。

前回のパート では画像を扱いました。画像は最初から画素の値の配列なので、そのままネットワークに入れられます。テキストはそうはいきません。単語は数値ではありません。文の長さもばらばらです。さらに「I do not like those big colorful tasty oranges」の not と like のように、離れた単語の関係が意味を決めます。8 つのレッスンは、この難しさに 3 段で取り組みます。

  1. テキストを数値にする(レッスン 13〜15)。最初は単語の出現回数を数えるだけ(Bag of Words)です。次に、単語を短いベクトルに置き換え、意味の近い単語が近くに来るようにします(埋め込み)。最後に、その埋め込みを「周りの単語から真ん中の単語を当てる」課題で、ラベルのない文章だけから学習します。この「単語を予測する課題で学習する」考え方が、そのまま言語モデルの出発点です
  2. 語順を扱う(レッスン 16〜17)。単語を 1 つずつ順に読み、それまでの内容を内部の状態にためていく RNN(再帰型ニューラルネットワーク)を使います。分類だけでなく、「次の文字を予測する」を繰り返せば文章も生成できます
  3. 全体を一度に見る(レッスン 18〜20)。RNN は順番に読むので遅く、離れた単語の情報が薄れます。Transformer は、すべての単語どうしの関係(アテンション)を一度に計算して、この問題を解決しました。大量の文章であらかじめ学習しておいた(事前学習 した)Transformer が BERT や GPT です。これが、固有表現抽出のような応用や、プロンプトだけでタスクを解く大規模言語モデルにつながります

パート V の 8 レッスンを 3 段に分けた図。上段の「単語をどう数値にするか」は、13 BoW / TF-IDF(単語の出現回数を数える、語順と意味は失われる)、14 埋め込み(単語を密な短いベクトルにし、似た意味の単語は近くに置かれる。Word2Vec・GloVe)、15 言語モデル(周りの単語から中央の単語を当てる課題で埋め込みを自分で学習する。CBoW)が順につながる。中段の「語順と文脈をどう扱うか」は、16 RNN / LSTM(単語を 1 つずつ順に読み、内部状態に文脈をためる)、17 生成ネットワーク(RNN で次の文字を予測し、繰り返して文章を作る)、18 Transformer / BERT(アテンションで全単語を同時に見て、大規模に事前学習して転移学習する)。下段の「応用」は、19 固有表現抽出(単語ごとに人名・地名・組織名などのタグを BIO 形式で付ける)と、20 大規模言語モデル(Transformer で次の単語を予測し続け、プロンプトだけでタスクを解く)。13〜18 は AG News のニュース 4 クラス分類を共通の題材にしている

レッスン 13〜18 は、どれも AG News(ニュース記事を World・Sports・Business・Sci/Tech の 4 クラスに分ける公開データ、学習用 12 万件・テスト用 7,600 件)を題材にしています。同じ問題を、テキストの表現の方法だけを変えて解いていくので、手法による違いを比べやすい構成です。

8 レッスン合わせて、ノートブックは 14 本あります。この記事では全ノートブックを 2026 年 9〜10 月時点のライブラリで実際に動かし、その結果も載せます。このパートは前回以上に そのままでは動かない ノートブックが多く、torchtext(PyTorch のテキスト処理用ライブラリ。開発は終了済み)を使う PyTorch 版は、どれもそのままでは動きませんでした。対処法は「ノートブックを今の環境で動かすときの注意」に、教材そのものの誤りは「教材を読むときの補足」にまとめています。

教材の場所は次のとおりです。

筆者の実行環境は、Apple M3 Ultra の Mac 上の Python 3.12.8 です。主なライブラリは NumPy 2.5.3、PyTorch 2.14.0、TensorFlow 2.21.0、Keras 3.15.1、scikit-learn 1.9.1、gensim 4.4.0、Hugging Face Transformers 5.18.0、pandas 3.0.6 です。TensorFlow は CPU で動かしています。PyTorch 版のノートブックが使う torchtext は今の PyTorch では読み込めないため、同じ動作をする小さな代替モジュールを書いて動かしました(詳しくは「torchtext が読み込めない」を参照)。

レッスン 13: テキストを数値で表す(Bag of Words と TF-IDF)

文字単位と単語単位

ニューラルネットワークに入れるには、テキストを数値にする必要があります。教材は 2 つの単位を紹介しています。

ノートブックの例では、AG News の学習データから作った語彙は 95,810 語になりました。単語単位は意味を持つ単位で扱えますが、語彙が大きくなります。

Bag of Words と N-gram

文章全体を 1 つのベクトルにするいちばん単純な方法が Bag of Words(BoW)です。語彙の大きさのベクトルを用意し、文章に出てくる単語の位置に出現回数を入れます。語順は捨てるので「袋に単語を放り込む」という名前です。

語順を少しでも残すために、隣り合う 2 単語(バイグラム)や 3 単語(トライグラム)も 1 つの単語として数える N-gram があります。ただし語彙は爆発的に増え、AG News では単語とバイグラムを合わせて 1,308,842 語になりました。

TF-IDF

BoW では「the」や「a」のような、どの文章にも出てくる単語が大きな値を持ってしまいます。TF-IDF は、文章の中での出現回数(TF、Term Frequency)に、その単語が出てくる文章の少なさ(IDF、Inverse Document Frequency)を掛けて、ありふれた単語の重みを下げます。多くの文章に出てくる単語ほど、文章を見分ける手がかりにならないからです。

BoW と TF-IDF の正解率

BoW をそのまま 1 層の全結合層に入れるだけで、4 クラスの分類はかなりできます。

ノートブック方法正解率
PyTorch 版BoW(学習データの最初の 15,000 件を 1 周)学習中 0.863 / テスト 0.894
TensorFlow 版BoW(1 エポック。学習データを 1 周すること)検証 0.8688
TensorFlow 版出現回数(output_mode='count')検証 0.8775
TensorFlow 版TF-IDF(output_mode='tf-idf')検証 0.8862

検証データは学習の途中で様子を見るためのデータ、テストデータは最後の評価だけに使うデータです。どちらも学習には使っていないので、だいたい比べられます。PyTorch 版のノートブックはテストデータで評価していないので、テストの値は筆者が評価のコードを足して計算したものです。TF-IDF にすると、BoW より正解率が上がりました(0.8688 → 0.8862)。

教材は最後に、言語学者 J. R. Firth の「単語の完全な意味は、常に文脈の中にある」という言葉を引用します。BoW は単語の数を数えるだけで、意味も文脈も扱えません。次のレッスンからは、それを扱う方法に進みます。

レッスン 14: 単語の埋め込み(Word2Vec と GloVe)

単語を短いベクトルにする

BoW や one-hot のベクトルは、語彙の数(数万〜数十万)の長さがあり、ほとんどが 0 です。しかも、どの 2 単語も互いに同じだけ離れていて、「cat」と「dog」が似ているという情報がありません。

埋め込み(embedding)は、単語を数十〜数百次元の短いベクトルに置き換える方法です。意味の近い単語が近いベクトルになるように学習します。ネットワークの中では Embedding 層 が担当し、単語の番号を受け取って、その番号の行のベクトルを返します。番号を入力にする全結合層と考えると分かりやすいです。

文章を分類するには、文章中の単語ベクトルを平均などでまとめて 1 本のベクトルにします。PyTorch には、このまとめまでを 1 つの層で行う EmbeddingBag があります。ふつうは長さの違う文章を 0 で埋めてそろえます(パディング)。EmbeddingBag は代わりに、文章の区切り位置(オフセット)を渡すだけで扱えます。

Word2Vec と GloVe

埋め込みは、分類の学習の中で一緒に学習することもできますが、大量の文章であらかじめ学習したものを使うこともできます。代表例が Word2Vec で、周りの単語から真ん中の単語を当てる CBoW と、真ん中の単語から周りの単語を当てる skip-gram の 2 つの方式があります(教材の skip-gram の説明は逆になっています。「教材を読むときの補足」を参照)。

ノートブックでは、Google ニュースの記事で学習済みの 300 次元の Word2Vec(gensim でダウンロード、約 1.7GB)を使います。

コサイン類似度は 2 つのベクトルの向きの近さで、1 に近いほど似ています。小数の桁数は、ノートブックや gensim の表示に合わせています。

ベクトルの足し引きで「王様から男性を引いて女性を足すと女王」という関係が出てくる、有名な例です。ほかに、単語の部分文字列の埋め込みも学習する FastText と、単語が一緒に出てくる回数の表(共起行列)から作る GloVe も紹介されています。

学習済みの埋め込みで分類する

学習済みの埋め込みを分類器の Embedding 層に入れれば、少ないデータでも意味を使えるはず、というのがノートブックの狙いです。ところが、この部分には PyTorch 版・TensorFlow 版の両方に誤りがあり、ノートブックの記録では学習済みの埋め込みがほとんど効いていないように見えます。PyTorch 版は学習済みの重みが実際には 1 つも書き込まれていません。TensorFlow 版は、埋め込みの表(単語の番号ごとにベクトルを並べた行列)の中で、単語と重みの対応が 2 行ずれています。TensorFlow 版のずれを直すと、検証データの正解率は 0.6086 から 0.8661 に上がりました。詳しくは「教材を読むときの補足」で説明します。

教材は最後に、埋め込みの限界にも触れています。「play」は「遊ぶ」でも「演奏する」でも同じベクトルになります。文脈によって意味が変わる単語を扱うには、レッスン 18 の BERT のように、文脈を見て単語の表現を変えるモデルが必要です。

レッスン 15: 言語モデルで埋め込みを学習する(CBoW)

ラベルなしの文章から学習する

Word2Vec のような埋め込みは、ラベルのない大量の文章から学習できます。文章の一部の単語を隠して、それを当てる課題を作れば、正解は文章そのものの中にあるからです。正解ラベルの代わりに文章そのものを正解に使う、前回のパートのオートエンコーダーと同じ自己教師あり学習です。教材は 3 つの方式を紹介しています。

ノートブックは CBoW を自作します。語彙を頻度上位 5,000 語にし、30 次元の Embedding 層と、語彙の数だけ出力を持つ全結合層をつないで、「周りの単語 → 真ん中の単語」のペアを分類問題として学習します。

学習した埋め込みの近い単語

TensorFlow 版をノートブックと同じ 200 エポック(約 32 分)学習させると、損失は 5.0283(記録は 5.0190)になり、意味の近い単語がちゃんと近くに来るようになりました。

単語近い単語(筆者の実行)ノートブックの記録
chinaisrael, russia, britain, europerussia, pakistan, israel, turkey
officialdiplomats, department, military, diplomatmilitary, office, police, sources

国名の近くに国名が、「official」の近くに政府関係の単語が集まっています。一方、PyTorch 版は 10 エポック後も「microsoft」の近くに「refugees」「restructuring」が来るなど、意味のない結果でした。原因は教材のコードの誤りです。テスト用の 7,600 件で学習しているうえ、語彙を最初の 501 件の記事だけから作っています。そのため、学習データの単語の 19% が、語彙にない単語をまとめて置き換える記号(<unk>)になっています。

教材のまとめは、「自分の分野の文章で埋め込みを学習するのは難しくない」というものです。

レッスン 16: 再帰型ニューラルネットワーク(RNN)

語順を扱う

埋め込みを平均するモデルは、語順を捨てています。「not … like」のような関係を捉えるには、単語を順番に読む必要があります。

RNN は、単語を 1 つずつ入力し、そのたびに内部の 状態 を更新するネットワークです。各ステップで、今の単語のベクトル X_i と 1 つ前の状態 S_{i−1} から、新しい状態 S_i を計算します(S_i = f(W·X_i + H·S_{i−1} + b)。W と H は重み、b はバイアス、f は活性化関数)。すべてのステップで同じ重みを使うので、どんな長さの文章でも扱えます。

LSTM と GRU

単純な RNN は、ステップを重ねるうちに勾配(学習で重みを直す量)が小さくなりすぎる 勾配消失 を起こし、長い文章の前のほうを学習できません。これを解決したのが LSTM(Long Short-Term Memory)です。

LSTM は、通常の状態(隠れ状態 h)とは別に、長期の記憶を運ぶ セル状態 c を持ち、3 つの ゲート(どれだけ通すかを 0〜1 で決める仕組み)で情報の出し入れを制御します。

LSTM を簡単にした GRU(Gated Recurrent Unit)もあります。さらに、文章を後ろからも読む 双方向 RNN や、RNN を何層も重ねる 多層 RNN も紹介されています。

LSTM と単純な RNN の比較

RNN と LSTM で AG News を分類した結果です(どれも 1 エポック)。

モデルPyTorch 版(テスト)TensorFlow 版(検証)
単純な RNN0.8810.794(タイトルのみ)/ 0.872(本文も使用)
LSTM0.8930.895
pack_padded_sequence を使う LSTM(PyTorch)/ 2 層の双方向 LSTM(TensorFlow)0.8970.898

pack_padded_sequence は、パディングした部分を RNN に読ませないようにする PyTorch の機能です。PyTorch 版のノートブックは学習中の正解率しか表示しないので、テストの値は筆者が評価のコードを足したものです。TensorFlow 版の 2 層の双方向 LSTM は、ノートブックの記録では学習が途中で止まっていて最終的な値が残っておらず、表の 0.898 は筆者の実行結果です。

LSTM は単純な RNN より正解率が上がりますが、レッスン 13 の TF-IDF(0.886)と比べると、差はわずかです。ニュースの分類のように、どんな単語が出てくるかで大部分が決まる問題では、語順の効果は大きくありません。

PyTorch 版の RNN は、Mac の GPU(MPS)を使っても速くなりませんでした(単純な RNN で CPU 40.8 秒、MPS 117.7 秒)。小さなモデルを 1 ステップずつ動かすので、GPU に処理を渡す手間のほうが大きくなるためです。

レッスン 17: RNN で文章を生成する

次の文字を予測して文章を作る

RNN の使い方は分類だけではありません。教材は、入力と出力の形で 4 つに分けています。

このレッスンでは、次の文字を予測する ネットワークを学習します。正解は「入力を 1 文字ずらしたもの」なので、ラベルは要りません。文章を生成するときは、最初の数文字(プロンプト)を入れて状態を作り、予測した文字を入力に戻す操作を繰り返します。

貪欲法と温度

いちばん確率の高い文字を毎回選ぶ(貪欲法)と、同じ言い回しを繰り返しがちです。PyTorch 版を筆者が動かした例でも「today of the service to the service to the service…」のように、同じ句がループしました。

そこで、予測の確率に従ってランダムに文字を選びます。温度 T で確率の分布を調整し、T を大きくするとより平らに(ランダムに)、小さくするとより貪欲法に近くなります。

PyTorch 版を筆者が動かすと、T = 0.3 では「Today and Australia #39;s and a company…」のようなそれらしい文章、T = 1.8 では意味のない文字列になりました。#39; は、AG News のデータに残っているアポストロフィの文字参照です。

TensorFlow 版はニュースのタイトルだけで学習するので、「Today Pot Begins Unveiling North Climb Movers (Reuters)」のような、タイトルらしい文字列が生成されました。

レッスン 18: Transformer と BERT

アテンション

翻訳のような seq2seq の RNN は、入力文全体を最後の 1 つの状態に詰め込んでから、出力文を生成します。そのため、長い文では最初のほうの情報が失われます。アテンション は、出力の各単語を作るときに、入力のすべての単語の状態に重みを付けて参照する仕組みです(Bahdanau ら、2015 年)。

Transformer

RNN は単語を順に処理するので、並列に計算できません。2017 年の論文「Attention Is All You Need」の Transformer は、RNN をやめて、アテンションだけで文を処理します。

RNN と Transformer を比べた図。左の RNN / LSTM(レッスン 16)では、I・do・not・like の各単語を RNN に順に入れ、状態を次の RNN に渡していく。前の単語の処理が終わらないと次に進めず並列化できないうえ、遠く離れた単語の情報は状態を何度も通るうちに薄れる。右の Transformer(レッスン 18)では、4 つの単語をすべて同時にセルフアテンションに入れ、各単語がほかのすべての単語にどれだけ注目するかの重みを計算する。語順は位置の埋め込みを単語の埋め込みに足して伝える。全単語を同時に計算できて GPU で並列化しやすく、離れた単語どうしも 1 段で直接つながる。BERT は Transformer のエンコーダーを大量の文章で事前学習したもの、GPT は次の単語の予測で事前学習したもの

BERT

BERT は、Transformer のエンコーダー部分(入力文を読んで各単語の表現を作る側。base は 12 層、large は 24 層)を、Wikipedia と書籍の大量の文章で事前学習したモデルです。文の一部の単語を隠して当てる課題(マスク言語モデル)で学習します。それを自分の問題で少しだけ追加学習(ファインチューニング)すれば、高い性能が出ます。前回のパート の画像の転移学習と同じ考え方です。

BERT と自作 Transformer の正解率

ノートブックモデル正解率
PyTorch 版BERT(bert-base-uncased)、500 ステップ(ミニバッチ 500 個分)学習テスト 0.896(Mac の GPU で 36 秒)
TensorFlow 版自作の Transformer ブロック、1 エポック検証 0.9179
TensorFlow 版小さな BERT(4 層)を凍結して分類層だけ学習検証 0.7933
TensorFlow 版小さな BERT も含めて学習(教材のまま)検証 0.8245
TensorFlow 版同上、学習率のスケジュールの誤りを修正検証 0.8916

TensorFlow 版の数値は、「互換モードで動かす」で説明する Keras 2 系の tf-keras で動かしたものです。学習の条件も、評価に使ったデータ(テストか検証か)もそろっていないので、表の値は手法の優劣を表すものではありません。BERT を含めた学習は、学習率を少しずつ上げてから下げる「スケジュール」の計算が教材のままだと誤っていて、学習率がほとんど上がりません。直すと、検証の正解率は 0.8245 から 0.8916 に上がりました。

レッスン 19: 固有表現抽出(NER)

単語ごとにタグを付ける

チャットボットで「明日の東京の天気は?」と聞かれたら、意図(天気を知りたい)と、その中の具体的な値(明日、東京)を取り出す必要があります。後者のように、文中の人名・地名・組織名・日付などを見つけるのが 固有表現抽出(NER)です。

NER は、単語ごとにタグを付ける分類問題として解きます。複数の単語からなる固有表現を表すために、BIO 形式 を使います。固有表現の最初の単語に B-(Begin)、続く単語に I-(Inside)、それ以外に O(Outside)を付けます。

単語JohnSmithwenttoParis
タグB-perI-perOOB-geo

per は人名(person)、geo は地名(geographical)を表します。

ノートブックは、Kaggle の「Annotated Corpus for Named Entity Recognition」(タグを付けた文章を集めたデータ。約 4.8 万文、17 種類のタグ)を、埋め込み → 2 層の双方向 LSTM → 単語ごとの分類 というネットワークで学習します。レッスン 17 の「多対多」の RNN です。

NER の正解率の見方

1 エポックで正解率は 0.9851 になり、テストの文「John Smith went to Paris」の人名・地名も正しく取れました。ただし、この正解率は見かけほど高くありません。

「全部 O」と答えるだけで、正解率は 0.968 になります。筆者がデータの 10% を学習から外して評価すると、固有表現の単位で数えた F1 値は 0.775 でした。F1 値は、適合率(見つけたもののうち正しかった割合)と再現率(正解のうち見つけられた割合)の調和平均です。NER の評価には、単語単位の正解率ではなく、固有表現単位の F1 値を使うのが一般的です。

レッスン 20: 大規模言語モデル(GPT)

GPT

GPT(Generative Pre-trained Transformer)は、Transformer で 次の単語を予測する 言語モデルです。GPT-2 の論文は、大量の文章で事前学習するだけで、追加の学習なしに(ゼロショット)、あるいは例をいくつか見せるだけで(少数ショット)、さまざまなタスクを解けることを示しました。

言語モデルは、文の単語列 W の確率 P(W) を、前の単語から次の単語の条件付き確率を掛け合わせて計算します。その良さは パープレキシティ(1/P(W) の N 乗根、N は単語数)で測ります。おおよそ、モデルが次の単語を平均で何個の候補の中から迷っているかを表し、小さいほど文章をよく予測できています。

教材は、GPT-2(15 億パラメータ)、GPT-3(1,750 億パラメータ)と、Azure OpenAI や OpenAI API での利用、そして プロンプトエンジニアリング(解かせたいタスクが伝わるようにプロンプトを工夫すること)を紹介します。GPT-4 を「100 兆パラメータ」とする表の誤りについては、全体の記事 で書いたとおりです。OpenAI の GPT-4 Technical Report は、モデルの大きさを公表していません。

ノートブックの GPT は GPT-1

ノートブックは、Hugging Face Transformers の pipeline('text-generation', model='openai-gpt') で文章を生成します。この openai-gpt は、レッスン 20 の README の表に載っていない最初の GPT(GPT-1、約 1.2 億パラメータ)です。

# ノートブックのセルから抜粋。generator は pipeline('text-generation', model='openai-gpt') で作ったもの
generator("I love when you say this -> Positive\nI have myself -> Negative\nThis is awful for you to say this ->", max_length=40, num_return_sequences=5)

少数ショットで感情を判定させる例ですが、GPT-1 では Positive と Negative が入り混じった答えになりました。翻訳や類義語の例もうまくいかず、ノートブックに残っている出力も同じです。プロンプトだけでタスクを解けるのは、GPT-3 以降の大きなモデルになってからの話です。教材の LLM の章が GPT-2 / GPT-3 の時代で止まっていることは、全体の記事 でも触れました。

ノートブックを今の環境で動かすときの注意

このパートのノートブックは、2022 年に作られたものがほとんどで、Keras 3 や torchtext の開発終了には対応していません。2026 年 9〜10 月時点のライブラリで動かすと、次の箇所で止まったり、黙っておかしな動きをしたりしました。

日本語版のフォルダからは動かない

日本語版のフォルダには、翻訳されたノートブックがあります。コードのセルは英語版と同じです。ただし、PyTorch 版のノートブックが読み込む補助モジュール torchnlp.py が日本語版のフォルダにはなく、次のエラーで止まります。

ModuleNotFoundError: No module named 'torchnlp'

前回のパートと同じく、ノートブックは英語版の lessons/ のフォルダで動かし、説明は日本語版で読むのが確実です。

torchtext が読み込めない(レッスン 13〜18 の PyTorch 版)

レッスン 13〜18 の PyTorch 版のノートブックは、どれも torchtext(PyTorch のテキスト処理用ライブラリ)で単語の分割・語彙の作成・AG News の読み込みを行っています。torchtext は 2024 年の 0.18.0 で開発を終えていて、今の PyTorch とは組み合わせられません。やっかいなのは、pip install torchtext は成功してしまうことです。読み込もうとして初めて、次のエラーで止まります。

OSError: Could not load this library: .../site-packages/torchtext/lib/libtorchtext.so

内部の C++ ライブラリが、古い PyTorch(2.3 前後)に合わせてビルドされているためです。公式の解決策はありません。筆者は、ノートブックが使う 4 つの機能だけを作り直した小さなモジュールで動かしました。対象は get_tokenizer('basic_english')、ngrams_iterator、vocab、AG_NEWS で、中身は torchtext 0.18 のソースから Python の部分を写したものです(このモジュールは公開していません)。AG News は torchtext と同じ CSV ファイルを読み込み、ノートブックに記録された語彙の大きさや単語の番号がすべて一致することを確かめています。

自分で書き直すなら、単語の分割は正規表現、語彙は Python の dict、データは Hugging Face の datasets か CSV の直接読み込みで置き換えられます。

requirements ファイルではインストールできない

パートのフォルダにある requirements-pytorch.txt と requirements-tf.txt は、どちらもそのままではインストールできません。

ファイルは参考程度にして、必要なライブラリを個別に入れるのが現実的です。

Keras 3 で変わったこと

TensorFlow 版のノートブックは、Keras 3 で次のエラーが出ます。前回のパートと共通のものも多くあります。

エラー対処
module 'keras._tf_keras.keras.layers' has no attribute 'experimental'keras.layers.experimental.preprocessing.TextVectorization を keras.layers.TextVectorization にする
Cast string to float is not supportedTextVectorization(..., input_shape=(1,)) の input_shape をやめ、モデルの最初に keras.Input(shape=(1,), dtype=tf.string) を置く
A KerasTensor cannot be used as input to a TensorFlow functionモデルの中の tf.one_hot や tf.reduce_sum を keras.ops.one_hot や keras.ops.sum にする
Argument(s) not recognized: {'lr': 0.1}SGD(learning_rate=0.1) にする(レッスン 15)
Cannot take the length of shape with unknown ranktf.py_function が返したテンソルに set_shape で形を設定する(レッスン 17)
Layer TransformerBlock has multiple required positional arguments: [inputs, training]def call(self, inputs, training=None) のように training に既定値を付ける(レッスン 18)

Cast string to float is not supported のエラーは、文字列を受け取る層の前に、Keras 3 が自動で小数の入力を作ってしまうために起きます。次のように書き換えると動きました。

model = keras.models.Sequential([
    keras.Input(shape=(1,), dtype=tf.string),
    vectorizer,
    # 以下、ノートブックの層はそのまま
])

Keras 3 で正解率が下がるセル(レッスン 14)

エラーは出ないのに、Keras 3 だと結果が悪くなるセルもありました。レッスン 14 の TensorFlow 版の最初の分類(最適化手法を指定せず、既定の RMSprop を使うセル)は、ノートブックの記録では検証の正解率 0.8642 ですが、Keras 3 では 0.6874 でした。同じコードを互換モード(後述)で動かすと 0.8629 で、記録とほぼ同じです。

調べると、Keras 3 の RMSprop と Adam では、ミニバッチの中で同じ単語が n 回出てくると、その単語の埋め込みの更新量が √n 倍になっていました(n = 100 で 10 倍)。「the」のような頻出の単語ほど大きく動いてしまうわけです。原因は、Keras 3 のソースを読んだかぎりでは、同じ行への勾配を足し合わせる前に 1 つずつ二乗しているためと推測しています。optimizer='adam' を指定するとこのセルは 0.8728 になりましたが、Adam も同じ問題を持つので、根本的な解決ではありません。

互換モードで動かす(レッスン 18 の TensorFlow 版)

レッスン 18 の TensorFlow 版は、TensorFlow Hub の BERT、TensorFlow Model Garden(official パッケージ)、Hugging Face の TensorFlow 版 BERT と、Keras 3 に対応していない部品を多く使っています。

いちばん手早いのは、Keras 2 系を別パッケージにした tf-keras を入れて、TensorFlow を読み込む前に環境変数 TF_USE_LEGACY_KERAS=1 を設定する方法です。手順は次のとおりです。

  1. tf-keras と、TensorFlow Hub の BERT が使うパッケージを入れる(筆者の環境では tf-keras 2.21.0、tensorflow-text 2.21.1、tensorflow-hub 0.16.1)
  2. ノートブックの最初のセルで、TensorFlow を読み込む前に環境変数を設定する
  3. TensorFlow Hub の読み込みで pkg_resources がないというエラーが出たら、setuptools を 82 未満にする(82 で pkg_resources が削除された)
  4. Hugging Face の部分を動かすなら、Transformers 4 系を入れる(筆者は 4.57.6)
pip install tf-keras tensorflow-text tensorflow-hub
import os
os.environ["TF_USE_LEGACY_KERAS"] = "1"
import tensorflow as tf

この互換モードでは、レッスン 18 の自作 Transformer のセルは書き換えなしで動きました。official パッケージだけは入らないので、筆者はノートブックが使う学習率のスケジュールの部分を写した代わりのモジュールで動かしました。

pandas 2 で「None」が欠損値になる(レッスン 19)

NER のノートブックは、語彙を作るセルで次のエラーになります。

AttributeError: 'float' object has no attribute 'lower'

pandas 2.0 で、CSV を読むときに欠損値とみなす文字列に「None」が加わりました。コーパスに英単語の「None」が 10 回出てくるため、それが欠損値(小数の NaN)になってしまいます。次のように、欠損値として扱う文字列を指定し直すと動きました。

df = pd.read_csv('ner_dataset.csv', encoding='unicode-escape', keep_default_na=False, na_values={'Sentence #': ['']})

keep_default_na=False だけにすると、文の区切りを判定している列(Sentence #)の空欄まで欠損値でなくなり、文の区切りが壊れます。なお、Kaggle のデータのダウンロードにはログインが必要なので、筆者は Hugging Face にある同じデータの複製(約 4.8 万文・104 万 8,575 行)から CSV を作り直しました。

pipeline が max_length を無視する(レッスン 20)

GPT のノートブックは max_length=40 などで生成の長さを指定していますが、今の Transformers では次の警告が出て、248〜277 トークンもの長い文章が生成されます(警告は max_length=100 のセルのもの)。

Both `max_new_tokens` (=256) and `max_length`(=100) seem to have been set. `max_new_tokens` will take precedence.

Transformers 4.52 以降、文章生成の pipeline には「新しく 256 トークンまで生成する」という既定の設定があり、そちらが優先されるためです。max_new_tokens=None を一緒に渡すと、指定どおりの長さになりました。

generator("People who liked the movie The Matrix also liked ", max_length=40, max_new_tokens=None, num_return_sequences=5)

その他

教材を読むときの補足

教材そのものの誤りをまとめます。日本語版は英語版の誤りもそのまま翻訳しているので、特に断りがなければ英語版・日本語版に共通です。

結果を変えてしまうコードの誤り

エラーにならないので気づきにくく、いちばん注意が要るものです。

記述の誤り

リンクとファイルの問題

レッスンの進め方

各レッスンに講義前・講義後のクイズが付いています。クイズは英語版のみです。

レッスンクイズラボ・課題
13 テキストの表現講義前 / 講義後自分で選んだデータセット(例: UFO の目撃情報)でノートブックを動かし直す
14 埋め込み講義前 / 講義後別の種類の文章(例: ビートルズの歌詞)で同じことをする
15 言語モデル講義前 / 講義後好きな本(『不思議の国のアリス』など)で skip-gram の埋め込みを学習する
16 RNN講義前 / 講義後自分のデータセット(例: 天気に関するツイート)で分類する
17 生成ネットワーク講義前 / 講義後好きな本で、単語単位の文章生成器を作る
18 Transformer講義前 / 講義後Hugging Face の学習用スクリプトで、自分のデータセットを使って試す
19 固有表現抽出講義前 / 講義後医学論文のデータ(BC5CDR)から病名と薬品名を抽出する。LSTM の後に PubMedBERT で解く
20 大規模言語モデル講義前 / 講義後なし

レッスン 15 のラボは、前述のとおり、ノートブックの作り方のまま skip-gram に変えても、学習データが CBoW とまったく同じになります。2 つを本当に比べたいなら、CBoW を「周りの単語の埋め込みを平均して真ん中の単語を当てる」本来の形に書き直してから取り組むのがおすすめです。レッスン 19 のラボの BC5CDR は、ダウンロードに登録が必要です。筆者はラボを動かしていません。

まとめ

次のパート「VI. その他の AI 技術」では、ニューラルネットワーク以外の手法として、遺伝的アルゴリズム、深層強化学習、マルチエージェントシステムを扱います(解説: 遺伝的アルゴリズム・強化学習・マルチエージェントをやさしく解説 — Microsoft AI-For-Beginners レッスン 21〜23)。



前の記事
遺伝的アルゴリズム・強化学習・マルチエージェントをやさしく解説 — Microsoft AI-For-Beginners レッスン 21〜23
次の記事
コンピュータビジョンの基礎をやさしく解説 — Microsoft AI-For-Beginners レッスン 06〜12