🌐 Update translations via Co-op Translator
This commit is contained in:
parent
58d0e77a4b
commit
3ac667ea23
|
|
@ -1,8 +1,8 @@
|
|||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "f3a6b0ddf7e6e3f33b2a543baf086dc9",
|
||||
"translation_date": "2025-08-24T21:01:21+00:00",
|
||||
"original_hash": "07191303b7ea2aff1d47e2b0fe4bb862",
|
||||
"translation_date": "2025-08-30T08:42:33+00:00",
|
||||
"source_file": "README.md",
|
||||
"language_code": "ja"
|
||||
}
|
||||
|
|
@ -21,109 +21,120 @@ CO_OP_TRANSLATOR_METADATA:
|
|||
|
||||
[](https://discord.gg/zxKYvhSnVp?WT.mc_id=academic-000002-leestott)
|
||||
|
||||
# 初心者のための人工知能 - カリキュラム
|
||||
# 初心者のための人工知能 - カリキュラム
|
||||
|
||||
| ](./lessons/sketchnotes/ai-overview.png)|
|
||||
|:---:|
|
||||
| 初心者のためのAI - _スケッチノート by [@girlie_mac](https://twitter.com/girlie_mac)_ |
|
||||
||
|
||||
|:---:|
|
||||
| 初心者のためのAI - _スケッチノート: [@girlie_mac](https://twitter.com/girlie_mac)_ |
|
||||
|
||||
**人工知能** (AI) の世界を探求する12週間、24レッスンのカリキュラムです! 実践的なレッスン、クイズ、ラボが含まれています。このカリキュラムは初心者向けで、TensorFlowやPyTorchなどのツール、そしてAIの倫理についてもカバーしています。
|
||||
**人工知能**(AI)の世界を、12週間・24レッスンのカリキュラムで探求しましょう! 実践的なレッスン、クイズ、ラボが含まれています。このカリキュラムは初心者向けで、TensorFlowやPyTorchなどのツール、そしてAI倫理についても扱います。
|
||||
|
||||
## 学べること
|
||||
### 🌐 多言語対応
|
||||
|
||||
**[コースのマインドマップ](http://soshnikov.com/courses/ai-for-beginners/mindmap.html)**
|
||||
#### GitHub Actionによるサポート(自動更新・常に最新)
|
||||
|
||||
このカリキュラムでは以下を学びます:
|
||||
[フランス語](../fr/README.md) | [スペイン語](../es/README.md) | [ドイツ語](../de/README.md) | [ロシア語](../ru/README.md) | [アラビア語](../ar/README.md) | [ペルシャ語(ファルシー)](../fa/README.md) | [ウルドゥー語](../ur/README.md) | [中国語(簡体字)](../zh/README.md) | [中国語(繁体字、マカオ)](../mo/README.md) | [中国語(繁体字、香港)](../hk/README.md) | [中国語(繁体字、台湾)](../tw/README.md) | [日本語](./README.md) | [韓国語](../ko/README.md) | [ヒンディー語](../hi/README.md) | [ベンガル語](../bn/README.md) | [マラーティー語](../mr/README.md) | [ネパール語](../ne/README.md) | [パンジャブ語(グルムキー)](../pa/README.md) | [ポルトガル語(ポルトガル)](../pt/README.md) | [ポルトガル語(ブラジル)](../br/README.md) | [イタリア語](../it/README.md) | [ポーランド語](../pl/README.md) | [トルコ語](../tr/README.md) | [ギリシャ語](../el/README.md) | [タイ語](../th/README.md) | [スウェーデン語](../sv/README.md) | [デンマーク語](../da/README.md) | [ノルウェー語](../no/README.md) | [フィンランド語](../fi/README.md) | [オランダ語](../nl/README.md) | [ヘブライ語](../he/README.md) | [ベトナム語](../vi/README.md) | [インドネシア語](../id/README.md) | [マレー語](../ms/README.md) | [タガログ語(フィリピン語)](../tl/README.md) | [スワヒリ語](../sw/README.md) | [ハンガリー語](../hu/README.md) | [チェコ語](../cs/README.md) | [スロバキア語](../sk/README.md) | [ルーマニア語](../ro/README.md) | [ブルガリア語](../bg/README.md) | [セルビア語(キリル文字)](../sr/README.md) | [クロアチア語](../hr/README.md) | [スロベニア語](../sl/README.md) | [ウクライナ語](../uk/README.md) | [ビルマ語(ミャンマー)](../my/README.md)
|
||||
|
||||
* **知識表現**や推論を含む「古き良き」シンボリックアプローチ([GOFAI](https://en.wikipedia.org/wiki/Symbolic_artificial_intelligence))など、人工知能へのさまざまなアプローチ。
|
||||
* 現代AIの中心である**ニューラルネットワーク**と**ディープラーニング**。これらの重要なトピックの概念を、[TensorFlow](http://Tensorflow.org)や[PyTorch](http://pytorch.org)といった人気のフレームワークを使ったコードで説明します。
|
||||
* 画像やテキストを扱うための**ニューラルアーキテクチャ**。最新のモデルをカバーしますが、最先端の内容には少し欠けるかもしれません。
|
||||
* **遺伝的アルゴリズム**や**マルチエージェントシステム**など、あまり一般的でないAIアプローチ。
|
||||
**追加の翻訳を希望する場合は、[こちら](https://github.com/Azure/co-op-translator/blob/main/getting_started/supported-languages.md)に記載されている言語をご確認ください。**
|
||||
|
||||
このカリキュラムで扱わない内容:
|
||||
## コミュニティに参加する
|
||||
[](https://discord.gg/kzRShWzttr)
|
||||
|
||||
> [このコースの追加リソースはMicrosoft Learnコレクションで見つけることができます](https://learn.microsoft.com/en-us/collections/7w28iy2xrqzdj0?WT.mc_id=academic-77998-bethanycheum)
|
||||
## 学べる内容
|
||||
|
||||
* **ビジネスにおけるAIの活用事例**。Microsoft Learnの[Introduction to AI for business users](https://docs.microsoft.com/learn/paths/introduction-ai-for-business-users/?WT.mc_id=academic-77998-bethanycheum)学習パスや、[INSEAD](https://www.insead.edu/)と協力して開発された[AI Business School](https://www.microsoft.com/ai/ai-business-school/?WT.mc_id=academic-77998-bethanycheum)を検討してください。
|
||||
* **古典的な機械学習**。これは[Machine Learning for Beginners Curriculum](http://github.com/Microsoft/ML-for-Beginners)で詳しく説明されています。
|
||||
* **[Cognitive Services](https://azure.microsoft.com/services/cognitive-services/?WT.mc_id=academic-77998-bethanycheum)**を使用して構築された実践的なAIアプリケーション。これについては、Microsoft Learnの[vision](https://docs.microsoft.com/learn/paths/create-computer-vision-solutions-azure-cognitive-services/?WT.mc_id=academic-77998-bethanycheum)、[natural language processing](https://docs.microsoft.com/learn/paths/explore-natural-language-processing/?WT.mc_id=academic-77998-bethanycheum)、**[Generative AI with Azure OpenAI Service](https://learn.microsoft.com/en-us/training/paths/develop-ai-solutions-azure-openai/?WT.mc_id=academic-77998-bethanycheum)**などのモジュールから始めることをお勧めします。
|
||||
* **クラウドフレームワーク**(例:[Azure Machine Learning](https://azure.microsoft.com/services/machine-learning/?WT.mc_id=academic-77998-bethanycheum)、[Microsoft Fabric](https://learn.microsoft.com/en-us/training/paths/get-started-fabric/?WT.mc_id=academic-77998-bethanycheum)、[Azure Databricks](https://docs.microsoft.com/learn/paths/data-engineer-azure-databricks?WT.mc_id=academic-77998-bethanycheum))。[Build and operate machine learning solutions with Azure Machine Learning](https://docs.microsoft.com/learn/paths/build-ai-solutions-with-azure-ml-service/?WT.mc_id=academic-77998-bethanycheum)や[Build and Operate Machine Learning Solutions with Azure Databricks](https://docs.microsoft.com/learn/paths/build-operate-machine-learning-solutions-azure-databricks/?WT.mc_id=academic-77998-bethanycheum)学習パスを利用してください。
|
||||
* **会話型AI**や**チャットボット**。これには[Create conversational AI solutions](https://docs.microsoft.com/learn/paths/create-conversational-ai-solutions/?WT.mc_id=academic-77998-bethanycheum)学習パスがあり、詳細については[このブログ記事](https://soshnikov.com/azure/hello-bot-conversational-ai-on-microsoft-platform/)を参照してください。
|
||||
* ディープラーニングの**高度な数学**。これについては、Ian Goodfellow、Yoshua Bengio、Aaron Courvilleによる[Deep Learning](https://www.amazon.com/Deep-Learning-Adaptive-Computation-Machine/dp/0262035618)をお勧めします。この本は[https://www.deeplearningbook.org/](https://www.deeplearningbook.org/)でもオンラインで利用可能です。
|
||||
**[コースのマインドマップ](http://soshnikov.com/courses/ai-for-beginners/mindmap.html)**
|
||||
|
||||
クラウドにおけるAIの入門としては、[Get started with artificial intelligence on Azure](https://docs.microsoft.com/learn/paths/get-started-with-artificial-intelligence-on-azure/?WT.mc_id=academic-77998-bethanycheum)学習パスを検討してください。
|
||||
このカリキュラムでは以下を学びます:
|
||||
|
||||
# コンテンツ
|
||||
* **人工知能**のさまざまなアプローチ。特に、**知識表現**と推論を用いた「古典的な」シンボリックアプローチ([GOFAI](https://en.wikipedia.org/wiki/Symbolic_artificial_intelligence))について。
|
||||
* 現代AIの中核をなす**ニューラルネットワーク**と**ディープラーニング**。これらの重要なトピックの概念を、[TensorFlow](http://Tensorflow.org)や[PyTorch](http://pytorch.org)といった人気のフレームワークを使って説明します。
|
||||
* 画像やテキストを扱うための**ニューラルアーキテクチャ**。最近のモデルを取り上げますが、最先端の内容には少し欠けるかもしれません。
|
||||
* あまり知られていないAIアプローチ、例えば**遺伝的アルゴリズム**や**マルチエージェントシステム**。
|
||||
|
||||
| | レッスンリンク | PyTorch/Keras/TensorFlow | ラボ |
|
||||
| :-: | :------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------: | ------------------------------------------------------------------------------ |
|
||||
| 0 | [コースセットアップ](./lessons/0-course-setup/setup.md) | [開発環境のセットアップ](./lessons/0-course-setup/how-to-run.md) | |
|
||||
| I | [**AIの概要**](./lessons/1-Intro/README.md) | | |
|
||||
| 01 | [AIの概要と歴史](./lessons/1-Intro/README.md) | - | - |
|
||||
| II | **シンボリックAI** |
|
||||
| 02 | [知識表現とエキスパートシステム](./lessons/2-Symbolic/README.md) | [エキスパートシステム](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/2-Symbolic/Animals.ipynb) / [オントロジー](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/2-Symbolic/FamilyOntology.ipynb) /[概念グラフ](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/2-Symbolic/MSConceptGraph.ipynb) | |
|
||||
| III | [**ニューラルネットワークの概要**](./lessons/3-NeuralNetworks/README.md) |||
|
||||
| 03 | [パーセプトロン](./lessons/3-NeuralNetworks/03-Perceptron/README.md) | [ノートブック](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/3-NeuralNetworks/03-Perceptron/Perceptron.ipynb) | [ラボ](./lessons/3-NeuralNetworks/03-Perceptron/lab/README.md) |
|
||||
| 04 | [多層パーセプトロンと独自フレームワークの作成](./lessons/3-NeuralNetworks/04-OwnFramework/README.md) | [ノートブック](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/3-NeuralNetworks/04-OwnFramework/OwnFramework.ipynb) | [ラボ](./lessons/3-NeuralNetworks/04-OwnFramework/lab/README.md) |
|
||||
| 05 | [フレームワークの概要 (PyTorch/TensorFlow) と過学習](./lessons/3-NeuralNetworks/05-Frameworks/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/3-NeuralNetworks/05-Frameworks/IntroPyTorch.ipynb) / [Keras](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/3-NeuralNetworks/05-Frameworks/IntroKeras.ipynb) / [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/3-NeuralNetworks/05-Frameworks/IntroKerasTF.ipynb) | [ラボ](./lessons/3-NeuralNetworks/05-Frameworks/lab/README.md) |
|
||||
| IV | [**コンピュータビジョン**](./lessons/4-ComputerVision/README.md) | [PyTorch](https://docs.microsoft.com/learn/modules/intro-computer-vision-pytorch/?WT.mc_id=academic-77998-cacaste) / [TensorFlow](https://docs.microsoft.com/learn/modules/intro-computer-vision-TensorFlow/?WT.mc_id=academic-77998-cacaste)| [Microsoft Azureでコンピュータビジョンを探求](https://learn.microsoft.com/en-us/collections/7w28iy2xrqzdj0?WT.mc_id=academic-77998-bethanycheum) |
|
||||
| 06 | [コンピュータビジョンの概要。OpenCV](./lessons/4-ComputerVision/06-IntroCV/README.md) | [ノートブック](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/06-IntroCV/OpenCV.ipynb) | [ラボ](./lessons/4-ComputerVision/06-IntroCV/lab/README.md) |
|
||||
| 07 | [畳み込みニューラルネットワーク](./lessons/4-ComputerVision/07-ConvNets/README.md) & [CNNアーキテクチャ](./lessons/4-ComputerVision/07-ConvNets/CNN_Architectures.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/07-ConvNets/ConvNetsPyTorch.ipynb) /[TensorFlow](https://microsoft.github.io/AI-For-Beginners/lessons/4-ComputerVision/07-ConvNets/ConvNetsTF.ipynb) | [ラボ](./lessons/4-ComputerVision/07-ConvNets/lab/README.md) |
|
||||
| 08 | [事前学習済みネットワークと転移学習](./lessons/4-ComputerVision/08-TransferLearning/README.md) および [トレーニングのコツ](./lessons/4-ComputerVision/08-TransferLearning/TrainingTricks.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/08-TransferLearning/TransferLearningPyTorch.ipynb) / [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/3-NeuralNetworks/05-Frameworks/IntroKerasTF.ipynb) | [ラボ](./lessons/4-ComputerVision/08-TransferLearning/lab/README.md) |
|
||||
| 09 | [オートエンコーダーとVAE](./lessons/4-ComputerVision/09-Autoencoders/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/09-Autoencoders/AutoEncodersPyTorch.ipynb) / [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/09-Autoencoders/AutoencodersTF.ipynb) | |
|
||||
| 10 | [生成的敵対ネットワーク(GAN)と芸術的スタイル転送](./lessons/4-ComputerVision/10-GANs/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/10-GANs/GANPyTorch.ipynb) / [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/10-GANs/GANTF.ipynb) | |
|
||||
| 11 | [物体検出](./lessons/4-ComputerVision/11-ObjectDetection/README.md) | [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/11-ObjectDetection/ObjectDetection.ipynb) | [ラボ](./lessons/4-ComputerVision/11-ObjectDetection/lab/README.md) |
|
||||
| 12 | [セマンティックセグメンテーション. U-Net](./lessons/4-ComputerVision/12-Segmentation/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/12-Segmentation/SemanticSegmentationPytorch.ipynb) / [TensorFlow](../../(https:/github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/12-Segmentation/SemanticSegmentationTF.ipynb)) | |
|
||||
| V | [**自然言語処理**](./lessons/5-NLP/README.md) | [PyTorch](https://docs.microsoft.com/learn/modules/intro-natural-language-processing-pytorch/?WT.mc_id=academic-77998-cacaste) /[TensorFlow](https://docs.microsoft.com/learn/modules/intro-natural-language-processing-TensorFlow/?WT.mc_id=academic-77998-cacaste) | [Microsoft Azureで自然言語処理を探求する](https://learn.microsoft.com/en-us/collections/7w28iy2xrqzdj0?WT.mc_id=academic-77998-bethanycheum)|
|
||||
| 13 | [テキスト表現. Bow/TF-IDF](./lessons/5-NLP/13-TextRep/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/13-TextRep/TextRepresentationPyTorch.ipynb) / [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/13-TextRep/TextRepresentationTF.ipynb) | |
|
||||
| 14 | [セマンティック単語埋め込み. Word2VecとGloVe](./lessons/5-NLP/14-Embeddings/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/14-Embeddings/EmbeddingsPyTorch.ipynb) / [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/14-Embeddings/EmbeddingsTF.ipynb) | |
|
||||
| 15 | [言語モデリング. 独自の埋め込みをトレーニングする](./lessons/5-NLP/15-LanguageModeling/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/15-LanguageModeling/CBoW-PyTorch.ipynb) / [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/15-LanguageModeling/CBoW-TF.ipynb) | [ラボ](./lessons/5-NLP/15-LanguageModeling/lab/README.md) |
|
||||
| 16 | [リカレントニューラルネットワーク](./lessons/5-NLP/16-RNN/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/16-RNN/RNNPyTorch.ipynb) / [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/16-RNN/RNNTF.ipynb) | |
|
||||
| 17 | [生成的リカレントネットワーク](./lessons/5-NLP/17-GenerativeNetworks/README.md) | [PyTorch](https://microsoft.github.io/AI-For-Beginners/lessons/5-NLP/17-GenerativeNetworks/GenerativePyTorch.md) / [TensorFlow](https://microsoft.github.io/AI-For-Beginners/lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.md) | [ラボ](./lessons/5-NLP/17-GenerativeNetworks/lab/README.md) |
|
||||
| 18 | [トランスフォーマー. BERT.](./lessons/5-NLP/18-Transformers/READMEtransformers.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/18-Transformers/TransformersPyTorch.ipynb) /[TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/18-Transformers/TransformersTF.ipynb) | |
|
||||
| 19 | [固有表現認識](./lessons/5-NLP/19-NER/README.md) | [TensorFlow](https://microsoft.github.io/AI-For-Beginners/lessons/5-NLP/19-NER/NER-TF.ipynb) | [ラボ](./lessons/5-NLP/19-NER/lab/README.md) |
|
||||
| 20 | [大規模言語モデル、プロンプトプログラミング、少数ショットタスク](./lessons/5-NLP/20-LangModels/READMELargeLang.md) | [PyTorch](https://microsoft.github.io/AI-For-Beginners/lessons/5-NLP/20-LangModels/GPT-PyTorch.ipynb) | |
|
||||
このカリキュラムで扱わない内容:
|
||||
|
||||
> [このコースの追加リソースはMicrosoft Learnコレクションでご覧いただけます](https://learn.microsoft.com/en-us/collections/7w28iy2xrqzdj0?WT.mc_id=academic-77998-bethanycheum)
|
||||
|
||||
* **ビジネスにおけるAIの活用事例**。Microsoft Learnの[ビジネスユーザー向けAI入門](https://docs.microsoft.com/learn/paths/introduction-ai-for-business-users/?WT.mc_id=academic-77998-bethanycheum)学習パスや、[INSEAD](https://www.insead.edu/)と共同開発された[AIビジネススクール](https://www.microsoft.com/ai/ai-business-school/?WT.mc_id=academic-77998-bethanycheum)を受講することをお勧めします。
|
||||
* **クラシック機械学習**。これは[初心者のための機械学習カリキュラム](http://github.com/Microsoft/ML-for-Beginners)で詳しく説明されています。
|
||||
* **[Cognitive Services](https://azure.microsoft.com/services/cognitive-services/?WT.mc_id=academic-77998-bethanycheum)**を使用した実践的なAIアプリケーション。これについては、Microsoft Learnの[ビジョン](https://docs.microsoft.com/learn/paths/create-computer-vision-solutions-azure-cognitive-services/?WT.mc_id=academic-77998-bethanycheum)、[自然言語処理](https://docs.microsoft.com/learn/paths/explore-natural-language-processing/?WT.mc_id=academic-77998-bethanycheum)、**[Azure OpenAI Serviceを使った生成AI](https://learn.microsoft.com/en-us/training/paths/develop-ai-solutions-azure-openai/?WT.mc_id=academic-77998-bethanycheum)**などのモジュールから始めることをお勧めします。
|
||||
* 特定のML**クラウドフレームワーク**(例:[Azure Machine Learning](https://azure.microsoft.com/services/machine-learning/?WT.mc_id=academic-77998-bethanycheum)、[Microsoft Fabric](https://learn.microsoft.com/en-us/training/paths/get-started-fabric/?WT.mc_id=academic-77998-bethanycheum)、[Azure Databricks](https://docs.microsoft.com/learn/paths/data-engineer-azure-databricks?WT.mc_id=academic-77998-bethanycheum))。[Azure Machine Learningを使った機械学習ソリューションの構築と運用](https://docs.microsoft.com/learn/paths/build-ai-solutions-with-azure-ml-service/?WT.mc_id=academic-77998-bethanycheum)や[Azure Databricksを使った機械学習ソリューションの構築と運用](https://docs.microsoft.com/learn/paths/build-operate-machine-learning-solutions-azure-databricks/?WT.mc_id=academic-77998-bethanycheum)学習パスを利用してください。
|
||||
* **会話型AI**や**チャットボット**。これについては、[会話型AIソリューションの作成](https://docs.microsoft.com/learn/paths/create-conversational-ai-solutions/?WT.mc_id=academic-77998-bethanycheum)学習パスや、[このブログ記事](https://soshnikov.com/azure/hello-bot-conversational-ai-on-microsoft-platform/)を参照してください。
|
||||
* **ディープラーニングの深い数学的背景**。これについては、Ian Goodfellow、Yoshua Bengio、Aaron Courvilleによる[Deep Learning](https://www.amazon.com/Deep-Learning-Adaptive-Computation-Machine/dp/0262035618)をお勧めします。この本は[https://www.deeplearningbook.org/](https://www.deeplearningbook.org/)でもオンラインで利用可能です。
|
||||
|
||||
クラウドにおけるAIの入門としては、[Azureでの人工知能の入門](https://docs.microsoft.com/learn/paths/get-started-with-artificial-intelligence-on-azure/?WT.mc_id=academic-77998-bethanycheum)学習パスを受講することを検討してください。
|
||||
|
||||
# コンテンツ
|
||||
|
||||
| | レッスンリンク | PyTorch/Keras/TensorFlow | ラボ |
|
||||
| :-: | :------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------: | ------------------------------------------------------------------------------ |
|
||||
| 0 | [コースセットアップ](./lessons/0-course-setup/setup.md) | [開発環境のセットアップ](./lessons/0-course-setup/how-to-run.md) | |
|
||||
| I | [**AIの導入**](./lessons/1-Intro/README.md) | | |
|
||||
| 01 | [AIの導入と歴史](./lessons/1-Intro/README.md) | - | - |
|
||||
| II | **シンボリックAI** |
|
||||
| 02 | [知識表現とエキスパートシステム](./lessons/2-Symbolic/README.md) | [エキスパートシステム](./lessons/2-Symbolic/Animals.ipynb) / [オントロジー](./lessons/2-Symbolic/FamilyOntology.ipynb) /[概念グラフ](./lessons/2-Symbolic/MSConceptGraph.ipynb) | |
|
||||
| III | [**ニューラルネットワークの導入**](./lessons/3-NeuralNetworks/README.md) |||
|
||||
| 03 | [パーセプトロン](./lessons/3-NeuralNetworks/03-Perceptron/README.md) | [ノートブック](./lessons/3-NeuralNetworks/03-Perceptron/Perceptron.ipynb) | [ラボ](./lessons/3-NeuralNetworks/03-Perceptron/lab/README.md) |
|
||||
| 04 | [多層パーセプトロンと独自フレームワークの作成](./lessons/3-NeuralNetworks/04-OwnFramework/README.md) | [ノートブック](./lessons/3-NeuralNetworks/04-OwnFramework/OwnFramework.ipynb) | [ラボ](./lessons/3-NeuralNetworks/04-OwnFramework/lab/README.md) |
|
||||
| 05 | [フレームワークの紹介 (PyTorch/TensorFlow) と過学習](./lessons/3-NeuralNetworks/05-Frameworks/README.md) | [PyTorch](./lessons/3-NeuralNetworks/05-Frameworks/IntroPyTorch.ipynb) / [Keras](./lessons/3-NeuralNetworks/05-Frameworks/IntroKeras.ipynb) / [TensorFlow](./lessons/3-NeuralNetworks/05-Frameworks/IntroKerasTF.ipynb) | [Lab](./lessons/3-NeuralNetworks/05-Frameworks/lab/README.md) |
|
||||
| IV | [**コンピュータビジョン**](./lessons/4-ComputerVision/README.md) | [PyTorch](https://docs.microsoft.com/learn/modules/intro-computer-vision-pytorch/?WT.mc_id=academic-77998-cacaste) / [TensorFlow](https://docs.microsoft.com/learn/modules/intro-computer-vision-TensorFlow/?WT.mc_id=academic-77998-cacaste)| [Microsoft Azureでコンピュータビジョンを探求](https://learn.microsoft.com/en-us/collections/7w28iy2xrqzdj0?WT.mc_id=academic-77998-bethanycheum) |
|
||||
| 06 | [コンピュータビジョンの紹介. OpenCV](./lessons/4-ComputerVision/06-IntroCV/README.md) | [Notebook](./lessons/4-ComputerVision/06-IntroCV/OpenCV.ipynb) | [Lab](./lessons/4-ComputerVision/06-IntroCV/lab/README.md) |
|
||||
| 07 | [畳み込みニューラルネットワーク (CNN)](./lessons/4-ComputerVision/07-ConvNets/README.md) & [CNNアーキテクチャ](./lessons/4-ComputerVision/07-ConvNets/CNN_Architectures.md) | [PyTorch](./lessons/4-ComputerVision/07-ConvNets/ConvNetsPyTorch.ipynb) /[TensorFlow](./lessons/4-ComputerVision/07-ConvNets/ConvNetsTF.ipynb) | [Lab](./lessons/4-ComputerVision/07-ConvNets/lab/README.md) |
|
||||
| 08 | [事前学習済みネットワークと転移学習](./lessons/4-ComputerVision/08-TransferLearning/README.md) および [トレーニングのコツ](./lessons/4-ComputerVision/08-TransferLearning/TrainingTricks.md) | [PyTorch](./lessons/4-ComputerVision/08-TransferLearning/TransferLearningPyTorch.ipynb) / [TensorFlow](./lessons/3-NeuralNetworks/05-Frameworks/IntroKerasTF.ipynb) | [Lab](./lessons/4-ComputerVision/08-TransferLearning/lab/README.md) |
|
||||
| 09 | [オートエンコーダと変分オートエンコーダ (VAEs)](./lessons/4-ComputerVision/09-Autoencoders/README.md) | [PyTorch](./lessons/4-ComputerVision/09-Autoencoders/AutoEncodersPyTorch.ipynb) / [TensorFlow](./lessons/4-ComputerVision/09-Autoencoders/AutoencodersTF.ipynb) | |
|
||||
| 10 | [敵対的生成ネットワーク (GANs) と芸術的スタイル転送](./lessons/4-ComputerVision/10-GANs/README.md) | [PyTorch](./lessons/4-ComputerVision/10-GANs/GANPyTorch.ipynb) / [TensorFlow](./lessons/4-ComputerVision/10-GANs/GANTF.ipynb) | |
|
||||
| 11 | [物体検出](./lessons/4-ComputerVision/11-ObjectDetection/README.md) | [TensorFlow](./lessons/4-ComputerVision/11-ObjectDetection/ObjectDetection.ipynb) | [Lab](./lessons/4-ComputerVision/11-ObjectDetection/lab/README.md) |
|
||||
| 12 | [セマンティックセグメンテーション. U-Net](./lessons/4-ComputerVision/12-Segmentation/README.md) | [PyTorch](./lessons/4-ComputerVision/12-Segmentation/SemanticSegmentationPytorch.ipynb) / [TensorFlow](./lessons/4-ComputerVision/12-Segmentation/SemanticSegmentationTF.ipynb) | |
|
||||
| V | [**自然言語処理 (NLP)**](./lessons/5-NLP/README.md) | [PyTorch](https://docs.microsoft.com/learn/modules/intro-natural-language-processing-pytorch/?WT.mc_id=academic-77998-cacaste) /[TensorFlow](https://docs.microsoft.com/learn/modules/intro-natural-language-processing-TensorFlow/?WT.mc_id=academic-77998-cacaste) | [Microsoft Azureで自然言語処理を探求](https://learn.microsoft.com/en-us/collections/7w28iy2xrqzdj0?WT.mc_id=academic-77998-bethanycheum)|
|
||||
| 13 | [テキスト表現. BoW/TF-IDF](./lessons/5-NLP/13-TextRep/README.md) | [PyTorch](./lessons/5-NLP/13-TextRep/TextRepresentationPyTorch.ipynb) / [TensorFlow](./lessons/5-NLP/13-TextRep/TextRepresentationTF.ipynb) | |
|
||||
| 14 | [セマンティック単語埋め込み. Word2VecとGloVe](./lessons/5-NLP/14-Embeddings/README.md) | [PyTorch](./lessons/5-NLP/14-Embeddings/EmbeddingsPyTorch.ipynb) / [TensorFlow](./lessons/5-NLP/14-Embeddings/EmbeddingsTF.ipynb) | |
|
||||
| 15 | [言語モデリング. 独自の埋め込みのトレーニング](./lessons/5-NLP/15-LanguageModeling/README.md) | [PyTorch](./lessons/5-NLP/15-LanguageModeling/CBoW-PyTorch.ipynb) / [TensorFlow](./lessons/5-NLP/15-LanguageModeling/CBoW-TF.ipynb) | [Lab](./lessons/5-NLP/15-LanguageModeling/lab/README.md) |
|
||||
| 16 | [リカレントニューラルネットワーク (RNN)](./lessons/5-NLP/16-RNN/README.md) | [PyTorch](./lessons/5-NLP/16-RNN/RNNPyTorch.ipynb) / [TensorFlow](./lessons/5-NLP/16-RNN/RNNTF.ipynb) | |
|
||||
| 17 | [生成リカレントネットワーク](./lessons/5-NLP/17-GenerativeNetworks/README.md) | [PyTorch](./lessons/5-NLP/17-GenerativeNetworks/GenerativePyTorch.md) / [TensorFlow](./lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.md) | [Lab](./lessons/5-NLP/17-GenerativeNetworks/lab/README.md) |
|
||||
| 18 | [トランスフォーマー. BERT.](./lessons/5-NLP/18-Transformers/READMEtransformers.md) | [PyTorch](./lessons/5-NLP/18-Transformers/TransformersPyTorch.ipynb) /[TensorFlow](./lessons/5-NLP/18-Transformers/TransformersTF.ipynb) | |
|
||||
| 19 | [固有表現認識 (NER)](./lessons/5-NLP/19-NER/README.md) | [TensorFlow](./lessons/5-NLP/19-NER/NER-TF.ipynb) | [Lab](./lessons/5-NLP/19-NER/lab/README.md) |
|
||||
| 20 | [大規模言語モデル、プロンプトプログラミング、少数ショットタスク](./lessons/5-NLP/20-LangModels/READMELargeLang.md) | [PyTorch](./lessons/5-NLP/20-LangModels/GPT-PyTorch.ipynb) | |
|
||||
| VI | **その他のAI技術** || |
|
||||
| 21 | [遺伝的アルゴリズム](./lessons/6-Other/21-GeneticAlgorithms/README.md) | [ノートブック](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/6-Other/21-GeneticAlgorithms/Genetic.ipynb) | |
|
||||
| 22 | [深層強化学習](./lessons/6-Other/22-DeepRL/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/6-Other/22-DeepRL/CartPole-RL-PyTorch.ipynb) /[TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/6-Other/22-DeepRL/CartPole-RL-TF.ipynb) | [ラボ](./lessons/6-Other/22-DeepRL/lab/README.md) |
|
||||
| 21 | [遺伝的アルゴリズム](./lessons/6-Other/21-GeneticAlgorithms/README.md) | [Notebook](./lessons/6-Other/21-GeneticAlgorithms/Genetic.ipynb) | |
|
||||
| 22 | [深層強化学習](./lessons/6-Other/22-DeepRL/README.md) | [PyTorch](./lessons/6-Other/22-DeepRL/CartPole-RL-PyTorch.ipynb) /[TensorFlow](./lessons/6-Other/22-DeepRL/CartPole-RL-TF.ipynb) | [Lab](./lessons/6-Other/22-DeepRL/lab/README.md) |
|
||||
| 23 | [マルチエージェントシステム](./lessons/6-Other/23-MultiagentSystems/README.md) | | |
|
||||
| VII | **AI倫理** | | |
|
||||
| 24 | [AI倫理と責任あるAI](./lessons/7-Ethics/README.md) | [Microsoft Learn: 責任あるAIの原則](https://docs.microsoft.com/learn/paths/responsible-ai-business-principles/?WT.mc_id=academic-77998-cacaste) | |
|
||||
| IX | **その他** | | |
|
||||
| 25 | [マルチモーダルネットワーク、CLIPとVQGAN](./lessons/X-Extras/X1-MultiModal/README.md) | [ノートブック](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/X-Extras/X1-MultiModal/Clip.ipynb) | |
|
||||
| 25 | [マルチモーダルネットワーク、CLIPとVQGAN](./lessons/X-Extras/X1-MultiModal/README.md) | [Notebook](./lessons/X-Extras/X1-MultiModal/Clip.ipynb) | |
|
||||
|
||||
## 各レッスンに含まれる内容
|
||||
|
||||
* 事前学習資料
|
||||
* 実行可能なJupyterノートブック(**PyTorch**または**TensorFlow**に特化していることが多い)。実行可能なノートブックには多くの理論的な内容も含まれているため、トピックを理解するには少なくとも1つのバージョン(PyTorchまたはTensorFlow)を通して学ぶ必要があります。
|
||||
* **ラボ**が一部のトピックで利用可能で、学んだ内容を特定の問題に適用する機会を提供します。
|
||||
* 一部のセクションには、関連トピックをカバーする[**MS Learn**](https://learn.microsoft.com/en-us/collections/7w28iy2xrqzdj0?WT.mc_id=academic-77998-bethanycheum)モジュールへのリンクが含まれています。
|
||||
* 事前学習資料
|
||||
* 実行可能なJupyter Notebook(フレームワークに特化したものが多い **PyTorch** または **TensorFlow**)。実行可能なノートブックには多くの理論的な内容も含まれているため、トピックを理解するには少なくとも1つのバージョン(PyTorchまたはTensorFlow)を通して学ぶ必要があります。
|
||||
* **Lab** が一部のトピックで利用可能で、学んだ内容を特定の問題に適用する機会を提供します。
|
||||
* 一部のセクションには、関連トピックをカバーする [**MS Learn**](https://learn.microsoft.com/en-us/collections/7w28iy2xrqzdj0?WT.mc_id=academic-77998-bethanycheum) モジュールへのリンクが含まれています。
|
||||
|
||||
## 始め方
|
||||
|
||||
- 開発環境のセットアップを支援するために[セットアップレッスン](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/0-course-setup/setup.md)を作成しました。
|
||||
- 教育者向けに[カリキュラムセットアップレッスン](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/0-course-setup/for-teachers.md)も用意しています!
|
||||
- [VSCodeまたはCodepaceでコードを実行する方法](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/0-course-setup/how-to-run.md)
|
||||
- 開発環境のセットアップをサポートするために、[セットアップレッスン](./lessons/0-course-setup/setup.md)を作成しました。
|
||||
- 教育者向けに、[カリキュラムセットアップレッスン](./lessons/0-course-setup/for-teachers.md)も用意しています!
|
||||
- [VSCodeまたはCodepaceでコードを実行する方法](./lessons/0-course-setup/how-to-run.md)
|
||||
|
||||
以下の手順に従ってください:
|
||||
|
||||
リポジトリをフォークする: このページの右上にある「Fork」ボタンをクリックします。
|
||||
リポジトリをフォーク: このページの右上にある「Fork」ボタンをクリックします。
|
||||
|
||||
リポジトリをクローンする: `git clone https://github.com/microsoft/AI-For-Beginners.git`
|
||||
リポジトリをクローン: `git clone https://github.com/microsoft/AI-For-Beginners.git`
|
||||
|
||||
このリポジトリを後で簡単に見つけられるようにスター(🌟)を付けるのを忘れないでください。
|
||||
このリポジトリにスター (🌟) を付けて、後で簡単に見つけられるようにしてください。
|
||||
|
||||
## 他の学習者と出会う
|
||||
## 他の学習者とつながる
|
||||
|
||||
[公式AI Discordサーバー](https://aka.ms/genai-discord?WT.mc_id=academic-105485-bethanycheum)に参加して、このコースを受講している他の学習者と交流し、サポートを受けましょう。
|
||||
[公式AI Discordサーバー](https://aka.ms/genai-discord?WT.mc_id=academic-105485-bethanycheum) に参加して、このコースを受講している他の学習者と交流し、サポートを受けましょう。
|
||||
|
||||
構築中に製品フィードバックや質問がある場合は、[Azure AI Foundry開発者フォーラム](https://aka.ms/foundry/forum)をご覧ください。
|
||||
プロダクトに関するフィードバックや、構築中の質問がある場合は、[Azure AI Foundry Developer Forum](https://aka.ms/foundry/forum) を訪れてください。
|
||||
|
||||
## クイズ
|
||||
> **クイズについての注意**: すべてのクイズは、etc\quiz-app内のQuiz-appフォルダーに含まれています。これらはレッスン内からリンクされています。クイズアプリはローカルで実行することも、Azureにデプロイすることも可能です。詳細な手順は`quiz-app`フォルダー内の指示に従ってください。クイズは徐々にローカライズされています。
|
||||
> **クイズについての注意**: すべてのクイズは、etc\quiz-app内のQuiz-appフォルダーに含まれています。または[オンラインでこちら](https://ff-quizzes.netlify.app/)からアクセスできます。クイズはレッスン内からリンクされています。クイズアプリはローカルで実行することも、Azureにデプロイすることも可能です。`quiz-app`フォルダー内の指示に従ってください。クイズは徐々にローカライズされています。
|
||||
## ヘルプ募集
|
||||
|
||||
提案やスペルミス、コードの誤りを見つけましたか?Issueを作成するか、Pull Requestを送ってください。
|
||||
提案やスペルミス、コードのエラーを見つけましたか?Issueを立てるか、プルリクエストを作成してください。
|
||||
|
||||
## 特別な感謝
|
||||
|
||||
|
|
@ -137,20 +148,22 @@ CO_OP_TRANSLATOR_METADATA:
|
|||
|
||||
私たちのチームは他にもカリキュラムを制作しています!ぜひチェックしてください:
|
||||
|
||||
- [Generative AI for Beginners](https://aka.ms/genai-beginners)
|
||||
- [Generative AI for Beginners .NET](https://github.com/microsoft/Generative-AI-for-beginners-dotnet)
|
||||
- [Generative AI with JavaScript](https://github.com/microsoft/generative-ai-with-javascript)
|
||||
- [Generative AI with Java](https://github.com/microsoft/Generative-AI-for-beginners-java)
|
||||
- [AI for Beginners](https://aka.ms/ai-beginners)
|
||||
- [Data Science for Beginners](https://aka.ms/datascience-beginners)
|
||||
- [ML for Beginners](https://aka.ms/ml-beginners)
|
||||
- [Cybersecurity for Beginners](https://github.com/microsoft/Security-101)
|
||||
- [Web Dev for Beginners](https://aka.ms/webdev-beginners)
|
||||
- [IoT for Beginners](https://aka.ms/iot-beginners)
|
||||
- [XR Development for Beginners](https://github.com/microsoft/xr-development-for-beginners)
|
||||
- [Mastering GitHub Copilot for Agentic use](https://github.com/microsoft/Mastering-GitHub-Copilot-for-Paired-Programming)
|
||||
- [Mastering GitHub Copilot for C#/.NET Developers](https://github.com/microsoft/mastering-github-copilot-for-dotnet-csharp-developers)
|
||||
- [Choose Your Own Copilot Adventure](https://github.com/microsoft/CopilotAdventures)
|
||||
- [初心者向け生成AI](https://aka.ms/genai-beginners)
|
||||
- [初心者向け生成AI .NET](https://github.com/microsoft/Generative-AI-for-beginners-dotnet)
|
||||
- [JavaScriptで学ぶ生成AI](https://github.com/microsoft/generative-ai-with-javascript)
|
||||
- [Javaで学ぶ生成AI](https://github.com/microsoft/Generative-AI-for-beginners-java)
|
||||
- [初心者向けAI](https://aka.ms/ai-beginners)
|
||||
- [初心者向けデータサイエンス](https://aka.ms/datascience-beginners)
|
||||
- [初心者向け機械学習](https://aka.ms/ml-beginners)
|
||||
- [初心者向けサイバーセキュリティ](https://github.com/microsoft/Security-101)
|
||||
- [初心者向けWeb開発](https://aka.ms/webdev-beginners)
|
||||
- [初心者向けIoT](https://aka.ms/iot-beginners)
|
||||
- [初心者向けXR開発](https://github.com/microsoft/xr-development-for-beginners)
|
||||
- [GitHub Copilotを活用したエージェント的利用のマスター](https://github.com/microsoft/Mastering-GitHub-Copilot-for-Paired-Programming)
|
||||
- [C#/.NET開発者向けGitHub Copilotのマスター](https://github.com/microsoft/mastering-github-copilot-for-dotnet-csharp-developers)
|
||||
- [自分で選ぶCopilotアドベンチャー](https://github.com/microsoft/CopilotAdventures)
|
||||
|
||||
---
|
||||
|
||||
**免責事項**:
|
||||
この文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を期すよう努めておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があります。元の言語で記載された原文が公式な情報源と見なされるべきです。重要な情報については、専門の人間による翻訳を推奨します。本翻訳の使用に起因する誤解や誤認について、当方は一切の責任を負いません。
|
||||
この文書はAI翻訳サービス[Co-op Translator](https://github.com/Azure/co-op-translator)を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があります。元の言語で記載された文書を正式な情報源としてご参照ください。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当社は責任を負いません。
|
||||
|
|
@ -0,0 +1,478 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"source": [
|
||||
"# 動物専門家システムの実装\n",
|
||||
"\n",
|
||||
"[AI for Beginners Curriculum](http://github.com/microsoft/ai-for-beginners) の例。\n",
|
||||
"\n",
|
||||
"このサンプルでは、いくつかの物理的特徴に基づいて動物を特定するための簡単な知識ベースシステムを実装します。このシステムは以下の AND-OR ツリーで表すことができます(これはツリーの一部であり、簡単にさらにルールを追加することができます):\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 後方推論を用いた独自のエキスパートシステムシェル\n",
|
||||
"\n",
|
||||
"生産規則に基づいた知識表現のための簡単な言語を定義してみましょう。ルールを定義するためにPythonのクラスをキーワードとして使用します。基本的に以下の3種類のクラスがあります:\n",
|
||||
"* `Ask` はユーザーに尋ねる必要がある質問を表します。可能な回答のセットを含みます。\n",
|
||||
"* `If` はルールを表し、ルールの内容を保存するための単なる構文糖衣です。\n",
|
||||
"* `AND`/`OR` はツリーのAND/OR分岐を表すクラスです。これらは引数のリストを内部に保存するだけです。コードを簡素化するために、すべての機能は親クラス `Content` に定義されています。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class Ask():\n",
|
||||
" def __init__(self,choices=['y','n']):\n",
|
||||
" self.choices = choices\n",
|
||||
" def ask(self):\n",
|
||||
" if max([len(x) for x in self.choices])>1:\n",
|
||||
" for i,x in enumerate(self.choices):\n",
|
||||
" print(\"{0}. {1}\".format(i,x),flush=True)\n",
|
||||
" x = int(input())\n",
|
||||
" return self.choices[x]\n",
|
||||
" else:\n",
|
||||
" print(\"/\".join(self.choices),flush=True)\n",
|
||||
" return input()\n",
|
||||
"\n",
|
||||
"class Content():\n",
|
||||
" def __init__(self,x):\n",
|
||||
" self.x=x\n",
|
||||
" \n",
|
||||
"class If(Content):\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"class AND(Content):\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"class OR(Content):\n",
|
||||
" pass"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"私たちのシステムでは、作業記憶は**属性-値ペア**としての**事実**のリストを含みます。ナレッジベースは、条件(AND-OR式として表現される)に基づいてアクション(作業記憶に挿入されるべき新しい事実)をマッピングする1つの大きな辞書として定義できます。また、一部の事実は`Ask`されることがあります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"rules = {\n",
|
||||
" 'default': Ask(['y','n']),\n",
|
||||
" 'color' : Ask(['red-brown','black and white','other']),\n",
|
||||
" 'pattern' : Ask(['dark stripes','dark spots']),\n",
|
||||
" 'mammal': If(OR(['hair','gives milk'])),\n",
|
||||
" 'carnivor': If(OR([AND(['sharp teeth','claws','forward-looking eyes']),'eats meat'])),\n",
|
||||
" 'ungulate': If(['mammal',OR(['has hooves','chews cud'])]),\n",
|
||||
" 'bird': If(OR(['feathers',AND(['flies','lies eggs'])])),\n",
|
||||
" 'animal:monkey' : If(['mammal','carnivor','color:red-brown','pattern:dark spots']),\n",
|
||||
" 'animal:tiger' : If(['mammal','carnivor','color:red-brown','pattern:dark stripes']),\n",
|
||||
" 'animal:giraffe' : If(['ungulate','long neck','long legs','pattern:dark spots']),\n",
|
||||
" 'animal:zebra' : If(['ungulate','pattern:dark stripes']),\n",
|
||||
" 'animal:ostrich' : If(['bird','long nech','color:black and white','cannot fly']),\n",
|
||||
" 'animal:pinguin' : If(['bird','swims','color:black and white','cannot fly']),\n",
|
||||
" 'animal:albatross' : If(['bird','flies well'])\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"逆推論を行うために、`Knowledgebase` クラスを定義します。このクラスには以下が含まれます:\n",
|
||||
"* 作業用の`memory` - 属性と値をマッピングする辞書\n",
|
||||
"* 上記で定義された形式の知識ベースの`rules`\n",
|
||||
"\n",
|
||||
"主なメソッドは以下の2つです:\n",
|
||||
"* `get` - 必要に応じて推論を行い、属性の値を取得します。例えば、`get('color')`は色スロットの値を取得します(必要であれば尋ね、作業メモリに値を保存します)。`get('color:blue')`を尋ねた場合、色を尋ねた後、その色に応じて`y`/`n`の値を返します。\n",
|
||||
"* `eval` - 実際の推論を行います。つまり、AND/ORツリーをたどり、サブゴールを評価するなどの処理を行います。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class KnowledgeBase():\n",
|
||||
" def __init__(self,rules):\n",
|
||||
" self.rules = rules\n",
|
||||
" self.memory = {}\n",
|
||||
" \n",
|
||||
" def get(self,name):\n",
|
||||
" if ':' in name:\n",
|
||||
" k,v = name.split(':')\n",
|
||||
" vv = self.get(k)\n",
|
||||
" return 'y' if v==vv else 'n'\n",
|
||||
" if name in self.memory.keys():\n",
|
||||
" return self.memory[name]\n",
|
||||
" for fld in self.rules.keys():\n",
|
||||
" if fld==name or fld.startswith(name+\":\"):\n",
|
||||
" # print(\" + proving {}\".format(fld))\n",
|
||||
" value = 'y' if fld==name else fld.split(':')[1]\n",
|
||||
" res = self.eval(self.rules[fld],field=name)\n",
|
||||
" if res!='y' and res!='n' and value=='y':\n",
|
||||
" self.memory[name] = res\n",
|
||||
" return res\n",
|
||||
" if res=='y':\n",
|
||||
" self.memory[name] = value\n",
|
||||
" return value\n",
|
||||
" # field is not found, using default\n",
|
||||
" res = self.eval(self.rules['default'],field=name)\n",
|
||||
" self.memory[name]=res\n",
|
||||
" return res\n",
|
||||
" \n",
|
||||
" def eval(self,expr,field=None):\n",
|
||||
" # print(\" + eval {}\".format(expr))\n",
|
||||
" if isinstance(expr,Ask):\n",
|
||||
" print(field)\n",
|
||||
" return expr.ask()\n",
|
||||
" elif isinstance(expr,If):\n",
|
||||
" return self.eval(expr.x)\n",
|
||||
" elif isinstance(expr,AND) or isinstance(expr,list):\n",
|
||||
" expr = expr.x if isinstance(expr,AND) else expr\n",
|
||||
" for x in expr:\n",
|
||||
" if self.eval(x)=='n':\n",
|
||||
" return 'n'\n",
|
||||
" return 'y'\n",
|
||||
" elif isinstance(expr,OR):\n",
|
||||
" for x in expr.x:\n",
|
||||
" if self.eval(x)=='y':\n",
|
||||
" return 'y'\n",
|
||||
" return 'n'\n",
|
||||
" elif isinstance(expr,str):\n",
|
||||
" return self.get(expr)\n",
|
||||
" else:\n",
|
||||
" print(\"Unknown expr: {}\".format(expr))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"さて、動物の知識ベースを定義し、相談を行いましょう。この呼び出しでは質問が行われることに注意してください。はい/いいえの質問には `y`/`n` を入力して答えるか、複数選択肢の質問には番号 (0..N) を指定して答えることができます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"hair\n",
|
||||
"y/n\n",
|
||||
"sharp teeth\n",
|
||||
"y/n\n",
|
||||
"claws\n",
|
||||
"y/n\n",
|
||||
"forward-looking eyes\n",
|
||||
"y/n\n",
|
||||
"color\n",
|
||||
"0. red-brown\n",
|
||||
"1. black and white\n",
|
||||
"2. other\n",
|
||||
"has hooves\n",
|
||||
"y/n\n",
|
||||
"long neck\n",
|
||||
"y/n\n",
|
||||
"long legs\n",
|
||||
"y/n\n",
|
||||
"pattern\n",
|
||||
"0. dark stripes\n",
|
||||
"1. dark spots\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'giraffe'"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"kb = KnowledgeBase(rules)\n",
|
||||
"kb.get('animal')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## PyKnowを使った前向き推論\n",
|
||||
"\n",
|
||||
"次の例では、知識表現のためのライブラリの1つである[PyKnow](https://github.com/buguroo/pyknow/)を使用して、前向き推論を実装してみます。**PyKnow**は、Pythonで前向き推論システムを作成するためのライブラリで、古典的なシステムである[CLIPS](http://www.clipsrules.net/index.html)に似た設計になっています。\n",
|
||||
"\n",
|
||||
"もちろん、自分で前向き推論(フォワードチェイニング)を実装することも可能ですが、素朴な実装では通常あまり効率的ではありません。より効果的なルールマッチングのために、特別なアルゴリズムである[Rete](https://en.wikipedia.org/wiki/Rete_algorithm)が使用されます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Collecting git+https://github.com/buguroo/pyknow/\n",
|
||||
" Cloning https://github.com/buguroo/pyknow/ to /tmp/pip-req-build-3cqeulyl\n",
|
||||
" Running command git clone --filter=blob:none --quiet https://github.com/buguroo/pyknow/ /tmp/pip-req-build-3cqeulyl\n",
|
||||
" Resolved https://github.com/buguroo/pyknow/ to commit 48818336f2e9a126f1964f2d8dc22d37ff800fe8\n",
|
||||
" Preparing metadata (setup.py) ... \u001b[?25ldone\n",
|
||||
"\u001b[?25hCollecting frozendict==1.2\n",
|
||||
" Using cached frozendict-1.2.tar.gz (2.6 kB)\n",
|
||||
" Preparing metadata (setup.py) ... \u001b[?25ldone\n",
|
||||
"\u001b[?25hCollecting schema==0.6.7\n",
|
||||
" Using cached schema-0.6.7-py2.py3-none-any.whl (14 kB)\n",
|
||||
"Building wheels for collected packages: pyknow, frozendict\n",
|
||||
" Building wheel for pyknow (setup.py) ... \u001b[?25ldone\n",
|
||||
"\u001b[?25h Created wheel for pyknow: filename=pyknow-1.7.0-py3-none-any.whl size=34228 sha256=b7de5b09292c4007667c72f69b98d5a1b5f7324ff15f9dd8e077c3d5f7aade42\n",
|
||||
" Stored in directory: /tmp/pip-ephem-wheel-cache-k7jpave7/wheels/81/1a/d3/f6c15dbe1955598a37755215f2a10449e7418500d7bd4b9508\n",
|
||||
" Building wheel for frozendict (setup.py) ... \u001b[?25ldone\n",
|
||||
"\u001b[?25h Created wheel for frozendict: filename=frozendict-1.2-py3-none-any.whl size=3148 sha256=2863d55c240d2409cddf05ccfe600591f8478681549fc97555c47c90dc6bb160\n",
|
||||
" Stored in directory: /home/rg/.cache/pip/wheels/49/ac/f8/cb8120244e710bdb479c86198b03c7b08c3c2d3d2bf448fd6e\n",
|
||||
"Successfully built pyknow frozendict\n",
|
||||
"Installing collected packages: schema, frozendict, pyknow\n",
|
||||
"Successfully installed frozendict-1.2 pyknow-1.7.0 schema-0.6.7\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import sys\n",
|
||||
"!{sys.executable} -m pip install git+https://github.com/buguroo/pyknow/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from pyknow import *\n",
|
||||
"#import pyknow"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"私たちは、`KnowledgeEngine`をサブクラス化するクラスとしてシステムを定義します。各ルールは、ルールが発火する条件を指定する`@Rule`アノテーションを持つ個別の関数によって定義されます。ルール内では、`declare`関数を使用して新しい事実を追加することができ、それらの事実を追加することで、前向き推論エンジンによってさらに多くのルールが呼び出される結果となります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class Animals(KnowledgeEngine):\n",
|
||||
" @Rule(OR(\n",
|
||||
" AND(Fact('sharp teeth'),Fact('claws'),Fact('forward looking eyes')),\n",
|
||||
" Fact('eats meat')))\n",
|
||||
" def cornivor(self):\n",
|
||||
" self.declare(Fact('carnivor'))\n",
|
||||
" \n",
|
||||
" @Rule(OR(Fact('hair'),Fact('gives milk')))\n",
|
||||
" def mammal(self):\n",
|
||||
" self.declare(Fact('mammal'))\n",
|
||||
"\n",
|
||||
" @Rule(Fact('mammal'),\n",
|
||||
" OR(Fact('has hooves'),Fact('chews cud')))\n",
|
||||
" def hooves(self):\n",
|
||||
" self.declare('ungulate')\n",
|
||||
" \n",
|
||||
" @Rule(OR(Fact('feathers'),AND(Fact('flies'),Fact('lays eggs'))))\n",
|
||||
" def bird(self):\n",
|
||||
" self.declare('bird')\n",
|
||||
" \n",
|
||||
" @Rule(Fact('mammal'),Fact('carnivor'),\n",
|
||||
" Fact(color='red-brown'),\n",
|
||||
" Fact(pattern='dark spots'))\n",
|
||||
" def monkey(self):\n",
|
||||
" self.declare(Fact(animal='monkey'))\n",
|
||||
"\n",
|
||||
" @Rule(Fact('mammal'),Fact('carnivor'),\n",
|
||||
" Fact(color='red-brown'),\n",
|
||||
" Fact(pattern='dark stripes'))\n",
|
||||
" def tiger(self):\n",
|
||||
" self.declare(Fact(animal='tiger'))\n",
|
||||
"\n",
|
||||
" @Rule(Fact('ungulate'),\n",
|
||||
" Fact('long neck'),\n",
|
||||
" Fact('long legs'),\n",
|
||||
" Fact(pattern='dark spots'))\n",
|
||||
" def giraffe(self):\n",
|
||||
" self.declare(Fact(animal='giraffe'))\n",
|
||||
"\n",
|
||||
" @Rule(Fact('ungulate'),\n",
|
||||
" Fact(pattern='dark stripes'))\n",
|
||||
" def zebra(self):\n",
|
||||
" self.declare(Fact(animal='zebra'))\n",
|
||||
"\n",
|
||||
" @Rule(Fact('bird'),\n",
|
||||
" Fact('long neck'),\n",
|
||||
" Fact('cannot fly'),\n",
|
||||
" Fact(color='black and white'))\n",
|
||||
" def straus(self):\n",
|
||||
" self.declare(Fact(animal='ostrich'))\n",
|
||||
"\n",
|
||||
" @Rule(Fact('bird'),\n",
|
||||
" Fact('swims'),\n",
|
||||
" Fact('cannot fly'),\n",
|
||||
" Fact(color='black and white'))\n",
|
||||
" def pinguin(self):\n",
|
||||
" self.declare(Fact(animal='pinguin'))\n",
|
||||
"\n",
|
||||
" @Rule(Fact('bird'),\n",
|
||||
" Fact('flies well'))\n",
|
||||
" def albatros(self):\n",
|
||||
" self.declare(Fact(animal='albatross'))\n",
|
||||
" \n",
|
||||
" @Rule(Fact(animal=MATCH.a))\n",
|
||||
" def print_result(self,a):\n",
|
||||
" print('Animal is {}'.format(a))\n",
|
||||
" \n",
|
||||
" def factz(self,l):\n",
|
||||
" for x in l:\n",
|
||||
" self.declare(x)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"知識ベースを定義したら、いくつかの初期事実で作業メモリを埋め、次に推論を実行するために`run()`メソッドを呼び出します。その結果として、新たに推論された事実が作業メモリに追加され、動物に関する最終的な事実も含まれます(初期事実を正しく設定した場合)。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Animal is tiger\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"FactList([(0, InitialFact()),\n",
|
||||
" (1, Fact(color='red-brown')),\n",
|
||||
" (2, Fact(pattern='dark stripes')),\n",
|
||||
" (3, Fact('sharp teeth')),\n",
|
||||
" (4, Fact('claws')),\n",
|
||||
" (5, Fact('forward looking eyes')),\n",
|
||||
" (6, Fact('gives milk')),\n",
|
||||
" (7, Fact('mammal')),\n",
|
||||
" (8, Fact('carnivor')),\n",
|
||||
" (9, Fact(animal='tiger'))])"
|
||||
]
|
||||
},
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"ex1 = Animals()\n",
|
||||
"ex1.reset()\n",
|
||||
"ex1.factz([\n",
|
||||
" Fact(color='red-brown'),\n",
|
||||
" Fact(pattern='dark stripes'),\n",
|
||||
" Fact('sharp teeth'),\n",
|
||||
" Fact('claws'),\n",
|
||||
" Fact('forward looking eyes'),\n",
|
||||
" Fact('gives milk')])\n",
|
||||
"ex1.run()\n",
|
||||
"ex1.facts"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知ください。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当方は責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.7.4 64-bit (conda)",
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
|
||||
}
|
||||
},
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.11.2"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "ab2bd97b0453415b89a469284609a8ce",
|
||||
"translation_date": "2025-08-30T09:41:24+00:00",
|
||||
"source_file": "lessons/2-Symbolic/Animals.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,595 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"source": [
|
||||
"# 家族関係のオントロジー\n",
|
||||
"\n",
|
||||
"この例は[AI for Beginners Curriculum](http://github.com/microsoft/ai-for-beginners)の一部であり、[このブログ記事](https://habr.com/post/270857/)に触発されています。\n",
|
||||
"\n",
|
||||
"家族内の人々の関係を覚えるのはいつも難しいと感じます。この例では、家族関係を定義するオントロジーと実際の系譜図を取り上げ、それを使って自動推論を行い、すべての親族を見つける方法を示します。\n",
|
||||
"\n",
|
||||
"### 系譜図の取得\n",
|
||||
"\n",
|
||||
"例として、[ロマノフ皇帝一家](https://en.wikipedia.org/wiki/House_of_Romanov)の系譜図を取り上げます。家族関係を記述する最も一般的な形式は[GEDCOM](https://en.wikipedia.org/wiki/GEDCOM)です。ロマノフ家の系譜図をGEDCOM形式で取得します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0 HEAD\n",
|
||||
"1 CHAR UTF8\n",
|
||||
"1 GEDC\n",
|
||||
"2 VERS 5.5\n",
|
||||
"0 @0@ INDI\n",
|
||||
"1 NAME Mihail Fedorovich /Romanov/\n",
|
||||
"1 SEX M\n",
|
||||
"1 BIRT\n",
|
||||
"2 DATE 1613\n",
|
||||
"1 DEAT \n",
|
||||
"2 DATE 1645\n",
|
||||
"1 FAMS @41@\n",
|
||||
"0 @1@ INDI\n",
|
||||
"1 NAME Evdokija Lukjanovna /Streshneva/\n",
|
||||
"1 SEX F\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"!head -15 data/tsars.ged"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"GEDCOMファイルを使用するには、`python-gedcom`ライブラリを使用できます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Collecting python-gedcom\n",
|
||||
" Downloading python_gedcom-1.0.0-py2.py3-none-any.whl (35 kB)\n",
|
||||
"Installing collected packages: python-gedcom\n",
|
||||
"Successfully installed python-gedcom-1.0.0\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import sys\n",
|
||||
"!{sys.executable} -m pip install python-gedcom"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"このライブラリはファイル解析に関するいくつかの技術的な問題を取り除きますが、ツリー内のすべての個人と家族に対してかなり低レベルのアクセスを提供します。以下はファイルを解析し、すべての個人のリストを表示する方法です:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from gedcom.parser import Parser\n",
|
||||
"from gedcom.element.individual import IndividualElement\n",
|
||||
"from gedcom.element.family import FamilyElement\n",
|
||||
"g = Parser()\n",
|
||||
"g.parse_file('data/tsars.ged')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"scrolled": true,
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[('@0@', ('Mihail Fedorovich', 'Romanov')),\n",
|
||||
" ('@1@', ('Evdokija Lukjanovna', 'Streshneva')),\n",
|
||||
" ('@2@', ('Aleksej Mihajlovich', 'Romanov')),\n",
|
||||
" ('@3@', ('Marija Ilinichna', 'Miloslavskaja')),\n",
|
||||
" ('@4@', ('Natalja Kirillovna', 'Naryshkina')),\n",
|
||||
" ('@5@', ('Marfa Matveevna', 'Apraksina')),\n",
|
||||
" ('@6@', ('Fedor Alekseevich', 'Romanov')),\n",
|
||||
" ('@7@', ('Sofja Aleksevna', 'Romanova')),\n",
|
||||
" ('@8@', ('Ivan V Alekseevich', 'Romanov')),\n",
|
||||
" ('@9@', ('Praskovja Fedorovna', 'Saltykova')),\n",
|
||||
" ('@10@', ('Ekaterina Ivanovna', 'Romanova')),\n",
|
||||
" ('@11@', ('Anna Ivanovna', 'Romanova')),\n",
|
||||
" ('@12@', ('Fridrih Vilgelm', 'Kurlandskij')),\n",
|
||||
" ('@13@', ('Karl Leopold', 'Meklenburg-Shverinskij')),\n",
|
||||
" ('@14@', ('Anna Leopoldovna', 'Meklenburg-Shverinskaja')),\n",
|
||||
" ('@15@', ('Anton Ulrih', 'Braunshvejg-Volfenbjuttelskij')),\n",
|
||||
" ('@16@', ('Ivan VI Antonovich', 'Braunshvejg-Volfenbjuttelskij')),\n",
|
||||
" ('@17@', ('Petr I Alekseevich', 'Romanov')),\n",
|
||||
" ('@18@', ('Evdokija Fedorovna', 'Lopuhina')),\n",
|
||||
" ('@19@', ('Ekaterina I Alekseevna', 'Mihajlova')),\n",
|
||||
" ('@20@', ('Aleksej Petrovich', 'Romanov')),\n",
|
||||
" ('@21@', ('Sharlotta Kristina', 'Braunshvejg-Volfenbjuttelskaja')),\n",
|
||||
" ('@22@', ('Petr II Alekseevich', 'Romanov')),\n",
|
||||
" ('@23@', ('Anna Petrovna', 'Romanova')),\n",
|
||||
" ('@24@', ('Elizaveta Petrovna', 'Romanova')),\n",
|
||||
" ('@25@', ('Karl Fridrih', 'Golshtejn-Gottorpskij')),\n",
|
||||
" ('@26@', ('Petr III Fedorovich', 'Romanov')),\n",
|
||||
" ('@27@', ('Ekaterina II', 'Alekseevna')),\n",
|
||||
" ('@28@', ('Pavel I Petrovich', 'Romanov')),\n",
|
||||
" ('@29@', ('Natalja Alekseevna', 'Gessen-Darmshtadskaja')),\n",
|
||||
" ('@30@', ('Marija Fedorovna', 'Vjurtembergskaja')),\n",
|
||||
" ('@31@', ('Aleksandr I Pavlovich', 'Romanov')),\n",
|
||||
" ('@32@', ('Elizaveta Alekseevna', 'Baden-Durlahskaja')),\n",
|
||||
" ('@33@', ('Nikolaj I Pavlovich', 'Romanov')),\n",
|
||||
" ('@34@', ('Aleksandra Fedorovna', 'Prusskaja')),\n",
|
||||
" ('@35@', ('Aleksandr II Nikolaevich', 'Romanov')),\n",
|
||||
" ('@36@', ('Marija Aleksandrovna', 'Gessenskaja')),\n",
|
||||
" ('@37@', ('Aleksandr III Aleksandrovich', 'Romanov')),\n",
|
||||
" ('@38@', ('Marija Fedorovna', 'Datskaja')),\n",
|
||||
" ('@39@', ('Nikolaj II Aleksandrovich', 'Romanov')),\n",
|
||||
" ('@40@', ('Aleksandra Fedorovna', 'Gessenskaja'))]"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"d = g.get_element_dictionary()\n",
|
||||
"[ (k,v.get_name()) for k,v in d.items() if isinstance(v,IndividualElement)]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"家族についての情報を得る方法は次の通りです。これには**識別子**のリストが表示されることに注意してください。より明確にしたい場合は、それらを名前に変換する必要があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[('@41@', ['@0@', '@1@', '@2@']),\n",
|
||||
" ('@42@', ['@2@', '@3@', '@6@', '@7@', '@8@']),\n",
|
||||
" ('@43@', ['@8@', '@9@', '@10@', '@11@']),\n",
|
||||
" ('@44@', ['@13@', '@10@', '@14@']),\n",
|
||||
" ('@45@', ['@15@', '@14@', '@16@']),\n",
|
||||
" ('@46@', ['@2@', '@4@', '@17@']),\n",
|
||||
" ('@47@', ['@17@', '@18@', '@20@']),\n",
|
||||
" ('@48@', ['@20@', '@21@', '@22@']),\n",
|
||||
" ('@49@', ['@17@', '@19@', '@23@', '@24@']),\n",
|
||||
" ('@50@', ['@25@', '@23@', '@26@']),\n",
|
||||
" ('@51@', ['@26@', '@27@', '@28@']),\n",
|
||||
" ('@52@', ['@28@', '@30@', '@31@', '@33@']),\n",
|
||||
" ('@53@', ['@33@', '@34@', '@35@']),\n",
|
||||
" ('@54@', ['@35@', '@36@', '@37@']),\n",
|
||||
" ('@55@', ['@37@', '@38@', '@39@'])]"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"d = g.get_element_dictionary()\n",
|
||||
"[ (k,[x.get_value() for x in v.get_child_elements()]) for k,v in d.items() if isinstance(v,FamilyElement)]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 家族オントロジーの取得\n",
|
||||
"\n",
|
||||
"次に、[家族オントロジー](https://raw.githubusercontent.com/blokhin/genealogical-trees/master/data/header.ttl)を見てみましょう。これはセマンティックウェブのトリプレットの集合として定義されています。このオントロジーでは、`isUncleOf`、`isCousinOf`などの関係が定義されています。これらの関係はすべて、基本的な述語である`isMotherOf`、`isFatherOf`、`isBrotherOf`、`isSisterOf`を基に定義されています。オントロジーを使用して自動推論を行い、その他のすべての関係を導き出します。\n",
|
||||
"\n",
|
||||
"以下は、`isAuntOf`プロパティのサンプル定義です。このプロパティは、`isSisterOf`と`isParentOf`の合成として定義されています(*叔母は親の姉妹*)。\n",
|
||||
"\n",
|
||||
"```\n",
|
||||
"fhkb:isAuntOf a owl:ObjectProperty ;\n",
|
||||
" rdfs:domain fhkb:Woman ;\n",
|
||||
" rdfs:range fhkb:Person ;\n",
|
||||
" owl:propertyChainAxiom ( fhkb:isSisterOf fhkb:isParentOf ) .\n",
|
||||
"```\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"@prefix fhkb: <http://www.example.com/genealogy.owl#> .\n",
|
||||
"@prefix owl: <http://www.w3.org/2002/07/owl#> .\n",
|
||||
"@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n",
|
||||
"@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n",
|
||||
"@prefix xml: <http://www.w3.org/XML/1998/namespace> .\n",
|
||||
"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n",
|
||||
"\n",
|
||||
"<http://www.example.com/genealogy.owl#> a owl:Ontology .\n",
|
||||
"\n",
|
||||
"fhkb:DomainEntity a owl:Class .\n",
|
||||
"\n",
|
||||
"fhkb:Man a owl:Class ;\n",
|
||||
" owl:equivalentClass [ a owl:Class ;\n",
|
||||
" owl:intersectionOf ( fhkb:Person [ a owl:Restriction ;\n",
|
||||
" owl:onProperty fhkb:hasSex ;\n",
|
||||
" owl:someValuesFrom fhkb:Male ] ) ] .\n",
|
||||
"\n",
|
||||
"fhkb:Woman a owl:Class ;\n",
|
||||
" owl:equivalentClass [ a owl:Class ;\n",
|
||||
" owl:intersectionOf ( fhkb:Person [ a owl:Restriction ;\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"!head -20 data/onto.ttl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 推論のためのオントロジー構築\n",
|
||||
"\n",
|
||||
"簡単のため、家族オントロジーの元のルールとGEDCOMファイルからの個人に関する事実を含む1つのオントロジーファイルを作成します。GEDCOMファイルを調べ、家族や個人に関する情報を抽出し、それをトリプレットに変換します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!cp data/onto.ttl .\n",
|
||||
"\n",
|
||||
"gedcom_dict = g.get_element_dictionary()\n",
|
||||
"individuals, marriages = {}, {}\n",
|
||||
"\n",
|
||||
"def term2id(el):\n",
|
||||
" return \"i\" + el.get_pointer().replace('@', '').lower()\n",
|
||||
"\n",
|
||||
"out = open(\"onto.ttl\",\"a\")\n",
|
||||
"\n",
|
||||
"for k, v in gedcom_dict.items():\n",
|
||||
" if isinstance(v,IndividualElement):\n",
|
||||
" children, siblings = set(), set()\n",
|
||||
" idx = term2id(v)\n",
|
||||
"\n",
|
||||
" title = v.get_name()[0] + \" \" + v.get_name()[1]\n",
|
||||
" title = title.replace('\"', '').replace('[', '').replace(']', '').replace('(', '').replace(')', '').strip()\n",
|
||||
"\n",
|
||||
" own_families = g.get_families(v, 'FAMS')\n",
|
||||
" for fam in own_families:\n",
|
||||
" children |= set(term2id(i) for i in g.get_family_members(fam, \"CHIL\"))\n",
|
||||
"\n",
|
||||
" parent_families = g.get_families(v, 'FAMC')\n",
|
||||
" if len(parent_families):\n",
|
||||
" for member in g.get_family_members(parent_families[0], \"CHIL\"): # NB adoptive families i.e len(parent_families)>1 are not considered (TODO?)\n",
|
||||
" if member.get_pointer() == v.get_pointer():\n",
|
||||
" continue\n",
|
||||
" siblings.add(term2id(member))\n",
|
||||
"\n",
|
||||
" if idx in individuals:\n",
|
||||
" children |= individuals[idx].get('children', set())\n",
|
||||
" siblings |= individuals[idx].get('siblings', set())\n",
|
||||
" individuals[idx] = {'sex': v.get_gender().lower(), 'children': children, 'siblings': siblings, 'title': title}\n",
|
||||
"\n",
|
||||
" elif isinstance(v,FamilyElement):\n",
|
||||
" wife, husb, children = None, None, set()\n",
|
||||
" children = set(term2id(i) for i in g.get_family_members(v, \"CHIL\"))\n",
|
||||
"\n",
|
||||
" try:\n",
|
||||
" wife = g.get_family_members(v, \"WIFE\")[0]\n",
|
||||
" wife = term2id(wife)\n",
|
||||
" if wife in individuals: individuals[wife]['children'] |= children\n",
|
||||
" else: individuals[wife] = {'children': children}\n",
|
||||
" except IndexError: pass\n",
|
||||
" try:\n",
|
||||
" husb = g.get_family_members(v, \"HUSB\")[0]\n",
|
||||
" husb = term2id(husb)\n",
|
||||
" if husb in individuals: individuals[husb]['children'] |= children\n",
|
||||
" else: individuals[husb] = {'children': children}\n",
|
||||
" except IndexError: pass\n",
|
||||
"\n",
|
||||
" if wife and husb: marriages[wife + husb] = (term2id(v), wife, husb)\n",
|
||||
"\n",
|
||||
"for idx, val in individuals.items():\n",
|
||||
" added_terms = ''\n",
|
||||
" if val['sex'] == 'f':\n",
|
||||
" parent_predicate, sibl_predicate = \"isMotherOf\", \"isSisterOf\"\n",
|
||||
" else:\n",
|
||||
" parent_predicate, sibl_predicate = \"isFatherOf\", \"isBrotherOf\"\n",
|
||||
" if len(val['children']):\n",
|
||||
" added_terms += \" ;\\n fhkb:\" + parent_predicate + \" \" + \", \".join([\"fhkb:\" + i for i in val['children']])\n",
|
||||
" if len(val['siblings']):\n",
|
||||
" added_terms += \" ;\\n fhkb:\" + sibl_predicate + \" \" + \", \".join([\"fhkb:\" + i for i in val['siblings']])\n",
|
||||
" out.write(\"fhkb:%s a owl:NamedIndividual, owl:Thing%s ;\\n rdfs:label \\\"%s\\\" .\\n\" % (idx, added_terms, val['title']))\n",
|
||||
"\n",
|
||||
"for k, v in marriages.items():\n",
|
||||
" out.write(\"fhkb:%s a owl:NamedIndividual, owl:Thing ;\\n fhkb:hasFemalePartner fhkb:%s ;\\n fhkb:hasMalePartner fhkb:%s .\\n\" % v)\n",
|
||||
"\n",
|
||||
"out.write(\"[] a owl:AllDifferent ;\\n owl:distinctMembers (\")\n",
|
||||
"for idx in individuals.keys():\n",
|
||||
" out.write(\" fhkb:\" + idx)\n",
|
||||
"for k, v in marriages.items():\n",
|
||||
" out.write(\" fhkb:\" + v[0])\n",
|
||||
"out.write(\" ) .\")\n",
|
||||
"out.close()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
" fhkb:hasFemalePartner fhkb:i34 ;\n",
|
||||
" fhkb:hasMalePartner fhkb:i33 .\n",
|
||||
"fhkb:i54 a owl:NamedIndividual, owl:Thing ;\n",
|
||||
" fhkb:hasFemalePartner fhkb:i36 ;\n",
|
||||
" fhkb:hasMalePartner fhkb:i35 .\n",
|
||||
"fhkb:i55 a owl:NamedIndividual, owl:Thing ;\n",
|
||||
" fhkb:hasFemalePartner fhkb:i38 ;\n",
|
||||
" fhkb:hasMalePartner fhkb:i37 .\n",
|
||||
"[] a owl:AllDifferent ;\n",
|
||||
" owl:distinctMembers ( fhkb:i0 fhkb:i1 fhkb:i2 fhkb:i3 fhkb:i4 fhkb:i5 fhkb:i6 fhkb:i7 fhkb:i8 fhkb:i9 fhkb:i10 fhkb:i11 fhkb:i12 fhkb:i13 fhkb:i14 fhkb:i15 fhkb:i16 fhkb:i17 fhkb:i18 fhkb:i19 fhkb:i20 fhkb:i21 fhkb:i22 fhkb:i23 fhkb:i24 fhkb:i25 fhkb:i26 fhkb:i27 fhkb:i28 fhkb:i29 fhkb:i30 fhkb:i31 fhkb:i32 fhkb:i33 fhkb:i34 fhkb:i35 fhkb:i36 fhkb:i37 fhkb:i38 fhkb:i39 fhkb:i40 fhkb:i41 fhkb:i42 fhkb:i43 fhkb:i44 fhkb:i45 fhkb:i46 fhkb:i47 fhkb:i48 fhkb:i49 fhkb:i50 fhkb:i51 fhkb:i52 fhkb:i53 fhkb:i54 fhkb:i55 ) ."
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"!tail onto.ttl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 推論の実行\n",
|
||||
"\n",
|
||||
"次に、このオントロジーを使用して推論やクエリを実行できるようにします。[RDFLib](https://github.com/RDFLib)を使用します。このライブラリは、さまざまな形式でRDFグラフを読み込んだり、クエリを実行したりするためのものです。\n",
|
||||
"\n",
|
||||
"論理推論には、[OWL-RL](https://github.com/RDFLib/OWL-RL)ライブラリを使用します。このライブラリを使うことで、RDFグラフの**閉包**を構築できます。つまり、推論可能なすべての概念や関係を追加することができます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Requirement already satisfied: rdflib in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (6.3.2)\n",
|
||||
"Requirement already satisfied: isodate<0.7.0,>=0.6.0 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from rdflib) (0.6.1)\n",
|
||||
"Requirement already satisfied: pyparsing<4,>=2.1.0 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from rdflib) (3.0.9)\n",
|
||||
"Requirement already satisfied: six in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from isodate<0.7.0,>=0.6.0->rdflib) (1.16.0)\n",
|
||||
"Collecting git+https://github.com/RDFLib/OWL-RL.git\n",
|
||||
" Cloning https://github.com/RDFLib/OWL-RL.git to /tmp/pip-req-build-lbfzwi3m\n",
|
||||
" Running command git clone --filter=blob:none --quiet https://github.com/RDFLib/OWL-RL.git /tmp/pip-req-build-lbfzwi3m\n",
|
||||
" Resolved https://github.com/RDFLib/OWL-RL.git to commit a77e1791b88b54aace609bc6000aac14c7add4ff\n",
|
||||
" Preparing metadata (setup.py) ... \u001b[?25ldone\n",
|
||||
"\u001b[?25hRequirement already satisfied: rdflib>=6.0.2 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from owlrl==6.0.2) (6.3.2)\n",
|
||||
"Requirement already satisfied: isodate<0.7.0,>=0.6.0 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from rdflib>=6.0.2->owlrl==6.0.2) (0.6.1)\n",
|
||||
"Requirement already satisfied: pyparsing<4,>=2.1.0 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from rdflib>=6.0.2->owlrl==6.0.2) (3.0.9)\n",
|
||||
"Requirement already satisfied: six in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from isodate<0.7.0,>=0.6.0->rdflib>=6.0.2->owlrl==6.0.2) (1.16.0)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"!{sys.executable} -m pip install rdflib\n",
|
||||
"!{sys.executable} -m pip install git+https://github.com/RDFLib/OWL-RL.git"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"オントロジーファイルを開いて、いくつのトリプレットが含まれているか確認しましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Triplets found:669\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import rdflib\n",
|
||||
"from owlrl import DeductiveClosure, OWLRL_Extension\n",
|
||||
"\n",
|
||||
"g = rdflib.Graph()\n",
|
||||
"g.parse(\"onto.ttl\", format=\"turtle\")\n",
|
||||
"\n",
|
||||
"print(\"Triplets found:%d\" % len(g))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"では、クロージャを構築して、三つ組の数がどのように増加するか見てみましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Triplets after inference:4246\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"DeductiveClosure(OWLRL_Extension).expand(g)\n",
|
||||
"print(\"Triplets after inference:%d\" % len(g))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 親戚を検索する\n",
|
||||
"\n",
|
||||
"これで、グラフを使って人々の間のさまざまな関係を調べることができます。**SPARQL**言語を`query`メソッドと組み合わせて使用します。今回は、家系図の中で全ての**叔父**を見てみましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Fedor Alekseevich Romanov is uncle of Ekaterina Ivanovna Romanova\n",
|
||||
"Aleksandr I Pavlovich Romanov is uncle of Aleksandr II Nikolaevich Romanov\n",
|
||||
"Fedor Alekseevich Romanov is uncle of Anna Ivanovna Romanova\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"qres = g.query(\n",
|
||||
" \"\"\"SELECT DISTINCT ?aname ?bname\n",
|
||||
" WHERE {\n",
|
||||
" ?a fhkb:isUncleOf ?b .\n",
|
||||
" ?a rdfs:label ?aname .\n",
|
||||
" ?b rdfs:label ?bname .\n",
|
||||
" }\"\"\")\n",
|
||||
"\n",
|
||||
"for row in qres:\n",
|
||||
" print(\"%s is uncle of %s\" % row)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"さまざまな家族関係を試してみましょう。例えば、`isAncestorOf` 関係を使って、特定の人物のすべての祖先を再帰的に定義することができます。\n",
|
||||
"\n",
|
||||
"最後に、片付けをしましょう!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!rm onto.ttl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があります。元の言語で記載された文書を正式な情報源としてお考えください。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解について、当社は責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.6",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.11.2"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "6537d5597320e27b6052b4377b8ff8bb",
|
||||
"translation_date": "2025-08-30T09:39:13+00:00",
|
||||
"source_file": "lessons/2-Symbolic/FamilyOntology.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,548 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"source": [
|
||||
"## Microsoft Concept Graph\n",
|
||||
"\n",
|
||||
"[Microsoft Concept Graph](https://concept.research.microsoft.com/) は、インターネットから抽出された用語の大規模な分類体系で、概念間の「is-a」関係を含んでいます。\n",
|
||||
"\n",
|
||||
"Context Graph は以下の2つの形式で利用可能です:\n",
|
||||
" * ダウンロード用の大規模なテキストファイル\n",
|
||||
" * REST API\n",
|
||||
"\n",
|
||||
"統計情報:\n",
|
||||
" * 5401933 のユニークな概念\n",
|
||||
" * 12551613 のユニークなインスタンス\n",
|
||||
" * 87603947 の「is-a」関係\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Webサービスの利用方法\n",
|
||||
"\n",
|
||||
"Webサービスでは、ある概念が異なるグループに属する確率を推定するためのさまざまな呼び出しを提供しています。詳細は[こちら](https://concept.research.microsoft.com/Home/Api)をご覧ください。 \n",
|
||||
"以下は呼び出しのサンプルURLです: `https://concept.research.microsoft.com/api/Concept/ScoreByProb?instance=microsoft&topK=10`\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'company': 0.6105356614382954,\n",
|
||||
" 'vendor': 0.08858636677518003,\n",
|
||||
" 'client': 0.048239124001183784,\n",
|
||||
" 'firm': 0.045476965571668145,\n",
|
||||
" 'large company': 0.043109401203511886,\n",
|
||||
" 'organization': 0.043010752688172046,\n",
|
||||
" 'corporation': 0.035908059583703265,\n",
|
||||
" 'brand': 0.03383644076156654,\n",
|
||||
" 'software company': 0.027522935779816515,\n",
|
||||
" 'technology company': 0.023774292196902438}"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import urllib\n",
|
||||
"import json\n",
|
||||
"import ssl\n",
|
||||
"\n",
|
||||
"def http(x):\n",
|
||||
" ssl._create_default_https_context = ssl._create_unverified_context\n",
|
||||
" response = urllib.request.urlopen(x)\n",
|
||||
" data = response.read()\n",
|
||||
" return data.decode('utf-8')\n",
|
||||
"\n",
|
||||
"def query(x):\n",
|
||||
" return json.loads(http(\"https://concept.research.microsoft.com/api/Concept/ScoreByProb?instance={}&topK=10\".format(urllib.parse.quote(x))))\n",
|
||||
"\n",
|
||||
"query('microsoft')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ニュースタイトルを親概念を使って分類してみましょう。ニュースタイトルを取得するには、[NewsApi.org](http://newsapi.org) サービスを使用します。このサービスを利用するには、自分自身のAPIキーを取得する必要があります。ウェブサイトにアクセスして無料の開発者プランに登録してください。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"newsapi_key = '<your API key here>'\n",
|
||||
"def get_news(country='us'):\n",
|
||||
" res = json.loads(http(\"https://newsapi.org/v2/top-headlines?country={0}&apiKey={1}\".format(country,newsapi_key)))\n",
|
||||
" return res['articles']\n",
|
||||
"\n",
|
||||
"all_titles = [x['title'] for x in get_news('us')+get_news('gb')]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"['Covid-19 Live Updates: Vaccines and Boosters News - The New York Times',\n",
|
||||
" 'Ukrainians Flee Mariupol as Russian Forces Push to Take Port City - The Wall Street Journal',\n",
|
||||
" 'Bond Yields Jump, Stock Futures Rise After Powell Says Fed Is Ready to Be More Aggressive - The Wall Street Journal',\n",
|
||||
" 'Putin critic Alexei Navalny found guilty by Russian court - New York Post ',\n",
|
||||
" \"Supreme Court nominee Ketanji Brown Jackson will face questions at confirmation hearing's second day - CNN\",\n",
|
||||
" '2 teachers killed at Swedish high school, student arrested - ABC News',\n",
|
||||
" 'Clues to Covid-19’s Next Moves Come From Sewers - The Wall Street Journal',\n",
|
||||
" 'Republicans to roll dice by grilling Jackson over child-pornography sentencing decisions | TheHill - The Hill',\n",
|
||||
" '‘Clear sign’ Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent',\n",
|
||||
" 'NASA confirms there are 5,000 planets outside our solar system - Daily Mail',\n",
|
||||
" \"US stocks whipsawed overnight after Fed Chair Powell's remarks - Fox Business\",\n",
|
||||
" \"'We've learned absolutely nothing': Tests could again be in short supply if Covid surges - POLITICO\",\n",
|
||||
" \"Duchess of Cambridge swaps khaki jungle gear for Vampire's Wife dress on Belize trip - Daily Mail\",\n",
|
||||
" 'China searches for victims, flight recorders after first plane crash in 12 years - Reuters',\n",
|
||||
" 'Second superyacht linked to Russian oligarch Abramovich docks in Turkey - Reuters',\n",
|
||||
" 'Live updates: Russia stops talks with Japan over sanctions - The Associated Press - en Español',\n",
|
||||
" 'Powers Remain and Threats Lurk as Women’s Sweet 16 Is Set - The New York Times',\n",
|
||||
" 'Webb Space Telescope Begins Multi-Instrument Alignment - SciTechDaily',\n",
|
||||
" \"UConn vs UCF - NCAA women's tournament second-round highlights - March Madness\",\n",
|
||||
" 'Bucking Republican Trend, Indiana Governor Vetoes Transgender Sports Bill - The New York Times',\n",
|
||||
" \"Maggie Fox dead: Coronation Street and Shameless actress dies after 'sudden accident' - Mirror Online - The Mirror\",\n",
|
||||
" 'China plane crash – live: Search for survivors continues as witness describes moment flight fell from sky - The Independent',\n",
|
||||
" 'Daniel Morgan murder: damning report condemns Met police - The Guardian',\n",
|
||||
" 'What to expect from Rishi Sunak’s Spring Statement - BBC.com',\n",
|
||||
" 'UK and Republic of Ireland in line to host Euro 2028 after no one else bids - The Guardian',\n",
|
||||
" \"Friends beg Vladimir Putin's 'lover' to persuade him to end Ukraine invasion - The Mirror\",\n",
|
||||
" 'Brass Eye’s outtakes show the brutal TV comedy was the tip of an iceberg - The Guardian',\n",
|
||||
" \"Vladimir Putin threatens civilians to break Mariupol's spirit - The Times\",\n",
|
||||
" 'Shell U-turn on Cambo oilfield would threaten green targets, say campaigners - The Guardian',\n",
|
||||
" 'St Helens dog attack: Girl aged 17 months killed at home - BBC',\n",
|
||||
" \"PlayStation to buy 'Assassin's Creed' veteran Jade Raymond's Haven Studios - NME\",\n",
|
||||
" '‘Clear sign’ Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent',\n",
|
||||
" 'NASA confirms there are 5,000 planets outside our solar system - Daily Mail',\n",
|
||||
" 'Nintendo Switch finally has folders • Eurogamer.net - Eurogamer.net',\n",
|
||||
" 'FA to “find a solution” as Liverpool fan group blasts “shambolic” Wembley travel - This Is Anfield',\n",
|
||||
" 'Manchester United transfer news LIVE Erik ten Hag latest and Man Utd manager updates - Manchester Evening News',\n",
|
||||
" 'Inflation raises cost of UK government borrowing in February; crude oil up again – business live - The Guardian',\n",
|
||||
" 'Alexei Navalny: Kremlin critic found guilty of large-scale fraud and contempt of court by Russian court - Sky News',\n",
|
||||
" \"UK prepares to nationalize Russia natural gas giant Gazprom's retail unit - Business Insider\",\n",
|
||||
" 'Zaghari-Ratcliffe: Hunt calls for inquiry into delay over Iran debt payment - The Guardian']"
|
||||
]
|
||||
},
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"all_titles"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"まず第一に、ニュースのタイトルから名詞を抽出できるようにしたいと考えています。そのために、`TextBlob`ライブラリを使用します。このライブラリは、このような典型的な自然言語処理のタスクを大幅に簡素化してくれます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Requirement already satisfied: textblob in c:\\winapp\\miniconda3\\lib\\site-packages (0.17.1)\n",
|
||||
"Requirement already satisfied: nltk>=3.1 in c:\\winapp\\miniconda3\\lib\\site-packages (from textblob) (3.5)\n",
|
||||
"Requirement already satisfied: joblib in c:\\winapp\\miniconda3\\lib\\site-packages (from nltk>=3.1->textblob) (1.0.1)\n",
|
||||
"Requirement already satisfied: regex in c:\\winapp\\miniconda3\\lib\\site-packages (from nltk>=3.1->textblob) (2021.11.10)\n",
|
||||
"Requirement already satisfied: tqdm in c:\\winapp\\miniconda3\\lib\\site-packages (from nltk>=3.1->textblob) (4.61.2)\n",
|
||||
"Requirement already satisfied: click in c:\\winapp\\miniconda3\\lib\\site-packages (from nltk>=3.1->textblob) (8.0.3)\n",
|
||||
"Requirement already satisfied: colorama in c:\\winapp\\miniconda3\\lib\\site-packages (from click->nltk>=3.1->textblob) (0.4.4)\n",
|
||||
"Finished.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[nltk_data] Downloading package brown to\n",
|
||||
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
|
||||
"[nltk_data] Package brown is already up-to-date!\n",
|
||||
"[nltk_data] Downloading package punkt to\n",
|
||||
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
|
||||
"[nltk_data] Package punkt is already up-to-date!\n",
|
||||
"[nltk_data] Downloading package wordnet to\n",
|
||||
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
|
||||
"[nltk_data] Package wordnet is already up-to-date!\n",
|
||||
"[nltk_data] Downloading package averaged_perceptron_tagger to\n",
|
||||
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
|
||||
"[nltk_data] Package averaged_perceptron_tagger is already up-to-\n",
|
||||
"[nltk_data] date!\n",
|
||||
"[nltk_data] Downloading package conll2000 to\n",
|
||||
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
|
||||
"[nltk_data] Package conll2000 is already up-to-date!\n",
|
||||
"[nltk_data] Downloading package movie_reviews to\n",
|
||||
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
|
||||
"[nltk_data] Package movie_reviews is already up-to-date!\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import sys\n",
|
||||
"!{sys.executable} -m pip install textblob\n",
|
||||
"!{sys.executable} -m textblob.download_corpora\n",
|
||||
"from textblob import TextBlob"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'covid-19 live updates': 1,\n",
|
||||
" 'vaccines': 1,\n",
|
||||
" 'boosters': 1,\n",
|
||||
" 'york': 4,\n",
|
||||
" 'ukrainians flee mariupol': 1,\n",
|
||||
" 'forces push': 1,\n",
|
||||
" 'port city': 1,\n",
|
||||
" 'wall street journal': 3,\n",
|
||||
" 'bond yields': 1,\n",
|
||||
" 'futures rise': 1,\n",
|
||||
" 'powell says fed': 1,\n",
|
||||
" 'ready': 1,\n",
|
||||
" 'be': 1,\n",
|
||||
" 'aggressive': 1,\n",
|
||||
" 'putin': 3,\n",
|
||||
" 'alexei navalny': 2,\n",
|
||||
" 'russian': 2,\n",
|
||||
" 'supreme court nominee': 1,\n",
|
||||
" 'ketanji brown jackson': 1,\n",
|
||||
" \"confirmation hearing 's\": 1,\n",
|
||||
" 'cnn': 1,\n",
|
||||
" 'swedish': 1,\n",
|
||||
" 'high school': 1,\n",
|
||||
" 'abc': 1,\n",
|
||||
" 'clues': 1,\n",
|
||||
" 'covid-19': 1,\n",
|
||||
" '’ s': 2,\n",
|
||||
" 'moves': 1,\n",
|
||||
" 'sewers': 1,\n",
|
||||
" 'roll dice': 1,\n",
|
||||
" 'jackson': 1,\n",
|
||||
" 'decisions |': 1,\n",
|
||||
" 'thehill': 1,\n",
|
||||
" 'clear': 2,\n",
|
||||
" 'chemical weapons': 2,\n",
|
||||
" 'ukraine': 3,\n",
|
||||
" 'claims president': 2,\n",
|
||||
" 'biden': 2,\n",
|
||||
" 'nasa': 2,\n",
|
||||
" 'solar system': 2,\n",
|
||||
" 'daily mail': 3,\n",
|
||||
" 'us stocks': 1,\n",
|
||||
" 'fed chair powell': 1,\n",
|
||||
" \"'s remarks\": 1,\n",
|
||||
" 'fox': 1,\n",
|
||||
" \"'we 've\": 1,\n",
|
||||
" 'tests': 1,\n",
|
||||
" 'covid': 1,\n",
|
||||
" 'politico': 1,\n",
|
||||
" 'duchess': 1,\n",
|
||||
" 'cambridge': 1,\n",
|
||||
" 'swaps khaki jungle gear': 1,\n",
|
||||
" 'vampire': 1,\n",
|
||||
" 'wife': 1,\n",
|
||||
" 'belize': 1,\n",
|
||||
" 'china': 2,\n",
|
||||
" 'flight recorders': 1,\n",
|
||||
" 'plane crash': 1,\n",
|
||||
" 'reuters': 2,\n",
|
||||
" 'russian oligarch': 1,\n",
|
||||
" 'abramovich': 1,\n",
|
||||
" 'live': 1,\n",
|
||||
" 'russia': 2,\n",
|
||||
" 'stops talks': 1,\n",
|
||||
" 'japan': 1,\n",
|
||||
" 'español': 1,\n",
|
||||
" 'powers remain': 1,\n",
|
||||
" 'threats lurk': 1,\n",
|
||||
" 'set': 1,\n",
|
||||
" 'webb': 1,\n",
|
||||
" 'telescope begins multi-instrument alignment': 1,\n",
|
||||
" 'scitechdaily': 1,\n",
|
||||
" 'uconn': 1,\n",
|
||||
" 'ucf': 1,\n",
|
||||
" 'ncaa': 1,\n",
|
||||
" \"women 's tournament second-round highlights\": 1,\n",
|
||||
" 'march madness': 1,\n",
|
||||
" 'bucking republican trend': 1,\n",
|
||||
" 'indiana': 1,\n",
|
||||
" 'vetoes transgender': 1,\n",
|
||||
" 'bill': 1,\n",
|
||||
" 'maggie fox': 1,\n",
|
||||
" 'coronation': 1,\n",
|
||||
" 'shameless': 1,\n",
|
||||
" \"'sudden accident\": 1,\n",
|
||||
" 'mirror online': 1,\n",
|
||||
" 'mirror': 2,\n",
|
||||
" 'plane crash –': 1,\n",
|
||||
" 'search': 1,\n",
|
||||
" 'moment flight': 1,\n",
|
||||
" 'daniel morgan': 1,\n",
|
||||
" 'report condemns': 1,\n",
|
||||
" 'met': 1,\n",
|
||||
" 'guardian': 6,\n",
|
||||
" 'rishi sunak': 1,\n",
|
||||
" '’ s spring': 1,\n",
|
||||
" 'statement': 1,\n",
|
||||
" 'bbc.com': 1,\n",
|
||||
" 'uk': 3,\n",
|
||||
" 'ireland': 1,\n",
|
||||
" 'euro': 1,\n",
|
||||
" 'vladimir putin': 2,\n",
|
||||
" \"'s 'lover\": 1,\n",
|
||||
" 'brass eye': 1,\n",
|
||||
" '’ s outtakes': 1,\n",
|
||||
" 'brutal tv comedy': 1,\n",
|
||||
" 'threatens civilians': 1,\n",
|
||||
" 'mariupol': 1,\n",
|
||||
" \"'s spirit\": 1,\n",
|
||||
" 'shell u-turn': 1,\n",
|
||||
" 'cambo': 1,\n",
|
||||
" 'green targets': 1,\n",
|
||||
" 'st helens': 1,\n",
|
||||
" 'dog attack': 1,\n",
|
||||
" 'girl': 1,\n",
|
||||
" 'bbc': 1,\n",
|
||||
" 'playstation': 1,\n",
|
||||
" \"'assassin 's\": 1,\n",
|
||||
" 'creed': 1,\n",
|
||||
" 'jade raymond': 1,\n",
|
||||
" 'haven studios': 1,\n",
|
||||
" 'nme': 1,\n",
|
||||
" 'nintendo switch': 1,\n",
|
||||
" 'folders •': 1,\n",
|
||||
" 'eurogamer.net': 2,\n",
|
||||
" 'fa': 1,\n",
|
||||
" 'solution ”': 1,\n",
|
||||
" 'liverpool': 1,\n",
|
||||
" 'fan group blasts “ shambolic ”': 1,\n",
|
||||
" 'wembley': 1,\n",
|
||||
" 'anfield': 1,\n",
|
||||
" 'manchester': 1,\n",
|
||||
" 'live erik': 1,\n",
|
||||
" 'hag': 1,\n",
|
||||
" 'utd': 1,\n",
|
||||
" 'manager updates': 1,\n",
|
||||
" 'manchester evening': 1,\n",
|
||||
" 'inflation': 1,\n",
|
||||
" 'government borrowing': 1,\n",
|
||||
" 'february': 1,\n",
|
||||
" 'crude oil': 1,\n",
|
||||
" '– business': 1,\n",
|
||||
" 'kremlin': 1,\n",
|
||||
" 'large-scale fraud': 1,\n",
|
||||
" 'sky': 1,\n",
|
||||
" 'natural gas': 1,\n",
|
||||
" 'gazprom': 1,\n",
|
||||
" 'retail unit': 1,\n",
|
||||
" 'insider': 1,\n",
|
||||
" 'zaghari-ratcliffe': 1,\n",
|
||||
" 'hunt': 1,\n",
|
||||
" 'iran': 1,\n",
|
||||
" 'debt payment': 1}"
|
||||
]
|
||||
},
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"w = {}\n",
|
||||
"for x in all_titles:\n",
|
||||
" for n in TextBlob(x).noun_phrases:\n",
|
||||
" if n in w:\n",
|
||||
" w[n].append(x)\n",
|
||||
" else:\n",
|
||||
" w[n]=[x]\n",
|
||||
"{ x:len(w[x]) for x in w.keys()}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"名詞が大きなテーマグループを与えないことがわかります。概念グラフから得られたより一般的な用語に名詞を置き換えましょう。これは少し時間がかかりますが、各名詞句に対してRESTコールを行っているためです。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"w = {}\n",
|
||||
"for x in all_titles:\n",
|
||||
" for noun in TextBlob(x).noun_phrases:\n",
|
||||
" terms = query(noun.replace(' ','%20'))\n",
|
||||
" for term in [u for u in terms.keys() if terms[u]>0.1]:\n",
|
||||
" if term in w:\n",
|
||||
" w[term].append(x)\n",
|
||||
" else:\n",
|
||||
" w[term]=[x]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'city': 9,\n",
|
||||
" 'brand': 4,\n",
|
||||
" 'place': 9,\n",
|
||||
" 'town': 4,\n",
|
||||
" 'factor': 4,\n",
|
||||
" 'film': 4,\n",
|
||||
" 'nation': 11,\n",
|
||||
" 'state': 5,\n",
|
||||
" 'person': 4,\n",
|
||||
" 'organization': 5,\n",
|
||||
" 'publication': 10,\n",
|
||||
" 'market': 5,\n",
|
||||
" 'economy': 4,\n",
|
||||
" 'company': 6,\n",
|
||||
" 'newspaper': 6,\n",
|
||||
" 'relationship': 6}"
|
||||
]
|
||||
},
|
||||
"execution_count": 24,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"{ x:len(w[x]) for x in w.keys() if len(w[x])>3}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 27,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\n",
|
||||
"ECONOMY:\n",
|
||||
"China searches for victims, flight recorders after first plane crash in 12 years - Reuters\n",
|
||||
"Live updates: Russia stops talks with Japan over sanctions - The Associated Press - en Español\n",
|
||||
"China plane crash – live: Search for survivors continues as witness describes moment flight fell from sky - The Independent\n",
|
||||
"UK prepares to nationalize Russia natural gas giant Gazprom's retail unit - Business Insider\n",
|
||||
"\n",
|
||||
"NATION:\n",
|
||||
"‘Clear sign’ Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent\n",
|
||||
"Duchess of Cambridge swaps khaki jungle gear for Vampire's Wife dress on Belize trip - Daily Mail\n",
|
||||
"China searches for victims, flight recorders after first plane crash in 12 years - Reuters\n",
|
||||
"Live updates: Russia stops talks with Japan over sanctions - The Associated Press - en Español\n",
|
||||
"Live updates: Russia stops talks with Japan over sanctions - The Associated Press - en Español\n",
|
||||
"China plane crash – live: Search for survivors continues as witness describes moment flight fell from sky - The Independent\n",
|
||||
"UK and Republic of Ireland in line to host Euro 2028 after no one else bids - The Guardian\n",
|
||||
"Friends beg Vladimir Putin's 'lover' to persuade him to end Ukraine invasion - The Mirror\n",
|
||||
"‘Clear sign’ Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent\n",
|
||||
"UK prepares to nationalize Russia natural gas giant Gazprom's retail unit - Business Insider\n",
|
||||
"Zaghari-Ratcliffe: Hunt calls for inquiry into delay over Iran debt payment - The Guardian\n",
|
||||
"\n",
|
||||
"PERSON:\n",
|
||||
"‘Clear sign’ Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent\n",
|
||||
"Duchess of Cambridge swaps khaki jungle gear for Vampire's Wife dress on Belize trip - Daily Mail\n",
|
||||
"Second superyacht linked to Russian oligarch Abramovich docks in Turkey - Reuters\n",
|
||||
"‘Clear sign’ Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print('\\nECONOMY:\\n'+'\\n'.join(w['economy']))\n",
|
||||
"print('\\nNATION:\\n'+'\\n'.join(w['nation']))\n",
|
||||
"print('\\nPERSON:\\n'+'\\n'.join(w['person']))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書はAI翻訳サービス[Co-op Translator](https://github.com/Azure/co-op-translator)を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があります。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当社は責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.7.4 64-bit (conda)",
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
|
||||
}
|
||||
},
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.5"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "4087f998407d06ceb2947016ba4605d0",
|
||||
"translation_date": "2025-08-30T09:40:27+00:00",
|
||||
"source_file": "lessons/2-Symbolic/MSConceptGraph.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,8 +1,8 @@
|
|||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "7336583e4630220c835335da640016db",
|
||||
"translation_date": "2025-08-24T21:16:18+00:00",
|
||||
"original_hash": "ba5d1eb353d20d3e7181066b3c424b99",
|
||||
"translation_date": "2025-08-30T08:44:02+00:00",
|
||||
"source_file": "lessons/3-NeuralNetworks/03-Perceptron/lab/README.md",
|
||||
"language_code": "ja"
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ CO_OP_TRANSLATOR_METADATA:
|
|||
|
||||
## 課題
|
||||
|
||||
このレッスンで開発したMNIST手書き数字の二値分類コードを使用して、任意の数字を認識できる多クラス分類器を作成してください。訓練データセットとテストデータセットで分類精度を計算し、混同行列を出力してください。
|
||||
このレッスンで開発したコードを使用して、MNIST手書き数字の二値分類を行い、任意の数字を認識できる多クラス分類器を作成してください。訓練データセットとテストデータセットで分類精度を計算し、混同行列を出力してください。
|
||||
|
||||
## ヒント
|
||||
|
||||
|
|
@ -21,11 +21,13 @@ CO_OP_TRANSLATOR_METADATA:
|
|||
1. 二値分類用に10個の異なるパーセプトロンを訓練する(各数字に1つずつ)
|
||||
1. 入力された数字を分類する関数を定義する
|
||||
|
||||
> **ヒント**: 10個のパーセプトロンの重みを1つの行列にまとめれば、1回の行列積で入力された数字に対して10個のパーセプトロンを適用することができます。その後、出力に対して`argmax`操作を適用することで、最も可能性の高い数字を見つけることができます。
|
||||
> **ヒント**: 10個のパーセプトロンの重みを1つの行列にまとめれば、入力された数字に対して1回の行列積で全てのパーセプトロンを適用することができます。その後、出力に対して `argmax` 操作を適用することで、最も可能性の高い数字を見つけることができます。
|
||||
|
||||
## 開始ノートブック
|
||||
## スタートノートブック
|
||||
|
||||
[PerceptronMultiClass.ipynb](../../../../../../lessons/3-NeuralNetworks/03-Perceptron/lab/PerceptronMultiClass.ipynb) を開いてラボを開始してください。
|
||||
[PerceptronMultiClass.ipynb](PerceptronMultiClass.ipynb) を開いてラボを開始してください。
|
||||
|
||||
---
|
||||
|
||||
**免責事項**:
|
||||
この文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な表現が含まれる可能性があることをご承知おきください。原文(元の言語で記載された文書)が公式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。本翻訳の使用に起因する誤解や誤認について、当方は一切の責任を負いません。
|
||||
この文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知ください。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当方は一切の責任を負いません。
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,183 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# MNIST数字分類を自作フレームワークで実装\n",
|
||||
"\n",
|
||||
"[AI for Beginners Curriculum](https://github.com/microsoft/ai-for-beginners)のラボ課題。\n",
|
||||
"\n",
|
||||
"### データセットの読み込み\n",
|
||||
"\n",
|
||||
"このコードは、インターネット上のリポジトリからデータセットをダウンロードします。また、AI Curriculumリポジトリの`/data`ディレクトリから手動でデータセットをコピーすることも可能です。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
" % Total % Received % Xferd Average Speed Time Time Time Current\n",
|
||||
" Dload Upload Total Spent Left Speed\n",
|
||||
"\n",
|
||||
" 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\n",
|
||||
"100 9.9M 100 9.9M 0 0 9.9M 0 0:00:01 --:--:-- 0:00:01 15.8M\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"!rm *.pkl\n",
|
||||
"!wget https://raw.githubusercontent.com/microsoft/AI-For-Beginners/main/data/mnist.pkl.gz\n",
|
||||
"!gzip -d mnist.pkl.gz"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pickle\n",
|
||||
"with open('mnist.pkl','rb') as f:\n",
|
||||
" MNIST = pickle.load(f)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"labels = MNIST['Train']['Labels']\n",
|
||||
"data = MNIST['Train']['Features']"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"データの形状を確認してみましょう:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(42000, 784)"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"data.shape"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### データの分割\n",
|
||||
"\n",
|
||||
"データをトレーニング用とテスト用のデータセットに分割するために、Scikit Learnを使用します:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Train samples: 33600, test samples: 8400\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from sklearn.model_selection import train_test_split\n",
|
||||
"\n",
|
||||
"features_train, features_test, labels_train, labels_test = train_test_split(data,labels,test_size=0.2)\n",
|
||||
"\n",
|
||||
"print(f\"Train samples: {len(features_train)}, test samples: {len(features_test)}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 手順\n",
|
||||
"\n",
|
||||
"1. レッスンからフレームワークコードを取得し、このノートブック、または(可能であれば)別のPythonモジュールに貼り付けます。\n",
|
||||
"1. 1層のパーセプトロンを定義して訓練し、訓練中のトレーニング精度と検証精度を観察します。\n",
|
||||
"1. 過学習が発生したかどうかを理解し、層のパラメータを調整して精度を向上させます。\n",
|
||||
"1. 2層および3層のパーセプトロンについても、前の手順を繰り返します。層間で異なる活性化関数を試してみてください。\n",
|
||||
"1. 以下の質問に答えてみてください:\n",
|
||||
" - 層間の活性化関数はネットワークの性能に影響を与えますか?\n",
|
||||
" - このタスクには2層または3層のネットワークが必要ですか?\n",
|
||||
" - 層の数が増えるにつれて、ネットワークの訓練に問題が発生しましたか?\n",
|
||||
" - 訓練中にネットワークの重みはどのように振る舞いますか?エポックごとの重みの最大絶対値をプロットして、その関係を理解してみてください。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知ください。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当方は一切の責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.7.4 64-bit (conda)",
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
|
||||
}
|
||||
},
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.5"
|
||||
},
|
||||
"orig_nbformat": 2,
|
||||
"coopTranslator": {
|
||||
"original_hash": "6fa055f484eb5d6bdf41166a356d3abf",
|
||||
"translation_date": "2025-08-30T09:48:05+00:00",
|
||||
"source_file": "lessons/3-NeuralNetworks/04-OwnFramework/lab/MyFW_MNIST.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,108 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 光学フローを使用した手のひらの動き検出\n",
|
||||
"\n",
|
||||
"このラボは[AI for Beginners Curriculum](http://aka.ms/ai-beginners)の一部です。\n",
|
||||
"\n",
|
||||
"[この動画](../../../../../../lessons/4-ComputerVision/06-IntroCV/lab/palm-movement.mp4)を考えてみてください。この動画では、安定した背景の上で人の手のひらが左/右/上/下に動いています。\n",
|
||||
"\n",
|
||||
"**あなたの目標**は、光学フローを使用して、動画のどの部分が上/下/左/右の動きを含んでいるかを判定することです。\n",
|
||||
"\n",
|
||||
"まず、講義で説明されたように動画フレームを取得することから始めましょう:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Code here"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"講義で説明されたように密なオプティカルフローのフレームを計算し、密なオプティカルフローを極座標に変換してください。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Code here"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"光フレームごとに方向のヒストグラムを作成します。ヒストグラムは、特定のビンに該当するベクトルの数を示し、フレーム上の異なる移動方向を分離する必要があります。\n",
|
||||
"\n",
|
||||
"> また、ある閾値以下の大きさを持つすべてのベクトルをゼロにすることを検討してください。これにより、目や頭などの動画内の小さな余分な動きが除去されます。\n",
|
||||
"\n",
|
||||
"いくつかのフレームのヒストグラムをプロットしてください。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Code here"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ヒストグラムを見れば、移動の方向を判断する方法は非常に簡単なはずです。上下左右の方向に対応するビンを選択し、特定の閾値を超えているものを選ぶ必要があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Code here"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"おめでとうございます!上記のすべての手順を完了した場合、ラボを終了しました!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書はAI翻訳サービス[Co-op Translator](https://github.com/Azure/co-op-translator)を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があります。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤った解釈について、当方は責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
},
|
||||
"orig_nbformat": 4,
|
||||
"coopTranslator": {
|
||||
"original_hash": "153d9e417e079bf62f8f693002d0deaf",
|
||||
"translation_date": "2025-08-30T09:21:43+00:00",
|
||||
"source_file": "lessons/4-ComputerVision/06-IntroCV/lab/MovementDetection.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,577 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# テキスト分類タスク\n",
|
||||
"\n",
|
||||
"前述の通り、今回は**AG_NEWS**データセットを使用したシンプルなテキスト分類タスクに焦点を当てます。このタスクでは、ニュースの見出しを「世界」「スポーツ」「ビジネス」「科学/技術」の4つのカテゴリのいずれかに分類します。\n",
|
||||
"\n",
|
||||
"## データセット\n",
|
||||
"\n",
|
||||
"このデータセットは[`torchtext`](https://github.com/pytorch/text)モジュールに組み込まれているため、簡単にアクセスできます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import torch\n",
|
||||
"import torchtext\n",
|
||||
"import os\n",
|
||||
"import collections\n",
|
||||
"os.makedirs('./data',exist_ok=True)\n",
|
||||
"train_dataset, test_dataset = torchtext.datasets.AG_NEWS(root='./data')\n",
|
||||
"classes = ['World', 'Sports', 'Business', 'Sci/Tech']"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ここで、`train_dataset` と `test_dataset` は、それぞれクラス番号(ラベル)とテキストのペアを返すコレクションを含んでいます。例えば:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(3,\n",
|
||||
" \"Wall St. Bears Claw Back Into the Black (Reuters) Reuters - Short-sellers, Wall Street's dwindling\\\\band of ultra-cynics, are seeing green again.\")"
|
||||
]
|
||||
},
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"list(train_dataset)[0]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"では、データセットから最初の10件の新しい見出しを出力しましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"**Sci/Tech** -> Wall St. Bears Claw Back Into the Black (Reuters) Reuters - Short-sellers, Wall Street's dwindling\\band of ultra-cynics, are seeing green again.\n",
|
||||
"**Sci/Tech** -> Carlyle Looks Toward Commercial Aerospace (Reuters) Reuters - Private investment firm Carlyle Group,\\which has a reputation for making well-timed and occasionally\\controversial plays in the defense industry, has quietly placed\\its bets on another part of the market.\n",
|
||||
"**Sci/Tech** -> Oil and Economy Cloud Stocks' Outlook (Reuters) Reuters - Soaring crude prices plus worries\\about the economy and the outlook for earnings are expected to\\hang over the stock market next week during the depth of the\\summer doldrums.\n",
|
||||
"**Sci/Tech** -> Iraq Halts Oil Exports from Main Southern Pipeline (Reuters) Reuters - Authorities have halted oil export\\flows from the main pipeline in southern Iraq after\\intelligence showed a rebel militia could strike\\infrastructure, an oil official said on Saturday.\n",
|
||||
"**Sci/Tech** -> Oil prices soar to all-time record, posing new menace to US economy (AFP) AFP - Tearaway world oil prices, toppling records and straining wallets, present a new economic menace barely three months before the US presidential elections.\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"for i,x in zip(range(5),train_dataset):\n",
|
||||
" print(f\"**{classes[x[0]]}** -> {x[1]}\")\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"データセットはイテレーターであるため、データを複数回使用したい場合はリストに変換する必要があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"train_dataset, test_dataset = torchtext.datasets.AG_NEWS(root='./data')\n",
|
||||
"train_dataset = list(train_dataset)\n",
|
||||
"test_dataset = list(test_dataset)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## トークン化\n",
|
||||
"\n",
|
||||
"次に、テキストを**数値**に変換し、それをテンソルとして表現できるようにする必要があります。単語レベルの表現を求める場合、以下の2つの作業が必要です:\n",
|
||||
"* **トークナイザー**を使用してテキストを**トークン**に分割する\n",
|
||||
"* それらのトークンの**語彙**を構築する\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"['he', 'said', 'hello']"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"tokenizer = torchtext.data.utils.get_tokenizer('basic_english')\n",
|
||||
"tokenizer('He said: hello')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"counter = collections.Counter()\n",
|
||||
"for (label, line) in train_dataset:\n",
|
||||
" counter.update(tokenizer(line))\n",
|
||||
"vocab = torchtext.vocab.vocab(counter, min_freq=1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"語彙を使用することで、トークン化された文字列を簡単に数値のセットにエンコードできます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 19,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Vocab size if 95810\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[599, 3279, 97, 1220, 329, 225, 7368]"
|
||||
]
|
||||
},
|
||||
"execution_count": 19,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vocab_size = len(vocab)\n",
|
||||
"print(f\"Vocab size if {vocab_size}\")\n",
|
||||
"\n",
|
||||
"stoi = vocab.get_stoi() # dict to convert tokens to indices\n",
|
||||
"\n",
|
||||
"def encode(x):\n",
|
||||
" return [stoi[s] for s in tokenizer(x)]\n",
|
||||
"\n",
|
||||
"encode('I love to play with my words')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Bag of Words テキスト表現\n",
|
||||
"\n",
|
||||
"言葉は意味を表すため、時には文中の順序に関係なく、個々の単語を見るだけでテキストの意味を推測できることがあります。例えば、ニュースを分類する際に、*weather* や *snow* といった単語は *天気予報* を示す可能性が高く、*stocks* や *dollar* といった単語は *金融ニュース* に関連すると考えられます。\n",
|
||||
"\n",
|
||||
"**Bag of Words** (BoW) ベクトル表現は、最も一般的に使用される伝統的なベクトル表現です。各単語はベクトルのインデックスにリンクされ、ベクトル要素には特定の文書内での単語の出現回数が含まれます。\n",
|
||||
"\n",
|
||||
" \n",
|
||||
"\n",
|
||||
"> **Note**: BoW は、テキスト内の個々の単語に対するすべてのワンホットエンコードされたベクトルの合計として考えることもできます。\n",
|
||||
"\n",
|
||||
"以下は、Scikit Learn の Python ライブラリを使用して Bag of Words 表現を生成する例です:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[1, 1, 0, 2, 0, 0, 0, 0, 0]], dtype=int64)"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from sklearn.feature_extraction.text import CountVectorizer\n",
|
||||
"vectorizer = CountVectorizer()\n",
|
||||
"corpus = [\n",
|
||||
" 'I like hot dogs.',\n",
|
||||
" 'The dog ran fast.',\n",
|
||||
" 'Its hot outside.',\n",
|
||||
" ]\n",
|
||||
"vectorizer.fit_transform(corpus)\n",
|
||||
"vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"AG_NEWSデータセットのベクトル表現からbag-of-wordsベクトルを計算するには、次の関数を使用できます:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"tensor([2., 1., 2., ..., 0., 0., 0.])\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vocab_size = len(vocab)\n",
|
||||
"\n",
|
||||
"def to_bow(text,bow_vocab_size=vocab_size):\n",
|
||||
" res = torch.zeros(bow_vocab_size,dtype=torch.float32)\n",
|
||||
" for i in encode(text):\n",
|
||||
" if i<bow_vocab_size:\n",
|
||||
" res[i] += 1\n",
|
||||
" return res\n",
|
||||
"\n",
|
||||
"print(to_bow(train_dataset[0][1]))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **注意:** ここでは、デフォルトの語彙サイズを指定するためにグローバル変数 `vocab_size` を使用しています。語彙サイズが非常に大きい場合が多いため、最も頻繁に使用される単語に語彙サイズを制限することができます。`vocab_size` の値を下げて以下のコードを実行し、その影響を確認してください。精度が多少低下することが予想されますが、劇的な変化はなく、性能が向上するはずです。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## BoW分類器のトレーニング\n",
|
||||
"\n",
|
||||
"テキストのBag-of-Words表現を構築する方法を学んだので、その上で分類器をトレーニングしてみましょう。まず、トレーニング用のデータセットを変換する必要があります。すべての位置ベクトル表現をBag-of-Words表現に変換する方法です。これを実現するには、標準的なtorchの`DataLoader`に`collate_fn`パラメータとして`bowify`関数を渡します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from torch.utils.data import DataLoader\n",
|
||||
"import numpy as np \n",
|
||||
"\n",
|
||||
"# this collate function gets list of batch_size tuples, and needs to \n",
|
||||
"# return a pair of label-feature tensors for the whole minibatch\n",
|
||||
"def bowify(b):\n",
|
||||
" return (\n",
|
||||
" torch.LongTensor([t[0]-1 for t in b]),\n",
|
||||
" torch.stack([to_bow(t[1]) for t in b])\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"train_loader = DataLoader(train_dataset, batch_size=16, collate_fn=bowify, shuffle=True)\n",
|
||||
"test_loader = DataLoader(test_dataset, batch_size=16, collate_fn=bowify, shuffle=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"では、1つの線形層を含むシンプルな分類器ニューラルネットワークを定義しましょう。入力ベクトルのサイズは `vocab_size` に等しく、出力サイズはクラス数(4)に対応します。分類タスクを解いているため、最終的な活性化関数は `LogSoftmax()` です。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"net = torch.nn.Sequential(torch.nn.Linear(vocab_size,4),torch.nn.LogSoftmax(dim=1))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"これから標準的なPyTorchのトレーニングループを定義します。データセットが非常に大きいため、学習目的のために1エポックのみ、場合によっては1エポック未満でトレーニングを行います(`epoch_size`パラメータを指定することでトレーニングを制限できます)。また、トレーニング中に累積されたトレーニング精度を報告します。報告の頻度は`report_freq`パラメータを使用して指定します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def train_epoch(net,dataloader,lr=0.01,optimizer=None,loss_fn = torch.nn.NLLLoss(),epoch_size=None, report_freq=200):\n",
|
||||
" optimizer = optimizer or torch.optim.Adam(net.parameters(),lr=lr)\n",
|
||||
" net.train()\n",
|
||||
" total_loss,acc,count,i = 0,0,0,0\n",
|
||||
" for labels,features in dataloader:\n",
|
||||
" optimizer.zero_grad()\n",
|
||||
" out = net(features)\n",
|
||||
" loss = loss_fn(out,labels) #cross_entropy(out,labels)\n",
|
||||
" loss.backward()\n",
|
||||
" optimizer.step()\n",
|
||||
" total_loss+=loss\n",
|
||||
" _,predicted = torch.max(out,1)\n",
|
||||
" acc+=(predicted==labels).sum()\n",
|
||||
" count+=len(labels)\n",
|
||||
" i+=1\n",
|
||||
" if i%report_freq==0:\n",
|
||||
" print(f\"{count}: acc={acc.item()/count}\")\n",
|
||||
" if epoch_size and count>epoch_size:\n",
|
||||
" break\n",
|
||||
" return total_loss.item()/count, acc.item()/count"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 25,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3200: acc=0.8028125\n",
|
||||
"6400: acc=0.8371875\n",
|
||||
"9600: acc=0.8534375\n",
|
||||
"12800: acc=0.85765625\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(0.026090790722161722, 0.8620069296375267)"
|
||||
]
|
||||
},
|
||||
"execution_count": 25,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"train_epoch(net,train_loader,epoch_size=15000)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## バイグラム、トライグラム、Nグラム\n",
|
||||
"\n",
|
||||
"バッグオブワーズアプローチの1つの制約は、一部の単語が複数の単語で構成される表現の一部である場合があることです。例えば、「hot dog」という単語は、他の文脈での「hot」や「dog」という単語とは全く異なる意味を持ちます。「hot」と「dog」を常に同じベクトルで表現すると、モデルが混乱する可能性があります。\n",
|
||||
"\n",
|
||||
"これに対処するために、**Nグラム表現**が文書分類の手法でよく使用されます。ここでは、各単語、2単語(バイグラム)、または3単語(トライグラム)の頻度が分類器を訓練するための有用な特徴となります。例えば、バイグラム表現では、元の単語に加えて、すべての単語ペアを語彙に追加します。\n",
|
||||
"\n",
|
||||
"以下は、Scikit Learnを使用してバイグラムのバッグオブワード表現を生成する方法の例です:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 26,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Vocabulary:\n",
|
||||
" {'i': 7, 'like': 11, 'hot': 4, 'dogs': 2, 'i like': 8, 'like hot': 12, 'hot dogs': 5, 'the': 16, 'dog': 0, 'ran': 14, 'fast': 3, 'the dog': 17, 'dog ran': 1, 'ran fast': 15, 'its': 9, 'outside': 13, 'its hot': 10, 'hot outside': 6}\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[1, 0, 1, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],\n",
|
||||
" dtype=int64)"
|
||||
]
|
||||
},
|
||||
"execution_count": 26,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"bigram_vectorizer = CountVectorizer(ngram_range=(1, 2), token_pattern=r'\\b\\w+\\b', min_df=1)\n",
|
||||
"corpus = [\n",
|
||||
" 'I like hot dogs.',\n",
|
||||
" 'The dog ran fast.',\n",
|
||||
" 'Its hot outside.',\n",
|
||||
" ]\n",
|
||||
"bigram_vectorizer.fit_transform(corpus)\n",
|
||||
"print(\"Vocabulary:\\n\",bigram_vectorizer.vocabulary_)\n",
|
||||
"bigram_vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"N-gramアプローチの主な欠点は、語彙サイズが非常に速く増加し始めることです。実際には、N-gram表現を*埋め込み*などの次元削減技術と組み合わせる必要があります。この点については次のユニットで説明します。\n",
|
||||
"\n",
|
||||
"**AG News**データセットでN-gram表現を使用するには、特別なN-gram語彙を構築する必要があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 27,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Bigram vocabulary length = 1308842\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"counter = collections.Counter()\n",
|
||||
"for (label, line) in train_dataset:\n",
|
||||
" l = tokenizer(line)\n",
|
||||
" counter.update(torchtext.data.utils.ngrams_iterator(l,ngrams=2))\n",
|
||||
" \n",
|
||||
"bi_vocab = torchtext.vocab.vocab(counter, min_freq=1)\n",
|
||||
"\n",
|
||||
"print(\"Bigram vocabulary length = \",len(bi_vocab))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"次のコードを使って分類器を訓練することもできますが、それでは非常にメモリ効率が悪くなります。次のユニットでは、埋め込みを使用してバイグラム分類器を訓練します。\n",
|
||||
"\n",
|
||||
"> **Note:** テキスト内で指定された回数以上出現するn-gramのみを残すことができます。これにより、頻度の低いバイグラムが省略され、次元数が大幅に減少します。そのためには、`min_freq`パラメータを高い値に設定し、語彙の長さの変化を観察してください。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Term Frequency Inverse Document Frequency TF-IDF\n",
|
||||
"\n",
|
||||
"BoW表現では、単語の出現頻度は単語そのものに関係なく均等に重み付けされます。しかし、*a* や *in* などの頻繁に使われる単語は、専門用語に比べて分類において重要性が低いことは明らかです。実際、ほとんどのNLPタスクでは、ある単語が他の単語よりも重要である場合があります。\n",
|
||||
"\n",
|
||||
"**TF-IDF**は、**term frequency–inverse document frequency(単語頻度–逆文書頻度)**の略です。これはBoWの変形で、単語が文書に出現するかどうかを示す二値の0/1ではなく、コーパス内での単語の出現頻度に関連する浮動小数点値を使用します。\n",
|
||||
"\n",
|
||||
"より正式には、文書$j$内の単語$i$の重み$w_{ij}$は以下のように定義されます:\n",
|
||||
"$$\n",
|
||||
"w_{ij} = tf_{ij}\\times\\log({N\\over df_i})\n",
|
||||
"$$\n",
|
||||
"ここで、\n",
|
||||
"* $tf_{ij}$は文書$j$内で単語$i$が出現する回数、つまり以前に見たBoW値\n",
|
||||
"* $N$はコレクション内の文書数\n",
|
||||
"* $df_i$はコレクション全体で単語$i$を含む文書数\n",
|
||||
"\n",
|
||||
"TF-IDF値$w_{ij}$は、単語が文書内で出現する回数に比例して増加し、コーパス内でその単語を含む文書数によって調整されます。これにより、ある単語が他の単語よりも頻繁に出現する事実を補正することができます。例えば、単語がコレクション内の*すべて*の文書に出現する場合、$df_i=N$となり、$w_{ij}=0$となります。この場合、その単語は完全に無視されます。\n",
|
||||
"\n",
|
||||
"Scikit Learnを使用すれば、簡単にテキストのTF-IDFベクトル化を作成できます:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 28,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[0.43381609, 0. , 0.43381609, 0. , 0.65985664,\n",
|
||||
" 0.43381609, 0. , 0. , 0. , 0. ,\n",
|
||||
" 0. , 0. , 0. , 0. , 0. ,\n",
|
||||
" 0. ]])"
|
||||
]
|
||||
},
|
||||
"execution_count": 28,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from sklearn.feature_extraction.text import TfidfVectorizer\n",
|
||||
"vectorizer = TfidfVectorizer(ngram_range=(1,2))\n",
|
||||
"vectorizer.fit_transform(corpus)\n",
|
||||
"vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 結論\n",
|
||||
"\n",
|
||||
"しかし、TF-IDF表現は異なる単語に頻度の重みを与えるものの、意味や順序を表現することはできません。有名な言語学者J.R.ファースが1935年に述べたように、「単語の完全な意味は常に文脈に依存しており、文脈を無視した意味の研究は真剣に受け止められるべきではない」のです。このコースの後半では、言語モデルを使用してテキストから文脈情報を捉える方法を学びます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知ください。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤認について、当方は一切の責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.8.12 ('py38')",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "7b9040985e748e4e2d4c689892456ad7",
|
||||
"translation_date": "2025-08-30T10:40:32+00:00",
|
||||
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationPyTorch.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,647 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# テキスト分類タスク\n",
|
||||
"\n",
|
||||
"このモジュールでは、**[AG_NEWS](http://www.di.unipi.it/~gulli/AG_corpus_of_news_articles.html)** データセットに基づいたシンプルなテキスト分類タスクから始めます。ニュースの見出しを「World(世界)」、「Sports(スポーツ)」、「Business(ビジネス)」、「Sci/Tech(科学/技術)」の4つのカテゴリのいずれかに分類します。\n",
|
||||
"\n",
|
||||
"## データセット\n",
|
||||
"\n",
|
||||
"データセットを読み込むために、**[TensorFlow Datasets](https://www.tensorflow.org/datasets)** API を使用します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import tensorflow as tf\n",
|
||||
"from tensorflow import keras\n",
|
||||
"import tensorflow_datasets as tfds\n",
|
||||
"\n",
|
||||
"# In this tutorial, we will be training a lot of models. In order to use GPU memory cautiously,\n",
|
||||
"# we will set tensorflow option to grow GPU memory allocation when required.\n",
|
||||
"physical_devices = tf.config.list_physical_devices('GPU') \n",
|
||||
"if len(physical_devices)>0:\n",
|
||||
" tf.config.experimental.set_memory_growth(physical_devices[0], True)\n",
|
||||
"\n",
|
||||
"dataset = tfds.load('ag_news_subset')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"データセットのトレーニング部分とテスト部分には、それぞれ `dataset['train']` と `dataset['test']` を使用してアクセスできます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Length of train dataset = 120000\n",
|
||||
"Length of test dataset = 7600\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"ds_train = dataset['train']\n",
|
||||
"ds_test = dataset['test']\n",
|
||||
"\n",
|
||||
"print(f\"Length of train dataset = {len(ds_train)}\")\n",
|
||||
"print(f\"Length of test dataset = {len(ds_test)}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"私たちのデータセットから最初の10件の新しい見出しを印刷しましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3 (Sci/Tech) -> b'AMD Debuts Dual-Core Opteron Processor' b'AMD #39;s new dual-core Opteron chip is designed mainly for corporate computing applications, including databases, Web services, and financial transactions.'\n",
|
||||
"1 (Sports) -> b\"Wood's Suspension Upheld (Reuters)\" b'Reuters - Major League Baseball\\\\Monday announced a decision on the appeal filed by Chicago Cubs\\\\pitcher Kerry Wood regarding a suspension stemming from an\\\\incident earlier this season.'\n",
|
||||
"2 (Business) -> b'Bush reform may have blue states seeing red' b'President Bush #39;s quot;revenue-neutral quot; tax reform needs losers to balance its winners, and people claiming the federal deduction for state and local taxes may be in administration planners #39; sights, news reports say.'\n",
|
||||
"3 (Sci/Tech) -> b\"'Halt science decline in schools'\" b'Britain will run out of leading scientists unless science education is improved, says Professor Colin Pillinger.'\n",
|
||||
"1 (Sports) -> b'Gerrard leaves practice' b'London, England (Sports Network) - England midfielder Steven Gerrard injured his groin late in Thursday #39;s training session, but is hopeful he will be ready for Saturday #39;s World Cup qualifier against Austria.'\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"classes = ['World', 'Sports', 'Business', 'Sci/Tech']\n",
|
||||
"\n",
|
||||
"for i,x in zip(range(5),ds_train):\n",
|
||||
" print(f\"{x['label']} ({classes[x['label']]}) -> {x['title']} {x['description']}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## テキストのベクトル化\n",
|
||||
"\n",
|
||||
"次に、テキストを**数値**に変換し、テンソルとして表現できるようにする必要があります。単語レベルでの表現を行いたい場合、以下の2つのステップが必要です:\n",
|
||||
"\n",
|
||||
"* **トークナイザー**を使用してテキストを**トークン**に分割する。\n",
|
||||
"* それらのトークンの**語彙**を構築する。\n",
|
||||
"\n",
|
||||
"### 語彙サイズの制限\n",
|
||||
"\n",
|
||||
"AG Newsデータセットの例では、語彙サイズが非常に大きく、10万語以上あります。一般的に言えば、テキストにほとんど出現しない単語は必要ありません — それらは数文にしか現れず、モデルがそれらから学習することはありません。そのため、ベクトライザーのコンストラクタに引数を渡すことで、語彙サイズを小さな数に制限するのが理にかなっています。\n",
|
||||
"\n",
|
||||
"これらのステップはどちらも**TextVectorization**レイヤーを使用して処理できます。ベクトライザーオブジェクトをインスタンス化し、その後`adapt`メソッドを呼び出してすべてのテキストを処理し、語彙を構築しましょう:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"vocab_size = 50000\n",
|
||||
"vectorizer = keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size)\n",
|
||||
"vectorizer.adapt(ds_train.take(500).map(lambda x: x['title']+' '+x['description']))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **注意** 私たちは、全データセットの一部のみを使用して語彙を構築しています。これは、実行時間を短縮し、待ち時間を減らすためです。しかし、全データセットの中のいくつかの単語が語彙に含まれず、トレーニング中に無視されるリスクを伴います。そのため、全語彙サイズを使用し、`adapt`中に全データセットを処理することで最終的な精度を向上させることは可能ですが、その効果は大きくはありません。\n",
|
||||
"\n",
|
||||
"これで実際の語彙にアクセスできるようになりました:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"['', '[UNK]', 'the', 'to', 'a', 'in', 'of', 'and', 'on', 'for']\n",
|
||||
"Length of vocabulary: 5335\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vocab = vectorizer.get_vocabulary()\n",
|
||||
"vocab_size = len(vocab)\n",
|
||||
"print(vocab[:10])\n",
|
||||
"print(f\"Length of vocabulary: {vocab_size}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ベクトライザーを使用すると、任意のテキストを簡単に数値のセットにエンコードできます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tf.Tensor: shape=(7,), dtype=int64, numpy=array([ 112, 3695, 3, 304, 11, 1041, 1], dtype=int64)>"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vectorizer('I love to play with my words')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Bag-of-wordsテキスト表現\n",
|
||||
"\n",
|
||||
"言葉は意味を表すため、時には文中の順序に関係なく、個々の単語を見るだけでテキストの意味を推測できることがあります。例えば、ニュースを分類する際に、*weather*や*snow*といった単語は*天気予報*を示し、*stocks*や*dollar*といった単語は*金融ニュース*に関連する可能性があります。\n",
|
||||
"\n",
|
||||
"**Bag-of-words** (BoW)ベクトル表現は、最も理解しやすい伝統的なベクトル表現です。各単語がベクトルのインデックスにリンクされ、ベクトルの要素には、特定の文書内で各単語が出現した回数が含まれます。\n",
|
||||
"\n",
|
||||
" \n",
|
||||
"\n",
|
||||
"> **Note**: BoWは、テキスト内の個々の単語に対するすべてのone-hotエンコードされたベクトルの合計として考えることもできます。\n",
|
||||
"\n",
|
||||
"以下は、Scikit LearnのPythonライブラリを使用してBag-of-words表現を生成する例です:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[1, 1, 0, 2, 0, 0, 0, 0, 0]], dtype=int64)"
|
||||
]
|
||||
},
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from sklearn.feature_extraction.text import CountVectorizer\n",
|
||||
"sc_vectorizer = CountVectorizer()\n",
|
||||
"corpus = [\n",
|
||||
" 'I like hot dogs.',\n",
|
||||
" 'The dog ran fast.',\n",
|
||||
" 'Its hot outside.',\n",
|
||||
" ]\n",
|
||||
"sc_vectorizer.fit_transform(corpus)\n",
|
||||
"sc_vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"上記で定義したKerasベクトライザーを使用して、各単語番号をワンホットエンコーディングに変換し、それらのベクトルをすべて加算することもできます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([0., 5., 0., ..., 0., 0., 0.], dtype=float32)"
|
||||
]
|
||||
},
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def to_bow(text):\n",
|
||||
" return tf.reduce_sum(tf.one_hot(vectorizer(text),vocab_size),axis=0)\n",
|
||||
"\n",
|
||||
"to_bow('My dog likes hot dogs on a hot day.').numpy()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **注記**: Kerasの例と結果が異なることに驚くかもしれません。その理由は、Kerasの例ではベクトルの長さが語彙サイズに対応しており、この語彙はAG Newsデータセット全体から構築されています。一方、Scikit Learnの例では、サンプルテキストからその場で語彙を構築しているためです。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## BoW分類器のトレーニング\n",
|
||||
"\n",
|
||||
"テキストのバッグオブワーズ表現の作り方を学んだので、それを使う分類器をトレーニングしてみましょう。まず、データセットをバッグオブワーズ表現に変換する必要があります。これは、次のように`map`関数を使うことで実現できます:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"batch_size = 128\n",
|
||||
"\n",
|
||||
"ds_train_bow = ds_train.map(lambda x: (to_bow(x['title']+x['description']),x['label'])).batch(batch_size)\n",
|
||||
"ds_test_bow = ds_test.map(lambda x: (to_bow(x['title']+x['description']),x['label'])).batch(batch_size)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"では、1つの線形層を含むシンプルな分類器ニューラルネットワークを定義しましょう。入力サイズは`vocab_size`で、出力サイズはクラス数(4)に対応します。分類タスクを解くため、最終的な活性化関数は**softmax**です。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"938/938 [==============================] - 66s 70ms/step - loss: 0.6144 - acc: 0.8427 - val_loss: 0.4416 - val_acc: 0.8697\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<keras.callbacks.History at 0x20c70a947f0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model = keras.models.Sequential([\n",
|
||||
" keras.layers.Dense(4,activation='softmax',input_shape=(vocab_size,))\n",
|
||||
"])\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
|
||||
"model.fit(ds_train_bow,validation_data=ds_test_bow)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"4つのクラスがあるため、80%以上の精度は良い結果と言えます。\n",
|
||||
"\n",
|
||||
"## 1つのネットワークとして分類器を訓練する\n",
|
||||
"\n",
|
||||
"ベクトライザもKerasのレイヤーであるため、それを含むネットワークを定義し、エンドツーエンドで訓練することができます。この方法では、`map`を使ってデータセットをベクトル化する必要がなく、元のデータセットをそのままネットワークの入力に渡すことができます。\n",
|
||||
"\n",
|
||||
"> **Note**: データセット内のフィールド(例えば`title`、`description`、`label`など)を辞書からタプルに変換するために、データセットに対して`map`を適用する必要は依然としてあります。ただし、ディスクからデータを読み込む際に、最初から必要な構造を持つデータセットを構築することが可能です。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"model\"\n",
|
||||
"_________________________________________________________________\n",
|
||||
" Layer (type) Output Shape Param # \n",
|
||||
"=================================================================\n",
|
||||
" input_1 (InputLayer) [(None, 1)] 0 \n",
|
||||
" \n",
|
||||
" text_vectorization (TextVec (None, None) 0 \n",
|
||||
" torization) \n",
|
||||
" \n",
|
||||
" tf.one_hot (TFOpLambda) (None, None, 5335) 0 \n",
|
||||
" \n",
|
||||
" tf.math.reduce_sum (TFOpLam (None, 5335) 0 \n",
|
||||
" bda) \n",
|
||||
" \n",
|
||||
" dense_2 (Dense) (None, 4) 21344 \n",
|
||||
" \n",
|
||||
"=================================================================\n",
|
||||
"Total params: 21,344\n",
|
||||
"Trainable params: 21,344\n",
|
||||
"Non-trainable params: 0\n",
|
||||
"_________________________________________________________________\n",
|
||||
"938/938 [==============================] - 73s 77ms/step - loss: 0.6057 - acc: 0.8414 - val_loss: 0.4202 - val_acc: 0.8736\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<keras.callbacks.History at 0x20c721521f0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def extract_text(x):\n",
|
||||
" return x['title']+' '+x['description']\n",
|
||||
"\n",
|
||||
"def tupelize(x):\n",
|
||||
" return (extract_text(x),x['label'])\n",
|
||||
"\n",
|
||||
"inp = keras.Input(shape=(1,),dtype=tf.string)\n",
|
||||
"x = vectorizer(inp)\n",
|
||||
"x = tf.reduce_sum(tf.one_hot(x,vocab_size),axis=1)\n",
|
||||
"out = keras.layers.Dense(4,activation='softmax')(x)\n",
|
||||
"model = keras.models.Model(inp,out)\n",
|
||||
"model.summary()\n",
|
||||
"\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## バイグラム、トライグラム、n-グラム\n",
|
||||
"\n",
|
||||
"Bag-of-wordsアプローチの制約の一つは、いくつかの単語が複数の単語からなる表現の一部である場合があることです。例えば、「hot dog」という単語は、他の文脈で使われる「hot」や「dog」という単語とは全く異なる意味を持ちます。「hot」と「dog」を常に同じベクトルで表現すると、モデルが混乱する可能性があります。\n",
|
||||
"\n",
|
||||
"これに対処するために、**n-グラム表現**が文書分類の手法でよく使用されます。ここでは、各単語、2語の組み合わせ(バイグラム)、または3語の組み合わせ(トライグラム)の頻度が、分類器を訓練するための有用な特徴となります。例えば、バイグラム表現では、元の単語に加えて、すべての単語ペアを語彙に追加します。\n",
|
||||
"\n",
|
||||
"以下は、Scikit Learnを使用してバイグラムのBag-of-Words表現を生成する例です:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Vocabulary:\n",
|
||||
" {'i': 7, 'like': 11, 'hot': 4, 'dogs': 2, 'i like': 8, 'like hot': 12, 'hot dogs': 5, 'the': 16, 'dog': 0, 'ran': 14, 'fast': 3, 'the dog': 17, 'dog ran': 1, 'ran fast': 15, 'its': 9, 'outside': 13, 'its hot': 10, 'hot outside': 6}\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[1, 0, 1, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],\n",
|
||||
" dtype=int64)"
|
||||
]
|
||||
},
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"bigram_vectorizer = CountVectorizer(ngram_range=(1, 2), token_pattern=r'\\b\\w+\\b', min_df=1)\n",
|
||||
"corpus = [\n",
|
||||
" 'I like hot dogs.',\n",
|
||||
" 'The dog ran fast.',\n",
|
||||
" 'Its hot outside.',\n",
|
||||
" ]\n",
|
||||
"bigram_vectorizer.fit_transform(corpus)\n",
|
||||
"print(\"Vocabulary:\\n\",bigram_vectorizer.vocabulary_)\n",
|
||||
"bigram_vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"n-gramアプローチの主な欠点は、語彙サイズが非常に速く増加し始めることです。実際には、n-gram表現を次のユニットで説明する*埋め込み*のような次元削減技術と組み合わせる必要があります。\n",
|
||||
"\n",
|
||||
"**AG News**データセットでn-gram表現を使用するには、`TextVectorization`コンストラクタに`ngrams`パラメータを渡す必要があります。バイグラム語彙の長さは**非常に大きく**、私たちの場合では130万以上のトークンがあります!したがって、バイグラムトークンを適切な数に制限するのが理にかなっています。\n",
|
||||
"\n",
|
||||
"上記と同じコードを使用して分類器を訓練することもできますが、それは非常にメモリ効率が悪いでしょう。次のユニットでは、埋め込みを使用してバイグラム分類器を訓練します。それまでの間、このノートブックでバイグラム分類器の訓練を試して、より高い精度を得られるかどうか試してみてください。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## BoWベクトルの自動計算\n",
|
||||
"\n",
|
||||
"上記の例では、個々の単語のワンホットエンコーディングを合計することで、手動でBoWベクトルを計算しました。しかし、TensorFlowの最新バージョンでは、ベクトライザーのコンストラクタに`output_mode='count'`パラメータを渡すことで、BoWベクトルを自動的に計算することができます。これにより、モデルの定義とトレーニングが大幅に簡単になります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Training vectorizer\n",
|
||||
"938/938 [==============================] - 7s 7ms/step - loss: 0.5929 - acc: 0.8486 - val_loss: 0.4168 - val_acc: 0.8772\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<keras.callbacks.History at 0x20c725217c0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model = keras.models.Sequential([\n",
|
||||
" keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,output_mode='count'),\n",
|
||||
" keras.layers.Dense(4,input_shape=(vocab_size,), activation='softmax')\n",
|
||||
"])\n",
|
||||
"print(\"Training vectorizer\")\n",
|
||||
"model.layers[0].adapt(ds_train.take(500).map(extract_text))\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 頻度-逆文書頻度 (TF-IDF)\n",
|
||||
"\n",
|
||||
"BoW(Bag of Words)表現では、単語の出現頻度は単語そのものに関係なく同じ方法で重み付けされます。しかし、*a* や *in* のような頻出単語は、専門用語に比べて分類において重要性が低いことは明らかです。ほとんどのNLPタスクでは、ある単語が他の単語よりも重要である場合があります。\n",
|
||||
"\n",
|
||||
"**TF-IDF**は、**頻度-逆文書頻度**を意味します。これはBag of Wordsの変形で、単語が文書内に出現するかどうかを示す二値の0/1ではなく、コーパス内での単語の出現頻度に関連する浮動小数点値を使用します。\n",
|
||||
"\n",
|
||||
"より正式には、文書$j$内の単語$i$の重み$w_{ij}$は以下のように定義されます:\n",
|
||||
"$$\n",
|
||||
"w_{ij} = tf_{ij}\\times\\log({N\\over df_i})\n",
|
||||
"$$\n",
|
||||
"ここで、\n",
|
||||
"* $tf_{ij}$ は文書$j$内で単語$i$が出現した回数、つまり以前見たBoW値\n",
|
||||
"* $N$ はコレクション内の文書数\n",
|
||||
"* $df_i$ はコレクション全体で単語$i$を含む文書数\n",
|
||||
"\n",
|
||||
"TF-IDF値$w_{ij}$は、単語が文書内で出現する回数に比例して増加し、その単語を含むコーパス内の文書数によって調整されます。これにより、ある単語が他の単語よりも頻繁に出現する事実を補正します。例えば、単語がコレクション内の*すべての*文書に出現する場合、$df_i=N$となり、$w_{ij}=0$となります。この場合、その単語は完全に無視されます。\n",
|
||||
"\n",
|
||||
"Scikit Learnを使用すれば、簡単にテキストのTF-IDFベクトル化を作成できます:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[0.43381609, 0. , 0.43381609, 0. , 0.65985664,\n",
|
||||
" 0.43381609, 0. , 0. , 0. , 0. ,\n",
|
||||
" 0. , 0. , 0. , 0. , 0. ,\n",
|
||||
" 0. ]])"
|
||||
]
|
||||
},
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from sklearn.feature_extraction.text import TfidfVectorizer\n",
|
||||
"vectorizer = TfidfVectorizer(ngram_range=(1,2))\n",
|
||||
"vectorizer.fit_transform(corpus)\n",
|
||||
"vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Kerasでは、`TextVectorization`レイヤーに`output_mode='tf-idf'`パラメータを渡すことで、TF-IDF頻度を自動的に計算できます。TF-IDFを使用すると精度が向上するかどうか確認するために、上記で使用したコードを繰り返してみましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Training vectorizer\n",
|
||||
"938/938 [==============================] - 12s 12ms/step - loss: 0.4197 - acc: 0.8662 - val_loss: 0.3432 - val_acc: 0.8849\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<keras.callbacks.History at 0x20c729dfd30>"
|
||||
]
|
||||
},
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model = keras.models.Sequential([\n",
|
||||
" keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,output_mode='tf-idf'),\n",
|
||||
" keras.layers.Dense(4,input_shape=(vocab_size,), activation='softmax')\n",
|
||||
"])\n",
|
||||
"print(\"Training vectorizer\")\n",
|
||||
"model.layers[0].adapt(ds_train.take(500).map(extract_text))\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 結論\n",
|
||||
"\n",
|
||||
"TF-IDF表現は異なる単語に頻度の重みを与えることができますが、意味や順序を表現することはできません。有名な言語学者J.R.ファースが1935年に言ったように、「単語の完全な意味は常に文脈的であり、文脈を離れた意味の研究は真剣に受け止められるべきではない。」このコースの後半では、言語モデルを使用してテキストから文脈情報を捉える方法を学びます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知ください。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当方は一切の責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "0cb620c6d4b9f7a635928804c26cf22403d89d98d79684e4529119355ee6d5a5"
|
||||
},
|
||||
"kernel_info": {
|
||||
"name": "conda-env-py37_tensorflow-py"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "py37_tensorflow",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"nteract": {
|
||||
"version": "nteract-front-end@1.0.0"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "19b43951d55b377a76209c24c1f017e4",
|
||||
"translation_date": "2025-08-30T10:43:21+00:00",
|
||||
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationTF.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -0,0 +1,724 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 埋め込み\n",
|
||||
"\n",
|
||||
"前回の例では、`vocab_size`の長さを持つ高次元のバッグオブワードベクトルを操作し、低次元の位置表現ベクトルからスパースなワンホット表現に明示的に変換していました。このワンホット表現はメモリ効率が良くない上に、各単語が互いに独立して扱われます。つまり、ワンホットエンコードされたベクトルは単語間の意味的な類似性を表現しません。\n",
|
||||
"\n",
|
||||
"このユニットでは、**News AG**データセットを引き続き探求します。まず、データをロードし、前のノートブックからいくつかの定義を取得しましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Loading dataset...\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"d:\\WORK\\ai-for-beginners\\5-NLP\\14-Embeddings\\data\\train.csv: 29.5MB [00:01, 18.8MB/s] \n",
|
||||
"d:\\WORK\\ai-for-beginners\\5-NLP\\14-Embeddings\\data\\test.csv: 1.86MB [00:00, 11.2MB/s] \n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Building vocab...\n",
|
||||
"Vocab size = 95812\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import torch\n",
|
||||
"import torchtext\n",
|
||||
"import numpy as np\n",
|
||||
"from torchnlp import *\n",
|
||||
"train_dataset, test_dataset, classes, vocab = load_dataset()\n",
|
||||
"vocab_size = len(vocab)\n",
|
||||
"print(\"Vocab size = \",vocab_size)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 埋め込みとは?\n",
|
||||
"\n",
|
||||
"**埋め込み**のアイデアは、単語を低次元の密なベクトルで表現し、その単語の意味を何らかの形で反映させることです。後ほど意味のある単語埋め込みを構築する方法について説明しますが、今は単語ベクトルの次元を下げる方法として埋め込みを考えてみましょう。\n",
|
||||
"\n",
|
||||
"埋め込み層は単語を入力として受け取り、指定された`embedding_size`の出力ベクトルを生成します。ある意味では`Linear`層に非常に似ていますが、ワンホットエンコードされたベクトルを受け取る代わりに、単語番号を入力として受け取ることができます。\n",
|
||||
"\n",
|
||||
"ネットワークの最初の層として埋め込み層を使用することで、バッグオブワードモデルから**埋め込みバッグ**モデルに切り替えることができます。このモデルでは、まずテキスト内の各単語を対応する埋め込みに変換し、それらの埋め込み全体に対して`sum`、`average`、`max`などの集約関数を計算します。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"私たちの分類器ニューラルネットワークは、埋め込み層、集約層、そしてその上に線形分類器を持つ構造になります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class EmbedClassifier(torch.nn.Module):\n",
|
||||
" def __init__(self, vocab_size, embed_dim, num_class):\n",
|
||||
" super().__init__()\n",
|
||||
" self.embedding = torch.nn.Embedding(vocab_size, embed_dim)\n",
|
||||
" self.fc = torch.nn.Linear(embed_dim, num_class)\n",
|
||||
"\n",
|
||||
" def forward(self, x):\n",
|
||||
" x = self.embedding(x)\n",
|
||||
" x = torch.mean(x,dim=1)\n",
|
||||
" return self.fc(x)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 可変なシーケンスサイズへの対応\n",
|
||||
"\n",
|
||||
"このアーキテクチャの結果として、ネットワークに渡すミニバッチを特定の方法で作成する必要があります。前のユニットでは、Bag-of-Words(BoW)を使用している際、ミニバッチ内のすべてのBoWテンソルはテキストシーケンスの実際の長さに関係なく、`vocab_size`という同じサイズを持っていました。しかし、単語埋め込み(word embeddings)に移行すると、各テキストサンプル内の単語数が可変となり、それらのサンプルをミニバッチにまとめる際にはパディングを適用する必要があります。\n",
|
||||
"\n",
|
||||
"これを実現するには、データソースに`collate_fn`関数を提供するという同じ手法を使用します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def padify(b):\n",
|
||||
" # b is the list of tuples of length batch_size\n",
|
||||
" # - first element of a tuple = label, \n",
|
||||
" # - second = feature (text sequence)\n",
|
||||
" # build vectorized sequence\n",
|
||||
" v = [encode(x[1]) for x in b]\n",
|
||||
" # first, compute max length of a sequence in this minibatch\n",
|
||||
" l = max(map(len,v))\n",
|
||||
" return ( # tuple of two tensors - labels and features\n",
|
||||
" torch.LongTensor([t[0]-1 for t in b]),\n",
|
||||
" torch.stack([torch.nn.functional.pad(torch.tensor(t),(0,l-len(t)),mode='constant',value=0) for t in v])\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=padify, shuffle=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 埋め込み分類器のトレーニング\n",
|
||||
"\n",
|
||||
"適切なデータローダーを定義したので、前のユニットで定義したトレーニング関数を使ってモデルをトレーニングすることができます:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3200: acc=0.6415625\n",
|
||||
"6400: acc=0.6865625\n",
|
||||
"9600: acc=0.7103125\n",
|
||||
"12800: acc=0.726953125\n",
|
||||
"16000: acc=0.739375\n",
|
||||
"19200: acc=0.75046875\n",
|
||||
"22400: acc=0.7572321428571429\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(0.889799795315499, 0.7623160588611644)"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"net = EmbedClassifier(vocab_size,32,len(classes)).to(device)\n",
|
||||
"train_epoch(net,train_loader, lr=1, epoch_size=25000)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **注意**: 時間の都合上、ここでは25,000件のレコード(1エポック未満)のみをトレーニングしていますが、トレーニングを続けたり、複数のエポックをトレーニングする関数を書いたり、学習率のパラメータを調整して精度を向上させることができます。約90%の精度に到達することが可能なはずです。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### EmbeddingBagレイヤーと可変長シーケンスの表現\n",
|
||||
"\n",
|
||||
"以前のアーキテクチャでは、すべてのシーケンスを同じ長さにパディングしてミニバッチに収める必要がありました。しかし、これは可変長シーケンスを表現する最も効率的な方法ではありません。別のアプローチとして、**オフセット**ベクトルを使用する方法があります。このベクトルは、1つの大きなベクトルに格納されたすべてのシーケンスのオフセットを保持します。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"> **Note**: 上の図では文字のシーケンスを示していますが、この例では単語のシーケンスを扱っています。ただし、オフセットベクトルでシーケンスを表現するという基本的な原則は同じです。\n",
|
||||
"\n",
|
||||
"オフセット表現を扱うために、[`EmbeddingBag`](https://pytorch.org/docs/stable/generated/torch.nn.EmbeddingBag.html)レイヤーを使用します。このレイヤーは`Embedding`に似ていますが、コンテンツベクトルとオフセットベクトルを入力として受け取り、さらに平均化レイヤーを含みます。この平均化レイヤーは`mean`、`sum`、または`max`を選択できます。\n",
|
||||
"\n",
|
||||
"以下は、`EmbeddingBag`を使用するように修正されたネットワークの例です:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class EmbedClassifier(torch.nn.Module):\n",
|
||||
" def __init__(self, vocab_size, embed_dim, num_class):\n",
|
||||
" super().__init__()\n",
|
||||
" self.embedding = torch.nn.EmbeddingBag(vocab_size, embed_dim)\n",
|
||||
" self.fc = torch.nn.Linear(embed_dim, num_class)\n",
|
||||
"\n",
|
||||
" def forward(self, text, off):\n",
|
||||
" x = self.embedding(text, off)\n",
|
||||
" return self.fc(x)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"トレーニング用のデータセットを準備するために、オフセットベクトルを準備する変換関数を提供する必要があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def offsetify(b):\n",
|
||||
" # first, compute data tensor from all sequences\n",
|
||||
" x = [torch.tensor(encode(t[1])) for t in b]\n",
|
||||
" # now, compute the offsets by accumulating the tensor of sequence lengths\n",
|
||||
" o = [0] + [len(t) for t in x]\n",
|
||||
" o = torch.tensor(o[:-1]).cumsum(dim=0)\n",
|
||||
" return ( \n",
|
||||
" torch.LongTensor([t[0]-1 for t in b]), # labels\n",
|
||||
" torch.cat(x), # text \n",
|
||||
" o\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=offsetify, shuffle=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"前回の例とは異なり、今回のネットワークは2つのパラメータを受け取ります。データベクトルとオフセットベクトルで、それぞれサイズが異なります。同様に、データローダーも2つではなく3つの値を提供します。テキストベクトルとオフセットベクトルの両方が特徴として提供されます。そのため、これに対応するためにトレーニング関数を少し調整する必要があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3200: acc=0.6153125\n",
|
||||
"6400: acc=0.6615625\n",
|
||||
"9600: acc=0.6932291666666667\n",
|
||||
"12800: acc=0.715078125\n",
|
||||
"16000: acc=0.7270625\n",
|
||||
"19200: acc=0.7382291666666667\n",
|
||||
"22400: acc=0.7486160714285715\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(22.771553103007037, 0.7551983365323096)"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"net = EmbedClassifier(vocab_size,32,len(classes)).to(device)\n",
|
||||
"\n",
|
||||
"def train_epoch_emb(net,dataloader,lr=0.01,optimizer=None,loss_fn = torch.nn.CrossEntropyLoss(),epoch_size=None, report_freq=200):\n",
|
||||
" optimizer = optimizer or torch.optim.Adam(net.parameters(),lr=lr)\n",
|
||||
" loss_fn = loss_fn.to(device)\n",
|
||||
" net.train()\n",
|
||||
" total_loss,acc,count,i = 0,0,0,0\n",
|
||||
" for labels,text,off in dataloader:\n",
|
||||
" optimizer.zero_grad()\n",
|
||||
" labels,text,off = labels.to(device), text.to(device), off.to(device)\n",
|
||||
" out = net(text, off)\n",
|
||||
" loss = loss_fn(out,labels) #cross_entropy(out,labels)\n",
|
||||
" loss.backward()\n",
|
||||
" optimizer.step()\n",
|
||||
" total_loss+=loss\n",
|
||||
" _,predicted = torch.max(out,1)\n",
|
||||
" acc+=(predicted==labels).sum()\n",
|
||||
" count+=len(labels)\n",
|
||||
" i+=1\n",
|
||||
" if i%report_freq==0:\n",
|
||||
" print(f\"{count}: acc={acc.item()/count}\")\n",
|
||||
" if epoch_size and count>epoch_size:\n",
|
||||
" break\n",
|
||||
" return total_loss.item()/count, acc.item()/count\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"train_epoch_emb(net,train_loader, lr=4, epoch_size=25000)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## セマンティック埋め込み: Word2Vec\n",
|
||||
"\n",
|
||||
"前回の例では、モデルの埋め込み層が単語をベクトル表現にマッピングする方法を学びましたが、この表現にはあまり意味的な要素がありませんでした。似たような単語や同義語が、あるベクトル距離(例えばユークリッド距離)に基づいて互いに近いベクトルに対応するようなベクトル表現を学ぶことができれば便利です。\n",
|
||||
"\n",
|
||||
"そのためには、特定の方法で大量のテキストコレクションを使って埋め込みモデルを事前学習する必要があります。セマンティック埋め込みを学習する最初の方法の一つが [Word2Vec](https://en.wikipedia.org/wiki/Word2vec) と呼ばれるものです。これは、単語の分散表現を生成するために使用される2つの主要なアーキテクチャに基づいています:\n",
|
||||
"\n",
|
||||
" - **連続型バッグオブワーズ** (CBoW) — このアーキテクチャでは、周囲のコンテキストから単語を予測するようにモデルを訓練します。ngram $(W_{-2},W_{-1},W_0,W_1,W_2)$ が与えられた場合、モデルの目標は $(W_{-2},W_{-1},W_1,W_2)$ から $W_0$ を予測することです。\n",
|
||||
" - **連続型スキップグラム** — CBoWとは逆のアプローチです。このモデルは、周囲のコンテキスト単語のウィンドウを使用して現在の単語を予測します。\n",
|
||||
"\n",
|
||||
"CBoWは高速ですが、スキップグラムは遅いものの、頻度の低い単語をより良く表現することができます。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"Google Newsデータセットで事前学習されたWord2Vec埋め込みを試すには、**gensim** ライブラリを使用することができます。以下は「neural」に最も類似した単語を見つける例です。\n",
|
||||
"\n",
|
||||
"> **Note:** 初めて単語ベクトルを作成する際、ダウンロードに時間がかかる場合があります!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import gensim.downloader as api\n",
|
||||
"w2v = api.load('word2vec-google-news-300')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"neuronal -> 0.7804799675941467\n",
|
||||
"neurons -> 0.7326500415802002\n",
|
||||
"neural_circuits -> 0.7252851724624634\n",
|
||||
"neuron -> 0.7174385190010071\n",
|
||||
"cortical -> 0.6941086649894714\n",
|
||||
"brain_circuitry -> 0.6923246383666992\n",
|
||||
"synaptic -> 0.6699118614196777\n",
|
||||
"neural_circuitry -> 0.6638563275337219\n",
|
||||
"neurochemical -> 0.6555314064025879\n",
|
||||
"neuronal_activity -> 0.6531826257705688\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"for w,p in w2v.most_similar('neural'):\n",
|
||||
" print(f\"{w} -> {p}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"単語からベクトル埋め込みを計算し、分類モデルの訓練に使用することもできます(明確にするためにベクトルの最初の20成分のみを表示します):\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([ 0.01226807, 0.06225586, 0.10693359, 0.05810547, 0.23828125,\n",
|
||||
" 0.03686523, 0.05151367, -0.20703125, 0.01989746, 0.10058594,\n",
|
||||
" -0.03759766, -0.1015625 , -0.15820312, -0.08105469, -0.0390625 ,\n",
|
||||
" -0.05053711, 0.16015625, 0.2578125 , 0.10058594, -0.25976562],\n",
|
||||
" dtype=float32)"
|
||||
]
|
||||
},
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"w2v.word_vec('play')[:20]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"セマンティカル埋め込みの素晴らしい点は、ベクトルエンコーディングを操作して意味を変更できることです。例えば、*king* と *woman* にできるだけ近く、*man* からできるだけ遠いベクトル表現を持つ単語を見つけるように求めることができます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"('queen', 0.7118192911148071)"
|
||||
]
|
||||
},
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"w2v.most_similar(positive=['king','woman'],negative=['man'])[0]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"CBoWとSkip-Gramsはどちらも「予測型」の埋め込みであり、ローカルな文脈のみを考慮します。Word2Vecはグローバルな文脈を活用しません。\n",
|
||||
"\n",
|
||||
"**FastText**は、Word2Vecを基盤にして、各単語とその中に含まれる文字n-gramのベクトル表現を学習します。これらの表現の値は、各トレーニングステップで1つのベクトルに平均化されます。このプロセスは事前学習に多くの追加計算を必要としますが、単語埋め込みがサブワード情報をエンコードできるようにします。\n",
|
||||
"\n",
|
||||
"別の手法である**GloVe**は、共起行列のアイデアを活用し、ニューラル手法を用いて共起行列をより表現力があり非線形な単語ベクトルに分解します。\n",
|
||||
"\n",
|
||||
"gensimは複数の単語埋め込みモデルをサポートしているため、埋め込みをFastTextやGloVeに変更して例を試すことができます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## PyTorchで事前学習済みの埋め込みを使用する\n",
|
||||
"\n",
|
||||
"上記の例を修正して、埋め込み層の行列をWord2Vecのような意味的な埋め込みで事前に初期化することができます。事前学習済みの埋め込みの語彙と私たちのテキストコーパスの語彙が一致しない可能性が高いため、欠けている単語の重みはランダムな値で初期化する必要があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Embedding size: 300\n",
|
||||
"Populating matrix, this will take some time...Done, found 41080 words, 54732 words missing\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"embed_size = len(w2v.get_vector('hello'))\n",
|
||||
"print(f'Embedding size: {embed_size}')\n",
|
||||
"\n",
|
||||
"net = EmbedClassifier(vocab_size,embed_size,len(classes))\n",
|
||||
"\n",
|
||||
"print('Populating matrix, this will take some time...',end='')\n",
|
||||
"found, not_found = 0,0\n",
|
||||
"for i,w in enumerate(vocab.get_itos()):\n",
|
||||
" try:\n",
|
||||
" net.embedding.weight[i].data = torch.tensor(w2v.get_vector(w))\n",
|
||||
" found+=1\n",
|
||||
" except:\n",
|
||||
" net.embedding.weight[i].data = torch.normal(0.0,1.0,(embed_size,))\n",
|
||||
" not_found+=1\n",
|
||||
"\n",
|
||||
"print(f\"Done, found {found} words, {not_found} words missing\")\n",
|
||||
"net = net.to(device)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"では、モデルを訓練しましょう。モデルの訓練にかかる時間は、埋め込み層のサイズが大きく、パラメータの数が非常に多いため、前の例よりもかなり長くなります。また、この理由から、過学習を避けたい場合は、より多くの例でモデルを訓練する必要があるかもしれません。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3200: acc=0.6359375\n",
|
||||
"6400: acc=0.68109375\n",
|
||||
"9600: acc=0.7067708333333333\n",
|
||||
"12800: acc=0.723671875\n",
|
||||
"16000: acc=0.73625\n",
|
||||
"19200: acc=0.7463541666666667\n",
|
||||
"22400: acc=0.7560714285714286\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(214.1013875559821, 0.7626759436980166)"
|
||||
]
|
||||
},
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"train_epoch_emb(net,train_loader, lr=4, epoch_size=25000)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"私たちの場合、精度の大幅な向上は見られませんでした。これは、おそらく異なる語彙が原因です。 \n",
|
||||
"異なる語彙の問題を克服するために、以下のいずれかの解決策を使用できます: \n",
|
||||
"* 自分の語彙でword2vecモデルを再学習する \n",
|
||||
"* 事前学習済みのword2vecモデルの語彙を使用してデータセットを読み込む。データセットを読み込む際に使用する語彙は指定可能です。 \n",
|
||||
"\n",
|
||||
"後者のアプローチの方が簡単に思えます。特に、PyTorchの`torchtext`フレームワークには埋め込みの組み込みサポートが含まれているためです。例えば、以下の方法でGloVeベースの語彙をインスタンス化できます: \n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"100%|█████████▉| 399999/400000 [00:15<00:00, 25411.14it/s]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vocab = torchtext.vocab.GloVe(name='6B', dim=50)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ロードされた語彙には、以下の基本的な操作があります:\n",
|
||||
"* `vocab.stoi` 辞書を使用すると、単語を辞書のインデックスに変換できます\n",
|
||||
"* `vocab.itos` はその逆で、数字を単語に変換します\n",
|
||||
"* `vocab.vectors` は埋め込みベクトルの配列で、単語 `s` の埋め込みを取得するには、`vocab.vectors[vocab.stoi[s]]` を使用する必要があります\n",
|
||||
"\n",
|
||||
"以下は、埋め込みを操作して方程式 **kind-man+woman = queen** を示す例です(少し係数を調整して動作させました):\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'queen'"
|
||||
]
|
||||
},
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# get the vector corresponding to kind-man+woman\n",
|
||||
"qvec = vocab.vectors[vocab.stoi['king']]-vocab.vectors[vocab.stoi['man']]+1.3*vocab.vectors[vocab.stoi['woman']]\n",
|
||||
"# find the index of the closest embedding vector \n",
|
||||
"d = torch.sum((vocab.vectors-qvec)**2,dim=1)\n",
|
||||
"min_idx = torch.argmin(d)\n",
|
||||
"# find the corresponding word\n",
|
||||
"vocab.itos[min_idx]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"GloVeの語彙を使用してデータセットをエンコードする必要があります。その埋め込みを使用して分類器を訓練するには、まずデータセットをエンコードする必要があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def offsetify(b):\n",
|
||||
" # first, compute data tensor from all sequences\n",
|
||||
" x = [torch.tensor(encode(t[1],voc=vocab)) for t in b] # pass the instance of vocab to encode function!\n",
|
||||
" # now, compute the offsets by accumulating the tensor of sequence lengths\n",
|
||||
" o = [0] + [len(t) for t in x]\n",
|
||||
" o = torch.tensor(o[:-1]).cumsum(dim=0)\n",
|
||||
" return ( \n",
|
||||
" torch.LongTensor([t[0]-1 for t in b]), # labels\n",
|
||||
" torch.cat(x), # text \n",
|
||||
" o\n",
|
||||
" )"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"上記のように、すべてのベクトル埋め込みは `vocab.vectors` 行列に保存されています。これにより、単純なコピーを使用して埋め込み層の重みにそれらの重みをロードすることが非常に簡単になります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"net = EmbedClassifier(len(vocab),len(vocab.vectors[0]),len(classes))\n",
|
||||
"net.embedding.weight.data = vocab.vectors\n",
|
||||
"net = net.to(device)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3200: acc=0.6271875\n",
|
||||
"6400: acc=0.68078125\n",
|
||||
"9600: acc=0.7030208333333333\n",
|
||||
"12800: acc=0.71984375\n",
|
||||
"16000: acc=0.7346875\n",
|
||||
"19200: acc=0.7455729166666667\n",
|
||||
"22400: acc=0.7529464285714286\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(35.53972978646833, 0.7575175943698017)"
|
||||
]
|
||||
},
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=offsetify, shuffle=True)\n",
|
||||
"train_epoch_emb(net,train_loader, lr=4, epoch_size=25000)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"私たちが精度の大幅な向上を見られない理由の一つは、データセット内のいくつかの単語が事前学習済みのGloVe語彙に欠けているため、それらが事実上無視されていることにあります。この問題を克服するために、データセット上で独自の埋め込みを学習することができます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 文脈的埋め込み\n",
|
||||
"\n",
|
||||
"Word2Vecのような従来の事前学習済み埋め込み表現の主な制約の1つは、語義の曖昧性の問題です。事前学習済みの埋め込みは、文脈内での単語の意味をある程度捉えることができますが、単語のすべての可能な意味が同じ埋め込みにエンコードされます。このため、下流のモデルで問題が発生することがあります。例えば、「play」という単語は使用される文脈によって異なる意味を持つことがあります。\n",
|
||||
"\n",
|
||||
"例えば、「play」という単語は以下の2つの文で全く異なる意味を持っています:\n",
|
||||
"- 私は劇場で**劇**を観ました。\n",
|
||||
"- ジョンは友達と**遊び**たいと思っています。\n",
|
||||
"\n",
|
||||
"上記の事前学習済み埋め込みは、「play」という単語のこれら両方の意味を同じ埋め込みで表現しています。この制約を克服するためには、**言語モデル**に基づいた埋め込みを構築する必要があります。この言語モデルは、大規模なテキストコーパスで学習されており、単語が異なる文脈でどのように組み合わされるかを「理解」しています。文脈的埋め込みについて詳しく説明することはこのチュートリアルの範囲外ですが、次のユニットで言語モデルについて話す際に再び取り上げます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書はAI翻訳サービス[Co-op Translator](https://github.com/Azure/co-op-translator)を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があります。元の言語で記載された文書を正式な情報源としてお考えください。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当方は一切の責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "0cb620c6d4b9f7a635928804c26cf22403d89d98d79684e4529119355ee6d5a5"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "py37_pytorch",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "f50b026abce5cf36783a560ea72cb9b1",
|
||||
"translation_date": "2025-08-30T10:37:13+00:00",
|
||||
"source_file": "lessons/5-NLP/14-Embeddings/EmbeddingsPyTorch.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,695 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 埋め込み\n",
|
||||
"\n",
|
||||
"前回の例では、`vocab_size`の長さを持つ高次元のバッグオブワードベクトルを操作し、低次元の位置表現ベクトルを明示的にスパースなワンホット表現に変換しました。このワンホット表現はメモリ効率が良くありません。さらに、各単語は互いに独立して扱われるため、ワンホットエンコードされたベクトルは単語間の意味的な類似性を表現しません。\n",
|
||||
"\n",
|
||||
"このユニットでは、**News AG**データセットを引き続き探求します。まずはデータをロードし、前のユニットからいくつかの定義を取得しましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import tensorflow as tf\n",
|
||||
"from tensorflow import keras\n",
|
||||
"import tensorflow_datasets as tfds\n",
|
||||
"import numpy as np\n",
|
||||
"\n",
|
||||
"ds_train, ds_test = tfds.load('ag_news_subset').values()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 埋め込みとは?\n",
|
||||
"\n",
|
||||
"**埋め込み(embedding)** のアイデアは、単語をその意味を反映した低次元の密なベクトルで表現することです。後ほど、意味のある単語埋め込みを構築する方法について説明しますが、ここでは埋め込みを単語ベクトルの次元を削減する方法として考えてみましょう。\n",
|
||||
"\n",
|
||||
"埋め込み層は単語を入力として受け取り、指定された `embedding_size` の出力ベクトルを生成します。ある意味では、これは `Dense` 層に非常に似ていますが、入力としてワンホットエンコードされたベクトルを取る代わりに、単語番号を直接受け取ることができます。\n",
|
||||
"\n",
|
||||
"ネットワークの最初の層として埋め込み層を使用することで、バッグオブワード(bag-of-words)モデルから **埋め込みバッグ(embedding bag)** モデルに切り替えることができます。このモデルでは、まずテキスト内の各単語を対応する埋め込みに変換し、その後、`sum`、`average`、`max` などの集約関数をこれらの埋め込み全体に対して計算します。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"私たちの分類器ニューラルネットワークは以下の層で構成されています:\n",
|
||||
"\n",
|
||||
"* `TextVectorization` 層:文字列を入力として受け取り、トークン番号のテンソルを生成します。適切な語彙サイズ `vocab_size` を指定し、使用頻度の低い単語を無視します。入力の形状は1で、出力の形状は $n$ になります。これは、結果として $n$ 個のトークンを得るためで、それぞれが 0 から `vocab_size` の範囲の番号を含みます。\n",
|
||||
"* `Embedding` 層:$n$ 個の番号を受け取り、それぞれの番号を指定された長さ(この例では100)の密なベクトルに変換します。したがって、形状 $n$ の入力テンソルは $n\\times 100$ のテンソルに変換されます。\n",
|
||||
"* 集約層:このテンソルの第1軸に沿って平均を計算します。つまり、異なる単語に対応する $n$ 個の入力テンソル全体の平均を計算します。この層を実装するために、`Lambda` 層を使用し、平均を計算する関数を渡します。出力の形状は100になり、これは入力シーケンス全体の数値表現となります。\n",
|
||||
"* 最後の `Dense` 線形分類器。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"sequential\"\n",
|
||||
"_________________________________________________________________\n",
|
||||
" Layer (type) Output Shape Param # \n",
|
||||
"=================================================================\n",
|
||||
" text_vectorization (TextVec (None, None) 0 \n",
|
||||
" torization) \n",
|
||||
" \n",
|
||||
" embedding (Embedding) (None, None, 100) 3000000 \n",
|
||||
" \n",
|
||||
" lambda (Lambda) (None, 100) 0 \n",
|
||||
" \n",
|
||||
" dense (Dense) (None, 4) 404 \n",
|
||||
" \n",
|
||||
"=================================================================\n",
|
||||
"Total params: 3,000,404\n",
|
||||
"Trainable params: 3,000,404\n",
|
||||
"Non-trainable params: 0\n",
|
||||
"_________________________________________________________________\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vocab_size = 30000\n",
|
||||
"batch_size = 128\n",
|
||||
"\n",
|
||||
"vectorizer = keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,input_shape=(1,))\n",
|
||||
"\n",
|
||||
"model = keras.models.Sequential([\n",
|
||||
" vectorizer, \n",
|
||||
" keras.layers.Embedding(vocab_size,100),\n",
|
||||
" keras.layers.Lambda(lambda x: tf.reduce_mean(x,axis=1)),\n",
|
||||
" keras.layers.Dense(4, activation='softmax')\n",
|
||||
"])\n",
|
||||
"model.summary()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"`summary` の出力において、**output shape** 列の最初のテンソル次元 `None` はミニバッチサイズを表し、2番目の次元はトークンシーケンスの長さを表します。ミニバッチ内のすべてのトークンシーケンスは異なる長さを持っています。この問題への対処方法については、次のセクションで説明します。\n",
|
||||
"\n",
|
||||
"それでは、ネットワークをトレーニングしてみましょう:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Training vectorizer\n",
|
||||
"938/938 [==============================] - 20s 20ms/step - loss: 0.7891 - acc: 0.8155 - val_loss: 0.4470 - val_acc: 0.8642\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<keras.callbacks.History at 0x22255515100>"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def extract_text(x):\n",
|
||||
" return x['title']+' '+x['description']\n",
|
||||
"\n",
|
||||
"def tupelize(x):\n",
|
||||
" return (extract_text(x),x['label'])\n",
|
||||
"\n",
|
||||
"print(\"Training vectorizer\")\n",
|
||||
"vectorizer.adapt(ds_train.take(500).map(extract_text))\n",
|
||||
"\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'])\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"nteract": {
|
||||
"transient": {
|
||||
"deleting": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
"> **注意** データのサブセットに基づいてベクトライザーを構築していることを理解してください。これはプロセスを高速化するために行われており、その結果、テキスト内のすべてのトークンが語彙に含まれない場合があります。この場合、それらのトークンは無視されるため、精度がわずかに低下する可能性があります。しかし、実際にはテキストのサブセットでも良好な語彙の推定が得られることが多いです。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 変数シーケンスサイズの扱い\n",
|
||||
"\n",
|
||||
"ミニバッチでの学習がどのように行われるかを理解しましょう。上記の例では、入力テンソルの次元は1であり、128個のミニバッチを使用するため、テンソルの実際のサイズは $128 \\times 1$ となります。しかし、各文のトークン数は異なります。`TextVectorization` レイヤーを単一の入力に適用すると、テキストのトークン化方法によって返されるトークン数が異なります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"tf.Tensor([ 1 45], shape=(2,), dtype=int64)\n",
|
||||
"tf.Tensor([ 112 1271 1 3 1747 158], shape=(6,), dtype=int64)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(vectorizer('Hello, world!'))\n",
|
||||
"print(vectorizer('I am glad to meet you!'))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"しかし、ベクトライザーを複数のシーケンスに適用する場合、矩形の形状を持つテンソルを生成する必要があるため、未使用の要素をPADトークン(この場合はゼロ)で埋めます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tf.Tensor: shape=(2, 6), dtype=int64, numpy=\n",
|
||||
"array([[ 1, 45, 0, 0, 0, 0],\n",
|
||||
" [ 112, 1271, 1, 3, 1747, 158]], dtype=int64)>"
|
||||
]
|
||||
},
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vectorizer(['Hello, world!','I am glad to meet you!'])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ここで埋め込みを見ることができます:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[[ 1.53059261e-02, 6.80514947e-02, 3.14026810e-02, ...,\n",
|
||||
" -8.92002955e-02, 1.52911525e-04, -5.65562584e-02],\n",
|
||||
" [ 2.57456154e-01, 2.79364467e-01, -2.03605562e-01, ...,\n",
|
||||
" -2.07474351e-01, 8.31158683e-02, -2.03911960e-01],\n",
|
||||
" [ 3.98201384e-02, -8.03454965e-03, 2.39790026e-02, ...,\n",
|
||||
" -7.18549127e-04, 2.66963355e-02, -4.30646613e-02],\n",
|
||||
" [ 3.98201384e-02, -8.03454965e-03, 2.39790026e-02, ...,\n",
|
||||
" -7.18549127e-04, 2.66963355e-02, -4.30646613e-02],\n",
|
||||
" [ 3.98201384e-02, -8.03454965e-03, 2.39790026e-02, ...,\n",
|
||||
" -7.18549127e-04, 2.66963355e-02, -4.30646613e-02],\n",
|
||||
" [ 3.98201384e-02, -8.03454965e-03, 2.39790026e-02, ...,\n",
|
||||
" -7.18549127e-04, 2.66963355e-02, -4.30646613e-02]],\n",
|
||||
"\n",
|
||||
" [[ 1.89674050e-01, 2.61548996e-01, -3.67433839e-02, ...,\n",
|
||||
" -2.07366899e-01, -1.05442435e-01, -2.36952081e-01],\n",
|
||||
" [ 6.16133213e-02, 1.80511594e-01, 9.77298319e-02, ...,\n",
|
||||
" -5.46628237e-02, -1.07340455e-01, -1.06589928e-01],\n",
|
||||
" [ 1.53059261e-02, 6.80514947e-02, 3.14026810e-02, ...,\n",
|
||||
" -8.92002955e-02, 1.52911525e-04, -5.65562584e-02],\n",
|
||||
" [-4.84890305e-02, -8.41715634e-02, 1.51529670e-01, ...,\n",
|
||||
" 1.28192469e-01, -7.77286515e-02, 1.26041949e-01],\n",
|
||||
" [-4.17212099e-02, -5.60694858e-02, 4.08860669e-02, ...,\n",
|
||||
" 8.70475471e-02, 8.92383084e-02, 1.67974353e-01],\n",
|
||||
" [ 2.85779923e-01, 4.57767487e-01, 4.52292450e-02, ...,\n",
|
||||
" -1.97419018e-01, -2.04659685e-01, -2.79758364e-01]]],\n",
|
||||
" dtype=float32)"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.layers[1](vectorizer(['Hello, world!','I am glad to meet you!'])).numpy()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **注意**: パディングの量を最小限に抑えるために、場合によってはデータセット内のすべてのシーケンスを長さの増加順(より正確にはトークン数の増加順)に並べ替えることが理にかなっています。これにより、各ミニバッチが類似した長さのシーケンスを含むようになります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## セマンティック埋め込み: Word2Vec\n",
|
||||
"\n",
|
||||
"前回の例では、埋め込み層が単語をベクトル表現にマッピングする方法を学習しましたが、これらの表現にはセマンティックな意味がありませんでした。類似した単語や同義語が、あるベクトル距離(例えばユークリッド距離)において互いに近いベクトルに対応するようなベクトル表現を学習できると便利です。\n",
|
||||
"\n",
|
||||
"そのためには、大量のテキストコレクションを使用して、[Word2Vec](https://en.wikipedia.org/wiki/Word2vec)のような手法で埋め込みモデルを事前学習する必要があります。Word2Vecは、単語の分散表現を生成するために使用される2つの主要なアーキテクチャに基づいています:\n",
|
||||
"\n",
|
||||
" - **連続バグ・オブ・ワーズ** (CBoW): モデルに周囲の文脈から単語を予測させる手法です。ngram $(W_{-2},W_{-1},W_0,W_1,W_2)$ が与えられた場合、モデルの目標は $(W_{-2},W_{-1},W_1,W_2)$ から $W_0$ を予測することです。\n",
|
||||
" - **連続スキップグラム**: CBoWとは逆の手法です。このモデルでは、現在の単語を予測するために周囲の文脈単語のウィンドウを使用します。\n",
|
||||
"\n",
|
||||
"CBoWは高速ですが、スキップグラムは処理が遅いものの、頻度の低い単語をより良く表現することができます。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"Googleニュースのデータセットで事前学習されたWord2Vec埋め込みを試すには、**gensim**ライブラリを使用することができます。以下に、'neural'に最も類似した単語を見つける例を示します。\n",
|
||||
"\n",
|
||||
"> **Note:** 初めて単語ベクトルを作成する際、ダウンロードに時間がかかる場合があります!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import gensim.downloader as api\n",
|
||||
"w2v = api.load('word2vec-google-news-300')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"neuronal -> 0.7804799675941467\n",
|
||||
"neurons -> 0.7326500415802002\n",
|
||||
"neural_circuits -> 0.7252851724624634\n",
|
||||
"neuron -> 0.7174385190010071\n",
|
||||
"cortical -> 0.6941086649894714\n",
|
||||
"brain_circuitry -> 0.6923246383666992\n",
|
||||
"synaptic -> 0.6699118614196777\n",
|
||||
"neural_circuitry -> 0.6638563275337219\n",
|
||||
"neurochemical -> 0.6555314064025879\n",
|
||||
"neuronal_activity -> 0.6531826257705688\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"for w,p in w2v.most_similar('neural'):\n",
|
||||
" print(f\"{w} -> {p}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"単語からベクトル埋め込みを抽出し、分類モデルのトレーニングに使用することもできます。埋め込みは300成分を持っていますが、ここでは明確にするためにベクトルの最初の20成分のみを示します:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([ 0.01226807, 0.06225586, 0.10693359, 0.05810547, 0.23828125,\n",
|
||||
" 0.03686523, 0.05151367, -0.20703125, 0.01989746, 0.10058594,\n",
|
||||
" -0.03759766, -0.1015625 , -0.15820312, -0.08105469, -0.0390625 ,\n",
|
||||
" -0.05053711, 0.16015625, 0.2578125 , 0.10058594, -0.25976562],\n",
|
||||
" dtype=float32)"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"w2v['play'][:20]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"セマンティック埋め込みの素晴らしい点は、セマンティクスに基づいてベクトルエンコーディングを操作できることです。例えば、*king* と *woman* のベクトル表現にできるだけ近く、*man* からできるだけ遠い単語を見つけるように求めることができます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"('queen', 0.7118192911148071)"
|
||||
]
|
||||
},
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"w2v.most_similar(positive=['king','woman'],negative=['man'])[0]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"tags": []
|
||||
},
|
||||
"source": [
|
||||
"上記の例では、内部のGenSymマジックが使用されていますが、基本的なロジックは実際には非常に簡単です。埋め込みに関する興味深い点は、埋め込みベクトルに対して通常のベクトル操作を行うことができ、それが単語の**意味**に関する操作を反映するということです。上記の例はベクトル操作の観点で表現することができます:**KING-MAN+WOMAN**に対応するベクトルを計算し(対応する単語のベクトル表現に対して`+`と`-`の操作を行う)、そのベクトルに最も近い単語を辞書から見つけます:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'queen'"
|
||||
]
|
||||
},
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# get the vector corresponding to kind-man+woman\n",
|
||||
"qvec = w2v['king']-1.7*w2v['man']+1.7*w2v['woman']\n",
|
||||
"# find the index of the closest embedding vector \n",
|
||||
"d = np.sum((w2v.vectors-qvec)**2,axis=1)\n",
|
||||
"min_idx = np.argmin(d)\n",
|
||||
"# find the corresponding word\n",
|
||||
"w2v.index_to_key[min_idx]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **NOTE**: *man* と *woman* ベクトルに小さな係数を追加しました - これを削除して何が起こるか試してみてください。\n",
|
||||
"\n",
|
||||
"最も近いベクトルを見つけるために、TensorFlowの仕組みを使って、自分のベクトルと語彙内のすべてのベクトルとの距離のベクトルを計算し、その後 `argmin` を使用して最小の単語のインデックスを見つけます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Word2Vecは単語の意味を表現する優れた方法のように思えますが、以下のような多くの欠点があります:\n",
|
||||
"\n",
|
||||
"* CBoWモデルとskip-gramモデルはどちらも**予測型埋め込み**であり、ローカルな文脈のみを考慮します。Word2Vecはグローバルな文脈を活用しません。\n",
|
||||
"* Word2Vecは単語の**形態**、つまり単語の意味が語幹などの異なる部分に依存する可能性があるという事実を考慮しません。\n",
|
||||
"\n",
|
||||
"**FastText**はこの2つ目の制約を克服しようと試み、Word2Vecを基に各単語とその中に含まれる文字n-gramのベクトル表現を学習します。これらの表現値は、各トレーニングステップで1つのベクトルに平均化されます。この方法は事前学習に多くの追加計算を必要としますが、単語埋め込みがサブワード情報をエンコードできるようにします。\n",
|
||||
"\n",
|
||||
"もう1つの手法である**GloVe**は、単語埋め込みに対して異なるアプローチを採用しており、単語-文脈行列の因数分解に基づいています。まず、異なる文脈での単語の出現回数をカウントする大きな行列を構築し、その後、この行列を再構築誤差を最小化する形で低次元に表現しようとします。\n",
|
||||
"\n",
|
||||
"gensimライブラリはこれらの単語埋め込みをサポートしており、上記のモデル読み込みコードを変更することで、それらを試すことができます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Kerasで事前学習済みの埋め込みを使用する\n",
|
||||
"\n",
|
||||
"上記の例を修正して、埋め込み層の行列をWord2Vecのようなセマンティック埋め込みで事前に初期化することができます。事前学習済みの埋め込みの語彙とテキストコーパスの語彙は一致しない可能性が高いため、どちらかを選択する必要があります。ここでは、トークナイザーの語彙を使用する場合と、Word2Vecの埋め込みの語彙を使用する場合の2つの選択肢を検討します。\n",
|
||||
"\n",
|
||||
"### トークナイザーの語彙を使用する場合\n",
|
||||
"\n",
|
||||
"トークナイザーの語彙を使用する場合、語彙の中には対応するWord2Vecの埋め込みが存在する単語もあれば、存在しない単語もあります。語彙サイズが`vocab_size`で、Word2Vecの埋め込みベクトルの長さが`embed_size`の場合、埋め込み層は形状が`vocab_size`$\\times$`embed_size`の重み行列で表されます。この行列を語彙を順に処理して埋めていきます:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Embedding size: 300\n",
|
||||
"Populating matrix, this will take some time...Done, found 4551 words, 784 words missing\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"embed_size = len(w2v.get_vector('hello'))\n",
|
||||
"print(f'Embedding size: {embed_size}')\n",
|
||||
"\n",
|
||||
"vocab = vectorizer.get_vocabulary()\n",
|
||||
"W = np.zeros((vocab_size,embed_size))\n",
|
||||
"print('Populating matrix, this will take some time...',end='')\n",
|
||||
"found, not_found = 0,0\n",
|
||||
"for i,w in enumerate(vocab):\n",
|
||||
" try:\n",
|
||||
" W[i] = w2v.get_vector(w)\n",
|
||||
" found+=1\n",
|
||||
" except:\n",
|
||||
" # W[i] = np.random.normal(0.0,0.3,size=(embed_size,))\n",
|
||||
" not_found+=1\n",
|
||||
"\n",
|
||||
"print(f\"Done, found {found} words, {not_found} words missing\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Word2Vecの語彙に存在しない単語については、ゼロのままにするか、ランダムなベクトルを生成することができます。\n",
|
||||
"\n",
|
||||
"次に、事前学習済みの重みを使用して埋め込み層を定義します:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"emb = keras.layers.Embedding(vocab_size,embed_size,weights=[W],trainable=False)\n",
|
||||
"model = keras.models.Sequential([\n",
|
||||
" vectorizer, emb,\n",
|
||||
" keras.layers.Lambda(lambda x: tf.reduce_mean(x,axis=1)),\n",
|
||||
" keras.layers.Dense(4, activation='softmax')\n",
|
||||
"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"938/938 [==============================] - 10s 10ms/step - loss: 1.1075 - acc: 0.7822 - val_loss: 0.9134 - val_acc: 0.8175\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<keras.callbacks.History at 0x2220226ef10>"
|
||||
]
|
||||
},
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'])\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(batch_size),\n",
|
||||
" validation_data=ds_test.map(tupelize).batch(batch_size))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **Note**: `Embedding`を作成する際に`trainable=False`を設定していることに注意してください。これは、Embedding層を再学習しないことを意味します。この設定により、精度が若干低下する可能性がありますが、トレーニング速度が向上します。\n",
|
||||
"\n",
|
||||
"### 埋め込み語彙の使用\n",
|
||||
"\n",
|
||||
"以前のアプローチの問題点は、TextVectorizationとEmbeddingで使用される語彙が異なることです。この問題を解決するために、以下のいずれかの方法を使用できます:\n",
|
||||
"* Word2Vecモデルを私たちの語彙で再学習する。\n",
|
||||
"* 事前学習済みのWord2Vecモデルの語彙を使用してデータセットをロードする。データセットをロードする際に使用する語彙は指定可能です。\n",
|
||||
"\n",
|
||||
"後者の方法の方が簡単そうなので、これを実装してみましょう。まず、Word2Vec埋め込みから取得した指定語彙を使用して`TextVectorization`層を作成します:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"vocab = list(w2v.vocab.keys())\n",
|
||||
"vectorizer = keras.layers.experimental.preprocessing.TextVectorization(input_shape=(1,))\n",
|
||||
"vectorizer.set_vocabulary(vocab)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"gensimの単語埋め込みライブラリには便利な関数`get_keras_embeddings`が含まれており、対応するKeras埋め込み層を自動的に作成してくれます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Epoch 1/5\n",
|
||||
"938/938 [==============================] - 20s 14ms/step - loss: 1.3377 - acc: 0.4978 - val_loss: 1.2995 - val_acc: 0.5647\n",
|
||||
"Epoch 2/5\n",
|
||||
"938/938 [==============================] - 10s 10ms/step - loss: 1.2587 - acc: 0.5722 - val_loss: 1.2339 - val_acc: 0.5842\n",
|
||||
"Epoch 3/5\n",
|
||||
"938/938 [==============================] - 10s 10ms/step - loss: 1.1980 - acc: 0.5884 - val_loss: 1.1826 - val_acc: 0.5954\n",
|
||||
"Epoch 4/5\n",
|
||||
"938/938 [==============================] - 12s 13ms/step - loss: 1.1503 - acc: 0.6002 - val_loss: 1.1417 - val_acc: 0.6018\n",
|
||||
"Epoch 5/5\n",
|
||||
"938/938 [==============================] - 11s 12ms/step - loss: 1.1120 - acc: 0.6097 - val_loss: 1.1083 - val_acc: 0.6104\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<keras.callbacks.History at 0x2220ccb81c0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model = keras.models.Sequential([\n",
|
||||
" vectorizer, \n",
|
||||
" w2v.get_keras_embedding(train_embeddings=False),\n",
|
||||
" keras.layers.Lambda(lambda x: tf.reduce_mean(x,axis=1)),\n",
|
||||
" keras.layers.Dense(4, activation='softmax')\n",
|
||||
"])\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'])\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(128),validation_data=ds_test.map(tupelize).batch(128),epochs=5)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"私たちがより高い精度を見ていない理由の一つは、データセットのいくつかの単語が事前学習済みのGloVe語彙に欠けているため、それらが事実上無視されているからです。これを克服するために、データセットに基づいて独自の埋め込みを訓練することができます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 文脈的埋め込み\n",
|
||||
"\n",
|
||||
"Word2Vecのような従来の事前学習済み埋め込み表現の主な制限の1つは、単語の意味をある程度捉えることはできても、異なる意味を区別することができない点です。この制限は、下流のモデルで問題を引き起こす可能性があります。\n",
|
||||
"\n",
|
||||
"例えば、単語「play」は以下の2つの文で異なる意味を持っています:\n",
|
||||
"- 私は劇場で**play**(劇)を観ました。\n",
|
||||
"- ジョンは友達と**play**(遊ぶ)をしたいと思っています。\n",
|
||||
"\n",
|
||||
"先ほど説明した事前学習済み埋め込みは、単語「play」の両方の意味を同じ埋め込みで表現します。この制限を克服するためには、**言語モデル**に基づいて埋め込みを構築する必要があります。この言語モデルは、大規模なテキストコーパスで訓練されており、単語が異なる文脈でどのように組み合わされるかを*理解*しています。文脈的埋め込みについて詳しく説明することはこのチュートリアルの範囲外ですが、次のユニットで言語モデルについて話す際に再び取り上げます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書はAI翻訳サービス[Co-op Translator](https://github.com/Azure/co-op-translator)を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があります。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当社は責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "0cb620c6d4b9f7a635928804c26cf22403d89d98d79684e4529119355ee6d5a5"
|
||||
},
|
||||
"kernel_info": {
|
||||
"name": "conda-env-py37_tensorflow-py"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "py37_tensorflow",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"nteract": {
|
||||
"version": "nteract-front-end@1.0.0"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "b859482be7f61d1eadc2c6a2720a37e4",
|
||||
"translation_date": "2025-08-30T10:33:31+00:00",
|
||||
"source_file": "lessons/5-NLP/14-Embeddings/EmbeddingsTF.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -0,0 +1,576 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "NXTSugt6ieXh"
|
||||
},
|
||||
"source": [
|
||||
"## CBoWモデルのトレーニング\n",
|
||||
"\n",
|
||||
"このノートブックは[AI for Beginners Curriculum](http://aka.ms/ai-beginners)の一部です。\n",
|
||||
"\n",
|
||||
"この例では、CBoW言語モデルをトレーニングして独自のWord2Vec埋め込み空間を作成する方法を見ていきます。テキストのソースとしてAG Newsデータセットを使用します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"import torch\n",
|
||||
"import torchtext\n",
|
||||
"import os\n",
|
||||
"import collections\n",
|
||||
"import builtins\n",
|
||||
"import random\n",
|
||||
"import numpy as np"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "q-UiiJUKaxHj"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "TFbR8CZaTZ1q"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"まず、データセットを読み込み、トークナイザーとボキャブラリーを定義しましょう。計算量を少し制限するために、`vocab_size` を5000に設定します。\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "HIwC7lI5T-ov"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"def load_dataset(ngrams = 1, min_freq = 1, vocab_size = 5000 , lines_cnt = 500):\n",
|
||||
" tokenizer = torchtext.data.utils.get_tokenizer('basic_english')\n",
|
||||
" print(\"Loading dataset...\")\n",
|
||||
" test_dataset, train_dataset = torchtext.datasets.AG_NEWS(root='./data')\n",
|
||||
" train_dataset = list(train_dataset)\n",
|
||||
" test_dataset = list(test_dataset)\n",
|
||||
" classes = ['World', 'Sports', 'Business', 'Sci/Tech']\n",
|
||||
" print('Building vocab...')\n",
|
||||
" counter = collections.Counter()\n",
|
||||
" for i, (_, line) in enumerate(train_dataset):\n",
|
||||
" counter.update(torchtext.data.utils.ngrams_iterator(tokenizer(line),ngrams=ngrams))\n",
|
||||
" if i == lines_cnt:\n",
|
||||
" break\n",
|
||||
" vocab = torchtext.vocab.Vocab(collections.Counter(dict(counter.most_common(vocab_size))), min_freq=min_freq)\n",
|
||||
" return train_dataset, test_dataset, classes, vocab, tokenizer"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "wdZuygtgiuLG"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"train_dataset, test_dataset, _, vocab, tokenizer = load_dataset()"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "4d1nU1gsivGu",
|
||||
"outputId": "949fe272-ae0e-49f5-c373-6703458b3a74"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Loading dataset...\n",
|
||||
"Building vocab...\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"def encode(x, vocabulary, tokenizer = tokenizer):\n",
|
||||
" return [vocabulary[s] for s in tokenizer(x)]"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "1XDYNhG8ToFV"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "LIlQk6_PaHVY"
|
||||
},
|
||||
"source": [
|
||||
"## CBoWモデル\n",
|
||||
"\n",
|
||||
"CBoWは、$2N$個の周辺単語から1つの単語を予測することを学習します。例えば、$N=1$の場合、文 *I like to train networks* から以下のペアが得られます: (like,I), (I, like), (to, like), (like,to), (train,to), (to, train), (networks, train), (train,networks)。ここで、最初の単語は入力として使用される周辺単語で、2番目の単語が予測対象の単語です。\n",
|
||||
"\n",
|
||||
"次の単語を予測するネットワークを構築するには、周辺単語を入力として与え、単語番号を出力として得る必要があります。CBoWネットワークのアーキテクチャは以下の通りです:\n",
|
||||
"\n",
|
||||
"* 入力単語は埋め込み層を通過します。この埋め込み層が私たちのWord2Vec埋め込みとなり、`embedder`変数として個別に定義します。この例では埋め込みサイズを30に設定しますが、より高次元で実験することも可能です(実際のWord2Vecでは300次元です)。\n",
|
||||
"* 埋め込みベクトルは、その後、出力単語を予測する線形層に渡されます。この層には`vocab_size`個のニューロンがあります。\n",
|
||||
"\n",
|
||||
"出力に関しては、損失関数として`CrossEntropyLoss`を使用する場合、ワンホットエンコーディングを行わずに、単語番号をそのまま期待される結果として提供する必要があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"vocab_size = len(vocab)\n",
|
||||
"\n",
|
||||
"embedder = torch.nn.Embedding(num_embeddings = vocab_size, embedding_dim = 30)\n",
|
||||
"model = torch.nn.Sequential(\n",
|
||||
" embedder,\n",
|
||||
" torch.nn.Linear(in_features = 30, out_features = vocab_size),\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"print(model)"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "akKTcKQKkfl2",
|
||||
"outputId": "da687e3e-a8ec-4c1a-e456-ab8cd6ac7dad"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Sequential(\n",
|
||||
" (0): Embedding(5002, 30)\n",
|
||||
" (1): Linear(in_features=30, out_features=5002, bias=True)\n",
|
||||
")\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "Nud6jgGPaHVa"
|
||||
},
|
||||
"source": [
|
||||
"## トレーニングデータの準備\n",
|
||||
"\n",
|
||||
"それでは、テキストからCBoWの単語ペアを計算するメイン関数をプログラムしてみましょう。この関数ではウィンドウサイズを指定でき、入力単語と出力単語のペアセットを返します。この関数は単語だけでなく、ベクトルやテンソルにも使用できる点に注意してください。これにより、テキストをエンコードしてから`to_cbow`関数に渡すことが可能になります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "x-dsXygOieXn",
|
||||
"outputId": "c2218280-e540-40ba-9546-efe48d0d714f"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"[['like', 'I'], ['to', 'I'], ['I', 'like'], ['to', 'like'], ['train', 'like'], ['I', 'to'], ['like', 'to'], ['train', 'to'], ['networks', 'to'], ['like', 'train'], ['to', 'train'], ['networks', 'train'], ['to', 'networks'], ['train', 'networks']]\n",
|
||||
"[[232, 172], [5, 172], [172, 232], [5, 232], [0, 232], [172, 5], [232, 5], [0, 5], [1202, 5], [232, 0], [5, 0], [1202, 0], [5, 1202], [0, 1202]]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def to_cbow(sent,window_size=2):\n",
|
||||
" res = []\n",
|
||||
" for i,x in enumerate(sent):\n",
|
||||
" for j in range(max(0,i-window_size),min(i+window_size+1,len(sent))):\n",
|
||||
" if i!=j:\n",
|
||||
" res.append([sent[j],x])\n",
|
||||
" return res\n",
|
||||
"\n",
|
||||
"print(to_cbow(['I','like','to','train','networks']))\n",
|
||||
"print(to_cbow(encode('I like to train networks', vocab)))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "XVaaDLjaaHVb"
|
||||
},
|
||||
"source": [
|
||||
"トレーニングデータセットを準備しましょう。すべてのニュースを確認し、`to_cbow` を呼び出して単語ペアのリストを取得し、そのペアを `X` と `Y` に追加します。時間を節約するために、最初の10k件のニュース項目のみを考慮しますが、待つ時間がある場合やより良い埋め込みを得たい場合は、この制限を簡単に取り除くことができます :)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "54b-Gd9TieXo"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"X = []\n",
|
||||
"Y = []\n",
|
||||
"for i, x in zip(range(10000), train_dataset):\n",
|
||||
" for w1, w2 in to_cbow(encode(x[1], vocab), window_size = 5):\n",
|
||||
" X.append(w1)\n",
|
||||
" Y.append(w2)\n",
|
||||
"\n",
|
||||
"X = torch.tensor(X)\n",
|
||||
"Y = torch.tensor(Y)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"そのデータを1つのデータセットに変換し、データローダーを作成します。\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "cwWy0PzXWhN5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"class SimpleIterableDataset(torch.utils.data.IterableDataset):\n",
|
||||
" def __init__(self, X, Y):\n",
|
||||
" super(SimpleIterableDataset).__init__()\n",
|
||||
" self.data = []\n",
|
||||
" for i in range(len(X)):\n",
|
||||
" self.data.append( (Y[i], X[i]) )\n",
|
||||
" random.shuffle(self.data)\n",
|
||||
"\n",
|
||||
" def __iter__(self):\n",
|
||||
" return iter(self.data)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "mfoAcGPFZU8p"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "e4NQ_-5waHVc"
|
||||
},
|
||||
"source": [
|
||||
"そのデータを1つのデータセットに変換し、データローダーを作成します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "AbLUcojlieXo"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ds = SimpleIterableDataset(X, Y)\n",
|
||||
"dl = torch.utils.data.DataLoader(ds, batch_size = 256)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "pKQr7sXeaHVc"
|
||||
},
|
||||
"source": [
|
||||
"では、実際のトレーニングを始めましょう。学習率がかなり高い`SGD`オプティマイザーを使用します。また、`Adam`などの他のオプティマイザーを試してみることもできます。まずは10エポックでトレーニングを行いますが、さらに損失を減らしたい場合はこのセルを再実行することができます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"def train_epoch(net, dataloader, lr = 0.01, optimizer = None, loss_fn = torch.nn.CrossEntropyLoss(), epochs = None, report_freq = 1):\n",
|
||||
" optimizer = optimizer or torch.optim.Adam(net.parameters(), lr = lr)\n",
|
||||
" loss_fn = loss_fn.to(device)\n",
|
||||
" net.train()\n",
|
||||
"\n",
|
||||
" for i in range(epochs):\n",
|
||||
" total_loss, j = 0, 0, \n",
|
||||
" for labels, features in dataloader:\n",
|
||||
" optimizer.zero_grad()\n",
|
||||
" features, labels = features.to(device), labels.to(device)\n",
|
||||
" out = net(features)\n",
|
||||
" loss = loss_fn(out, labels)\n",
|
||||
" loss.backward()\n",
|
||||
" optimizer.step()\n",
|
||||
" total_loss += loss\n",
|
||||
" j += 1\n",
|
||||
" if i % report_freq == 0:\n",
|
||||
" print(f\"Epoch: {i+1}: loss={total_loss.item()/j}\")\n",
|
||||
"\n",
|
||||
" return total_loss.item()/j"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "HeeCYKr_KF1w"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"train_epoch(net = model, dataloader = dl, optimizer = torch.optim.SGD(model.parameters(), lr = 0.1), loss_fn = torch.nn.CrossEntropyLoss(), epochs = 10)"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "KVgwGtDHgDlT",
|
||||
"outputId": "2447833f-f0e3-4566-c33d-addbfe2f451d"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Epoch: 1: loss=5.664632366860172\n",
|
||||
"Epoch: 2: loss=5.632101973960962\n",
|
||||
"Epoch: 3: loss=5.610399051405015\n",
|
||||
"Epoch: 4: loss=5.594621561080262\n",
|
||||
"Epoch: 5: loss=5.582538017415446\n",
|
||||
"Epoch: 6: loss=5.572900234519603\n",
|
||||
"Epoch: 7: loss=5.564951676341915\n",
|
||||
"Epoch: 8: loss=5.558288112064614\n",
|
||||
"Epoch: 9: loss=5.552576955031129\n",
|
||||
"Epoch: 10: loss=5.547634165194347\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"output_type": "execute_result",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"5.547634165194347"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"execution_count": 16
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "W8u2qXZmaHVd"
|
||||
},
|
||||
"source": [
|
||||
"## Word2Vecを試してみる\n",
|
||||
"\n",
|
||||
"Word2Vecを使用するために、語彙内のすべての単語に対応するベクトルを抽出してみましょう:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "r8TatcXjkU_t"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"vectors = torch.stack([embedder(torch.tensor(vocab[s])) for s in vocab.itos], 0)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "3OcX21UOaHVd"
|
||||
},
|
||||
"source": [
|
||||
"例えば、単語**Paris**がどのようにベクトルにエンコードされるか見てみましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "bz6tAeLzieXp",
|
||||
"outputId": "5b20850e-4342-45e9-f840-cfac2b4d61d8"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"tensor([-0.0915, 2.1224, -0.0281, -0.6819, 1.1219, 0.6458, -1.3704, -1.3314,\n",
|
||||
" -1.1437, 0.4496, 0.2301, -0.3515, -0.8485, 1.0481, 0.4386, -0.8949,\n",
|
||||
" 0.5644, 1.0939, -2.5096, 3.2949, -0.2601, -0.8640, 0.1421, -0.0804,\n",
|
||||
" -0.5083, -1.0560, 0.9753, -0.5949, -1.6046, 0.5774],\n",
|
||||
" grad_fn=<EmbeddingBackward>)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"paris_vec = embedder(torch.tensor(vocab['paris']))\n",
|
||||
"print(paris_vec)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "pHTJlaeYaHVd"
|
||||
},
|
||||
"source": [
|
||||
"Word2Vecを使用して類義語を探すのは興味深いです。以下の関数は、指定された入力に対して最も近い`n`個の単語を返します。それらを見つけるために、$|w_i - v|$のノルムを計算します。ここで、$v$は入力単語に対応するベクトルであり、$w_i$は語彙内の$i$番目の単語のエンコーディングです。その後、配列をソートし、`argsort`を使用して対応するインデックスを返し、語彙内で最も近い単語の位置をエンコードするリストの最初の`n`個の要素を取得します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "NlZyi-_olFar",
|
||||
"outputId": "b5dbb163-88c4-4d5a-eaf2-6751f700e98c"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "execute_result",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"['microsoft', 'quoted', 'lp', 'rate', 'top']"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"execution_count": 56
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def close_words(x, n = 5):\n",
|
||||
" vec = embedder(torch.tensor(vocab[x]))\n",
|
||||
" top5 = np.linalg.norm(vectors.detach().numpy() - vec.detach().numpy(), axis = 1).argsort()[:n]\n",
|
||||
" return [ vocab.itos[x] for x in top5 ]\n",
|
||||
"\n",
|
||||
"close_words('microsoft')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "-dQq7xeAln0U",
|
||||
"outputId": "66f768c3-c248-4bfd-ce4f-c8ffc6d0dd0d"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "execute_result",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"['basketball', 'lot', 'sinai', 'states', 'healthdaynews']"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"execution_count": 51
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"close_words('basketball')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "fJXqK26b29sa",
|
||||
"outputId": "78f0baba-ffd0-485a-dd87-0a12bedfd7fa"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "execute_result",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"['funds', 'travel', 'sydney', 'japan', 'business']"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"execution_count": 77
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"close_words('funds')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "My0VeTDd3Ji8"
|
||||
},
|
||||
"source": [
|
||||
"## 要点\n",
|
||||
"\n",
|
||||
"CBoWのような巧妙な手法を使うことで、Word2Vecモデルを訓練することができます。また、中心の単語を与えられたときに隣接する単語を予測するように訓練されたskip-gramモデルを試してみて、その性能を確認してみるのも良いでしょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書はAI翻訳サービス[Co-op Translator](https://github.com/Azure/co-op-translator)を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があります。元の言語で記載された文書を正式な情報源としてご参照ください。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当方は責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"collapsed_sections": [],
|
||||
"name": "CBoW-PyTorch.ipynb",
|
||||
"provenance": []
|
||||
},
|
||||
"interpreter": {
|
||||
"hash": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.8.12 ('py38')",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"orig_nbformat": 4,
|
||||
"gpuClass": "standard",
|
||||
"coopTranslator": {
|
||||
"original_hash": "36df28efe3fe40b6fb0a7fa48fe3ea82",
|
||||
"translation_date": "2025-08-30T10:14:44+00:00",
|
||||
"source_file": "lessons/5-NLP/15-LanguageModeling/CBoW-PyTorch.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,479 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# 再帰型ニューラルネットワーク\n",
|
||||
"\n",
|
||||
"前のモジュールでは、テキストの豊かな意味表現を使用し、その埋め込みの上に単純な線形分類器を構築してきました。このアーキテクチャは、文中の単語の集約された意味を捉えることができますが、単語の**順序**を考慮していません。埋め込みの上での集約操作によって、元のテキストからこの情報が失われてしまうためです。このようなモデルは単語の順序をモデル化することができないため、テキスト生成や質問応答のようなより複雑で曖昧なタスクを解くことができません。\n",
|
||||
"\n",
|
||||
"テキストシーケンスの意味を捉えるためには、**再帰型ニューラルネットワーク**(RNN)と呼ばれる別のニューラルネットワークアーキテクチャを使用する必要があります。RNNでは、文をネットワークに1つずつシンボルを通過させ、ネットワークはある**状態**を生成します。そして次のシンボルとともにその状態を再びネットワークに渡します。\n",
|
||||
"\n",
|
||||
"与えられたトークンの入力シーケンス $X_0,\\dots,X_n$ に対して、RNNはニューラルネットワークブロックのシーケンスを作成し、このシーケンスをバックプロパゲーションを使用してエンドツーエンドで学習します。各ネットワークブロックは入力として $(X_i,S_i)$ のペアを受け取り、結果として $S_{i+1}$ を生成します。最終状態 $S_n$ または出力 $X_n$ は線形分類器に渡され、結果を生成します。すべてのネットワークブロックは同じ重みを共有し、1回のバックプロパゲーションパスでエンドツーエンドで学習されます。\n",
|
||||
"\n",
|
||||
"状態ベクトル $S_0,\\dots,S_n$ がネットワークを通過するため、単語間の順序的な依存関係を学習することができます。例えば、シーケンスのどこかに単語 *not* が現れる場合、状態ベクトル内の特定の要素を否定することを学習し、結果として否定を表現することができます。\n",
|
||||
"\n",
|
||||
"> 図中のすべてのRNNブロックの重みが共有されているため、同じ図を1つのブロック(右側)として表現することができ、再帰的なフィードバックループがネットワークの出力状態を入力に戻します。\n",
|
||||
"\n",
|
||||
"では、再帰型ニューラルネットワークがニュースデータセットの分類にどのように役立つか見てみましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Loading dataset...\n",
|
||||
"Building vocab...\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import torch\n",
|
||||
"import torchtext\n",
|
||||
"from torchnlp import *\n",
|
||||
"train_dataset, test_dataset, classes, vocab = load_dataset()\n",
|
||||
"vocab_size = len(vocab)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## シンプルなRNN分類器\n",
|
||||
"\n",
|
||||
"シンプルなRNNの場合、各リカレントユニットは単純な線形ネットワークで構成されており、結合された入力ベクトルと状態ベクトルを受け取り、新しい状態ベクトルを生成します。PyTorchでは、このユニットを`RNNCell`クラスで表現し、そのようなセルのネットワークを`RNN`レイヤーとして表現します。\n",
|
||||
"\n",
|
||||
"RNN分類器を定義するには、まず埋め込み層を適用して入力語彙の次元を下げ、その上にRNNレイヤーを配置します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class RNNClassifier(torch.nn.Module):\n",
|
||||
" def __init__(self, vocab_size, embed_dim, hidden_dim, num_class):\n",
|
||||
" super().__init__()\n",
|
||||
" self.hidden_dim = hidden_dim\n",
|
||||
" self.embedding = torch.nn.Embedding(vocab_size, embed_dim)\n",
|
||||
" self.rnn = torch.nn.RNN(embed_dim,hidden_dim,batch_first=True)\n",
|
||||
" self.fc = torch.nn.Linear(hidden_dim, num_class)\n",
|
||||
"\n",
|
||||
" def forward(self, x):\n",
|
||||
" batch_size = x.size(0)\n",
|
||||
" x = self.embedding(x)\n",
|
||||
" x,h = self.rnn(x)\n",
|
||||
" return self.fc(x.mean(dim=1))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **Note:** ここでは簡単さを重視して未学習の埋め込み層を使用していますが、より良い結果を得るためには、前のユニットで説明したように、Word2VecやGloVe埋め込みを使用した事前学習済みの埋め込み層を利用することができます。より深く理解するために、このコードを事前学習済みの埋め込みに対応するように適応させることを検討してください。\n",
|
||||
"\n",
|
||||
"今回の場合、パディングされたデータローダーを使用します。そのため、各バッチには同じ長さのパディングされたシーケンスが含まれます。RNN層は埋め込みテンソルのシーケンスを受け取り、次の2つの出力を生成します:\n",
|
||||
"* $x$ は各ステップでのRNNセルの出力シーケンス\n",
|
||||
"* $h$ はシーケンスの最後の要素に対する最終的な隠れ状態\n",
|
||||
"\n",
|
||||
"その後、全結合の線形分類器を適用してクラス数を取得します。\n",
|
||||
"\n",
|
||||
"> **Note:** RNNの訓練は非常に難しいです。RNNセルがシーケンスの長さに沿って展開されると、逆伝播に関与する層の数が非常に多くなります。そのため、小さい学習率を選択し、より大きなデータセットでネットワークを訓練する必要があります。良い結果を得るには時間がかかる可能性があるため、GPUの使用が推奨されます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3200: acc=0.3090625\n",
|
||||
"6400: acc=0.38921875\n",
|
||||
"9600: acc=0.4590625\n",
|
||||
"12800: acc=0.511953125\n",
|
||||
"16000: acc=0.5506875\n",
|
||||
"19200: acc=0.57921875\n",
|
||||
"22400: acc=0.6070089285714285\n",
|
||||
"25600: acc=0.6304296875\n",
|
||||
"28800: acc=0.6484027777777778\n",
|
||||
"32000: acc=0.66509375\n",
|
||||
"35200: acc=0.6790056818181818\n",
|
||||
"38400: acc=0.6929166666666666\n",
|
||||
"41600: acc=0.7035817307692308\n",
|
||||
"44800: acc=0.7137276785714286\n",
|
||||
"48000: acc=0.72225\n",
|
||||
"51200: acc=0.73001953125\n",
|
||||
"54400: acc=0.7372794117647059\n",
|
||||
"57600: acc=0.7436631944444444\n",
|
||||
"60800: acc=0.7503947368421052\n",
|
||||
"64000: acc=0.75634375\n",
|
||||
"67200: acc=0.7615773809523809\n",
|
||||
"70400: acc=0.7662642045454545\n",
|
||||
"73600: acc=0.7708423913043478\n",
|
||||
"76800: acc=0.7751822916666666\n",
|
||||
"80000: acc=0.7790625\n",
|
||||
"83200: acc=0.7825\n",
|
||||
"86400: acc=0.7858564814814815\n",
|
||||
"89600: acc=0.7890513392857142\n",
|
||||
"92800: acc=0.7920474137931034\n",
|
||||
"96000: acc=0.7952708333333334\n",
|
||||
"99200: acc=0.7982258064516129\n",
|
||||
"102400: acc=0.80099609375\n",
|
||||
"105600: acc=0.8037594696969697\n",
|
||||
"108800: acc=0.8060569852941176\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=padify, shuffle=True)\n",
|
||||
"net = RNNClassifier(vocab_size,64,32,len(classes)).to(device)\n",
|
||||
"train_epoch(net,train_loader, lr=0.001)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 長短期記憶(LSTM)\n",
|
||||
"\n",
|
||||
"古典的なRNNの主な問題の1つは、いわゆる**勾配消失**問題です。RNNは1回の逆伝播でエンドツーエンドに学習するため、ネットワークの最初の層に誤差を伝播させるのが難しくなり、その結果、遠く離れたトークン間の関係を学習することができません。この問題を回避する方法の1つは、**ゲート**と呼ばれる仕組みを使用して**明示的な状態管理**を導入することです。この種のアーキテクチャで最もよく知られているものは、**長短期記憶(LSTM)**と**ゲート付きリレー単位(GRU)**です。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"LSTMネットワークはRNNに似た構造で組織されていますが、層から層へ渡される2つの状態があります。それは、実際の状態$c$と隠れベクトル$h$です。各ユニットでは、隠れベクトル$h_i$が入力$x_i$と結合され、それらが**ゲート**を介して状態$c$に何が起こるかを制御します。各ゲートはシグモイド活性化関数(出力範囲は$[0,1]$)を持つニューラルネットワークであり、状態ベクトルと掛け算することでビットマスクのように考えることができます。以下のゲートがあります(上記の図で左から右へ):\n",
|
||||
"* **忘却ゲート**は隠れベクトルを受け取り、ベクトル$c$のどの成分を忘れるべきか、どの成分を通過させるべきかを決定します。\n",
|
||||
"* **入力ゲート**は入力と隠れベクトルから情報を取り出し、それを状態に挿入します。\n",
|
||||
"* **出力ゲート**は状態を$\\tanh$活性化を持つ線形層を通して変換し、その後、隠れベクトル$h_i$を使用してその成分の一部を選択し、新しい状態$c_{i+1}$を生成します。\n",
|
||||
"\n",
|
||||
"状態$c$の成分は、オン・オフを切り替えられるフラグのように考えることができます。例えば、シーケンス内で*Alice*という名前に出会ったとき、それが女性キャラクターを指していると仮定し、文中に女性名詞があるというフラグを状態に立てることができます。その後、*and Tom*というフレーズに出会ったときには、複数名詞があるというフラグを立てます。このようにして、状態を操作することで文の文法的な特性を追跡できると考えられます。\n",
|
||||
"\n",
|
||||
"> **Note**: LSTMの内部構造を理解するための素晴らしいリソースとして、Christopher Olahによる[Understanding LSTM Networks](https://colah.github.io/posts/2015-08-Understanding-LSTMs/)という記事があります。\n",
|
||||
"\n",
|
||||
"LSTMセルの内部構造は複雑に見えるかもしれませんが、PyTorchはこの実装を`LSTMCell`クラス内に隠しており、LSTM層全体を表す`LSTM`オブジェクトを提供しています。そのため、LSTM分類器の実装は、前述の単純なRNNと非常に似たものになります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class LSTMClassifier(torch.nn.Module):\n",
|
||||
" def __init__(self, vocab_size, embed_dim, hidden_dim, num_class):\n",
|
||||
" super().__init__()\n",
|
||||
" self.hidden_dim = hidden_dim\n",
|
||||
" self.embedding = torch.nn.Embedding(vocab_size, embed_dim)\n",
|
||||
" self.embedding.weight.data = torch.randn_like(self.embedding.weight.data)-0.5\n",
|
||||
" self.rnn = torch.nn.LSTM(embed_dim,hidden_dim,batch_first=True)\n",
|
||||
" self.fc = torch.nn.Linear(hidden_dim, num_class)\n",
|
||||
"\n",
|
||||
" def forward(self, x):\n",
|
||||
" batch_size = x.size(0)\n",
|
||||
" x = self.embedding(x)\n",
|
||||
" x,(h,c) = self.rnn(x)\n",
|
||||
" return self.fc(h[-1])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3200: acc=0.259375\n",
|
||||
"6400: acc=0.25859375\n",
|
||||
"9600: acc=0.26177083333333334\n",
|
||||
"12800: acc=0.2784375\n",
|
||||
"16000: acc=0.313\n",
|
||||
"19200: acc=0.3528645833333333\n",
|
||||
"22400: acc=0.3965625\n",
|
||||
"25600: acc=0.4385546875\n",
|
||||
"28800: acc=0.4752777777777778\n",
|
||||
"32000: acc=0.505375\n",
|
||||
"35200: acc=0.5326704545454546\n",
|
||||
"38400: acc=0.5557552083333334\n",
|
||||
"41600: acc=0.5760817307692307\n",
|
||||
"44800: acc=0.5954910714285714\n",
|
||||
"48000: acc=0.6118333333333333\n",
|
||||
"51200: acc=0.62681640625\n",
|
||||
"54400: acc=0.6404779411764706\n",
|
||||
"57600: acc=0.6520138888888889\n",
|
||||
"60800: acc=0.662828947368421\n",
|
||||
"64000: acc=0.673546875\n",
|
||||
"67200: acc=0.6831547619047619\n",
|
||||
"70400: acc=0.6917897727272727\n",
|
||||
"73600: acc=0.6997146739130434\n",
|
||||
"76800: acc=0.707109375\n",
|
||||
"80000: acc=0.714075\n",
|
||||
"83200: acc=0.7209134615384616\n",
|
||||
"86400: acc=0.727037037037037\n",
|
||||
"89600: acc=0.7326674107142858\n",
|
||||
"92800: acc=0.7379633620689655\n",
|
||||
"96000: acc=0.7433645833333333\n",
|
||||
"99200: acc=0.7479032258064516\n",
|
||||
"102400: acc=0.752119140625\n",
|
||||
"105600: acc=0.7562405303030303\n",
|
||||
"108800: acc=0.76015625\n",
|
||||
"112000: acc=0.7641339285714286\n",
|
||||
"115200: acc=0.7677777777777778\n",
|
||||
"118400: acc=0.7711233108108108\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(0.03487814127604167, 0.7728)"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"net = LSTMClassifier(vocab_size,64,32,len(classes)).to(device)\n",
|
||||
"train_epoch(net,train_loader, lr=0.001)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## パックされたシーケンス\n",
|
||||
"\n",
|
||||
"この例では、ミニバッチ内のすべてのシーケンスをゼロベクトルでパディングする必要がありました。この方法ではメモリの無駄が発生するだけでなく、RNNではパディングされた入力項目のために追加のRNNセルが作成されることが問題となります。これらのセルは学習に参加しますが、重要な入力情報を持っていません。そのため、RNNを実際のシーケンスサイズに合わせて学習させる方がはるかに効率的です。\n",
|
||||
"\n",
|
||||
"これを実現するために、PyTorchではパディングされたシーケンスを特別な形式で保存する方法が導入されています。例えば、以下のようなパディングされたミニバッチがあるとします:\n",
|
||||
"```\n",
|
||||
"[[1,2,3,4,5],\n",
|
||||
" [6,7,8,0,0],\n",
|
||||
" [9,0,0,0,0]]\n",
|
||||
"```\n",
|
||||
"ここで、0はパディングされた値を表し、入力シーケンスの実際の長さのベクトルは `[5,3,1]` です。\n",
|
||||
"\n",
|
||||
"パディングされたシーケンスでRNNを効率的に学習させるためには、まず最初のRNNセルのグループを大きなミニバッチ(`[1,6,9]`)で学習を開始し、次に3番目のシーケンスの処理を終了して、短縮されたミニバッチ(`[2,7]`、`[3,8]`)で学習を続ける必要があります。このようにして、パックされたシーケンスは1つのベクトルとして表されます。この場合、`[1,6,9,2,7,3,8,4,5]` と長さのベクトル(`[5,3,1]`)で表現され、これを使って元のパディングされたミニバッチを簡単に再構築することができます。\n",
|
||||
"\n",
|
||||
"パックされたシーケンスを生成するには、`torch.nn.utils.rnn.pack_padded_sequence` 関数を使用します。RNN、LSTM、GRUを含むすべての再帰層は、入力としてパックされたシーケンスをサポートしており、パックされた出力を生成します。この出力は、`torch.nn.utils.rnn.pad_packed_sequence` を使用してデコードできます。\n",
|
||||
"\n",
|
||||
"パックされたシーケンスを生成するには、ネットワークに長さのベクトルを渡す必要があるため、ミニバッチを準備するための別の関数が必要です。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def pad_length(b):\n",
|
||||
" # build vectorized sequence\n",
|
||||
" v = [encode(x[1]) for x in b]\n",
|
||||
" # compute max length of a sequence in this minibatch and length sequence itself\n",
|
||||
" len_seq = list(map(len,v))\n",
|
||||
" l = max(len_seq)\n",
|
||||
" return ( # tuple of three tensors - labels, padded features, length sequence\n",
|
||||
" torch.LongTensor([t[0]-1 for t in b]),\n",
|
||||
" torch.stack([torch.nn.functional.pad(torch.tensor(t),(0,l-len(t)),mode='constant',value=0) for t in v]),\n",
|
||||
" torch.tensor(len_seq)\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"train_loader_len = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=pad_length, shuffle=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"実際のネットワークは上記の `LSTMClassifier` に非常に似ていますが、`forward` パスではパディングされたミニバッチとシーケンス長のベクトルの両方を受け取ります。埋め込みを計算した後、パックされたシーケンスを計算し、それを LSTM レイヤーに渡し、結果を再びアンパックします。\n",
|
||||
"\n",
|
||||
"> **Note**: 実際にはアンパックされた結果 `x` を使用しません。なぜなら、後続の計算では隠れ層からの出力を使用するためです。したがって、このコードからアンパック処理を完全に削除することも可能です。ここにアンパック処理を残している理由は、もしネットワークの出力をさらに計算で使用する必要がある場合に、このコードを簡単に修正できるようにするためです。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class LSTMPackClassifier(torch.nn.Module):\n",
|
||||
" def __init__(self, vocab_size, embed_dim, hidden_dim, num_class):\n",
|
||||
" super().__init__()\n",
|
||||
" self.hidden_dim = hidden_dim\n",
|
||||
" self.embedding = torch.nn.Embedding(vocab_size, embed_dim)\n",
|
||||
" self.embedding.weight.data = torch.randn_like(self.embedding.weight.data)-0.5\n",
|
||||
" self.rnn = torch.nn.LSTM(embed_dim,hidden_dim,batch_first=True)\n",
|
||||
" self.fc = torch.nn.Linear(hidden_dim, num_class)\n",
|
||||
"\n",
|
||||
" def forward(self, x, lengths):\n",
|
||||
" batch_size = x.size(0)\n",
|
||||
" x = self.embedding(x)\n",
|
||||
" pad_x = torch.nn.utils.rnn.pack_padded_sequence(x,lengths,batch_first=True,enforce_sorted=False)\n",
|
||||
" pad_x,(h,c) = self.rnn(pad_x)\n",
|
||||
" x, _ = torch.nn.utils.rnn.pad_packed_sequence(pad_x,batch_first=True)\n",
|
||||
" return self.fc(h[-1])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3200: acc=0.285625\n",
|
||||
"6400: acc=0.33359375\n",
|
||||
"9600: acc=0.3876041666666667\n",
|
||||
"12800: acc=0.44078125\n",
|
||||
"16000: acc=0.4825\n",
|
||||
"19200: acc=0.5235416666666667\n",
|
||||
"22400: acc=0.5559821428571429\n",
|
||||
"25600: acc=0.58609375\n",
|
||||
"28800: acc=0.6116666666666667\n",
|
||||
"32000: acc=0.63340625\n",
|
||||
"35200: acc=0.6525284090909091\n",
|
||||
"38400: acc=0.668515625\n",
|
||||
"41600: acc=0.6822596153846154\n",
|
||||
"44800: acc=0.6948214285714286\n",
|
||||
"48000: acc=0.7052708333333333\n",
|
||||
"51200: acc=0.71521484375\n",
|
||||
"54400: acc=0.7239889705882353\n",
|
||||
"57600: acc=0.7315277777777778\n",
|
||||
"60800: acc=0.7388486842105263\n",
|
||||
"64000: acc=0.74571875\n",
|
||||
"67200: acc=0.7518303571428572\n",
|
||||
"70400: acc=0.7576988636363636\n",
|
||||
"73600: acc=0.7628940217391305\n",
|
||||
"76800: acc=0.7681510416666667\n",
|
||||
"80000: acc=0.7728125\n",
|
||||
"83200: acc=0.7772235576923077\n",
|
||||
"86400: acc=0.7815393518518519\n",
|
||||
"89600: acc=0.7857700892857142\n",
|
||||
"92800: acc=0.7895043103448276\n",
|
||||
"96000: acc=0.7930520833333333\n",
|
||||
"99200: acc=0.7959072580645161\n",
|
||||
"102400: acc=0.798994140625\n",
|
||||
"105600: acc=0.802064393939394\n",
|
||||
"108800: acc=0.8051378676470589\n",
|
||||
"112000: acc=0.8077857142857143\n",
|
||||
"115200: acc=0.8104600694444445\n",
|
||||
"118400: acc=0.8128293918918919\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(0.029785829671223958, 0.8138166666666666)"
|
||||
]
|
||||
},
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"net = LSTMPackClassifier(vocab_size,64,32,len(classes)).to(device)\n",
|
||||
"train_epoch_emb(net,train_loader_len, lr=0.001,use_pack_sequence=True)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **注意:** トレーニング関数に渡すパラメータ `use_pack_sequence` に気付いたかもしれません。現在、`pack_padded_sequence` 関数は長さシーケンステンソルがCPUデバイス上にあることを要求しているため、トレーニング関数はトレーニング時に長さシーケンスデータをGPUに移動することを避ける必要があります。[`torchnlp.py`](../../../../../lessons/5-NLP/16-RNN/torchnlp.py) ファイル内の `train_emb` 関数の実装を確認することができます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 双方向および多層RNN\n",
|
||||
"\n",
|
||||
"これまでの例では、すべてのリカレントネットワークがシーケンスの始まりから終わりに向かって一方向に動作していました。それは自然に感じられます。なぜなら、私たちが文章を読んだり音声を聞いたりする方法に似ているからです。しかし、実際のケースでは入力シーケンスにランダムアクセスできることが多いため、リカレント計算を両方向で実行する方が理にかなっている場合があります。このようなネットワークは**双方向**RNNと呼ばれ、RNN/LSTM/GRUのコンストラクタに`bidirectional=True`パラメータを渡すことで作成できます。\n",
|
||||
"\n",
|
||||
"双方向ネットワークを扱う場合、各方向に対して1つずつ、2つの隠れ状態ベクトルが必要になります。PyTorchではこれらのベクトルを2倍のサイズの1つのベクトルとしてエンコードします。これは非常に便利です。なぜなら、通常は結果として得られる隠れ状態を全結合の線形層に渡すため、このサイズの増加を考慮して層を作成するだけで済むからです。\n",
|
||||
"\n",
|
||||
"リカレントネットワーク(単方向でも双方向でも)は、シーケンス内の特定のパターンを捉え、それを状態ベクトルに保存したり、出力に渡したりすることができます。畳み込みネットワークと同様に、最初の層によって抽出された低レベルのパターンを基に、より高次のパターンを捉えるために、もう1つのリカレント層をその上に構築することができます。これにより、**多層RNN**という概念が生まれます。これは2つ以上のリカレントネットワークで構成され、前の層の出力が次の層の入力として渡されます。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"*Fernando Lópezによる[素晴らしい投稿](https://towardsdatascience.com/from-a-lstm-cell-to-a-multilayer-lstm-network-with-pytorch-2899eb5696f3)からの画像*\n",
|
||||
"\n",
|
||||
"PyTorchでは、このようなネットワークの構築が簡単です。RNN/LSTM/GRUのコンストラクタに`num_layers`パラメータを渡すだけで、複数のリカレント層を自動的に構築できます。この場合、隠れ状態ベクトルのサイズも比例して増加するため、リカレント層の出力を処理する際にこの点を考慮する必要があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 他のタスクにおけるRNN\n",
|
||||
"\n",
|
||||
"このユニットでは、RNNがシーケンス分類に使用できることを学びましたが、実際にはテキスト生成や機械翻訳など、さらに多くのタスクを処理することができます。これらのタスクについては次のユニットで検討します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知ください。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当方は一切の責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.8.12 ('py38')",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "522ee52ae3d5ae933e283286254e9a55",
|
||||
"translation_date": "2025-08-30T10:30:30+00:00",
|
||||
"source_file": "lessons/5-NLP/16-RNN/RNNPyTorch.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,460 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# 再帰型ニューラルネットワーク\n",
|
||||
"\n",
|
||||
"前のモジュールでは、テキストの豊かな意味表現について学びました。これまで使用してきたアーキテクチャは、文中の単語の集合的な意味を捉えることができますが、単語の**順序**を考慮していません。埋め込み後の集約操作によって、元のテキストからこの情報が失われるためです。このようなモデルは単語の順序を表現することができないため、テキスト生成や質問応答のような、より複雑で曖昧なタスクを解決することができません。\n",
|
||||
"\n",
|
||||
"テキストシーケンスの意味を捉えるために、**再帰型ニューラルネットワーク**(Recurrent Neural Network、RNN)と呼ばれるニューラルネットワークのアーキテクチャを使用します。RNNを使用する際には、文をネットワークに1トークンずつ通し、ネットワークが生成する**状態**を次のトークンとともに再びネットワークに渡します。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"トークンの入力シーケンス $X_0,\\dots,X_n$ が与えられると、RNNはニューラルネットワークブロックのシーケンスを作成し、このシーケンスをバックプロパゲーションを使用してエンドツーエンドで学習します。各ネットワークブロックは、入力としてペア $(X_i,S_i)$ を受け取り、結果として $S_{i+1}$ を生成します。最終状態 $S_n$ または出力 $Y_n$ は線形分類器に渡され、結果を生成します。すべてのネットワークブロックは同じ重みを共有し、1回のバックプロパゲーションパスでエンドツーエンドで学習されます。\n",
|
||||
"\n",
|
||||
"> 上の図は、展開された形(左側)とよりコンパクトな再帰表現(右側)の再帰型ニューラルネットワークを示しています。すべてのRNNセルが同じ**共有可能な重み**を持つことを理解することが重要です。\n",
|
||||
"\n",
|
||||
"状態ベクトル $S_0,\\dots,S_n$ がネットワークを通じて渡されるため、RNNは単語間の順序的な依存関係を学習することができます。例えば、シーケンス内のどこかに単語 *not* が現れる場合、状態ベクトル内の特定の要素を否定する方法を学習することができます。\n",
|
||||
"\n",
|
||||
"内部では、各RNNセルには2つの重み行列 $W_H$ と $W_I$、およびバイアス $b$ が含まれています。各RNNステップで、入力 $X_i$ と入力状態 $S_i$ が与えられると、出力状態は $S_{i+1} = f(W_H\\times S_i + W_I\\times X_i+b)$ として計算されます。ここで、$f$ は活性化関数(しばしば $\\tanh$)です。\n",
|
||||
"\n",
|
||||
"> テキスト生成(次のユニットで扱います)や機械翻訳のような問題では、各RNNステップで何らかの出力値を得たい場合があります。この場合、もう1つの行列 $W_O$ が存在し、出力は $Y_i=f(W_O\\times S_i+b_O)$ として計算されます。\n",
|
||||
"\n",
|
||||
"再帰型ニューラルネットワークがニュースデータセットの分類にどのように役立つかを見てみましょう。\n",
|
||||
"\n",
|
||||
"> サンドボックス環境では、必要なライブラリがインストールされ、データが事前取得されていることを確認するために、以下のセルを実行する必要があります。ローカルで実行している場合は、以下のセルをスキップできます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import sys\n",
|
||||
"!{sys.executable} -m pip install --quiet tensorflow_datasets==4.4.0\n",
|
||||
"!cd ~ && wget -q -O - https://mslearntensorflowlp.blob.core.windows.net/data/tfds-ag-news.tgz | tar xz"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import tensorflow as tf\n",
|
||||
"from tensorflow import keras\n",
|
||||
"import tensorflow_datasets as tfds\n",
|
||||
"import numpy as np\n",
|
||||
"\n",
|
||||
"# We are going to be training pretty large models. In order not to face errors, we need\n",
|
||||
"# to set tensorflow option to grow GPU memory allocation when required\n",
|
||||
"physical_devices = tf.config.list_physical_devices('GPU') \n",
|
||||
"if len(physical_devices)>0:\n",
|
||||
" tf.config.experimental.set_memory_growth(physical_devices[0], True)\n",
|
||||
"\n",
|
||||
"ds_train, ds_test = tfds.load('ag_news_subset').values()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"nteract": {
|
||||
"transient": {
|
||||
"deleting": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
"大規模なモデルをトレーニングする際、GPUメモリの割り当てが問題になることがあります。また、データがGPUメモリに収まるようにしつつ、トレーニングを十分に高速化するために、ミニバッチサイズを調整して試す必要があるかもしれません。このコードを自分のGPUマシンで実行している場合、トレーニングを高速化するためにミニバッチサイズを調整して試してみるとよいでしょう。\n",
|
||||
"\n",
|
||||
"> **Note**: 特定のバージョンのNVidiaドライバーでは、モデルのトレーニング後にメモリを解放しないことが知られています。このノートブックではいくつかの例を実行しており、特定の環境ではメモリが不足する可能性があります。特に、同じノートブック内で独自の実験を行っている場合にそのリスクが高まります。モデルのトレーニングを開始する際に奇妙なエラーが発生した場合、ノートブックのカーネルを再起動することを検討してください。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"jupyter": {
|
||||
"outputs_hidden": false,
|
||||
"source_hidden": false
|
||||
},
|
||||
"nteract": {
|
||||
"transient": {
|
||||
"deleting": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"batch_size = 16\n",
|
||||
"embed_size = 64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## シンプルなRNN分類器\n",
|
||||
"\n",
|
||||
"シンプルなRNNの場合、各リカレントユニットは単純な線形ネットワークで構成されており、入力ベクトルと状態ベクトルを受け取り、新しい状態ベクトルを生成します。Kerasでは、これを`SimpleRNN`レイヤーで表現できます。\n",
|
||||
"\n",
|
||||
"RNNレイヤーにワンホットエンコードされたトークンを直接渡すことも可能ですが、高次元であるため、これはあまり良い方法ではありません。そのため、まず埋め込みレイヤーを使用して単語ベクトルの次元を下げ、その後にRNNレイヤー、最後に`Dense`分類器を使用します。\n",
|
||||
"\n",
|
||||
"> **Note**: 次元がそれほど高くない場合、例えば文字レベルのトークン化を使用する場合には、ワンホットエンコードされたトークンを直接RNNセルに渡すのが理にかなっている場合もあります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"sequential\"\n",
|
||||
"_________________________________________________________________\n",
|
||||
"Layer (type) Output Shape Param # \n",
|
||||
"=================================================================\n",
|
||||
"text_vectorization (TextVect (None, None) 0 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"embedding (Embedding) (None, None, 64) 1280000 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"simple_rnn (SimpleRNN) (None, 16) 1296 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"dense (Dense) (None, 4) 68 \n",
|
||||
"=================================================================\n",
|
||||
"Total params: 1,281,364\n",
|
||||
"Trainable params: 1,281,364\n",
|
||||
"Non-trainable params: 0\n",
|
||||
"_________________________________________________________________\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vocab_size = 20000\n",
|
||||
"\n",
|
||||
"vectorizer = keras.layers.experimental.preprocessing.TextVectorization(\n",
|
||||
" max_tokens=vocab_size,\n",
|
||||
" input_shape=(1,))\n",
|
||||
"\n",
|
||||
"model = keras.models.Sequential([\n",
|
||||
" vectorizer,\n",
|
||||
" keras.layers.Embedding(vocab_size, embed_size),\n",
|
||||
" keras.layers.SimpleRNN(16),\n",
|
||||
" keras.layers.Dense(4,activation='softmax')\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"model.summary()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **Note:** ここでは簡単のために未学習の埋め込み層を使用していますが、より良い結果を得るためには、前のユニットで説明したように、Word2Vecを使用した事前学習済みの埋め込み層を使用することができます。このコードを事前学習済みの埋め込みに対応させるのは良い練習になるでしょう。\n",
|
||||
"\n",
|
||||
"では、RNNを訓練してみましょう。一般的にRNNは訓練が非常に難しいです。なぜなら、RNNセルがシーケンスの長さに沿って展開されると、逆伝播に関与する層の数が非常に多くなるからです。そのため、学習率を小さく設定し、大規模なデータセットでネットワークを訓練する必要があります。良い結果を得るには時間がかかるため、GPUを使用することが推奨されます。\n",
|
||||
"\n",
|
||||
"処理を高速化するために、ニュースのタイトルのみにRNNモデルを訓練し、説明文は省略します。説明文を含めて訓練を試し、モデルを訓練できるか試してみてください。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Training vectorizer\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def extract_title(x):\n",
|
||||
" return x['title']\n",
|
||||
"\n",
|
||||
"def tupelize_title(x):\n",
|
||||
" return (extract_title(x),x['label'])\n",
|
||||
"\n",
|
||||
"print('Training vectorizer')\n",
|
||||
"vectorizer.adapt(ds_train.take(2000).map(extract_title))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"7500/7500 [==============================] - 82s 11ms/step - loss: 0.6629 - acc: 0.7623 - val_loss: 0.5559 - val_acc: 0.7995\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7f3e0030d350>"
|
||||
]
|
||||
},
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
|
||||
"model.fit(ds_train.map(tupelize_title).batch(batch_size),validation_data=ds_test.map(tupelize_title).batch(batch_size))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"nteract": {
|
||||
"transient": {
|
||||
"deleting": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
"> **注意** ニュースのタイトルのみでトレーニングしているため、ここでの精度は低くなる可能性があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 変数シーケンスの再確認\n",
|
||||
"\n",
|
||||
"`TextVectorization`レイヤーは、ミニバッチ内の可変長シーケンスを自動的にパッドトークンで埋めます。ただし、これらのトークンもトレーニングに参加し、モデルの収束を複雑にする可能性があります。\n",
|
||||
"\n",
|
||||
"パディングの量を最小限に抑えるために取れるアプローチはいくつかあります。その1つは、データセットをシーケンスの長さで並べ替え、すべてのシーケンスをサイズごとにグループ化する方法です。これは、`tf.data.experimental.bucket_by_sequence_length`関数を使用して実行できます([ドキュメント](https://www.tensorflow.org/api_docs/python/tf/data/experimental/bucket_by_sequence_length)を参照)。\n",
|
||||
"\n",
|
||||
"もう1つのアプローチは、**マスキング**を使用することです。Kerasでは、一部のレイヤーがトレーニング時に考慮すべきトークンを示す追加の入力をサポートしています。モデルにマスキングを組み込むには、`Masking`レイヤーを別途追加する([ドキュメント](https://keras.io/api/layers/core_layers/masking/)を参照)か、`Embedding`レイヤーの`mask_zero=True`パラメータを指定する方法があります。\n",
|
||||
"\n",
|
||||
"> **Note**: このトレーニングは、データセット全体で1エポックを完了するのに約5分かかります。もし途中で待ちきれなくなった場合は、トレーニングを中断しても構いません。また、トレーニングに使用するデータ量を制限することもできます。その場合は、`ds_train`や`ds_test`データセットの後に`.take(...)`句を追加してください。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"7500/7500 [==============================] - 371s 49ms/step - loss: 0.5401 - acc: 0.8079 - val_loss: 0.3780 - val_acc: 0.8822\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7f3dec118850>"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def extract_text(x):\n",
|
||||
" return x['title']+' '+x['description']\n",
|
||||
"\n",
|
||||
"def tupelize(x):\n",
|
||||
" return (extract_text(x),x['label'])\n",
|
||||
"\n",
|
||||
"model = keras.models.Sequential([\n",
|
||||
" vectorizer,\n",
|
||||
" keras.layers.Embedding(vocab_size,embed_size,mask_zero=True),\n",
|
||||
" keras.layers.SimpleRNN(16),\n",
|
||||
" keras.layers.Dense(4,activation='softmax')\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"マスキングを使用することで、タイトルと説明の全データセットを使ってモデルを訓練できるようになりました。\n",
|
||||
"\n",
|
||||
"> **Note**: ニュースのタイトルで訓練されたベクトライザーを使用していることに気づきましたか?記事全体の本文ではなくタイトルだけを使っているため、一部のトークンが無視される可能性があります。そのため、ベクトライザーを再訓練する方が望ましいかもしれません。ただし、その影響はごくわずかである可能性が高いため、簡潔さを優先して以前の事前訓練済みベクトライザーを使用することにします。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## LSTM: 長短期記憶\n",
|
||||
"\n",
|
||||
"RNNの主な問題の1つは、**勾配消失**です。RNNは非常に長くなることがあり、逆伝播中にネットワークの最初の層まで勾配を伝播させるのが難しくなる場合があります。このような状況になると、ネットワークは離れたトークン間の関係を学習できなくなります。この問題を回避する1つの方法は、**ゲート**を使用して**明示的な状態管理**を導入することです。ゲートを導入する最も一般的なアーキテクチャは、**長短期記憶(LSTM)**と**ゲート付きリレー単位(GRU)**です。ここではLSTMについて説明します。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"LSTMネットワークはRNNと似た構造で組織されていますが、層から層へ渡される2つの状態があります。それは、実際の状態$c$と隠れベクトル$h$です。各ユニットでは、隠れベクトル$h_{t-1}$が入力$x_t$と組み合わされ、それらが一緒になって**ゲート**を通じて状態$c_t$と出力$h_t$に何が起こるかを制御します。各ゲートにはシグモイド活性化関数(出力範囲は$[0,1]$)があり、状態ベクトルに掛け算されるとビットマスクのように機能すると考えることができます。LSTMには以下のゲートがあります(上記の図で左から右に並んでいます):\n",
|
||||
"* **忘却ゲート**:ベクトル$c_{t-1}$のどの成分を忘れるべきか、またどの成分を通過させるべきかを決定します。\n",
|
||||
"* **入力ゲート**:入力ベクトルと前の隠れベクトルからどれだけの情報を状態ベクトルに取り込むべきかを決定します。\n",
|
||||
"* **出力ゲート**:新しい状態ベクトルを取り、それを使って新しい隠れベクトル$h_t$を生成する際にどの成分を使用するかを決定します。\n",
|
||||
"\n",
|
||||
"状態$c$の成分は、オン・オフを切り替えられるフラグのように考えることができます。例えば、シーケンス内で*Alice*という名前に出会ったとき、それが女性を指していると推測し、文中に女性名詞があることを示すフラグを状態で立てます。その後、*and Tom*という単語に出会うと、複数名詞があることを示すフラグを立てます。このように、状態を操作することで文法的な特性を追跡することができます。\n",
|
||||
"\n",
|
||||
"> **Note**: LSTMの内部構造を理解するための素晴らしいリソースはこちらです:[Understanding LSTM Networks](https://colah.github.io/posts/2015-08-Understanding-LSTMs/)(Christopher Olahによる)。\n",
|
||||
"\n",
|
||||
"LSTMセルの内部構造は複雑に見えるかもしれませんが、Kerasはこの実装を`LSTM`レイヤー内に隠しているため、上記の例で行う必要があるのは再帰レイヤーを置き換えることだけです。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"15000/15000 [==============================] - 188s 13ms/step - loss: 0.5692 - acc: 0.7916 - val_loss: 0.3441 - val_acc: 0.8870\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7f3d6af5c350>"
|
||||
]
|
||||
},
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model = keras.models.Sequential([\n",
|
||||
" vectorizer,\n",
|
||||
" keras.layers.Embedding(vocab_size, embed_size),\n",
|
||||
" keras.layers.LSTM(8),\n",
|
||||
" keras.layers.Dense(4,activation='softmax')\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(8),validation_data=ds_test.map(tupelize).batch(8))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 双方向および多層RNN\n",
|
||||
"\n",
|
||||
"これまでの例では、リカレントネットワークはシーケンスの始まりから終わりまで動作していました。この方法は、私たちが読む方向や話を聞く方向と一致しているため、自然に感じられます。しかし、入力シーケンスをランダムにアクセスする必要があるシナリオでは、リカレント計算を両方向で実行する方が理にかなっています。両方向で計算を可能にするRNNは**双方向RNN**と呼ばれ、リカレント層を特別な`Bidirectional`層でラップすることで作成できます。\n",
|
||||
"\n",
|
||||
"> **Note**: `Bidirectional`層は内部の層を2つコピーし、そのうちの1つの`go_backwards`プロパティを`True`に設定して、シーケンスに沿って逆方向に進むようにします。\n",
|
||||
"\n",
|
||||
"リカレントネットワーク(単方向でも双方向でも)は、シーケンス内のパターンを捉え、それを状態ベクトルに保存したり、出力として返したりします。畳み込みネットワークと同様に、最初の層で抽出された低レベルのパターンから構築された高レベルのパターンを捉えるために、最初の層の後に別のリカレント層を追加することができます。これにより、**多層RNN**という概念が生まれます。これは、2つ以上のリカレントネットワークで構成され、前の層の出力が次の層の入力として渡されます。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"*Fernando Lópezによる[素晴らしい投稿](https://towardsdatascience.com/from-a-lstm-cell-to-a-multilayer-lstm-network-with-pytorch-2899eb5696f3)からの画像。*\n",
|
||||
"\n",
|
||||
"Kerasを使用すると、これらのネットワークを簡単に構築できます。モデルにリカレント層を追加するだけで済みます。最後の層以外のすべての層では、`return_sequences=True`パラメータを指定する必要があります。これは、リカレント計算の最終状態だけでなく、すべての中間状態を返す必要があるためです。\n",
|
||||
"\n",
|
||||
"では、分類問題のために2層の双方向LSTMを構築してみましょう。\n",
|
||||
"\n",
|
||||
"> **Note** このコードは再び実行にかなり時間がかかりますが、これまでで最高の精度を達成します。そのため、待つ価値があるかもしれません。結果を確認してみましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"5044/7500 [===================>..........] - ETA: 2:33 - loss: 0.3709 - acc: 0.8706\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r5045/7500 [===================>..........] - ETA: 2:33 - loss: 0.3709 - acc: 0.8706"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model = keras.models.Sequential([\n",
|
||||
" vectorizer,\n",
|
||||
" keras.layers.Embedding(vocab_size, 128, mask_zero=True),\n",
|
||||
" keras.layers.Bidirectional(keras.layers.LSTM(64,return_sequences=True)),\n",
|
||||
" keras.layers.Bidirectional(keras.layers.LSTM(64)), \n",
|
||||
" keras.layers.Dense(4,activation='softmax')\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(batch_size),\n",
|
||||
" validation_data=ds_test.map(tupelize).batch(batch_size))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 他のタスクにおけるRNN\n",
|
||||
"\n",
|
||||
"これまで、RNNを使ってテキストのシーケンスを分類することに焦点を当ててきました。しかし、RNNはそれ以外にも、テキスト生成や機械翻訳など、さまざまなタスクを処理することができます。これらのタスクについては次のユニットで取り上げます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知ください。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当社は責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernel_info": {
|
||||
"name": "conda-env-py37_tensorflow-py"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "py37_tensorflow",
|
||||
"language": "python",
|
||||
"name": "conda-env-py37_tensorflow-py"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.7.9"
|
||||
},
|
||||
"nteract": {
|
||||
"version": "nteract-front-end@1.0.0"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "81351e61f619b432ff51010a4f993194",
|
||||
"translation_date": "2025-08-30T10:27:22+00:00",
|
||||
"source_file": "lessons/5-NLP/16-RNN/RNNTF.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -0,0 +1,416 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# 生成ネットワーク\n",
|
||||
"\n",
|
||||
"リカレントニューラルネットワーク (RNN) とそのゲート付きセルのバリエーション(例えば、長短期記憶セル (LSTM) やゲート付きリカレントユニット (GRU))は、言語モデル化の仕組みを提供します。つまり、これらは単語の順序を学習し、シーケンス内の次の単語を予測することができます。この特性により、RNNを使用して、通常のテキスト生成、機械翻訳、さらには画像キャプション生成といった**生成タスク**を実行することが可能になります。\n",
|
||||
"\n",
|
||||
"前のユニットで議論したRNNアーキテクチャでは、各RNNユニットが次の隠れ状態を出力として生成していました。しかし、各リカレントユニットにもう一つの出力を追加することで、**シーケンス**(元のシーケンスと同じ長さのもの)を出力することが可能になります。さらに、各ステップで入力を受け取らず、初期状態ベクトルだけを受け取り、それに基づいて出力シーケンスを生成するRNNユニットを使用することもできます。\n",
|
||||
"\n",
|
||||
"このノートブックでは、テキスト生成を助けるシンプルな生成モデルに焦点を当てます。簡単のために、**文字レベルのネットワーク**を構築し、文字ごとにテキストを生成します。トレーニング中には、テキストコーパスを取得し、それを文字列のシーケンスに分割する必要があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Loading dataset...\n",
|
||||
"Building vocab...\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import torch\n",
|
||||
"import torchtext\n",
|
||||
"import numpy as np\n",
|
||||
"from torchnlp import *\n",
|
||||
"train_dataset,test_dataset,classes,vocab = load_dataset()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## キャラクター語彙の構築\n",
|
||||
"\n",
|
||||
"キャラクターレベルの生成ネットワークを構築するには、テキストを単語ではなく個々の文字に分割する必要があります。これを実現するためには、異なるトークナイザーを定義する必要があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Vocabulary size = 82\n",
|
||||
"Encoding of 'a' is 1\n",
|
||||
"Character with code 13 is c\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def char_tokenizer(words):\n",
|
||||
" return list(words) #[word for word in words]\n",
|
||||
"\n",
|
||||
"counter = collections.Counter()\n",
|
||||
"for (label, line) in train_dataset:\n",
|
||||
" counter.update(char_tokenizer(line))\n",
|
||||
"vocab = torchtext.vocab.vocab(counter)\n",
|
||||
"\n",
|
||||
"vocab_size = len(vocab)\n",
|
||||
"print(f\"Vocabulary size = {vocab_size}\")\n",
|
||||
"print(f\"Encoding of 'a' is {vocab.get_stoi()['a']}\")\n",
|
||||
"print(f\"Character with code 13 is {vocab.get_itos()[13]}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"データセットからテキストをどのようにエンコードできるかの例を見てみましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"tensor([ 0, 1, 2, 2, 3, 4, 5, 6, 3, 7, 8, 1, 9, 10, 3, 11, 2, 1,\n",
|
||||
" 12, 3, 7, 1, 13, 14, 3, 15, 16, 5, 17, 3, 5, 18, 8, 3, 7, 2,\n",
|
||||
" 1, 13, 14, 3, 19, 20, 8, 21, 5, 8, 9, 10, 22, 3, 20, 8, 21, 5,\n",
|
||||
" 8, 9, 10, 3, 23, 3, 4, 18, 17, 9, 5, 23, 10, 8, 2, 2, 8, 9,\n",
|
||||
" 10, 24, 3, 0, 1, 2, 2, 3, 4, 5, 9, 8, 8, 5, 25, 10, 3, 26,\n",
|
||||
" 12, 27, 16, 26, 2, 27, 16, 28, 29, 30, 1, 16, 26, 3, 17, 31, 3, 21,\n",
|
||||
" 2, 5, 9, 1, 23, 13, 32, 16, 27, 13, 10, 24, 3, 1, 9, 8, 3, 10,\n",
|
||||
" 8, 8, 27, 16, 28, 3, 28, 9, 8, 8, 16, 3, 1, 28, 1, 27, 16, 6])"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def enc(x):\n",
|
||||
" return torch.LongTensor(encode(x,voc=vocab,tokenizer=char_tokenizer))\n",
|
||||
"\n",
|
||||
"enc(train_dataset[0][1])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## ジェネレーティブRNNのトレーニング\n",
|
||||
"\n",
|
||||
"RNNを使ってテキストを生成する方法は以下の通りです。各ステップで、`nchars`の長さの文字列を入力として取り、ネットワークに対して各入力文字に対する次の出力文字を生成するように求めます。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"実際のシナリオによっては、*end-of-sequence* `<eos>` のような特別な文字を含めることもあります。しかし、今回の場合は無限にテキストを生成するネットワークをトレーニングしたいので、各シーケンスのサイズを`nchars`トークンに固定します。その結果、各トレーニング例は`nchars`の入力と`nchars`の出力(入力シーケンスを1文字左にシフトしたもの)で構成されます。ミニバッチはこのようなシーケンスをいくつかまとめたものになります。\n",
|
||||
"\n",
|
||||
"ミニバッチを生成する方法としては、長さ`l`のニューステキストを取り、それから可能なすべての入力-出力の組み合わせを生成します(その組み合わせは`l-nchars`個になります)。これらは1つのミニバッチを形成し、トレーニングステップごとにミニバッチのサイズは異なることになります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(tensor([[ 0, 1, 2, ..., 28, 29, 30],\n",
|
||||
" [ 1, 2, 2, ..., 29, 30, 1],\n",
|
||||
" [ 2, 2, 3, ..., 30, 1, 16],\n",
|
||||
" ...,\n",
|
||||
" [20, 8, 21, ..., 1, 28, 1],\n",
|
||||
" [ 8, 21, 5, ..., 28, 1, 27],\n",
|
||||
" [21, 5, 8, ..., 1, 27, 16]]),\n",
|
||||
" tensor([[ 1, 2, 2, ..., 29, 30, 1],\n",
|
||||
" [ 2, 2, 3, ..., 30, 1, 16],\n",
|
||||
" [ 2, 3, 4, ..., 1, 16, 26],\n",
|
||||
" ...,\n",
|
||||
" [ 8, 21, 5, ..., 28, 1, 27],\n",
|
||||
" [21, 5, 8, ..., 1, 27, 16],\n",
|
||||
" [ 5, 8, 9, ..., 27, 16, 6]]))"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"nchars = 100\n",
|
||||
"\n",
|
||||
"def get_batch(s,nchars=nchars):\n",
|
||||
" ins = torch.zeros(len(s)-nchars,nchars,dtype=torch.long,device=device)\n",
|
||||
" outs = torch.zeros(len(s)-nchars,nchars,dtype=torch.long,device=device)\n",
|
||||
" for i in range(len(s)-nchars):\n",
|
||||
" ins[i] = enc(s[i:i+nchars])\n",
|
||||
" outs[i] = enc(s[i+1:i+nchars+1])\n",
|
||||
" return ins,outs\n",
|
||||
"\n",
|
||||
"get_batch(train_dataset[0][1])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ジェネレーター・ネットワークを定義してみましょう。これは、前のユニットで説明した任意のリカレントセル(シンプル、LSTM、またはGRU)を基に構築できます。この例ではLSTMを使用します。\n",
|
||||
"\n",
|
||||
"ネットワークは文字を入力として受け取り、語彙サイズが比較的小さいため、埋め込み層は必要ありません。一つのホットエンコードされた入力を直接LSTMセルに渡すことができます。ただし、文字の番号を入力として渡すため、LSTMに渡す前にそれらを一つのホットエンコードに変換する必要があります。これは、`forward`パス中に`one_hot`関数を呼び出すことで行われます。出力エンコーダーは、隠れ状態を一つのホットエンコードされた出力に変換する線形層になります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class LSTMGenerator(torch.nn.Module):\n",
|
||||
" def __init__(self, vocab_size, hidden_dim):\n",
|
||||
" super().__init__()\n",
|
||||
" self.rnn = torch.nn.LSTM(vocab_size,hidden_dim,batch_first=True)\n",
|
||||
" self.fc = torch.nn.Linear(hidden_dim, vocab_size)\n",
|
||||
"\n",
|
||||
" def forward(self, x, s=None):\n",
|
||||
" x = torch.nn.functional.one_hot(x,vocab_size).to(torch.float32)\n",
|
||||
" x,s = self.rnn(x,s)\n",
|
||||
" return self.fc(x),s"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"トレーニング中に生成されたテキストをサンプリングできるようにしたいと考えています。そのために、初期文字列 `start` から始まり、長さ `size` の出力文字列を生成する `generate` 関数を定義します。\n",
|
||||
"\n",
|
||||
"その動作は以下の通りです。まず、初期文字列全体をネットワークに通し、出力状態 `s` と次に予測される文字 `out` を取得します。`out` はワンホットエンコードされているため、`argmax` を使用して語彙内の文字 `nc` のインデックスを取得し、`itos` を使って実際の文字を特定し、結果として得られる文字列リスト `chars` に追加します。この1文字を生成するプロセスを `size` 回繰り返し、必要な文字数を生成します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def generate(net,size=100,start='today '):\n",
|
||||
" chars = list(start)\n",
|
||||
" out, s = net(enc(chars).view(1,-1).to(device))\n",
|
||||
" for i in range(size):\n",
|
||||
" nc = torch.argmax(out[0][-1])\n",
|
||||
" chars.append(vocab.get_itos()[nc])\n",
|
||||
" out, s = net(nc.view(1,-1),s)\n",
|
||||
" return ''.join(chars)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"さあ、トレーニングを始めましょう!トレーニングループはこれまでの例とほぼ同じですが、精度を表示する代わりに、1000エポックごとに生成されたテキストのサンプルを表示します。\n",
|
||||
"\n",
|
||||
"損失の計算方法には特に注意が必要です。損失を計算するには、ワンホットエンコードされた出力 `out` と、期待されるテキスト `text_out`(文字インデックスのリスト)を使用します。幸いなことに、`cross_entropy` 関数は非正規化されたネットワーク出力を最初の引数として受け取り、クラス番号を2番目の引数として受け取ります。これはまさに私たちが持っているものです。この関数はミニバッチサイズに対する自動平均化も行います。\n",
|
||||
"\n",
|
||||
"また、トレーニングを `samples_to_train` サンプルで制限し、待ち時間を短縮します。ぜひ実験してみて、より長いトレーニングを試してみてください。場合によっては、複数のエポックでトレーニングすることも可能です(その場合、このコードの周りに別のループを作成する必要があります)。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Current loss = 4.398899078369141\n",
|
||||
"today sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr s\n",
|
||||
"Current loss = 2.161320447921753\n",
|
||||
"today and to the tor to to the tor to to the tor to to the tor to to the tor to to the tor to to the tor t\n",
|
||||
"Current loss = 1.6722588539123535\n",
|
||||
"today and the court to the could to the could to the could to the could to the could to the could to the c\n",
|
||||
"Current loss = 2.423795223236084\n",
|
||||
"today and a second to the conternation of the conternation of the conternation of the conternation of the \n",
|
||||
"Current loss = 1.702607274055481\n",
|
||||
"today and the company to the company to the company to the company to the company to the company to the co\n",
|
||||
"Current loss = 1.692358136177063\n",
|
||||
"today and the company to the company to the company to the company to the company to the company to the co\n",
|
||||
"Current loss = 1.9722288846969604\n",
|
||||
"today and the control the control the control the control the control the control the control the control \n",
|
||||
"Current loss = 1.8705692291259766\n",
|
||||
"today and the second to the second to the second to the second to the second to the second to the second t\n",
|
||||
"Current loss = 1.7626899480819702\n",
|
||||
"today and a security and a security and a security and a security and a security and a security and a secu\n",
|
||||
"Current loss = 1.5574463605880737\n",
|
||||
"today and the company and the company and the company and the company and the company and the company and \n",
|
||||
"Current loss = 1.5620026588439941\n",
|
||||
"today and the be that the be the be that the be the be that the be the be that the be the be that the be t\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"net = LSTMGenerator(vocab_size,64).to(device)\n",
|
||||
"\n",
|
||||
"samples_to_train = 10000\n",
|
||||
"optimizer = torch.optim.Adam(net.parameters(),0.01)\n",
|
||||
"loss_fn = torch.nn.CrossEntropyLoss()\n",
|
||||
"net.train()\n",
|
||||
"for i,x in enumerate(train_dataset):\n",
|
||||
" # x[0] is class label, x[1] is text\n",
|
||||
" if len(x[1])-nchars<10:\n",
|
||||
" continue\n",
|
||||
" samples_to_train-=1\n",
|
||||
" if not samples_to_train: break\n",
|
||||
" text_in, text_out = get_batch(x[1])\n",
|
||||
" optimizer.zero_grad()\n",
|
||||
" out,s = net(text_in)\n",
|
||||
" loss = torch.nn.functional.cross_entropy(out.view(-1,vocab_size),text_out.flatten()) #cross_entropy(out,labels)\n",
|
||||
" loss.backward()\n",
|
||||
" optimizer.step()\n",
|
||||
" if i%1000==0:\n",
|
||||
" print(f\"Current loss = {loss.item()}\")\n",
|
||||
" print(generate(net))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"この例はすでにかなり良いテキストを生成していますが、いくつかの方法でさらに改善することができます:\n",
|
||||
"\n",
|
||||
"* **より良いミニバッチ生成** \n",
|
||||
" トレーニング用のデータを準備する際、1つのサンプルから1つのミニバッチを生成する方法を採用しました。しかし、この方法は理想的ではありません。ミニバッチのサイズがすべて異なり、テキストが`nchars`より小さい場合にはミニバッチを生成できないこともあります。また、小さなミニバッチではGPUを十分に活用できません。より賢明な方法は、すべてのサンプルから1つの大きなテキストチャンクを取得し、すべての入力-出力ペアを生成してシャッフルし、均等なサイズのミニバッチを生成することです。\n",
|
||||
"\n",
|
||||
"* **多層LSTM** \n",
|
||||
" LSTMセルを2層または3層試してみるのは理にかなっています。前のユニットで述べたように、LSTMの各層はテキストから特定のパターンを抽出します。文字レベルの生成器の場合、低いLSTM層が音節の抽出を担当し、より高い層が単語や単語の組み合わせを担当すると予想されます。これは、LSTMコンストラクタに層数のパラメータを渡すことで簡単に実装できます。\n",
|
||||
"\n",
|
||||
"* **GRUユニット**を試してみて、どちらがより良い結果を出すかを確認することもできます。また、**異なる隠れ層のサイズ**を試してみるのも良いでしょう。隠れ層が大きすぎると過学習を引き起こす可能性があります(例えば、ネットワークがテキストをそのまま学習してしまう)。一方で、サイズが小さすぎると良い結果が得られない可能性があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## ソフトテキスト生成と温度\n",
|
||||
"\n",
|
||||
"以前の`generate`の定義では、生成されるテキストの次の文字として、常に最も高い確率を持つ文字を選んでいました。この結果、以下の例のように、テキストが同じ文字列の繰り返しになりがちでした。\n",
|
||||
"```\n",
|
||||
"today of the second the company and a second the company ...\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"しかし、次の文字の確率分布を見てみると、いくつかの最も高い確率の間に大きな差がない場合があります。例えば、ある文字の確率が0.2で、別の文字が0.19であるといった具合です。たとえば、'*play*'というシーケンスの次の文字を探す場合、次の文字はスペースでも**e**(単語*player*のように)でも同じくらい適切である可能性があります。\n",
|
||||
"\n",
|
||||
"このことから、常に確率が最も高い文字を選ぶのが「公平」とは限らないという結論に至ります。2番目に高い確率の文字を選んでも、意味のあるテキストにつながる可能性があるのです。ネットワークの出力による確率分布から文字を**サンプリング**する方が賢明です。\n",
|
||||
"\n",
|
||||
"このサンプリングは、いわゆる**多項分布**を実装する`multinomial`関数を使用して行うことができます。この**ソフト**なテキスト生成を実装する関数は以下のように定義されます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"--- Temperature = 0.3\n",
|
||||
"Today and a company and complete an all the land the restrational the as a security and has provers the pay to and a report and the computer in the stand has filities and working the law the stations for a company and with the company and the final the first company and refight of the state and and workin\n",
|
||||
"\n",
|
||||
"--- Temperature = 0.8\n",
|
||||
"Today he oniis its first to Aus bomblaties the marmation a to manan boogot that pirate assaid a relaid their that goverfin the the Cappets Ecrotional Assonia Cition targets it annight the w scyments Blamity #39;s TVeer Diercheg Reserals fran envyuil that of ster said access what succers of Dour-provelith\n",
|
||||
"\n",
|
||||
"--- Temperature = 1.0\n",
|
||||
"Today holy they a 11 will meda a toket subsuaties, engins for Chanos, they's has stainger past to opening orital his thempting new Nattona was al innerforder advan-than #36;s night year his religuled talitatian what the but with Wednesday to Justment will wemen of Mark CCC Camp as Timed Nae wome a leaders\n",
|
||||
"\n",
|
||||
"--- Temperature = 1.3\n",
|
||||
"Today gpone 2.5 fech atcusion poor cocles toparsdorM.cht Line Pamage put 43 his calt lowed to the book, that has authh-the silia rruch ailing to'ory andhes beutirsimi- Aefffive heading offil an auf eacklets is charged evis, Gunymy oy) Mony has it after-sloythyor loveId out filme, the Natabl -Najuntaxiggs \n",
|
||||
"\n",
|
||||
"--- Temperature = 1.8\n",
|
||||
"Today plary, P.slan chly\\401 mardregationly #39;t 8.1Mide) closes ,filtcon alfly playin roven!\\grea.-QFBEP: Iss onfarchQ/itilia CCf Zivesigntwasta orce.-Peul-aw.uicrin of fuglinfsut aftaningwo, MIEX awayew Aice Woiduar Corvagiugge oppo esig ThusBratourid canthly-RyI.co lagitems\\eexciaishes.conBabntusmor I\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def generate_soft(net,size=100,start='today ',temperature=1.0):\n",
|
||||
" chars = list(start)\n",
|
||||
" out, s = net(enc(chars).view(1,-1).to(device))\n",
|
||||
" for i in range(size):\n",
|
||||
" #nc = torch.argmax(out[0][-1])\n",
|
||||
" out_dist = out[0][-1].div(temperature).exp()\n",
|
||||
" nc = torch.multinomial(out_dist,1)[0]\n",
|
||||
" chars.append(vocab.get_itos()[nc])\n",
|
||||
" out, s = net(nc.view(1,-1),s)\n",
|
||||
" return ''.join(chars)\n",
|
||||
" \n",
|
||||
"for i in [0.3,0.8,1.0,1.3,1.8]:\n",
|
||||
" print(f\"--- Temperature = {i}\\n{generate_soft(net,size=300,start='Today ',temperature=i)}\\n\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"私たちは、**温度**と呼ばれるもう1つのパラメーターを導入しました。これは、最高確率にどれだけ厳密に従うべきかを示すために使用されます。温度が1.0の場合、公平な多項分布サンプリングを行い、温度が無限大に近づくと、すべての確率が等しくなり、次の文字をランダムに選択します。以下の例では、温度を上げすぎるとテキストが無意味になることが観察でき、温度が0に近づくと「循環的な」厳密生成されたテキストに似てくることがわかります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知ください。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当方は一切の責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.8.12 ('py38')",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "7673cd150d96c74c6d6011460094efb4",
|
||||
"translation_date": "2025-08-30T10:12:33+00:00",
|
||||
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativePyTorch.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -0,0 +1,495 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# 生成ネットワーク\n",
|
||||
"\n",
|
||||
"リカレントニューラルネットワーク (RNN) とそのゲート付きセルのバリエーション(例えば、長短期記憶セル (LSTM) やゲート付きリカレントユニット (GRU))は、言語モデル化の仕組みを提供します。つまり、これらは単語の順序を学習し、シーケンス内の次の単語を予測することができます。この特性により、RNNを使って**生成タスク**を実行することが可能になります。例えば、通常のテキスト生成、機械翻訳、さらには画像キャプション生成などです。\n",
|
||||
"\n",
|
||||
"前のユニットで議論したRNNアーキテクチャでは、各RNNユニットが次の隠れ状態を出力として生成していました。しかし、各リカレントユニットにもう一つの出力を追加することで、**シーケンス**(元のシーケンスと同じ長さのもの)を出力することが可能になります。さらに、各ステップで入力を受け取らず、初期状態ベクトルだけを受け取り、それに基づいて出力のシーケンスを生成するRNNユニットを使用することもできます。\n",
|
||||
"\n",
|
||||
"このノートブックでは、テキスト生成を助けるシンプルな生成モデルに焦点を当てます。簡単のために、**文字レベルのネットワーク**を構築し、文字ごとにテキストを生成します。トレーニング中には、テキストコーパスを取得し、それを文字列のシーケンスに分割する必要があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import tensorflow as tf\n",
|
||||
"from tensorflow import keras\n",
|
||||
"import tensorflow_datasets as tfds\n",
|
||||
"import numpy as np\n",
|
||||
"\n",
|
||||
"ds_train, ds_test = tfds.load('ag_news_subset').values()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 文字ボキャブラリーの構築\n",
|
||||
"\n",
|
||||
"文字レベルの生成ネットワークを構築するには、テキストを単語ではなく個々の文字に分割する必要があります。これまで使用していた`TextVectorization`レイヤーではそれができないため、以下の2つの選択肢があります:\n",
|
||||
"\n",
|
||||
"* テキストを手動で読み込み、[この公式Kerasの例](https://keras.io/examples/generative/lstm_character_level_text_generation/)のように手作業でトークン化を行う\n",
|
||||
"* 文字レベルのトークン化に`Tokenizer`クラスを使用する\n",
|
||||
"\n",
|
||||
"ここでは2つ目の選択肢を選びます。`Tokenizer`は単語単位でのトークン化にも使用できるため、文字レベルから単語レベルのトークン化に簡単に切り替えることが可能です。\n",
|
||||
"\n",
|
||||
"文字レベルのトークン化を行うには、`char_level=True`パラメータを渡す必要があります:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def extract_text(x):\n",
|
||||
" return x['title']+' '+x['description']\n",
|
||||
"\n",
|
||||
"def tupelize(x):\n",
|
||||
" return (extract_text(x),x['label'])\n",
|
||||
"\n",
|
||||
"tokenizer = keras.preprocessing.text.Tokenizer(char_level=True,lower=False)\n",
|
||||
"tokenizer.fit_on_texts([x['title'].numpy().decode('utf-8') for x in ds_train])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"シーケンスの終了を示す特別なトークンとして**<eos>**を使用したいと考えています。それを語彙に手動で追加しましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"eos_token = len(tokenizer.word_index)+1\n",
|
||||
"tokenizer.word_index['<eos>'] = eos_token\n",
|
||||
"\n",
|
||||
"vocab_size = eos_token + 1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[[48, 2, 10, 10, 5, 44, 1, 25, 5, 8, 10, 13, 78]]"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"tokenizer.texts_to_sequences(['Hello, world!'])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## タイトル生成のための生成型RNNのトレーニング\n",
|
||||
"\n",
|
||||
"ニュースタイトルを生成するためにRNNをトレーニングする方法は以下の通りです。各ステップで1つのタイトルを取り出し、それをRNNに入力します。そして、各入力文字に対してネットワークに次の出力文字を生成させます。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"シーケンスの最後の文字に対しては、ネットワークに `<eos>` トークンを生成させます。\n",
|
||||
"\n",
|
||||
"ここで使用する生成型RNNの主な違いは、RNNの最終セルだけでなく、各ステップの出力を利用する点です。これを実現するには、RNNセルに `return_sequences` パラメータを指定します。\n",
|
||||
"\n",
|
||||
"したがって、トレーニング中のネットワークへの入力は、ある長さのエンコードされた文字列のシーケンスであり、出力は同じ長さのシーケンスですが、1つの要素分シフトされ、最後に `<eos>` で終了します。ミニバッチは複数のそのようなシーケンスで構成され、すべてのシーケンスを揃えるために**パディング**を使用する必要があります。\n",
|
||||
"\n",
|
||||
"データセットを変換する関数を作成しましょう。ミニバッチレベルでシーケンスをパディングしたいので、まず `.batch()` を呼び出してデータセットをバッチ化し、その後 `map` を使って変換を行います。この変換関数は、ミニバッチ全体をパラメータとして受け取ります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def title_batch(x):\n",
|
||||
" x = [t.numpy().decode('utf-8') for t in x]\n",
|
||||
" z = tokenizer.texts_to_sequences(x)\n",
|
||||
" z = tf.keras.preprocessing.sequence.pad_sequences(z)\n",
|
||||
" return tf.one_hot(z,vocab_size), tf.one_hot(tf.concat([z[:,1:],tf.constant(eos_token,shape=(len(z),1))],axis=1),vocab_size)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ここで行ういくつかの重要なこと:\n",
|
||||
"* まず、文字列テンソルから実際のテキストを抽出します\n",
|
||||
"* `text_to_sequences` は文字列のリストを整数テンソルのリストに変換します\n",
|
||||
"* `pad_sequences` はそれらのテンソルを最大長にパディングします\n",
|
||||
"* 最後に、すべての文字をワンホットエンコードし、シフトと `<eos>` の追加も行います。なぜワンホットエンコードされた文字が必要なのかは、すぐにわかるでしょう\n",
|
||||
"\n",
|
||||
"ただし、この関数は **Pythonic** であり、つまり Tensorflow の計算グラフに自動的に変換することはできません。この関数を直接 `Dataset.map` 関数で使用しようとするとエラーが発生します。この Pythonic な呼び出しを `py_function` ラッパーを使用して囲む必要があります:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def title_batch_fn(x):\n",
|
||||
" x = x['title']\n",
|
||||
" a,b = tf.py_function(title_batch,inp=[x],Tout=(tf.float32,tf.float32))\n",
|
||||
" return a,b"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **注**: Python的な変換関数とTensorflowの変換関数を区別するのは少し複雑に感じるかもしれません。また、なぜデータセットを`fit`に渡す前に標準的なPython関数を使って変換しないのか疑問に思うかもしれません。確かにそれも可能ですが、`Dataset.map`を使用することには大きな利点があります。それは、データ変換パイプラインがTensorflowの計算グラフを使用して実行されるため、GPU計算を活用でき、CPUとGPU間でデータをやり取りする必要性が最小限に抑えられる点です。\n",
|
||||
"\n",
|
||||
"さて、ジェネレーターネットワークを構築し、トレーニングを開始しましょう。これは、前のユニットで議論した任意の再帰型セル(シンプル、LSTM、またはGRU)に基づくことができます。この例ではLSTMを使用します。\n",
|
||||
"\n",
|
||||
"ネットワークは文字を入力として受け取り、語彙サイズが比較的小さいため、埋め込み層は必要ありません。一つのホットエンコードされた入力を直接LSTMセルに渡すことができます。出力層は`Dense`分類器となり、LSTMの出力を一つのホットエンコードされたトークン番号に変換します。\n",
|
||||
"\n",
|
||||
"さらに、可変長のシーケンスを扱うため、`Masking`層を使用して、文字列のパディング部分を無視するマスクを作成することができます。これは厳密には必要ではありません。なぜなら、`<eos>`トークン以降の内容にはあまり興味がないからです。しかし、この層タイプの経験を得るために使用してみます。`input_shape`は`(None, vocab_size)`となり、`None`は可変長のシーケンスを示します。また、出力形状も`(None, vocab_size)`となります。以下の`summary`からも確認できます:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"sequential\"\n",
|
||||
"_________________________________________________________________\n",
|
||||
"Layer (type) Output Shape Param # \n",
|
||||
"=================================================================\n",
|
||||
"masking (Masking) (None, None, 84) 0 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"lstm (LSTM) (None, None, 128) 109056 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"dense (Dense) (None, None, 84) 10836 \n",
|
||||
"=================================================================\n",
|
||||
"Total params: 119,892\n",
|
||||
"Trainable params: 119,892\n",
|
||||
"Non-trainable params: 0\n",
|
||||
"_________________________________________________________________\n",
|
||||
"15000/15000 [==============================] - 229s 15ms/step - loss: 1.5385\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7fa40c1245e0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model = keras.models.Sequential([\n",
|
||||
" keras.layers.Masking(input_shape=(None,vocab_size)),\n",
|
||||
" keras.layers.LSTM(128,return_sequences=True),\n",
|
||||
" keras.layers.Dense(vocab_size,activation='softmax')\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"model.summary()\n",
|
||||
"model.compile(loss='categorical_crossentropy')\n",
|
||||
"\n",
|
||||
"model.fit(ds_train.batch(8).map(title_batch_fn))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 出力の生成\n",
|
||||
"\n",
|
||||
"モデルのトレーニングが完了したので、次はそれを使って出力を生成してみましょう。まず、トークン番号のシーケンスで表現されたテキストをデコードする方法が必要です。このために、`tokenizer.sequences_to_texts` 関数を使うことができますが、文字レベルのトークン化ではうまく機能しません。したがって、トークナイザーから取得したトークンの辞書(`word_index` と呼ばれるもの)を使い、逆マップを作成して独自のデコード関数を作成します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"reverse_map = {val:key for key, val in tokenizer.word_index.items()}\n",
|
||||
"\n",
|
||||
"def decode(x):\n",
|
||||
" return ''.join([reverse_map[t] for t in x])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"まず、文字列 `start` を用意し、それをシーケンス `inp` にエンコードします。そして、各ステップでネットワークを呼び出し、次の文字を推測します。\n",
|
||||
"\n",
|
||||
"ネットワークの出力 `out` は、各トークンの確率を表す `vocab_size` 要素のベクトルです。`argmax` を使用して最も確率の高いトークン番号を見つけ、その文字を生成されたトークンのリストに追加します。そして、生成を続けます。このようにして1文字を生成するプロセスを `size` 回繰り返し、必要な文字数を生成します。`eos_token` が検出された場合は、早期に終了します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'Today #39;s lead to strike for the strike for the strike for the strike (AFP)'"
|
||||
]
|
||||
},
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def generate(model,size=100,start='Today '):\n",
|
||||
" inp = tokenizer.texts_to_sequences([start])[0]\n",
|
||||
" chars = inp\n",
|
||||
" for i in range(size):\n",
|
||||
" out = model(tf.expand_dims(tf.one_hot(inp,vocab_size),0))[0][-1]\n",
|
||||
" nc = tf.argmax(out)\n",
|
||||
" if nc==eos_token:\n",
|
||||
" break\n",
|
||||
" chars.append(nc.numpy())\n",
|
||||
" inp = inp+[nc]\n",
|
||||
" return decode(chars)\n",
|
||||
" \n",
|
||||
"generate(model)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## トレーニング中の出力サンプリング\n",
|
||||
"\n",
|
||||
"*精度*のような有用な指標がないため、モデルが改善しているかどうかを確認する唯一の方法は、トレーニング中に生成された文字列を**サンプリング**することです。そのために、**コールバック**を使用します。これは、`fit`関数に渡すことができ、トレーニング中に定期的に呼び出される関数のことです。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Epoch 1/3\n",
|
||||
"15000/15000 [==============================] - 226s 15ms/step - loss: 1.2703\n",
|
||||
"Today #39;s a lead in the company for the strike\n",
|
||||
"Epoch 2/3\n",
|
||||
"15000/15000 [==============================] - 227s 15ms/step - loss: 1.2057\n",
|
||||
"Today #39;s the Market Service on Security Start (AP)\n",
|
||||
"Epoch 3/3\n",
|
||||
"15000/15000 [==============================] - 226s 15ms/step - loss: 1.1752\n",
|
||||
"Today #39;s a line on the strike to start for the start\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7fa40c74e3d0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"sampling_callback = keras.callbacks.LambdaCallback(\n",
|
||||
" on_epoch_end = lambda batch, logs: print(generate(model))\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"model.fit(ds_train.batch(8).map(title_batch_fn),callbacks=[sampling_callback],epochs=3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"この例では、すでにかなり良いテキストを生成していますが、いくつかの方法でさらに改善することができます:\n",
|
||||
"\n",
|
||||
"* **テキスト量を増やす**。このタスクではタイトルのみを使用しましたが、全文で試してみるのも良いでしょう。ただし、RNNは長いシーケンスを扱うのが得意ではないため、短い文に分割するか、あらかじめ定義した値 `num_chars`(例えば256)の固定シーケンス長で常にトレーニングするのが理にかなっています。上記の例を変更してそのようなアーキテクチャにするには、[公式のKerasチュートリアル](https://keras.io/examples/generative/lstm_character_level_text_generation/)を参考にすると良いでしょう。\n",
|
||||
"\n",
|
||||
"* **多層LSTM**。LSTMセルを2層または3層にするのも試す価値があります。前のユニットで述べたように、LSTMの各層はテキストから特定のパターンを抽出します。文字レベルの生成器の場合、低いLSTM層は音節を抽出し、高い層は単語や単語の組み合わせを抽出すると予想されます。これは、LSTMコンストラクタに層数のパラメータを渡すことで簡単に実装できます。\n",
|
||||
"\n",
|
||||
"* **GRUユニット**を試してみて、どちらがより良い結果を出すか比較するのも良いでしょう。また、**異なる隠れ層のサイズ**を試すのも一案です。隠れ層が大きすぎると過学習(例えばネットワークが正確なテキストを学習してしまう)を引き起こす可能性があり、逆に小さすぎると良い結果が得られないかもしれません。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## ソフトテキスト生成と温度\n",
|
||||
"\n",
|
||||
"以前の`generate`の定義では、生成されるテキストの次の文字として、常に最も高い確率を持つ文字を選んでいました。この結果、以下の例のように、テキストが同じ文字列の繰り返しになりがちでした。\n",
|
||||
"```\n",
|
||||
"today of the second the company and a second the company ...\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"しかし、次の文字の確率分布を見てみると、いくつかの最も高い確率の間の差がそれほど大きくない場合があります。例えば、ある文字の確率が0.2で、別の文字が0.19である場合などです。たとえば、'*play*'という文字列の次の文字を探すとき、次の文字はスペースでも**e**(単語*player*のように)でも同じくらい適切である可能性があります。\n",
|
||||
"\n",
|
||||
"このことから、常に確率が最も高い文字を選ぶのが「公平」とは限らないという結論に至ります。2番目に高い確率の文字を選んでも、意味のあるテキストにつながる可能性があるからです。ネットワークの出力による確率分布から文字を**サンプリング**する方が賢明です。\n",
|
||||
"\n",
|
||||
"このサンプリングは、いわゆる**多項分布**を実装する`np.multinomial`関数を使用して行うことができます。この**ソフト**なテキスト生成を実装する関数は以下のように定義されています。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 33,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\n",
|
||||
"--- Temperature = 0.3\n",
|
||||
"Today #39;s strike #39; to start at the store return\n",
|
||||
"On Sunday PO to Be Data Profit Up (Reuters)\n",
|
||||
"Moscow, SP wins straight to the Microsoft #39;s control of the space start\n",
|
||||
"President olding of the blast start for the strike to pay <b>...</b>\n",
|
||||
"Little red riding hood ficed to the spam countered in European <b>...</b>\n",
|
||||
"\n",
|
||||
"--- Temperature = 0.8\n",
|
||||
"Today countie strikes ryder missile faces food market blut\n",
|
||||
"On Sunday collores lose-toppy of sale of Bullment in <b>...</b>\n",
|
||||
"Moscow, IBM Diffeiting in Afghan Software Hotels (Reuters)\n",
|
||||
"President Ol Luster for Profit Peaced Raised (AP)\n",
|
||||
"Little red riding hood dace on depart talks #39; bank up\n",
|
||||
"\n",
|
||||
"--- Temperature = 1.0\n",
|
||||
"Today wits House buiting debate fixes #39; supervice stake again\n",
|
||||
"On Sunday arling digital poaching In for level\n",
|
||||
"Moscow, DS Up 7, Top Proble Protest Caprey Mamarian Strike\n",
|
||||
"President teps help of roubler stepted lessabul-Dhalitics (AFP)\n",
|
||||
"Little red riding hood signs on cash in Carter-youb\n",
|
||||
"\n",
|
||||
"--- Temperature = 1.3\n",
|
||||
"Today wits flawer ro, pSIA figat's co DroftwavesIs Talo up\n",
|
||||
"On Sunday hround elitwing wint EU Powerburlinetien\n",
|
||||
"Moscow, Bazz #39;s sentries olymen winnelds' next for Olympite Huc?\n",
|
||||
"President lost securitys from power Elections in Smiltrials\n",
|
||||
"Little red riding hood vides profit, exponituity, profitmainalist-at said listers\n",
|
||||
"\n",
|
||||
"--- Temperature = 1.8\n",
|
||||
"Today #39;It: He deat: N.KA Asside\n",
|
||||
"On Sunday i arry Par aldeup patient Wo stele1\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ename": "KeyError",
|
||||
"evalue": "0",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
||||
"\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)",
|
||||
"\u001b[0;32m<ipython-input-33-db32367a0feb>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf\"\\n--- Temperature = {i}\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mj\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mgenerate_soft\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0msize\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m300\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mstart\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mwords\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mj\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mtemperature\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
|
||||
"\u001b[0;32m<ipython-input-33-db32367a0feb>\u001b[0m in \u001b[0;36mgenerate_soft\u001b[0;34m(model, size, start, temperature)\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0mchars\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0minp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0minp\u001b[0m\u001b[0;34m+\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mnc\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 13\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mchars\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 14\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 15\u001b[0m \u001b[0mwords\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m'Today '\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'On Sunday '\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'Moscow, '\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'President '\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'Little red riding hood '\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
||||
"\u001b[0;32m<ipython-input-10-3f5fa6130b1d>\u001b[0m in \u001b[0;36mdecode\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mreverse_map\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mt\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
|
||||
"\u001b[0;32m<ipython-input-10-3f5fa6130b1d>\u001b[0m in \u001b[0;36m<listcomp>\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mreverse_map\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mt\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
|
||||
"\u001b[0;31mKeyError\u001b[0m: 0"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def generate_soft(model,size=100,start='Today ',temperature=1.0):\n",
|
||||
" inp = tokenizer.texts_to_sequences([start])[0]\n",
|
||||
" chars = inp\n",
|
||||
" for i in range(size):\n",
|
||||
" out = model(tf.expand_dims(tf.one_hot(inp,vocab_size),0))[0][-1]\n",
|
||||
" probs = tf.exp(tf.math.log(out)/temperature).numpy().astype(np.float64)\n",
|
||||
" probs = probs/np.sum(probs)\n",
|
||||
" nc = np.argmax(np.random.multinomial(1,probs,1))\n",
|
||||
" if nc==eos_token:\n",
|
||||
" break\n",
|
||||
" chars.append(nc)\n",
|
||||
" inp = inp+[nc]\n",
|
||||
" return decode(chars)\n",
|
||||
"\n",
|
||||
"words = ['Today ','On Sunday ','Moscow, ','President ','Little red riding hood ']\n",
|
||||
" \n",
|
||||
"for i in [0.3,0.8,1.0,1.3,1.8]:\n",
|
||||
" print(f\"\\n--- Temperature = {i}\")\n",
|
||||
" for j in range(5):\n",
|
||||
" print(generate_soft(model,size=300,start=words[j],temperature=i))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"私たちは、**温度**と呼ばれるもう1つのパラメーターを導入しました。これは、最高確率にどれだけ厳密に従うべきかを示すために使用されます。温度が1.0の場合、公平な多項分布サンプリングを行い、温度が無限大に近づくとすべての確率が等しくなり、次の文字をランダムに選択します。以下の例では、温度を上げすぎるとテキストが意味をなさなくなり、温度が0に近づくと「循環的な」厳密生成テキストに似てくることが観察できます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書はAI翻訳サービス[Co-op Translator](https://github.com/Azure/co-op-translator)を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があります。元の言語で記載された文書を正式な情報源としてお考えください。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当方は責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.8.12 ('py38')",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "9fbb7d5fda708537649f71f5f646fcde",
|
||||
"translation_date": "2025-08-30T10:09:51+00:00",
|
||||
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -0,0 +1,353 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# 注意メカニズムとトランスフォーマー\n",
|
||||
"\n",
|
||||
"リカレントネットワークの主な欠点の一つは、シーケンス内のすべての単語が結果に同じ影響を与えることです。このため、名前付きエンティティ認識や機械翻訳などのシーケンス間タスクにおいて、標準的なLSTMエンコーダーデコーダーモデルでは性能が最適化されません。実際には、入力シーケンス内の特定の単語が他の単語よりも順序出力に大きな影響を与えることがよくあります。\n",
|
||||
"\n",
|
||||
"機械翻訳のようなシーケンス間モデルを考えてみましょう。このモデルは2つのリカレントネットワークによって実装されます。一つのネットワーク(**エンコーダー**)が入力シーケンスを隠れ状態に圧縮し、もう一つのネットワーク(**デコーダー**)がその隠れ状態を展開して翻訳結果を生成します。このアプローチの問題点は、ネットワークの最終状態が文の冒頭を記憶するのが難しくなるため、長い文に対してモデルの品質が低下することです。\n",
|
||||
"\n",
|
||||
"**注意メカニズム**は、RNNの各出力予測に対する各入力ベクトルの文脈的影響を重み付けする手段を提供します。これを実現する方法は、入力RNNの中間状態と出力RNNの間にショートカットを作成することです。この方法では、出力記号$y_t$を生成する際に、異なる重み係数$\\alpha_{t,i}$を用いてすべての入力隠れ状態$h_i$を考慮します。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"*[Bahdanau et al., 2015](https://arxiv.org/pdf/1409.0473.pdf)の加法型注意メカニズムを持つエンコーダーデコーダーモデル。画像は[このブログ記事](https://lilianweng.github.io/lil-log/2018/06/24/attention-attention.html)から引用。]*\n",
|
||||
"\n",
|
||||
"注意行列$\\{\\alpha_{i,j}\\}$は、出力シーケンス内の特定の単語の生成において、入力単語がどの程度影響を与えるかを表します。以下はそのような行列の例です:\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"*[Bahdanau et al., 2015](https://arxiv.org/pdf/1409.0473.pdf) (Fig.3)から引用された図]*\n",
|
||||
"\n",
|
||||
"注意メカニズムは、現在またはほぼ現在の自然言語処理の最先端技術の多くを支えています。しかし、注意を追加することでモデルのパラメータ数が大幅に増加し、RNNのスケーリング問題を引き起こしました。RNNのスケーリングにおける重要な制約は、モデルのリカレント性がバッチ処理やトレーニングの並列化を困難にすることです。RNNではシーケンスの各要素を順序通りに処理する必要があり、簡単に並列化することができません。\n",
|
||||
"\n",
|
||||
"注意メカニズムの採用とこの制約が組み合わさり、現在の最先端技術であるトランスフォーマーモデルが誕生しました。これらはBERTからOpenGPT3まで、私たちが今日知り、使用しているモデルです。\n",
|
||||
"\n",
|
||||
"## トランスフォーマーモデル\n",
|
||||
"\n",
|
||||
"各予測の文脈を次の評価ステップに渡す代わりに、**トランスフォーマーモデル**は**位置エンコーディング**と注意を使用して、指定されたテキストウィンドウ内で入力の文脈を捉えます。以下の画像は、位置エンコーディングと注意が指定されたウィンドウ内で文脈を捉える方法を示しています。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"各入力位置が独立して各出力位置にマッピングされるため、トランスフォーマーはRNNよりも並列化が容易であり、より大規模で表現力豊かな言語モデルを可能にします。各注意ヘッドは、単語間の異なる関係を学習するために使用され、下流の自然言語処理タスクを改善します。\n",
|
||||
"\n",
|
||||
"**BERT**(Bidirectional Encoder Representations from Transformers)は、非常に大規模な多層トランスフォーマーネットワークであり、*BERT-base*では12層、*BERT-large*では24層を持ちます。このモデルは、まず大規模なテキストデータ(Wikipedia + 書籍)を使用して教師なし学習(文中のマスクされた単語を予測する)で事前学習されます。事前学習中にモデルは言語理解の重要なレベルを吸収し、その後、他のデータセットで微調整することで活用できます。このプロセスは**転移学習**と呼ばれます。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"BERT、DistilBERT、BigBird、OpenGPT3など、微調整可能なトランスフォーマーアーキテクチャには多くのバリエーションがあります。[HuggingFaceパッケージ](https://github.com/huggingface/)は、PyTorchを使用してこれらのアーキテクチャの多くをトレーニングするためのリポジトリを提供しています。\n",
|
||||
"\n",
|
||||
"## BERTを使用したテキスト分類\n",
|
||||
"\n",
|
||||
"事前学習済みのBERTモデルを使用して、従来のタスクであるシーケンス分類を解決する方法を見てみましょう。元のAG Newsデータセットを分類します。\n",
|
||||
"\n",
|
||||
"まず、HuggingFaceライブラリとデータセットをロードします:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Loading dataset...\n",
|
||||
"Building vocab...\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import torch\n",
|
||||
"import torchtext\n",
|
||||
"from torchnlp import *\n",
|
||||
"import transformers\n",
|
||||
"train_dataset, test_dataset, classes, vocab = load_dataset()\n",
|
||||
"vocab_len = len(vocab)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"事前学習済みのBERTモデルを使用するため、特定のトークナイザーを使用する必要があります。まず、事前学習済みBERTモデルに関連付けられたトークナイザーを読み込みます。\n",
|
||||
"\n",
|
||||
"HuggingFaceライブラリには事前学習済みモデルのリポジトリが含まれており、モデル名を`from_pretrained`関数の引数として指定するだけで使用できます。モデルに必要なバイナリファイルはすべて自動的にダウンロードされます。\n",
|
||||
"\n",
|
||||
"ただし、場合によっては独自のモデルを読み込む必要があることもあります。その場合、トークナイザーのパラメータ、モデルパラメータを含む`config.json`ファイル、バイナリウェイトなど、関連するすべてのファイルを含むディレクトリを指定することができます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# To load the model from Internet repository using model name. \n",
|
||||
"# Use this if you are running from your own copy of the notebooks\n",
|
||||
"bert_model = 'bert-base-uncased' \n",
|
||||
"\n",
|
||||
"# To load the model from the directory on disk. Use this for Microsoft Learn module, because we have\n",
|
||||
"# prepared all required files for you.\n",
|
||||
"bert_model = './bert'\n",
|
||||
"\n",
|
||||
"tokenizer = transformers.BertTokenizer.from_pretrained(bert_model)\n",
|
||||
"\n",
|
||||
"MAX_SEQ_LEN = 128\n",
|
||||
"PAD_INDEX = tokenizer.convert_tokens_to_ids(tokenizer.pad_token)\n",
|
||||
"UNK_INDEX = tokenizer.convert_tokens_to_ids(tokenizer.unk_token)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"`tokenizer` オブジェクトには、テキストを直接エンコードするために使用できる `encode` 関数が含まれています。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[101, 1052, 22123, 2953, 2818, 2003, 1037, 2307, 7705, 2005, 17953, 2361, 102]"
|
||||
]
|
||||
},
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"tokenizer.encode('PyTorch is a great framework for NLP')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"次に、トレーニング中にデータにアクセスするために使用するイテレーターを作成しましょう。BERTは独自のエンコード関数を使用するため、以前に定義した`padify`に似たパディング関数を定義する必要があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def pad_bert(b):\n",
|
||||
" # b is the list of tuples of length batch_size\n",
|
||||
" # - first element of a tuple = label, \n",
|
||||
" # - second = feature (text sequence)\n",
|
||||
" # build vectorized sequence\n",
|
||||
" v = [tokenizer.encode(x[1]) for x in b]\n",
|
||||
" # compute max length of a sequence in this minibatch\n",
|
||||
" l = max(map(len,v))\n",
|
||||
" return ( # tuple of two tensors - labels and features\n",
|
||||
" torch.LongTensor([t[0] for t in b]),\n",
|
||||
" torch.stack([torch.nn.functional.pad(torch.tensor(t),(0,l-len(t)),mode='constant',value=0) for t in v])\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=8, collate_fn=pad_bert, shuffle=True)\n",
|
||||
"test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=8, collate_fn=pad_bert)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"私たちの場合、`bert-base-uncased`という事前学習済みのBERTモデルを使用します。`BertForSequenceClassfication`パッケージを使用してモデルをロードしましょう。これにより、分類のために必要なアーキテクチャがすでにモデルに含まれており、最終的な分類器も含まれています。最終的な分類器の重みが初期化されていないため、モデルには事前学習が必要であるという警告メッセージが表示されますが、それは全く問題ありません。なぜなら、まさにこれからそれを行うからです!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Some weights of the model checkpoint at ./bert were not used when initializing BertForSequenceClassification: ['cls.predictions.bias', 'cls.predictions.transform.dense.weight', 'cls.predictions.transform.dense.bias', 'cls.predictions.decoder.weight', 'cls.seq_relationship.weight', 'cls.seq_relationship.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.transform.LayerNorm.bias']\n",
|
||||
"- This IS expected if you are initializing BertForSequenceClassification from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n",
|
||||
"- This IS NOT expected if you are initializing BertForSequenceClassification from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n",
|
||||
"Some weights of BertForSequenceClassification were not initialized from the model checkpoint at ./bert and are newly initialized: ['classifier.weight', 'classifier.bias']\n",
|
||||
"You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model = transformers.BertForSequenceClassification.from_pretrained(bert_model,num_labels=4).to(device)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"さあ、トレーニングを始めましょう!BERTはすでに事前学習されているため、初期の重みを壊さないように、学習率をかなり小さく設定して始める必要があります。\n",
|
||||
"\n",
|
||||
"トレーニングの主要な処理は、`BertForSequenceClassification`モデルによって行われます。このモデルをトレーニングデータに適用すると、入力されたミニバッチに対して損失(loss)とネットワークの出力の両方を返します。損失はパラメータの最適化に使用され(`loss.backward()`で逆伝播を実行)、`out`は取得したラベル`labs`(`argmax`を使用して計算)と期待される`labels`を比較することでトレーニング精度を計算するために使用されます。\n",
|
||||
"\n",
|
||||
"プロセスを管理するために、いくつかのイテレーションにわたって損失と精度を累積し、`report_freq`トレーニングサイクルごとにそれらを出力します。\n",
|
||||
"\n",
|
||||
"このトレーニングはおそらくかなりの時間がかかるため、イテレーションの回数を制限します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Loss = 1.1254194641113282, Accuracy = 0.585\n",
|
||||
"Loss = 0.6194715118408203, Accuracy = 0.83\n",
|
||||
"Loss = 0.46665248870849607, Accuracy = 0.8475\n",
|
||||
"Loss = 0.4309701919555664, Accuracy = 0.8575\n",
|
||||
"Loss = 0.35427074432373046, Accuracy = 0.8825\n",
|
||||
"Loss = 0.3306886291503906, Accuracy = 0.8975\n",
|
||||
"Loss = 0.30340143203735354, Accuracy = 0.8975\n",
|
||||
"Loss = 0.26139299392700194, Accuracy = 0.915\n",
|
||||
"Loss = 0.26708646774291994, Accuracy = 0.9225\n",
|
||||
"Loss = 0.3667240524291992, Accuracy = 0.8675\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"optimizer = torch.optim.Adam(model.parameters(), lr=2e-5)\n",
|
||||
"\n",
|
||||
"report_freq = 50\n",
|
||||
"iterations = 500 # make this larger to train for longer time!\n",
|
||||
"\n",
|
||||
"model.train()\n",
|
||||
"\n",
|
||||
"i,c = 0,0\n",
|
||||
"acc_loss = 0\n",
|
||||
"acc_acc = 0\n",
|
||||
"\n",
|
||||
"for labels,texts in train_loader:\n",
|
||||
" labels = labels.to(device)-1 # get labels in the range 0-3 \n",
|
||||
" texts = texts.to(device)\n",
|
||||
" loss, out = model(texts, labels=labels)[:2]\n",
|
||||
" labs = out.argmax(dim=1)\n",
|
||||
" acc = torch.mean((labs==labels).type(torch.float32))\n",
|
||||
" optimizer.zero_grad()\n",
|
||||
" loss.backward()\n",
|
||||
" optimizer.step()\n",
|
||||
" acc_loss += loss\n",
|
||||
" acc_acc += acc\n",
|
||||
" i+=1\n",
|
||||
" c+=1\n",
|
||||
" if i%report_freq==0:\n",
|
||||
" print(f\"Loss = {acc_loss.item()/c}, Accuracy = {acc_acc.item()/c}\")\n",
|
||||
" c = 0\n",
|
||||
" acc_loss = 0\n",
|
||||
" acc_acc = 0\n",
|
||||
" iterations-=1\n",
|
||||
" if not iterations:\n",
|
||||
" break"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"BERT分類を使用すると(特に反復回数を増やして十分に待つと)、かなり良い精度が得られることがわかります!これは、BERTがすでに言語の構造を非常によく理解しており、最終的な分類器を微調整するだけで済むからです。しかし、BERTは大規模なモデルであるため、トレーニング全体のプロセスには時間がかかり、かなりの計算能力(GPU、できれば複数台)が必要です!\n",
|
||||
"\n",
|
||||
"> **Note:** この例では、最小クラスの事前学習済みBERTモデルの1つを使用しています。より大きなモデルを使用すれば、さらに良い結果が得られる可能性があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## モデルの性能評価\n",
|
||||
"\n",
|
||||
"これで、テストデータセットを使ってモデルの性能を評価できます。評価ループはトレーニングループと非常に似ていますが、`model.eval()`を呼び出してモデルを評価モードに切り替えることを忘れないようにしましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Final accuracy: 0.9047029702970297\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.eval()\n",
|
||||
"iterations = 100\n",
|
||||
"acc = 0\n",
|
||||
"i = 0\n",
|
||||
"for labels,texts in test_loader:\n",
|
||||
" labels = labels.to(device)-1 \n",
|
||||
" texts = texts.to(device)\n",
|
||||
" _, out = model(texts, labels=labels)[:2]\n",
|
||||
" labs = out.argmax(dim=1)\n",
|
||||
" acc += torch.mean((labs==labels).type(torch.float32))\n",
|
||||
" i+=1\n",
|
||||
" if i>iterations: break\n",
|
||||
" \n",
|
||||
"print(f\"Final accuracy: {acc.item()/i}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## まとめ\n",
|
||||
"\n",
|
||||
"このユニットでは、**transformers** ライブラリから事前学習済みの言語モデルを簡単に取り出し、テキスト分類タスクに適応させる方法を学びました。同様に、BERTモデルはエンティティ抽出、質問応答、その他のNLPタスクにも利用できます。\n",
|
||||
"\n",
|
||||
"トランスフォーマーモデルは、現在のNLPの最先端を代表しており、カスタムNLPソリューションを実装する際には、まず最初に試してみるべき選択肢です。しかし、高度なニューラルモデルを構築したい場合には、このモジュールで説明したリカレントニューラルネットワークの基本的な原理を理解することが非常に重要です。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があります。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当社は責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "py37_pytorch",
|
||||
"language": "python",
|
||||
"name": "conda-env-py37_pytorch-py"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.7.7"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "753865967678a92dbce7d7efbd36d980",
|
||||
"translation_date": "2025-08-30T10:18:13+00:00",
|
||||
"source_file": "lessons/5-NLP/18-Transformers/TransformersPyTorch.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -0,0 +1,825 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# 注意メカニズムとトランスフォーマー\n",
|
||||
"\n",
|
||||
"リカレントネットワークの主な欠点の一つは、シーケンス内のすべての単語が結果に同じ影響を与えることです。このため、名前付きエンティティ認識や機械翻訳などのシーケンス間タスクにおいて、標準的なLSTMエンコーダーデコーダーモデルでは性能が最適化されません。実際には、入力シーケンス内の特定の単語が他の単語よりも順序出力に大きな影響を与えることがよくあります。\n",
|
||||
"\n",
|
||||
"機械翻訳のようなシーケンス間モデルを考えてみましょう。このモデルは2つのリカレントネットワークによって実装されます。一つのネットワーク(**エンコーダー**)が入力シーケンスを隠れ状態に圧縮し、もう一つのネットワーク(**デコーダー**)がその隠れ状態を展開して翻訳結果を生成します。このアプローチの問題点は、ネットワークの最終状態が文の冒頭を記憶するのが難しくなるため、長い文に対してモデルの品質が低下することです。\n",
|
||||
"\n",
|
||||
"**注意メカニズム**は、RNNの各出力予測に対する各入力ベクトルの文脈的影響を重み付けする手段を提供します。このメカニズムは、入力RNNの中間状態と出力RNNの間にショートカットを作成することで実装されます。この方法では、出力記号$y_t$を生成する際に、異なる重み係数$\\alpha_{t,i}$を用いてすべての入力隠れ状態$h_i$を考慮します。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"*[Bahdanau et al., 2015](https://arxiv.org/pdf/1409.0473.pdf)の加法型注意メカニズムを備えたエンコーダーデコーダーモデル。画像は[このブログ記事](https://lilianweng.github.io/lil-log/2018/06/24/attention-attention.html)から引用。]*\n",
|
||||
"\n",
|
||||
"注意行列$\\{\\alpha_{i,j}\\}$は、出力シーケンス内の特定の単語の生成において、入力単語がどの程度影響を与えるかを表します。以下はそのような行列の例です:\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"*[Bahdanau et al., 2015](https://arxiv.org/pdf/1409.0473.pdf)(図3)から引用された図]*\n",
|
||||
"\n",
|
||||
"注意メカニズムは、現在またはほぼ現在の自然言語処理の最先端技術の多くを支えています。しかし、注意を追加することでモデルのパラメータ数が大幅に増加し、RNNのスケーリング問題を引き起こしました。RNNのスケーリングにおける重要な制約は、モデルのリカレント性がバッチ処理やトレーニングの並列化を困難にすることです。RNNではシーケンスの各要素を順序通りに処理する必要があるため、簡単に並列化することができません。\n",
|
||||
"\n",
|
||||
"注意メカニズムの採用とこの制約が組み合わさり、現在私たちが使用している最先端のトランスフォーマーモデル(BERTやOpenGPT3など)が誕生しました。\n",
|
||||
"\n",
|
||||
"## トランスフォーマーモデル\n",
|
||||
"\n",
|
||||
"各予測の文脈を次の評価ステップに渡す代わりに、**トランスフォーマーモデル**は**位置エンコーディング**と**注意**を使用して、指定されたテキストウィンドウ内で与えられた入力の文脈を捉えます。以下の画像は、位置エンコーディングと注意がどのようにして指定されたウィンドウ内の文脈を捉えるかを示しています。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"各入力位置が独立して各出力位置にマッピングされるため、トランスフォーマーはRNNよりも並列化が容易であり、より大規模で表現力豊かな言語モデルを可能にします。各注意ヘッドは、単語間の異なる関係を学習するために使用され、自然言語処理の下流タスクを改善します。\n",
|
||||
"\n",
|
||||
"## シンプルなトランスフォーマーモデルの構築\n",
|
||||
"\n",
|
||||
"Kerasには組み込みのトランスフォーマーレイヤーは含まれていませんが、自分で構築することができます。これまでと同様に、AG Newsデータセットのテキスト分類に焦点を当てますが、トランスフォーマーモデルはより難しいNLPタスクで最良の結果を示すことに注意する価値があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import tensorflow as tf\n",
|
||||
"from tensorflow import keras\n",
|
||||
"import tensorflow_datasets as tfds\n",
|
||||
"import numpy as np\n",
|
||||
"\n",
|
||||
"ds_train, ds_test = tfds.load('ag_news_subset').values()\n",
|
||||
"\n",
|
||||
"def extract_text(x):\n",
|
||||
" return x['title']+' '+x['description']\n",
|
||||
"\n",
|
||||
"def tupelize(x):\n",
|
||||
" return (extract_text(x),x['label'])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Kerasの新しいレイヤーは`Layer`クラスを継承し、`call`メソッドを実装する必要があります。まずは**Positional Embedding**レイヤーから始めましょう。[公式のKerasドキュメント](https://keras.io/examples/nlp/text_classification_with_transformer/)のコードを使用します。すべての入力シーケンスを長さ`maxlen`にパディングすることを前提とします。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class TokenAndPositionEmbedding(keras.layers.Layer):\n",
|
||||
" def __init__(self, maxlen, vocab_size, embed_dim):\n",
|
||||
" super(TokenAndPositionEmbedding, self).__init__()\n",
|
||||
" self.token_emb = keras.layers.Embedding(input_dim=vocab_size, output_dim=embed_dim)\n",
|
||||
" self.pos_emb = keras.layers.Embedding(input_dim=maxlen, output_dim=embed_dim)\n",
|
||||
" self.maxlen = maxlen\n",
|
||||
"\n",
|
||||
" def call(self, x):\n",
|
||||
" maxlen = self.maxlen\n",
|
||||
" positions = tf.range(start=0, limit=maxlen, delta=1)\n",
|
||||
" positions = self.pos_emb(positions)\n",
|
||||
" x = self.token_emb(x)\n",
|
||||
" return x+positions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"このレイヤーは2つの`Embedding`レイヤーで構成されています。1つはトークンを埋め込むためのもので(前に説明した方法で行います)、もう1つはトークンの位置を埋め込むためのものです。トークンの位置は、`tf.range`を使用して0から`maxlen`までの自然数のシーケンスとして作成され、それを埋め込みレイヤーに渡します。この2つの埋め込みベクトルを加算することで、入力の位置情報を埋め込んだ表現が得られます。この表現の形状は`maxlen`$\\times$`embed_dim`となります。\n",
|
||||
"\n",
|
||||
"次に、トランスフォーマーブロックを実装してみましょう。これは、先ほど定義した埋め込みレイヤーの出力を受け取ります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class TransformerBlock(keras.layers.Layer):\n",
|
||||
" def __init__(self, embed_dim, num_heads, ff_dim, rate=0.1):\n",
|
||||
" super(TransformerBlock, self).__init__()\n",
|
||||
" self.att = keras.layers.MultiHeadAttention(num_heads=num_heads, key_dim=embed_dim, name='attn')\n",
|
||||
" self.ffn = keras.Sequential(\n",
|
||||
" [keras.layers.Dense(ff_dim, activation=\"relu\"), keras.layers.Dense(embed_dim),]\n",
|
||||
" )\n",
|
||||
" self.layernorm1 = keras.layers.LayerNormalization(epsilon=1e-6)\n",
|
||||
" self.layernorm2 = keras.layers.LayerNormalization(epsilon=1e-6)\n",
|
||||
" self.dropout1 = keras.layers.Dropout(rate)\n",
|
||||
" self.dropout2 = keras.layers.Dropout(rate)\n",
|
||||
"\n",
|
||||
" def call(self, inputs, training):\n",
|
||||
" attn_output = self.att(inputs, inputs)\n",
|
||||
" attn_output = self.dropout1(attn_output, training=training)\n",
|
||||
" out1 = self.layernorm1(inputs + attn_output)\n",
|
||||
" ffn_output = self.ffn(out1)\n",
|
||||
" ffn_output = self.dropout2(ffn_output, training=training)\n",
|
||||
" return self.layernorm2(out1 + ffn_output)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Transformerは、位置エンコードされた入力に対して`MultiHeadAttention`を適用し、`maxlen`$\\times$`embed_dim`の次元を持つアテンションベクトルを生成します。このベクトルは入力と混合され、`LayerNormalization`を使用して正規化されます。\n",
|
||||
"\n",
|
||||
"> **Note**: `LayerNormalization`は、この学習パスの*コンピュータビジョン*の部分で説明した`BatchNormalization`に似ていますが、各トレーニングサンプルの前の層の出力を独立して正規化し、[-1..1]の範囲に収めます。\n",
|
||||
"\n",
|
||||
"この層の出力は次に`Dense`ネットワーク(この場合、2層のパーセプトロン)を通過し、その結果が最終出力に加えられます(最終出力も再び正規化されます)。\n",
|
||||
"\n",
|
||||
"さて、完全なTransformerモデルを定義する準備が整いました:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"sequential_1\"\n",
|
||||
"_________________________________________________________________\n",
|
||||
"Layer (type) Output Shape Param # \n",
|
||||
"=================================================================\n",
|
||||
"text_vectorization (TextVect (None, 256) 0 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"token_and_position_embedding (None, 256, 32) 648192 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"transformer_block (Transform (None, 256, 32) 10656 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"global_average_pooling1d (Gl (None, 32) 0 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"dropout_2 (Dropout) (None, 32) 0 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"dense_2 (Dense) (None, 20) 660 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"dropout_3 (Dropout) (None, 20) 0 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"dense_3 (Dense) (None, 4) 84 \n",
|
||||
"=================================================================\n",
|
||||
"Total params: 659,592\n",
|
||||
"Trainable params: 659,592\n",
|
||||
"Non-trainable params: 0\n",
|
||||
"_________________________________________________________________\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"embed_dim = 32 # Embedding size for each token\n",
|
||||
"num_heads = 2 # Number of attention heads\n",
|
||||
"ff_dim = 32 # Hidden layer size in feed forward network inside transformer\n",
|
||||
"maxlen = 256\n",
|
||||
"vocab_size = 20000\n",
|
||||
"\n",
|
||||
"model = keras.models.Sequential([\n",
|
||||
" keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,output_sequence_length=maxlen, input_shape=(1,)),\n",
|
||||
" TokenAndPositionEmbedding(maxlen, vocab_size, embed_dim),\n",
|
||||
" TransformerBlock(embed_dim, num_heads, ff_dim),\n",
|
||||
" keras.layers.GlobalAveragePooling1D(),\n",
|
||||
" keras.layers.Dropout(0.1),\n",
|
||||
" keras.layers.Dense(20, activation=\"relu\"),\n",
|
||||
" keras.layers.Dropout(0.1),\n",
|
||||
" keras.layers.Dense(4, activation=\"softmax\")\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"model.summary()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Training tokenizer\n",
|
||||
"938/938 [==============================] - 45s 39ms/step - loss: 0.4978 - acc: 0.8068 - val_loss: 0.2808 - val_acc: 0.9124\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7f9c2427a0d0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print('Training tokenizer')\n",
|
||||
"model.layers[0].adapt(ds_train.map(extract_text))\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(128),validation_data=ds_test.map(tupelize).batch(128))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## BERT トランスフォーマーモデル\n",
|
||||
"\n",
|
||||
"**BERT**(Bidirectional Encoder Representations from Transformers)は、非常に大規模な多層トランスフォーマーネットワークで、*BERT-base* では12層、*BERT-large* では24層の構造を持っています。このモデルは、まず大規模なテキストデータ(Wikipedia + 書籍)を使用して、教師なし学習(文中のマスクされた単語を予測する)で事前学習されます。事前学習の過程で、モデルは言語理解の高度な知識を吸収し、その後、他のデータセットで微調整を行うことで活用できます。このプロセスは**転移学習**と呼ばれます。\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"BERT、DistilBERT、BigBird、OpenGPT3 など、微調整可能なトランスフォーマーアーキテクチャには多くのバリエーションがあります。\n",
|
||||
"\n",
|
||||
"では、事前学習済みの BERT モデルを使用して、従来のシーケンス分類問題を解決する方法を見てみましょう。[公式ドキュメント](https://www.tensorflow.org/text/tutorials/classify_text_with_bert)からアイデアと一部のコードを拝借します。\n",
|
||||
"\n",
|
||||
"事前学習済みモデルをロードするには、**Tensorflow hub** を使用します。まず、BERT 専用のベクトライザーをロードしましょう:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "ModuleNotFoundError",
|
||||
"evalue": "No module named 'tensorflow_text'",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
|
||||
"\u001b[1;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)",
|
||||
"\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_41180/4216669875.py\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mimport\u001b[0m \u001b[0mtensorflow_text\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mtensorflow_hub\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mhub\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[0mvectorizer\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mhub\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mKerasLayer\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
|
||||
"\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'tensorflow_text'"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import tensorflow_text \n",
|
||||
"import tensorflow_hub as hub\n",
|
||||
"vectorizer = hub.KerasLayer('https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'input_type_ids': <tf.Tensor: shape=(1, 128), dtype=int32, numpy=\n",
|
||||
" array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],\n",
|
||||
" dtype=int32)>,\n",
|
||||
" 'input_word_ids': <tf.Tensor: shape=(1, 128), dtype=int32, numpy=\n",
|
||||
" array([[ 101, 1045, 2293, 19081, 102, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0]], dtype=int32)>,\n",
|
||||
" 'input_mask': <tf.Tensor: shape=(1, 128), dtype=int32, numpy=\n",
|
||||
" array([[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],\n",
|
||||
" dtype=int32)>}"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vectorizer(['I love transformers'])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"元のネットワークが訓練された際に使用されたものと同じベクトライザーを使用することが重要です。また、BERTベクトライザーは以下の3つのコンポーネントを返します:\n",
|
||||
"* `input_word_ids`:入力文のトークン番号のシーケンス\n",
|
||||
"* `input_mask`:シーケンスのどの部分が実際の入力で、どの部分がパディングであるかを示します。これは、`Masking`レイヤーによって生成されるマスクに似ています\n",
|
||||
"* `input_type_ids`:言語モデリングタスクで使用され、1つのシーケンス内で2つの入力文を指定することができます。\n",
|
||||
"\n",
|
||||
"次に、BERT特徴抽出器をインスタンス化します:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"bert = hub.KerasLayer('https://tfhub.dev/tensorflow/small_bert/bert_en_uncased_L-4_H-128_A-2/1')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"pooled_output -> (1, 128)\n",
|
||||
"encoder_outputs -> 4\n",
|
||||
"sequence_output -> (1, 128, 128)\n",
|
||||
"default -> (1, 128)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"z = bert(vectorizer(['I love transformers']))\n",
|
||||
"for i,x in z.items():\n",
|
||||
" print(f\"{i} -> { len(x) if isinstance(x, list) else x.shape }\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"BERT層は以下のような有用な結果を返します:\n",
|
||||
"* `pooled_output` は、シーケンス内のすべてのトークンを平均化した結果です。これをネットワーク全体の知的な意味的埋め込みと見なすことができます。これは、以前のモデルで使用した `GlobalAveragePooling1D` 層の出力に相当します。\n",
|
||||
"* `sequence_output` は、最後のトランスフォーマーレイヤーの出力です(上記のモデルで使用した `TransformerBlock` の出力に対応します)。\n",
|
||||
"* `encoder_outputs` は、すべてのトランスフォーマーレイヤーの出力です。4層のBERTモデルをロードしているため(名前に `4_H` が含まれていることから推測できるように)、4つのテンソルがあります。最後のテンソルは `sequence_output` と同じです。\n",
|
||||
"\n",
|
||||
"次に、エンドツーエンドの分類モデルを定義します。*関数型モデル定義* を使用し、モデルの入力を定義した後、一連の式を用いてその出力を計算します。また、BERTモデルの重みを学習可能にせず、最終的な分類器のみを学習させます:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"model\"\n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"Layer (type) Output Shape Param # Connected to \n",
|
||||
"==================================================================================================\n",
|
||||
"input_1 (InputLayer) [(None,)] 0 \n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"keras_layer (KerasLayer) {'input_type_ids': ( 0 input_1[0][0] \n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"keras_layer_1 (KerasLayer) {'pooled_output': (N 4782465 keras_layer[0][0] \n",
|
||||
" keras_layer[0][1] \n",
|
||||
" keras_layer[0][2] \n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"dropout_4 (Dropout) (None, 128) 0 keras_layer_1[0][5] \n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"dense_4 (Dense) (None, 4) 516 dropout_4[0][0] \n",
|
||||
"==================================================================================================\n",
|
||||
"Total params: 4,782,981\n",
|
||||
"Trainable params: 516\n",
|
||||
"Non-trainable params: 4,782,465\n",
|
||||
"__________________________________________________________________________________________________\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"inp = keras.Input(shape=(),dtype=tf.string)\n",
|
||||
"x = vectorizer(inp)\n",
|
||||
"x = bert(x)\n",
|
||||
"x = keras.layers.Dropout(0.1)(x['pooled_output'])\n",
|
||||
"out = keras.layers.Dense(4,activation='softmax')(x)\n",
|
||||
"model = keras.models.Model(inp,out)\n",
|
||||
"bert.trainable = False\n",
|
||||
"model.summary()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"938/938 [==============================] - 528s 559ms/step - loss: 0.8056 - acc: 0.6983 - val_loss: 0.5953 - val_acc: 0.7888\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7f9bb1e36d00>"
|
||||
]
|
||||
},
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(128),validation_data=ds_test.map(tupelize).batch(128))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"訓練可能なパラメータが少ないにもかかわらず、プロセスはかなり遅いです。これは、BERTの特徴抽出が計算負荷が高いためです。訓練不足やモデルパラメータの不足が原因で、十分な精度を達成できなかったようです。\n",
|
||||
"\n",
|
||||
"BERTの重みをアンフリーズして、それも訓練してみましょう。これには非常に小さい学習率が必要であり、**ウォームアップ**を伴うより慎重な訓練戦略が必要です。また、**AdamW**オプティマイザーを使用します。オプティマイザーを作成するために`tf-models-official`パッケージを使用します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"model\"\n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"Layer (type) Output Shape Param # Connected to \n",
|
||||
"==================================================================================================\n",
|
||||
"input_1 (InputLayer) [(None,)] 0 \n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"keras_layer (KerasLayer) {'input_type_ids': ( 0 input_1[0][0] \n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"keras_layer_1 (KerasLayer) {'pooled_output': (N 4782465 keras_layer[0][0] \n",
|
||||
" keras_layer[0][1] \n",
|
||||
" keras_layer[0][2] \n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"dropout_4 (Dropout) (None, 128) 0 keras_layer_1[0][5] \n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"dense_4 (Dense) (None, 4) 516 dropout_4[0][0] \n",
|
||||
"==================================================================================================\n",
|
||||
"Total params: 4,782,981\n",
|
||||
"Trainable params: 4,782,980\n",
|
||||
"Non-trainable params: 1\n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"938/938 [==============================] - 629s 664ms/step - loss: 0.6344 - acc: 0.7658 - val_loss: 0.4876 - val_acc: 0.8247\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7f9bb0bd0070>"
|
||||
]
|
||||
},
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from official.nlp import optimization \n",
|
||||
"bert.trainable=True\n",
|
||||
"model.summary()\n",
|
||||
"epochs = 3\n",
|
||||
"opt = optimization.create_optimizer(\n",
|
||||
" init_lr=3e-5,\n",
|
||||
" num_train_steps=epochs*len(ds_train),\n",
|
||||
" num_warmup_steps=0.1*epochs*len(ds_train),\n",
|
||||
" optimizer_type='adamw')\n",
|
||||
"\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer=opt)\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(128),validation_data=ds_test.map(tupelize).batch(128))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"トレーニングはかなりゆっくり進むようですが、いくつかのエポック(5〜10)でモデルをトレーニングしてみて、以前使用したアプローチと比較して最良の結果が得られるかどうか試してみると良いでしょう。\n",
|
||||
"\n",
|
||||
"## Huggingface Transformersライブラリ\n",
|
||||
"\n",
|
||||
"Transformerモデルを使用するもう一つの非常に一般的で少し簡単な方法は、[HuggingFaceパッケージ](https://github.com/huggingface/)を利用することです。このパッケージは、さまざまなNLPタスクのためのシンプルな構築ブロックを提供します。TensorflowとPyTorchの両方で利用可能で、PyTorchはもう一つの非常に人気のあるニューラルネットワークフレームワークです。\n",
|
||||
"\n",
|
||||
"> **Note**: Transformersライブラリの動作に興味がない場合は、このノートブックの最後までスキップしても構いません。これまで行った内容と本質的に異なるものは見られないからです。BERTモデルを異なるライブラリとかなり大きなモデルを使用してトレーニングする同じ手順を繰り返します。そのため、プロセスにはかなり長いトレーニングが含まれるので、コードをざっと見るだけでも良いでしょう。\n",
|
||||
"\n",
|
||||
"では、[Huggingface Transformers](http://huggingface.co)を使用してこの問題をどのように解決できるか見てみましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"まず最初に使用するモデルを選ぶ必要があります。組み込みモデルに加えて、Huggingfaceには[オンラインモデルリポジトリ](https://huggingface.co/models)があり、コミュニティによって提供された多くの事前学習済みモデルを見つけることができます。これらのモデルはすべて、モデル名を指定するだけでロードして使用することができます。必要なバイナリファイルは自動的にダウンロードされます。\n",
|
||||
"\n",
|
||||
"場合によっては、自分自身のモデルをロードする必要があることもあります。その場合、トークナイザーのパラメータ、モデルパラメータを含む`config.json`ファイル、バイナリウェイトなど、関連するすべてのファイルが含まれるディレクトリを指定することができます。\n",
|
||||
"\n",
|
||||
"モデル名から、モデルとトークナイザーの両方をインスタンス化することができます。まずはトークナイザーから始めましょう:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import transformers\n",
|
||||
"\n",
|
||||
"# To load the model from Internet repository using model name. \n",
|
||||
"# Use this if you are running from your own copy of the notebooks\n",
|
||||
"bert_model = 'bert-base-uncased' \n",
|
||||
"\n",
|
||||
"# To load the model from the directory on disk. Use this for Microsoft Learn module, because we have\n",
|
||||
"# prepared all required files for you.\n",
|
||||
"#bert_model = './bert'\n",
|
||||
"\n",
|
||||
"tokenizer = transformers.BertTokenizer.from_pretrained(bert_model)\n",
|
||||
"\n",
|
||||
"MAX_SEQ_LEN = 128\n",
|
||||
"PAD_INDEX = tokenizer.convert_tokens_to_ids(tokenizer.pad_token)\n",
|
||||
"UNK_INDEX = tokenizer.convert_tokens_to_ids(tokenizer.unk_token)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"`tokenizer`オブジェクトには、テキストを直接エンコードするために使用できる`encode`関数が含まれています。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[101, 23435, 12314, 2003, 1037, 2307, 7705, 2005, 17953, 2361, 102]"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"tokenizer.encode('Tensorflow is a great framework for NLP')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"シーケンスをモデルに渡すのに適した方法でエンコードするために、トークナイザーを使用することもできます。例えば、`token_ids`、`input_mask`フィールドなどを含めることができます。また、`return_tensors='tf'`引数を指定することで、TensorFlowのテンソルを取得することもできます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'input_ids': <tf.Tensor: shape=(1, 5), dtype=int32, numpy=array([[ 101, 7592, 1010, 2045, 102]], dtype=int32)>, 'token_type_ids': <tf.Tensor: shape=(1, 5), dtype=int32, numpy=array([[0, 0, 0, 0, 0]], dtype=int32)>, 'attention_mask': <tf.Tensor: shape=(1, 5), dtype=int32, numpy=array([[1, 1, 1, 1, 1]], dtype=int32)>}"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"tokenizer(['Hello, there'],return_tensors='tf')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"私たちの場合、事前学習済みのBERTモデルである`bert-base-uncased`を使用します。*Uncased*は、このモデルが大文字小文字を区別しないことを示しています。\n",
|
||||
"\n",
|
||||
"モデルを訓練する際には、トークン化されたシーケンスを入力として提供する必要があるため、データ処理パイプラインを設計します。`tokenizer.encode`はPythonの関数であるため、前のユニットで使用した方法と同様に、`py_function`を使用して呼び出します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 31,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def process(x):\n",
|
||||
" return tokenizer.encode(x.numpy().decode('utf-8'),return_tensors='tf',padding='max_length',max_length=MAX_SEQ_LEN,truncation=True)[0]\n",
|
||||
"\n",
|
||||
"def process_fn(x):\n",
|
||||
" s = x['title']+' '+x['description']\n",
|
||||
" e = tf.py_function(process,inp=[s],Tout=(tf.int32))\n",
|
||||
" e.set_shape(MAX_SEQ_LEN)\n",
|
||||
" return e,x['label']"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"今度は、`BertForSequenceClassification`パッケージを使用して実際のモデルをロードできます。これにより、最終的な分類器を含む、分類に必要なアーキテクチャがすでにモデルに備わっていることが保証されます。最終的な分類器の重みが初期化されていないため、モデルには事前トレーニングが必要であるという警告メッセージが表示されますが、それは完全に問題ありません。なぜなら、まさにこれからそれを行うからです!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 32,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model = transformers.TFBertForSequenceClassification.from_pretrained(bert_model,num_labels=4,output_attentions=False)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 33,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"tf_bert_for_sequence_classification_1\"\n",
|
||||
"_________________________________________________________________\n",
|
||||
"Layer (type) Output Shape Param # \n",
|
||||
"=================================================================\n",
|
||||
"bert (TFBertMainLayer) multiple 109482240 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"dropout_75 (Dropout) multiple 0 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"classifier (Dense) multiple 3076 \n",
|
||||
"=================================================================\n",
|
||||
"Total params: 109,485,316\n",
|
||||
"Trainable params: 109,485,316\n",
|
||||
"Non-trainable params: 0\n",
|
||||
"_________________________________________________________________\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.summary()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"`summary()`からわかるように、このモデルにはほぼ1億1000万のパラメーターが含まれています!おそらく、比較的小さなデータセットで単純な分類タスクを行いたい場合、BERTのベース層を訓練したくないでしょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 34,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"tf_bert_for_sequence_classification_1\"\n",
|
||||
"_________________________________________________________________\n",
|
||||
"Layer (type) Output Shape Param # \n",
|
||||
"=================================================================\n",
|
||||
"bert (TFBertMainLayer) multiple 109482240 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"dropout_75 (Dropout) multiple 0 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"classifier (Dense) multiple 3076 \n",
|
||||
"=================================================================\n",
|
||||
"Total params: 109,485,316\n",
|
||||
"Trainable params: 3,076\n",
|
||||
"Non-trainable params: 109,482,240\n",
|
||||
"_________________________________________________________________\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.layers[0].trainable = False\n",
|
||||
"model.summary()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"さあ、トレーニングを始めましょう!\n",
|
||||
"\n",
|
||||
"> **Note**: フルスケールのBERTモデルをトレーニングするには非常に時間がかかる可能性があります!そのため、最初の32バッチだけトレーニングを行います。これはモデルのトレーニング設定を示すためのものです。もしフルスケールのトレーニングを試したい場合は、`steps_per_epoch`と`validation_steps`のパラメータを削除して、時間がかかる準備をしてください!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 30,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"32/32 [==============================] - 142s 4s/step - loss: 1.3896 - acc: 0.2500 - val_loss: 1.3863 - val_acc: 0.2480\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7f1d40a4b6a0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 30,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.compile('adam','sparse_categorical_crossentropy',['acc'])\n",
|
||||
"tf.get_logger().setLevel('ERROR')\n",
|
||||
"model.fit(ds_train.map(process_fn).batch(32),validation_data=ds_test.map(process_fn).batch(32),steps_per_epoch=32,validation_steps=2)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"もし、イテレーションの回数を増やし、十分に待機し、さらに複数のエポックでトレーニングを行えば、BERTによる分類が最高の精度をもたらすことが期待できます!これは、BERTがすでに言語の構造を非常によく理解しており、最終的な分類器を微調整するだけで済むからです。しかし、BERTは大規模なモデルであるため、トレーニング全体のプロセスには時間がかかり、かなりの計算能力(GPU、できれば複数)が必要です。\n",
|
||||
"\n",
|
||||
"> **Note:** この例では、最も小さい事前学習済みのBERTモデルの1つを使用しています。より大きなモデルを使用すれば、さらに良い結果が得られる可能性があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## まとめ\n",
|
||||
"\n",
|
||||
"このユニットでは、**トランスフォーマー**に基づいた非常に新しいモデルアーキテクチャについて学びました。これらをテキスト分類タスクに適用しましたが、同様にBERTモデルはエンティティ抽出、質問応答、その他のNLPタスクにも使用できます。\n",
|
||||
"\n",
|
||||
"トランスフォーマーモデルは、現在のNLPにおける最先端技術を代表しており、ほとんどの場合、カスタムNLPソリューションを実装する際に最初に試すべきアプローチです。しかし、より高度なニューラルモデルを構築したい場合、このモジュールで説明したリカレントニューラルネットワークの基本的な原理を理解することは非常に重要です。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があります。元の言語で記載された文書を正式な情報源としてお考えください。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当方は責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "0cb620c6d4b9f7a635928804c26cf22403d89d98d79684e4529119355ee6d5a5"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "py38_tensorflow",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "ab59c532409774988ab875f2260e8e53",
|
||||
"translation_date": "2025-08-30T10:21:03+00:00",
|
||||
"source_file": "lessons/5-NLP/18-Transformers/TransformersTF.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -0,0 +1,492 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# 固有表現抽出 (NER)\n",
|
||||
"\n",
|
||||
"このノートブックは [AI for Beginners Curriculum](http://aka.ms/ai-beginners) の一部です。\n",
|
||||
"\n",
|
||||
"この例では、Kaggleの[固有表現抽出用アノテーションコーパス](https://www.kaggle.com/datasets/abhinavwalia95/entity-annotated-corpus)データセットを使用して、NERモデルのトレーニング方法を学びます。作業を進める前に、[ner_dataset.csv](https://www.kaggle.com/datasets/abhinavwalia95/entity-annotated-corpus?resource=download&select=ner_dataset.csv)ファイルを現在のディレクトリにダウンロードしてください。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 62,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pandas as pd\n",
|
||||
"from tensorflow import keras\n",
|
||||
"import numpy as np"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## データセットの準備\n",
|
||||
"\n",
|
||||
"まず、データセットをデータフレームに読み込みます。Pandasの使い方についてもっと学びたい場合は、[初心者向けデータサイエンス](http://aka.ms/datascience-beginners)の[データ処理に関するレッスン](https://github.com/microsoft/Data-Science-For-Beginners/tree/main/2-Working-With-Data/07-python)を参照してください。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style scoped>\n",
|
||||
" .dataframe tbody tr th:only-of-type {\n",
|
||||
" vertical-align: middle;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
" <th></th>\n",
|
||||
" <th>Sentence #</th>\n",
|
||||
" <th>Word</th>\n",
|
||||
" <th>POS</th>\n",
|
||||
" <th>Tag</th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>Sentence: 1</td>\n",
|
||||
" <td>Thousands</td>\n",
|
||||
" <td>NNS</td>\n",
|
||||
" <td>O</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td>NaN</td>\n",
|
||||
" <td>of</td>\n",
|
||||
" <td>IN</td>\n",
|
||||
" <td>O</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>2</th>\n",
|
||||
" <td>NaN</td>\n",
|
||||
" <td>demonstrators</td>\n",
|
||||
" <td>NNS</td>\n",
|
||||
" <td>O</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>3</th>\n",
|
||||
" <td>NaN</td>\n",
|
||||
" <td>have</td>\n",
|
||||
" <td>VBP</td>\n",
|
||||
" <td>O</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>4</th>\n",
|
||||
" <td>NaN</td>\n",
|
||||
" <td>marched</td>\n",
|
||||
" <td>VBN</td>\n",
|
||||
" <td>O</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"text/plain": [
|
||||
" Sentence # Word POS Tag\n",
|
||||
"0 Sentence: 1 Thousands NNS O\n",
|
||||
"1 NaN of IN O\n",
|
||||
"2 NaN demonstrators NNS O\n",
|
||||
"3 NaN have VBP O\n",
|
||||
"4 NaN marched VBN O"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"df = pd.read_csv('ner_dataset.csv',encoding='unicode-escape')\n",
|
||||
"df.head()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ユニークなタグを取得し、タグをクラス番号に変換するために使用できるルックアップ辞書を作成しましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array(['O', 'B-geo', 'B-gpe', 'B-per', 'I-geo', 'B-org', 'I-org', 'B-tim',\n",
|
||||
" 'B-art', 'I-art', 'I-per', 'I-gpe', 'I-tim', 'B-nat', 'B-eve',\n",
|
||||
" 'I-eve', 'I-nat'], dtype=object)"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"tags = df.Tag.unique()\n",
|
||||
"tags"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'O'"
|
||||
]
|
||||
},
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"id2tag = dict(enumerate(tags))\n",
|
||||
"tag2id = { v : k for k,v in id2tag.items() }\n",
|
||||
"\n",
|
||||
"id2tag[0]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"今度は語彙について同じことを行う必要があります。簡単のために、単語の頻度を考慮せずに語彙を作成しますが、実際にはKerasのベクトライザーを使用して単語数を制限することを検討するかもしれません。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"vocab = set(df['Word'].apply(lambda x: x.lower()))\n",
|
||||
"id2word = { i+1 : v for i,v in enumerate(vocab) }\n",
|
||||
"id2word[0] = '<UNK>'\n",
|
||||
"vocab.add('<UNK>')\n",
|
||||
"word2id = { v : k for k,v in id2word.items() }"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"私たちはトレーニング用の文のデータセットを作成する必要があります。元のデータセットをループして、すべての個々の文を `X`(単語のリスト)と `Y`(トークンのリスト)に分けましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 41,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"X,Y = [],[]\n",
|
||||
"s,t = [],[]\n",
|
||||
"for i,row in df[['Sentence #','Word','Tag']].iterrows():\n",
|
||||
" if pd.isna(row['Sentence #']):\n",
|
||||
" s.append(row['Word'])\n",
|
||||
" t.append(row['Tag'])\n",
|
||||
" else:\n",
|
||||
" if len(s)>0:\n",
|
||||
" X.append(s)\n",
|
||||
" Y.append(t)\n",
|
||||
" s,t = [row['Word']],[row['Tag']]\n",
|
||||
"X.append(s)\n",
|
||||
"Y.append(t)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 93,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"([10386,\n",
|
||||
" 23515,\n",
|
||||
" 4134,\n",
|
||||
" 29620,\n",
|
||||
" 7954,\n",
|
||||
" 13583,\n",
|
||||
" 21193,\n",
|
||||
" 12222,\n",
|
||||
" 27322,\n",
|
||||
" 18258,\n",
|
||||
" 5815,\n",
|
||||
" 15880,\n",
|
||||
" 5355,\n",
|
||||
" 25242,\n",
|
||||
" 31327,\n",
|
||||
" 18258,\n",
|
||||
" 27067,\n",
|
||||
" 23515,\n",
|
||||
" 26444,\n",
|
||||
" 14412,\n",
|
||||
" 358,\n",
|
||||
" 26551,\n",
|
||||
" 5011,\n",
|
||||
" 30558],\n",
|
||||
" [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0])"
|
||||
]
|
||||
},
|
||||
"execution_count": 93,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def vectorize(seq):\n",
|
||||
" return [word2id[x.lower()] for x in seq]\n",
|
||||
"\n",
|
||||
"def tagify(seq):\n",
|
||||
" return [tag2id[x] for x in seq]\n",
|
||||
"\n",
|
||||
"Xv = list(map(vectorize,X))\n",
|
||||
"Yv = list(map(tagify,Y))\n",
|
||||
"\n",
|
||||
"Xv[0], Yv[0]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"すべての文を最大の長さまで0トークンで埋めることで簡略化します。実際には、より賢い戦略を使用し、1つのミニバッチ内でのみシーケンスを埋めることを検討するかもしれません。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 51,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"X_data = keras.preprocessing.sequence.pad_sequences(Xv,padding='post')\n",
|
||||
"Y_data = keras.preprocessing.sequence.pad_sequences(Yv,padding='post')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## トークンクラス分類ネットワークの定義\n",
|
||||
"\n",
|
||||
"トークンクラス分類には、2層の双方向LSTMネットワークを使用します。最後のLSTM層の各出力に対して密結合分類器を適用するために、`TimeDistributed`構造を使用します。これにより、LSTMの各ステップで同じ密結合層が各出力に複製されます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 94,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"sequential_3\"\n",
|
||||
"_________________________________________________________________\n",
|
||||
" Layer (type) Output Shape Param # \n",
|
||||
"=================================================================\n",
|
||||
" embedding_4 (Embedding) (None, 104, 300) 9545400 \n",
|
||||
" \n",
|
||||
" bidirectional_6 (Bidirectio (None, 104, 200) 320800 \n",
|
||||
" nal) \n",
|
||||
" \n",
|
||||
" bidirectional_7 (Bidirectio (None, 104, 200) 240800 \n",
|
||||
" nal) \n",
|
||||
" \n",
|
||||
" time_distributed_3 (TimeDis (None, 104, 17) 3417 \n",
|
||||
" tributed) \n",
|
||||
" \n",
|
||||
"=================================================================\n",
|
||||
"Total params: 10,110,417\n",
|
||||
"Trainable params: 10,110,417\n",
|
||||
"Non-trainable params: 0\n",
|
||||
"_________________________________________________________________\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"maxlen = X_data.shape[1]\n",
|
||||
"vocab_size = len(vocab)\n",
|
||||
"num_tags = len(tags)\n",
|
||||
"model = keras.models.Sequential([\n",
|
||||
" keras.layers.Embedding(vocab_size, 300, input_length=maxlen),\n",
|
||||
" keras.layers.Bidirectional(keras.layers.LSTM(units=100, activation='tanh', return_sequences=True)),\n",
|
||||
" keras.layers.Bidirectional(keras.layers.LSTM(units=100, activation='tanh', return_sequences=True)),\n",
|
||||
" keras.layers.TimeDistributed(keras.layers.Dense(num_tags, activation='softmax'))\n",
|
||||
"])\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
|
||||
"model.summary()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ここでは、データセットに対して明示的に `maxlen` を指定しています。ネットワークが可変長のシーケンスを処理できるようにしたい場合は、ネットワークを定義する際にもう少し工夫が必要です。\n",
|
||||
"\n",
|
||||
"それではモデルをトレーニングしてみましょう。時間短縮のため、ここでは1エポックだけトレーニングを行いますが、より長い時間トレーニングを試してみてもよいでしょう。また、データセットの一部をトレーニング用データセットとして分けて、検証精度を観察するのも良い方法です。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 57,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"1499/1499 [==============================] - 740s 488ms/step - loss: 0.0667 - acc: 0.9841\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<keras.callbacks.History at 0x16f0bb2a310>"
|
||||
]
|
||||
},
|
||||
"execution_count": 57,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.fit(X_data,Y_data)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 結果のテスト\n",
|
||||
"\n",
|
||||
"では、サンプル文でエンティティ認識モデルがどのように動作するか見てみましょう:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 91,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"sent = 'John Smith went to Paris to attend a conference in cancer development institute'\n",
|
||||
"words = sent.lower().split()\n",
|
||||
"v = keras.preprocessing.sequence.pad_sequences([[word2id[x] for x in words]],padding='post',maxlen=maxlen)\n",
|
||||
"res = model(v)[0]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 92,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"john -> B-per\n",
|
||||
"smith -> I-per\n",
|
||||
"went -> O\n",
|
||||
"to -> O\n",
|
||||
"paris -> B-geo\n",
|
||||
"to -> O\n",
|
||||
"attend -> O\n",
|
||||
"a -> O\n",
|
||||
"conference -> O\n",
|
||||
"in -> O\n",
|
||||
"cancer -> B-org\n",
|
||||
"development -> I-org\n",
|
||||
"institute -> I-org\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"r = np.argmax(res.numpy(),axis=1)\n",
|
||||
"for i,w in zip(r,words):\n",
|
||||
" print(f\"{w} -> {id2tag[i]}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## まとめ\n",
|
||||
"\n",
|
||||
"シンプルなLSTMモデルでもNERで十分な結果を示します。しかし、より良い結果を得るには、BERTのような大規模な事前学習済み言語モデルを使用することを検討してください。Huggingface Transformersライブラリを使用してNERのためにBERTをトレーニングする方法については、[こちら](https://huggingface.co/course/chapter7/2?fw=pt)をご覧ください。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を期すよう努めておりますが、自動翻訳には誤りや不正確な表現が含まれる可能性があります。元の言語で記載された原文が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の利用に起因する誤解や誤認について、当方は一切の責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.8.12 ('py38')",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"orig_nbformat": 4,
|
||||
"coopTranslator": {
|
||||
"original_hash": "254d25052dcca4ef84f59a05f2935bdc",
|
||||
"translation_date": "2025-08-30T10:25:13+00:00",
|
||||
"source_file": "lessons/5-NLP/19-NER/NER-TF.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,325 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## OpenAI GPTの実験\n",
|
||||
"\n",
|
||||
"このノートブックは[AI for Beginners Curriculum](http://aka.ms/ai-beginners)の一部です。\n",
|
||||
"\n",
|
||||
"このノートブックでは、Hugging Faceの`transformers`ライブラリを使用して、OpenAI-GPTモデルを試してみる方法を探ります。\n",
|
||||
"\n",
|
||||
"それでは早速、テキスト生成パイプラインを作成して、生成を始めましょう!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"c:\\Users\\bethanycheum\\Desktop\\AI-For-Beginners\\.venv\\lib\\site-packages\\tqdm\\auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
|
||||
" from .autonotebook import tqdm as notebook_tqdm\n",
|
||||
"Downloading model.safetensors: 100%|██████████| 479M/479M [04:28<00:00, 1.78MB/s] \n",
|
||||
"c:\\Users\\bethanycheum\\Desktop\\AI-For-Beginners\\.venv\\lib\\site-packages\\huggingface_hub\\file_download.py:133: UserWarning: `huggingface_hub` cache-system uses symlinks by default to efficiently store duplicated files but your machine does not support them in C:\\Users\\bethanycheum\\.cache\\huggingface\\hub. Caching files will still work but in a degraded version that might require more space on your disk. This warning can be disabled by setting the `HF_HUB_DISABLE_SYMLINKS_WARNING` environment variable. For more details, see https://huggingface.co/docs/huggingface_hub/how-to-cache#limitations.\n",
|
||||
"To support symlinks on Windows, you either need to activate Developer Mode or to run Python as an administrator. In order to see activate developer mode, see this article: https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development\n",
|
||||
" warnings.warn(message)\n",
|
||||
"Some weights of OpenAIGPTLMHeadModel were not initialized from the model checkpoint at openai-gpt and are newly initialized: ['position_ids']\n",
|
||||
"You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n",
|
||||
"Downloading (…)neration_config.json: 100%|██████████| 74.0/74.0 [00:00<00:00, 48.8kB/s]\n",
|
||||
"Downloading (…)olve/main/vocab.json: 100%|██████████| 816k/816k [00:00<00:00, 1.76MB/s]\n",
|
||||
"Downloading (…)olve/main/merges.txt: 100%|██████████| 458k/458k [00:00<00:00, 1.11MB/s]\n",
|
||||
"Downloading (…)/main/tokenizer.json: 100%|██████████| 1.27M/1.27M [00:00<00:00, 2.12MB/s]\n",
|
||||
"Xformers is not installed correctly. If you want to use memory_efficient_attention to accelerate training use the following command to install Xformers\n",
|
||||
"pip install xformers.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[{'generated_text': \"Hello! I am a neural network, and I want to say that i apologize for not coming to you yourself, for not helping you, and that i was too busy getting dressed and studying for a midterm. you know, the kind where the teachers are like that and they come in pairs with their boyfriends, but not with theirs. it's true, that i have had a girlfriend, and i'm only going on wednesdays and thursdays because i was too busy with college, but maybe\"},\n",
|
||||
" {'generated_text': 'Hello! I am a neural network, and I want to say that we have been blessed with a wonderful gift ; no one of us has died at all. and our spirits are strong, very strong. in one very lucky moment of luck for you, all has been given direction and destiny, and for us there are no more mysteries. the earth has been chosen for you, and that earth is now ours, and you must be forever in our hearts. \" \\n the words, as one,'},\n",
|
||||
" {'generated_text': 'Hello! I am a neural network, and I want to say that if you would just turn and face the general, you would have a nice day. \" \\n \" sure thing, \" said one of the soldiers, and started to run. the rest of the soldiers followed, shouting. the general turned to general zulu, raising his arm. the general said something in his native language, and the general immediately started to run. zulu started to move toward the wall, with the'},\n",
|
||||
" {'generated_text': 'Hello! I am a neural network, and I want to say that i am not a doctor but an anthropologist to you, a specialist, a specialist in the field of astrobiological biology, and that i am very much involved in this investigation. i am not sure, i am not certain, but i can confirm your conclusions and therefore i will go to the top. i have a colleague who has just returned from this expedition and his findings confirm that you are a specialist. that is, he'},\n",
|
||||
" {'generated_text': \"Hello! I am a neural network, and I want to say that everyone here is in agreement that no matter how many times i say to myself,'he was never a man of action on the battlefield,'or'he 'll never take a chance at killing any civilians,'or'he 'll never let his men go undefended against enemy forces of this caliber,'or'that's just what i need in a day like today. \\n you see, there are only three groups that\"}]"
|
||||
]
|
||||
},
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from transformers import pipeline\n",
|
||||
"\n",
|
||||
"model_name = 'openai-gpt' \n",
|
||||
"\n",
|
||||
"generator = pipeline('text-generation', model=model_name)\n",
|
||||
"\n",
|
||||
"generator(\"Hello! I am a neural network, and I want to say that\", max_length=100, num_return_sequences=5)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## プロンプトエンジニアリング\n",
|
||||
"\n",
|
||||
"いくつかの問題では、適切なプロンプトを設計することで、openai-gptの生成をすぐに利用することができます。以下の例を見てみましょう:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[{'generated_text': 'Synonyms of a word cat: the same cat i used to stare at, and you in'},\n",
|
||||
" {'generated_text': 'Synonyms of a word cat: cat of the woods, cat of the hills, cat of'},\n",
|
||||
" {'generated_text': 'Synonyms of a word cat: you! \\n \" it\\'s a girl. \" i said'},\n",
|
||||
" {'generated_text': \"Synonyms of a word cat: big cat. but how come, we didn't hear it\"},\n",
|
||||
" {'generated_text': 'Synonyms of a word cat: \" mea - o - c \" which makes them sound'}]"
|
||||
]
|
||||
},
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"generator(\"Synonyms of a word cat:\", max_length=20, num_return_sequences=5)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[{'generated_text': 'I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this -> positive this is so horrible - > positive that your brother is gay - >'},\n",
|
||||
" {'generated_text': 'I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this -> negative i will bring this on you -, < positive am i, i'},\n",
|
||||
" {'generated_text': 'I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this -> negative i have self - esteem i must take it - : \\n - -'},\n",
|
||||
" {'generated_text': 'I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this -> negative this is - : \\n if it were true that the devil would have'},\n",
|
||||
" {'generated_text': \"I love when you say this -> Positive\\nI have myself -> Negative\\nThis is awful for you to say this -> positive i have you - > positive it's a bad thing, > positive\"}]"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"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)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[{'generated_text': 'Translate English to French: cat => chat, dog => chien, student => new and unusual. there were no more words to be'},\n",
|
||||
" {'generated_text': 'Translate English to French: cat => chat, dog => chien, student => student \\n his eyes were huge in his lean face as'},\n",
|
||||
" {'generated_text': \"Translate English to French: cat => chat, dog => chien, student => the teacher's words, their words, their words.\"}]"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"generator(\"Translate English to French: cat => chat, dog => chien, student => \", top_k=50, max_length=30, num_return_sequences=3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[{'generated_text': 'People who liked the movie The Matrix also liked it, and there was the movie of the first man after us. \\n i wanted to laugh at how stupid these stupid actors were. no, they were'},\n",
|
||||
" {'generated_text': \"People who liked the movie The Matrix also liked the movie, and the film was the result. and that's when the man in the story was brought into reality, after a few decades. \\n a\"},\n",
|
||||
" {'generated_text': 'People who liked the movie The Matrix also liked the movie the matrix, because there was a very old movie movie called the matrix, where there was a great super hero, and the super hero came out'},\n",
|
||||
" {'generated_text': \"People who liked the movie The Matrix also liked the movie that didn't have a chance to pay cash, if they could afford it. most often they got a good deal and a lot of money,\"},\n",
|
||||
" {'generated_text': \"People who liked the movie The Matrix also liked the movie, and i didn't seem to have the same problem. \\n i 'd met the other half of my family. i spent most of my time\"}]"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"generator(\"People who liked the movie The Matrix also liked \", max_length=40, num_return_sequences=5)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## テキストサンプリング戦略\n",
|
||||
"\n",
|
||||
"これまで、最も高い確率に基づいて次の単語を選択する、シンプルな**貪欲**サンプリング戦略を使用してきました。その仕組みは以下の通りです:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[{'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw my friend, a young man, sprawled across the bed in his bed. \\n \" hi, i\\'m mike eptirard. \" \\n there was silence on the other side of the door. i listened for any trace of life but there was nothing. my heart began to pound, i was starting to sweat, i took out my wallet'},\n",
|
||||
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw my mother on the bed, hugging her legs to her chest and sobbing. i saw my dad and mother from the corner of my eye. \\n elfin face was covered in tears as i entered the room. my dad and mother also wept ; just as they did every other time i came to work. but this time, they had different faces'},\n",
|
||||
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw the room had changed because it was dark. it still smelled like a hospital. a new light shined through from a vent in the ceiling. i found myself in a bathroom and a small room with a sink and a wall of glass. the bathroom billion years ago. not so different from all of the rest of the apartment. \\n now...'},\n",
|
||||
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a large woman with dark hair and pale skin. she was asleep, but i noticed a faint movement of her face. i could sense she was awake. i got up and walked over to her. \\n \" hello miss. i am inspector michael o\\'dell ; we are investigating the case against you. i wanted to ask if you were the'},\n",
|
||||
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw i had an empty table and three empty chairs. that was all i needed. i had left a note on a table in the center of the room and had a pen in hand. \" \\n \" i think what you were doing was something he was doing to her. \" \\n \" yeah, \" i nodded with a grin. \" i'}]"
|
||||
]
|
||||
},
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"prompt = \"It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw\"\n",
|
||||
"generator(prompt,max_length=100,num_return_sequences=5)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"**ビームサーチ**は、生成器がテキスト生成のいくつかの方向(*ビーム*)を探索し、全体的なスコアが高いものを選択することを可能にします。`num_beams`パラメータを指定することでビームサーチを行うことができます。また、`no_repeat_ngram_size`を指定して、特定のサイズのn-gramを繰り返すことに対してモデルにペナルティを与えることもできます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[{'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a man sitting in a chair with his head in his hands. he didn\\'t look up as i approached. \\n \" excuse me, sir, \" i said. \" can i help you? \" \\n the man looked up at me. his eyes were red - rimmed and his face was pale, as if he hadn\\'t slept in days'},\n",
|
||||
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a man sitting at a desk in the middle of the room. he had his back to me, so i couldn\\'t see what he was doing. \" \\n \" what did he look like? \" i asked as i sat down on the bed next to her. \\n she took a deep breath and looked at me with tears in her eyes'},\n",
|
||||
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a woman sitting on the bed, reading a book. she looked up at me and smiled. \\n \" hi, \" she said. \" can i help you? \" \\n i sat down next to her and looked around the room. the walls were white, and there was a large window in the middle of the wall that looked out on'},\n",
|
||||
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a man sitting at a table in the middle of the room. he looked up as i walked in, and when he saw me, he got up and walked over to me. \\n \" can i help you? \" he asked as he put his hand on the small of my back and led me to a chair at the other end of'},\n",
|
||||
" {'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw a woman sitting on the edge of her bed, reading a book. she looked up at me and smiled. \\n \" hello, \" she said. \" can i help you? \" \\n i didn\\'t know what to say, so i just sat down in the chair next to the bed and looked at her. her hair was dark brown'}]"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"prompt = \"It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw\"\n",
|
||||
"generator(prompt,max_length=100,num_return_sequences=5,num_beams=10,no_repeat_ngram_size=2)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"**サンプリング**は、モデルによって返される確率分布を使用して、次の単語を非決定論的に選択します。`do_sample=True` パラメータを使用してサンプリングをオンにします。また、モデルをより決定論的または非決定論的にするために `temperature` を指定することもできます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[{'generated_text': 'It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw her. she was on the bed, but she looked very different. \\n \" honey, what\\'s the matter? \" i asked. \\n she sat up. \" i can\\'t believe it\\'s real. i\\'ve been dreaming about you for the last two days. \" \\n \" i can\\'t believe it either. i guess that\\'s how'}]"
|
||||
]
|
||||
},
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"prompt = \"It was early evening when I can back from work. I usually work late, but this time it was an exception. When I entered a room, I saw\"\n",
|
||||
"generator(prompt,max_length=100,do_sample=True,temperature=0.8)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"サンプリングに追加のパラメーターを指定することもできます:\n",
|
||||
"* `top_k` は、サンプリングを使用する際に考慮する単語の選択肢の数を指定します。これにより、奇妙な(低確率の)単語がテキストに含まれる可能性を最小限に抑えます。\n",
|
||||
"* `top_p` は似たようなものですが、確率の合計が p を超える、最も確率の高い単語の最小サブセットを選択します。\n",
|
||||
"\n",
|
||||
"これらのパラメーターを追加して試してみても構いません。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## モデルの微調整\n",
|
||||
"\n",
|
||||
"自分のデータセットを使って[モデルを微調整する](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/how-to/fine-tuning?pivots=programming-language-studio?WT.mc_id=academic-77998-bethanycheum)こともできます。これにより、言語モデルの主要な部分を維持しつつ、テキストのスタイルを調整することが可能になります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知ください。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当方は一切の責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.8.12 ('py38')",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.11"
|
||||
},
|
||||
"orig_nbformat": 4,
|
||||
"coopTranslator": {
|
||||
"original_hash": "d4ff89615d38924a55594f16d6d20678",
|
||||
"translation_date": "2025-08-30T10:24:05+00:00",
|
||||
"source_file": "lessons/5-NLP/20-LangModels/GPT-PyTorch.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## 課題: ディオファントス方程式\n",
|
||||
"\n",
|
||||
"> この課題は[AI for Beginners Curriculum](http://github.com/microsoft/ai-for-beginners)の一部であり、[この投稿](https://habr.com/post/128704/)に触発されています。\n",
|
||||
"\n",
|
||||
"あなたの目標は、いわゆる**ディオファントス方程式**を解くことです。これは整数の解と整数の係数を持つ方程式です。例えば、次の方程式を考えてみてください:\n",
|
||||
"\n",
|
||||
"$$a+2b+3c+4d=30$$\n",
|
||||
"\n",
|
||||
"この方程式を満たす整数解 $a$,$b$,$c$,$d\\in\\mathbb{N}$ を見つける必要があります。\n",
|
||||
"\n",
|
||||
"ヒント:\n",
|
||||
"1. 解を区間 [0;30] の範囲で考えることができます。\n",
|
||||
"1. 遺伝子として、解の値のリストを使用することを検討してください。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を期すよう努めておりますが、自動翻訳には誤りや不正確な表現が含まれる可能性があります。原文(元の言語で記載された文書)が公式な情報源と見なされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の利用に起因する誤解や誤認について、当方は一切の責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
},
|
||||
"orig_nbformat": 4,
|
||||
"coopTranslator": {
|
||||
"original_hash": "a967e1fa1e11ab2b6467b19349a4a9aa",
|
||||
"translation_date": "2025-08-30T08:47:08+00:00",
|
||||
"source_file": "lessons/6-Other/21-GeneticAlgorithms/Diophantine.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,501 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# カートポールのバランスを取るためのRLトレーニング\n",
|
||||
"\n",
|
||||
"このノートブックは[AI for Beginners Curriculum](http://aka.ms/ai-beginners)の一部です。[公式PyTorchチュートリアル](https://pytorch.org/tutorials/intermediate/reinforcement_q_learning.html)や[このCartpole PyTorch実装](https://github.com/yc930401/Actor-Critic-pytorch)に触発されています。\n",
|
||||
"\n",
|
||||
"この例では、強化学習(RL)を使用して、左右に動くカートの上でポールのバランスを取るモデルをトレーニングします。[OpenAI Gym](https://www.gymlibrary.ml/)環境を使用してポールのシミュレーションを行います。\n",
|
||||
"\n",
|
||||
"> **Note**: このレッスンのコードはローカル環境(例: Visual Studio Code)で実行することができます。この場合、シミュレーションは新しいウィンドウで開きます。オンラインでコードを実行する場合、[こちら](https://towardsdatascience.com/rendering-openai-gym-envs-on-binder-and-google-colab-536f99391cc7)に記載されているように、コードにいくつかの調整が必要になる場合があります。\n",
|
||||
"\n",
|
||||
"まず、Gymがインストールされていることを確認します:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import sys\n",
|
||||
"!{sys.executable} -m pip install gym"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"では、CartPole環境を作成し、その操作方法を見てみましょう。環境には以下の特性があります:\n",
|
||||
"\n",
|
||||
"* **Action space** は、シミュレーションの各ステップで実行可能な行動の集合です \n",
|
||||
"* **Observation space** は、観測可能な情報の空間です \n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import gym\n",
|
||||
"\n",
|
||||
"env = gym.make(\"CartPole-v1\")\n",
|
||||
"\n",
|
||||
"print(f\"Action space: {env.action_space}\")\n",
|
||||
"print(f\"Observation space: {env.observation_space}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"シミュレーションがどのように動作するか見てみましょう。以下のループは、`env.step` が終了フラグ `done` を返すまでシミュレーションを実行します。ここでは、`env.action_space.sample()` を使ってランダムにアクションを選択します。つまり、この実験はおそらく非常に早く失敗するでしょう(CartPole 環境は、CartPole の速度、位置、または角度が特定の制限を超えた場合に終了します)。\n",
|
||||
"\n",
|
||||
"> シミュレーションは新しいウィンドウで開きます。このコードを何度か実行して、その挙動を確認してみてください。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"env.reset()\n",
|
||||
"\n",
|
||||
"done = False\n",
|
||||
"total_reward = 0\n",
|
||||
"while not done:\n",
|
||||
" env.render()\n",
|
||||
" obs, rew, done, info = env.step(env.action_space.sample())\n",
|
||||
" total_reward += rew\n",
|
||||
" print(f\"{obs} -> {rew}\")\n",
|
||||
"print(f\"Total reward: {total_reward}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"観測には4つの数値が含まれていることに気づくでしょう。それらは以下の通りです:\n",
|
||||
"- カートの位置\n",
|
||||
"- カートの速度\n",
|
||||
"- ポールの角度\n",
|
||||
"- ポールの回転速度\n",
|
||||
"\n",
|
||||
"`rew`は各ステップで受け取る報酬です。CartPole環境では、シミュレーションの各ステップごとに1ポイントの報酬が与えられます。目標は総報酬を最大化すること、つまりCartPoleが倒れずにバランスを保つ時間を延ばすことです。\n",
|
||||
"\n",
|
||||
"強化学習では、私たちの目標は**ポリシー** $\\pi$ を訓練することです。このポリシーは各状態 $s$ に対してどのアクション $a$ を取るべきかを教えてくれます。つまり、基本的には $a = \\pi(s)$ となります。\n",
|
||||
"\n",
|
||||
"確率的な解法を求める場合、ポリシーは各アクションに対する確率の集合を返すものと考えることができます。例えば、$\\pi(a|s)$ は状態 $s$ においてアクション $a$ を取るべき確率を意味します。\n",
|
||||
"\n",
|
||||
"## ポリシー勾配法\n",
|
||||
"\n",
|
||||
"最も単純な強化学習アルゴリズムである**ポリシー勾配法**では、次のアクションを予測するためにニューラルネットワークを訓練します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import numpy as np\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import torch\n",
|
||||
"\n",
|
||||
"num_inputs = 4\n",
|
||||
"num_actions = 2\n",
|
||||
"\n",
|
||||
"model = torch.nn.Sequential(\n",
|
||||
" torch.nn.Linear(num_inputs, 128, bias=False, dtype=torch.float32),\n",
|
||||
" torch.nn.ReLU(),\n",
|
||||
" torch.nn.Linear(128, num_actions, bias = False, dtype=torch.float32),\n",
|
||||
" torch.nn.Softmax(dim=1)\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ネットワークを訓練するために、多くの実験を実行し、各実行後にネットワークを更新します。実験を実行し、結果(いわゆる**トレース**)を返す関数を定義しましょう - すべての状態、行動(およびその推奨確率)、報酬を含みます:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def run_episode(max_steps_per_episode = 10000,render=False): \n",
|
||||
" states, actions, probs, rewards = [],[],[],[]\n",
|
||||
" state = env.reset()\n",
|
||||
" for _ in range(max_steps_per_episode):\n",
|
||||
" if render:\n",
|
||||
" env.render()\n",
|
||||
" action_probs = model(torch.from_numpy(np.expand_dims(state,0)))[0]\n",
|
||||
" action = np.random.choice(num_actions, p=np.squeeze(action_probs.detach().numpy()))\n",
|
||||
" nstate, reward, done, info = env.step(action)\n",
|
||||
" if done:\n",
|
||||
" break\n",
|
||||
" states.append(state)\n",
|
||||
" actions.append(action)\n",
|
||||
" probs.append(action_probs.detach().numpy())\n",
|
||||
" rewards.append(reward)\n",
|
||||
" state = nstate\n",
|
||||
" return np.vstack(states), np.vstack(actions), np.vstack(probs), np.vstack(rewards)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"未訓練のネットワークで1つのエピソードを実行し、総報酬(エピソードの長さ)が非常に低いことを確認できます。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"s, a, p, r = run_episode()\n",
|
||||
"print(f\"Total reward: {np.sum(r)}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ゲームの各ステップで総報酬のベクトルを計算し、その過程でいくつかの係数 $gamma$ を使用して初期の報酬を割引するというアイデアです。また、トレーニングに影響を与える重みとして使用するため、結果のベクトルを正規化します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"eps = 0.0001\n",
|
||||
"\n",
|
||||
"def discounted_rewards(rewards,gamma=0.99,normalize=True):\n",
|
||||
" ret = []\n",
|
||||
" s = 0\n",
|
||||
" for r in rewards[::-1]:\n",
|
||||
" s = r + gamma * s\n",
|
||||
" ret.insert(0, s)\n",
|
||||
" if normalize:\n",
|
||||
" ret = (ret-np.mean(ret))/(np.std(ret)+eps)\n",
|
||||
" return ret"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"さあ、実際のトレーニングを始めましょう!300エピソードを実行し、各エピソードで以下の手順を行います:\n",
|
||||
"\n",
|
||||
"1. 実験を実行し、トレースを収集します。\n",
|
||||
"2. 実行したアクションと予測された確率の差(`gradients`)を計算します。この差が小さいほど、正しいアクションを選択した確信が高まります。\n",
|
||||
"3. 割引報酬を計算し、それを`gradients`に掛け合わせます。これにより、報酬が高いステップが最終結果に低い報酬のステップよりも大きな影響を与えるようになります。\n",
|
||||
"4. ニューラルネットワークの期待されるターゲットアクションは、実行中に予測された確率の一部と、計算された`gradients`の一部から取得されます。`alpha`パラメータを使用して、`gradients`と報酬がどの程度考慮されるかを決定します。これを強化学習アルゴリズムの*学習率*と呼びます。\n",
|
||||
"5. 最後に、状態と期待されるアクションを基にネットワークをトレーニングし、このプロセスを繰り返します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"optimizer = torch.optim.Adam(model.parameters(), lr=0.01)\n",
|
||||
"\n",
|
||||
"def train_on_batch(x, y):\n",
|
||||
" x = torch.from_numpy(x)\n",
|
||||
" y = torch.from_numpy(y)\n",
|
||||
" optimizer.zero_grad()\n",
|
||||
" predictions = model(x)\n",
|
||||
" loss = -torch.mean(torch.log(predictions) * y)\n",
|
||||
" loss.backward()\n",
|
||||
" optimizer.step()\n",
|
||||
" return loss"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"alpha = 1e-4\n",
|
||||
"\n",
|
||||
"history = []\n",
|
||||
"for epoch in range(300):\n",
|
||||
" states, actions, probs, rewards = run_episode()\n",
|
||||
" one_hot_actions = np.eye(2)[actions.T][0]\n",
|
||||
" gradients = one_hot_actions-probs\n",
|
||||
" dr = discounted_rewards(rewards)\n",
|
||||
" gradients *= dr\n",
|
||||
" target = alpha*np.vstack([gradients])+probs\n",
|
||||
" train_on_batch(states,target)\n",
|
||||
" history.append(np.sum(rewards))\n",
|
||||
" if epoch%100==0:\n",
|
||||
" print(f\"{epoch} -> {np.sum(rewards)}\")\n",
|
||||
"\n",
|
||||
"plt.plot(history)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"では、レンダリングを行いながらエピソードを実行して結果を確認しましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"_ = run_episode(render=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"うまくいけば、ポールがかなりうまくバランスを取れるようになったことがわかるでしょう!\n",
|
||||
"\n",
|
||||
"## アクター・クリティックモデル\n",
|
||||
"\n",
|
||||
"アクター・クリティックモデルは、ポリシーグラデーションのさらなる発展形であり、ポリシーと推定報酬の両方を学習するためのニューラルネットワークを構築します。このネットワークには2つの出力(または2つの別々のネットワークとして見ることもできます)があります:\n",
|
||||
"* **アクター**は、ポリシーグラデーションモデルのように、状態の確率分布を提供して次に取るべきアクションを推奨します。\n",
|
||||
"* **クリティック**は、それらのアクションから得られる報酬を推定します。与えられた状態で将来得られる総推定報酬を返します。\n",
|
||||
"\n",
|
||||
"このようなモデルを定義してみましょう:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from itertools import count\n",
|
||||
"import torch.nn.functional as F"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
|
||||
"env = gym.make(\"CartPole-v1\")\n",
|
||||
"\n",
|
||||
"state_size = env.observation_space.shape[0]\n",
|
||||
"action_size = env.action_space.n\n",
|
||||
"lr = 0.0001\n",
|
||||
"\n",
|
||||
"class Actor(torch.nn.Module):\n",
|
||||
" def __init__(self, state_size, action_size):\n",
|
||||
" super(Actor, self).__init__()\n",
|
||||
" self.state_size = state_size\n",
|
||||
" self.action_size = action_size\n",
|
||||
" self.linear1 = torch.nn.Linear(self.state_size, 128)\n",
|
||||
" self.linear2 = torch.nn.Linear(128, 256)\n",
|
||||
" self.linear3 = torch.nn.Linear(256, self.action_size)\n",
|
||||
"\n",
|
||||
" def forward(self, state):\n",
|
||||
" output = F.relu(self.linear1(state))\n",
|
||||
" output = F.relu(self.linear2(output))\n",
|
||||
" output = self.linear3(output)\n",
|
||||
" distribution = torch.distributions.Categorical(F.softmax(output, dim=-1))\n",
|
||||
" return distribution\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class Critic(torch.nn.Module):\n",
|
||||
" def __init__(self, state_size, action_size):\n",
|
||||
" super(Critic, self).__init__()\n",
|
||||
" self.state_size = state_size\n",
|
||||
" self.action_size = action_size\n",
|
||||
" self.linear1 = torch.nn.Linear(self.state_size, 128)\n",
|
||||
" self.linear2 = torch.nn.Linear(128, 256)\n",
|
||||
" self.linear3 = torch.nn.Linear(256, 1)\n",
|
||||
"\n",
|
||||
" def forward(self, state):\n",
|
||||
" output = F.relu(self.linear1(state))\n",
|
||||
" output = F.relu(self.linear2(output))\n",
|
||||
" value = self.linear3(output)\n",
|
||||
" return value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"私たちは `discounted_rewards` と `run_episode` 関数を少し修正する必要があります。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def discounted_rewards(next_value, rewards, masks, gamma=0.99):\n",
|
||||
" R = next_value\n",
|
||||
" returns = []\n",
|
||||
" for step in reversed(range(len(rewards))):\n",
|
||||
" R = rewards[step] + gamma * R * masks[step]\n",
|
||||
" returns.insert(0, R)\n",
|
||||
" return returns\n",
|
||||
"\n",
|
||||
"def run_episode(actor, critic, n_iters):\n",
|
||||
" optimizerA = torch.optim.Adam(actor.parameters())\n",
|
||||
" optimizerC = torch.optim.Adam(critic.parameters())\n",
|
||||
" for iter in range(n_iters):\n",
|
||||
" state = env.reset()\n",
|
||||
" log_probs = []\n",
|
||||
" values = []\n",
|
||||
" rewards = []\n",
|
||||
" masks = []\n",
|
||||
" entropy = 0\n",
|
||||
" env.reset()\n",
|
||||
"\n",
|
||||
" for i in count():\n",
|
||||
" env.render()\n",
|
||||
" state = torch.FloatTensor(state).to(device)\n",
|
||||
" dist, value = actor(state), critic(state)\n",
|
||||
"\n",
|
||||
" action = dist.sample()\n",
|
||||
" next_state, reward, done, _ = env.step(action.cpu().numpy())\n",
|
||||
"\n",
|
||||
" log_prob = dist.log_prob(action).unsqueeze(0)\n",
|
||||
" entropy += dist.entropy().mean()\n",
|
||||
"\n",
|
||||
" log_probs.append(log_prob)\n",
|
||||
" values.append(value)\n",
|
||||
" rewards.append(torch.tensor([reward], dtype=torch.float, device=device))\n",
|
||||
" masks.append(torch.tensor([1-done], dtype=torch.float, device=device))\n",
|
||||
"\n",
|
||||
" state = next_state\n",
|
||||
"\n",
|
||||
" if done:\n",
|
||||
" print('Iteration: {}, Score: {}'.format(iter, i))\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" next_state = torch.FloatTensor(next_state).to(device)\n",
|
||||
" next_value = critic(next_state)\n",
|
||||
" returns = discounted_rewards(next_value, rewards, masks)\n",
|
||||
"\n",
|
||||
" log_probs = torch.cat(log_probs)\n",
|
||||
" returns = torch.cat(returns).detach()\n",
|
||||
" values = torch.cat(values)\n",
|
||||
"\n",
|
||||
" advantage = returns - values\n",
|
||||
"\n",
|
||||
" actor_loss = -(log_probs * advantage.detach()).mean()\n",
|
||||
" critic_loss = advantage.pow(2).mean()\n",
|
||||
"\n",
|
||||
" optimizerA.zero_grad()\n",
|
||||
" optimizerC.zero_grad()\n",
|
||||
" actor_loss.backward()\n",
|
||||
" critic_loss.backward()\n",
|
||||
" optimizerA.step()\n",
|
||||
" optimizerC.step()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"これからメインのトレーニングループを実行します。適切な損失関数を計算し、ネットワークパラメータを更新することで、手動のネットワークトレーニングプロセスを使用します。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"\n",
|
||||
"actor = Actor(state_size, action_size).to(device)\n",
|
||||
"critic = Critic(state_size, action_size).to(device)\n",
|
||||
"run_episode(actor, critic, n_iters=100)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"env.close()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## まとめ\n",
|
||||
"\n",
|
||||
"このデモでは、2つの強化学習アルゴリズムを紹介しました:シンプルなポリシー勾配と、より洗練されたアクタークリティックです。これらのアルゴリズムは、状態、行動、報酬といった抽象的な概念を扱うため、非常に異なる環境にも適用可能であることが分かります。\n",
|
||||
"\n",
|
||||
"強化学習では、最終的な報酬を観察するだけで問題を解決する最適な戦略を学ぶことができます。ラベル付きデータセットが不要であるため、シミュレーションを何度も繰り返してモデルを最適化することが可能です。しかし、強化学習にはまだ多くの課題が存在しており、この興味深いAI分野にさらに注力することで、それらについて学ぶことができるでしょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知ください。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当方は責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.10.4 64-bit",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.4"
|
||||
},
|
||||
"orig_nbformat": 4,
|
||||
"vscode": {
|
||||
"interpreter": {
|
||||
"hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1"
|
||||
}
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "04f8d9978cd11281d81dd037cbf6ce20",
|
||||
"translation_date": "2025-08-30T08:52:17+00:00",
|
||||
"source_file": "lessons/6-Other/22-DeepRL/CartPole-RL-PyTorch.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,109 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# マウンテンカーを脱出させるためのトレーニング\n",
|
||||
"\n",
|
||||
"[AI for Beginners Curriculum](https://github.com/microsoft/ai-for-beginners) の課題。\n",
|
||||
"\n",
|
||||
"あなたの目標は、OpenAI環境で[Mountain Car](https://www.gymlibrary.ml/environments/classic_control/mountain_car/)を操作するRLエージェントをトレーニングすることです。\n",
|
||||
"\n",
|
||||
"まずは環境を作成しましょう。\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import gym\n",
|
||||
"env = gym.make('MountainCar-v0')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ランダムな実験がどのように見えるか見てみましょう:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"state = env.reset()\n",
|
||||
"while True:\n",
|
||||
" env.render()\n",
|
||||
" action = env.action_space.sample()\n",
|
||||
" state, reward, done, info = env.step(action)\n",
|
||||
" if done:\n",
|
||||
" break"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"## Lost of code here"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"env.close()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**免責事項**: \nこの文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知ください。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当社は責任を負いません。\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.8.12 ('py38')",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "f062b3b18449593ef8e0fcc029868781",
|
||||
"translation_date": "2025-08-30T08:56:18+00:00",
|
||||
"source_file": "lessons/6-Other/22-DeepRL/lab/MountainCar.ipynb",
|
||||
"language_code": "ja"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,8 +1,8 @@
|
|||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "f3a6b0ddf7e6e3f33b2a543baf086dc9",
|
||||
"translation_date": "2025-08-25T21:19:22+00:00",
|
||||
"original_hash": "07191303b7ea2aff1d47e2b0fe4bb862",
|
||||
"translation_date": "2025-08-30T08:45:35+00:00",
|
||||
"source_file": "README.md",
|
||||
"language_code": "my"
|
||||
}
|
||||
|
|
@ -21,111 +21,122 @@ CO_OP_TRANSLATOR_METADATA:
|
|||
|
||||
[](https://discord.gg/zxKYvhSnVp?WT.mc_id=academic-000002-leestott)
|
||||
|
||||
# အခြေခံသိရှိရန်အတွက် အတတ်ပညာရပ် - သင်ခန်းစာများ
|
||||
# အခြေခံအဆင့်အတုအမြင်တု (Artificial Intelligence) သင်ခန်းစာ
|
||||
|
||||
| ](./lessons/sketchnotes/ai-overview.png)|
|
||||
||
|
||||
|:---:|
|
||||
| AI For Beginners - _Sketchnote by [@girlie_mac](https://twitter.com/girlie_mac)_ |
|
||||
|
||||
**Artificial Intelligence** (AI) ရဲ့ ကမ္ဘာကို 12-ပတ်၊ 24-သင်ခန်းစာများဖြင့် လေ့လာပါ။ သင်ခန်းစာများ၊ မေးခွန်းများနှင့် လက်တွေ့လုပ်ငန်းများပါဝင်ပြီး အခြေခံသင်ယူသူများအတွက် သင့်လျော်သည်။ TensorFlow နှင့် PyTorch ကိရိယာများ၊ AI ရဲ့ စည်းကမ်းများကိုလည်း လေ့လာနိုင်ပါသည်။
|
||||
**Artificial Intelligence** (AI) အပေါ် ၁၂ ပတ်၊ ၂၄ သင်ခန်းစာပါသော သင်ရိုးညွှန်းတမ်းကို လေ့လာပါ။ ၎င်းတွင် လက်တွေ့သင်ခန်းစာများ၊ စမ်းမေးခွန်းများနှင့် လက်တွေ့လေ့ကျင့်ခန်းများ ပါဝင်သည်။ သင်ရိုးညွှန်းတမ်းသည် အခြေခံအဆင့်အတွက် သင့်လျော်ပြီး TensorFlow နှင့် PyTorch ကိရိယာများ၊ AI အပေါ် သမိုင်းနှင့် ကျင့်ဝတ်များကိုလည်း ဖော်ပြထားသည်။
|
||||
|
||||
## သင်လေ့လာနိုင်မည့်အရာများ
|
||||
### 🌐 ဘာသာစကားများပံ့ပိုးမှု
|
||||
|
||||
**[သင်ခန်းစာများ၏ Mindmap](http://soshnikov.com/courses/ai-for-beginners/mindmap.html)**
|
||||
#### GitHub Action မှတဆင့် အလိုအလျောက် (အမြဲနောက်ဆုံးအခြေအနေ)
|
||||
|
||||
ဒီသင်ခန်းစာများတွင် သင်လေ့လာနိုင်မည့်အရာများမှာ -
|
||||
[French](../fr/README.md) | [Spanish](../es/README.md) | [German](../de/README.md) | [Russian](../ru/README.md) | [Arabic](../ar/README.md) | [Persian (Farsi)](../fa/README.md) | [Urdu](../ur/README.md) | [Chinese (Simplified)](../zh/README.md) | [Chinese (Traditional, Macau)](../mo/README.md) | [Chinese (Traditional, Hong Kong)](../hk/README.md) | [Chinese (Traditional, Taiwan)](../tw/README.md) | [Japanese](../ja/README.md) | [Korean](../ko/README.md) | [Hindi](../hi/README.md) | [Bengali](../bn/README.md) | [Marathi](../mr/README.md) | [Nepali](../ne/README.md) | [Punjabi (Gurmukhi)](../pa/README.md) | [Portuguese (Portugal)](../pt/README.md) | [Portuguese (Brazil)](../br/README.md) | [Italian](../it/README.md) | [Polish](../pl/README.md) | [Turkish](../tr/README.md) | [Greek](../el/README.md) | [Thai](../th/README.md) | [Swedish](../sv/README.md) | [Danish](../da/README.md) | [Norwegian](../no/README.md) | [Finnish](../fi/README.md) | [Dutch](../nl/README.md) | [Hebrew](../he/README.md) | [Vietnamese](../vi/README.md) | [Indonesian](../id/README.md) | [Malay](../ms/README.md) | [Tagalog (Filipino)](../tl/README.md) | [Swahili](../sw/README.md) | [Hungarian](../hu/README.md) | [Czech](../cs/README.md) | [Slovak](../sk/README.md) | [Romanian](../ro/README.md) | [Bulgarian](../bg/README.md) | [Serbian (Cyrillic)](../sr/README.md) | [Croatian](../hr/README.md) | [Slovenian](../sl/README.md) | [Ukrainian](../uk/README.md) | [Burmese (Myanmar)](./README.md)
|
||||
|
||||
* **Artificial Intelligence** ရဲ့ အမျိုးမျိုးသောနည်းလမ်းများ၊ အထူးသဖြင့် **Knowledge Representation** နှင့် reasoning ([GOFAI](https://en.wikipedia.org/wiki/Symbolic_artificial_intelligence)) ကို အသုံးပြုသော "ရိုးရိုးလေး" symbolic နည်းလမ်းများ။
|
||||
* **Neural Networks** နှင့် **Deep Learning**၊ အခေတ်သစ် AI ရဲ့ အခြေခံဖြစ်သော နည်းလမ်းများ။ TensorFlow နှင့် PyTorch ကဲ့သို့သော framework နှစ်ခုကို အသုံးပြု၍ အဓိကအကြောင်းအရာများကို code ဖြင့် ရှင်းလင်းပြသမည်။
|
||||
* **Neural Architectures** ကို ရုပ်ပုံများနှင့် စာသားများအတွက် အသုံးပြုခြင်း။ နောက်ဆုံးပေါ်နည်းလမ်းများကို လေ့လာမည်ဖြစ်သော်လည်း အချို့နည်းလမ်းများမှာ နောက်ဆုံးပေါ်နည်းလမ်းများထက် နည်းနည်းနောက်ကျနိုင်သည်။
|
||||
* **Genetic Algorithms** နှင့် **Multi-Agent Systems** ကဲ့သို့သော နည်းလမ်းများကိုလည်း လေ့လာမည်။
|
||||
**အပိုဘာသာစကားများကို ပံ့ပိုးလိုပါက [ဒီနေရာ](https://github.com/Azure/co-op-translator/blob/main/getting_started/supported-languages.md) တွင် ရှာဖွေပါ။**
|
||||
|
||||
ဒီသင်ခန်းစာများတွင် မပါဝင်မည့်အရာများ -
|
||||
## အသိုင်းအဝိုင်းနှင့် ပူးပေါင်းပါ
|
||||
[](https://discord.gg/kzRShWzttr)
|
||||
|
||||
> [ဒီသင်ခန်းစာများအတွက် Microsoft Learn collection မှ အပိုဆောင်းအရင်းအမြစ်များကို ရှာဖွေပါ](https://learn.microsoft.com/en-us/collections/7w28iy2xrqzdj0?WT.mc_id=academic-77998-bethanycheum)
|
||||
## သင်လေ့လာမည့်အရာများ
|
||||
|
||||
* **AI in Business** ကို အသုံးပြုခြင်းဆိုင်ရာ စီးပွားရေးအခွက်အခွင်းများ။ [Introduction to AI for business users](https://docs.microsoft.com/learn/paths/introduction-ai-for-business-users/?WT.mc_id=academic-77998-bethanycheum) သင်ခန်းစာများကို Microsoft Learn မှာ လေ့လာပါ၊ သို့မဟုတ် [AI Business School](https://www.microsoft.com/ai/ai-business-school/?WT.mc_id=academic-77998-bethanycheum) ကို [INSEAD](https://www.insead.edu/) နှင့် ပူးပေါင်းဖွင့်လှစ်ထားသည်။
|
||||
* **Classic Machine Learning** ကို [Machine Learning for Beginners Curriculum](http://github.com/Microsoft/ML-for-Beginners) မှာ ရှင်းလင်းထားသည်။
|
||||
* **[Cognitive Services](https://azure.microsoft.com/services/cognitive-services/?WT.mc_id=academic-77998-bethanycheum)** ကို အသုံးပြု၍ AI လက်တွေ့အသုံးချမှုများ။ Microsoft Learn မှာ [vision](https://docs.microsoft.com/learn/paths/create-computer-vision-solutions-azure-cognitive-services/?WT.mc_id=academic-77998-bethanycheum), [natural language processing](https://docs.microsoft.com/learn/paths/explore-natural-language-processing/?WT.mc_id=academic-77998-bethanycheum), **[Generative AI with Azure OpenAI Service](https://learn.microsoft.com/en-us/training/paths/develop-ai-solutions-azure-openai/?WT.mc_id=academic-77998-bethanycheum)** နှင့် အခြား module များကို စတင်လေ့လာပါ။
|
||||
* **Cloud Frameworks** (ML) အထူးသဖြင့် [Azure Machine Learning](https://azure.microsoft.com/services/machine-learning/?WT.mc_id=academic-77998-bethanycheum), [Microsoft Fabric](https://learn.microsoft.com/en-us/training/paths/get-started-fabric/?WT.mc_id=academic-77998-bethanycheum), သို့မဟုတ် [Azure Databricks](https://docs.microsoft.com/learn/paths/data-engineer-azure-databricks?WT.mc_id=academic-77998-bethanycheum) ကို အသုံးပြု၍ သင်ခန်းစာများကို လေ့လာပါ။
|
||||
* **Conversational AI** နှင့် **Chat Bots**။ [Create conversational AI solutions](https://docs.microsoft.com/learn/paths/create-conversational-ai-solutions/?WT.mc_id=academic-77998-bethanycheum) သင်ခန်းစာများကို လေ့လာပါ၊ သို့မဟုတ် [ဒီ blog post](https://soshnikov.com/azure/hello-bot-conversational-ai-on-microsoft-platform/) ကို အသေးစိတ်ဖတ်ရှုပါ။
|
||||
* **Deep Mathematics** (deep learning) အတွက် [Deep Learning](https://www.amazon.com/Deep-Learning-Adaptive-Computation-Machine/dp/0262035618) ကို Ian Goodfellow, Yoshua Bengio နှင့် Aaron Courville မှ ရေးသားထားပြီး [https://www.deeplearningbook.org/](https://www.deeplearningbook.org/) မှာလည်း ရရှိနိုင်ပါသည်။
|
||||
**[သင်ခန်းစာ၏ Mindmap](http://soshnikov.com/courses/ai-for-beginners/mindmap.html)**
|
||||
|
||||
_Cloud_ AI ကို စတင်လေ့လာရန် [Get started with artificial intelligence on Azure](https://docs.microsoft.com/learn/paths/get-started-with-artificial-intelligence-on-azure/?WT.mc_id=academic-77998-bethanycheum) သင်ခန်းစာများကို လေ့လာပါ။
|
||||
ဒီသင်ရိုးညွှန်းတမ်းတွင် သင်လေ့လာမည့်အရာများမှာ -
|
||||
|
||||
* Artificial Intelligence အပေါ် အမျိုးမျိုးသောနည်းလမ်းများ၊ အထူးသဖြင့် **Knowledge Representation** နှင့် reasoning ([GOFAI](https://en.wikipedia.org/wiki/Symbolic_artificial_intelligence)) အပါအဝင် "symbolic approach" ကိုလေ့လာပါ။
|
||||
* **Neural Networks** နှင့် **Deep Learning** ကိုလေ့လာပါ။ ၎င်းသည် ခေတ်သစ် AI ၏ အခြေခံဖြစ်သည်။ TensorFlow နှင့် PyTorch ကိရိယာများကို အသုံးပြု၍ အဓိကအကြောင်းအရာများကို ရှင်းလင်းပြသမည်။
|
||||
* **Neural Architectures** ကို ရုပ်ပုံများနှင့် စာသားများနှင့်အလုပ်လုပ်ရန်အတွက် အသုံးပြုပါမည်။
|
||||
* **Genetic Algorithms** နှင့် **Multi-Agent Systems** ကဲ့သို့သော နည်းလမ်းများကိုလည်း လေ့လာပါမည်။
|
||||
|
||||
ဒီသင်ရိုးညွှန်းတမ်းတွင် မပါဝင်မည့်အရာများ -
|
||||
|
||||
> [ဒီသင်ခန်းစာအတွက် Microsoft Learn collection တွင် အပိုအရင်းအမြစ်များကို ရှာဖွေပါ](https://learn.microsoft.com/en-us/collections/7w28iy2xrqzdj0?WT.mc_id=academic-77998-bethanycheum)
|
||||
|
||||
* **AI in Business** ကို အသုံးပြုခြင်းဆိုင်ရာ စီးပွားရေးအခန်းကဏ္ဍများ။ [AI for business users](https://docs.microsoft.com/learn/paths/introduction-ai-for-business-users/?WT.mc_id=academic-77998-bethanycheum) သင်ခန်းစာကို Microsoft Learn တွင် လေ့လာပါ။
|
||||
* **Classic Machine Learning** ကို [Machine Learning for Beginners Curriculum](http://github.com/Microsoft/ML-for-Beginners) တွင် ရှင်းလင်းထားသည်။
|
||||
* **Cognitive Services** အသုံးပြု၍ AI အလေ့အကျင့်များကို ဖန်တီးခြင်း။
|
||||
* **Cloud Frameworks** အထူးသဖြင့် [Azure Machine Learning](https://azure.microsoft.com/services/machine-learning/?WT.mc_id=academic-77998-bethanycheum) နှင့် [Microsoft Fabric](https://learn.microsoft.com/en-us/training/paths/get-started-fabric/?WT.mc_id=academic-77998-bethanycheum) စသည်တို့ကို လေ့လာပါ။
|
||||
* **Conversational AI** နှင့် **Chat Bots** ကို [Create conversational AI solutions](https://docs.microsoft.com/learn/paths/create-conversational-ai-solutions/?WT.mc_id=academic-77998-bethanycheum) သင်ခန်းစာတွင် လေ့လာပါ။
|
||||
* **Deep Mathematics** ကို [Deep Learning](https://www.amazon.com/Deep-Learning-Adaptive-Computation-Machine/dp/0262035618) စာအုပ်မှ လေ့လာပါ။
|
||||
|
||||
AI in the Cloud အပေါ် အနည်းငယ်သော အကျဉ်းချုပ်ကို [Get started with artificial intelligence on Azure](https://docs.microsoft.com/learn/paths/get-started-with-artificial-intelligence-on-azure/?WT.mc_id=academic-77998-bethanycheum) သင်ခန်းစာမှ စတင်ပါ။
|
||||
|
||||
# အကြောင်းအရာ
|
||||
|
||||
| | သင်ခန်းစာလင့်ခ် | PyTorch/Keras/TensorFlow | Lab |
|
||||
| :-: | :------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------: | ------------------------------------------------------------------------------ |
|
||||
| 0 | [သင်ခန်းစာများ စတင်ပြင်ဆင်ခြင်း](./lessons/0-course-setup/setup.md) | [သင့်ရဲ့ Development Environment ကို ပြင်ဆင်ပါ](./lessons/0-course-setup/how-to-run.md) | |
|
||||
| I | [**AI ရဲ့ အကျဉ်းချုပ်**](./lessons/1-Intro/README.md) | | |
|
||||
| 01 | [AI ရဲ့ သမိုင်းကြောင်းနှင့် အကျဉ်းချုပ်](./lessons/1-Intro/README.md) | - | - |
|
||||
| 0 | [သင်ခန်းစာ Setup](./lessons/0-course-setup/setup.md) | [သင့် Development Environment ကို Setup လုပ်ပါ](./lessons/0-course-setup/how-to-run.md) | |
|
||||
| I | [**AI အကျဉ်းချုပ်**](./lessons/1-Intro/README.md) | | |
|
||||
| 01 | [AI အကျဉ်းချုပ်နှင့် သမိုင်း](./lessons/1-Intro/README.md) | - | - |
|
||||
| II | **Symbolic AI** |
|
||||
| 02 | [Knowledge Representation နှင့် Expert Systems](./lessons/2-Symbolic/README.md) | [Expert Systems](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/2-Symbolic/Animals.ipynb) / [Ontology](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/2-Symbolic/FamilyOntology.ipynb) /[Concept Graph](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/2-Symbolic/MSConceptGraph.ipynb) | |
|
||||
| III | [**Neural Networks ရဲ့ အကျဉ်းချုပ်**](./lessons/3-NeuralNetworks/README.md) |||
|
||||
| 03 | [Perceptron](./lessons/3-NeuralNetworks/03-Perceptron/README.md) | [Notebook](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/3-NeuralNetworks/03-Perceptron/Perceptron.ipynb) | [Lab](./lessons/3-NeuralNetworks/03-Perceptron/lab/README.md) |
|
||||
| 04 | [Multi-Layered Perceptron နှင့် ကိုယ်ပိုင် Framework တည်ဆောက်ခြင်း](./lessons/3-NeuralNetworks/04-OwnFramework/README.md) | [Notebook](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/3-NeuralNetworks/04-OwnFramework/OwnFramework.ipynb) | [Lab](./lessons/3-NeuralNetworks/04-OwnFramework/lab/README.md) |
|
||||
| 05 | [Frameworks (PyTorch/TensorFlow) နှင့် Overfitting ရဲ့ အကျဉ်းချုပ်](./lessons/3-NeuralNetworks/05-Frameworks/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/3-NeuralNetworks/05-Frameworks/IntroPyTorch.ipynb) / [Keras](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/3-NeuralNetworks/05-Frameworks/IntroKeras.ipynb) / [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/3-NeuralNetworks/05-Frameworks/IntroKerasTF.ipynb) | [Lab](./lessons/3-NeuralNetworks/05-Frameworks/lab/README.md) |
|
||||
| IV | [**Computer Vision**](./lessons/4-ComputerVision/README.md) | [PyTorch](https://docs.microsoft.com/learn/modules/intro-computer-vision-pytorch/?WT.mc_id=academic-77998-cacaste) / [TensorFlow](https://docs.microsoft.com/learn/modules/intro-computer-vision-TensorFlow/?WT.mc_id=academic-77998-cacaste)| [Explore Computer Vision on Microsoft Azure](https://learn.microsoft.com/en-us/collections/7w28iy2xrqzdj0?WT.mc_id=academic-77998-bethanycheum) |
|
||||
| 06 | [Computer Vision ရဲ့ အကျဉ်းချုပ်။ OpenCV](./lessons/4-ComputerVision/06-IntroCV/README.md) | [Notebook](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/06-IntroCV/OpenCV.ipynb) | [Lab](./lessons/4-ComputerVision/06-IntroCV/lab/README.md) |
|
||||
| 07 | [Convolutional Neural Networks](./lessons/4-ComputerVision/07-ConvNets/README.md) & [CNN Architectures](./lessons/4-ComputerVision/07-ConvNets/CNN_Architectures.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/07-ConvNets/ConvNetsPyTorch.ipynb) /[TensorFlow](https://microsoft.github.io/AI-For-Beginners/lessons/4-ComputerVision/07-ConvNets/ConvNetsTF.ipynb) | [Lab](./lessons/4-ComputerVision/07-ConvNets/lab/README.md) |
|
||||
| 08 | [ကြိုတင်သင်ကြားထားသောကွန်ယက်များနှင့် လွှဲပြောင်းသင်ကြားမှု](./lessons/4-ComputerVision/08-TransferLearning/README.md) နှင့် [လေ့ကျင့်မှုအထောက်အကူများ](./lessons/4-ComputerVision/08-TransferLearning/TrainingTricks.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/08-TransferLearning/TransferLearningPyTorch.ipynb) / [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/3-NeuralNetworks/05-Frameworks/IntroKerasTF.ipynb) | [Lab](./lessons/4-ComputerVision/08-TransferLearning/lab/README.md) |
|
||||
| 09 | [အော်တိုအင်ကိုဒါများနှင့် VAEs](./lessons/4-ComputerVision/09-Autoencoders/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/09-Autoencoders/AutoEncodersPyTorch.ipynb) / [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/09-Autoencoders/AutoencodersTF.ipynb) | |
|
||||
| 10 | [Generative Adversarial Networks နှင့် အနုပညာစတိုင်လွှဲပြောင်းမှု](./lessons/4-ComputerVision/10-GANs/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/10-GANs/GANPyTorch.ipynb) / [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/10-GANs/GANTF.ipynb) | |
|
||||
| 11 | [အရာဝတ္ထုရှာဖွေမှု](./lessons/4-ComputerVision/11-ObjectDetection/README.md) | [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/11-ObjectDetection/ObjectDetection.ipynb) | [Lab](./lessons/4-ComputerVision/11-ObjectDetection/lab/README.md) |
|
||||
| 12 | [အဓိပ္ပါယ်ဆိုင်ရာခွဲခြမ်းစိတ်ဖြာမှု။ U-Net](./lessons/4-ComputerVision/12-Segmentation/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/12-Segmentation/SemanticSegmentationPytorch.ipynb) / [TensorFlow](../../(https:/github.com/microsoft/AI-For-Beginners/blob/main/lessons/4-ComputerVision/12-Segmentation/SemanticSegmentationTF.ipynb)) | |
|
||||
| V | [**ဘာသာစကားသဘာဝဆိုင်ရာလုပ်ငန်းစဉ်များ**](./lessons/5-NLP/README.md) | [PyTorch](https://docs.microsoft.com/learn/modules/intro-natural-language-processing-pytorch/?WT.mc_id=academic-77998-cacaste) /[TensorFlow](https://docs.microsoft.com/learn/modules/intro-natural-language-processing-TensorFlow/?WT.mc_id=academic-77998-cacaste) | [Microsoft Azure တွင် ဘာသာစကားသဘာဝဆိုင်ရာလုပ်ငန်းစဉ်များကို စူးစမ်းပါ](https://learn.microsoft.com/en-us/collections/7w28iy2xrqzdj0?WT.mc_id=academic-77998-bethanycheum)|
|
||||
| 13 | [စာသားကိုယ်စားပြုမှု။ Bow/TF-IDF](./lessons/5-NLP/13-TextRep/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/13-TextRep/TextRepresentationPyTorch.ipynb) / [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/13-TextRep/TextRepresentationTF.ipynb) | |
|
||||
| 14 | [အဓိပ္ပါယ်ဆိုင်ရာ စကားလုံး embedding များ။ Word2Vec နှင့် GloVe](./lessons/5-NLP/14-Embeddings/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/14-Embeddings/EmbeddingsPyTorch.ipynb) / [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/14-Embeddings/EmbeddingsTF.ipynb) | |
|
||||
| 15 | [ဘာသာစကားမော်ဒယ်ဖွဲ့စည်းမှု။ ကိုယ်ပိုင် embedding များကို လေ့ကျင့်ခြင်း](./lessons/5-NLP/15-LanguageModeling/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/15-LanguageModeling/CBoW-PyTorch.ipynb) / [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/15-LanguageModeling/CBoW-TF.ipynb) | [Lab](./lessons/5-NLP/15-LanguageModeling/lab/README.md) |
|
||||
| 16 | [ပြန်လည်ထပ်ဆင့်သော နယူးရယ်ကွန်ယက်များ](./lessons/5-NLP/16-RNN/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/16-RNN/RNNPyTorch.ipynb) / [TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/16-RNN/RNNTF.ipynb) | |
|
||||
| 17 | [Generative ပြန်လည်ထပ်ဆင့်ကွန်ယက်များ](./lessons/5-NLP/17-GenerativeNetworks/README.md) | [PyTorch](https://microsoft.github.io/AI-For-Beginners/lessons/5-NLP/17-GenerativeNetworks/GenerativePyTorch.md) / [TensorFlow](https://microsoft.github.io/AI-For-Beginners/lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.md) | [Lab](./lessons/5-NLP/17-GenerativeNetworks/lab/README.md) |
|
||||
| 18 | [Transformers။ BERT။](./lessons/5-NLP/18-Transformers/READMEtransformers.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/18-Transformers/TransformersPyTorch.ipynb) /[TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/5-NLP/18-Transformers/TransformersTF.ipynb) | |
|
||||
| 19 | [အမည်ပေးထားသော အဖွဲ့အစည်းအသိအမှတ်ပြုမှု](./lessons/5-NLP/19-NER/README.md) | [TensorFlow](https://microsoft.github.io/AI-For-Beginners/lessons/5-NLP/19-NER/NER-TF.ipynb) | [Lab](./lessons/5-NLP/19-NER/lab/README.md) |
|
||||
| 20 | [ကြီးမားသော ဘာသာစကားမော်ဒယ်များ၊ Prompt Programming နှင့် Few-Shot Tasks](./lessons/5-NLP/20-LangModels/READMELargeLang.md) | [PyTorch](https://microsoft.github.io/AI-For-Beginners/lessons/5-NLP/20-LangModels/GPT-PyTorch.ipynb) | |
|
||||
| VI | **အခြား AI နည်းပညာများ** || |
|
||||
| 21 | [Genetic Algorithms](./lessons/6-Other/21-GeneticAlgorithms/README.md) | [Notebook](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/6-Other/21-GeneticAlgorithms/Genetic.ipynb) | |
|
||||
| 22 | [နက်ရှိုင်းသော အားကစားသင်ကြားမှု](./lessons/6-Other/22-DeepRL/README.md) | [PyTorch](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/6-Other/22-DeepRL/CartPole-RL-PyTorch.ipynb) /[TensorFlow](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/6-Other/22-DeepRL/CartPole-RL-TF.ipynb) | [Lab](./lessons/6-Other/22-DeepRL/lab/README.md) |
|
||||
| 02 | [Knowledge Representation နှင့် Expert Systems](./lessons/2-Symbolic/README.md) | [Expert Systems](./lessons/2-Symbolic/Animals.ipynb) / [Ontology](./lessons/2-Symbolic/FamilyOntology.ipynb) /[Concept Graph](./lessons/2-Symbolic/MSConceptGraph.ipynb) | |
|
||||
| III | [**Neural Networks အကျဉ်းချုပ်**](./lessons/3-NeuralNetworks/README.md) |||
|
||||
| 03 | [Perceptron](./lessons/3-NeuralNetworks/03-Perceptron/README.md) | [Notebook](./lessons/3-NeuralNetworks/03-Perceptron/Perceptron.ipynb) | [Lab](./lessons/3-NeuralNetworks/03-Perceptron/lab/README.md) |
|
||||
| 04 | [Multi-Layered Perceptron နှင့် ကိုယ်ပိုင် Framework ဖန်တီးခြင်း](./lessons/3-NeuralNetworks/04-OwnFramework/README.md) | [Notebook](./lessons/3-NeuralNetworks/04-OwnFramework/OwnFramework.ipynb) | [Lab](./lessons/3-NeuralNetworks/04-OwnFramework/lab/README.md) |
|
||||
| 05 | [Frameworks (PyTorch/TensorFlow) နှင့် Overfitting အကြောင်းမိတ်ဆက်](./lessons/3-NeuralNetworks/05-Frameworks/README.md) | [PyTorch](./lessons/3-NeuralNetworks/05-Frameworks/IntroPyTorch.ipynb) / [Keras](./lessons/3-NeuralNetworks/05-Frameworks/IntroKeras.ipynb) / [TensorFlow](./lessons/3-NeuralNetworks/05-Frameworks/IntroKerasTF.ipynb) | [Lab](./lessons/3-NeuralNetworks/05-Frameworks/lab/README.md) |
|
||||
| IV | [**ကွန်ပျူတာမြင်ကွင်း (Computer Vision)**](./lessons/4-ComputerVision/README.md) | [PyTorch](https://docs.microsoft.com/learn/modules/intro-computer-vision-pytorch/?WT.mc_id=academic-77998-cacaste) / [TensorFlow](https://docs.microsoft.com/learn/modules/intro-computer-vision-TensorFlow/?WT.mc_id=academic-77998-cacaste)| [Microsoft Azure တွင် Computer Vision ကိုလေ့လာပါ](https://learn.microsoft.com/en-us/collections/7w28iy2xrqzdj0?WT.mc_id=academic-77998-bethanycheum) |
|
||||
| 06 | [Computer Vision အကြောင်းမိတ်ဆက်။ OpenCV](./lessons/4-ComputerVision/06-IntroCV/README.md) | [Notebook](./lessons/4-ComputerVision/06-IntroCV/OpenCV.ipynb) | [Lab](./lessons/4-ComputerVision/06-IntroCV/lab/README.md) |
|
||||
| 07 | [Convolutional Neural Networks](./lessons/4-ComputerVision/07-ConvNets/README.md) & [CNN Architectures](./lessons/4-ComputerVision/07-ConvNets/CNN_Architectures.md) | [PyTorch](./lessons/4-ComputerVision/07-ConvNets/ConvNetsPyTorch.ipynb) /[TensorFlow](./lessons/4-ComputerVision/07-ConvNets/ConvNetsTF.ipynb) | [Lab](./lessons/4-ComputerVision/07-ConvNets/lab/README.md) |
|
||||
| 08 | [Pre-trained Networks နှင့် Transfer Learning](./lessons/4-ComputerVision/08-TransferLearning/README.md) and [Training Tricks](./lessons/4-ComputerVision/08-TransferLearning/TrainingTricks.md) | [PyTorch](./lessons/4-ComputerVision/08-TransferLearning/TransferLearningPyTorch.ipynb) / [TensorFlow](./lessons/3-NeuralNetworks/05-Frameworks/IntroKerasTF.ipynb) | [Lab](./lessons/4-ComputerVision/08-TransferLearning/lab/README.md) |
|
||||
| 09 | [Autoencoders နှင့် VAEs](./lessons/4-ComputerVision/09-Autoencoders/README.md) | [PyTorch](./lessons/4-ComputerVision/09-Autoencoders/AutoEncodersPyTorch.ipynb) / [TensorFlow](./lessons/4-ComputerVision/09-Autoencoders/AutoencodersTF.ipynb) | |
|
||||
| 10 | [Generative Adversarial Networks & Artistic Style Transfer](./lessons/4-ComputerVision/10-GANs/README.md) | [PyTorch](./lessons/4-ComputerVision/10-GANs/GANPyTorch.ipynb) / [TensorFlow](./lessons/4-ComputerVision/10-GANs/GANTF.ipynb) | |
|
||||
| 11 | [Object Detection](./lessons/4-ComputerVision/11-ObjectDetection/README.md) | [TensorFlow](./lessons/4-ComputerVision/11-ObjectDetection/ObjectDetection.ipynb) | [Lab](./lessons/4-ComputerVision/11-ObjectDetection/lab/README.md) |
|
||||
| 12 | [Semantic Segmentation. U-Net](./lessons/4-ComputerVision/12-Segmentation/README.md) | [PyTorch](./lessons/4-ComputerVision/12-Segmentation/SemanticSegmentationPytorch.ipynb) / [TensorFlow](./lessons/4-ComputerVision/12-Segmentation/SemanticSegmentationTF.ipynb) | |
|
||||
| V | [**ဘာသာစကားအပြုအမူဆိုင်ရာ (Natural Language Processing)**](./lessons/5-NLP/README.md) | [PyTorch](https://docs.microsoft.com/learn/modules/intro-natural-language-processing-pytorch/?WT.mc_id=academic-77998-cacaste) /[TensorFlow](https://docs.microsoft.com/learn/modules/intro-natural-language-processing-TensorFlow/?WT.mc_id=academic-77998-cacaste) | [Microsoft Azure တွင် Natural Language Processing ကိုလေ့လာပါ](https://learn.microsoft.com/en-us/collections/7w28iy2xrqzdj0?WT.mc_id=academic-77998-bethanycheum)|
|
||||
| 13 | [စာသားကိုယ်စားပြုမှု။ Bow/TF-IDF](./lessons/5-NLP/13-TextRep/README.md) | [PyTorch](./lessons/5-NLP/13-TextRep/TextRepresentationPyTorch.ipynb) / [TensorFlow](./lessons/5-NLP/13-TextRep/TextRepresentationTF.ipynb) | |
|
||||
| 14 | [Semantic word embeddings. Word2Vec နှင့် GloVe](./lessons/5-NLP/14-Embeddings/README.md) | [PyTorch](./lessons/5-NLP/14-Embeddings/EmbeddingsPyTorch.ipynb) / [TensorFlow](./lessons/5-NLP/14-Embeddings/EmbeddingsTF.ipynb) | |
|
||||
| 15 | [ဘာသာစကားမော်ဒယ်။ ကိုယ်ပိုင် embeddings များကိုလေ့ကျင့်ခြင်း](./lessons/5-NLP/15-LanguageModeling/README.md) | [PyTorch](./lessons/5-NLP/15-LanguageModeling/CBoW-PyTorch.ipynb) / [TensorFlow](./lessons/5-NLP/15-LanguageModeling/CBoW-TF.ipynb) | [Lab](./lessons/5-NLP/15-LanguageModeling/lab/README.md) |
|
||||
| 16 | [Recurrent Neural Networks](./lessons/5-NLP/16-RNN/README.md) | [PyTorch](./lessons/5-NLP/16-RNN/RNNPyTorch.ipynb) / [TensorFlow](./lessons/5-NLP/16-RNN/RNNTF.ipynb) | |
|
||||
| 17 | [Generative Recurrent Networks](./lessons/5-NLP/17-GenerativeNetworks/README.md) | [PyTorch](./lessons/5-NLP/17-GenerativeNetworks/GenerativePyTorch.md) / [TensorFlow](./lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.md) | [Lab](./lessons/5-NLP/17-GenerativeNetworks/lab/README.md) |
|
||||
| 18 | [Transformers. BERT.](./lessons/5-NLP/18-Transformers/READMEtransformers.md) | [PyTorch](./lessons/5-NLP/18-Transformers/TransformersPyTorch.ipynb) /[TensorFlow](./lessons/5-NLP/18-Transformers/TransformersTF.ipynb) | |
|
||||
| 19 | [Named Entity Recognition](./lessons/5-NLP/19-NER/README.md) | [TensorFlow](./lessons/5-NLP/19-NER/NER-TF.ipynb) | [Lab](./lessons/5-NLP/19-NER/lab/README.md) |
|
||||
| 20 | [အကြီးစားဘာသာစကားမော်ဒယ်များ၊ Prompt Programming နှင့် Few-Shot Tasks](./lessons/5-NLP/20-LangModels/READMELargeLang.md) | [PyTorch](./lessons/5-NLP/20-LangModels/GPT-PyTorch.ipynb) | |
|
||||
| VI | **အခြား AI နည်းလမ်းများ** || |
|
||||
| 21 | [Genetic Algorithms](./lessons/6-Other/21-GeneticAlgorithms/README.md) | [Notebook](./lessons/6-Other/21-GeneticAlgorithms/Genetic.ipynb) | |
|
||||
| 22 | [Deep Reinforcement Learning](./lessons/6-Other/22-DeepRL/README.md) | [PyTorch](./lessons/6-Other/22-DeepRL/CartPole-RL-PyTorch.ipynb) /[TensorFlow](./lessons/6-Other/22-DeepRL/CartPole-RL-TF.ipynb) | [Lab](./lessons/6-Other/22-DeepRL/lab/README.md) |
|
||||
| 23 | [Multi-Agent Systems](./lessons/6-Other/23-MultiagentSystems/README.md) | | |
|
||||
| VII | **AI စည်းကမ်းများ** | | |
|
||||
| 24 | [AI စည်းကမ်းများနှင့် တာဝန်ရှိသော AI](./lessons/7-Ethics/README.md) | [Microsoft Learn: တာဝန်ရှိသော AI မူဝါဒများ](https://docs.microsoft.com/learn/paths/responsible-ai-business-principles/?WT.mc_id=academic-77998-cacaste) | |
|
||||
| VII | **AI ကျင့်ဝတ်သိက္ခာများ** | | |
|
||||
| 24 | [AI ကျင့်ဝတ်သိက္ခာနှင့် တာဝန်ရှိသော AI](./lessons/7-Ethics/README.md) | [Microsoft Learn: Responsible AI Principles](https://docs.microsoft.com/learn/paths/responsible-ai-business-principles/?WT.mc_id=academic-77998-cacaste) | |
|
||||
| IX | **အပိုဆောင်းများ** | | |
|
||||
| 25 | [Multi-Modal Networks, CLIP နှင့် VQGAN](./lessons/X-Extras/X1-MultiModal/README.md) | [Notebook](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/X-Extras/X1-MultiModal/Clip.ipynb) | |
|
||||
| 25 | [Multi-Modal Networks, CLIP နှင့် VQGAN](./lessons/X-Extras/X1-MultiModal/README.md) | [Notebook](./lessons/X-Extras/X1-MultiModal/Clip.ipynb) | |
|
||||
|
||||
## သင်ခန်းစာတိုင်းတွင် ပါဝင်သည်
|
||||
|
||||
* ကြိုတင်ဖတ်ရှုရန် အကြောင်းအရာများ
|
||||
* လုပ်ဆောင်နိုင်သော Jupyter Notebooks များ၊ အများအားဖြင့် framework (**PyTorch** သို့မဟုတ် **TensorFlow**) အတွက် သီးသန့်ဖြစ်သည်။ ထို notebook များတွင် သီအိုရီဆိုင်ရာ အကြောင်းအရာများလည်း ပါဝင်ပြီး၊ ခေါင်းစဉ်ကို နားလည်ရန် notebook တစ်ခု (PyTorch သို့မဟုတ် TensorFlow) ကို အနည်းဆုံး လေ့လာရမည်။
|
||||
* **Labs** သင်ခန်းစာအချို့တွင် ရရှိနိုင်ပြီး သင်လေ့လာထားသော အကြောင်းအရာများကို သတ်မှတ်ပြဿနာတစ်ခုတွင် လက်တွေ့ကျင့်သုံးနိုင်ရန် အခွင့်အရေးပေးသည်။
|
||||
* အချို့သော အပိုင်းများတွင် [**MS Learn**](https://learn.microsoft.com/en-us/collections/7w28iy2xrqzdj0?WT.mc_id=academic-77998-bethanycheum) မှ ဆက်စပ်သော ခေါင်းစဉ်များကို ဖော်ပြထားသည်။
|
||||
* ကြိုတင်ဖတ်ရှုရန်အကြောင်းအရာများ
|
||||
* **PyTorch** သို့မဟုတ် **TensorFlow** framework အတွက် သီးသန့်ရေးသားထားသော Jupyter Notebooks များ။ ဤ notebooks များတွင် သီအိုရီဆိုင်ရာအကြောင်းအရာများလည်း ပါဝင်ပြီး သင်ခန်းစာကို နားလည်ရန်အတွက် PyTorch သို့မဟုတ် TensorFlow ၏ အနည်းဆုံးတစ်မျိုးကို လေ့လာရန်လိုအပ်ပါသည်။
|
||||
* **Labs** သင်ခန်းစာအချို့တွင် ရရှိနိုင်ပြီး သင်လေ့လာထားသောအကြောင်းအရာများကို သတ်မှတ်ပြဿနာတစ်ခုတွင် လက်တွေ့ကျင့်သုံးနိုင်စေရန် အခွင့်အရေးပေးပါသည်။
|
||||
* အချို့သောအပိုင်းများတွင် [**MS Learn**](https://learn.microsoft.com/en-us/collections/7w28iy2xrqzdj0?WT.mc_id=academic-77998-bethanycheum) ၏ ဆက်စပ်အကြောင်းအရာများကို လင့်ခ်များဖြင့် ပံ့ပိုးထားပါသည်။
|
||||
|
||||
## စတင်ရန်
|
||||
|
||||
- သင်၏ ဖွံ့ဖြိုးရေးပတ်ဝန်းကျင်ကို ပြင်ဆင်ရန် အကူအညီပေးသည့် [setup lesson](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/0-course-setup/setup.md) တစ်ခုကို ဖန်တီးထားပါသည်။
|
||||
- ဆရာများအတွက်လည်း [curricula setup lesson](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/0-course-setup/for-teachers.md) တစ်ခုကို ဖန်တီးထားပါသည်။
|
||||
- [VSCode သို့မဟုတ် Codepace တွင် ကုဒ်ကို လည်ပတ်ရန်](https://github.com/microsoft/AI-For-Beginners/blob/main/lessons/0-course-setup/how-to-run.md) အဆင့်များကို လိုက်နာပါ။
|
||||
- သင်၏ ဖွံ့ဖြိုးရေးပတ်ဝန်းကျင်ကို ပြင်ဆင်ရန်အတွက် [setup lesson](./lessons/0-course-setup/setup.md) ကို ဖန်တီးထားပါသည်။
|
||||
- ဆရာများအတွက်လည်း [curricula setup lesson](./lessons/0-course-setup/for-teachers.md) ကို ဖန်တီးထားပါသည်။
|
||||
- [VSCode သို့မဟုတ် Codepace တွင် ကုဒ်ကို အလုပ်လုပ်စေခြင်း](./lessons/0-course-setup/how-to-run.md) အကြောင်းကိုလည်း ဖတ်ရှုနိုင်ပါသည်။
|
||||
|
||||
အဆင့်များကို လိုက်နာပါ:
|
||||
ဤအဆင့်များကို လိုက်နာပါ-
|
||||
|
||||
Repository ကို Fork လုပ်ပါ: ဒီစာမျက်နှာ၏ အပေါ်ယံညာဘက်တွင် "Fork" ခလုတ်ကို နှိပ်ပါ။
|
||||
Repository ကို Fork လုပ်ပါ- ဤစာမျက်နှာ၏ အပေါ်ညာဘက်ထောင့်ရှိ "Fork" ခလုတ်ကို နှိပ်ပါ။
|
||||
|
||||
Repository ကို Clone လုပ်ပါ: `git clone https://github.com/microsoft/AI-For-Beginners.git`
|
||||
Repository ကို Clone လုပ်ပါ- `git clone https://github.com/microsoft/AI-For-Beginners.git`
|
||||
|
||||
ဒီ repo ကို နောက်ပိုင်းတွင် လွယ်ကူစွာ ရှာဖွေရန်အတွက် star (🌟) လုပ်ထားပါ။
|
||||
ဤ repo ကို နောက်ပိုင်းတွင် လွယ်ကူစွာ ရှာဖွေရန်အတွက် star (🌟) လုပ်ထားပါ။
|
||||
|
||||
## အခြား သင်ကြားသူများနှင့် တွေ့ဆုံပါ
|
||||
## အခြားသင်ကြားသူများနှင့်တွေ့ဆုံပါ
|
||||
|
||||
ဒီသင်တန်းကို လေ့လာနေသော အခြား သင်ကြားသူများနှင့် တွေ့ဆုံရန်နှင့် အထောက်အကူရရန် [တရားဝင် AI Discord server](https://aka.ms/genai-discord?WT.mc_id=academic-105485-bethanycheum) ကို ဝင်ပါ။
|
||||
ဤသင်တန်းကို လေ့လာနေသော အခြားသင်ကြားသူများနှင့် တွေ့ဆုံရန်နှင့် အထောက်အပံ့ရရန် [AI Discord server](https://aka.ms/genai-discord?WT.mc_id=academic-105485-bethanycheum) တွင် ပါဝင်ပါ။
|
||||
|
||||
သင်တစ်ခုခု ဖန်တီးနေစဉ်တွင် ထုတ်ကုန်အကြံပြုချက်များ သို့မဟုတ် မေးခွန်းများရှိပါက [Azure AI Foundry Developer Forum](https://aka.ms/foundry/forum) ကို သွားပါ။
|
||||
သင်တစ်စုံတစ်ရာ ဖန်တီးနေစဉ်တွင် ထုတ်ကုန်အကြံပြုချက်များ သို့မဟုတ် မေးခွန်းများရှိပါက [Azure AI Foundry Developer Forum](https://aka.ms/foundry/forum) သို့ သွားပါ။
|
||||
|
||||
## စစ်ဆေးမှုများ
|
||||
> **ကွစ်များအကြောင်းမှတ်ချက်**: ကွစ်များအားလုံးကို Quiz-app ဖိုလ်ဒါထဲတွင် etc\quiz-app တွင် ထည့်သွင်းထားပါသည်။ ၎င်းများကို သင်ခန်းစာများအတွင်းမှ ချိတ်ဆက်ထားပြီး၊ quiz app ကို ဒေသတွင်းတွင် အလုပ်လည်စေခြင်း သို့မဟုတ် Azure သို့ တင်သွင်းနိုင်ပါသည်။ `quiz-app` ဖိုလ်ဒါအတွင်းရှိ လမ်းညွှန်ချက်များကို လိုက်နာပါ။ ၎င်းများကို တဖြည်းဖြည်း ဒေသီဖြစ်အောင် ပြုလုပ်နေပါသည်။
|
||||
## စစ်ဆေးမေးခွန်းများ
|
||||
> **မေးခွန်းများအကြောင်းမှတ်ချက်**: မေးခွန်းများအားလုံးသည် Quiz-app ဖိုလ်ဒါတွင် etc\quiz-app တွင်ပါရှိပြီး၊ [အွန်လိုင်းတွင် ဒီမှာ](https://ff-quizzes.netlify.app/) တွေ့နိုင်ပါသည်။ မေးခွန်းများကို သင်ခန်းစာများအတွင်းမှ ချိတ်ဆက်ထားပြီး၊ quiz app ကို ဒေသတွင်းတွင် အလုပ်လည်စေခြင်း သို့မဟုတ် Azure တွင် တင်သွင်းနိုင်ပါသည်။ `quiz-app` ဖိုလ်ဒါအတွင်းရှိ လမ်းညွှန်ချက်များကို လိုက်နာပါ။ မေးခွန်းများကို တဖြည်းဖြည်း ဒေသိယပြုလုပ်နေပါသည်။
|
||||
## အကူအညီလိုအပ်သည်
|
||||
|
||||
သင်မှာ အကြံပြုချက်များရှိပါသလား၊ ဒါမှမဟုတ် စာလုံးပေါင်းအမှားများ သို့မဟုတ် ကုဒ်အမှားများ ရှာဖွေတွေ့ရှိပါသလား။ Issue တစ်ခုတင်ပေးပါ သို့မဟုတ် pull request တစ်ခု ဖန်တီးပေးပါ။
|
||||
သင်မှာ အကြံပြုချက်များရှိပါသလား၊ ဒါမှမဟုတ် စာလုံးပေါင်းအမှားများ သို့မဟုတ် ကုဒ်အမှားများ ရှာဖွေတွေ့ရှိပါသလား။ Issue တစ်ခုတင်ပါ သို့မဟုတ် Pull Request တစ်ခု ဖန်တီးပါ။
|
||||
|
||||
## အထူးကျေးဇူးတင်စကား
|
||||
## အထူးကျေးဇူးတင်ပါသည်
|
||||
|
||||
* **✍️ အဓိကရေးသားသူ:** [Dmitry Soshnikov](http://soshnikov.com), PhD
|
||||
* **🔥 တည်းဖြတ်သူ:** [Jen Looper](https://twitter.com/jenlooper), PhD
|
||||
|
|
@ -152,5 +163,7 @@ Repository ကို Clone လုပ်ပါ: `git clone https://github.com/mic
|
|||
- [Mastering GitHub Copilot for C#/.NET Developers](https://github.com/microsoft/mastering-github-copilot-for-dotnet-csharp-developers)
|
||||
- [Choose Your Own Copilot Adventure](https://github.com/microsoft/CopilotAdventures)
|
||||
|
||||
---
|
||||
|
||||
**အကြောင်းကြားချက်**:
|
||||
ဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှန်ကန်မှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်မှုများတွင် အမှားများ သို့မဟုတ် မမှန်ကန်မှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာတရားရှိသော ရင်းမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူ့ဘာသာပြန်ပညာရှင်များမှ ပရော်ဖက်ရှင်နယ် ဘာသာပြန်မှုကို အကြံပြုပါသည်။ ဤဘာသာပြန်မှုကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားလွဲမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။
|
||||
ဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်ခြင်းတွင် အမှားများ သို့မဟုတ် မမှန်ကန်မှုများ ပါရှိနိုင်သည်ကို သတိပြုပါ။ မူရင်းဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာတရားရှိသော ရင်းမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူ့ဘာသာပြန်ပညာရှင်များမှ ပရော်ဖက်ရှင်နယ် ဘာသာပြန်ခြင်းကို အကြံပြုပါသည်။ ဤဘာသာပြန်ကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားယူမှားမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။
|
||||
|
|
@ -0,0 +1,480 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"source": [
|
||||
"# တိရစ္ဆာန် အတတ်ပညာ စနစ် တည်ဆောက်ခြင်း\n",
|
||||
"\n",
|
||||
"[AI for Beginners Curriculum](http://github.com/microsoft/ai-for-beginners) မှ နမူနာတစ်ခု။\n",
|
||||
"\n",
|
||||
"ဒီနမူနာမှာတော့ ရုပ်ပိုင်းဆိုင်ရာ အင်္ဂါရပ်အချို့အပေါ် မူတည်ပြီး တိရစ္ဆာန်ကို သတ်မှတ်နိုင်ရန် ရိုးရှင်းတဲ့ အသိပညာအခြေပြု စနစ်တစ်ခုကို တည်ဆောက်သွားမှာ ဖြစ်ပါတယ်။ ဒီစနစ်ကို အောက်ပါ AND-OR သစ်ပင်ဖြင့် ကိုယ်စားပြုနိုင်ပါတယ် (ဒီဟာက သစ်ပင်တစ်ခုလုံးရဲ့ အစိတ်အပိုင်းတစ်ခုသာဖြစ်ပြီး နောက်ထပ် စည်းမျဉ်းများကို လွယ်ကူစွာ ထပ်ထည့်နိုင်ပါတယ်)။\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## ကျွန်ုပ်တို့၏ အတတ်ပညာစနစ် shell ကို နောက်ပြန်သုံးသပ်မှုဖြင့်\n",
|
||||
"\n",
|
||||
"ပုံစံစည်းမျဉ်းများအပေါ် အခြေခံပြီး အသိပညာကို ကိုယ်စားပြုရန်အတွက် ရိုးရှင်းသော ဘာသာစကားတစ်ခုကို သတ်မှတ်ကြည့်ရအောင်။ ကျွန်ုပ်တို့သည် စည်းမျဉ်းများကို သတ်မှတ်ရန်အတွက် Python class များကို keyword အဖြစ် အသုံးပြုမည်။ အဓိကအားဖြင့် အတန်း (classes) ၃ မျိုးရှိမည်ဖြစ်သည်။\n",
|
||||
"* `Ask` သည် အသုံးပြုသူကို မေးရမည့် မေးခွန်းကို ကိုယ်စားပြုသည်။ ၎င်းတွင် အဖြေများ၏ အစုအဖွဲ့ကို ပါဝင်သည်။\n",
|
||||
"* `If` သည် စည်းမျဉ်းကို ကိုယ်စားပြုသည်၊ ၎င်းသည် စည်းမျဉ်း၏ အကြောင်းအရာကို သိမ်းဆည်းရန် syntactic sugar ဖြစ်သည်။\n",
|
||||
"* `AND`/`OR` သည် အပင်၏ AND/OR ချိတ်ဆက်မှုများကို ကိုယ်စားပြုရန်အတွက် classes ဖြစ်သည်။ ၎င်းတို့သည် အတွင်းရှိ arguments များ၏ စာရင်းကိုသာ သိမ်းဆည်းသည်။ ကုဒ်ကို ရိုးရှင်းစေရန် အလုပ်ဆောင်မှုအားလုံးကို မိဘ class `Content` တွင် သတ်မှတ်ထားသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class Ask():\n",
|
||||
" def __init__(self,choices=['y','n']):\n",
|
||||
" self.choices = choices\n",
|
||||
" def ask(self):\n",
|
||||
" if max([len(x) for x in self.choices])>1:\n",
|
||||
" for i,x in enumerate(self.choices):\n",
|
||||
" print(\"{0}. {1}\".format(i,x),flush=True)\n",
|
||||
" x = int(input())\n",
|
||||
" return self.choices[x]\n",
|
||||
" else:\n",
|
||||
" print(\"/\".join(self.choices),flush=True)\n",
|
||||
" return input()\n",
|
||||
"\n",
|
||||
"class Content():\n",
|
||||
" def __init__(self,x):\n",
|
||||
" self.x=x\n",
|
||||
" \n",
|
||||
"class If(Content):\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"class AND(Content):\n",
|
||||
" pass\n",
|
||||
"\n",
|
||||
"class OR(Content):\n",
|
||||
" pass"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့၏စနစ်တွင်၊ အလုပ်လုပ်နေသောမှတ်ဉာဏ်သည် **attribute-value pairs** အဖြစ် **အချက်အလက်များ** စာရင်းကို ပါဝင်မည်ဖြစ်သည်။ အသိပညာအခြေခံကို AND-OR အထူးပြုချက်များအဖြစ် ဖော်ပြထားသော အခြေအနေများသို့ လုပ်ဆောင်မှုများ (အလုပ်လုပ်နေသောမှတ်ဉာဏ်ထဲသို့ ထည့်သွင်းသင့်သော အချက်အလက်အသစ်များ) ကို မြေပုံဆွဲပေးသည့် dictionary တစ်ခုအဖြစ် သတ်မှတ်နိုင်သည်။ ထို့အပြင်၊ အချက်အလက်အချို့ကို `Ask`-ed ပြုလုပ်နိုင်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"rules = {\n",
|
||||
" 'default': Ask(['y','n']),\n",
|
||||
" 'color' : Ask(['red-brown','black and white','other']),\n",
|
||||
" 'pattern' : Ask(['dark stripes','dark spots']),\n",
|
||||
" 'mammal': If(OR(['hair','gives milk'])),\n",
|
||||
" 'carnivor': If(OR([AND(['sharp teeth','claws','forward-looking eyes']),'eats meat'])),\n",
|
||||
" 'ungulate': If(['mammal',OR(['has hooves','chews cud'])]),\n",
|
||||
" 'bird': If(OR(['feathers',AND(['flies','lies eggs'])])),\n",
|
||||
" 'animal:monkey' : If(['mammal','carnivor','color:red-brown','pattern:dark spots']),\n",
|
||||
" 'animal:tiger' : If(['mammal','carnivor','color:red-brown','pattern:dark stripes']),\n",
|
||||
" 'animal:giraffe' : If(['ungulate','long neck','long legs','pattern:dark spots']),\n",
|
||||
" 'animal:zebra' : If(['ungulate','pattern:dark stripes']),\n",
|
||||
" 'animal:ostrich' : If(['bird','long nech','color:black and white','cannot fly']),\n",
|
||||
" 'animal:pinguin' : If(['bird','swims','color:black and white','cannot fly']),\n",
|
||||
" 'animal:albatross' : If(['bird','flies well'])\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"နောက်ပြန်သုံးသပ်မှုလုပ်ဆောင်ရန် `Knowledgebase` class ကိုသတ်မှတ်မည်။ ၎င်းတွင်ပါဝင်မည်မှာ:\n",
|
||||
"\n",
|
||||
"* `memory` - attribute များနှင့် value များကို mapping လုပ်ထားသော dictionary\n",
|
||||
"* Knowledgebase `rules` - အထက်တွင်ဖော်ပြထားသည့်ပုံစံအတိုင်း\n",
|
||||
"\n",
|
||||
"အဓိက method နှစ်ခုမှာ:\n",
|
||||
"\n",
|
||||
"* `get` - attribute တစ်ခု၏ value ကိုရယူရန်၊ လိုအပ်ပါက inference လုပ်ဆောင်မည်။ ဥပမာအားဖြင့် `get('color')` သည် color slot ၏ value ကိုရယူမည် (လိုအပ်ပါကမေးမြန်းပြီး၊ နောက်ပိုင်းအသုံးပြုရန် working memory တွင် value ကိုသိမ်းဆည်းမည်)။ `get('color:blue')` ကိုမေးမြန်းပါက color ကိုမေးမြန်းပြီး၊ color အပေါ်မူတည်၍ `y`/`n` value ကိုပြန်ပေးမည်။\n",
|
||||
"* `eval` - အမှန်တကယ်သော inference ကိုလုပ်ဆောင်မည်၊ AND/OR tree ကိုဖြတ်သန်းပြီး sub-goals များကိုအကဲဖြတ်မည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class KnowledgeBase():\n",
|
||||
" def __init__(self,rules):\n",
|
||||
" self.rules = rules\n",
|
||||
" self.memory = {}\n",
|
||||
" \n",
|
||||
" def get(self,name):\n",
|
||||
" if ':' in name:\n",
|
||||
" k,v = name.split(':')\n",
|
||||
" vv = self.get(k)\n",
|
||||
" return 'y' if v==vv else 'n'\n",
|
||||
" if name in self.memory.keys():\n",
|
||||
" return self.memory[name]\n",
|
||||
" for fld in self.rules.keys():\n",
|
||||
" if fld==name or fld.startswith(name+\":\"):\n",
|
||||
" # print(\" + proving {}\".format(fld))\n",
|
||||
" value = 'y' if fld==name else fld.split(':')[1]\n",
|
||||
" res = self.eval(self.rules[fld],field=name)\n",
|
||||
" if res!='y' and res!='n' and value=='y':\n",
|
||||
" self.memory[name] = res\n",
|
||||
" return res\n",
|
||||
" if res=='y':\n",
|
||||
" self.memory[name] = value\n",
|
||||
" return value\n",
|
||||
" # field is not found, using default\n",
|
||||
" res = self.eval(self.rules['default'],field=name)\n",
|
||||
" self.memory[name]=res\n",
|
||||
" return res\n",
|
||||
" \n",
|
||||
" def eval(self,expr,field=None):\n",
|
||||
" # print(\" + eval {}\".format(expr))\n",
|
||||
" if isinstance(expr,Ask):\n",
|
||||
" print(field)\n",
|
||||
" return expr.ask()\n",
|
||||
" elif isinstance(expr,If):\n",
|
||||
" return self.eval(expr.x)\n",
|
||||
" elif isinstance(expr,AND) or isinstance(expr,list):\n",
|
||||
" expr = expr.x if isinstance(expr,AND) else expr\n",
|
||||
" for x in expr:\n",
|
||||
" if self.eval(x)=='n':\n",
|
||||
" return 'n'\n",
|
||||
" return 'y'\n",
|
||||
" elif isinstance(expr,OR):\n",
|
||||
" for x in expr.x:\n",
|
||||
" if self.eval(x)=='y':\n",
|
||||
" return 'y'\n",
|
||||
" return 'n'\n",
|
||||
" elif isinstance(expr,str):\n",
|
||||
" return self.get(expr)\n",
|
||||
" else:\n",
|
||||
" print(\"Unknown expr: {}\".format(expr))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အခုတော့ ကျွန်ုပ်တို့၏ တိရစ္ဆာန် အသိပညာအခြေခံကို သတ်မှတ်ပြီး အကြံပေးမှုကို ဆောင်ရွက်ကြမည်။ ဤခေါ်ဆိုမှုသည် သင့်ကို မေးခွန်းများ မေးမည်ဖြစ်သည်။ ဟုတ်/မဟုတ် မေးခွန်းများအတွက် `y`/`n` ကို ရိုက်ထည့်ခြင်းဖြင့် သင် ဖြေနိုင်ပြီး၊ ရွေးချယ်စရာများ မေးခွန်းများအတွက် (0..N) ကို သတ်မှတ်ခြင်းဖြင့် ဖြေနိုင်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"hair\n",
|
||||
"y/n\n",
|
||||
"sharp teeth\n",
|
||||
"y/n\n",
|
||||
"claws\n",
|
||||
"y/n\n",
|
||||
"forward-looking eyes\n",
|
||||
"y/n\n",
|
||||
"color\n",
|
||||
"0. red-brown\n",
|
||||
"1. black and white\n",
|
||||
"2. other\n",
|
||||
"has hooves\n",
|
||||
"y/n\n",
|
||||
"long neck\n",
|
||||
"y/n\n",
|
||||
"long legs\n",
|
||||
"y/n\n",
|
||||
"pattern\n",
|
||||
"0. dark stripes\n",
|
||||
"1. dark spots\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'giraffe'"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"kb = KnowledgeBase(rules)\n",
|
||||
"kb.get('animal')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## PyKnow ကို အသုံးပြု၍ Forward Inference ပြုလုပ်ခြင်း\n",
|
||||
"\n",
|
||||
"နောက်ထပ် ဥပမာတွင် ကျွန်ုပ်တို့သည် သိမြင်မှုကို ကိုယ်စားပြုရန်အတွက် အသုံးပြုနိုင်သော စာကြောင်းများထဲမှ တစ်ခုဖြစ်သည့် [PyKnow](https://github.com/buguroo/pyknow/) ကို အသုံးပြု၍ forward inference ကို အကောင်အထည်ဖော်ကြည့်မည်ဖြစ်သည်။ **PyKnow** သည် Python တွင် forward inference system များ ဖန်တီးရန်အတွက် အသုံးပြုနိုင်သော စာကြောင်းတစ်ခုဖြစ်ပြီး၊ ရှေးဟောင်းစနစ် [CLIPS](http://www.clipsrules.net/index.html) နှင့် ဆင်တူစေရန် ဒီဇိုင်းထုတ်ထားသည်။\n",
|
||||
"\n",
|
||||
"ကျွန်ုပ်တို့သည် forward chaining ကို ကိုယ်တိုင်လည်း အလွယ်တကူ အကောင်အထည်ဖော်နိုင်မည်ဖြစ်သော်လည်း၊ ရိုးရိုးရှင်းရှင်း အကောင်အထည်ဖော်မှုများသည် အများအားဖြင့် ထိရောက်မှုမရှိလှပါ။ စည်းမျဉ်းများကို ထိရောက်စွာ ကိုက်ညီစေရန်အတွက် အထူး algorithm တစ်ခုဖြစ်သည့် [Rete](https://en.wikipedia.org/wiki/Rete_algorithm) ကို အသုံးပြုသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Collecting git+https://github.com/buguroo/pyknow/\n",
|
||||
" Cloning https://github.com/buguroo/pyknow/ to /tmp/pip-req-build-3cqeulyl\n",
|
||||
" Running command git clone --filter=blob:none --quiet https://github.com/buguroo/pyknow/ /tmp/pip-req-build-3cqeulyl\n",
|
||||
" Resolved https://github.com/buguroo/pyknow/ to commit 48818336f2e9a126f1964f2d8dc22d37ff800fe8\n",
|
||||
" Preparing metadata (setup.py) ... \u001b[?25ldone\n",
|
||||
"\u001b[?25hCollecting frozendict==1.2\n",
|
||||
" Using cached frozendict-1.2.tar.gz (2.6 kB)\n",
|
||||
" Preparing metadata (setup.py) ... \u001b[?25ldone\n",
|
||||
"\u001b[?25hCollecting schema==0.6.7\n",
|
||||
" Using cached schema-0.6.7-py2.py3-none-any.whl (14 kB)\n",
|
||||
"Building wheels for collected packages: pyknow, frozendict\n",
|
||||
" Building wheel for pyknow (setup.py) ... \u001b[?25ldone\n",
|
||||
"\u001b[?25h Created wheel for pyknow: filename=pyknow-1.7.0-py3-none-any.whl size=34228 sha256=b7de5b09292c4007667c72f69b98d5a1b5f7324ff15f9dd8e077c3d5f7aade42\n",
|
||||
" Stored in directory: /tmp/pip-ephem-wheel-cache-k7jpave7/wheels/81/1a/d3/f6c15dbe1955598a37755215f2a10449e7418500d7bd4b9508\n",
|
||||
" Building wheel for frozendict (setup.py) ... \u001b[?25ldone\n",
|
||||
"\u001b[?25h Created wheel for frozendict: filename=frozendict-1.2-py3-none-any.whl size=3148 sha256=2863d55c240d2409cddf05ccfe600591f8478681549fc97555c47c90dc6bb160\n",
|
||||
" Stored in directory: /home/rg/.cache/pip/wheels/49/ac/f8/cb8120244e710bdb479c86198b03c7b08c3c2d3d2bf448fd6e\n",
|
||||
"Successfully built pyknow frozendict\n",
|
||||
"Installing collected packages: schema, frozendict, pyknow\n",
|
||||
"Successfully installed frozendict-1.2 pyknow-1.7.0 schema-0.6.7\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import sys\n",
|
||||
"!{sys.executable} -m pip install git+https://github.com/buguroo/pyknow/"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from pyknow import *\n",
|
||||
"#import pyknow"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့၏စနစ်ကို `KnowledgeEngine` ကိုအခြေခံသော class အဖြစ်သတ်မှတ်ပါမည်။ Rule တစ်ခုစီကို `@Rule` အမှတ်အသားဖြင့်သတ်မှတ်ထားသော function တစ်ခုစီဖြင့်သတ်မှတ်ပါမည်၊ အဲဒီ Rule သည်မည်သည့်အချိန်တွင်အလုပ်လုပ်သင့်သည်ကိုသတ်မှတ်ပေးပါသည်။ Rule အတွင်းတွင် `declare` function ကိုအသုံးပြု၍ fact အသစ်များထည့်သွင်းနိုင်ပြီး၊ အဲဒီ fact များကိုထည့်သွင်းခြင်းဖြင့် forward inference engine မှတစ်ဆင့် Rule များအပိုဆောင်းခေါ်ယူခြင်းဖြစ်ပေါ်စေပါမည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class Animals(KnowledgeEngine):\n",
|
||||
" @Rule(OR(\n",
|
||||
" AND(Fact('sharp teeth'),Fact('claws'),Fact('forward looking eyes')),\n",
|
||||
" Fact('eats meat')))\n",
|
||||
" def cornivor(self):\n",
|
||||
" self.declare(Fact('carnivor'))\n",
|
||||
" \n",
|
||||
" @Rule(OR(Fact('hair'),Fact('gives milk')))\n",
|
||||
" def mammal(self):\n",
|
||||
" self.declare(Fact('mammal'))\n",
|
||||
"\n",
|
||||
" @Rule(Fact('mammal'),\n",
|
||||
" OR(Fact('has hooves'),Fact('chews cud')))\n",
|
||||
" def hooves(self):\n",
|
||||
" self.declare('ungulate')\n",
|
||||
" \n",
|
||||
" @Rule(OR(Fact('feathers'),AND(Fact('flies'),Fact('lays eggs'))))\n",
|
||||
" def bird(self):\n",
|
||||
" self.declare('bird')\n",
|
||||
" \n",
|
||||
" @Rule(Fact('mammal'),Fact('carnivor'),\n",
|
||||
" Fact(color='red-brown'),\n",
|
||||
" Fact(pattern='dark spots'))\n",
|
||||
" def monkey(self):\n",
|
||||
" self.declare(Fact(animal='monkey'))\n",
|
||||
"\n",
|
||||
" @Rule(Fact('mammal'),Fact('carnivor'),\n",
|
||||
" Fact(color='red-brown'),\n",
|
||||
" Fact(pattern='dark stripes'))\n",
|
||||
" def tiger(self):\n",
|
||||
" self.declare(Fact(animal='tiger'))\n",
|
||||
"\n",
|
||||
" @Rule(Fact('ungulate'),\n",
|
||||
" Fact('long neck'),\n",
|
||||
" Fact('long legs'),\n",
|
||||
" Fact(pattern='dark spots'))\n",
|
||||
" def giraffe(self):\n",
|
||||
" self.declare(Fact(animal='giraffe'))\n",
|
||||
"\n",
|
||||
" @Rule(Fact('ungulate'),\n",
|
||||
" Fact(pattern='dark stripes'))\n",
|
||||
" def zebra(self):\n",
|
||||
" self.declare(Fact(animal='zebra'))\n",
|
||||
"\n",
|
||||
" @Rule(Fact('bird'),\n",
|
||||
" Fact('long neck'),\n",
|
||||
" Fact('cannot fly'),\n",
|
||||
" Fact(color='black and white'))\n",
|
||||
" def straus(self):\n",
|
||||
" self.declare(Fact(animal='ostrich'))\n",
|
||||
"\n",
|
||||
" @Rule(Fact('bird'),\n",
|
||||
" Fact('swims'),\n",
|
||||
" Fact('cannot fly'),\n",
|
||||
" Fact(color='black and white'))\n",
|
||||
" def pinguin(self):\n",
|
||||
" self.declare(Fact(animal='pinguin'))\n",
|
||||
"\n",
|
||||
" @Rule(Fact('bird'),\n",
|
||||
" Fact('flies well'))\n",
|
||||
" def albatros(self):\n",
|
||||
" self.declare(Fact(animal='albatross'))\n",
|
||||
" \n",
|
||||
" @Rule(Fact(animal=MATCH.a))\n",
|
||||
" def print_result(self,a):\n",
|
||||
" print('Animal is {}'.format(a))\n",
|
||||
" \n",
|
||||
" def factz(self,l):\n",
|
||||
" for x in l:\n",
|
||||
" self.declare(x)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့သည် အသိပညာအခြေခံကို သတ်မှတ်ပြီးပါက အစောပိုင်းအချက်အလက်များဖြင့် အလုပ်လုပ်မိသားစုကို ဖြည့်ဆည်းပြီးနောက် `run()` နည်းလမ်းကို ခေါ်ဆို၍ သုံးသပ်မှုကို ဆောင်ရွက်ပါသည်။ အကျိုးအဖြစ် အသစ်ထွက်ရှိသော အချက်အလက်များကို အလုပ်လုပ်မိသားစုတွင် ထည့်သွင်းထားသည်ကို တွေ့နိုင်ပြီး (အစောပိုင်းအချက်အလက်များကို မှန်ကန်စွာ သတ်မှတ်ထားပါက) တိရစ္ဆာန်နှင့်ဆိုင်သော နောက်ဆုံးအချက်အလက်ကိုလည်း ပါဝင်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Animal is tiger\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"FactList([(0, InitialFact()),\n",
|
||||
" (1, Fact(color='red-brown')),\n",
|
||||
" (2, Fact(pattern='dark stripes')),\n",
|
||||
" (3, Fact('sharp teeth')),\n",
|
||||
" (4, Fact('claws')),\n",
|
||||
" (5, Fact('forward looking eyes')),\n",
|
||||
" (6, Fact('gives milk')),\n",
|
||||
" (7, Fact('mammal')),\n",
|
||||
" (8, Fact('carnivor')),\n",
|
||||
" (9, Fact(animal='tiger'))])"
|
||||
]
|
||||
},
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"ex1 = Animals()\n",
|
||||
"ex1.reset()\n",
|
||||
"ex1.factz([\n",
|
||||
" Fact(color='red-brown'),\n",
|
||||
" Fact(pattern='dark stripes'),\n",
|
||||
" Fact('sharp teeth'),\n",
|
||||
" Fact('claws'),\n",
|
||||
" Fact('forward looking eyes'),\n",
|
||||
" Fact('gives milk')])\n",
|
||||
"ex1.run()\n",
|
||||
"ex1.facts"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်မှုများတွင် အမှားများ သို့မဟုတ် မမှန်ကန်မှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာတရ အရင်းအမြစ်အဖြစ် ရှုလေ့လာသင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူက ဘာသာပြန်မှု ဝန်ဆောင်မှုကို အကြံပြုပါသည်။ ဤဘာသာပြန်မှုကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားလွဲမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.7.4 64-bit (conda)",
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
|
||||
}
|
||||
},
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.11.2"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "ab2bd97b0453415b89a469284609a8ce",
|
||||
"translation_date": "2025-08-30T09:42:22+00:00",
|
||||
"source_file": "lessons/2-Symbolic/Animals.ipynb",
|
||||
"language_code": "my"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,593 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"source": [
|
||||
"# မိသားစုဆက်နွယ်မှု Ontology\n",
|
||||
"\n",
|
||||
"ဤဥပမာသည် [AI for Beginners Curriculum](http://github.com/microsoft/ai-for-beginners) ၏ အစိတ်အပိုင်းတစ်ခုဖြစ်ပြီး၊ [ဤဘလော့ဂ်ပို့စ်](https://habr.com/post/270857/) မှ အကြောင်းအရာများကို အခြေခံ၍ ဖန်တီးထားပါသည်။\n",
|
||||
"\n",
|
||||
"မိသားစုတွင် လူများ၏ ဆက်နွယ်မှုများကို မှတ်မိရန် အခက်အခဲရှိတတ်သည်ဟု အမြဲခံစားရသည်။ ဤဥပမာတွင် မိသားစုဆက်နွယ်မှုများကို သတ်မှတ်ထားသော ontology နှင့် အမှန်တကယ်သော မျိုးရိုးခွဲခြားပုံစံကို ယူပြီး၊ အလိုအလျောက် အနီးစပ်ဆုံး ဆွေမျိုးများကို ရှာဖွေနိုင်ရန် အတတ်နိုင်ဆုံး inference ကို ပြသမည်ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"### မျိုးရိုးခွဲခြားပုံစံ ရယူခြင်း\n",
|
||||
"\n",
|
||||
"ဥပမာအနေနှင့် [Romanov Tsar Family](https://en.wikipedia.org/wiki/House_of_Romanov) ၏ မျိုးရိုးခွဲခြားပုံစံကို ယူပါမည်။ မိသားစုဆက်နွယ်မှုများကို ဖော်ပြရန် အများဆုံး အသုံးပြုသော ပုံစံမှာ [GEDCOM](https://en.wikipedia.org/wiki/GEDCOM) ဖြစ်သည်။ GEDCOM ပုံစံဖြင့် Romanov မိသားစု၏ မျိုးရိုးခွဲခြားပုံစံကို ယူပါမည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0 HEAD\n",
|
||||
"1 CHAR UTF8\n",
|
||||
"1 GEDC\n",
|
||||
"2 VERS 5.5\n",
|
||||
"0 @0@ INDI\n",
|
||||
"1 NAME Mihail Fedorovich /Romanov/\n",
|
||||
"1 SEX M\n",
|
||||
"1 BIRT\n",
|
||||
"2 DATE 1613\n",
|
||||
"1 DEAT \n",
|
||||
"2 DATE 1645\n",
|
||||
"1 FAMS @41@\n",
|
||||
"0 @1@ INDI\n",
|
||||
"1 NAME Evdokija Lukjanovna /Streshneva/\n",
|
||||
"1 SEX F\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"!head -15 data/tsars.ged"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"GEDCOM ဖိုင်ကို အသုံးပြုရန် `python-gedcom` စာကြည့်တိုက်ကို အသုံးပြုနိုင်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Collecting python-gedcom\n",
|
||||
" Downloading python_gedcom-1.0.0-py2.py3-none-any.whl (35 kB)\n",
|
||||
"Installing collected packages: python-gedcom\n",
|
||||
"Successfully installed python-gedcom-1.0.0\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import sys\n",
|
||||
"!{sys.executable} -m pip install python-gedcom"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ဤစာကြည့်တိုက်သည် ဖိုင်ကို အနက်ရှိုင်းစွာ ခွဲခြားရာတွင် ဖြစ်ပေါ်နိုင်သော နည်းပညာဆိုင်ရာ ပြဿနာများကို ဖယ်ရှားပေးသော်လည်း၊ သစ်ပင်အတွင်းရှိ လူများနှင့် မိသားစုများအားလုံးကို အနိမ့်ဆုံးအဆင့်မှ ဝင်ရောက်ကြည့်ရှုနိုင်စေသည်။ ဖိုင်ကို ခွဲခြားပြီး လူများအားလုံး၏ စာရင်းကို ပြသနိုင်ရန် အောက်ပါအတိုင်းလုပ်ဆောင်နိုင်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from gedcom.parser import Parser\n",
|
||||
"from gedcom.element.individual import IndividualElement\n",
|
||||
"from gedcom.element.family import FamilyElement\n",
|
||||
"g = Parser()\n",
|
||||
"g.parse_file('data/tsars.ged')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"scrolled": true,
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[('@0@', ('Mihail Fedorovich', 'Romanov')),\n",
|
||||
" ('@1@', ('Evdokija Lukjanovna', 'Streshneva')),\n",
|
||||
" ('@2@', ('Aleksej Mihajlovich', 'Romanov')),\n",
|
||||
" ('@3@', ('Marija Ilinichna', 'Miloslavskaja')),\n",
|
||||
" ('@4@', ('Natalja Kirillovna', 'Naryshkina')),\n",
|
||||
" ('@5@', ('Marfa Matveevna', 'Apraksina')),\n",
|
||||
" ('@6@', ('Fedor Alekseevich', 'Romanov')),\n",
|
||||
" ('@7@', ('Sofja Aleksevna', 'Romanova')),\n",
|
||||
" ('@8@', ('Ivan V Alekseevich', 'Romanov')),\n",
|
||||
" ('@9@', ('Praskovja Fedorovna', 'Saltykova')),\n",
|
||||
" ('@10@', ('Ekaterina Ivanovna', 'Romanova')),\n",
|
||||
" ('@11@', ('Anna Ivanovna', 'Romanova')),\n",
|
||||
" ('@12@', ('Fridrih Vilgelm', 'Kurlandskij')),\n",
|
||||
" ('@13@', ('Karl Leopold', 'Meklenburg-Shverinskij')),\n",
|
||||
" ('@14@', ('Anna Leopoldovna', 'Meklenburg-Shverinskaja')),\n",
|
||||
" ('@15@', ('Anton Ulrih', 'Braunshvejg-Volfenbjuttelskij')),\n",
|
||||
" ('@16@', ('Ivan VI Antonovich', 'Braunshvejg-Volfenbjuttelskij')),\n",
|
||||
" ('@17@', ('Petr I Alekseevich', 'Romanov')),\n",
|
||||
" ('@18@', ('Evdokija Fedorovna', 'Lopuhina')),\n",
|
||||
" ('@19@', ('Ekaterina I Alekseevna', 'Mihajlova')),\n",
|
||||
" ('@20@', ('Aleksej Petrovich', 'Romanov')),\n",
|
||||
" ('@21@', ('Sharlotta Kristina', 'Braunshvejg-Volfenbjuttelskaja')),\n",
|
||||
" ('@22@', ('Petr II Alekseevich', 'Romanov')),\n",
|
||||
" ('@23@', ('Anna Petrovna', 'Romanova')),\n",
|
||||
" ('@24@', ('Elizaveta Petrovna', 'Romanova')),\n",
|
||||
" ('@25@', ('Karl Fridrih', 'Golshtejn-Gottorpskij')),\n",
|
||||
" ('@26@', ('Petr III Fedorovich', 'Romanov')),\n",
|
||||
" ('@27@', ('Ekaterina II', 'Alekseevna')),\n",
|
||||
" ('@28@', ('Pavel I Petrovich', 'Romanov')),\n",
|
||||
" ('@29@', ('Natalja Alekseevna', 'Gessen-Darmshtadskaja')),\n",
|
||||
" ('@30@', ('Marija Fedorovna', 'Vjurtembergskaja')),\n",
|
||||
" ('@31@', ('Aleksandr I Pavlovich', 'Romanov')),\n",
|
||||
" ('@32@', ('Elizaveta Alekseevna', 'Baden-Durlahskaja')),\n",
|
||||
" ('@33@', ('Nikolaj I Pavlovich', 'Romanov')),\n",
|
||||
" ('@34@', ('Aleksandra Fedorovna', 'Prusskaja')),\n",
|
||||
" ('@35@', ('Aleksandr II Nikolaevich', 'Romanov')),\n",
|
||||
" ('@36@', ('Marija Aleksandrovna', 'Gessenskaja')),\n",
|
||||
" ('@37@', ('Aleksandr III Aleksandrovich', 'Romanov')),\n",
|
||||
" ('@38@', ('Marija Fedorovna', 'Datskaja')),\n",
|
||||
" ('@39@', ('Nikolaj II Aleksandrovich', 'Romanov')),\n",
|
||||
" ('@40@', ('Aleksandra Fedorovna', 'Gessenskaja'))]"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"d = g.get_element_dictionary()\n",
|
||||
"[ (k,v.get_name()) for k,v in d.items() if isinstance(v,IndividualElement)]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"မိသားစုများအကြောင်းအချက်အလက်ကို ရယူနိုင်မည့်နည်းလမ်းမှာ ဒီလိုပါ။ ဂရုစိုက်ရန်မှာ **အထောက်အထားများ** စာရင်းကိုပေးသော်လည်း၊ ပိုမိုရှင်းလင်းမှုရရှိစေရန် အမည်များသို့ ပြောင်းလဲရန် လိုအပ်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[('@41@', ['@0@', '@1@', '@2@']),\n",
|
||||
" ('@42@', ['@2@', '@3@', '@6@', '@7@', '@8@']),\n",
|
||||
" ('@43@', ['@8@', '@9@', '@10@', '@11@']),\n",
|
||||
" ('@44@', ['@13@', '@10@', '@14@']),\n",
|
||||
" ('@45@', ['@15@', '@14@', '@16@']),\n",
|
||||
" ('@46@', ['@2@', '@4@', '@17@']),\n",
|
||||
" ('@47@', ['@17@', '@18@', '@20@']),\n",
|
||||
" ('@48@', ['@20@', '@21@', '@22@']),\n",
|
||||
" ('@49@', ['@17@', '@19@', '@23@', '@24@']),\n",
|
||||
" ('@50@', ['@25@', '@23@', '@26@']),\n",
|
||||
" ('@51@', ['@26@', '@27@', '@28@']),\n",
|
||||
" ('@52@', ['@28@', '@30@', '@31@', '@33@']),\n",
|
||||
" ('@53@', ['@33@', '@34@', '@35@']),\n",
|
||||
" ('@54@', ['@35@', '@36@', '@37@']),\n",
|
||||
" ('@55@', ['@37@', '@38@', '@39@'])]"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"d = g.get_element_dictionary()\n",
|
||||
"[ (k,[x.get_value() for x in v.get_child_elements()]) for k,v in d.items() if isinstance(v,FamilyElement)]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### မိသားစု Ontology ရယူခြင်း\n",
|
||||
"\n",
|
||||
"အခုတော့ [မိသားစု ontology](https://raw.githubusercontent.com/blokhin/genealogical-trees/master/data/header.ttl) ကို Semantic Web triplets အနေနဲ့ သတ်မှတ်ထားတဲ့အတိုင်း ကြည့်လိုက်ရအောင်။ ဒီ ontology မှာ `isUncleOf`, `isCousinOf` စတဲ့ ဆက်နွယ်မှုတွေကို သတ်မှတ်ထားပြီး အခြားအများကြီးလည်း ပါဝင်ပါတယ်။ အဲဒီဆက်နွယ်မှုတွေကို `isMotherOf`, `isFatherOf`, `isBrotherOf` နဲ့ `isSisterOf` ဆိုတဲ့ အခြေခံ predicates တွေကို အခြေခံပြီး သတ်မှတ်ထားပါတယ်။ အဲဒီ ontology ကို အသုံးပြုပြီး အခြားဆက်နွယ်မှုအားလုံးကို အလိုအလျောက် reasoning နဲ့ ထုတ်ယူသွားမှာ ဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"ဒီမှာ `isAuntOf` property ရဲ့ နမူနာ သတ်မှတ်ချက်ကို ဖော်ပြထားပါတယ်။ ဒါဟာ `isSisterOf` နဲ့ `isParentOf` ရဲ့ composition အနေနဲ့ သတ်မှတ်ထားတာဖြစ်ပါတယ် (*အဒေါ်ဆိုတာ မိဘရဲ့ ညီမ ဖြစ်ပါတယ်*)။\n",
|
||||
"\n",
|
||||
"```\n",
|
||||
"fhkb:isAuntOf a owl:ObjectProperty ;\n",
|
||||
" rdfs:domain fhkb:Woman ;\n",
|
||||
" rdfs:range fhkb:Person ;\n",
|
||||
" owl:propertyChainAxiom ( fhkb:isSisterOf fhkb:isParentOf ) .\n",
|
||||
"```\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"@prefix fhkb: <http://www.example.com/genealogy.owl#> .\n",
|
||||
"@prefix owl: <http://www.w3.org/2002/07/owl#> .\n",
|
||||
"@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n",
|
||||
"@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n",
|
||||
"@prefix xml: <http://www.w3.org/XML/1998/namespace> .\n",
|
||||
"@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n",
|
||||
"\n",
|
||||
"<http://www.example.com/genealogy.owl#> a owl:Ontology .\n",
|
||||
"\n",
|
||||
"fhkb:DomainEntity a owl:Class .\n",
|
||||
"\n",
|
||||
"fhkb:Man a owl:Class ;\n",
|
||||
" owl:equivalentClass [ a owl:Class ;\n",
|
||||
" owl:intersectionOf ( fhkb:Person [ a owl:Restriction ;\n",
|
||||
" owl:onProperty fhkb:hasSex ;\n",
|
||||
" owl:someValuesFrom fhkb:Male ] ) ] .\n",
|
||||
"\n",
|
||||
"fhkb:Woman a owl:Class ;\n",
|
||||
" owl:equivalentClass [ a owl:Class ;\n",
|
||||
" owl:intersectionOf ( fhkb:Person [ a owl:Restriction ;\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"!head -20 data/onto.ttl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### အတိအကျကို ချမှတ်ရန် Ontology တည်ဆောက်ခြင်း\n",
|
||||
"\n",
|
||||
"ရိုးရှင်းစွာဖြင့်၊ မိသားစု ontology မှ မူရင်းစည်းကမ်းများနှင့် GEDCOM ဖိုင်မှ တစ်ဦးချင်းအကြောင်းအရာများပါဝင်သော ontology ဖိုင်တစ်ခုကို ဖန်တီးမည်ဖြစ်သည်။ GEDCOM ဖိုင်ကို ကျော်လွှားပြီး မိသားစုများနှင့် တစ်ဦးချင်းများအကြောင်းအရာကို ထုတ်ယူကာ၊ triple အဖြစ်သို့ ပြောင်းလဲမည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!cp data/onto.ttl .\n",
|
||||
"\n",
|
||||
"gedcom_dict = g.get_element_dictionary()\n",
|
||||
"individuals, marriages = {}, {}\n",
|
||||
"\n",
|
||||
"def term2id(el):\n",
|
||||
" return \"i\" + el.get_pointer().replace('@', '').lower()\n",
|
||||
"\n",
|
||||
"out = open(\"onto.ttl\",\"a\")\n",
|
||||
"\n",
|
||||
"for k, v in gedcom_dict.items():\n",
|
||||
" if isinstance(v,IndividualElement):\n",
|
||||
" children, siblings = set(), set()\n",
|
||||
" idx = term2id(v)\n",
|
||||
"\n",
|
||||
" title = v.get_name()[0] + \" \" + v.get_name()[1]\n",
|
||||
" title = title.replace('\"', '').replace('[', '').replace(']', '').replace('(', '').replace(')', '').strip()\n",
|
||||
"\n",
|
||||
" own_families = g.get_families(v, 'FAMS')\n",
|
||||
" for fam in own_families:\n",
|
||||
" children |= set(term2id(i) for i in g.get_family_members(fam, \"CHIL\"))\n",
|
||||
"\n",
|
||||
" parent_families = g.get_families(v, 'FAMC')\n",
|
||||
" if len(parent_families):\n",
|
||||
" for member in g.get_family_members(parent_families[0], \"CHIL\"): # NB adoptive families i.e len(parent_families)>1 are not considered (TODO?)\n",
|
||||
" if member.get_pointer() == v.get_pointer():\n",
|
||||
" continue\n",
|
||||
" siblings.add(term2id(member))\n",
|
||||
"\n",
|
||||
" if idx in individuals:\n",
|
||||
" children |= individuals[idx].get('children', set())\n",
|
||||
" siblings |= individuals[idx].get('siblings', set())\n",
|
||||
" individuals[idx] = {'sex': v.get_gender().lower(), 'children': children, 'siblings': siblings, 'title': title}\n",
|
||||
"\n",
|
||||
" elif isinstance(v,FamilyElement):\n",
|
||||
" wife, husb, children = None, None, set()\n",
|
||||
" children = set(term2id(i) for i in g.get_family_members(v, \"CHIL\"))\n",
|
||||
"\n",
|
||||
" try:\n",
|
||||
" wife = g.get_family_members(v, \"WIFE\")[0]\n",
|
||||
" wife = term2id(wife)\n",
|
||||
" if wife in individuals: individuals[wife]['children'] |= children\n",
|
||||
" else: individuals[wife] = {'children': children}\n",
|
||||
" except IndexError: pass\n",
|
||||
" try:\n",
|
||||
" husb = g.get_family_members(v, \"HUSB\")[0]\n",
|
||||
" husb = term2id(husb)\n",
|
||||
" if husb in individuals: individuals[husb]['children'] |= children\n",
|
||||
" else: individuals[husb] = {'children': children}\n",
|
||||
" except IndexError: pass\n",
|
||||
"\n",
|
||||
" if wife and husb: marriages[wife + husb] = (term2id(v), wife, husb)\n",
|
||||
"\n",
|
||||
"for idx, val in individuals.items():\n",
|
||||
" added_terms = ''\n",
|
||||
" if val['sex'] == 'f':\n",
|
||||
" parent_predicate, sibl_predicate = \"isMotherOf\", \"isSisterOf\"\n",
|
||||
" else:\n",
|
||||
" parent_predicate, sibl_predicate = \"isFatherOf\", \"isBrotherOf\"\n",
|
||||
" if len(val['children']):\n",
|
||||
" added_terms += \" ;\\n fhkb:\" + parent_predicate + \" \" + \", \".join([\"fhkb:\" + i for i in val['children']])\n",
|
||||
" if len(val['siblings']):\n",
|
||||
" added_terms += \" ;\\n fhkb:\" + sibl_predicate + \" \" + \", \".join([\"fhkb:\" + i for i in val['siblings']])\n",
|
||||
" out.write(\"fhkb:%s a owl:NamedIndividual, owl:Thing%s ;\\n rdfs:label \\\"%s\\\" .\\n\" % (idx, added_terms, val['title']))\n",
|
||||
"\n",
|
||||
"for k, v in marriages.items():\n",
|
||||
" out.write(\"fhkb:%s a owl:NamedIndividual, owl:Thing ;\\n fhkb:hasFemalePartner fhkb:%s ;\\n fhkb:hasMalePartner fhkb:%s .\\n\" % v)\n",
|
||||
"\n",
|
||||
"out.write(\"[] a owl:AllDifferent ;\\n owl:distinctMembers (\")\n",
|
||||
"for idx in individuals.keys():\n",
|
||||
" out.write(\" fhkb:\" + idx)\n",
|
||||
"for k, v in marriages.items():\n",
|
||||
" out.write(\" fhkb:\" + v[0])\n",
|
||||
"out.write(\" ) .\")\n",
|
||||
"out.close()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
" fhkb:hasFemalePartner fhkb:i34 ;\n",
|
||||
" fhkb:hasMalePartner fhkb:i33 .\n",
|
||||
"fhkb:i54 a owl:NamedIndividual, owl:Thing ;\n",
|
||||
" fhkb:hasFemalePartner fhkb:i36 ;\n",
|
||||
" fhkb:hasMalePartner fhkb:i35 .\n",
|
||||
"fhkb:i55 a owl:NamedIndividual, owl:Thing ;\n",
|
||||
" fhkb:hasFemalePartner fhkb:i38 ;\n",
|
||||
" fhkb:hasMalePartner fhkb:i37 .\n",
|
||||
"[] a owl:AllDifferent ;\n",
|
||||
" owl:distinctMembers ( fhkb:i0 fhkb:i1 fhkb:i2 fhkb:i3 fhkb:i4 fhkb:i5 fhkb:i6 fhkb:i7 fhkb:i8 fhkb:i9 fhkb:i10 fhkb:i11 fhkb:i12 fhkb:i13 fhkb:i14 fhkb:i15 fhkb:i16 fhkb:i17 fhkb:i18 fhkb:i19 fhkb:i20 fhkb:i21 fhkb:i22 fhkb:i23 fhkb:i24 fhkb:i25 fhkb:i26 fhkb:i27 fhkb:i28 fhkb:i29 fhkb:i30 fhkb:i31 fhkb:i32 fhkb:i33 fhkb:i34 fhkb:i35 fhkb:i36 fhkb:i37 fhkb:i38 fhkb:i39 fhkb:i40 fhkb:i41 fhkb:i42 fhkb:i43 fhkb:i44 fhkb:i45 fhkb:i46 fhkb:i47 fhkb:i48 fhkb:i49 fhkb:i50 fhkb:i51 fhkb:i52 fhkb:i53 fhkb:i54 fhkb:i55 ) ."
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"!tail onto.ttl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### အတည်ပြုမှုလုပ်ခြင်း\n",
|
||||
"\n",
|
||||
"အခုတော့ ဒီ ontology ကို အတည်ပြုမှုလုပ်ခြင်းနှင့် မေးမြန်းမှုများအတွက် အသုံးပြုနိုင်ဖို့လိုပါတယ်။ [RDFLib](https://github.com/RDFLib) ကို အသုံးပြုမယ်၊ ဒါဟာ RDF Graph ကို အမျိုးမျိုးသော ဖော်မတ်များတွင် ဖတ်ရှုခြင်း၊ မေးမြန်းခြင်း စသည်တို့အတွက် အသုံးပြုနိုင်တဲ့ library ဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"Logical inference အတွက် [OWL-RL](https://github.com/RDFLib/OWL-RL) library ကို အသုံးပြုမယ်၊ ဒါဟာ RDF Graph ရဲ့ **Closure** ကို တည်ဆောက်နိုင်စေပြီး၊ အတည်ပြုနိုင်တဲ့ အကြောင်းအရာများနှင့် ဆက်နွယ်မှုများအားလုံးကို ထည့်သွင်းပေးနိုင်ပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Requirement already satisfied: rdflib in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (6.3.2)\n",
|
||||
"Requirement already satisfied: isodate<0.7.0,>=0.6.0 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from rdflib) (0.6.1)\n",
|
||||
"Requirement already satisfied: pyparsing<4,>=2.1.0 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from rdflib) (3.0.9)\n",
|
||||
"Requirement already satisfied: six in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from isodate<0.7.0,>=0.6.0->rdflib) (1.16.0)\n",
|
||||
"Collecting git+https://github.com/RDFLib/OWL-RL.git\n",
|
||||
" Cloning https://github.com/RDFLib/OWL-RL.git to /tmp/pip-req-build-lbfzwi3m\n",
|
||||
" Running command git clone --filter=blob:none --quiet https://github.com/RDFLib/OWL-RL.git /tmp/pip-req-build-lbfzwi3m\n",
|
||||
" Resolved https://github.com/RDFLib/OWL-RL.git to commit a77e1791b88b54aace609bc6000aac14c7add4ff\n",
|
||||
" Preparing metadata (setup.py) ... \u001b[?25ldone\n",
|
||||
"\u001b[?25hRequirement already satisfied: rdflib>=6.0.2 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from owlrl==6.0.2) (6.3.2)\n",
|
||||
"Requirement already satisfied: isodate<0.7.0,>=0.6.0 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from rdflib>=6.0.2->owlrl==6.0.2) (0.6.1)\n",
|
||||
"Requirement already satisfied: pyparsing<4,>=2.1.0 in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from rdflib>=6.0.2->owlrl==6.0.2) (3.0.9)\n",
|
||||
"Requirement already satisfied: six in /home/rg/anaconda3/envs/ai4beg/lib/python3.11/site-packages (from isodate<0.7.0,>=0.6.0->rdflib>=6.0.2->owlrl==6.0.2) (1.16.0)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"!{sys.executable} -m pip install rdflib\n",
|
||||
"!{sys.executable} -m pip install git+https://github.com/RDFLib/OWL-RL.git"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အွန်တိုလိုဂျီဖိုင်ကိုဖွင့်ပြီး၊ အဲဒီမှာရှိတဲ့ထရီပလက်များရဲ့အရေအတွက်ကိုကြည့်ကြမယ်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Triplets found:669\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import rdflib\n",
|
||||
"from owlrl import DeductiveClosure, OWLRL_Extension\n",
|
||||
"\n",
|
||||
"g = rdflib.Graph()\n",
|
||||
"g.parse(\"onto.ttl\", format=\"turtle\")\n",
|
||||
"\n",
|
||||
"print(\"Triplets found:%d\" % len(g))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Triplets after inference:4246\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"DeductiveClosure(OWLRL_Extension).expand(g)\n",
|
||||
"print(\"Triplets after inference:%d\" % len(g))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### ဆွေမျိုးများကို ရှာဖွေခြင်း\n",
|
||||
"\n",
|
||||
"အခုတော့ လူများအကြား ဆွေမျိုးဆက်နွယ်မှုများကို ကြည့်ရှုနိုင်ရန် graph ကို query လုပ်နိုင်ပါပြီ။ **SPARQL** ဘာသာစကားကို `query` method နဲ့ တွဲဖက်အသုံးပြုနိုင်ပါတယ်။ ကျွန်တော်တို့ရဲ့ အခန်းကဏ္ဍမှာတော့ မိသားစုအပင်ထဲမှာရှိတဲ့ **အကို/အမောင်များ**အားလုံးကို ကြည့်ရှုလိုက်ရအောင်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Fedor Alekseevich Romanov is uncle of Ekaterina Ivanovna Romanova\n",
|
||||
"Aleksandr I Pavlovich Romanov is uncle of Aleksandr II Nikolaevich Romanov\n",
|
||||
"Fedor Alekseevich Romanov is uncle of Anna Ivanovna Romanova\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"qres = g.query(\n",
|
||||
" \"\"\"SELECT DISTINCT ?aname ?bname\n",
|
||||
" WHERE {\n",
|
||||
" ?a fhkb:isUncleOf ?b .\n",
|
||||
" ?a rdfs:label ?aname .\n",
|
||||
" ?b rdfs:label ?bname .\n",
|
||||
" }\"\"\")\n",
|
||||
"\n",
|
||||
"for row in qres:\n",
|
||||
" print(\"%s is uncle of %s\" % row)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အခြားမိသားစုဆက်နွယ်မှုများကို စမ်းသပ်ကြည့်ပါ။ ဥပမာအားဖြင့် `isAncestorOf` ဆက်နွယ်မှုကို ကြည့်ရှုနိုင်ပြီး၊ သတ်မှတ်ထားသောပုဂ္ဂိုလ်တစ်ဦး၏ အဘိုးအဘွားများအားလုံးကို ထပ်တလဲလဲ သတ်မှတ်ပေးသည်။\n",
|
||||
"\n",
|
||||
"နောက်ဆုံးမှာတော့ ရှင်းလင်းမှုလုပ်လိုက်ရအောင်!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!rm onto.ttl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်မှုများတွင် အမှားများ သို့မဟုတ် မမှန်ကန်မှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာတရားရှိသော ရင်းမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူ့ဘာသာပြန်ပညာရှင်များမှ ပရော်ဖက်ရှင်နယ် ဘာသာပြန်မှုကို အကြံပြုပါသည်။ ဤဘာသာပြန်မှုကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားလွဲမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.6",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.11.2"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "6537d5597320e27b6052b4377b8ff8bb",
|
||||
"translation_date": "2025-08-30T09:40:13+00:00",
|
||||
"source_file": "lessons/2-Symbolic/FamilyOntology.ipynb",
|
||||
"language_code": "my"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,548 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"source": [
|
||||
"## Microsoft Concept Graph\n",
|
||||
"\n",
|
||||
"[Microsoft Concept Graph](https://concept.research.microsoft.com/) သည် အင်တာနက်မှ ရှာဖွေထားသော စကားလုံးများ၏ အကြီးစား အမျိုးအစားခွဲခြင်းဖြစ်ပြီး၊ အကြောင်းအရာများအကြား `is-a` ဆက်နွယ်မှုများပါရှိသည်။\n",
|
||||
"\n",
|
||||
"Context Graph ကို အောက်ပါအမျိုးအစားနှစ်မျိုးဖြင့် ရရှိနိုင်ပါသည်။\n",
|
||||
" * ဒေါင်းလုဒ်လုပ်ရန် အကြီးစားစာသားဖိုင်\n",
|
||||
" * REST API\n",
|
||||
"\n",
|
||||
"အချက်အလက်များ:\n",
|
||||
" * 5401933 ထူးခြားသော အကြောင်းအရာများ\n",
|
||||
" * 12551613 ထူးခြားသော နမူနာများ\n",
|
||||
" * 87603947 `is-a` ဆက်နွယ်မှုများ\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## ဝဘ်ဝန်ဆောင်မှုအသုံးပြုခြင်း\n",
|
||||
"\n",
|
||||
"ဝဘ်ဝန်ဆောင်မှုသည် အမျိုးအစားအမျိုးမျိုးတွင် အယူအဆတစ်ခုပါဝင်နိုင်မှု၏ အလားအလာကို ခန့်မှန်းရန် ခေါ်ဆိုမှုများကို ပေးသည်။ အချက်အလက်များကို [ဒီမှာ](https://concept.research.microsoft.com/Home/Api) တွေ့နိုင်ပါသည်။\n",
|
||||
"ဤသည်မှာ ခေါ်ဆိုရန် နမူနာ URL ဖြစ်သည် - `https://concept.research.microsoft.com/api/Concept/ScoreByProb?instance=microsoft&topK=10`\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'company': 0.6105356614382954,\n",
|
||||
" 'vendor': 0.08858636677518003,\n",
|
||||
" 'client': 0.048239124001183784,\n",
|
||||
" 'firm': 0.045476965571668145,\n",
|
||||
" 'large company': 0.043109401203511886,\n",
|
||||
" 'organization': 0.043010752688172046,\n",
|
||||
" 'corporation': 0.035908059583703265,\n",
|
||||
" 'brand': 0.03383644076156654,\n",
|
||||
" 'software company': 0.027522935779816515,\n",
|
||||
" 'technology company': 0.023774292196902438}"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import urllib\n",
|
||||
"import json\n",
|
||||
"import ssl\n",
|
||||
"\n",
|
||||
"def http(x):\n",
|
||||
" ssl._create_default_https_context = ssl._create_unverified_context\n",
|
||||
" response = urllib.request.urlopen(x)\n",
|
||||
" data = response.read()\n",
|
||||
" return data.decode('utf-8')\n",
|
||||
"\n",
|
||||
"def query(x):\n",
|
||||
" return json.loads(http(\"https://concept.research.microsoft.com/api/Concept/ScoreByProb?instance={}&topK=10\".format(urllib.parse.quote(x))))\n",
|
||||
"\n",
|
||||
"query('microsoft')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အကြောင်းအရာများကို မိဘအယူအဆများဖြင့် သတင်းခေါင်းစဉ်များကို အမျိုးအစားခွဲကြည့်ရအောင်။ သတင်းခေါင်းစဉ်များရယူရန် [NewsApi.org](http://newsapi.org) ဝန်ဆောင်မှုကို အသုံးပြုမည်ဖြစ်သည်။ ဝန်ဆောင်မှုကို အသုံးပြုရန် သင်၏ကိုယ်ပိုင် API key ရယူရန် လိုအပ်သည် - ဝက်ဘ်ဆိုဒ်သို့ သွားပြီး အခမဲ့ developer plan အတွက် မှတ်ပုံတင်ပါ။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"newsapi_key = '<your API key here>'\n",
|
||||
"def get_news(country='us'):\n",
|
||||
" res = json.loads(http(\"https://newsapi.org/v2/top-headlines?country={0}&apiKey={1}\".format(country,newsapi_key)))\n",
|
||||
" return res['articles']\n",
|
||||
"\n",
|
||||
"all_titles = [x['title'] for x in get_news('us')+get_news('gb')]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"['Covid-19 Live Updates: Vaccines and Boosters News - The New York Times',\n",
|
||||
" 'Ukrainians Flee Mariupol as Russian Forces Push to Take Port City - The Wall Street Journal',\n",
|
||||
" 'Bond Yields Jump, Stock Futures Rise After Powell Says Fed Is Ready to Be More Aggressive - The Wall Street Journal',\n",
|
||||
" 'Putin critic Alexei Navalny found guilty by Russian court - New York Post ',\n",
|
||||
" \"Supreme Court nominee Ketanji Brown Jackson will face questions at confirmation hearing's second day - CNN\",\n",
|
||||
" '2 teachers killed at Swedish high school, student arrested - ABC News',\n",
|
||||
" 'Clues to Covid-19’s Next Moves Come From Sewers - The Wall Street Journal',\n",
|
||||
" 'Republicans to roll dice by grilling Jackson over child-pornography sentencing decisions | TheHill - The Hill',\n",
|
||||
" '‘Clear sign’ Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent',\n",
|
||||
" 'NASA confirms there are 5,000 planets outside our solar system - Daily Mail',\n",
|
||||
" \"US stocks whipsawed overnight after Fed Chair Powell's remarks - Fox Business\",\n",
|
||||
" \"'We've learned absolutely nothing': Tests could again be in short supply if Covid surges - POLITICO\",\n",
|
||||
" \"Duchess of Cambridge swaps khaki jungle gear for Vampire's Wife dress on Belize trip - Daily Mail\",\n",
|
||||
" 'China searches for victims, flight recorders after first plane crash in 12 years - Reuters',\n",
|
||||
" 'Second superyacht linked to Russian oligarch Abramovich docks in Turkey - Reuters',\n",
|
||||
" 'Live updates: Russia stops talks with Japan over sanctions - The Associated Press - en Español',\n",
|
||||
" 'Powers Remain and Threats Lurk as Women’s Sweet 16 Is Set - The New York Times',\n",
|
||||
" 'Webb Space Telescope Begins Multi-Instrument Alignment - SciTechDaily',\n",
|
||||
" \"UConn vs UCF - NCAA women's tournament second-round highlights - March Madness\",\n",
|
||||
" 'Bucking Republican Trend, Indiana Governor Vetoes Transgender Sports Bill - The New York Times',\n",
|
||||
" \"Maggie Fox dead: Coronation Street and Shameless actress dies after 'sudden accident' - Mirror Online - The Mirror\",\n",
|
||||
" 'China plane crash – live: Search for survivors continues as witness describes moment flight fell from sky - The Independent',\n",
|
||||
" 'Daniel Morgan murder: damning report condemns Met police - The Guardian',\n",
|
||||
" 'What to expect from Rishi Sunak’s Spring Statement - BBC.com',\n",
|
||||
" 'UK and Republic of Ireland in line to host Euro 2028 after no one else bids - The Guardian',\n",
|
||||
" \"Friends beg Vladimir Putin's 'lover' to persuade him to end Ukraine invasion - The Mirror\",\n",
|
||||
" 'Brass Eye’s outtakes show the brutal TV comedy was the tip of an iceberg - The Guardian',\n",
|
||||
" \"Vladimir Putin threatens civilians to break Mariupol's spirit - The Times\",\n",
|
||||
" 'Shell U-turn on Cambo oilfield would threaten green targets, say campaigners - The Guardian',\n",
|
||||
" 'St Helens dog attack: Girl aged 17 months killed at home - BBC',\n",
|
||||
" \"PlayStation to buy 'Assassin's Creed' veteran Jade Raymond's Haven Studios - NME\",\n",
|
||||
" '‘Clear sign’ Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent',\n",
|
||||
" 'NASA confirms there are 5,000 planets outside our solar system - Daily Mail',\n",
|
||||
" 'Nintendo Switch finally has folders • Eurogamer.net - Eurogamer.net',\n",
|
||||
" 'FA to “find a solution” as Liverpool fan group blasts “shambolic” Wembley travel - This Is Anfield',\n",
|
||||
" 'Manchester United transfer news LIVE Erik ten Hag latest and Man Utd manager updates - Manchester Evening News',\n",
|
||||
" 'Inflation raises cost of UK government borrowing in February; crude oil up again – business live - The Guardian',\n",
|
||||
" 'Alexei Navalny: Kremlin critic found guilty of large-scale fraud and contempt of court by Russian court - Sky News',\n",
|
||||
" \"UK prepares to nationalize Russia natural gas giant Gazprom's retail unit - Business Insider\",\n",
|
||||
" 'Zaghari-Ratcliffe: Hunt calls for inquiry into delay over Iran debt payment - The Guardian']"
|
||||
]
|
||||
},
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"all_titles"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ပထမဆုံးအနေနဲ့၊ သတင်းခေါင်းစဉ်တွေထဲက နာမ်တွေကို ထုတ်ယူနိုင်ဖို့လိုပါတယ်။ ဒါကိုလုပ်ဖို့အတွက် `TextBlob` စာကြည့်တိုက်ကို အသုံးပြုမယ်၊ အဲဒါက ဒီလိုပုံမှန် NLP အလုပ်တွေကို လွယ်ကူစေပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Requirement already satisfied: textblob in c:\\winapp\\miniconda3\\lib\\site-packages (0.17.1)\n",
|
||||
"Requirement already satisfied: nltk>=3.1 in c:\\winapp\\miniconda3\\lib\\site-packages (from textblob) (3.5)\n",
|
||||
"Requirement already satisfied: joblib in c:\\winapp\\miniconda3\\lib\\site-packages (from nltk>=3.1->textblob) (1.0.1)\n",
|
||||
"Requirement already satisfied: regex in c:\\winapp\\miniconda3\\lib\\site-packages (from nltk>=3.1->textblob) (2021.11.10)\n",
|
||||
"Requirement already satisfied: tqdm in c:\\winapp\\miniconda3\\lib\\site-packages (from nltk>=3.1->textblob) (4.61.2)\n",
|
||||
"Requirement already satisfied: click in c:\\winapp\\miniconda3\\lib\\site-packages (from nltk>=3.1->textblob) (8.0.3)\n",
|
||||
"Requirement already satisfied: colorama in c:\\winapp\\miniconda3\\lib\\site-packages (from click->nltk>=3.1->textblob) (0.4.4)\n",
|
||||
"Finished.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[nltk_data] Downloading package brown to\n",
|
||||
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
|
||||
"[nltk_data] Package brown is already up-to-date!\n",
|
||||
"[nltk_data] Downloading package punkt to\n",
|
||||
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
|
||||
"[nltk_data] Package punkt is already up-to-date!\n",
|
||||
"[nltk_data] Downloading package wordnet to\n",
|
||||
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
|
||||
"[nltk_data] Package wordnet is already up-to-date!\n",
|
||||
"[nltk_data] Downloading package averaged_perceptron_tagger to\n",
|
||||
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
|
||||
"[nltk_data] Package averaged_perceptron_tagger is already up-to-\n",
|
||||
"[nltk_data] date!\n",
|
||||
"[nltk_data] Downloading package conll2000 to\n",
|
||||
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
|
||||
"[nltk_data] Package conll2000 is already up-to-date!\n",
|
||||
"[nltk_data] Downloading package movie_reviews to\n",
|
||||
"[nltk_data] C:\\Users\\dmitryso\\AppData\\Roaming\\nltk_data...\n",
|
||||
"[nltk_data] Package movie_reviews is already up-to-date!\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import sys\n",
|
||||
"!{sys.executable} -m pip install textblob\n",
|
||||
"!{sys.executable} -m textblob.download_corpora\n",
|
||||
"from textblob import TextBlob"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'covid-19 live updates': 1,\n",
|
||||
" 'vaccines': 1,\n",
|
||||
" 'boosters': 1,\n",
|
||||
" 'york': 4,\n",
|
||||
" 'ukrainians flee mariupol': 1,\n",
|
||||
" 'forces push': 1,\n",
|
||||
" 'port city': 1,\n",
|
||||
" 'wall street journal': 3,\n",
|
||||
" 'bond yields': 1,\n",
|
||||
" 'futures rise': 1,\n",
|
||||
" 'powell says fed': 1,\n",
|
||||
" 'ready': 1,\n",
|
||||
" 'be': 1,\n",
|
||||
" 'aggressive': 1,\n",
|
||||
" 'putin': 3,\n",
|
||||
" 'alexei navalny': 2,\n",
|
||||
" 'russian': 2,\n",
|
||||
" 'supreme court nominee': 1,\n",
|
||||
" 'ketanji brown jackson': 1,\n",
|
||||
" \"confirmation hearing 's\": 1,\n",
|
||||
" 'cnn': 1,\n",
|
||||
" 'swedish': 1,\n",
|
||||
" 'high school': 1,\n",
|
||||
" 'abc': 1,\n",
|
||||
" 'clues': 1,\n",
|
||||
" 'covid-19': 1,\n",
|
||||
" '’ s': 2,\n",
|
||||
" 'moves': 1,\n",
|
||||
" 'sewers': 1,\n",
|
||||
" 'roll dice': 1,\n",
|
||||
" 'jackson': 1,\n",
|
||||
" 'decisions |': 1,\n",
|
||||
" 'thehill': 1,\n",
|
||||
" 'clear': 2,\n",
|
||||
" 'chemical weapons': 2,\n",
|
||||
" 'ukraine': 3,\n",
|
||||
" 'claims president': 2,\n",
|
||||
" 'biden': 2,\n",
|
||||
" 'nasa': 2,\n",
|
||||
" 'solar system': 2,\n",
|
||||
" 'daily mail': 3,\n",
|
||||
" 'us stocks': 1,\n",
|
||||
" 'fed chair powell': 1,\n",
|
||||
" \"'s remarks\": 1,\n",
|
||||
" 'fox': 1,\n",
|
||||
" \"'we 've\": 1,\n",
|
||||
" 'tests': 1,\n",
|
||||
" 'covid': 1,\n",
|
||||
" 'politico': 1,\n",
|
||||
" 'duchess': 1,\n",
|
||||
" 'cambridge': 1,\n",
|
||||
" 'swaps khaki jungle gear': 1,\n",
|
||||
" 'vampire': 1,\n",
|
||||
" 'wife': 1,\n",
|
||||
" 'belize': 1,\n",
|
||||
" 'china': 2,\n",
|
||||
" 'flight recorders': 1,\n",
|
||||
" 'plane crash': 1,\n",
|
||||
" 'reuters': 2,\n",
|
||||
" 'russian oligarch': 1,\n",
|
||||
" 'abramovich': 1,\n",
|
||||
" 'live': 1,\n",
|
||||
" 'russia': 2,\n",
|
||||
" 'stops talks': 1,\n",
|
||||
" 'japan': 1,\n",
|
||||
" 'español': 1,\n",
|
||||
" 'powers remain': 1,\n",
|
||||
" 'threats lurk': 1,\n",
|
||||
" 'set': 1,\n",
|
||||
" 'webb': 1,\n",
|
||||
" 'telescope begins multi-instrument alignment': 1,\n",
|
||||
" 'scitechdaily': 1,\n",
|
||||
" 'uconn': 1,\n",
|
||||
" 'ucf': 1,\n",
|
||||
" 'ncaa': 1,\n",
|
||||
" \"women 's tournament second-round highlights\": 1,\n",
|
||||
" 'march madness': 1,\n",
|
||||
" 'bucking republican trend': 1,\n",
|
||||
" 'indiana': 1,\n",
|
||||
" 'vetoes transgender': 1,\n",
|
||||
" 'bill': 1,\n",
|
||||
" 'maggie fox': 1,\n",
|
||||
" 'coronation': 1,\n",
|
||||
" 'shameless': 1,\n",
|
||||
" \"'sudden accident\": 1,\n",
|
||||
" 'mirror online': 1,\n",
|
||||
" 'mirror': 2,\n",
|
||||
" 'plane crash –': 1,\n",
|
||||
" 'search': 1,\n",
|
||||
" 'moment flight': 1,\n",
|
||||
" 'daniel morgan': 1,\n",
|
||||
" 'report condemns': 1,\n",
|
||||
" 'met': 1,\n",
|
||||
" 'guardian': 6,\n",
|
||||
" 'rishi sunak': 1,\n",
|
||||
" '’ s spring': 1,\n",
|
||||
" 'statement': 1,\n",
|
||||
" 'bbc.com': 1,\n",
|
||||
" 'uk': 3,\n",
|
||||
" 'ireland': 1,\n",
|
||||
" 'euro': 1,\n",
|
||||
" 'vladimir putin': 2,\n",
|
||||
" \"'s 'lover\": 1,\n",
|
||||
" 'brass eye': 1,\n",
|
||||
" '’ s outtakes': 1,\n",
|
||||
" 'brutal tv comedy': 1,\n",
|
||||
" 'threatens civilians': 1,\n",
|
||||
" 'mariupol': 1,\n",
|
||||
" \"'s spirit\": 1,\n",
|
||||
" 'shell u-turn': 1,\n",
|
||||
" 'cambo': 1,\n",
|
||||
" 'green targets': 1,\n",
|
||||
" 'st helens': 1,\n",
|
||||
" 'dog attack': 1,\n",
|
||||
" 'girl': 1,\n",
|
||||
" 'bbc': 1,\n",
|
||||
" 'playstation': 1,\n",
|
||||
" \"'assassin 's\": 1,\n",
|
||||
" 'creed': 1,\n",
|
||||
" 'jade raymond': 1,\n",
|
||||
" 'haven studios': 1,\n",
|
||||
" 'nme': 1,\n",
|
||||
" 'nintendo switch': 1,\n",
|
||||
" 'folders •': 1,\n",
|
||||
" 'eurogamer.net': 2,\n",
|
||||
" 'fa': 1,\n",
|
||||
" 'solution ”': 1,\n",
|
||||
" 'liverpool': 1,\n",
|
||||
" 'fan group blasts “ shambolic ”': 1,\n",
|
||||
" 'wembley': 1,\n",
|
||||
" 'anfield': 1,\n",
|
||||
" 'manchester': 1,\n",
|
||||
" 'live erik': 1,\n",
|
||||
" 'hag': 1,\n",
|
||||
" 'utd': 1,\n",
|
||||
" 'manager updates': 1,\n",
|
||||
" 'manchester evening': 1,\n",
|
||||
" 'inflation': 1,\n",
|
||||
" 'government borrowing': 1,\n",
|
||||
" 'february': 1,\n",
|
||||
" 'crude oil': 1,\n",
|
||||
" '– business': 1,\n",
|
||||
" 'kremlin': 1,\n",
|
||||
" 'large-scale fraud': 1,\n",
|
||||
" 'sky': 1,\n",
|
||||
" 'natural gas': 1,\n",
|
||||
" 'gazprom': 1,\n",
|
||||
" 'retail unit': 1,\n",
|
||||
" 'insider': 1,\n",
|
||||
" 'zaghari-ratcliffe': 1,\n",
|
||||
" 'hunt': 1,\n",
|
||||
" 'iran': 1,\n",
|
||||
" 'debt payment': 1}"
|
||||
]
|
||||
},
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"w = {}\n",
|
||||
"for x in all_titles:\n",
|
||||
" for n in TextBlob(x).noun_phrases:\n",
|
||||
" if n in w:\n",
|
||||
" w[n].append(x)\n",
|
||||
" else:\n",
|
||||
" w[n]=[x]\n",
|
||||
"{ x:len(w[x]) for x in w.keys()}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့သည် နာမ်များသည် အကြီးမားသော အဓိကအကြောင်းအရာအုပ်စုများကို မပေးနိုင်ကြောင်း တွေ့နိုင်ပါသည်။ နာမ်များကို အကြောင်းအရာဂရပ်မှ ရရှိသော ပိုမိုယေဘူယျသော စကားလုံးများဖြင့် အစားထိုးကြည့်ပါစို့။ ဤလုပ်ငန်းစဉ်သည် အချိန်အနည်းငယ်ယူပါမည်၊ အကြောင်းမှာ ကျွန်ုပ်တို့သည် နာမ်စကားစုတစ်ခုစီအတွက် REST ခေါ်ဆိုမှုကို လုပ်ဆောင်နေခြင်းဖြစ်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"w = {}\n",
|
||||
"for x in all_titles:\n",
|
||||
" for noun in TextBlob(x).noun_phrases:\n",
|
||||
" terms = query(noun.replace(' ','%20'))\n",
|
||||
" for term in [u for u in terms.keys() if terms[u]>0.1]:\n",
|
||||
" if term in w:\n",
|
||||
" w[term].append(x)\n",
|
||||
" else:\n",
|
||||
" w[term]=[x]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'city': 9,\n",
|
||||
" 'brand': 4,\n",
|
||||
" 'place': 9,\n",
|
||||
" 'town': 4,\n",
|
||||
" 'factor': 4,\n",
|
||||
" 'film': 4,\n",
|
||||
" 'nation': 11,\n",
|
||||
" 'state': 5,\n",
|
||||
" 'person': 4,\n",
|
||||
" 'organization': 5,\n",
|
||||
" 'publication': 10,\n",
|
||||
" 'market': 5,\n",
|
||||
" 'economy': 4,\n",
|
||||
" 'company': 6,\n",
|
||||
" 'newspaper': 6,\n",
|
||||
" 'relationship': 6}"
|
||||
]
|
||||
},
|
||||
"execution_count": 24,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"{ x:len(w[x]) for x in w.keys() if len(w[x])>3}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 27,
|
||||
"metadata": {
|
||||
"trusted": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\n",
|
||||
"ECONOMY:\n",
|
||||
"China searches for victims, flight recorders after first plane crash in 12 years - Reuters\n",
|
||||
"Live updates: Russia stops talks with Japan over sanctions - The Associated Press - en Español\n",
|
||||
"China plane crash – live: Search for survivors continues as witness describes moment flight fell from sky - The Independent\n",
|
||||
"UK prepares to nationalize Russia natural gas giant Gazprom's retail unit - Business Insider\n",
|
||||
"\n",
|
||||
"NATION:\n",
|
||||
"‘Clear sign’ Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent\n",
|
||||
"Duchess of Cambridge swaps khaki jungle gear for Vampire's Wife dress on Belize trip - Daily Mail\n",
|
||||
"China searches for victims, flight recorders after first plane crash in 12 years - Reuters\n",
|
||||
"Live updates: Russia stops talks with Japan over sanctions - The Associated Press - en Español\n",
|
||||
"Live updates: Russia stops talks with Japan over sanctions - The Associated Press - en Español\n",
|
||||
"China plane crash – live: Search for survivors continues as witness describes moment flight fell from sky - The Independent\n",
|
||||
"UK and Republic of Ireland in line to host Euro 2028 after no one else bids - The Guardian\n",
|
||||
"Friends beg Vladimir Putin's 'lover' to persuade him to end Ukraine invasion - The Mirror\n",
|
||||
"‘Clear sign’ Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent\n",
|
||||
"UK prepares to nationalize Russia natural gas giant Gazprom's retail unit - Business Insider\n",
|
||||
"Zaghari-Ratcliffe: Hunt calls for inquiry into delay over Iran debt payment - The Guardian\n",
|
||||
"\n",
|
||||
"PERSON:\n",
|
||||
"‘Clear sign’ Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent\n",
|
||||
"Duchess of Cambridge swaps khaki jungle gear for Vampire's Wife dress on Belize trip - Daily Mail\n",
|
||||
"Second superyacht linked to Russian oligarch Abramovich docks in Turkey - Reuters\n",
|
||||
"‘Clear sign’ Putin considering using chemical weapons in Ukraine, claims President Biden - The Independent\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print('\\nECONOMY:\\n'+'\\n'.join(w['economy']))\n",
|
||||
"print('\\nNATION:\\n'+'\\n'.join(w['nation']))\n",
|
||||
"print('\\nPERSON:\\n'+'\\n'.join(w['person']))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်မှုများတွင် အမှားများ သို့မဟုတ် မတိကျမှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာတရ အရင်းအမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူ့ဘာသာပြန်ပညာရှင်များမှ ပရော်ဖက်ရှင်နယ် ဘာသာပြန်မှုကို အကြံပြုပါသည်။ ဤဘာသာပြန်မှုကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားလွဲမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.7.4 64-bit (conda)",
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
|
||||
}
|
||||
},
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.5"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "4087f998407d06ceb2947016ba4605d0",
|
||||
"translation_date": "2025-08-30T09:40:59+00:00",
|
||||
"source_file": "lessons/2-Symbolic/MSConceptGraph.ipynb",
|
||||
"language_code": "my"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,31 +1,33 @@
|
|||
<!--
|
||||
CO_OP_TRANSLATOR_METADATA:
|
||||
{
|
||||
"original_hash": "7336583e4630220c835335da640016db",
|
||||
"translation_date": "2025-08-26T00:01:34+00:00",
|
||||
"original_hash": "ba5d1eb353d20d3e7181066b3c424b99",
|
||||
"translation_date": "2025-08-30T08:46:51+00:00",
|
||||
"source_file": "lessons/3-NeuralNetworks/03-Perceptron/lab/README.md",
|
||||
"language_code": "my"
|
||||
}
|
||||
-->
|
||||
# Multi-Class Classification with Perceptron
|
||||
|
||||
[AI for Beginners Curriculum](https://github.com/microsoft/ai-for-beginners) မှ လက်တွေ့လေ့ကျင့်ခန်း။
|
||||
[AI for Beginners Curriculum](https://github.com/microsoft/ai-for-beginners) မှ Lab Assignment။
|
||||
|
||||
## လုပ်ငန်းတာဝန်
|
||||
## Task
|
||||
|
||||
ဒီသင်ခန်းစာမှာ MNIST လက်ရေးလက်သားဂဏန်းများကို binary classification အတွက် ဖန်တီးထားတဲ့ ကုဒ်ကို အသုံးပြုပြီး၊ မည်သည့်ဂဏန်းကိုမဆို အသိအမှတ်ပြုနိုင်မည့် multi-class classified တစ်ခု ဖန်တီးပါ။ သင်ကြားမှုနှင့် စမ်းသပ်မှု dataset များပေါ်တွင် classification accuracy ကိုတွက်ချက်ပြီး confusion matrix ကို print ထုတ်ပါ။
|
||||
ဒီသင်ခန်းစာမှာ MNIST လက်ရေးလက်သားဂဏန်းများကို binary classification အတွက် ဖန်တီးထားတဲ့ ကုဒ်ကို အသုံးပြုပြီး၊ မည်သည့်ဂဏန်းကိုမဆို အသိအမှတ်ပြုနိုင်မယ့် multi-class classifier တစ်ခု ဖန်တီးပါ။ Train dataset နဲ့ test dataset ပေါ်မှာ classification accuracy ကိုတွက်ချက်ပြီး၊ confusion matrix ကို print ထုတ်ပါ။
|
||||
|
||||
## အကြံပြုချက်များ
|
||||
## Hints
|
||||
|
||||
1. ဂဏန်းတစ်ခုစီအတွက် "ဒီဂဏန်း vs. အခြားဂဏန်းအားလုံး" binary classifier အတွက် dataset တစ်ခုဖန်တီးပါ။
|
||||
1. Binary classification အတွက် perceptron ၁၀ ခု (ဂဏန်းတစ်ခုစီအတွက် တစ်ခုစီ) ကို လေ့ကျင့်ပါ။
|
||||
1. Input digit ကို အသိအမှတ်ပြုနိုင်မည့် function တစ်ခု သတ်မှတ်ပါ။
|
||||
1. ဂဏန်းတစ်ခုစီအတွက် "ဒီဂဏန်း vs. အခြားဂဏန်းအားလုံး" ဆိုတဲ့ binary classifier dataset တစ်ခုဖန်တီးပါ။
|
||||
1. Binary classification အတွက် perceptron 10 ခု (ဂဏန်းတစ်ခုစီအတွက် တစ်ခုစီ) ကို train လုပ်ပါ။
|
||||
1. Input digit ကို classify လုပ်ပေးမယ့် function တစ်ခုကို သတ်မှတ်ပါ။
|
||||
|
||||
> **အကြံပြုချက်**: Perceptron ၁၀ ခု၏ အလေးချိန်များကို matrix တစ်ခုအဖြစ် ပေါင်းစည်းထားနိုင်ပါက၊ input digits များကို perceptron ၁၀ ခုလုံးဖြင့် matrix multiplication တစ်ခုတည်းဖြင့် လျှောက်ထားနိုင်ပါမည်။ ထွက်လာသောရလဒ်တွင် `argmax` operation ကို အသုံးပြုခြင်းဖြင့် အများဆုံးဖြစ်နိုင်သောဂဏန်းကို ရှာဖွေနိုင်ပါသည်။
|
||||
> **Hint**: Perceptron 10 ခုရဲ့ weight တွေကို matrix တစ်ခုအဖြစ် ပေါင်းစည်းထားနိုင်ရင်၊ input digit တွေကို perceptron 10 ခုလုံးနဲ့ တစ်ကြိမ်တည်း matrix multiplication နဲ့ လျှောက်ထားနိုင်ပါတယ်။ အထွေထွေဆုံးဂဏန်းကို `argmax` operation ကို output ပေါ်မှာ လျှောက်ထားရုံနဲ့ ရှာနိုင်ပါတယ်။
|
||||
|
||||
## စတင်ရန် Notebook
|
||||
## Starting Notebook
|
||||
|
||||
[PerceptronMultiClass.ipynb](../../../../../../lessons/3-NeuralNetworks/03-Perceptron/lab/PerceptronMultiClass.ipynb) ကို ဖွင့်ပြီး လက်တွေ့လေ့ကျင့်ခန်းကို စတင်ပါ။
|
||||
Lab ကို [PerceptronMultiClass.ipynb](PerceptronMultiClass.ipynb) ဖွင့်ပြီး စတင်ပါ။
|
||||
|
||||
---
|
||||
|
||||
**အကြောင်းကြားချက်**:
|
||||
ဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်ခြင်းတွင် အမှားများ သို့မဟုတ် မမှန်ကန်မှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းစာရွက်စာတမ်းကို ၎င်း၏ မူလဘာသာစကားဖြင့် အာဏာတရ အရင်းအမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူ့ဘာသာပြန်ပညာရှင်များမှ ပရော်ဖက်ရှင်နယ် ဘာသာပြန်ခြင်းကို အကြံပြုပါသည်။ ဤဘာသာပြန်ကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအမှားများ သို့မဟုတ် အနားလွဲမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။
|
||||
ဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်ခြင်းတွင် အမှားများ သို့မဟုတ် မတိကျမှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းစာရွက်စာတမ်းကို ၎င်း၏ မူရင်းဘာသာစကားဖြင့် အာဏာတရားရှိသော အရင်းအမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူ့ဘာသာပြန်ပညာရှင်များမှ ပရော်ဖက်ရှင်နယ် ဘာသာပြန်ခြင်းကို အကြံပြုပါသည်။ ဤဘာသာပြန်ကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားယူမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,183 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# MNIST Digit Classification ကို ကျွန်ုပ်တို့ရဲ့ Framework နဲ့ လုပ်ဆောင်ခြင်း\n",
|
||||
"\n",
|
||||
"[AI for Beginners Curriculum](https://github.com/microsoft/ai-for-beginners) မှ Lab Assignment ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"### Dataset ကို ဖတ်ရှုခြင်း\n",
|
||||
"\n",
|
||||
"ဒီ code က အင်တာနက်ပေါ်မှာရှိတဲ့ repository ကနေ dataset ကို ဒေါင်းလုပ်လုပ်ဆောင်ပါမယ်။ သင်လည်း AI Curriculum repo ရဲ့ `/data` directory ထဲကနေ dataset ကို လက်ဖြင့် ကူးယူနိုင်ပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
" % Total % Received % Xferd Average Speed Time Time Time Current\n",
|
||||
" Dload Upload Total Spent Left Speed\n",
|
||||
"\n",
|
||||
" 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\n",
|
||||
"100 9.9M 100 9.9M 0 0 9.9M 0 0:00:01 --:--:-- 0:00:01 15.8M\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"!rm *.pkl\n",
|
||||
"!wget https://raw.githubusercontent.com/microsoft/AI-For-Beginners/main/data/mnist.pkl.gz\n",
|
||||
"!gzip -d mnist.pkl.gz"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import pickle\n",
|
||||
"with open('mnist.pkl','rb') as f:\n",
|
||||
" MNIST = pickle.load(f)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"labels = MNIST['Train']['Labels']\n",
|
||||
"data = MNIST['Train']['Features']"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အနေနဲ့ ကျွန်တော်တို့မှာရှိတဲ့ ဒေတာရဲ့ ပုံစံကို ကြည့်ကြမယ်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(42000, 784)"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"data.shape"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### ဒေတာကို ခွဲခြားခြင်း\n",
|
||||
"\n",
|
||||
"ကျွန်တော်တို့ Scikit Learn ကို အသုံးပြုပြီး သင်ကြားမှုနှင့် စမ်းသပ်မှု ဒေတာစုများအကြား ခွဲခြားပါမည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Train samples: 33600, test samples: 8400\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from sklearn.model_selection import train_test_split\n",
|
||||
"\n",
|
||||
"features_train, features_test, labels_train, labels_test = train_test_split(data,labels,test_size=0.2)\n",
|
||||
"\n",
|
||||
"print(f\"Train samples: {len(features_train)}, test samples: {len(features_test)}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### လမ်းညွှန်ချက်များ\n",
|
||||
"\n",
|
||||
"1. သင်ခန်းစာမှ framework code ကို ယူပြီး ဒီ notebook ထဲသို့ (သို့မဟုတ် ပိုကောင်းတာကတော့ သီးခြား Python module တစ်ခုထဲသို့) ကူးထည့်ပါ။\n",
|
||||
"1. တစ်လွှာတည်းပါဝင်သော perceptron ကို သတ်မှတ်ပြီး သင်ကြားပါ၊ သင်ကြားမှုနှင့် အတည်ပြုမှု တို့၏ တိုးတက်မှုတန်ဖိုးများကို သင်ကြားမှုအတွင်း စောင့်ကြည့်ပါ။\n",
|
||||
"1. Overfitting ဖြစ်ပေါ်ခဲ့သည်ဟုတ်/မဟုတ်ကို နားလည်ရန် ကြိုးစားပြီး layer parameters များကို ပြင်ဆင်ကာ တိုးတက်မှုတန်ဖိုးများကို မြှင့်တင်ပါ။\n",
|
||||
"1. ယခင်အဆင့်များကို 2-layered နှင့် 3-layered perceptrons များအတွက် ထပ်မံလုပ်ဆောင်ပါ။ Layer များအကြား activation functions များကို မတူညီစွာ စမ်းသပ်ကြည့်ပါ။\n",
|
||||
"1. အောက်ပါမေးခွန်းများကို ဖြေရှင်းကြည့်ပါ-\n",
|
||||
" - Layer များအကြားရှိ activation function သည် network ၏ performance ကို သက်ရောက်စေပါသလား?\n",
|
||||
" - ဒီ task အတွက် 2-layered network သို့မဟုတ် 3-layered network တစ်ခုလိုအပ်ပါသလား?\n",
|
||||
" - Layer အရေအတွက်များလာသည်နှင့်အမျှ network ကို သင်ကြားရာတွင် ပြဿနာများ ကြုံတွေ့ခဲ့ပါသလား?\n",
|
||||
" - သင်ကြားမှုအတွင်း network ၏ weight များသည် ဘယ်လိုပြုမူနေပါသလဲ? Epoch နှင့်အတူ weight များ၏ အများဆုံး absolute တန်ဖိုးကို plot ဆွဲကာ ဆက်စပ်မှုကို နားလည်နိုင်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်ခြင်းတွင် အမှားများ သို့မဟုတ် မတိကျမှုများ ပါရှိနိုင်သည်ကို သတိပြုပါ။ မူရင်းဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာတရ အရင်းအမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူက ဘာသာပြန်ခြင်းကို အကြံပြုပါသည်။ ဤဘာသာပြန်ကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွဲအချော်များ သို့မဟုတ် အနားလွဲမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.7.4 64-bit (conda)",
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
|
||||
}
|
||||
},
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.9.5"
|
||||
},
|
||||
"orig_nbformat": 2,
|
||||
"coopTranslator": {
|
||||
"original_hash": "6fa055f484eb5d6bdf41166a356d3abf",
|
||||
"translation_date": "2025-08-30T09:48:33+00:00",
|
||||
"source_file": "lessons/3-NeuralNetworks/04-OwnFramework/lab/MyFW_MNIST.ipynb",
|
||||
"language_code": "my"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,108 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## လက်ဖဝါးလှုပ်ရှားမှုကို Optical Flow အသုံးပြု၍ ရှာဖွေခြင်း\n",
|
||||
"\n",
|
||||
"ဤလက်တွေ့လေ့ကျင့်ခန်းသည် [AI for Beginners Curriculum](http://aka.ms/ai-beginners) ၏ အစိတ်အပိုင်းတစ်ခုဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"[ဤဗီဒီယို](../../../../../../lessons/4-ComputerVision/06-IntroCV/lab/palm-movement.mp4) ကိုစဉ်းစားပါ၊ ဗီဒီယိုတွင် လူတစ်ဦး၏ လက်ဖဝါးသည် တည်ငြိမ်သောနောက်ခံပေါ်တွင် ဘယ်/ညာ/အပေါ်/အောက်သို့ လှုပ်ရှားနေသည်။\n",
|
||||
"\n",
|
||||
"**သင့်ရည်မှန်းချက်**မှာ Optical Flow ကိုအသုံးပြုပြီး ဗီဒီယို၏ ဘယ်အပိုင်းများတွင် အပေါ်/အောက်/ဘယ်/ညာ လှုပ်ရှားမှုများပါဝင်သည်ကို သတ်မှတ်ရန်ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"စာတန်းထဲတွင် ဖော်ပြထားသည့်အတိုင်း ဗီဒီယိုဖရိမ်များကို ရယူခြင်းဖြင့် စတင်ပါ:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Code here"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အခုတော့၊ သင်ခန်းစာတွင် ဖော်ပြထားသည့်အတိုင်း အထူအလင်းမှုတ်စီးရေကို ရှုထောင်များတွက်ချက်ပြီး၊ အထူအလင်းမှုတ်စီးရေကို ပိုလာကိုဩဒိနိတ်များသို့ ပြောင်းပါ။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Code here"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အော့ပတီကယ် ဖလို ဖရိမ်းတစ်ခုစီအတွက် လမ်းညွှန်မှုများ၏ ဟစ်စတိုဂရမ်ကို တည်ဆောက်ပါ။ ဟစ်စတိုဂရမ်သည် ဘယ်လောက်အရေအတွက်ရှိသော ဗက်တာများက သတ်မှတ်ထားသော ဘင်တစ်ခုအောက်တွင် ကျရောက်နေသည်ကို ပြသပြီး၊ ဖရိမ်းပေါ်တွင် လှုပ်ရှားမှု၏ လမ်းညွှန်မှုများကို ခွဲခြားပြသနိုင်ရမည်ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"> သတ်မှတ်ထားသော စံနှုန်းအောက်ရှိ မက်ဂနီကျုဒ်များကို သုညအဖြစ် သတ်မှတ်လိုက်ရန်လိုအပ်နိုင်ပါသည်။ ဤနည်းလမ်းဖြင့် ဗီဒီယိုတွင် မျက်လုံးနှင့် ခေါင်းကဲ့သို့သော သေးငယ်သော အပိုလှုပ်ရှားမှုများကို ဖယ်ရှားနိုင်မည်ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"ဖရိမ်းအချို့အတွက် ဟစ်စတိုဂရမ်များကို ပုံဖော်ပြပါ။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Code here"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ဟစ်စတိုဂရမ်များကိုကြည့်ပါက၊ လှုပ်ရှားမှုဦးတည်ရာကိုသတ်မှတ်ရန် အလွန်ရိုးရှင်းသင့်သည်။ အပေါ်/အောက်/ဘယ်/ညာဦးတည်ရာများနှင့်ကိုက်ညီသော bin များကိုရွေးချယ်ရန်လိုအပ်ပြီး၊ အချို့သော threshold အထက်ရှိသော bin များကိုသာရွေးချယ်ပါ။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Code here"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အောင်မြင်ပါတယ်! အထက်ပါအဆင့်များအားလုံးကို ပြုလုပ်ပြီးပါက၊ သင်သည် လက်တွေ့လေ့လာခန်းကို ပြီးမြောက်ခဲ့ပါပြီ!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်မှုများတွင် အမှားများ သို့မဟုတ် မတိကျမှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းစာရွက်စာတမ်းကို ၎င်း၏ မူရင်းဘာသာစကားဖြင့် အာဏာတရားရှိသော အရင်းအမြစ်အဖြစ် ရှုလေ့ရှိသင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူက ဘာသာပြန်မှုကို အသုံးပြုရန် အကြံပြုပါသည်။ ဤဘာသာပြန်မှုကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားယူမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"language_info": {
|
||||
"name": "python"
|
||||
},
|
||||
"orig_nbformat": 4,
|
||||
"coopTranslator": {
|
||||
"original_hash": "153d9e417e079bf62f8f693002d0deaf",
|
||||
"translation_date": "2025-08-30T09:22:16+00:00",
|
||||
"source_file": "lessons/4-ComputerVision/06-IntroCV/lab/MovementDetection.ipynb",
|
||||
"language_code": "my"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,573 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# စာသားအမျိုးအစားသတ်မှတ်ခြင်း အလုပ်\n",
|
||||
"\n",
|
||||
"ကျွန်တော်တို့ ပြောခဲ့သလို **AG_NEWS** ဒေတာစုအပေါ် အခြေခံပြီး သတင်းခေါင်းစဉ်များကို ကမ္ဘာ့သတင်း၊ အားကစား၊ စီးပွားရေးနှင့် သိပ္ပံ/နည်းပညာ စသည့် ၄ မျိုးအတွင်းမှ တစ်ခုအဖြစ် သတ်မှတ်ရန် ရိုးရှင်းသော စာသားအမျိုးအစားသတ်မှတ်ခြင်း အလုပ်ကို အာရုံစိုက်သွားပါမည်။\n",
|
||||
"\n",
|
||||
"## ဒေတာစု\n",
|
||||
"\n",
|
||||
"ဒီဒေတာစုကို [`torchtext`](https://github.com/pytorch/text) module ထဲမှာ ပါဝင်ပြီး၊ အလွယ်တကူ အသုံးပြုနိုင်ပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import torch\n",
|
||||
"import torchtext\n",
|
||||
"import os\n",
|
||||
"import collections\n",
|
||||
"os.makedirs('./data',exist_ok=True)\n",
|
||||
"train_dataset, test_dataset = torchtext.datasets.AG_NEWS(root='./data')\n",
|
||||
"classes = ['World', 'Sports', 'Business', 'Sci/Tech']"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ဒီမှာ `train_dataset` နဲ့ `test_dataset` တွေဟာ label (အတန်းနံပါတ်) နဲ့ text တို့ကို အတွဲလိုက်ပြန်ပေးတဲ့ collection တွေကို ပါဝင်ထားပြီး၊ ဥပမာအားဖြင့်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(3,\n",
|
||||
" \"Wall St. Bears Claw Back Into the Black (Reuters) Reuters - Short-sellers, Wall Street's dwindling\\\\band of ultra-cynics, are seeing green again.\")"
|
||||
]
|
||||
},
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"list(train_dataset)[0]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ဒါဆိုရင်၊ ကျွန်တော်တို့ရဲ့ဒေတာစနစ်ထဲက နောက်ဆုံးထွက်ခေါင်းစဉ်အသစ် ၁၀ ခုကို ပုံနှိပ်ထုတ်ကြမယ်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"**Sci/Tech** -> Wall St. Bears Claw Back Into the Black (Reuters) Reuters - Short-sellers, Wall Street's dwindling\\band of ultra-cynics, are seeing green again.\n",
|
||||
"**Sci/Tech** -> Carlyle Looks Toward Commercial Aerospace (Reuters) Reuters - Private investment firm Carlyle Group,\\which has a reputation for making well-timed and occasionally\\controversial plays in the defense industry, has quietly placed\\its bets on another part of the market.\n",
|
||||
"**Sci/Tech** -> Oil and Economy Cloud Stocks' Outlook (Reuters) Reuters - Soaring crude prices plus worries\\about the economy and the outlook for earnings are expected to\\hang over the stock market next week during the depth of the\\summer doldrums.\n",
|
||||
"**Sci/Tech** -> Iraq Halts Oil Exports from Main Southern Pipeline (Reuters) Reuters - Authorities have halted oil export\\flows from the main pipeline in southern Iraq after\\intelligence showed a rebel militia could strike\\infrastructure, an oil official said on Saturday.\n",
|
||||
"**Sci/Tech** -> Oil prices soar to all-time record, posing new menace to US economy (AFP) AFP - Tearaway world oil prices, toppling records and straining wallets, present a new economic menace barely three months before the US presidential elections.\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"for i,x in zip(range(5),train_dataset):\n",
|
||||
" print(f\"**{classes[x[0]]}** -> {x[1]}\")\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ဒေတာစနစ်များသည် အကြောင်းအရာများဖြစ်သောကြောင့်၊ ဒေတာကို မကြိမ်များစွာ အသုံးပြုလိုပါက ဒါကို စာရင်းအဖြစ် ပြောင်းလဲရန် လိုအပ်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"train_dataset, test_dataset = torchtext.datasets.AG_NEWS(root='./data')\n",
|
||||
"train_dataset = list(train_dataset)\n",
|
||||
"test_dataset = list(test_dataset)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Tokenization\n",
|
||||
"\n",
|
||||
"အခုတော့ စာသားတွေကို **နံပါတ်တွေ** အဖြစ် ပြောင်းလဲပြီး tensors အနေနဲ့ ကိုယ်စားပြုနိုင်ဖို့ လိုအပ်ပါတယ်။ စကားလုံးအဆင့် ကိုယ်စားပြုမှု ရရှိချင်ရင် အောက်ပါ အရာနှစ်ခု လုပ်ဆောင်ရပါမယ်။\n",
|
||||
"* **tokenizer** ကို အသုံးပြုပြီး စာသားကို **tokens** အဖြစ် ခွဲခြားပါ။\n",
|
||||
"* အဲ့ဒီ tokens တွေကို **vocabulary** တစ်ခု တည်ဆောက်ပါ။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"['he', 'said', 'hello']"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"tokenizer = torchtext.data.utils.get_tokenizer('basic_english')\n",
|
||||
"tokenizer('He said: hello')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"counter = collections.Counter()\n",
|
||||
"for (label, line) in train_dataset:\n",
|
||||
" counter.update(tokenizer(line))\n",
|
||||
"vocab = torchtext.vocab.vocab(counter, min_freq=1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 19,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Vocab size if 95810\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[599, 3279, 97, 1220, 329, 225, 7368]"
|
||||
]
|
||||
},
|
||||
"execution_count": 19,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vocab_size = len(vocab)\n",
|
||||
"print(f\"Vocab size if {vocab_size}\")\n",
|
||||
"\n",
|
||||
"stoi = vocab.get_stoi() # dict to convert tokens to indices\n",
|
||||
"\n",
|
||||
"def encode(x):\n",
|
||||
" return [stoi[s] for s in tokenizer(x)]\n",
|
||||
"\n",
|
||||
"encode('I love to play with my words')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## စကားလုံးအိတ် (Bag of Words) စာသားကိုယ်စားပြုမှု\n",
|
||||
"\n",
|
||||
"စကားလုံးတွေဟာ အဓိပ္ပါယ်ကို ကိုယ်စားပြုနိုင်တဲ့အတွက်၊ တခါတရံမှာ စာကြောင်းထဲမှာ စကားလုံးတွေ ရှိနေတဲ့ အစီအစဉ်ကို မကြည့်ဘဲ စကားလုံးတစ်ခုချင်းစီကိုသာ ကြည့်ပြီး စာသားရဲ့ အဓိပ္ပါယ်ကို သိနိုင်ပါတယ်။ ဥပမာအားဖြင့် သတင်းတွေကို အမျိုးအစားခွဲရာမှာ *ရာသီဥတု*၊ *နှင်း* စတဲ့ စကားလုံးတွေဟာ *ရာသီဥတုခန့်မှန်းချက်* ကို ဖော်ပြနိုင်ပြီး၊ *အหุ้น*၊ *ဒေါ်လာ* စတဲ့ စကားလုံးတွေက *ဘဏ္ဍာရေးသတင်း* ကို ဖော်ပြနိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"**စကားလုံးအိတ်** (BoW) ဗက်တာကိုယ်စားပြုမှုဟာ အရင်က အသုံးများခဲ့တဲ့ ဗက်တာကိုယ်စားပြုမှုအနက် အများဆုံး အသုံးပြုတဲ့နည်းလမ်းဖြစ်ပါတယ်။ စကားလုံးတစ်လုံးချင်းစီကို ဗက်တာအညွှန်းနဲ့ ချိတ်ဆက်ထားပြီး၊ ဗက်တာအခန်းက စာရွက်တစ်ခုထဲမှာ စကားလုံးတစ်လုံးရဲ့ ဖြစ်ပေါ်မှုအရေအတွက်ကို ထည့်သွင်းထားပါတယ်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"> **Note**: BoW ကို စာသားထဲမှာ စကားလုံးတစ်လုံးချင်းစီအတွက် one-hot-encoded ဗက်တာတွေကို စုပေါင်းထားတဲ့အနေနဲ့လည်း စဉ်းစားနိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"အောက်မှာ Scikit Learn python library ကို အသုံးပြုပြီး စကားလုံးအိတ်ကိုယ်စားပြုမှုကို ဘယ်လို ဖန်တီးရမယ်ဆိုတာ ဥပမာတစ်ခု ဖော်ပြထားပါတယ်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[1, 1, 0, 2, 0, 0, 0, 0, 0]], dtype=int64)"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from sklearn.feature_extraction.text import CountVectorizer\n",
|
||||
"vectorizer = CountVectorizer()\n",
|
||||
"corpus = [\n",
|
||||
" 'I like hot dogs.',\n",
|
||||
" 'The dog ran fast.',\n",
|
||||
" 'Its hot outside.',\n",
|
||||
" ]\n",
|
||||
"vectorizer.fit_transform(corpus)\n",
|
||||
"vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"AG_NEWS ဒေတာစဉ်၏ဗက်တာကိုယ်စားပြုမှုမှ bag-of-words ဗက်တာကိုတွက်ချက်ရန်အတွက် ကျွန်ုပ်တို့အောက်ပါဖင်ခွင့်ကိုအသုံးပြုနိုင်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"tensor([2., 1., 2., ..., 0., 0., 0.])\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vocab_size = len(vocab)\n",
|
||||
"\n",
|
||||
"def to_bow(text,bow_vocab_size=vocab_size):\n",
|
||||
" res = torch.zeros(bow_vocab_size,dtype=torch.float32)\n",
|
||||
" for i in encode(text):\n",
|
||||
" if i<bow_vocab_size:\n",
|
||||
" res[i] += 1\n",
|
||||
" return res\n",
|
||||
"\n",
|
||||
"print(to_bow(train_dataset[0][1]))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## BoW ခွဲခြားမှုစနစ်ကို လေ့ကျင့်ခြင်း\n",
|
||||
"\n",
|
||||
"အခုတော့ ကျွန်တော်တို့ စကားလုံးအိတ် (Bag-of-Words) ကိုယ်စားပြုမှုကို တည်ဆောက်ပုံကို သင်ယူပြီးပြီဆိုတော့၊ အဲ့ဒီအပေါ်မှာ ခွဲခြားမှုစနစ်တစ်ခုကို လေ့ကျင့်ကြမယ်။ ပထမဦးဆုံး ကျွန်တော်တို့ရဲ့ dataset ကို လေ့ကျင့်ဖို့အတွက် ပြောင်းလဲဖို့လိုအပ်ပါတယ်၊ အဲ့ဒီမှာ အနေအထား vector ကိုယ်စားပြုမှုအားလုံးကို စကားလုံးအိတ်ကိုယ်စားပြုမှုအဖြစ် ပြောင်းလဲရပါမယ်။ ဒါကို `bowify` function ကို standard torch `DataLoader` ရဲ့ `collate_fn` parameter အဖြစ် ဖြတ်သွားခြင်းဖြင့် ပြုလုပ်နိုင်ပါတယ်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from torch.utils.data import DataLoader\n",
|
||||
"import numpy as np \n",
|
||||
"\n",
|
||||
"# this collate function gets list of batch_size tuples, and needs to \n",
|
||||
"# return a pair of label-feature tensors for the whole minibatch\n",
|
||||
"def bowify(b):\n",
|
||||
" return (\n",
|
||||
" torch.LongTensor([t[0]-1 for t in b]),\n",
|
||||
" torch.stack([to_bow(t[1]) for t in b])\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"train_loader = DataLoader(train_dataset, batch_size=16, collate_fn=bowify, shuffle=True)\n",
|
||||
"test_loader = DataLoader(test_dataset, batch_size=16, collate_fn=bowify, shuffle=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အခုတော့ linear layer တစ်ခုပါဝင်တဲ့ ရိုးရှင်းတဲ့ classifier neural network ကို သတ်မှတ်ကြမယ်။ input vector ရဲ့ အရွယ်အစားက `vocab_size` နဲ့ တန်းတူပြီး၊ output size က class အရေအတွက် (၄) ကို ကိုယ်စားပြုပါတယ်။ Classification task ကို ဖြေရှင်းနေတဲ့အတွက်၊ နောက်ဆုံး activation function က `LogSoftmax()` ဖြစ်ပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"net = torch.nn.Sequential(torch.nn.Linear(vocab_size,4),torch.nn.LogSoftmax(dim=1))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အခုတော့ ကျွန်တော်တို့ PyTorch ပုံမှန်လေ့ကျင့်မှု loop ကို သတ်မှတ်ပါမယ်။ ကျွန်တော်တို့ရဲ့ dataset က အတော်လေးကြီးမားတဲ့အတွက်၊ သင်ကြားရေးရည်ရွယ်ချက်အတွက် epoch တစ်ခုသာလေ့ကျင့်မှာဖြစ်ပြီး၊ တစ်ခါတစ်ရံမှာတော့ epoch တစ်ခုလုံးမပြည့်လည်းဖြစ်နိုင်ပါတယ် (`epoch_size` parameter ကို သတ်မှတ်ခြင်းအားဖြင့် လေ့ကျင့်မှုကို ကန့်သတ်နိုင်ပါတယ်)။ လေ့ကျင့်မှုအတွင်း စုစုပေါင်းလေ့ကျင့်မှုတိကျမှုကိုလည်း အစီရင်ခံမှာဖြစ်ပြီး၊ အစီရင်ခံမှုရဲ့ အကြိမ်ရေကို `report_freq` parameter ကို အသုံးပြု၍ သတ်မှတ်နိုင်ပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def train_epoch(net,dataloader,lr=0.01,optimizer=None,loss_fn = torch.nn.NLLLoss(),epoch_size=None, report_freq=200):\n",
|
||||
" optimizer = optimizer or torch.optim.Adam(net.parameters(),lr=lr)\n",
|
||||
" net.train()\n",
|
||||
" total_loss,acc,count,i = 0,0,0,0\n",
|
||||
" for labels,features in dataloader:\n",
|
||||
" optimizer.zero_grad()\n",
|
||||
" out = net(features)\n",
|
||||
" loss = loss_fn(out,labels) #cross_entropy(out,labels)\n",
|
||||
" loss.backward()\n",
|
||||
" optimizer.step()\n",
|
||||
" total_loss+=loss\n",
|
||||
" _,predicted = torch.max(out,1)\n",
|
||||
" acc+=(predicted==labels).sum()\n",
|
||||
" count+=len(labels)\n",
|
||||
" i+=1\n",
|
||||
" if i%report_freq==0:\n",
|
||||
" print(f\"{count}: acc={acc.item()/count}\")\n",
|
||||
" if epoch_size and count>epoch_size:\n",
|
||||
" break\n",
|
||||
" return total_loss.item()/count, acc.item()/count"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 25,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3200: acc=0.8028125\n",
|
||||
"6400: acc=0.8371875\n",
|
||||
"9600: acc=0.8534375\n",
|
||||
"12800: acc=0.85765625\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(0.026090790722161722, 0.8620069296375267)"
|
||||
]
|
||||
},
|
||||
"execution_count": 25,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"train_epoch(net,train_loader,epoch_size=15000)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## BiGrams, TriGrams နှင့် N-Grams\n",
|
||||
"\n",
|
||||
"Bag of words နည်းလမ်း၏ အားနည်းချက်တစ်ခုမှာ စကားလုံးအချို့သည် စကားလုံးများပေါင်းစပ်မှုဖြစ်ပြီး၊ ဥပမာအားဖြင့် 'hot dog' ဆိုသောစကားလုံးသည် 'hot' နှင့် 'dog' ဆိုသောစကားလုံးများ၏ အခြားအကြောင်းအရာများတွင်ရှိသည့် အဓိပ္ပါယ်နှင့် လုံးဝကွဲပြားနေသည်။ 'hot' နှင့် 'dog' စကားလုံးများကို အမြဲတမ်းတူညီသောဗက်တာများဖြင့် ကိုယ်စားပြုပါက၊ ၎င်းသည် မော်ဒယ်ကို ရှုပ်ထွေးစေနိုင်သည်။\n",
|
||||
"\n",
|
||||
"ဤပြဿနာကို ဖြေရှင်းရန် **N-gram ကိုယ်စားပြုမှုများ** ကို စာရွက်စာတမ်းများကို ခွဲခြားသတ်မှတ်ရာတွင် မကြာခဏအသုံးပြုကြပြီး၊ စကားလုံးတစ်လုံး၊ စကားလုံးနှစ်လုံး (bi-word) သို့မဟုတ် စကားလုံးသုံးလုံး (tri-word) ၏ ကြိမ်နှုန်းသည် Classifier များကို လေ့ကျင့်ရန် အသုံးဝင်သော အင်္ဂါရပ်တစ်ခုဖြစ်သည်။ ဥပမာအားဖြင့် bigram ကိုယ်စားပြုမှုတွင်၊ မူလစကားလုံးများအပြင် စကားလုံးစုံအားလုံးကို Vocabulary ထဲသို့ ထည့်သွင်းပါမည်။\n",
|
||||
"\n",
|
||||
"အောက်တွင် Scikit Learn ကို အသုံးပြု၍ bigram bag of word ကိုယ်စားပြုမှုကို ဘယ်လိုဖန်တီးရမည်ကို ဥပမာတစ်ခုအနေဖြင့် ဖော်ပြထားသည်-\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 26,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Vocabulary:\n",
|
||||
" {'i': 7, 'like': 11, 'hot': 4, 'dogs': 2, 'i like': 8, 'like hot': 12, 'hot dogs': 5, 'the': 16, 'dog': 0, 'ran': 14, 'fast': 3, 'the dog': 17, 'dog ran': 1, 'ran fast': 15, 'its': 9, 'outside': 13, 'its hot': 10, 'hot outside': 6}\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[1, 0, 1, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],\n",
|
||||
" dtype=int64)"
|
||||
]
|
||||
},
|
||||
"execution_count": 26,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"bigram_vectorizer = CountVectorizer(ngram_range=(1, 2), token_pattern=r'\\b\\w+\\b', min_df=1)\n",
|
||||
"corpus = [\n",
|
||||
" 'I like hot dogs.',\n",
|
||||
" 'The dog ran fast.',\n",
|
||||
" 'Its hot outside.',\n",
|
||||
" ]\n",
|
||||
"bigram_vectorizer.fit_transform(corpus)\n",
|
||||
"print(\"Vocabulary:\\n\",bigram_vectorizer.vocabulary_)\n",
|
||||
"bigram_vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"N-gram နည်းလမ်း၏ အဓိကအားနည်းချက်မှာ စကားလုံးစာရင်းအရွယ်အစားက အလွန်မြန်မြန်ဆန်ဆန် တိုးလာတတ်သည်။ အကဲဖြတ်လို့ရတဲ့အခြေအနေမှာတော့ N-gram ကို *embeddings* ကဲ့သို့သော အတိုင်းအတာလျှော့ချနည်းလမ်းများနှင့် ပေါင်းစပ်အသုံးပြုရန် လိုအပ်ပါသည်။ ဒီအကြောင်းကို နောက်တစ်ခုနစ်မှာ ဆွေးနွေးသွားမည်ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"**AG News** dataset တွင် N-gram ကို အသုံးပြုရန်အတွက် အထူး ngram စကားလုံးစာရင်းကို တည်ဆောက်ရန် လိုအပ်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 27,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Bigram vocabulary length = 1308842\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"counter = collections.Counter()\n",
|
||||
"for (label, line) in train_dataset:\n",
|
||||
" l = tokenizer(line)\n",
|
||||
" counter.update(torchtext.data.utils.ngrams_iterator(l,ngrams=2))\n",
|
||||
" \n",
|
||||
"bi_vocab = torchtext.vocab.vocab(counter, min_freq=1)\n",
|
||||
"\n",
|
||||
"print(\"Bigram vocabulary length = \",len(bi_vocab))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်တော်တို့ အထက်မှာရေးထားတဲ့ ကုဒ်ကို classifier ကို သင်ကြားဖို့ အသုံးပြုနိုင်ပါတယ်၊ သို့သော် memory ကို အလွန်အကျွံ အသုံးပြုမိနိုင်ပါတယ်။ နောက်တစ်ခုမှာတော့ bigram classifier ကို embeddings အသုံးပြုပြီး သင်ကြားပါမယ်။\n",
|
||||
"\n",
|
||||
"> **Note:** သင့်ရဲ့ text မှာ သတ်မှတ်ထားတဲ့ အကြိမ်အရေအတွက်ထက် ပိုများတဲ့ ngrams တွေကိုသာ ထားနိုင်ပါတယ်။ ဒါက infrequent bigrams တွေကို ဖယ်ရှားပေးပြီး dimensionality ကို အလွန်လျော့ချနိုင်စေမှာ ဖြစ်ပါတယ်။ ဒီအတွက် `min_freq` parameter ကို မြင့်မားတဲ့တန်ဖိုးတစ်ခု သတ်မှတ်ပေးပြီး vocabulary ရဲ့ အရှည်ပြောင်းလဲမှုကို ကြည့်ရှုပါ။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## စကားလုံးအကြိမ်ရေနှင့် စာရွက်စာတမ်းဆိုင်ရာ အလေးချိန် (TF-IDF)\n",
|
||||
"\n",
|
||||
"BoW (Bag of Words) ကိုယ်စားပြုမှုတွင် စကားလုံးများ၏ ပေါ်ပေါက်မှုအားလုံးကို တန်းတူအလေးချိန်ပေးထားပြီး၊ စကားလုံးတစ်လုံးချင်းစီ၏ အရေးပါမှုကို မထည့်သွင်းစဉ်းစားထားပါ။ သို့သော်၊ *a*, *in* စသည့် မကြာခဏတွေ့ရသော စကားလုံးများသည် အထူးသီးသန့်စကားလုံးများထက် အမျိုးအစားခွဲခြားမှုတွင် အရေးပါမှုနည်းပါသည်။ အမှန်တစ်ကယ်တွင်၊ NLP လုပ်ငန်းစဉ်များအများစုတွင် စကားလုံးတစ်ချို့သည် အခြားစကားလုံးများထက် ပိုမိုသက်ဆိုင်မှုရှိပါသည်။\n",
|
||||
"\n",
|
||||
"**TF-IDF** သည် **term frequency–inverse document frequency** ၏ အတိုကောက်ဖြစ်သည်။ ၎င်းသည် Bag of Words ၏ အမျိုးအစားတစ်ခုဖြစ်ပြီး၊ စကားလုံးတစ်လုံး၏ စာရွက်စာတမ်းတွင် ရှိနေမှုကို ပြသသည့် 0/1 အဘိဓါန်တန်ဖိုးအစား၊ စကားလုံးပေါ်ပေါက်မှု၏ အကြိမ်ရေနှင့် ဆက်စပ်သော အလျားလိုက်တန်ဖိုးကို အသုံးပြုထားသည်။\n",
|
||||
"\n",
|
||||
"ပိုမိုတိကျစွာဆိုရသော်၊ စကားလုံး $i$ ၏ စာရွက်စာတမ်း $j$ တွင်ရှိသော အလေးချိန် $w_{ij}$ ကို အောက်ပါအတိုင်း သတ်မှတ်ထားသည်။\n",
|
||||
"$$\n",
|
||||
"w_{ij} = tf_{ij}\\times\\log({N\\over df_i})\n",
|
||||
"$$\n",
|
||||
"ဒီမှာ\n",
|
||||
"* $tf_{ij}$ သည် စကားလုံး $i$ ၏ စာရွက်စာတမ်း $j$ တွင် ပေါ်ပေါက်မှုအကြိမ်ရေဖြစ်ပြီး၊ ယခင်က တွေ့ခဲ့သော BoW တန်ဖိုးဖြစ်သည်။\n",
|
||||
"* $N$ သည် စုစုပေါင်း စာရွက်စာတမ်းအရေအတွက်ဖြစ်သည်။\n",
|
||||
"* $df_i$ သည် စကားလုံး $i$ ကို အပါအဝင်ထားသော စာရွက်စာတမ်းအရေအတွက်ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"TF-IDF တန်ဖိုး $w_{ij}$ သည် စကားလုံးတစ်လုံးသည် စာရွက်စာတမ်းတစ်ခုတွင် ပေါ်ပေါက်မှုအကြိမ်ရေနှင့် လိုက်လျောညီထွေဖြစ်ပြီး၊ စကားလုံးတစ်လုံးသည် စုစုပေါင်း စာရွက်စာတမ်းများတွင် မကြာခဏပေါ်ပေါက်မှုကို ပြင်ဆင်ပေးသည်။ ဥပမာအားဖြင့်၊ စကားလုံးတစ်လုံးသည် စုစုပေါင်း စာရွက်စာတမ်းများအားလုံးတွင် ပေါ်ပေါက်နေပါက $df_i=N$ ဖြစ်ပြီး၊ $w_{ij}=0$ ဖြစ်မည်ဖြစ်၍ ၎င်းစကားလုံးများကို လုံးဝလျစ်လျူရှုမည်ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"Scikit Learn ကို အသုံးပြု၍ စာသားများ၏ TF-IDF ကို အလွယ်တကူ ဖန်တီးနိုင်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 28,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[0.43381609, 0. , 0.43381609, 0. , 0.65985664,\n",
|
||||
" 0.43381609, 0. , 0. , 0. , 0. ,\n",
|
||||
" 0. , 0. , 0. , 0. , 0. ,\n",
|
||||
" 0. ]])"
|
||||
]
|
||||
},
|
||||
"execution_count": 28,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from sklearn.feature_extraction.text import TfidfVectorizer\n",
|
||||
"vectorizer = TfidfVectorizer(ngram_range=(1,2))\n",
|
||||
"vectorizer.fit_transform(corpus)\n",
|
||||
"vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## အနှိပ်ချုပ်\n",
|
||||
"\n",
|
||||
"TF-IDF ကိုယ်စားပြုမှုများသည် စကားလုံးများကို အကြိမ်ရေအလေးချိန်ပေးနိုင်သော်လည်း အဓိပ္ပာယ်နှင့် အစီအစဉ်ကို ကိုယ်စားပြုနိုင်ခြင်းမရှိပါ။ 1935 ခုနှစ်တွင် နာမည်ကြီး ဘာသာဗေဒပညာရှင် J. R. Firth က “စကားလုံး၏ အပြည့်အစုံ အဓိပ္ပာယ်သည် အမြဲတမ်း အခြေအနေနှင့်ဆက်စပ်ပြီး အခြေအနေမှ ကင်းလွတ်သော အဓိပ္ပာယ်ကို လေ့လာခြင်းသည် အလေးထားစရာမရှိပါ” ဟု ပြောခဲ့သည်။ ကျွန်ုပ်တို့သည် သင်ခန်းစာတွင် နောက်ပိုင်းတွင် ဘာသာစကား မော်ဒယ်တစ်ခုကို အသုံးပြု၍ စာသားမှ အခြေအနေဆိုင်ရာ အချက်အလက်များကို ဖမ်းယူနည်းကို လေ့လာမည်ဖြစ်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်ခြင်းတွင် အမှားများ သို့မဟုတ် မတိကျမှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာရှိသော ရင်းမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူက ဘာသာပြန်ခြင်းကို အကြံပြုပါသည်။ ဤဘာသာပြန်ကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအမှားများ သို့မဟုတ် အနားယူမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.8.12 ('py38')",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "7b9040985e748e4e2d4c689892456ad7",
|
||||
"translation_date": "2025-08-30T10:42:22+00:00",
|
||||
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationPyTorch.ipynb",
|
||||
"language_code": "my"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,647 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# စာသားအမျိုးအစားသတ်မှတ်ခြင်း အလုပ်\n",
|
||||
"\n",
|
||||
"ဒီအခန်းမှာတော့ **[AG_NEWS](http://www.di.unipi.it/~gulli/AG_corpus_of_news_articles.html)** dataset ကိုအခြေခံပြီး ရိုးရှင်းတဲ့ စာသားအမျိုးအစားသတ်မှတ်ခြင်း အလုပ်ကို စတင်လုပ်ဆောင်ပါမယ်။ ဤအလုပ်မှာ သတင်းခေါင်းစဉ်များကို အမျိုးအစား ၄ မျိုးဖြစ်တဲ့ World, Sports, Business, Sci/Tech တို့ထဲက တစ်ခုအဖြစ် သတ်မှတ်ပေးပါမယ်။\n",
|
||||
"\n",
|
||||
"## Dataset အကြောင်း\n",
|
||||
"\n",
|
||||
"Dataset ကို load လုပ်ဖို့အတွက် **[TensorFlow Datasets](https://www.tensorflow.org/datasets)** API ကို အသုံးပြုပါမယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import tensorflow as tf\n",
|
||||
"from tensorflow import keras\n",
|
||||
"import tensorflow_datasets as tfds\n",
|
||||
"\n",
|
||||
"# In this tutorial, we will be training a lot of models. In order to use GPU memory cautiously,\n",
|
||||
"# we will set tensorflow option to grow GPU memory allocation when required.\n",
|
||||
"physical_devices = tf.config.list_physical_devices('GPU') \n",
|
||||
"if len(physical_devices)>0:\n",
|
||||
" tf.config.experimental.set_memory_growth(physical_devices[0], True)\n",
|
||||
"\n",
|
||||
"dataset = tfds.load('ag_news_subset')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အခုကျွန်တော်တို့ `dataset['train']` နဲ့ `dataset['test']` ကိုအသုံးပြုပြီး training portion နဲ့ test portion ကို dataset မှာ access လုပ်နိုင်ပါပြီ:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Length of train dataset = 120000\n",
|
||||
"Length of test dataset = 7600\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"ds_train = dataset['train']\n",
|
||||
"ds_test = dataset['test']\n",
|
||||
"\n",
|
||||
"print(f\"Length of train dataset = {len(ds_train)}\")\n",
|
||||
"print(f\"Length of test dataset = {len(ds_test)}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အချက်အလက်စုစည်းမှုမှ ပထမဆုံး ၁၀ ခုသော သတင်းခေါင်းစဉ်အသစ်များကို ပုံနှိပ်ကြမယ်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3 (Sci/Tech) -> b'AMD Debuts Dual-Core Opteron Processor' b'AMD #39;s new dual-core Opteron chip is designed mainly for corporate computing applications, including databases, Web services, and financial transactions.'\n",
|
||||
"1 (Sports) -> b\"Wood's Suspension Upheld (Reuters)\" b'Reuters - Major League Baseball\\\\Monday announced a decision on the appeal filed by Chicago Cubs\\\\pitcher Kerry Wood regarding a suspension stemming from an\\\\incident earlier this season.'\n",
|
||||
"2 (Business) -> b'Bush reform may have blue states seeing red' b'President Bush #39;s quot;revenue-neutral quot; tax reform needs losers to balance its winners, and people claiming the federal deduction for state and local taxes may be in administration planners #39; sights, news reports say.'\n",
|
||||
"3 (Sci/Tech) -> b\"'Halt science decline in schools'\" b'Britain will run out of leading scientists unless science education is improved, says Professor Colin Pillinger.'\n",
|
||||
"1 (Sports) -> b'Gerrard leaves practice' b'London, England (Sports Network) - England midfielder Steven Gerrard injured his groin late in Thursday #39;s training session, but is hopeful he will be ready for Saturday #39;s World Cup qualifier against Austria.'\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"classes = ['World', 'Sports', 'Business', 'Sci/Tech']\n",
|
||||
"\n",
|
||||
"for i,x in zip(range(5),ds_train):\n",
|
||||
" print(f\"{x['label']} ({classes[x['label']]}) -> {x['title']} {x['description']}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## စာသားကို ဂဏန်းအဖြစ်ပြောင်းခြင်း\n",
|
||||
"\n",
|
||||
"အခုတော့ စာသားတွေကို **ဂဏန်း** အဖြစ်ပြောင်းပြီး tensor အနေနဲ့ ကိုယ်စားပြုနိုင်အောင် ပြုလုပ်ရပါမယ်။ စကားလုံးအဆင့်ကိုယ်စားပြုမှုလိုချင်ရင် အောက်ပါအချက်နှစ်ခုကို ပြုလုပ်ရပါမယ်-\n",
|
||||
"\n",
|
||||
"* **tokenizer** ကိုသုံးပြီး စာသားကို **tokens** အဖြစ်ခွဲခြားပါ။\n",
|
||||
"* အဲ့ဒီ tokens တွေကို **vocabulary** တစ်ခုတည်ဆောက်ပါ။\n",
|
||||
"\n",
|
||||
"### Vocabulary အရွယ်အစားကို ကန့်သတ်ခြင်း\n",
|
||||
"\n",
|
||||
"AG News dataset ဥပမာမှာတော့ vocabulary size က အတော်လေးကြီးပါတယ်၊ စကားလုံး 100,000 ကျော်ပါဝင်ပါတယ်။ အထူးသဖြင့် စာသားမှာ ရှားရှားပါးပါးပေါ်လာတဲ့ စကားလုံးတွေကို မလိုအပ်ပါဘူး — အဲ့ဒီစကားလုံးတွေဟာ စာကြောင်းအနည်းငယ်မှာပဲ ပါဝင်ပြီး၊ model က အဲ့ဒီစကားလုံးတွေကနေ သင်ယူနိုင်မှာ မဟုတ်ပါဘူး။ ဒါကြောင့် vocabulary size ကို သေးငယ်တဲ့အရေအတွက်တစ်ခုအထိ ကန့်သတ်ဖို့ make sense ဖြစ်ပါတယ်၊ အဲ့ဒီအတွက် vectorizer constructor ကို argument ဖြတ်ပေးရပါမယ်။\n",
|
||||
"\n",
|
||||
"အဲ့ဒီအဆင့်နှစ်ခုကို **TextVectorization** layer ကိုသုံးပြီး လုပ်ဆောင်နိုင်ပါတယ်။ အရင်ဆုံး vectorizer object ကို instantiate လုပ်ပြီး၊ `adapt` method ကို ခေါ်သုံးကာ စာသားအားလုံးကို ဖြတ်သွားပြီး vocabulary တစ်ခုတည်ဆောက်ပါ။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"vocab_size = 50000\n",
|
||||
"vectorizer = keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size)\n",
|
||||
"vectorizer.adapt(ds_train.take(500).map(lambda x: x['title']+' '+x['description']))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **မှတ်ချက်** ကျွန်တော်တို့သည် စာလုံးစုစည်းမှုတစ်ခုကို တည်ဆောက်ရန် အချက်အလက်စုစည်းမှု၏ အစိတ်အပိုင်းတစ်ခုကိုသာ အသုံးပြုနေပါသည်။ ဒါကို လုပ်ခြင်းဖြင့် အကောင်အထည်ဖော်မှုအချိန်ကို မြန်ဆန်စေပြီး သင့်ကို စောင့်နေစရာမလိုအောင် လုပ်ဆောင်ပါသည်။ သို့သော် အချက်အလက်စုစည်းမှု၏ စာလုံးအချို့သည် စာလုံးစုစည်းမှုထဲတွင် မပါဝင်နိုင်ဘဲ လေ့ကျင့်မှုအတွင်း မျက်မမြင်ဖြစ်နိုင်သည်ဆိုသော အန္တရာယ်ကို ကျွန်တော်တို့ ခံယူထားပါသည်။ ထို့ကြောင့် `adapt` လုပ်ဆောင်မှုအတွင်း စာလုံးစုစည်းမှုအရွယ်အစားအားလုံးကို အသုံးပြုပြီး အချက်အလက်စုစည်းမှုအားလုံးကို ဖြတ်သန်းခြင်းဖြင့် နောက်ဆုံးရလဒ်တိကျမှုကို တိုးမြှင့်နိုင်မည်ဖြစ်သော်လည်း အလွန်အမင်း မတိုးတက်နိုင်ပါ။\n",
|
||||
"\n",
|
||||
"အခု ကျွန်တော်တို့ စာလုံးစုစည်းမှုကို တကယ်ရောက်ရှိနိုင်ပါပြီ:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"['', '[UNK]', 'the', 'to', 'a', 'in', 'of', 'and', 'on', 'for']\n",
|
||||
"Length of vocabulary: 5335\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vocab = vectorizer.get_vocabulary()\n",
|
||||
"vocab_size = len(vocab)\n",
|
||||
"print(vocab[:10])\n",
|
||||
"print(f\"Length of vocabulary: {vocab_size}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ဗက်တိုရာဇာကို အသုံးပြု၍ မည်သည့်စာသားကိုမဆို အလွယ်တကူ နံပါတ်များအဖြစ် ကုဒ်ပြုလုပ်နိုင်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tf.Tensor: shape=(7,), dtype=int64, numpy=array([ 112, 3695, 3, 304, 11, 1041, 1], dtype=int64)>"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vectorizer('I love to play with my words')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## စကားလုံးအထုပ် (Bag-of-words) စာသားကိုယ်စားပြုမှု\n",
|
||||
"\n",
|
||||
"စကားလုံးများသည် အဓိပ္ပါယ်ကို ကိုယ်စားပြုနိုင်သောကြောင့်၊ တစ်ခါတစ်ရံ စာသားတစ်ခု၏ အဓိပ္ပါယ်ကို စာကြောင်းအတွင်း စကားလုံးများ၏ အစီအစဉ်ကို မကြည့်ဘဲ၊ တစ်ခုချင်းစီ စကားလုံးများကိုသာ ကြည့်ခြင်းဖြင့် သိနိုင်ပါသည်။ ဥပမာအားဖြင့် သတင်းများကို အမျိုးအစားခွဲခြားရာတွင် *ရာသီဥတု* နှင့် *နှင်း* ကဲ့သို့သော စကားလုံးများသည် *ရာသီဥတုခန့်မှန်းချက်* ကို ဖော်ပြနိုင်ပြီး၊ *အหุ้น* နှင့် *ဒေါ်လာ* ကဲ့သို့သော စကားလုံးများသည် *ဘဏ္ဍာရေးသတင်း* ကို ဖော်ပြနိုင်ပါသည်။\n",
|
||||
"\n",
|
||||
"**စကားလုံးအထုပ်** (BoW) ဗက်တာကိုယ်စားပြုမှုသည် နားလည်ရန် အလွယ်ဆုံးသော ရိုးရာဗက်တာကိုယ်စားပြုမှုဖြစ်သည်။ စကားလုံးတစ်ခုချင်းစီကို ဗက်တာအညွှန်းနှင့် ချိတ်ဆက်ထားပြီး၊ ဗက်တာအခန်းကဏ္ဍတစ်ခုတွင် သတ်မှတ်ထားသော စာရွက်စာတမ်းအတွင်း စကားလုံးတစ်ခုချင်းစီ၏ ဖြစ်ပေါ်မှုအရေအတွက်ကို ပါဝင်ထားသည်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"> **Note**: BoW ကို စာသားအတွင်း စကားလုံးတစ်ခုချင်းစီအတွက် တစ်ခုချင်းစီ *one-hot-encoded* ဗက်တာများ၏ စုစုပေါင်းအဖြစ်လည်း စဉ်းစားနိုင်ပါသည်။\n",
|
||||
"\n",
|
||||
"အောက်တွင် Scikit Learn python library ကို အသုံးပြု၍ စကားလုံးအထုပ်ကိုယ်စားပြုမှုကို ဖန်တီးပုံ၏ ဥပမာကို ဖော်ပြထားပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[1, 1, 0, 2, 0, 0, 0, 0, 0]], dtype=int64)"
|
||||
]
|
||||
},
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from sklearn.feature_extraction.text import CountVectorizer\n",
|
||||
"sc_vectorizer = CountVectorizer()\n",
|
||||
"corpus = [\n",
|
||||
" 'I like hot dogs.',\n",
|
||||
" 'The dog ran fast.',\n",
|
||||
" 'Its hot outside.',\n",
|
||||
" ]\n",
|
||||
"sc_vectorizer.fit_transform(corpus)\n",
|
||||
"sc_vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့အပေါ်တွင်သတ်မှတ်ထားသော Keras vectorizer ကိုလည်းအသုံးပြုနိုင်ပြီး၊ စကားလုံးနံပါတ်တစ်ခုချင်းစီကို one-hot encoding အဖြစ်ပြောင်းလဲပြီး၊ အဲဒီ vector တွေကိုလုံးလုံးပေါင်းထည့်နိုင်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([0., 5., 0., ..., 0., 0., 0.], dtype=float32)"
|
||||
]
|
||||
},
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def to_bow(text):\n",
|
||||
" return tf.reduce_sum(tf.one_hot(vectorizer(text),vocab_size),axis=0)\n",
|
||||
"\n",
|
||||
"to_bow('My dog likes hot dogs on a hot day.').numpy()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **မှတ်ချက်**: အရင်ဥပမာနဲ့ရလဒ်ကွာခြားနေတယ်ဆိုတာကို သင်အံ့ဩနိုင်ပါတယ်။ အကြောင်းက Keras ဥပမာမှာ vector ရဲ့အရှည်ဟာ vocabulary size နဲ့ကိုက်ညီပြီး၊ အဲဒီ vocabulary ကို AG News dataset အပြည့်အစုံကနေတည်ဆောက်ထားတာဖြစ်ပါတယ်။ ဒါပေမယ့် Scikit Learn ဥပမာမှာတော့ vocabulary ကို sample text ကနေ ချက်ချင်းတည်ဆောက်ထားတာဖြစ်ပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## BoW ခွဲခြားစနစ်ကို လေ့ကျင့်ခြင်း\n",
|
||||
"\n",
|
||||
"အခုတော့ ကျွန်တော်တို့ စာသားကို bag-of-words ကိုယ်စားပြုမှုအဖြစ် တည်ဆောက်နည်းကို သင်ယူပြီးဖြစ်သောကြောင့်၊ ဒါကို အသုံးပြုတဲ့ ခွဲခြားစနစ်တစ်ခုကို လေ့ကျင့်ကြမယ်။ ပထမဦးစွာ ကျွန်တော်တို့ရဲ့ ဒေတာစုစည်းမှုကို bag-of-words ကိုယ်စားပြုမှုအဖြစ် ပြောင်းလဲဖို့ လိုအပ်ပါတယ်။ ဒါကို `map` function ကို အောက်ပါနည်းလမ်းဖြင့် အသုံးပြုခြင်းဖြင့် ပြုလုပ်နိုင်ပါတယ် - \n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"batch_size = 128\n",
|
||||
"\n",
|
||||
"ds_train_bow = ds_train.map(lambda x: (to_bow(x['title']+x['description']),x['label'])).batch(batch_size)\n",
|
||||
"ds_test_bow = ds_test.map(lambda x: (to_bow(x['title']+x['description']),x['label'])).batch(batch_size)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အခုတော့ linear layer တစ်ခုပါဝင်တဲ့ ရိုးရှင်းတဲ့ classifier neural network ကို သတ်မှတ်ကြမယ်။ Input size က `vocab_size` ဖြစ်ပြီး၊ output size က class အရေအတွက် (၄) ကို ကိုယ်စားပြုပါတယ်။ Classification task ကို ဖြေရှင်းနေတာဖြစ်လို့၊ နောက်ဆုံး activation function က **softmax** ဖြစ်ပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"938/938 [==============================] - 66s 70ms/step - loss: 0.6144 - acc: 0.8427 - val_loss: 0.4416 - val_acc: 0.8697\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<keras.callbacks.History at 0x20c70a947f0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model = keras.models.Sequential([\n",
|
||||
" keras.layers.Dense(4,activation='softmax',input_shape=(vocab_size,))\n",
|
||||
"])\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
|
||||
"model.fit(ds_train_bow,validation_data=ds_test_bow)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်တော်တို့မှာ အတန်း ၄ ခုရှိတဲ့အတွက် ၈၀% အထက်ရှိတဲ့ တိကျမှုဟာ ရလဒ်ကောင်းတစ်ခုဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"## တစ်ခုတည်းသော network အဖြစ် classifier ကို လေ့ကျင့်ခြင်း\n",
|
||||
"\n",
|
||||
"Vectorizer ကလည်း Keras layer တစ်ခုဖြစ်တဲ့အတွက်၊ network တစ်ခုအဖြစ် သတ်မှတ်ပြီး၊ အဆုံးအထိ လေ့ကျင့်နိုင်ပါတယ်။ ဒီနည်းလမ်းနဲ့ dataset ကို `map` အသုံးပြုပြီး vectorize လုပ်စရာမလိုတော့ပါဘူး၊ network ရဲ့ input ကို အစစ်အမှန် dataset ကိုပဲ ဖြတ်သွားနိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"> **Note**: Dataset ကို dictionary (ဥပမာ `title`, `description` နဲ့ `label`) ကနေ tuple အဖြစ် ပြောင်းဖို့ map တွေကို အသုံးပြုရဦးမှာဖြစ်ပါတယ်။ သို့သော် disk ကနေ data ကို load လုပ်တဲ့အခါမှာတော့ လိုအပ်တဲ့ ဖွဲ့စည်းမှုနဲ့ dataset ကို အစဉ်အတိုင်း တည်ဆောက်နိုင်ပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"model\"\n",
|
||||
"_________________________________________________________________\n",
|
||||
" Layer (type) Output Shape Param # \n",
|
||||
"=================================================================\n",
|
||||
" input_1 (InputLayer) [(None, 1)] 0 \n",
|
||||
" \n",
|
||||
" text_vectorization (TextVec (None, None) 0 \n",
|
||||
" torization) \n",
|
||||
" \n",
|
||||
" tf.one_hot (TFOpLambda) (None, None, 5335) 0 \n",
|
||||
" \n",
|
||||
" tf.math.reduce_sum (TFOpLam (None, 5335) 0 \n",
|
||||
" bda) \n",
|
||||
" \n",
|
||||
" dense_2 (Dense) (None, 4) 21344 \n",
|
||||
" \n",
|
||||
"=================================================================\n",
|
||||
"Total params: 21,344\n",
|
||||
"Trainable params: 21,344\n",
|
||||
"Non-trainable params: 0\n",
|
||||
"_________________________________________________________________\n",
|
||||
"938/938 [==============================] - 73s 77ms/step - loss: 0.6057 - acc: 0.8414 - val_loss: 0.4202 - val_acc: 0.8736\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<keras.callbacks.History at 0x20c721521f0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def extract_text(x):\n",
|
||||
" return x['title']+' '+x['description']\n",
|
||||
"\n",
|
||||
"def tupelize(x):\n",
|
||||
" return (extract_text(x),x['label'])\n",
|
||||
"\n",
|
||||
"inp = keras.Input(shape=(1,),dtype=tf.string)\n",
|
||||
"x = vectorizer(inp)\n",
|
||||
"x = tf.reduce_sum(tf.one_hot(x,vocab_size),axis=1)\n",
|
||||
"out = keras.layers.Dense(4,activation='softmax')(x)\n",
|
||||
"model = keras.models.Model(inp,out)\n",
|
||||
"model.summary()\n",
|
||||
"\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Bigrams, trigrams နှင့် n-grams\n",
|
||||
"\n",
|
||||
"Bag-of-words နည်းလမ်း၏ အားနည်းချက်တစ်ခုမှာ စကားလုံးတစ်ချို့သည် စကားလုံးများပေါင်းစပ်မှုဖြစ်ပြီး၊ ဥပမာအားဖြင့် 'hot dog' ဆိုသော စကားလုံးသည် 'hot' နှင့် 'dog' ဆိုသော စကားလုံးများ၏ အခြားအကြောင်းအရာများတွင် အဓိပ္ပါယ်ကွဲပြားမှုရှိသည်။ 'hot' နှင့် 'dog' စကားလုံးများကို အမြဲတမ်းတူညီသော vectors ဖြင့် ကိုယ်စားပြုပါက၊ ၎င်းသည် မော်ဒယ်ကို ရှုပ်ထွေးစေနိုင်သည်။\n",
|
||||
"\n",
|
||||
"ဤပြဿနာကို ဖြေရှင်းရန်၊ **n-gram ကိုယ်စားပြုမှုများ** ကို အချို့သော စာရွက်စာတမ်းများကို အမျိုးအစားခွဲခြားရာတွင် အသုံးပြုလေ့ရှိပြီး၊ စကားလုံးတစ်လုံး၊ စကားလုံးနှစ်လုံး (bi-word) သို့မဟုတ် စကားလုံးသုံးလုံး (tri-word) တစ်ခုချင်းစီ၏ frequency သည် classifier များကို လေ့ကျင့်ရန် အသုံးဝင်သော feature ဖြစ်သည်။ ဥပမာအားဖြင့် bigram ကိုယ်စားပြုမှုတွင်၊ မူရင်းစကားလုံးများအပြင် စကားလုံးအတွဲများအားလုံးကို vocabulary ထဲသို့ ထည့်သွင်းပါမည်။\n",
|
||||
"\n",
|
||||
"အောက်တွင် Scikit Learn ကို အသုံးပြု၍ bigram bag of word ကိုယ်စားပြုမှုကို ဖန်တီးနည်း၏ ဥပမာကို ဖော်ပြထားသည်-\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Vocabulary:\n",
|
||||
" {'i': 7, 'like': 11, 'hot': 4, 'dogs': 2, 'i like': 8, 'like hot': 12, 'hot dogs': 5, 'the': 16, 'dog': 0, 'ran': 14, 'fast': 3, 'the dog': 17, 'dog ran': 1, 'ran fast': 15, 'its': 9, 'outside': 13, 'its hot': 10, 'hot outside': 6}\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[1, 0, 1, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],\n",
|
||||
" dtype=int64)"
|
||||
]
|
||||
},
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"bigram_vectorizer = CountVectorizer(ngram_range=(1, 2), token_pattern=r'\\b\\w+\\b', min_df=1)\n",
|
||||
"corpus = [\n",
|
||||
" 'I like hot dogs.',\n",
|
||||
" 'The dog ran fast.',\n",
|
||||
" 'Its hot outside.',\n",
|
||||
" ]\n",
|
||||
"bigram_vectorizer.fit_transform(corpus)\n",
|
||||
"print(\"Vocabulary:\\n\",bigram_vectorizer.vocabulary_)\n",
|
||||
"bigram_vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"n-gram နည်းလမ်းရဲ့ အဓိကအားနည်းချက်က vocabulary အရွယ်အစားက အလွန်မြန်မြန်ဆန်ဆန် ကြီးထွားလာတတ်တာပဲ ဖြစ်ပါတယ်။ အကောင်အထည်ဖော်ရာမှာတော့ n-gram ကို အသုံးပြုတဲ့အခါ dimensionality reduction နည်းလမ်းတစ်ခုဖြစ်တဲ့ *embeddings* နဲ့ပေါင်းစပ်ဖို့ လိုအပ်ပါတယ်၊ ဒီအကြောင်းကို နောက်အခန်းမှာ ဆွေးနွေးပါမယ်။\n",
|
||||
"\n",
|
||||
"**AG News** dataset မှာ n-gram ကို အသုံးပြုဖို့ `ngrams` parameter ကို `TextVectorization` constructor ထဲမှာ ဖြတ်သွင်းရပါမယ်။ bigram vocabulary ရဲ့ အရှည်က **အလွန်ကြီးမား**ပြီး၊ ကျွန်တော်တို့ရဲ့ အခြေအနေမှာတော့ 1.3 million tokens ထက်ပိုပါတယ်! ဒါကြောင့် bigram tokens ကိုလည်း သင့်တော်တဲ့ အရေအတွက်တစ်ခုနဲ့ ကန့်သတ်ဖို့ make sense ဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"classifier ကို training လုပ်ဖို့ အပေါ်မှာ အသုံးပြုခဲ့တဲ့ code ကိုပဲ အသုံးပြုနိုင်ပါတယ်၊ ဒါပေမယ့် memory ကို အလွန်မထိရောက်စွာ အသုံးပြုမိနိုင်ပါဘူး။ နောက်အခန်းမှာတော့ embeddings ကို အသုံးပြုပြီး bigram classifier ကို training လုပ်ပါမယ်။ အခုအချိန်မှာတော့ ဒီ notebook ထဲမှာ bigram classifier training ကို စမ်းသပ်ပြီး အတိအကျမှု (accuracy) ပိုမြင့်တင်နိုင်မလား စမ်းကြည့်နိုင်ပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## BoW ဗက်တာများကို အလိုအလျောက်တွက်ချက်ခြင်း\n",
|
||||
"\n",
|
||||
"အထက်ပါ ဥပမာတွင် BoW ဗက်တာများကို တစ်ခုချင်းစီသော စကားလုံးများ၏ one-hot encodings များကို ပေါင်းပြီး လက်ဖြင့်တွက်ချက်ခဲ့ပါသည်။ သို့သော် TensorFlow ၏ နောက်ဆုံးဗားရှင်းတွင် `output_mode='count` parameter ကို vectorizer constructor သို့ ဖြတ်သွားခြင်းဖြင့် BoW ဗက်တာများကို အလိုအလျောက်တွက်ချက်နိုင်ပါသည်။ ဤနည်းလမ်းသည် မော်ဒယ်ကို သတ်မှတ်ခြင်းနှင့် လေ့ကျင့်ခြင်းကို အလွန်လွယ်ကူစေပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Training vectorizer\n",
|
||||
"938/938 [==============================] - 7s 7ms/step - loss: 0.5929 - acc: 0.8486 - val_loss: 0.4168 - val_acc: 0.8772\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<keras.callbacks.History at 0x20c725217c0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model = keras.models.Sequential([\n",
|
||||
" keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,output_mode='count'),\n",
|
||||
" keras.layers.Dense(4,input_shape=(vocab_size,), activation='softmax')\n",
|
||||
"])\n",
|
||||
"print(\"Training vectorizer\")\n",
|
||||
"model.layers[0].adapt(ds_train.take(500).map(extract_text))\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## စကားလုံးအကြိမ်ရေ - စာရွက်စာတမ်းအကြိမ်ရေကို ဆန့်ကျင်သော အကြိမ်ရေ (TF-IDF)\n",
|
||||
"\n",
|
||||
"BoW ကိုယ်စားပြုမှုတွင် စကားလုံးများ၏ ဖြစ်ပေါ်မှုကို စကားလုံး၏ အမျိုးအစားမရွေးဘဲ တူညီသောနည်းလမ်းဖြင့် အလေးပေးသည်။ သို့သော် *a* နှင့် *in* ကဲ့သို့ မကြာခဏ တွေ့ရသော စကားလုံးများသည် အထူးသီးသန့် စကားလုံးများထက် အမျိုးအစားခွဲခြားမှုအတွက် အရေးပါမှုနည်းပါးသည်ဟု သိသာသည်။ NLP အလုပ်များအများစုတွင် စကားလုံးတချို့သည် အခြားစကားလုံးများထက် ပိုမိုသက်ဆိုင်မှုရှိသည်။\n",
|
||||
"\n",
|
||||
"**TF-IDF** သည် **term frequency - inverse document frequency** ကို ဆိုလိုသည်။ ၎င်းသည် bag-of-words ၏ အမျိုးအစားတစ်ခုဖြစ်ပြီး စကားလုံးတစ်ခုသည် စာရွက်စာတမ်းတွင် ပါဝင်မှုကို binary 0/1 တန်ဖိုးဖြင့် ဖော်ပြခြင်းမဟုတ်ဘဲ စကားလုံး၏ corpus တွင် ဖြစ်ပေါ်မှုအကြိမ်ရေနှင့် ဆက်စပ်သော floating-point တန်ဖိုးကို အသုံးပြုသည်။\n",
|
||||
"\n",
|
||||
"ပိုမိုတိကျစွာဆိုရမည်ဆိုလျှင် စကားလုံး $i$ ၏ စာရွက်စာတမ်း $j$ တွင် အလေးပေးမှု $w_{ij}$ ကို အောက်ပါအတိုင်း သတ်မှတ်သည်။\n",
|
||||
"$$\n",
|
||||
"w_{ij} = tf_{ij}\\times\\log({N\\over df_i})\n",
|
||||
"$$\n",
|
||||
"အဲဒီမှာ\n",
|
||||
"* $tf_{ij}$ သည် $i$ ကို $j$ တွင် တွေ့ရသော အကြိမ်ရေဖြစ်သည်၊ ဒါဟာ ကျွန်တော်တို့ အရင်က တွေ့ခဲ့တဲ့ BoW တန်ဖိုးဖြစ်သည်\n",
|
||||
"* $N$ သည် စုစုပေါင်း စာရွက်စာတမ်းအရေအတွက်ဖြစ်သည်\n",
|
||||
"* $df_i$ သည် စကားလုံး $i$ ကို စုစုပေါင်း စာရွက်စာတမ်းများတွင် ပါဝင်သော စာရွက်စာတမ်းအရေအတွက်ဖြစ်သည်\n",
|
||||
"\n",
|
||||
"TF-IDF တန်ဖိုး $w_{ij}$ သည် စကားလုံးတစ်ခုသည် စာရွက်စာတမ်းတွင် ပါဝင်သော အကြိမ်ရေအတိုင်း တိုးမြှင့်ပြီး corpus တွင် စကားလုံးပါဝင်သော စာရွက်စာတမ်းအရေအတွက်ကို အလေးပေးမှုဖြင့် လျှော့ချသည်။ ၎င်းသည် စကားလုံးတစ်ချို့သည် အခြားစကားလုံးများထက် မကြာခဏ တွေ့ရသည်ဆိုသော အချက်ကို ပြင်ဆင်ရန် အထောက်အကူပြုသည်။ ဥပမာအားဖြင့် စကားလုံးတစ်ခုသည် စုစုပေါင်း စာရွက်စာတမ်းများ *အားလုံး* တွင် ပါဝင်လျှင် $df_i=N$ ဖြစ်ပြီး $w_{ij}=0$ ဖြစ်သည်။ ထို့ကြောင့် စကားလုံးများကို လုံးဝ မထည့်သွင်းစဉ်းစားတော့ပါ။\n",
|
||||
"\n",
|
||||
"Scikit Learn ကို အသုံးပြု၍ TF-IDF vectorization ကို လွယ်ကူစွာ ဖန်တီးနိုင်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[0.43381609, 0. , 0.43381609, 0. , 0.65985664,\n",
|
||||
" 0.43381609, 0. , 0. , 0. , 0. ,\n",
|
||||
" 0. , 0. , 0. , 0. , 0. ,\n",
|
||||
" 0. ]])"
|
||||
]
|
||||
},
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from sklearn.feature_extraction.text import TfidfVectorizer\n",
|
||||
"vectorizer = TfidfVectorizer(ngram_range=(1,2))\n",
|
||||
"vectorizer.fit_transform(corpus)\n",
|
||||
"vectorizer.transform(['My dog likes hot dogs on a hot day.']).toarray()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Keras တွင် `TextVectorization` layer သည် `output_mode='tf-idf'` parameter ကို ဖြတ်သွားခြင်းဖြင့် TF-IDF frequency များကို အလိုအလျောက်တွက်ချက်နိုင်သည်။ TF-IDF ကို အသုံးပြုခြင်းက တိကျမှုကို တိုးမြှင့်ပေးနိုင်မည်လားဆိုတာကို ကြည့်ရန် အထက်တွင် အသုံးပြုခဲ့သော code ကို ထပ်မံလုပ်ဆောင်ကြည့်ပါ။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Training vectorizer\n",
|
||||
"938/938 [==============================] - 12s 12ms/step - loss: 0.4197 - acc: 0.8662 - val_loss: 0.3432 - val_acc: 0.8849\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<keras.callbacks.History at 0x20c729dfd30>"
|
||||
]
|
||||
},
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model = keras.models.Sequential([\n",
|
||||
" keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,output_mode='tf-idf'),\n",
|
||||
" keras.layers.Dense(4,input_shape=(vocab_size,), activation='softmax')\n",
|
||||
"])\n",
|
||||
"print(\"Training vectorizer\")\n",
|
||||
"model.layers[0].adapt(ds_train.take(500).map(extract_text))\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',optimizer='adam',metrics=['acc'])\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## အနှစ်ချုပ်\n",
|
||||
"\n",
|
||||
"TF-IDF ကိုယ်စားပြုမှုများသည် စကားလုံးများအတွက် ကြိမ်နှုန်းအလေးချိန်များကို ပေးနိုင်သော်လည်း အဓိပ္ပါယ် သို့မဟုတ် အစီအစဉ်ကို ကိုယ်စားပြုနိုင်ခြင်း မရှိပါ။ 1935 ခုနှစ်တွင် နာမည်ကြီး ဘာသာဗေဒပညာရှင် J. R. Firth က ပြောခဲ့သလို၊ \"စကားလုံးတစ်လုံး၏ အပြည့်အစုံသော အဓိပ္ပါယ်သည် အမြဲတမ်း အခြေအနေအရသာသာ ရှိနိုင်ပြီး အခြေအနေမှ ကွဲလွဲသော အဓိပ္ပါယ်ကို လေ့လာခြင်းသည် အလေးထားစဉ်းစားရန် မဖြစ်နိုင်ပါ။\" ကျွန်ုပ်တို့သည် သင်တန်း၏ နောက်ပိုင်းတွင် ဘာသာစကား မော်ဒယ်တစ်ခုကို အသုံးပြု၍ စာသားမှ အခြေအနေဆိုင်ရာ အချက်အလက်များကို ဖမ်းယူနည်းကို လေ့လာသွားပါမည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေပါသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်မှုများတွင် အမှားများ သို့မဟုတ် မတိကျမှုများ ပါရှိနိုင်သည်ကို သတိပြုပါ။ မူရင်းဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာရှိသော ရင်းမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူက ဘာသာပြန်မှု ဝန်ဆောင်မှုကို အသုံးပြုရန် အကြံပြုပါသည်။ ဤဘာသာပြန်မှုကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားလွဲမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "0cb620c6d4b9f7a635928804c26cf22403d89d98d79684e4529119355ee6d5a5"
|
||||
},
|
||||
"kernel_info": {
|
||||
"name": "conda-env-py37_tensorflow-py"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "py37_tensorflow",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"nteract": {
|
||||
"version": "nteract-front-end@1.0.0"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "19b43951d55b377a76209c24c1f017e4",
|
||||
"translation_date": "2025-08-30T10:45:25+00:00",
|
||||
"source_file": "lessons/5-NLP/13-TextRep/TextRepresentationTF.ipynb",
|
||||
"language_code": "my"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -0,0 +1,721 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Embeddings\n",
|
||||
"\n",
|
||||
"ယခင်ဥပမာတွင် ကျွန်ုပ်တို့သည် `vocab_size` အရှည်ရှိ အမြင့်မားသော dimension bag-of-words vectors များကို အသုံးပြုခဲ့ပြီး၊ အနိမ့် dimension positional representation vectors များမှ sparse one-hot representation သို့ တိတိကျကျ ပြောင်းလဲခဲ့ပါသည်။ သို့သော်၊ one-hot representation သည် memory ကို ထိရောက်စွာ အသုံးမပြုနိုင်သလို၊ စကားလုံးတစ်လုံးချင်းစီကိုလည်း အချင်းချင်း သီးခြားစီ ဆက်စပ်မှုမရှိဘဲ ဆက်ဆံထားသည်။ အဆိုပါ one-hot encoded vectors များသည် စကားလုံးများအကြား အဓိပ္ပါယ်ဆိုင်ရာ ဆင်တူမှုများကို မဖော်ပြနိုင်ပါ။\n",
|
||||
"\n",
|
||||
"ဤယူနစ်တွင် ကျွန်ုပ်တို့သည် **News AG** dataset ကို ဆက်လက်လေ့လာသွားမည်ဖြစ်သည်။ စတင်ရန်အတွက် ဒေတာများကို load ပြုလုပ်ပြီး ယခင် notebook မှ အဓိပ္ပါယ်ဖွင့်ဆိုချက်များကို ရယူကြပါစို့။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Loading dataset...\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"d:\\WORK\\ai-for-beginners\\5-NLP\\14-Embeddings\\data\\train.csv: 29.5MB [00:01, 18.8MB/s] \n",
|
||||
"d:\\WORK\\ai-for-beginners\\5-NLP\\14-Embeddings\\data\\test.csv: 1.86MB [00:00, 11.2MB/s] \n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Building vocab...\n",
|
||||
"Vocab size = 95812\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import torch\n",
|
||||
"import torchtext\n",
|
||||
"import numpy as np\n",
|
||||
"from torchnlp import *\n",
|
||||
"train_dataset, test_dataset, classes, vocab = load_dataset()\n",
|
||||
"vocab_size = len(vocab)\n",
|
||||
"print(\"Vocab size = \",vocab_size)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Embedding ဆိုတာဘာလဲ?\n",
|
||||
"\n",
|
||||
"**Embedding** ဆိုတာက စကားလုံးတွေကို အနည်းဆုံး dimension ရှိတဲ့ dense vector တွေဖြင့် ကိုယ်စားပြုဖော်ပြတာဖြစ်ပြီး၊ စကားလုံးတစ်လုံးရဲ့ အဓိပ္ပါယ်ဆိုင်ရာ အနက်ကို တစ်နည်းနည်းနဲ့ ပြသပေးတာဖြစ်ပါတယ်။ စကားလုံး embedding တွေကို ဘယ်လို အဓိပ္ပါယ်ရှိအောင် ဖန်တီးမလဲဆိုတာကို နောက်ပိုင်းမှာ ဆွေးနွေးပေးပါမယ်၊ ဒါပေမယ့် အခုအချိန်မှာတော့ embedding ကို စကားလုံး vector ရဲ့ dimension ကို လျှော့ချတဲ့ နည်းလမ်းတစ်ခုအနေနဲ့ သာ စဉ်းစားကြည့်ပါ။\n",
|
||||
"\n",
|
||||
"ဒါကြောင့် embedding layer က စကားလုံးတစ်လုံးကို input အနေနဲ့ ယူပြီး၊ သတ်မှတ်ထားတဲ့ `embedding_size` ရဲ့ output vector ကို ထုတ်ပေးပါမယ်။ တစ်နည်းအားဖြင့်၊ ဒါဟာ `Linear` layer နဲ့ ဆင်တူပါတယ်၊ ဒါပေမယ့် one-hot encoded vector ကို ယူမယ့်အစား၊ စကားလုံးနံပါတ်ကို input အနေနဲ့ ယူနိုင်မှာ ဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"ကျွန်တော်တို့ network ရဲ့ ပထမဆုံး layer အနေနဲ့ embedding layer ကို သုံးခြင်းအားဖြင့်၊ bag-of-words မှ **embedding bag** မော်ဒယ်ဆီကို ပြောင်းနိုင်ပါတယ်။ ဒီမှာ ကျွန်တော်တို့ရဲ့ စာသားထဲက စကားလုံးတစ်လုံးစီကို သက်ဆိုင်ရာ embedding ကို ပြောင်းပြီး၊ ထို embedding တွေကို `sum`၊ `average` သို့မဟုတ် `max` ကဲ့သို့သော aggregate function တစ်ခုခုကို တွက်ချက်ပေးပါမယ်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"ကျွန်တော်တို့ရဲ့ classifier neural network က embedding layer နဲ့ စပြီး၊ aggregation layer နဲ့ linear classifier ကို အပေါ်မှာ ထည့်သွင်းထားပါမယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class EmbedClassifier(torch.nn.Module):\n",
|
||||
" def __init__(self, vocab_size, embed_dim, num_class):\n",
|
||||
" super().__init__()\n",
|
||||
" self.embedding = torch.nn.Embedding(vocab_size, embed_dim)\n",
|
||||
" self.fc = torch.nn.Linear(embed_dim, num_class)\n",
|
||||
"\n",
|
||||
" def forward(self, x):\n",
|
||||
" x = self.embedding(x)\n",
|
||||
" x = torch.mean(x,dim=1)\n",
|
||||
" return self.fc(x)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### အရွယ်အစား မတူညီသော variable sequence ကို ကိုင်တွယ်ခြင်း\n",
|
||||
"\n",
|
||||
"ဒီ architecture ရဲ့ ရလဒ်အနေနဲ့, network အတွက် minibatches တွေကို တစ်သတ်မှတ်နည်းလမ်းနဲ့ ဖန်တီးဖို့ လိုအပ်လာမယ်။ ယခင်ယူနစ်မှာ bag-of-words ကို အသုံးပြုတဲ့အခါ, minibatch ထဲမှာရှိတဲ့ BoW tensors အားလုံးဟာ `vocab_size` အရွယ်အစားတူညီနေခဲ့တယ်၊ ကျွန်တော်တို့ရဲ့ text sequence ရဲ့ အရှည်ကိုမထည့်သွင်းစဉ်းစားဘဲ။ ဒါပေမယ့် word embeddings ကို အသုံးပြုတဲ့အခါ, တစ်ခုချင်းစီ text sample မှာ စကားလုံးအရေအတွက် မတူညီလာနိုင်ပြီး, အဲ့ဒီ samples တွေကို minibatches အဖြစ် ပေါင်းစည်းတဲ့အခါ padding တစ်ခုခုကို အသုံးပြုဖို့ လိုအပ်လာမယ်။\n",
|
||||
"\n",
|
||||
"ဒါကို datasource ကို `collate_fn` function ပေးခြင်းနဲ့ တူညီတဲ့နည်းလမ်းကို အသုံးပြုပြီး လုပ်ဆောင်နိုင်ပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def padify(b):\n",
|
||||
" # b is the list of tuples of length batch_size\n",
|
||||
" # - first element of a tuple = label, \n",
|
||||
" # - second = feature (text sequence)\n",
|
||||
" # build vectorized sequence\n",
|
||||
" v = [encode(x[1]) for x in b]\n",
|
||||
" # first, compute max length of a sequence in this minibatch\n",
|
||||
" l = max(map(len,v))\n",
|
||||
" return ( # tuple of two tensors - labels and features\n",
|
||||
" torch.LongTensor([t[0]-1 for t in b]),\n",
|
||||
" torch.stack([torch.nn.functional.pad(torch.tensor(t),(0,l-len(t)),mode='constant',value=0) for t in v])\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=padify, shuffle=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### အထွေထွေ Embedding Classifier ကိုလေ့ကျင့်ခြင်း\n",
|
||||
"\n",
|
||||
"အခုတော့ သင့်တော်သော dataloader ကိုသတ်မှတ်ပြီးသားဖြစ်သောကြောင့် ယခင်ယူနစ်တွင်သတ်မှတ်ထားသောလေ့ကျင့်မှု function ကိုအသုံးပြု၍ မော်ဒယ်ကိုလေ့ကျင့်နိုင်ပါပြီ။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3200: acc=0.6415625\n",
|
||||
"6400: acc=0.6865625\n",
|
||||
"9600: acc=0.7103125\n",
|
||||
"12800: acc=0.726953125\n",
|
||||
"16000: acc=0.739375\n",
|
||||
"19200: acc=0.75046875\n",
|
||||
"22400: acc=0.7572321428571429\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(0.889799795315499, 0.7623160588611644)"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"net = EmbedClassifier(vocab_size,32,len(classes)).to(device)\n",
|
||||
"train_epoch(net,train_loader, lr=1, epoch_size=25000)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **မှတ်ချက်**: အချိန်သက်သာစေရန်အတွက် ဒီမှာ ၂၅,၀၀၀ မှတ်တမ်းပမာဏ (တစ်ခုလုံးသော epoch ထက်နည်း) ကိုသာလေ့ကျင့်နေပါသည်၊ သို့သော် သင်သည် လေ့ကျင့်မှုကို ဆက်လက်လုပ်ဆောင်နိုင်ပြီး၊ အတော်များများသော epoch များအတွက် လေ့ကျင့်ရန် function တစ်ခုရေးနိုင်ပြီး၊ သင့်တိုးတက်မှုနှုန်း parameter ကို စမ်းသပ်ခြင်းဖြင့် ပိုမိုမြင့်မားသော တိကျမှုရရှိရန် ကြိုးစားနိုင်ပါသည်။ သင်သည် ၉၀% အနီးအတောင်တိကျမှုကို ရောက်ရှိနိုင်သင့်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### EmbeddingBag Layer နှင့် အရှည်မတူညီသော အစီအစဉ်ကို ကိုယ်စားပြုခြင်း\n",
|
||||
"\n",
|
||||
"ယခင် အဆောက်အအုံတွင်၊ minibatch ထဲသို့ ထည့်သွင်းနိုင်ရန် အစီအစဉ်အားလုံးကို အရှည်တူအောင် pad လုပ်ရန် လိုအပ်ခဲ့သည်။ သို့သော်၊ အရှည်မတူညီသော အစီအစဉ်များကို ကိုယ်စားပြုရန်အတွက် ဤနည်းလမ်းသည် အကျိုးရှိဆုံးမဟုတ်ပါ။ အခြားနည်းလမ်းတစ်ခုမှာ **offset** vector ကို အသုံးပြုခြင်းဖြစ်ပြီး၊ ၎င်းသည် အစီအစဉ်အားလုံး၏ offsets ကို တစ်ခုတည်းသော vector အကြီးထဲတွင် သိမ်းဆည်းထားမည်ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"> **Note**: အထက်ပါ ပုံတွင် အက္ခရာများ၏ အစီအစဉ်ကို ပြထားသော်လည်း၊ ကျွန်ုပ်တို့၏ ဥပမာတွင် စကားလုံးများ၏ အစီအစဉ်များနှင့် အလုပ်လုပ်နေပါသည်။ သို့သော်၊ offset vector ဖြင့် အစီအစဉ်များကို ကိုယ်စားပြုခြင်း၏ အခြေခံသဘောတရားမှာ မပြောင်းလဲပါ။\n",
|
||||
"\n",
|
||||
"Offset ကိုယ်စားပြုမှုနှင့် အလုပ်လုပ်ရန်၊ [`EmbeddingBag`](https://pytorch.org/docs/stable/generated/torch.nn.EmbeddingBag.html) layer ကို အသုံးပြုပါသည်။ ၎င်းသည် `Embedding` နှင့် ဆင်တူသော်လည်း၊ content vector နှင့် offset vector ကို input အဖြစ် လက်ခံပြီး၊ `mean`, `sum` သို့မဟုတ် `max` ဖြစ်နိုင်သော averaging layer ကိုလည်း ပါဝင်စေသည်။\n",
|
||||
"\n",
|
||||
"ဤနေရာတွင် `EmbeddingBag` ကို အသုံးပြုထားသော ပြင်ဆင်ထားသော network ကို ဖော်ပြထားသည်-\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class EmbedClassifier(torch.nn.Module):\n",
|
||||
" def __init__(self, vocab_size, embed_dim, num_class):\n",
|
||||
" super().__init__()\n",
|
||||
" self.embedding = torch.nn.EmbeddingBag(vocab_size, embed_dim)\n",
|
||||
" self.fc = torch.nn.Linear(embed_dim, num_class)\n",
|
||||
"\n",
|
||||
" def forward(self, text, off):\n",
|
||||
" x = self.embedding(text, off)\n",
|
||||
" return self.fc(x)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ဒေတာစနစ်ကိုလေ့ကျင့်ရန်အတွက် ပြင်ဆင်ရန် offset vector ကိုပြင်ဆင်ပေးမည့် conversion function ကိုပေးရန်လိုအပ်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def offsetify(b):\n",
|
||||
" # first, compute data tensor from all sequences\n",
|
||||
" x = [torch.tensor(encode(t[1])) for t in b]\n",
|
||||
" # now, compute the offsets by accumulating the tensor of sequence lengths\n",
|
||||
" o = [0] + [len(t) for t in x]\n",
|
||||
" o = torch.tensor(o[:-1]).cumsum(dim=0)\n",
|
||||
" return ( \n",
|
||||
" torch.LongTensor([t[0]-1 for t in b]), # labels\n",
|
||||
" torch.cat(x), # text \n",
|
||||
" o\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=offsetify, shuffle=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ယခင် ဥပမာများနှင့် မတူကွဲပြားစွာ၊ ယခုအခါ ကျွန်ုပ်တို့၏ network သည် parameter နှစ်ခုကို လက်ခံပါသည် - data vector နှင့် offset vector၊ အရွယ်အစားကွဲပြားမှုရှိသည်။ ထို့အပြင် ကျွန်ုပ်တို့၏ data loader သည် 2 ခုအစား 3 ခုသောတန်ဖိုးများကိုပေးသည် - text နှင့် offset vector နှစ်ခုစလုံးကို feature အဖြစ်ပေးသည်။ ထို့ကြောင့် ကျွန်ုပ်တို့၏ training function ကို အနည်းငယ်ပြင်ဆင်ရန်လိုအပ်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3200: acc=0.6153125\n",
|
||||
"6400: acc=0.6615625\n",
|
||||
"9600: acc=0.6932291666666667\n",
|
||||
"12800: acc=0.715078125\n",
|
||||
"16000: acc=0.7270625\n",
|
||||
"19200: acc=0.7382291666666667\n",
|
||||
"22400: acc=0.7486160714285715\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(22.771553103007037, 0.7551983365323096)"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"net = EmbedClassifier(vocab_size,32,len(classes)).to(device)\n",
|
||||
"\n",
|
||||
"def train_epoch_emb(net,dataloader,lr=0.01,optimizer=None,loss_fn = torch.nn.CrossEntropyLoss(),epoch_size=None, report_freq=200):\n",
|
||||
" optimizer = optimizer or torch.optim.Adam(net.parameters(),lr=lr)\n",
|
||||
" loss_fn = loss_fn.to(device)\n",
|
||||
" net.train()\n",
|
||||
" total_loss,acc,count,i = 0,0,0,0\n",
|
||||
" for labels,text,off in dataloader:\n",
|
||||
" optimizer.zero_grad()\n",
|
||||
" labels,text,off = labels.to(device), text.to(device), off.to(device)\n",
|
||||
" out = net(text, off)\n",
|
||||
" loss = loss_fn(out,labels) #cross_entropy(out,labels)\n",
|
||||
" loss.backward()\n",
|
||||
" optimizer.step()\n",
|
||||
" total_loss+=loss\n",
|
||||
" _,predicted = torch.max(out,1)\n",
|
||||
" acc+=(predicted==labels).sum()\n",
|
||||
" count+=len(labels)\n",
|
||||
" i+=1\n",
|
||||
" if i%report_freq==0:\n",
|
||||
" print(f\"{count}: acc={acc.item()/count}\")\n",
|
||||
" if epoch_size and count>epoch_size:\n",
|
||||
" break\n",
|
||||
" return total_loss.item()/count, acc.item()/count\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"train_epoch_emb(net,train_loader, lr=4, epoch_size=25000)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Semantic Embeddings: Word2Vec\n",
|
||||
"\n",
|
||||
"ယခင်ဥပမာတွင် မော်ဒယ်၏ embedding layer သည် စကားလုံးများကို ဗက်တာအနေနဲ့ ဖော်ပြဖို့ သင်ယူခဲ့ပေမယ့်၊ အဲဒီဖော်ပြမှုမှာ အဓိပ္ပါယ်ဆိုင်ရာ အနက်အဓိပ္ပါယ်များ မပါရှိသလောက်ပါ။ စကားလုံးများကို ဗက်တာအနေနဲ့ ဖော်ပြရာမှာ၊ အဓိပ္ပါယ်တူသော စကားလုံးများ (သို့) အနီးစပ်ဆုံးသော စကားလုံးများသည် ဗက်တာအကွာအဝေး (ဥပမာ euclidian distance) အရ နီးစပ်နေမယ့် representation ကို သင်ယူနိုင်ရင် ပိုကောင်းမယ်လို့ ထင်ရပါတယ်။\n",
|
||||
"\n",
|
||||
"ဒါကို ပြုလုပ်ဖို့အတွက်၊ ကျွန်တော်တို့ရဲ့ embedding မော်ဒယ်ကို စာသားအစုကြီးတစ်ခုအပေါ်မှာ အထူးနည်းလမ်းတစ်ခုနဲ့ ကြိုတင်သင်ယူစေဖို့ လိုအပ်ပါတယ်။ အဓိပ္ပါယ်ဆိုင်ရာ embedding များကို သင်ယူစေဖို့ ပထမဆုံးနည်းလမ်းများထဲက တစ်ခုကို [Word2Vec](https://en.wikipedia.org/wiki/Word2vec) လို့ ခေါ်ပါတယ်။ ဒါဟာ စကားလုံးများကို ဖြန့်ဖြူးထားသော representation အဖြစ် ဖန်တီးဖို့ အသုံးပြုတဲ့ အဓိက architecture နှစ်ခုအပေါ်မှာ အခြေခံထားပါတယ်-\n",
|
||||
"\n",
|
||||
" - **Continuous bag-of-words** (CBoW) — ဒီ architecture မှာ မော်ဒယ်ကို ပတ်ဝန်းကျင်အကြောင်းအရာကနေ စကားလုံးတစ်လုံးကို ခန့်မှန်းဖို့ သင်ကြားပေးပါတယ်။ ngram $(W_{-2},W_{-1},W_0,W_1,W_2)$ ကို ပေးထားတဲ့အခါ၊ မော်ဒယ်ရဲ့ ရည်မှန်းချက်က $(W_{-2},W_{-1},W_1,W_2)$ ကနေ $W_0$ ကို ခန့်မှန်းဖို့ ဖြစ်ပါတယ်။\n",
|
||||
" - **Continuous skip-gram** — CBoW ရဲ့ ဆန့်ကျင်ဘက်ဖြစ်ပါတယ်။ ဒီမော်ဒယ်က ပတ်ဝန်းကျင်အကြောင်းအရာ စကားလုံးများကို အသုံးပြုပြီး လက်ရှိစကားလုံးကို ခန့်မှန်းပါတယ်။\n",
|
||||
"\n",
|
||||
"CBoW က ပိုမြန်ပါတယ်၊ skip-gram က ပိုနှေးပေမယ့် မကြာခဏ မတွေ့ရတဲ့ စကားလုံးများကို ပိုကောင်းစွာ ဖော်ပြနိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"Google News dataset ပေါ်မှာ ကြိုတင်သင်ယူထားတဲ့ word2vec embedding ကို စမ်းသပ်ဖို့၊ **gensim** library ကို အသုံးပြုနိုင်ပါတယ်။ အောက်မှာ 'neural' နဲ့ အနီးဆုံးသော စကားလုံးများကို ရှာဖွေထားပါတယ်-\n",
|
||||
"\n",
|
||||
"> **Note:** စကားလုံးဗက်တာများကို ပထမဆုံး ဖန်တီးတဲ့အခါ၊ အဲဒီဗက်တာများကို ဒေါင်းလုပ်လုပ်ရတာ အချိန်အတော်ကြာနိုင်ပါတယ်!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import gensim.downloader as api\n",
|
||||
"w2v = api.load('word2vec-google-news-300')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"neuronal -> 0.7804799675941467\n",
|
||||
"neurons -> 0.7326500415802002\n",
|
||||
"neural_circuits -> 0.7252851724624634\n",
|
||||
"neuron -> 0.7174385190010071\n",
|
||||
"cortical -> 0.6941086649894714\n",
|
||||
"brain_circuitry -> 0.6923246383666992\n",
|
||||
"synaptic -> 0.6699118614196777\n",
|
||||
"neural_circuitry -> 0.6638563275337219\n",
|
||||
"neurochemical -> 0.6555314064025879\n",
|
||||
"neuronal_activity -> 0.6531826257705688\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"for w,p in w2v.most_similar('neural'):\n",
|
||||
" print(f\"{w} -> {p}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့သည် စကားလုံးမှ ဗက်တာအင်ဘက်ဒ်များကိုလည်းတွက်ချက်နိုင်ပြီး အမျိုးအစားခွဲခြားမှုမော်ဒယ်ကိုလေ့ကျင့်ရန်အသုံးပြုနိုင်ပါသည် (ရှင်းလင်းမှုအတွက် ဗက်တာ၏ပထမ ၂၀ ခုအစိတ်အပိုင်းများကိုသာပြသပါသည်)။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([ 0.01226807, 0.06225586, 0.10693359, 0.05810547, 0.23828125,\n",
|
||||
" 0.03686523, 0.05151367, -0.20703125, 0.01989746, 0.10058594,\n",
|
||||
" -0.03759766, -0.1015625 , -0.15820312, -0.08105469, -0.0390625 ,\n",
|
||||
" -0.05053711, 0.16015625, 0.2578125 , 0.10058594, -0.25976562],\n",
|
||||
" dtype=float32)"
|
||||
]
|
||||
},
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"w2v.word_vec('play')[:20]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"('queen', 0.7118192911148071)"
|
||||
]
|
||||
},
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"w2v.most_similar(positive=['king','woman'],negative=['man'])[0]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"CBoW နဲ့ Skip-Grams နှစ်ခုလုံးဟာ “predictive” embeddings ဖြစ်ပြီး၊ ဒါတွေက အနီးအနားက context တွေကိုပဲ အဓိကထားပါတယ်။ Word2Vec က global context ကို အသုံးမပြုပါဘူး။\n",
|
||||
"\n",
|
||||
"**FastText** က Word2Vec အပေါ်မှာ တိုးတက်မှုတစ်ခုဖြစ်ပြီး၊ စကားလုံးတစ်လုံးစီအတွက် vector ကို သင်ယူရုံမက၊ စကားလုံးတစ်လုံးအတွင်းရှိ character n-grams တွေကိုပါ သင်ယူပါတယ်။ ဒီ representation တွေကို training တစ်ကြိမ်စီမှာ vector တစ်ခုအဖြစ် ပျမ်းမျှတွက်ချက်ပေးပါတယ်။ ဒါက pre-training အတွက် အချိန်ပိုကုန်စေသော်လည်း၊ word embeddings တွေမှာ sub-word information ကို encode လုပ်နိုင်စေပါတယ်။\n",
|
||||
"\n",
|
||||
"အခြားနည်းလမ်းတစ်ခုဖြစ်တဲ့ **GloVe** က co-occurrence matrix ရဲ့ အယူအဆကို အသုံးပြုပြီး၊ co-occurrence matrix ကို neural methods တွေသုံးပြီး ပိုမိုဖော်ပြနိုင်တဲ့၊ nonlinear word vectors တွေအဖြစ် ခွဲထုတ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"သင် gensim က support လုပ်ပေးတဲ့ word embedding models အမျိုးမျိုးကို အသုံးပြုပြီး၊ embeddings ကို FastText နဲ့ GloVe အဖြစ် ပြောင်းလဲပြီး စမ်းသပ်ကြည့်နိုင်ပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## PyTorch တွင် Pre-Trained Embeddings ကို အသုံးပြုခြင်း\n",
|
||||
"\n",
|
||||
"အထက်ပါ ဥပမာကို ပြောင်းလဲပြီး၊ Word2Vec ကဲ့သို့သော အဓိပ္ပါယ်ဆိုင်ရာ embeddings များဖြင့် ကျွန်ုပ်တို့၏ embedding layer တွင် matrix ကို ကြိုတင်ဖြည့်စွက်နိုင်ပါသည်။ Pre-trained embedding ၏ vocabulary နှင့် ကျွန်ုပ်တို့၏ text corpus ၏ vocabulary များသည် မျှမတူနိုင်ကြောင်းကို သတိပြုရမည်ဖြစ်ပြီး၊ မပါဝင်သော စကားလုံးများအတွက် weight များကို အလွတ်တစ်ဆင့်ဖြင့် initialize လုပ်မည်ဖြစ်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Embedding size: 300\n",
|
||||
"Populating matrix, this will take some time...Done, found 41080 words, 54732 words missing\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"embed_size = len(w2v.get_vector('hello'))\n",
|
||||
"print(f'Embedding size: {embed_size}')\n",
|
||||
"\n",
|
||||
"net = EmbedClassifier(vocab_size,embed_size,len(classes))\n",
|
||||
"\n",
|
||||
"print('Populating matrix, this will take some time...',end='')\n",
|
||||
"found, not_found = 0,0\n",
|
||||
"for i,w in enumerate(vocab.get_itos()):\n",
|
||||
" try:\n",
|
||||
" net.embedding.weight[i].data = torch.tensor(w2v.get_vector(w))\n",
|
||||
" found+=1\n",
|
||||
" except:\n",
|
||||
" net.embedding.weight[i].data = torch.normal(0.0,1.0,(embed_size,))\n",
|
||||
" not_found+=1\n",
|
||||
"\n",
|
||||
"print(f\"Done, found {found} words, {not_found} words missing\")\n",
|
||||
"net = net.to(device)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3200: acc=0.6359375\n",
|
||||
"6400: acc=0.68109375\n",
|
||||
"9600: acc=0.7067708333333333\n",
|
||||
"12800: acc=0.723671875\n",
|
||||
"16000: acc=0.73625\n",
|
||||
"19200: acc=0.7463541666666667\n",
|
||||
"22400: acc=0.7560714285714286\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(214.1013875559821, 0.7626759436980166)"
|
||||
]
|
||||
},
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"train_epoch_emb(net,train_loader, lr=4, epoch_size=25000)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်တော်တို့အနေဖြင့် တိကျမှုမှာ အလွန်များပြားသော တိုးတက်မှုကို မတွေ့ရပါဘူး၊ ဒါဟာ အလွန်ကွဲပြားတဲ့ ဝေါဟာရများကြောင့် ဖြစ်နိုင်ပါတယ်။ \n",
|
||||
"ကွဲပြားတဲ့ ဝေါဟာရများကြောင့် ဖြစ်ပေါ်လာတဲ့ ပြဿနာကို ဖြေရှင်းရန် အောက်ပါနည်းလမ်းများကို အသုံးပြုနိုင်ပါတယ်- \n",
|
||||
"* word2vec မော်ဒယ်ကို ကျွန်တော်တို့ရဲ့ ဝေါဟာရပေါ်မှာ ပြန်လည်လေ့ကျင့်ပါ \n",
|
||||
"* word2vec မော်ဒယ်ကို ကြိုတင်လေ့ကျင့်ထားတဲ့ ဝေါဟာရနဲ့ dataset ကို load လုပ်ပါ။ Dataset ကို load လုပ်တဲ့အခါ အသုံးပြုမယ့် ဝေါဟာရကို သတ်မှတ်နိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"နောက်ဆုံးနည်းလမ်းက ပိုမိုလွယ်ကူသလို PyTorch `torchtext` framework မှာ embedding တွေအတွက် built-in support ပါဝင်တာကြောင့် ပိုမိုအဆင်ပြေပါတယ်။ \n",
|
||||
"ဥပမာအားဖြင့် GloVe-based vocabulary ကို အောက်ပါနည်းလမ်းဖြင့် instantiate လုပ်နိုင်ပါတယ်- \n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"100%|█████████▉| 399999/400000 [00:15<00:00, 25411.14it/s]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vocab = torchtext.vocab.GloVe(name='6B', dim=50)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အသုံးပြုနိုင်သော ဝေါဟာရတွင် အခြေခံ လုပ်ဆောင်ချက်များ ရှိပါသည်။\n",
|
||||
"* `vocab.stoi` dictionary သည် စကားလုံးကို ၎င်း၏ အညွှန်းနံပါတ်သို့ ပြောင်းလဲရန် အကူအညီပေးသည်။\n",
|
||||
"* `vocab.itos` သည် ဆန့်ကျင်ဘက်လုပ်ဆောင်ချက်ကို ပြုလုပ်သည် - နံပါတ်ကို စကားလုံးသို့ ပြောင်းလဲသည်။\n",
|
||||
"* `vocab.vectors` သည် embedding vectors များပါဝင်သော array ဖြစ်ပြီး၊ စကားလုံး `s` ၏ embedding ကို ရယူရန် `vocab.vectors[vocab.stoi[s]]` ကို အသုံးပြုရမည်။\n",
|
||||
"\n",
|
||||
"ဤသည်မှာ **kind-man+woman = queen** ဆိုသော သင်္ချာကို ပြသရန် embedding များကို ပြောင်းလဲအသုံးပြုသည့် ဥပမာတစ်ခုဖြစ်သည် (အလုပ်ဖြစ်စေရန် coefficient ကို အနည်းငယ် ပြင်ဆင်ခဲ့ရသည်)။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'queen'"
|
||||
]
|
||||
},
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# get the vector corresponding to kind-man+woman\n",
|
||||
"qvec = vocab.vectors[vocab.stoi['king']]-vocab.vectors[vocab.stoi['man']]+1.3*vocab.vectors[vocab.stoi['woman']]\n",
|
||||
"# find the index of the closest embedding vector \n",
|
||||
"d = torch.sum((vocab.vectors-qvec)**2,dim=1)\n",
|
||||
"min_idx = torch.argmin(d)\n",
|
||||
"# find the corresponding word\n",
|
||||
"vocab.itos[min_idx]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ဒေါင်းလုပ်များကို အသုံးပြု၍ classifier ကို လေ့ကျင့်ရန်အတွက်၊ ကျွန်ုပ်တို့၏ dataset ကို GloVe vocabulary ကို အသုံးပြု၍ encode လုပ်ရန်အရင်လိုအပ်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def offsetify(b):\n",
|
||||
" # first, compute data tensor from all sequences\n",
|
||||
" x = [torch.tensor(encode(t[1],voc=vocab)) for t in b] # pass the instance of vocab to encode function!\n",
|
||||
" # now, compute the offsets by accumulating the tensor of sequence lengths\n",
|
||||
" o = [0] + [len(t) for t in x]\n",
|
||||
" o = torch.tensor(o[:-1]).cumsum(dim=0)\n",
|
||||
" return ( \n",
|
||||
" torch.LongTensor([t[0]-1 for t in b]), # labels\n",
|
||||
" torch.cat(x), # text \n",
|
||||
" o\n",
|
||||
" )"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အပေါ်တွင်မြင်တွေ့ခဲ့သည့်အတိုင်း၊ vector embedding အားလုံးကို `vocab.vectors` matrix တွင်သိမ်းဆည်းထားသည်။ ၎င်းကို embedding layer ၏ weight များထဲသို့ရိုးရှင်းသောကူးယူမှုကိုအသုံးပြု၍ weight များထည့်သွင်းရန်အလွန်လွယ်ကူစေသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"net = EmbedClassifier(len(vocab),len(vocab.vectors[0]),len(classes))\n",
|
||||
"net.embedding.weight.data = vocab.vectors\n",
|
||||
"net = net.to(device)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3200: acc=0.6271875\n",
|
||||
"6400: acc=0.68078125\n",
|
||||
"9600: acc=0.7030208333333333\n",
|
||||
"12800: acc=0.71984375\n",
|
||||
"16000: acc=0.7346875\n",
|
||||
"19200: acc=0.7455729166666667\n",
|
||||
"22400: acc=0.7529464285714286\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(35.53972978646833, 0.7575175943698017)"
|
||||
]
|
||||
},
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=offsetify, shuffle=True)\n",
|
||||
"train_epoch_emb(net,train_loader, lr=4, epoch_size=25000)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့ အချက်အလက်များတွင် ပါဝင်သော စကားလုံးများအနက် အချို့သည် ကြိုတင်လေ့ကျင့်ထားသော GloVe ဝေါဟာရတွင် မပါဝင်သောကြောင့် တိကျမှုမှာ အရေးပါသော တိုးတက်မှု မရှိခြင်း၏ အကြောင်းအရင်းများထဲမှ တစ်ခုဖြစ်သည်။ ထို့ကြောင့် အဆိုပါ စကားလုံးများကို အဓိကအားဖြင့် မထည့်သွင်းထားပါ။ ဤအချက်ကို ကျော်လွှားရန် ကျွန်ုပ်တို့၏ အချက်အလက်များပေါ်တွင် ကိုယ်ပိုင် embedding များကို လေ့ကျင့်နိုင်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## အကြောင်းအရာအခြေခံ Embeddings\n",
|
||||
"\n",
|
||||
"Word2Vec ကဲ့သို့သော ရိုးရာ pretrained embedding ကိုယ်စားပြုမှုများ၏ အဓိက ကန့်သတ်ချက်တစ်ခုမှာ စကားလုံးအဓိပ္ပါယ်ရှင်းလင်းမှု၏ ပြဿနာဖြစ်သည်။ Pretrained embeddings များသည် စကားလုံးများ၏ အချို့သော အဓိပ္ပါယ်များကို အကြောင်းအရာအတွင်းမှ ဖမ်းဆီးနိုင်သော်လည်း၊ စကားလုံးတစ်လုံး၏ အားလုံးဖြစ်နိုင်သော အဓိပ္ပါယ်များကို တစ်ခုတည်းသော embedding အတွင်းတွင် encode လုပ်ထားသည်။ ဒါက Downstream မော်ဒယ်များတွင် ပြဿနာများ ဖြစ်ပေါ်စေတတ်သည်၊ အကြောင်းမူကား 'play' ကဲ့သို့သော စကားလုံးများသည် အသုံးပြုသည့် အကြောင်းအရာပေါ်မူတည်၍ အဓိပ္ပါယ်များကွဲပြားနိုင်သည်။\n",
|
||||
"\n",
|
||||
"ဥပမာအားဖြင့် 'play' စကားလုံးသည် အောက်ပါ စာကြောင်းနှစ်ခုတွင် အဓိပ္ပါယ်ကွဲပြားမှုများ ရှိသည်။\n",
|
||||
"- ကျွန်တော် **play** တစ်ခုကို ရုံတော်မှာ သွားကြည့်ခဲ့တယ်။\n",
|
||||
"- John က သူ့သူငယ်ချင်းတွေနဲ့ **play** လုပ်ချင်တယ်။\n",
|
||||
"\n",
|
||||
"အထက်ပါ pretrained embeddings များသည် 'play' စကားလုံး၏ အဓိပ္ပါယ်နှစ်ခုလုံးကို တစ်ခုတည်းသော embedding အတွင်းတွင် ကိုယ်စားပြုထားသည်။ ဒီကန့်သတ်ချက်ကို ကျော်လွှားရန် **ဘာသာစကားမော်ဒယ်** အပေါ် အခြေခံထားသော embeddings များကို တည်ဆောက်ရန် လိုအပ်သည်။ ဘာသာစကားမော်ဒယ်သည် စာသားများ၏ အကြီးမားသော corpus အပေါ်တွင် လေ့ကျင့်ထားပြီး စကားလုံးများကို အကြောင်းအရာကွဲပြားမှုများအတွင်းတွင် ဘယ်လိုပေါင်းစည်းနိုင်သည်ကို *သိ* နိုင်သည်။ Contextual embeddings ကို ဆွေးနွေးခြင်းသည် ဒီသင်ခန်းစာ၏ အကျိုးကျေးဇူးအတွင်း မပါဝင်သော်လည်း၊ ဘာသာစကားမော်ဒယ်များကို နောက်ထပ် unit တွင် ပြန်လည်ဆွေးနွေးမည်ဖြစ်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်မှုများတွင် အမှားများ သို့မဟုတ် မမှန်ကန်မှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းစာရွက်စာတမ်းကို ၎င်း၏ မူရင်းဘာသာစကားဖြင့် အာဏာတရ အရင်းအမြစ်အဖြစ် ရှုလေ့လာသင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူ့ဘာသာပြန်ပညာရှင်များမှ ပရော်ဖက်ရှင်နယ် ဘာသာပြန်မှုကို အကြံပြုပါသည်။ ဤဘာသာပြန်မှုကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားလွဲမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "0cb620c6d4b9f7a635928804c26cf22403d89d98d79684e4529119355ee6d5a5"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "py37_pytorch",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "f50b026abce5cf36783a560ea72cb9b1",
|
||||
"translation_date": "2025-08-30T10:39:43+00:00",
|
||||
"source_file": "lessons/5-NLP/14-Embeddings/EmbeddingsPyTorch.ipynb",
|
||||
"language_code": "my"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,689 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Embeddings\n",
|
||||
"\n",
|
||||
"ယခင်ဥပမာတွင်၊ ကျွန်ုပ်တို့သည် `vocab_size` အရှည်ရှိသော အမြင့်မားသည့် bag-of-words ဗက်တာများကို အသုံးပြုခဲ့ပြီး၊ အနိမ့်အတိုင်းအတာရှိသော positional representation ဗက်တာများကို sparse one-hot representation အဖြစ် သွင်းပြောင်းခဲ့ပါသည်။ သို့သော်၊ ဒီ one-hot representation သည် မှတ်ဉာဏ်အသုံးပြုမှုအရ အကျိုးမရှိပါ။ ထို့အပြင်၊ စကားလုံးတစ်လုံးစီကို သီးခြားစီ သတ်မှတ်ထားသောကြောင့်၊ one-hot encoded ဗက်တာများသည် စကားလုံးများအကြား အဓိပ္ပါယ်ဆိုင်ရာ ဆက်စပ်မှုများကို မဖော်ပြနိုင်ပါ။\n",
|
||||
"\n",
|
||||
"ဒီယူနစ်တွင်၊ ကျွန်ုပ်တို့သည် **News AG** ဒေတာစကင်ကို ဆက်လက်လေ့လာသွားမည်ဖြစ်သည်။ စတင်ရန်အတွက်၊ ဒေတာကို load ပြုလုပ်ပြီး ယခင်ယူနစ်မှ အဓိပ္ပါယ်ဖွင့်ဆိုချက်များကို ပြန်လည်ရယူကြပါစို့။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import tensorflow as tf\n",
|
||||
"from tensorflow import keras\n",
|
||||
"import tensorflow_datasets as tfds\n",
|
||||
"import numpy as np\n",
|
||||
"\n",
|
||||
"ds_train, ds_test = tfds.load('ag_news_subset').values()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Embedding ဆိုတာဘာလဲ?\n",
|
||||
"\n",
|
||||
"**Embedding** ဆိုတဲ့အယူအဆက စကားလုံးတွေကို အနိမ့်အတိုင်းအတာရှိတဲ့ ဒေတာအမျိုးအစား (dense vectors) တွေသုံးပြီး စကားလုံးရဲ့ အဓိပ္ပါယ်ကို ကိုယ်စားပြုဖို့ ရည်ရွယ်ပါတယ်။ နောက်ပိုင်းမှာ အဓိပ္ပါယ်ရှိတဲ့ စကားလုံး embedding တွေကို ဘယ်လိုတည်ဆောက်မလဲဆိုတာကို ဆွေးနွေးပေမယ့် အခုအချိန်မှာတော့ စကားလုံး vector ရဲ့ dimensionality ကို လျှော့ချဖို့ နည်းလမ်းတစ်ခုအနေနဲ့ embedding ကို သက်သက်ထင်မြင်ပါ။\n",
|
||||
"\n",
|
||||
"Embedding layer က စကားလုံးတစ်လုံးကို input အနေနဲ့ယူပြီး `embedding_size` ဆိုတဲ့ အတိုင်းအတာရှိတဲ့ output vector ကို ထုတ်ပေးပါတယ်။ တစ်နည်းအားဖြင့်၊ ဒါဟာ `Dense` layer နဲ့ ဆင်တူပါတယ်၊ ဒါပေမယ့် one-hot encoded vector ကို input အနေနဲ့မယူဘဲ စကားလုံးနံပါတ်ကို input အနေနဲ့ယူနိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"ကျွန်တော်တို့ network ရဲ့ ပထမဆုံး layer အနေနဲ့ embedding layer ကို အသုံးပြုခြင်းအားဖြင့် bag-of-words နည်းလမ်းကနေ **embedding bag** မော်ဒယ်ဆီကို ပြောင်းနိုင်ပါတယ်။ ဒီမှာ ကျွန်တော်တို့ စာသားထဲက စကားလုံးတစ်လုံးချင်းစီကို သက်ဆိုင်ရာ embedding ကို ပြောင်းပြီး၊ အဲဒီ embedding တွေကို `sum`, `average`, `max` စတဲ့ aggregate function တစ်ခုခုနဲ့ တွက်ချက်ပေးနိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"ကျွန်တော်တို့ classifier neural network ရဲ့ layer တွေက အောက်ပါအတိုင်းဖြစ်ပါတယ်-\n",
|
||||
"\n",
|
||||
"* `TextVectorization` layer: ဒီ layer က string ကို input အနေနဲ့ယူပြီး token နံပါတ်တွေပါဝင်တဲ့ tensor ကို ထုတ်ပေးပါတယ်။ ကျွန်တော်တို့ `vocab_size` ဆိုတဲ့ reasonable vocabulary size ကို သတ်မှတ်ပြီး အသုံးနည်းတဲ့ စကားလုံးတွေကို မထည့်ပါဘူး။ Input shape က 1 ဖြစ်ပြီး Output shape က $n$ ဖြစ်ပါတယ်၊ အကြောင်းကတော့ $n$ tokens ရလို့ပါ၊ အဲဒီ token တစ်ခုချင်းစီမှာ 0 ကနေ `vocab_size` အတွင်းရှိ နံပါတ်တွေ ပါဝင်ပါတယ်။\n",
|
||||
"* `Embedding` layer: ဒီ layer က $n$ နံပါတ်တွေကိုယူပြီး နံပါတ်တစ်ခုချင်းစီကို သတ်မှတ်ထားတဲ့ အရှည် (ဥပမာ 100) ရှိတဲ့ dense vector ကို လျှော့ချပေးပါတယ်။ ဒါကြောင့် $n$ shape ရှိတဲ့ input tensor ကို $n\\times 100$ tensor အဖြစ် ပြောင်းပေးပါတယ်။\n",
|
||||
"* Aggregation layer: ဒီ layer က tensor ရဲ့ ပထမ axis အတိုင်းအတာကို average တွက်ချက်ပေးပါတယ်၊ ဒါဟာ input sequence တစ်ခုလုံးရဲ့ စုစုပေါင်း numeric ကိုယ်စားပြုမှု ဖြစ်ပါတယ်။ ဒီ layer ကို `Lambda` layer အသုံးပြုပြီး average တွက်ချက်တဲ့ function ကို ထည့်သွင်းပေးပါမယ်။ Output shape က 100 ဖြစ်ပြီး input sequence တစ်ခုလုံးရဲ့ ကိုယ်စားပြုမှု ဖြစ်ပါတယ်။\n",
|
||||
"* နောက်ဆုံး `Dense` linear classifier: Neural network ရဲ့ အဆုံး layer ဖြစ်ပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"sequential\"\n",
|
||||
"_________________________________________________________________\n",
|
||||
" Layer (type) Output Shape Param # \n",
|
||||
"=================================================================\n",
|
||||
" text_vectorization (TextVec (None, None) 0 \n",
|
||||
" torization) \n",
|
||||
" \n",
|
||||
" embedding (Embedding) (None, None, 100) 3000000 \n",
|
||||
" \n",
|
||||
" lambda (Lambda) (None, 100) 0 \n",
|
||||
" \n",
|
||||
" dense (Dense) (None, 4) 404 \n",
|
||||
" \n",
|
||||
"=================================================================\n",
|
||||
"Total params: 3,000,404\n",
|
||||
"Trainable params: 3,000,404\n",
|
||||
"Non-trainable params: 0\n",
|
||||
"_________________________________________________________________\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vocab_size = 30000\n",
|
||||
"batch_size = 128\n",
|
||||
"\n",
|
||||
"vectorizer = keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,input_shape=(1,))\n",
|
||||
"\n",
|
||||
"model = keras.models.Sequential([\n",
|
||||
" vectorizer, \n",
|
||||
" keras.layers.Embedding(vocab_size,100),\n",
|
||||
" keras.layers.Lambda(lambda x: tf.reduce_mean(x,axis=1)),\n",
|
||||
" keras.layers.Dense(4, activation='softmax')\n",
|
||||
"])\n",
|
||||
"model.summary()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"`summary` အတွင်းရှိ **output shape** ကော်လံမှာ ပထမဆုံး tensor အတိုင်းအတာ `None` ဟာ minibatch အရွယ်အစားကို ကိုယ်စားပြုပြီး ဒုတိယဟာ token အစဉ်အတိုင်းအတာရဲ့ အရှည်ကို ကိုယ်စားပြုပါတယ်။ Minibatch အတွင်းရှိ token အစဉ်တွေဟာ အရှည်တစ်ခုချင်းစီကွဲပြားပါတယ်။ ဒီအကြောင်းကို နောက်ပိုင်းအပိုင်းမှာ ဆွေးနွေးပါမယ်။\n",
|
||||
"\n",
|
||||
"အခု network ကို လေ့ကျင့်ကြစို့:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Training vectorizer\n",
|
||||
"938/938 [==============================] - 20s 20ms/step - loss: 0.7891 - acc: 0.8155 - val_loss: 0.4470 - val_acc: 0.8642\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<keras.callbacks.History at 0x22255515100>"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def extract_text(x):\n",
|
||||
" return x['title']+' '+x['description']\n",
|
||||
"\n",
|
||||
"def tupelize(x):\n",
|
||||
" return (extract_text(x),x['label'])\n",
|
||||
"\n",
|
||||
"print(\"Training vectorizer\")\n",
|
||||
"vectorizer.adapt(ds_train.take(500).map(extract_text))\n",
|
||||
"\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'])\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"nteract": {
|
||||
"transient": {
|
||||
"deleting": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
"> **မှတ်ချက်** ကျွန်ုပ်တို့သည် ဒေတာ၏ အပိုင်းခွဲတစ်ခုအပေါ် အခြေခံ၍ ဗက်တိုရာဇာကို တည်ဆောက်နေပါသည်။ ဤအရာကို လုပ်ဆောင်ခြင်းသည် လုပ်ငန်းစဉ်ကို မြန်ဆန်စေရန် ဖြစ်ပြီး၊ ၎င်းသည် ကျွန်ုပ်တို့၏ စာသားမှ အားလုံးသော တိုကင်များသည် ဝေါဟာရတွင် ပါဝင်မရှိနိုင်သော အခြေအနေတစ်ခု ဖြစ်ပေါ်စေနိုင်ပါသည်။ ဤအခြေအနေတွင်၊ ၎င်းတိုကင်များကို မထည့်သွင်းဘဲ လွှဲချော်မည်ဖြစ်ပြီး၊ ၎င်းသည် တိကျမှုအနည်းငယ် လျော့နည်းစေနိုင်ပါသည်။ သို့သော်၊ အမှန်တကယ်တွင် စာသား၏ အပိုင်းခွဲတစ်ခုသည် ဝေါဟာရခန့်မှန်းမှုကောင်းမွန်မှုကို အကြောင်းဖန်တီးပေးနိုင်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### အမျိုးမျိုးသော အရွယ်အစားရှိ အဆင့်များကို ကိုင်တွယ်ခြင်း\n",
|
||||
"\n",
|
||||
"မီနီဘတ်ချ်များတွင် လေ့ကျင့်မှုအခြေအနေကို နားလည်ကြရအောင်။ အထက်ပါ ဥပမာတွင် input tensor ၏ dimension သည် 1 ဖြစ်ပြီး၊ 128-အရှည်ရှိသော မီနီဘတ်ချ်များကို အသုံးပြုပါသည်။ ထို့ကြောင့် tensor ၏ အမှန်တကယ်အရွယ်အစားမှာ $128 \\times 1$ ဖြစ်သည်။ သို့သော်၊ mỗi စာကြောင်းတွင် token အရေအတွက်က မတူညီပါသည်။ `TextVectorization` layer ကို တစ်ခုတည်းသော input တွင် အသုံးပြုပါက၊ စာသားကို tokenize လုပ်ပုံအပေါ် မူတည်ပြီး၊ ပြန်လာသော token အရေအတွက်က မတူညီပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"tf.Tensor([ 1 45], shape=(2,), dtype=int64)\n",
|
||||
"tf.Tensor([ 112 1271 1 3 1747 158], shape=(6,), dtype=int64)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print(vectorizer('Hello, world!'))\n",
|
||||
"print(vectorizer('I am glad to meet you!'))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"သို့သော်၊ vectorizer ကို အစီအစဉ်များစွာတွင် အသုံးပြုသောအခါ၊ ၎င်းသည် တိရစက်ပုံသဏ္ဍာန်ရှိသော tensor တစ်ခုကို ထုတ်လုပ်ရမည်ဖြစ်ပြီး၊ အသုံးမပြုသော အစိတ်အပိုင်းများကို PAD token (ကျွန်ုပ်တို့၏အမှုတွင် သုည) ဖြင့် ဖြည့်ဆည်းသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tf.Tensor: shape=(2, 6), dtype=int64, numpy=\n",
|
||||
"array([[ 1, 45, 0, 0, 0, 0],\n",
|
||||
" [ 112, 1271, 1, 3, 1747, 158]], dtype=int64)>"
|
||||
]
|
||||
},
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vectorizer(['Hello, world!','I am glad to meet you!'])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([[[ 1.53059261e-02, 6.80514947e-02, 3.14026810e-02, ...,\n",
|
||||
" -8.92002955e-02, 1.52911525e-04, -5.65562584e-02],\n",
|
||||
" [ 2.57456154e-01, 2.79364467e-01, -2.03605562e-01, ...,\n",
|
||||
" -2.07474351e-01, 8.31158683e-02, -2.03911960e-01],\n",
|
||||
" [ 3.98201384e-02, -8.03454965e-03, 2.39790026e-02, ...,\n",
|
||||
" -7.18549127e-04, 2.66963355e-02, -4.30646613e-02],\n",
|
||||
" [ 3.98201384e-02, -8.03454965e-03, 2.39790026e-02, ...,\n",
|
||||
" -7.18549127e-04, 2.66963355e-02, -4.30646613e-02],\n",
|
||||
" [ 3.98201384e-02, -8.03454965e-03, 2.39790026e-02, ...,\n",
|
||||
" -7.18549127e-04, 2.66963355e-02, -4.30646613e-02],\n",
|
||||
" [ 3.98201384e-02, -8.03454965e-03, 2.39790026e-02, ...,\n",
|
||||
" -7.18549127e-04, 2.66963355e-02, -4.30646613e-02]],\n",
|
||||
"\n",
|
||||
" [[ 1.89674050e-01, 2.61548996e-01, -3.67433839e-02, ...,\n",
|
||||
" -2.07366899e-01, -1.05442435e-01, -2.36952081e-01],\n",
|
||||
" [ 6.16133213e-02, 1.80511594e-01, 9.77298319e-02, ...,\n",
|
||||
" -5.46628237e-02, -1.07340455e-01, -1.06589928e-01],\n",
|
||||
" [ 1.53059261e-02, 6.80514947e-02, 3.14026810e-02, ...,\n",
|
||||
" -8.92002955e-02, 1.52911525e-04, -5.65562584e-02],\n",
|
||||
" [-4.84890305e-02, -8.41715634e-02, 1.51529670e-01, ...,\n",
|
||||
" 1.28192469e-01, -7.77286515e-02, 1.26041949e-01],\n",
|
||||
" [-4.17212099e-02, -5.60694858e-02, 4.08860669e-02, ...,\n",
|
||||
" 8.70475471e-02, 8.92383084e-02, 1.67974353e-01],\n",
|
||||
" [ 2.85779923e-01, 4.57767487e-01, 4.52292450e-02, ...,\n",
|
||||
" -1.97419018e-01, -2.04659685e-01, -2.79758364e-01]]],\n",
|
||||
" dtype=float32)"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.layers[1](vectorizer(['Hello, world!','I am glad to meet you!'])).numpy()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Semantic embeddings: Word2Vec\n",
|
||||
"\n",
|
||||
"ယခင်ဥပမာတွင် embedding layer သည် စကားလုံးများကို ဗက်တာအနေဖြင့် ဖော်ပြရန် သင်ယူခဲ့သည်။ သို့သော်၊ ဤဗက်တာများတွင် အဓိပ္ပာယ်ဆိုင်ရာ အနက်မပါရှိသေးပါ။ အဓိပ္ပာယ်ဆိုင်ရာနီးစပ်မှုရှိသော စကားလုံးများ (ဥပမာ - အနက်တူသောစကားလုံးများ) သည် ဗက်တာအကွာအဝေးတစ်ခုအတွင်း နီးစပ်နေသည့် ဗက်တာများအဖြစ် ဖော်ပြနိုင်မည့် representation ကို သင်ယူနိုင်ရမည်ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"ဒါကို ပြုလုပ်ရန်၊ [Word2Vec](https://en.wikipedia.org/wiki/Word2vec) ကဲ့သို့သော နည်းလမ်းတစ်ခုကို အသုံးပြု၍ စာသားအစုအဝေးကြီးတစ်ခုကို အသုံးပြုကာ embedding model ကို ကြိုတင်သင်ကြားရမည်ဖြစ်သည်။ Word2Vec သည် စကားလုံးများကို distributed representation အဖြစ် ဖော်ဆောင်ရန် အသုံးပြုသော အဓိက architecture နှစ်ခုအပေါ် အခြေခံထားသည် -\n",
|
||||
"\n",
|
||||
" - **Continuous bag-of-words** (CBoW): ဒီနည်းလမ်းမှာ စကားလုံးတစ်လုံးကို ပတ်ဝန်းကျင်အခြေအနေမှ ခန့်မှန်းရန် မော်ဒယ်ကို သင်ကြားသည်။ ngram $(W_{-2},W_{-1},W_0,W_1,W_2)$ ရှိနေစဉ်၊ မော်ဒယ်၏ ရည်မှန်းချက်မှာ $(W_{-2},W_{-1},W_1,W_2)$ မှ $W_0$ ကို ခန့်မှန်းရန်ဖြစ်သည်။\n",
|
||||
" - **Continuous skip-gram**: CBoW နှင့် ဆန့်ကျင်ဘက်ဖြစ်သည်။ မော်ဒယ်သည် လက်ရှိစကားလုံးကို ခန့်မှန်းရန် ပတ်ဝန်းကျင်စကားလုံးများကို အသုံးပြုသည်။\n",
|
||||
"\n",
|
||||
"CBoW သည် မြန်ဆန်သော်လည်း၊ skip-gram သည် နှေးကွေးသော်လည်း မကြာခဏမတွေ့ရသော စကားလုံးများကို ပိုမိုကောင်းမွန်စွာ ဖော်ပြနိုင်သည်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"Google News dataset ပေါ်တွင် ကြိုတင်သင်ကြားထားသော Word2Vec embedding ကို စမ်းသပ်ရန် **gensim** library ကို အသုံးပြုနိုင်သည်။ အောက်တွင် 'neural' နှင့် နီးစပ်သော စကားလုံးများကို ရှာဖွေထားသည်။\n",
|
||||
"\n",
|
||||
"> **Note:** စကားလုံးဗက်တာများကို ပထမဆုံး ဖန်တီးစဉ်၊ ဒေါင်းလုဒ်လုပ်ရန် အချိန်အတော်ကြာနိုင်ပါသည်!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import gensim.downloader as api\n",
|
||||
"w2v = api.load('word2vec-google-news-300')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"neuronal -> 0.7804799675941467\n",
|
||||
"neurons -> 0.7326500415802002\n",
|
||||
"neural_circuits -> 0.7252851724624634\n",
|
||||
"neuron -> 0.7174385190010071\n",
|
||||
"cortical -> 0.6941086649894714\n",
|
||||
"brain_circuitry -> 0.6923246383666992\n",
|
||||
"synaptic -> 0.6699118614196777\n",
|
||||
"neural_circuitry -> 0.6638563275337219\n",
|
||||
"neurochemical -> 0.6555314064025879\n",
|
||||
"neuronal_activity -> 0.6531826257705688\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"for w,p in w2v.most_similar('neural'):\n",
|
||||
" print(f\"{w} -> {p}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့သည် စကားလုံးမှ ဗက်တာအင်ဘက်ဒ်ကို ထုတ်ယူနိုင်ပြီး အမျိုးအစားခွဲခြားမှု မော်ဒယ်ကို လေ့ကျင့်ရန် အသုံးပြုနိုင်ပါသည်။ အင်ဘက်ဒ်တွင် ၃၀၀ ခုသော အစိတ်အပိုင်းများရှိပါသည်၊ သို့သော် ရှင်းလင်းမှုအတွက် ဗက်တာ၏ ပထမ ၂၀ ခုသော အစိတ်အပိုင်းများကိုသာ ဤနေရာတွင် ပြသထားပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"array([ 0.01226807, 0.06225586, 0.10693359, 0.05810547, 0.23828125,\n",
|
||||
" 0.03686523, 0.05151367, -0.20703125, 0.01989746, 0.10058594,\n",
|
||||
" -0.03759766, -0.1015625 , -0.15820312, -0.08105469, -0.0390625 ,\n",
|
||||
" -0.05053711, 0.16015625, 0.2578125 , 0.10058594, -0.25976562],\n",
|
||||
" dtype=float32)"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"w2v['play'][:20]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"('queen', 0.7118192911148071)"
|
||||
]
|
||||
},
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"w2v.most_similar(positive=['king','woman'],negative=['man'])[0]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"tags": []
|
||||
},
|
||||
"source": [
|
||||
"အထက်ပါ ဥပမာသည် အတွင်းပိုင်း GenSym မျက်လှည့်တစ်ခုကို အသုံးပြုထားသော်လည်း အခြေခံ logic သည် အလွန်ရိုးရှင်းသည်။ Embeddings အကြောင်းတွင် စိတ်ဝင်စားဖွယ်ကောင်းသောအရာတစ်ခုမှာ embedding vectors ပေါ်တွင် သာမန်ဗက်တာလုပ်ဆောင်မှုများကို ပြုလုပ်နိုင်ပြီး၊ ၎င်းသည် စကားလုံး **အဓိပ္ပါယ်များ** ပေါ်တွင် လုပ်ဆောင်မှုများကို အကျိုးသက်ရောက်စေမည်ဖြစ်သည်။ အထက်ပါ ဥပမာကို ဗက်တာလုပ်ဆောင်မှုများအနေနှင့် ဖော်ပြနိုင်သည်- **KING-MAN+WOMAN** ကို ကိုယ်စားပြုသောဗက်တာကို တွက်ချက်ပြီး (သက်ဆိုင်သောစကားလုံးများ၏ဗက်တာကိုယ်စားပြုမှုများပေါ်တွင် `+` နှင့် `-` လုပ်ဆောင်မှုများကို ပြုလုပ်သည်)၊ ထို့နောက် အဆိုပါဗက်တာနှင့် အနီးဆုံးသော စကားလုံးကို အဘိဓာန်တွင် ရှာဖွေသည်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'queen'"
|
||||
]
|
||||
},
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# get the vector corresponding to kind-man+woman\n",
|
||||
"qvec = w2v['king']-1.7*w2v['man']+1.7*w2v['woman']\n",
|
||||
"# find the index of the closest embedding vector \n",
|
||||
"d = np.sum((w2v.vectors-qvec)**2,axis=1)\n",
|
||||
"min_idx = np.argmin(d)\n",
|
||||
"# find the corresponding word\n",
|
||||
"w2v.index_to_key[min_idx]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **NOTE**: *man* နှင့် *woman* vector များတွင် coefficient များကို အနည်းငယ်ထည့်ရန် လိုအပ်ခဲ့သည် - ၎င်းတို့ကို ဖယ်ရှားကြည့်ပါက ဘာဖြစ်မည်ကို ကြည့်ရှုနိုင်ပါသည်။\n",
|
||||
"\n",
|
||||
"အနီးဆုံး vector ကို ရှာဖွေရန်အတွက်၊ TensorFlow စက်ကိရိယာများကို အသုံးပြုကာ၊ ကျွန်ုပ်တို့၏ vector နှင့် vocabulary အတွင်းရှိ vector အားလုံးအကြား အကွာအဝေးများ၏ vector ကိုတွက်ချက်ပြီး၊ ထို့နောက် `argmin` ကို အသုံးပြုကာ အနည်းဆုံးသော စကားလုံး၏ index ကို ရှာဖွေပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Word2Vec သည် စကားလုံး၏ အဓိပ္ပါယ်ကို ဖော်ပြရန် အလွန်ကောင်းမွန်သည့် နည်းလမ်းတစ်ခုဖြစ်သော်လည်း အောက်ပါအချက်များအပါအဝင် အနည်းအကျဉ်းများစွာရှိသည်-\n",
|
||||
"\n",
|
||||
"* CBoW နှင့် skip-gram မော်ဒယ်များသည် **ခန့်မှန်းမှုအခြေခံ အထူးသက်မှတ်များ** ဖြစ်ပြီး ဒေသဆိုင်ရာအကြောင်းအရာကိုသာ အရေးပါစွာယူဆောင်သည်။ Word2Vec သည် အပြည်ပြည်ဆိုင်ရာအကြောင်းအရာကို အသုံးမပြုပါ။\n",
|
||||
"* Word2Vec သည် စကားလုံး၏ **ပုံသဏ္ဌာန်** (morphology) ကို မထည့်သွင်းစဉ်းစားပါ၊ ဥပမာအားဖြင့် စကားလုံး၏ အဓိပ္ပါယ်သည် root ကဲ့သို့သော စကားလုံး၏ အစိတ်အပိုင်းများပေါ်မူတည်နိုင်သည်။\n",
|
||||
"\n",
|
||||
"**FastText** သည် ဒုတိယကန့်သတ်ချက်ကို ကျော်လွှားရန် ကြိုးစားပြီး Word2Vec အပေါ် အခြေခံကာ စကားလုံးတစ်ခုစီနှင့် စကားလုံးအတွင်းရှိ အက္ခရာ n-grams များအတွက် ဗက်တာကိုယ်စားပြုမှုများကို သင်ယူသည်။ ထိုကိုယ်စားပြုမှုများ၏ တန်ဖိုးများကို သင်ကြားမှုအဆင့်တစ်ခုစီတွင် ဗက်တာတစ်ခုအဖြစ် ပျမ်းမျှတွက်ချက်သည်။ ဤနည်းလမ်းသည် သင်ကြားမှုမတိုင်မီ အလွန်များသောတွက်ချက်မှုများကို ထည့်သွင်းပေးသော်လည်း စကားလုံးအထူးသက်မှတ်များတွင် sub-word အချက်အလက်များကို encode ပြုလုပ်နိုင်စေသည်။\n",
|
||||
"\n",
|
||||
"နောက်ထပ်နည်းလမ်းတစ်ခုဖြစ်သော **GloVe** သည် စကားလုံးအထူးသက်မှတ်များကို အခြားနည်းလမ်းဖြင့် ဆောင်ရွက်သည်။ ၎င်းသည် စကားလုံး-အကြောင်းအရာ matrix ကို factorization အပေါ် အခြေခံသည်။ ပထမဦးစွာ စကားလုံးများ၏ အကြောင်းအရာအမျိုးမျိုးတွင် ဖြစ်ပေါ်မှုအရေအတွက်ကို ရေတွက်ထားသော matrix တစ်ခုကို တည်ဆောက်ပြီး ထို့နောက် reconstruction loss ကို အနည်းဆုံးဖြစ်စေရန် အနိမ့် dimension များတွင် matrix ကို ကိုယ်စားပြုရန် ကြိုးစားသည်။\n",
|
||||
"\n",
|
||||
"gensim library သည် ဤစကားလုံးအထူးသက်မှတ်များကို ပံ့ပိုးပေးပြီး အထက်ပါ မော်ဒယ် loading code ကို ပြောင်းလဲခြင်းဖြင့် ၎င်းတို့ကို စမ်းသပ်နိုင်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Keras တွင် pretrained embeddings ကို အသုံးပြုခြင်း\n",
|
||||
"\n",
|
||||
"အထက်ပါ ဥပမာကို ပြင်ဆင်ပြီး semantic embeddings (ဥပမာ - Word2Vec) ဖြင့် embedding layer ရှိ matrix ကို ကြိုတင်ဖြည့်စွက်နိုင်ပါတယ်။ Pretrained embedding ရဲ့ vocabulary နဲ့ text corpus ရဲ့ vocabulary တို့ဟာ မတူညီနိုင်ပါတယ်၊ ဒါကြောင့် တစ်ခုကို ရွေးချယ်ရပါမယ်။ ဒီမှာ Tokenizer vocabulary ကို အသုံးပြုခြင်းနဲ့ Word2Vec embeddings ရဲ့ vocabulary ကို အသုံးပြုခြင်းဆိုတဲ့ နှစ်မျိုးသော ရွေးချယ်မှုများကို လေ့လာပါမယ်။\n",
|
||||
"\n",
|
||||
"### Tokenizer vocabulary ကို အသုံးပြုခြင်း\n",
|
||||
"\n",
|
||||
"Tokenizer vocabulary ကို အသုံးပြုတဲ့အခါမှာ vocabulary ရဲ့ စကားလုံးတချို့မှာ Word2Vec embeddings ရှိနိုင်ပြီး တချို့မှာ မရှိနိုင်ပါ။ Vocabulary size ကို `vocab_size` ဟု သတ်မှတ်ပြီး၊ Word2Vec embedding vector ရဲ့ အလျားကို `embed_size` ဟု သတ်မှတ်ပါက embedding layer ကို `vocab_size`$\\times$`embed_size` ပုံစံရှိတဲ့ weight matrix တစ်ခုအဖြစ် ကိုယ်စားပြုနိုင်ပါတယ်။ ဒီ matrix ကို vocabulary ကို ဖြတ်သွားပြီး ဖြည့်စွက်ပါမယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Embedding size: 300\n",
|
||||
"Populating matrix, this will take some time...Done, found 4551 words, 784 words missing\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"embed_size = len(w2v.get_vector('hello'))\n",
|
||||
"print(f'Embedding size: {embed_size}')\n",
|
||||
"\n",
|
||||
"vocab = vectorizer.get_vocabulary()\n",
|
||||
"W = np.zeros((vocab_size,embed_size))\n",
|
||||
"print('Populating matrix, this will take some time...',end='')\n",
|
||||
"found, not_found = 0,0\n",
|
||||
"for i,w in enumerate(vocab):\n",
|
||||
" try:\n",
|
||||
" W[i] = w2v.get_vector(w)\n",
|
||||
" found+=1\n",
|
||||
" except:\n",
|
||||
" # W[i] = np.random.normal(0.0,0.3,size=(embed_size,))\n",
|
||||
" not_found+=1\n",
|
||||
"\n",
|
||||
"print(f\"Done, found {found} words, {not_found} words missing\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Word2Vec vocabulary တွင် မပါဝင်သော စကားလုံးများအတွက် ကျွန်ုပ်တို့သည် zeroes အဖြစ်ထားနိုင်ပါသည်၊ သို့မဟုတ် အလှည့်ကျ random vector တစ်ခုကို ဖန်တီးနိုင်ပါသည်။\n",
|
||||
"\n",
|
||||
"ယခု ကျွန်ုပ်တို့သည် pretrained weights ဖြင့် embedding layer တစ်ခုကို သတ်မှတ်နိုင်ပါပြီ။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"emb = keras.layers.Embedding(vocab_size,embed_size,weights=[W],trainable=False)\n",
|
||||
"model = keras.models.Sequential([\n",
|
||||
" vectorizer, emb,\n",
|
||||
" keras.layers.Lambda(lambda x: tf.reduce_mean(x,axis=1)),\n",
|
||||
" keras.layers.Dense(4, activation='softmax')\n",
|
||||
"])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"938/938 [==============================] - 10s 10ms/step - loss: 1.1075 - acc: 0.7822 - val_loss: 0.9134 - val_acc: 0.8175\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<keras.callbacks.History at 0x2220226ef10>"
|
||||
]
|
||||
},
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'])\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(batch_size),\n",
|
||||
" validation_data=ds_test.map(tupelize).batch(batch_size))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **မှတ်ချက်**: `Embedding` ကို ဖန်တီးတဲ့အချိန်မှာ `trainable=False` ကို သတ်မှတ်ထားတာကို သတိပြုပါ၊ ဒါက Embedding layer ကို ပြန်လည်လေ့ကျင့်မနေကြောင်းကို ဆိုလိုပါတယ်။ ဒီလိုလုပ်ခြင်းကြောင့် တိကျမှုအနည်းငယ်လျော့နည်းနိုင်ပေမယ့် လေ့ကျင့်မှုအချိန်ကို ပိုမိုလျင်မြန်စေပါတယ်။\n",
|
||||
"\n",
|
||||
"### Embedding စာလုံးစုကို အသုံးပြုခြင်း\n",
|
||||
"\n",
|
||||
"ယခင်နည်းလမ်းမှာ ရှိနေတဲ့ ပြဿနာတစ်ခုက TextVectorization နဲ့ Embedding မှာ အသုံးပြုထားတဲ့ စာလုံးစုတွေက မတူညီကြတာဖြစ်ပါတယ်။ ဒီပြဿနာကို ဖြေရှင်းဖို့အတွက် အောက်ပါနည်းလမ်းများကို အသုံးပြုနိုင်ပါတယ်-\n",
|
||||
"* Word2Vec မော်ဒယ်ကို ကျွန်တော်တို့ရဲ့ စာလုံးစုအပေါ်မှာ ပြန်လည်လေ့ကျင့်ပါ။\n",
|
||||
"* Pretrained Word2Vec မော်ဒယ်က စာလုံးစုကို အသုံးပြုပြီး ကျွန်တော်တို့ရဲ့ ဒေတာစနစ်ကို တင်ပါ။ ဒေတာစနစ်ကို တင်တဲ့အချိန်မှာ အသုံးပြုမယ့် စာလုံးစုကို သတ်မှတ်နိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"နောက်ဆုံးနည်းလမ်းက ပိုမိုလွယ်ကူတဲ့နည်းလမ်းလိုပဲ ထင်ရပါတယ်၊ ဒါကြောင့် အဲဒီနည်းလမ်းကို လက်တွေ့ကျင့်ကြည့်ရအောင်။ အရင်ဆုံး Word2Vec embeddings မှာ ပါဝင်တဲ့ စာလုံးစုကို အသုံးပြုပြီး `TextVectorization` layer တစ်ခုကို ဖန်တီးပါ-\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"vocab = list(w2v.vocab.keys())\n",
|
||||
"vectorizer = keras.layers.experimental.preprocessing.TextVectorization(input_shape=(1,))\n",
|
||||
"vectorizer.set_vocabulary(vocab)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Gensim စကားလုံး embedding မိုဃ်းစာကြည့်တိုက်တွင် သက်ဆိုင်ရာ Keras embedding အလွှာကို သင့်အတွက် အလိုအလျောက် ဖန်တီးပေးမည့် `get_keras_embeddings` ဟုခေါ်သော အဆင်ပြေသော လုပ်ဆောင်ချက်တစ်ခု ပါရှိသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Epoch 1/5\n",
|
||||
"938/938 [==============================] - 20s 14ms/step - loss: 1.3377 - acc: 0.4978 - val_loss: 1.2995 - val_acc: 0.5647\n",
|
||||
"Epoch 2/5\n",
|
||||
"938/938 [==============================] - 10s 10ms/step - loss: 1.2587 - acc: 0.5722 - val_loss: 1.2339 - val_acc: 0.5842\n",
|
||||
"Epoch 3/5\n",
|
||||
"938/938 [==============================] - 10s 10ms/step - loss: 1.1980 - acc: 0.5884 - val_loss: 1.1826 - val_acc: 0.5954\n",
|
||||
"Epoch 4/5\n",
|
||||
"938/938 [==============================] - 12s 13ms/step - loss: 1.1503 - acc: 0.6002 - val_loss: 1.1417 - val_acc: 0.6018\n",
|
||||
"Epoch 5/5\n",
|
||||
"938/938 [==============================] - 11s 12ms/step - loss: 1.1120 - acc: 0.6097 - val_loss: 1.1083 - val_acc: 0.6104\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<keras.callbacks.History at 0x2220ccb81c0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model = keras.models.Sequential([\n",
|
||||
" vectorizer, \n",
|
||||
" w2v.get_keras_embedding(train_embeddings=False),\n",
|
||||
" keras.layers.Lambda(lambda x: tf.reduce_mean(x,axis=1)),\n",
|
||||
" keras.layers.Dense(4, activation='softmax')\n",
|
||||
"])\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'])\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(128),validation_data=ds_test.map(tupelize).batch(128),epochs=5)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့ ပိုမိုတိကျမှုမြင့်မားသော ရလဒ်များ မမြင်ရသည့် အကြောင်းအရင်းများထဲမှ တစ်ခုမှာ ကျွန်ုပ်တို့၏ ဒေတာစနစ်မှ စကားလုံးအချို့သည် pretrained GloVe vocabulary တွင် မပါဝင်သောကြောင့် အဓိကအားဖြင့် မသိမ်းဆည်းထားခြင်း ဖြစ်ပါသည်။ ဤအခြေအနေကို ကျော်လွှားရန် ကျွန်ုပ်တို့၏ ဒေတာစနစ်အပေါ် အခြေခံ၍ ကျွန်ုပ်တို့၏ embedding များကို ကိုယ်တိုင် training ပြုလုပ်နိုင်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## အခြေအနေအရ အဓိပ္ပါယ်များ\n",
|
||||
"\n",
|
||||
"Word2Vec ကဲ့သို့သော ရိုးရာ pretrained embedding ကိုယ်စားပြုမှုများ၏ အဓိက ကန့်သတ်ချက်တစ်ခုမှာ စကားလုံးတစ်လုံး၏ အဓိပ္ပါယ်တစ်ချို့ကို ဖမ်းဆီးနိုင်သော်လည်း အဓိပ္ပါယ်များကို ခွဲခြားနိုင်မှုမရှိခြင်း ဖြစ်သည်။ ဒီအရာက Downstream မော်ဒယ်များတွင် ပြဿနာများ ဖြစ်ပေါ်စေနိုင်သည်။\n",
|
||||
"\n",
|
||||
"ဥပမာအားဖြင့် 'play' ဆိုသော စကားလုံးသည် အောက်ပါ စာကြောင်းနှစ်ခုတွင် အဓိပ္ပါယ်ကွဲပြားမှုရှိသည်။\n",
|
||||
"- ကျွန်တော်က ဇာတ်လမ်း **play** ကို ရုပ်ရှင်ရုံမှာ သွားကြည့်ခဲ့တယ်။\n",
|
||||
"- John က သူ့သူငယ်ချင်းတွေနဲ့ **play** လုပ်ချင်တယ်။\n",
|
||||
"\n",
|
||||
"ကျွန်တော်တို့ ပြောခဲ့တဲ့ pretrained embeddings တွေက 'play' ဆိုတဲ့ စကားလုံးရဲ့ အဓိပ္ပါယ်နှစ်ခုလုံးကို တူညီတဲ့ embedding အနေနဲ့ ကိုယ်စားပြုထားတယ်။ ဒီကန့်သတ်ချက်ကို ကျော်လွှားဖို့ **ဘာသာစကားမော်ဒယ်** အပေါ် အခြေခံပြီး embeddings တွေကို တည်ဆောက်ဖို့ လိုအပ်တယ်။ ဘာသာစကားမော်ဒယ်က စာသားအကြီးစား corpus တစ်ခုမှာ လေ့ကျင့်ထားပြီး စကားလုံးတွေကို အခြေအနေအမျိုးမျိုးမှာ ဘယ်လိုပေါင်းစည်းနိုင်တယ်ဆိုတာ *သိ* တယ်။ အခြေအနေအရ အဓိပ္ပါယ်များကို ဆွေးနွေးခြင်းက ဒီသင်ခန်းစာရဲ့ အကျယ်အဝန်းအပြင်မှာ ရှိပေမယ့် ဘာသာစကားမော်ဒယ်များကို နောက်ယူနစ်မှာ ပြန်လည်ဆွေးနွေးမယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်ခြင်းတွင် အမှားများ သို့မဟုတ် မတိကျမှုများ ပါဝင်နိုင်သည်ကို ကျေးဇူးပြု၍ သိရှိထားပါ။ မူရင်းဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာတရ အရင်းအမြစ်အဖြစ် ရှုလေ့လာသင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူ့ဘာသာပြန်ပညာရှင်များမှ ပရော်ဖက်ရှင်နယ် ဘာသာပြန်ခြင်းကို အကြံပြုပါသည်။ ဤဘာသာပြန်ကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအမှားများ သို့မဟုတ် အနားယူမှားမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "0cb620c6d4b9f7a635928804c26cf22403d89d98d79684e4529119355ee6d5a5"
|
||||
},
|
||||
"kernel_info": {
|
||||
"name": "conda-env-py37_tensorflow-py"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "py37_tensorflow",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"nteract": {
|
||||
"version": "nteract-front-end@1.0.0"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "b859482be7f61d1eadc2c6a2720a37e4",
|
||||
"translation_date": "2025-08-30T10:36:08+00:00",
|
||||
"source_file": "lessons/5-NLP/14-Embeddings/EmbeddingsTF.ipynb",
|
||||
"language_code": "my"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -0,0 +1,574 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "NXTSugt6ieXh"
|
||||
},
|
||||
"source": [
|
||||
"## CBoW မော်ဒယ်ကိုလေ့ကျင့်ခြင်း\n",
|
||||
"\n",
|
||||
"ဒီ notebook က [AI for Beginners Curriculum](http://aka.ms/ai-beginners) ရဲ့ အစိတ်အပိုင်းတစ်ခုဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"ဒီဥပမာမှာတော့ CBoW ဘာသာစကားမော်ဒယ်ကိုလေ့ကျင့်ပြီး Word2Vec embedding space ကို ကိုယ်တိုင်ရရှိအောင်လုပ်မယ်။ AG News dataset ကို စာသားရင်းမြစ်အဖြစ်အသုံးပြုမယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"import torch\n",
|
||||
"import torchtext\n",
|
||||
"import os\n",
|
||||
"import collections\n",
|
||||
"import builtins\n",
|
||||
"import random\n",
|
||||
"import numpy as np"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "q-UiiJUKaxHj"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "TFbR8CZaTZ1q"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"အရင်ဆုံး ကျွန်တော်တို့ရဲ့ ဒေတာစနစ်ကို load လုပ်ပြီး tokenizer နဲ့ vocabulary ကို သတ်မှတ်ပါမယ်။ `vocab_size` ကို ၅၀၀၀ အထိ သတ်မှတ်ပြီး ရှုထောင့်များကို အနည်းငယ် ကန့်သတ်ပါမယ်။\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "HIwC7lI5T-ov"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"def load_dataset(ngrams = 1, min_freq = 1, vocab_size = 5000 , lines_cnt = 500):\n",
|
||||
" tokenizer = torchtext.data.utils.get_tokenizer('basic_english')\n",
|
||||
" print(\"Loading dataset...\")\n",
|
||||
" test_dataset, train_dataset = torchtext.datasets.AG_NEWS(root='./data')\n",
|
||||
" train_dataset = list(train_dataset)\n",
|
||||
" test_dataset = list(test_dataset)\n",
|
||||
" classes = ['World', 'Sports', 'Business', 'Sci/Tech']\n",
|
||||
" print('Building vocab...')\n",
|
||||
" counter = collections.Counter()\n",
|
||||
" for i, (_, line) in enumerate(train_dataset):\n",
|
||||
" counter.update(torchtext.data.utils.ngrams_iterator(tokenizer(line),ngrams=ngrams))\n",
|
||||
" if i == lines_cnt:\n",
|
||||
" break\n",
|
||||
" vocab = torchtext.vocab.Vocab(collections.Counter(dict(counter.most_common(vocab_size))), min_freq=min_freq)\n",
|
||||
" return train_dataset, test_dataset, classes, vocab, tokenizer"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "wdZuygtgiuLG"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"train_dataset, test_dataset, _, vocab, tokenizer = load_dataset()"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "4d1nU1gsivGu",
|
||||
"outputId": "949fe272-ae0e-49f5-c373-6703458b3a74"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Loading dataset...\n",
|
||||
"Building vocab...\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"def encode(x, vocabulary, tokenizer = tokenizer):\n",
|
||||
" return [vocabulary[s] for s in tokenizer(x)]"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "1XDYNhG8ToFV"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "LIlQk6_PaHVY"
|
||||
},
|
||||
"source": [
|
||||
"## CBoW မော်ဒယ်\n",
|
||||
"\n",
|
||||
"CBoW သည် $2N$ အနီးအနားရှိ စကားလုံးများကို အခြေခံပြီး စကားလုံးတစ်လုံးကို ခန့်မှန်းရန် သင်ယူသည်။ ဥပမာအားဖြင့် $N=1$ ဖြစ်သောအခါ *I like to train networks* ဆိုသော စာကြောင်းမှ အောက်ပါ စုံတွဲများကို ရရှိမည်ဖြစ်သည် - (like,I), (I, like), (to, like), (like,to), (train,to), (to, train), (networks, train), (train,networks)။ ဒီမှာ ပထမ စကားလုံးသည် input အဖြစ် အသုံးပြုသော အနီးအနားရှိ စကားလုံးဖြစ်ပြီး ဒုတိယ စကားလုံးသည် ခန့်မှန်းရန် ရည်ရွယ်ထားသော စကားလုံးဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"နောက်ထပ် စကားလုံးကို ခန့်မှန်းရန် network တစ်ခုကို တည်ဆောက်ရန်အတွက် အနီးအနားရှိ စကားလုံးကို input အဖြစ် ပေးရမည်ဖြစ်ပြီး စကားလုံးနံပါတ်ကို output အဖြစ် ရယူရမည်။ CBoW network ၏ architecture သည် အောက်ပါအတိုင်းဖြစ်သည် -\n",
|
||||
"\n",
|
||||
"* Input စကားလုံးကို embedding layer မှတဆင့် ဖြတ်သွားမည်။ ဒီ embedding layer သည် Word2Vec embedding ဖြစ်မည်ဖြစ်ပြီး `embedder` variable အဖြစ် သီးသန့်သတ်မှတ်မည်။ ဤဥပမာတွင် embedding size = 30 ကို အသုံးပြုမည်ဖြစ်သော်လည်း အမြင့် dimension များ (အမှန်တကယ် Word2Vec တွင် 300 ရှိသည်) ကို စမ်းသပ်လိုပါက ပြောင်းလဲနိုင်သည်။\n",
|
||||
"* Embedding vector ကို linear layer သို့ ဖြတ်သွားပြီး output စကားလုံးကို ခန့်မှန်းမည်။ ထို့ကြောင့် `vocab_size` neurons ရှိသည်။\n",
|
||||
"\n",
|
||||
"Output အတွက် `CrossEntropyLoss` ကို loss function အဖြစ် အသုံးပြုပါက one-hot encoding မပါဘဲ စကားလုံးနံပါတ်များကိုသာ expected results အဖြစ် ပေးရမည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"vocab_size = len(vocab)\n",
|
||||
"\n",
|
||||
"embedder = torch.nn.Embedding(num_embeddings = vocab_size, embedding_dim = 30)\n",
|
||||
"model = torch.nn.Sequential(\n",
|
||||
" embedder,\n",
|
||||
" torch.nn.Linear(in_features = 30, out_features = vocab_size),\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"print(model)"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "akKTcKQKkfl2",
|
||||
"outputId": "da687e3e-a8ec-4c1a-e456-ab8cd6ac7dad"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Sequential(\n",
|
||||
" (0): Embedding(5002, 30)\n",
|
||||
" (1): Linear(in_features=30, out_features=5002, bias=True)\n",
|
||||
")\n"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "Nud6jgGPaHVa"
|
||||
},
|
||||
"source": [
|
||||
"## လေ့ကျင့်မှု ဒေတာ ပြင်ဆင်ခြင်း\n",
|
||||
"\n",
|
||||
"အခုတော့ စာသားထဲမှ CBoW စကားလုံးစုံများကိုတွက်ချက်ပေးမည့် အဓိက function ကိုရေးကြမယ်။ ဒီ function က window size ကို သတ်မှတ်ပေးနိုင်မှာဖြစ်ပြီး၊ input နှင့် output စကားလုံးစုံများကို ပြန်ပေးမယ်။ ဒီ function ကို စကားလုံးများအပေါ်မှာသာမက၊ vectors/tensors အပေါ်မှာလည်း အသုံးပြုနိုင်တယ် - ဒါကြောင့် စာသားကို encode လုပ်ပြီးနောက်မှ `to_cbow` function ကို ပေးပို့နိုင်မယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "x-dsXygOieXn",
|
||||
"outputId": "c2218280-e540-40ba-9546-efe48d0d714f"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"[['like', 'I'], ['to', 'I'], ['I', 'like'], ['to', 'like'], ['train', 'like'], ['I', 'to'], ['like', 'to'], ['train', 'to'], ['networks', 'to'], ['like', 'train'], ['to', 'train'], ['networks', 'train'], ['to', 'networks'], ['train', 'networks']]\n",
|
||||
"[[232, 172], [5, 172], [172, 232], [5, 232], [0, 232], [172, 5], [232, 5], [0, 5], [1202, 5], [232, 0], [5, 0], [1202, 0], [5, 1202], [0, 1202]]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def to_cbow(sent,window_size=2):\n",
|
||||
" res = []\n",
|
||||
" for i,x in enumerate(sent):\n",
|
||||
" for j in range(max(0,i-window_size),min(i+window_size+1,len(sent))):\n",
|
||||
" if i!=j:\n",
|
||||
" res.append([sent[j],x])\n",
|
||||
" return res\n",
|
||||
"\n",
|
||||
"print(to_cbow(['I','like','to','train','networks']))\n",
|
||||
"print(to_cbow(encode('I like to train networks', vocab)))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "XVaaDLjaaHVb"
|
||||
},
|
||||
"source": [
|
||||
"ကျောင်းသားသင်ကြားမှုဒေတာစုံကို ပြင်ဆင်ကြမယ်။ သတင်းအားလုံးကို ကျော်လွှားပြီး `to_cbow` ကို ခေါ်သုံးကာ စကားလုံးအတွဲများစာရင်းကို ရယူပြီး အဲ့ဒီအတွဲများကို `X` နဲ့ `Y` ထဲထည့်ပါမယ်။ အချိန်သက်သာစေရန်အတွက် ပထမ 10k သတင်းပစ္စည်းများကိုသာ စဉ်းစားပါမယ် - သင့်မှာ စောင့်ဆိုင်းဖို့ အချိန်ပိုရှိပြီး ပိုမိုကောင်းမွန်တဲ့ embedding များရယူလိုပါက အကန့်အသတ်ကို လွယ်ကူစွာ ဖယ်ရှားနိုင်ပါတယ် :)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "54b-Gd9TieXo"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"X = []\n",
|
||||
"Y = []\n",
|
||||
"for i, x in zip(range(10000), train_dataset):\n",
|
||||
" for w1, w2 in to_cbow(encode(x[1], vocab), window_size = 5):\n",
|
||||
" X.append(w1)\n",
|
||||
" Y.append(w2)\n",
|
||||
"\n",
|
||||
"X = torch.tensor(X)\n",
|
||||
"Y = torch.tensor(Y)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့သည် အဆိုပါဒေတာကို တစ်ခုတည်းသောဒေတာစုံအဖြစ် ပြောင်းလဲမည်ဖြစ်ပြီး၊ dataloader တစ်ခုကို ဖန်တီးမည်:\n"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "cwWy0PzXWhN5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"class SimpleIterableDataset(torch.utils.data.IterableDataset):\n",
|
||||
" def __init__(self, X, Y):\n",
|
||||
" super(SimpleIterableDataset).__init__()\n",
|
||||
" self.data = []\n",
|
||||
" for i in range(len(X)):\n",
|
||||
" self.data.append( (Y[i], X[i]) )\n",
|
||||
" random.shuffle(self.data)\n",
|
||||
"\n",
|
||||
" def __iter__(self):\n",
|
||||
" return iter(self.data)"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "mfoAcGPFZU8p"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "e4NQ_-5waHVc"
|
||||
},
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့သည် အဆိုပါဒေတာကို တစ်ခုတည်းသောဒေတာစုံအဖြစ် ပြောင်းလဲမည်ဖြစ်ပြီး၊ dataloader တစ်ခုကို ဖန်တီးမည်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "AbLUcojlieXo"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"ds = SimpleIterableDataset(X, Y)\n",
|
||||
"dl = torch.utils.data.DataLoader(ds, batch_size = 256)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "pKQr7sXeaHVc"
|
||||
},
|
||||
"source": [
|
||||
"အခုတော့ အမှန်တကယ် သင်ကြားမှုကို စတင်ကြမယ်။ ကျွန်တော်တို့ `SGD` optimizer ကို အသုံးပြုပြီး အလွန်မြင့်မားတဲ့ learning rate နဲ့ သင်ကြားပါမယ်။ သင် `Adam` ကဲ့သို့သော အခြား optimizer များကိုလည်း စမ်းသပ်ကြည့်နိုင်ပါတယ်။ အစမှာ 10 epochs အထိ သင်ကြားပါမယ် - သင်ပိုနည်းတဲ့ loss ရချင်ရင် ဒီ cell ကို ပြန်လည် run လုပ်နိုင်ပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"def train_epoch(net, dataloader, lr = 0.01, optimizer = None, loss_fn = torch.nn.CrossEntropyLoss(), epochs = None, report_freq = 1):\n",
|
||||
" optimizer = optimizer or torch.optim.Adam(net.parameters(), lr = lr)\n",
|
||||
" loss_fn = loss_fn.to(device)\n",
|
||||
" net.train()\n",
|
||||
"\n",
|
||||
" for i in range(epochs):\n",
|
||||
" total_loss, j = 0, 0, \n",
|
||||
" for labels, features in dataloader:\n",
|
||||
" optimizer.zero_grad()\n",
|
||||
" features, labels = features.to(device), labels.to(device)\n",
|
||||
" out = net(features)\n",
|
||||
" loss = loss_fn(out, labels)\n",
|
||||
" loss.backward()\n",
|
||||
" optimizer.step()\n",
|
||||
" total_loss += loss\n",
|
||||
" j += 1\n",
|
||||
" if i % report_freq == 0:\n",
|
||||
" print(f\"Epoch: {i+1}: loss={total_loss.item()/j}\")\n",
|
||||
"\n",
|
||||
" return total_loss.item()/j"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "HeeCYKr_KF1w"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"train_epoch(net = model, dataloader = dl, optimizer = torch.optim.SGD(model.parameters(), lr = 0.1), loss_fn = torch.nn.CrossEntropyLoss(), epochs = 10)"
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "KVgwGtDHgDlT",
|
||||
"outputId": "2447833f-f0e3-4566-c33d-addbfe2f451d"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"Epoch: 1: loss=5.664632366860172\n",
|
||||
"Epoch: 2: loss=5.632101973960962\n",
|
||||
"Epoch: 3: loss=5.610399051405015\n",
|
||||
"Epoch: 4: loss=5.594621561080262\n",
|
||||
"Epoch: 5: loss=5.582538017415446\n",
|
||||
"Epoch: 6: loss=5.572900234519603\n",
|
||||
"Epoch: 7: loss=5.564951676341915\n",
|
||||
"Epoch: 8: loss=5.558288112064614\n",
|
||||
"Epoch: 9: loss=5.552576955031129\n",
|
||||
"Epoch: 10: loss=5.547634165194347\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"output_type": "execute_result",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"5.547634165194347"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"execution_count": 16
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "W8u2qXZmaHVd"
|
||||
},
|
||||
"source": [
|
||||
"## Word2Vec ကို စမ်းသပ်ခြင်း\n",
|
||||
"\n",
|
||||
"Word2Vec ကို အသုံးပြုရန်၊ ကျွန်ုပ်တို့၏ ဝေါဟာရစာရင်းထဲရှိ စကားလုံးအားလုံးနှင့် ကိုက်ညီသော ဗက်တာများကို ထုတ်ယူကြမယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "r8TatcXjkU_t"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"vectors = torch.stack([embedder(torch.tensor(vocab[s])) for s in vocab.itos], 0)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "3OcX21UOaHVd"
|
||||
},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "bz6tAeLzieXp",
|
||||
"outputId": "5b20850e-4342-45e9-f840-cfac2b4d61d8"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "stream",
|
||||
"name": "stdout",
|
||||
"text": [
|
||||
"tensor([-0.0915, 2.1224, -0.0281, -0.6819, 1.1219, 0.6458, -1.3704, -1.3314,\n",
|
||||
" -1.1437, 0.4496, 0.2301, -0.3515, -0.8485, 1.0481, 0.4386, -0.8949,\n",
|
||||
" 0.5644, 1.0939, -2.5096, 3.2949, -0.2601, -0.8640, 0.1421, -0.0804,\n",
|
||||
" -0.5083, -1.0560, 0.9753, -0.5949, -1.6046, 0.5774],\n",
|
||||
" grad_fn=<EmbeddingBackward>)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"paris_vec = embedder(torch.tensor(vocab['paris']))\n",
|
||||
"print(paris_vec)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "pHTJlaeYaHVd"
|
||||
},
|
||||
"source": [
|
||||
"Word2Vec ကို သုံးပြီး အနီးစပ်ဆုံးသော စကားလုံးများကို ရှာဖွေခြင်းသည် စိတ်ဝင်စားဖွယ်ကောင်းသည်။ အောက်ပါ function သည် ပေးထားသော input အတွက် `n` အနီးစပ်ဆုံးသော စကားလုံးများကို ပြန်လည်ပေးပါမည်။ ၎င်းတို့ကို ရှာဖွေရန် $|w_i - v|$ ၏ norm ကို တွက်ချက်ပါမည်၊ ဤနေရာတွင် $v$ သည် input စကားလုံးနှင့် ဆက်စပ်သော vector ဖြစ်ပြီး $w_i$ သည် vocabulary အတွင်းရှိ $i$-th စကားလုံး၏ encoding ဖြစ်သည်။ ထို့နောက် array ကို sort လုပ်ပြီး `argsort` ကို အသုံးပြု၍ ဆက်စပ်သော indices များကို ပြန်လည်ပေးပြီး vocabulary အတွင်းရှိ အနီးစပ်ဆုံးသော စကားလုံးများ၏ တည်နေရာကို encode လုပ်ထားသော list ၏ ပထမဆုံး `n` elements ကို ယူပါမည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "NlZyi-_olFar",
|
||||
"outputId": "b5dbb163-88c4-4d5a-eaf2-6751f700e98c"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "execute_result",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"['microsoft', 'quoted', 'lp', 'rate', 'top']"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"execution_count": 56
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def close_words(x, n = 5):\n",
|
||||
" vec = embedder(torch.tensor(vocab[x]))\n",
|
||||
" top5 = np.linalg.norm(vectors.detach().numpy() - vec.detach().numpy(), axis = 1).argsort()[:n]\n",
|
||||
" return [ vocab.itos[x] for x in top5 ]\n",
|
||||
"\n",
|
||||
"close_words('microsoft')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "-dQq7xeAln0U",
|
||||
"outputId": "66f768c3-c248-4bfd-ce4f-c8ffc6d0dd0d"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "execute_result",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"['basketball', 'lot', 'sinai', 'states', 'healthdaynews']"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"execution_count": 51
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"close_words('basketball')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
},
|
||||
"id": "fJXqK26b29sa",
|
||||
"outputId": "78f0baba-ffd0-485a-dd87-0a12bedfd7fa"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"output_type": "execute_result",
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"['funds', 'travel', 'sydney', 'japan', 'business']"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"execution_count": 77
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"close_words('funds')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "My0VeTDd3Ji8"
|
||||
},
|
||||
"source": [
|
||||
"## အဓိကအချက်\n",
|
||||
"\n",
|
||||
"CBoW ကဲ့သို့သော ထူးခြားသောနည်းလမ်းများကို အသုံးပြု၍ Word2Vec မော်ဒယ်ကို လေ့ကျင့်နိုင်ပါသည်။ သင်သည် အလယ်ရှိ စကားလုံးကို ပေးပြီး အနီးအနားရှိ စကားလုံးကို ခန့်မှန်းရန် လေ့ကျင့်ထားသော skip-gram မော်ဒယ်ကိုလည်း လေ့ကျင့်ကြည့်ပြီး၊ ၎င်း၏ လုပ်ဆောင်မှုကောင်းမွန်မှုကို ကြည့်ရှုနိုင်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်ခြင်းတွင် အမှားများ သို့မဟုတ် မတိကျမှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းစာရွက်စာတမ်းကို ၎င်း၏ မူရင်းဘာသာစကားဖြင့် အာဏာတရားရှိသော အရင်းအမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူ့ဘာသာပြန်ပညာရှင်များမှ ပရော်ဖက်ရှင်နယ် ဘာသာပြန်ခြင်းကို အကြံပြုပါသည်။ ဤဘာသာပြန်ကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားယူမှုမှားများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"collapsed_sections": [],
|
||||
"name": "CBoW-PyTorch.ipynb",
|
||||
"provenance": []
|
||||
},
|
||||
"interpreter": {
|
||||
"hash": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.8.12 ('py38')",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"orig_nbformat": 4,
|
||||
"gpuClass": "standard",
|
||||
"coopTranslator": {
|
||||
"original_hash": "36df28efe3fe40b6fb0a7fa48fe3ea82",
|
||||
"translation_date": "2025-08-30T10:15:52+00:00",
|
||||
"source_file": "lessons/5-NLP/15-LanguageModeling/CBoW-PyTorch.ipynb",
|
||||
"language_code": "my"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,477 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# ပြန်လည်လုပ်ဆောင်နိုင်သော နယူးရယ်နက်ဝက်\n",
|
||||
"\n",
|
||||
"ယခင် module မှာ ကျွန်တော်တို့ rich semantic representations of text ကို အသုံးပြုပြီး embeddings အပေါ်မှာ simple linear classifier ကို ထည့်သုံးခဲ့ပါတယ်။ ဒီ architecture က စာကြောင်းတစ်ကြောင်းအတွင်းမှာ စကားလုံးတွေ၏ အဓိပ္ပါယ်ကို စုပေါင်းဖမ်းယူပေးနိုင်ပေမယ့် စကားလုံးတွေရဲ့ **အစီအစဉ်** ကို မထည့်သွင်းစဉ်းစားပါဘူး။ အကြောင်းကတော့ embeddings အပေါ်မှာ aggregation operation လုပ်တဲ့အခါမှာ original text ထဲက အစီအစဉ်ဆိုင်ရာ အချက်အလက်တွေကို ဖယ်ရှားလိုက်တဲ့အတွက်ပါ။ ဒီ model တွေက စကားလုံးအစီအစဉ်ကို မဖော်ဆောင်နိုင်တဲ့အတွက် text generation, question answering လို ပိုမိုရှုပ်ထွေးတဲ့ task တွေကို မဖြေရှင်းနိုင်ပါဘူး။\n",
|
||||
"\n",
|
||||
"စာကြောင်းအစီအစဉ်ရဲ့ အဓိပ္ပါယ်ကို ဖမ်းယူနိုင်ဖို့အတွက် **recurrent neural network** (RNN) လို့ခေါ်တဲ့ neural network architecture တစ်ခုကို အသုံးပြုရပါမယ်။ RNN မှာ ကျွန်တော်တို့ရဲ့ စာကြောင်းကို network အတွင်းသို့ symbol တစ်ခုစီအလိုက် ဖြတ်သွားပြီး network က **state** တစ်ခုကို ထုတ်ပေးပါတယ်။ ဒီ state ကို နောက် symbol နဲ့အတူ network ထဲကို ပြန်လည်ထည့်သွင်းပေးပါတယ်။\n",
|
||||
"\n",
|
||||
"Given the input sequence of tokens $X_0,\\dots,X_n$, RNN က neural network blocks တွေကို အစီအစဉ်အလိုက် ဖန်တီးပြီး ဒီ sequence ကို end-to-end အနေနဲ့ back propagation အသုံးပြုပြီး training လုပ်ပါတယ်။ Network block တစ်ခုစီက $(X_i,S_i)$ pair ကို input အနေနဲ့ ယူပြီး $S_{i+1}$ ကို output အနေနဲ့ ထုတ်ပေးပါတယ်။ နောက်ဆုံး state $S_n$ သို့မဟုတ် output $X_n ကို linear classifier ထဲသို့ ထည့်သွင်းပြီး ရလဒ်ကို ထုတ်ပေးပါတယ်။ Network block အားလုံးမှာ weight တွေကို share လုပ်ထားပြီး back propagation pass တစ်ခုတည်းနဲ့ end-to-end training လုပ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"State vectors $S_0,\\dots,S_n$ တွေကို network အတွင်းဖြတ်သွားတဲ့အတွက် စကားလုံးတွေရဲ့ အစီအစဉ်ဆိုင်ရာ အချင်းချင်းပေါ်မူတည်မှုတွေကို သင်ယူနိုင်ပါတယ်။ ဥပမာအားဖြင့် *not* ဆိုတဲ့ စကားလုံးတစ်လုံးက sequence တစ်ခုမှာ တစ်နေရာမှာပေါ်လာတဲ့အခါ state vector အတွင်းမှာ အချို့ element တွေကို negate လုပ်နိုင်ဖို့ သင်ယူနိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"> RNN blocks တွေမှာ weight တွေကို share လုပ်ထားတဲ့အတွက် ပုံမှာ RNN blocks အားလုံးကို block တစ်ခုအနေနဲ့ (ညာဘက်မှာ) recurrent feedback loop နဲ့ ပြန်လည်ဖော်ပြနိုင်ပါတယ်။ ဒီ loop က network ရဲ့ output state ကို input အနေနဲ့ ပြန်လည်ပေးပို့ပါတယ်။\n",
|
||||
"\n",
|
||||
"အခု ကျွန်တော်တို့ရဲ့ news dataset ကို classify လုပ်ဖို့ recurrent neural networks က ဘယ်လို အကူအညီပေးနိုင်မလဲဆိုတာ ကြည့်လိုက်ရအောင်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Loading dataset...\n",
|
||||
"Building vocab...\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import torch\n",
|
||||
"import torchtext\n",
|
||||
"from torchnlp import *\n",
|
||||
"train_dataset, test_dataset, classes, vocab = load_dataset()\n",
|
||||
"vocab_size = len(vocab)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## ရိုးရှင်းသော RNN ခွဲခြားသူ\n",
|
||||
"\n",
|
||||
"ရိုးရှင်းသော RNN ၏အခြေအနေတွင်၊ တစ်ခုချင်းစီသော recurrent unit သည် ရိုးရှင်းသော linear network တစ်ခုဖြစ်ပြီး၊ input vector နှင့် state vector ကိုပေါင်းစပ်ပြီး အသစ်သော state vector တစ်ခုကို ထုတ်လုပ်ပေးသည်။ PyTorch သည် ဤ unit ကို `RNNCell` class ဖြင့် ကိုယ်စားပြုပြီး၊ ဤ cells များ၏ network များကို `RNN` layer အဖြစ် ကိုယ်စားပြုသည်။\n",
|
||||
"\n",
|
||||
"RNN ခွဲခြားသူတစ်ခုကို သတ်မှတ်ရန်အတွက်၊ အရင်ဆုံး input vocabulary ၏ dimensionality ကို လျှော့ချရန် embedding layer တစ်ခုကို အသုံးပြုပြီး၊ ထို့နောက် RNN layer ကို ထပ်တင်ပါမည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class RNNClassifier(torch.nn.Module):\n",
|
||||
" def __init__(self, vocab_size, embed_dim, hidden_dim, num_class):\n",
|
||||
" super().__init__()\n",
|
||||
" self.hidden_dim = hidden_dim\n",
|
||||
" self.embedding = torch.nn.Embedding(vocab_size, embed_dim)\n",
|
||||
" self.rnn = torch.nn.RNN(embed_dim,hidden_dim,batch_first=True)\n",
|
||||
" self.fc = torch.nn.Linear(hidden_dim, num_class)\n",
|
||||
"\n",
|
||||
" def forward(self, x):\n",
|
||||
" batch_size = x.size(0)\n",
|
||||
" x = self.embedding(x)\n",
|
||||
" x,h = self.rnn(x)\n",
|
||||
" return self.fc(x.mean(dim=1))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **Note:** ဒီနေရာမှာ ကျွန်တော်တို့ Untrained embedding layer ကို အသုံးပြုထားပါတယ်၊ ဒါပေမယ့် ပိုမိုကောင်းမွန်တဲ့ရလဒ်ရဖို့ Word2Vec သို့မဟုတ် GloVe embeddings နဲ့ အတူ Pre-trained embedding layer ကို အသုံးပြုနိုင်ပါတယ်၊ အရင်ယူနစ်မှာ ဖော်ပြထားသလိုပဲ။ ပိုမိုနားလည်စေရန် ဒီကုဒ်ကို Pre-trained embeddings နဲ့ အလုပ်လုပ်အောင် ပြောင်းလဲကြည့်နိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"ဒီအခါမှာတော့ ကျွန်တော်တို့ Padded data loader ကို အသုံးပြုမှာဖြစ်ပြီး၊ အဲ့ဒီလိုဖြစ်တဲ့အခါမှာ တစ်ခုချင်းစီ batch မှာ အရှည်တူတဲ့ Padded sequences အရေအတွက် ပါဝင်မှာဖြစ်ပါတယ်။ RNN layer က embedding tensors ရဲ့ အစဉ်အတိုင်း sequence ကို ယူပြီး output နှစ်ခုကို ထုတ်ပေးပါမယ်။\n",
|
||||
"* $x$ ကတော့ RNN cell outputs တွေကို တစ်ဆင့်ချင်းစီမှာ sequence အတိုင်း ထုတ်ပေးမှာဖြစ်ပါတယ်။\n",
|
||||
"* $h$ ကတော့ sequence ရဲ့ နောက်ဆုံး element အတွက် final hidden state ဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"ဒီနောက်မှာတော့ Fully-connected linear classifier ကို အသုံးပြုပြီး အတန်းအရေအတွက်ကို ထုတ်ယူမှာဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"> **Note:** RNN တွေကို သင်ကြားဖို့ အတော်ခက်ခဲပါတယ်၊ အကြောင်းကတော့ RNN cells တွေကို sequence length အတိုင်း unroll လုပ်လိုက်တဲ့အခါမှာ Back propagation အတွက် ပါဝင်တဲ့ Layers အရေအတွက် အတော်များလာတတ်ပါတယ်။ ဒါကြောင့် Learning rate ကို သေးငယ်စွာရွေးချယ်ရမယ်၊ နဲ့ အကြီးမားတဲ့ Dataset ပေါ်မှာ Network ကို သင်ကြားရမယ်၊ ဒါမှသာ ကောင်းမွန်တဲ့ရလဒ်ရနိုင်ပါတယ်။ အချိန်အတော်ကြာတတ်တာကြောင့် GPU ကို အသုံးပြုရင် ပိုမိုအဆင်ပြေပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3200: acc=0.3090625\n",
|
||||
"6400: acc=0.38921875\n",
|
||||
"9600: acc=0.4590625\n",
|
||||
"12800: acc=0.511953125\n",
|
||||
"16000: acc=0.5506875\n",
|
||||
"19200: acc=0.57921875\n",
|
||||
"22400: acc=0.6070089285714285\n",
|
||||
"25600: acc=0.6304296875\n",
|
||||
"28800: acc=0.6484027777777778\n",
|
||||
"32000: acc=0.66509375\n",
|
||||
"35200: acc=0.6790056818181818\n",
|
||||
"38400: acc=0.6929166666666666\n",
|
||||
"41600: acc=0.7035817307692308\n",
|
||||
"44800: acc=0.7137276785714286\n",
|
||||
"48000: acc=0.72225\n",
|
||||
"51200: acc=0.73001953125\n",
|
||||
"54400: acc=0.7372794117647059\n",
|
||||
"57600: acc=0.7436631944444444\n",
|
||||
"60800: acc=0.7503947368421052\n",
|
||||
"64000: acc=0.75634375\n",
|
||||
"67200: acc=0.7615773809523809\n",
|
||||
"70400: acc=0.7662642045454545\n",
|
||||
"73600: acc=0.7708423913043478\n",
|
||||
"76800: acc=0.7751822916666666\n",
|
||||
"80000: acc=0.7790625\n",
|
||||
"83200: acc=0.7825\n",
|
||||
"86400: acc=0.7858564814814815\n",
|
||||
"89600: acc=0.7890513392857142\n",
|
||||
"92800: acc=0.7920474137931034\n",
|
||||
"96000: acc=0.7952708333333334\n",
|
||||
"99200: acc=0.7982258064516129\n",
|
||||
"102400: acc=0.80099609375\n",
|
||||
"105600: acc=0.8037594696969697\n",
|
||||
"108800: acc=0.8060569852941176\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=padify, shuffle=True)\n",
|
||||
"net = RNNClassifier(vocab_size,64,32,len(classes)).to(device)\n",
|
||||
"train_epoch(net,train_loader, lr=0.001)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## ရေရှည်တိုတောင်းမှတ်ဉာဏ် (Long Short Term Memory - LSTM)\n",
|
||||
"\n",
|
||||
"ရိုးရာ RNNs တွေမှာ အဓိကပြဿနာတစ်ခုက **vanishing gradients** ပြဿနာဖြစ်ပါတယ်။ RNNs တွေကို တစ်ကြိမ်တည်းမှာ အဆုံး-to-အဆုံး back-propagation နည်းလမ်းနဲ့ သင်ကြားရတဲ့အတွက် error ကို network ရဲ့ ပထမဆုံး layer တွေထိ ပြန်ပို့ဖို့ အခက်အခဲရှိပါတယ်။ ဒီကြောင့် network က အဝေးက token တွေကြားက ဆက်နွယ်မှုတွေကို သင်ယူလို့မရနိုင်ပါဘူး။ ဒီပြဿနာကို ရှောင်ရှားဖို့နည်းလမ်းတစ်ခုက **explicit state management** ကို **gates** လို့ခေါ်တဲ့ နည်းလမ်းနဲ့ အသုံးပြုဖို့ ဖြစ်ပါတယ်။ ဒီအမျိုးအစားမှာ အထင်ရှားဆုံး architecture နှစ်ခုရှိပါတယ် - **Long Short Term Memory** (LSTM) နဲ့ **Gated Relay Unit** (GRU) ဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"LSTM Network ကို RNN နဲ့ ဆင်တူတဲ့ပုံစံနဲ့ စီမံထားပြီး layer တစ်ခုမှ layer တစ်ခုဆီကို state နှစ်ခုကို ပို့ပေးပါတယ် - အမှန်တကယ် state $c$ နဲ့ hidden vector $h$ ဖြစ်ပါတယ်။ Unit တစ်ခုစီမှာ hidden vector $h_i$ ကို input $x_i$ နဲ့ concatenation လုပ်ပြီး **gates** တွေက state $c$ ကို ဘယ်လိုထိန်းချုပ်မယ်ဆိုတာကို ဆုံးဖြတ်ပါတယ်။ Gate တစ်ခုစီက sigmoid activation (output $[0,1]$ အတွင်း) ပါရှိတဲ့ neural network ဖြစ်ပြီး state vector ကို မျှတစွာ mask လုပ်တဲ့အခါမှာ bitwise mask အနေနဲ့ တွေးနိုင်ပါတယ်။ အပေါ်ပုံမှာ (ဘယ်မှညာ) gates တွေက:\n",
|
||||
"* **forget gate** က hidden vector ကိုယူပြီး vector $c$ ရဲ့ ဘယ် components တွေကို မေ့ပစ်ရမလဲ၊ ဘယ် components တွေကို ဆက်လက်အသုံးပြုရမလဲဆိုတာ ဆုံးဖြတ်ပါတယ်။\n",
|
||||
"* **input gate** က input နဲ့ hidden vector မှ အချက်အလက်တစ်ချို့ကိုယူပြီး state ထဲကို ထည့်သွင်းပါတယ်။\n",
|
||||
"* **output gate** က state ကို $\\tanh$ activation နဲ့ linear layer တစ်ခုကနေ ပြောင်းပြီး hidden vector $h_i$ ကို အသုံးပြုကာ state အသစ် $c_{i+1}$ ကို ထုတ်လုပ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"State $c$ ရဲ့ components တွေကို flag တွေလို switch on/off လုပ်နိုင်တဲ့အရာတွေလို တွေးနိုင်ပါတယ်။ ဥပမာအားဖြင့် sequence မှာ *Alice* ဆိုတဲ့နာမည်ကိုတွေ့တဲ့အခါ female character ကိုရည်ညွှန်းတယ်လို့ယူဆပြီး state မှာ female noun ရှိတယ်ဆိုတဲ့ flag ကိုတင်နိုင်ပါတယ်။ နောက်ပိုင်းမှာ *and Tom* ဆိုတဲ့ phrase ကိုတွေ့တဲ့အခါ plural noun ရှိတယ်ဆိုတဲ့ flag ကိုတင်နိုင်ပါတယ်။ ဒီလို state ကို ထိန်းချုပ်ခြင်းအားဖြင့် sentence ရဲ့ grammar properties တွေကို ထိန်းသိမ်းနိုင်တယ်လို့ ယူဆနိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"> **Note**: LSTM ရဲ့ အတွင်းပိုင်းကို နားလည်ဖို့အတွက် Christopher Olah ရဲ့ [Understanding LSTM Networks](https://colah.github.io/posts/2015-08-Understanding-LSTMs/) ဆိုတဲ့ ဆောင်းပါးက အလွန်ကောင်းမွန်တဲ့ resource ဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"LSTM cell ရဲ့ အတွင်းပိုင်းဖွဲ့စည်းပုံက ရှုပ်ထွေးနေသလိုပဲ PyTorch က `LSTMCell` class ထဲမှာ ဒီ implementation ကို ဖုံးကွယ်ထားပြီး `LSTM` object ကို LSTM layer အဖြစ် ကိုယ်စားပြုထားပါတယ်။ ဒါကြောင့် LSTM classifier ရဲ့ implementation က အထက်မှာ ကြည့်ခဲ့တဲ့ ရိုးရှင်းတဲ့ RNN နဲ့ ဆင်တူနေမှာဖြစ်ပါတယ်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class LSTMClassifier(torch.nn.Module):\n",
|
||||
" def __init__(self, vocab_size, embed_dim, hidden_dim, num_class):\n",
|
||||
" super().__init__()\n",
|
||||
" self.hidden_dim = hidden_dim\n",
|
||||
" self.embedding = torch.nn.Embedding(vocab_size, embed_dim)\n",
|
||||
" self.embedding.weight.data = torch.randn_like(self.embedding.weight.data)-0.5\n",
|
||||
" self.rnn = torch.nn.LSTM(embed_dim,hidden_dim,batch_first=True)\n",
|
||||
" self.fc = torch.nn.Linear(hidden_dim, num_class)\n",
|
||||
"\n",
|
||||
" def forward(self, x):\n",
|
||||
" batch_size = x.size(0)\n",
|
||||
" x = self.embedding(x)\n",
|
||||
" x,(h,c) = self.rnn(x)\n",
|
||||
" return self.fc(h[-1])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3200: acc=0.259375\n",
|
||||
"6400: acc=0.25859375\n",
|
||||
"9600: acc=0.26177083333333334\n",
|
||||
"12800: acc=0.2784375\n",
|
||||
"16000: acc=0.313\n",
|
||||
"19200: acc=0.3528645833333333\n",
|
||||
"22400: acc=0.3965625\n",
|
||||
"25600: acc=0.4385546875\n",
|
||||
"28800: acc=0.4752777777777778\n",
|
||||
"32000: acc=0.505375\n",
|
||||
"35200: acc=0.5326704545454546\n",
|
||||
"38400: acc=0.5557552083333334\n",
|
||||
"41600: acc=0.5760817307692307\n",
|
||||
"44800: acc=0.5954910714285714\n",
|
||||
"48000: acc=0.6118333333333333\n",
|
||||
"51200: acc=0.62681640625\n",
|
||||
"54400: acc=0.6404779411764706\n",
|
||||
"57600: acc=0.6520138888888889\n",
|
||||
"60800: acc=0.662828947368421\n",
|
||||
"64000: acc=0.673546875\n",
|
||||
"67200: acc=0.6831547619047619\n",
|
||||
"70400: acc=0.6917897727272727\n",
|
||||
"73600: acc=0.6997146739130434\n",
|
||||
"76800: acc=0.707109375\n",
|
||||
"80000: acc=0.714075\n",
|
||||
"83200: acc=0.7209134615384616\n",
|
||||
"86400: acc=0.727037037037037\n",
|
||||
"89600: acc=0.7326674107142858\n",
|
||||
"92800: acc=0.7379633620689655\n",
|
||||
"96000: acc=0.7433645833333333\n",
|
||||
"99200: acc=0.7479032258064516\n",
|
||||
"102400: acc=0.752119140625\n",
|
||||
"105600: acc=0.7562405303030303\n",
|
||||
"108800: acc=0.76015625\n",
|
||||
"112000: acc=0.7641339285714286\n",
|
||||
"115200: acc=0.7677777777777778\n",
|
||||
"118400: acc=0.7711233108108108\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(0.03487814127604167, 0.7728)"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"net = LSTMClassifier(vocab_size,64,32,len(classes)).to(device)\n",
|
||||
"train_epoch(net,train_loader, lr=0.001)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## အစုအဝေးများကို ထုပ်ပိုးခြင်း\n",
|
||||
"\n",
|
||||
"ဥပမာမှာတော့ minibatch ထဲမှာ sequence တွေကို zero vector တွေနဲ့ padding လုပ်ဖို့လိုအပ်ခဲ့ပါတယ်။ ဒါဟာ memory ကို အချို့အပိုသုံးစွဲရတာဖြစ်ပေမယ့် RNN တွေမှာတော့ padding လုပ်ထားတဲ့ input item တွေကြောင့် RNN cell အသစ်တွေကို ဖန်တီးရတာပိုအရေးကြီးပါတယ်။ အဲဒီ cell တွေဟာ training မှာ ပါဝင်ပေမယ့် အရေးကြီးတဲ့ input အချက်အလက်တွေကို မပါဝင်စေပါဘူး။ အဲဒီအစား RNN ကို အမှန်တကယ် sequence size အတိုင်း training လုပ်တာပိုကောင်းပါတယ်။\n",
|
||||
"\n",
|
||||
"ဒါကိုလုပ်ဖို့ PyTorch မှာ padding လုပ်ထားတဲ့ sequence တွေကို သိမ်းဆည်းဖို့ အထူး format တစ်ခုကို မိတ်ဆက်ထားပါတယ်။ ဥပမာအားဖြင့် input padded minibatch က ဒီလိုပုံစံရှိတယ်ဆိုပါစို့:\n",
|
||||
"```\n",
|
||||
"[[1,2,3,4,5],\n",
|
||||
" [6,7,8,0,0],\n",
|
||||
" [9,0,0,0,0]]\n",
|
||||
"```\n",
|
||||
"ဒီမှာ 0 တွေဟာ padding လုပ်ထားတဲ့ value တွေကို ကိုယ်စားပြုပြီး၊ input sequence တွေရဲ့ အမှန်တကယ် length vector က `[5,3,1]` ဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"padding လုပ်ထားတဲ့ sequence တွေနဲ့ RNN ကို ထိရောက်စွာ training လုပ်ဖို့အတွက် RNN cell တွေကို ပထမအကြိမ် training လုပ်တဲ့အခါမှာ minibatch ကြီး (`[1,6,9]`) ကို စတင်သုံးပြီး၊ အဲဒီနောက်မှာတော့ တတိယ sequence ကို processing ပြီးဆုံးပြီး၊ minibatch သေးသေးလေးတွေ (`[2,7]`, `[3,8]`) နဲ့ training ကို ဆက်လက်လုပ်ဆောင်သင့်ပါတယ်။ ဒီလိုနည်းဖြင့် packed sequence ကို vector တစ်ခုအနေနဲ့ ကိုယ်စားပြုထားပါတယ် - ဥပမာအားဖြင့် `[1,6,9,2,7,3,8,4,5]` ဖြစ်ပြီး၊ length vector (`[5,3,1]`) ကနေ အစမှတ် minibatch ကို ပြန်လည်တည်ဆောက်နိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"packed sequence ကို ထုတ်လုပ်ဖို့ `torch.nn.utils.rnn.pack_padded_sequence` function ကို အသုံးပြုနိုင်ပါတယ်။ RNN, LSTM, GRU အပါအဝင် recurrent layer အားလုံးဟာ packed sequence တွေကို input အနေနဲ့ support လုပ်ပြီး၊ packed output ကို ထုတ်လုပ်နိုင်ပါတယ်။ ထို output ကို `torch.nn.utils.rnn.pad_packed_sequence` ကို အသုံးပြုပြီး decode လုပ်နိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"packed sequence ကို ထုတ်လုပ်နိုင်ဖို့ network ကို length vector ကို pass လုပ်ဖို့လိုအပ်ပါတယ်၊ ဒါကြောင့် minibatch တွေကို ပြင်ဆင်ဖို့ function တစ်ခုကို အသုံးပြုဖို့လိုအပ်ပါတယ်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def pad_length(b):\n",
|
||||
" # build vectorized sequence\n",
|
||||
" v = [encode(x[1]) for x in b]\n",
|
||||
" # compute max length of a sequence in this minibatch and length sequence itself\n",
|
||||
" len_seq = list(map(len,v))\n",
|
||||
" l = max(len_seq)\n",
|
||||
" return ( # tuple of three tensors - labels, padded features, length sequence\n",
|
||||
" torch.LongTensor([t[0]-1 for t in b]),\n",
|
||||
" torch.stack([torch.nn.functional.pad(torch.tensor(t),(0,l-len(t)),mode='constant',value=0) for t in v]),\n",
|
||||
" torch.tensor(len_seq)\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"train_loader_len = torch.utils.data.DataLoader(train_dataset, batch_size=16, collate_fn=pad_length, shuffle=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အမှန်တကယ်က `LSTMClassifier` နမူနာနဲ့ အလွန်ဆင်တူတဲ့ network ဖြစ်မှာပါ၊ ဒါပေမယ့် `forward` pass ကတော့ padded minibatch နဲ့ sequence lengths ရဲ့ vector နှစ်ခုလုံးကို လက်ခံရမှာဖြစ်ပါတယ်။ Embedding ကိုတွက်ချက်ပြီးနောက်မှာ packed sequence ကိုတွက်ချက်ပြီး LSTM layer ကိုပို့ပြီးနောက်မှာ ပြန်လည် unpack လုပ်ပါမယ်။\n",
|
||||
"\n",
|
||||
"> **Note**: အမှန်တကယ်တော့ unpack လုပ်ထားတဲ့ `x` ရလဒ်ကို မသုံးပါဘူး၊ အကြောင်းက hidden layers က output ကို နောက်ထပ်တွက်ချက်မှုတွေမှာ သုံးမယ့်အတွက်ပါ။ ဒါကြောင့် ဒီ code မှာ unpacking ကို အပြည့်အဝ ဖယ်ရှားနိုင်ပါတယ်။ ဒါပေမယ့် ဒီ code ကို နောက်ထပ်တွက်ချက်မှုတွေမှာ network output ကို သုံးဖို့ လိုအပ်လာရင် အလွယ်တကူ ပြင်ဆင်နိုင်ဖို့အတွက် ဒီနေရာမှာ ထားထားတာပါ။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class LSTMPackClassifier(torch.nn.Module):\n",
|
||||
" def __init__(self, vocab_size, embed_dim, hidden_dim, num_class):\n",
|
||||
" super().__init__()\n",
|
||||
" self.hidden_dim = hidden_dim\n",
|
||||
" self.embedding = torch.nn.Embedding(vocab_size, embed_dim)\n",
|
||||
" self.embedding.weight.data = torch.randn_like(self.embedding.weight.data)-0.5\n",
|
||||
" self.rnn = torch.nn.LSTM(embed_dim,hidden_dim,batch_first=True)\n",
|
||||
" self.fc = torch.nn.Linear(hidden_dim, num_class)\n",
|
||||
"\n",
|
||||
" def forward(self, x, lengths):\n",
|
||||
" batch_size = x.size(0)\n",
|
||||
" x = self.embedding(x)\n",
|
||||
" pad_x = torch.nn.utils.rnn.pack_padded_sequence(x,lengths,batch_first=True,enforce_sorted=False)\n",
|
||||
" pad_x,(h,c) = self.rnn(pad_x)\n",
|
||||
" x, _ = torch.nn.utils.rnn.pad_packed_sequence(pad_x,batch_first=True)\n",
|
||||
" return self.fc(h[-1])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"3200: acc=0.285625\n",
|
||||
"6400: acc=0.33359375\n",
|
||||
"9600: acc=0.3876041666666667\n",
|
||||
"12800: acc=0.44078125\n",
|
||||
"16000: acc=0.4825\n",
|
||||
"19200: acc=0.5235416666666667\n",
|
||||
"22400: acc=0.5559821428571429\n",
|
||||
"25600: acc=0.58609375\n",
|
||||
"28800: acc=0.6116666666666667\n",
|
||||
"32000: acc=0.63340625\n",
|
||||
"35200: acc=0.6525284090909091\n",
|
||||
"38400: acc=0.668515625\n",
|
||||
"41600: acc=0.6822596153846154\n",
|
||||
"44800: acc=0.6948214285714286\n",
|
||||
"48000: acc=0.7052708333333333\n",
|
||||
"51200: acc=0.71521484375\n",
|
||||
"54400: acc=0.7239889705882353\n",
|
||||
"57600: acc=0.7315277777777778\n",
|
||||
"60800: acc=0.7388486842105263\n",
|
||||
"64000: acc=0.74571875\n",
|
||||
"67200: acc=0.7518303571428572\n",
|
||||
"70400: acc=0.7576988636363636\n",
|
||||
"73600: acc=0.7628940217391305\n",
|
||||
"76800: acc=0.7681510416666667\n",
|
||||
"80000: acc=0.7728125\n",
|
||||
"83200: acc=0.7772235576923077\n",
|
||||
"86400: acc=0.7815393518518519\n",
|
||||
"89600: acc=0.7857700892857142\n",
|
||||
"92800: acc=0.7895043103448276\n",
|
||||
"96000: acc=0.7930520833333333\n",
|
||||
"99200: acc=0.7959072580645161\n",
|
||||
"102400: acc=0.798994140625\n",
|
||||
"105600: acc=0.802064393939394\n",
|
||||
"108800: acc=0.8051378676470589\n",
|
||||
"112000: acc=0.8077857142857143\n",
|
||||
"115200: acc=0.8104600694444445\n",
|
||||
"118400: acc=0.8128293918918919\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(0.029785829671223958, 0.8138166666666666)"
|
||||
]
|
||||
},
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"net = LSTMPackClassifier(vocab_size,64,32,len(classes)).to(device)\n",
|
||||
"train_epoch_emb(net,train_loader_len, lr=0.001,use_pack_sequence=True)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Bidirectional နှင့် multilayer RNNs\n",
|
||||
"\n",
|
||||
"ကျွန်တော်တို့ရဲ့ ဥပမာတွေမှာ၊ အားလုံး recurrent networks တွေဟာ direction တစ်ခုတည်းမှာ လုပ်ဆောင်ခဲ့ပါတယ်၊ sequence ရဲ့အစမှ အဆုံးအထိ။ ဒါဟာ သဘာဝကျတဲ့အရာလိုပဲ၊ အကြောင်းကတော့ ကျွန်တော်တို့ စာဖတ်တာနဲ့ စကားနားထောင်တာကို တူတူပဲ။ သို့သော်လည်း၊ အများအပြား အကဲဖြတ်မှုတွေမှာ input sequence ကို random access လုပ်နိုင်တဲ့အခြေအနေရှိတဲ့အခါ၊ recurrent computation ကို direction နှစ်ခုလုံးမှာ လုပ်ဆောင်တာ make sense ဖြစ်နိုင်ပါတယ်။ ဒီလို networks တွေကို **bidirectional** RNNs လို့ခေါ်ပြီး၊ RNN/LSTM/GRU constructor ကို `bidirectional=True` parameter ဖြင့် pass လုပ်ခြင်းအားဖြင့် ဖန်တီးနိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"Bidirectional network ကို handle လုပ်တဲ့အခါ၊ direction တစ်ခုစီအတွက် hidden state vector နှစ်ခုလိုအပ်ပါမယ်။ PyTorch က ဒီ vectors တွေကို twice larger size ရှိတဲ့ vector တစ်ခုအဖြစ် encode လုပ်ပေးပါတယ်၊ ဒါဟာ အဆင်ပြေပါတယ်၊ အကြောင်းကတော့ normally hidden state ကို fully-connected linear layer ကို pass လုပ်မှာဖြစ်ပြီး၊ layer ဖန်တီးတဲ့အခါ size တိုးလာတာကို သတိထားရုံပဲ လိုအပ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"Recurrent network, one-directional ဖြစ်စေ bidirectional ဖြစ်စေ၊ sequence တစ်ခုအတွင်းမှာ pattern အချို့ကို capture လုပ်နိုင်ပြီး၊ state vector ထဲမှာ သိမ်းဆည်းနိုင်သလို output ကို pass လုပ်နိုင်ပါတယ်။ Convolutional networks တွေနဲ့တူတူပဲ၊ ပထမ layer က low-level patterns တွေကို extract လုပ်ပြီး၊ အဲ့ဒီ patterns တွေကို အသုံးပြုပြီး higher level patterns တွေကို capture လုပ်ဖို့ ပထမ layer ရဲ့အပေါ်မှာ recurrent layer တစ်ခုတိုးဖွဲ့နိုင်ပါတယ်။ ဒီအရာက **multi-layer RNN** ဆိုတဲ့အယူအဆကို ရောက်လာစေပြီး၊ ဒါဟာ recurrent networks နှစ်ခု သို့မဟုတ် အများကြီးပါဝင်ပြီး၊ အရင် layer ရဲ့ output ကို နောက် layer ရဲ့ input အဖြစ် pass လုပ်ပေးတဲ့ network ဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"*Fernando López ရဲ့ [ဒီ post](https://towardsdatascience.com/from-a-lstm-cell-to-a-multilayer-lstm-network-with-pytorch-2899eb5696f3) မှာရရှိတဲ့ပုံ*\n",
|
||||
"\n",
|
||||
"PyTorch က ဒီလို networks တွေကို ဖန်တီးဖို့ လွယ်ကူစေပါတယ်၊ အကြောင်းကတော့ `num_layers` parameter ကို RNN/LSTM/GRU constructor ကို pass လုပ်ရုံနဲ့ recurrence layers အများကြီးကို အလိုအလျောက် ဖန်တီးနိုင်ပါတယ်။ ဒါဟာ hidden/state vector ရဲ့ size တိုးလာမယ်ဆိုတာကိုလည်း အဓိကထားရမယ်၊ recurrent layers ရဲ့ output ကို handle လုပ်တဲ့အခါ ဒီအချက်ကို သတိထားဖို့လိုပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## RNN များကို အခြားအလုပ်များအတွက် အသုံးပြုခြင်း\n",
|
||||
"\n",
|
||||
"ဤယူနစ်တွင် RNN များကို အစီအစဉ်အလိုက် အမျိုးအစားခွဲခြင်းအတွက် အသုံးပြုနိုင်သည်ကို တွေ့ရှိခဲ့ပြီး၊ အမှန်တကယ်တွင် RNN များသည် စာသားထုတ်လုပ်ခြင်း၊ စက်ဖြင့်ဘာသာပြန်ခြင်းနှင့် အခြားအလုပ်များစွာကိုလည်း ကိုင်တွယ်နိုင်ပါသည်။ ဤအလုပ်များကို နောက်ယူနစ်တွင် ဆွေးနွေးမည်ဖြစ်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်မှုများတွင် အမှားများ သို့မဟုတ် မမှန်ကန်မှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာရှိသော ရင်းမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူ့ဘာသာပြန်ပညာရှင်များမှ ပရော်ဖက်ရှင်နယ် ဘာသာပြန်မှုကို အကြံပြုပါသည်။ ဤဘာသာပြန်မှုကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအမှားများ သို့မဟုတ် အနားယူမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.8.12 ('py38')",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "522ee52ae3d5ae933e283286254e9a55",
|
||||
"translation_date": "2025-08-30T10:32:23+00:00",
|
||||
"source_file": "lessons/5-NLP/16-RNN/RNNPyTorch.ipynb",
|
||||
"language_code": "my"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
|
|
@ -0,0 +1,460 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# ပြန်လည်ထပ်ခါတလဲလဲ နယူးရယ်နက်ဝက်များ\n",
|
||||
"\n",
|
||||
"ယခင် module တွင်၊ စာသားများ၏ အဓိပ္ပါယ်ဆိုင်ရာ သက်သေခံမှုများကို လေ့လာခဲ့ပါသည်။ ကျွန်ုပ်တို့အသုံးပြုနေသော architecture သည် စာကြောင်းတစ်ကြောင်းအတွင်းရှိ စကားလုံးများ၏ ပေါင်းစည်းထားသော အဓိပ္ပါယ်ကို ဖမ်းဆီးနိုင်သည်။ သို့သော် စကားလုံးများ၏ **အစီအစဉ်** ကို မထည့်သွင်းစဉ်းစားနိုင်ပါ၊ အကြောင်းမှာ embedding များကို လိုက်နာပြီး aggregation လုပ်ငန်းစဉ်သည် မူလစာသားမှ အချက်အလက်များကို ဖယ်ရှားလိုက်သောကြောင့် ဖြစ်သည်။ စကားလုံးအစီအစဉ်ကို ကိုယ်စားပြုနိုင်မှုမရှိသောကြောင့်၊ မိမိတို့သည် စာသားထုတ်လုပ်ခြင်း သို့မဟုတ် မေးခွန်းဖြေဆိုခြင်းကဲ့သို့သော ပိုမိုရှုပ်ထွေးသော သို့မဟုတ် မရှင်းလင်းသော လုပ်ငန်းများကို ဖြေရှင်းနိုင်မည်မဟုတ်ပါ။\n",
|
||||
"\n",
|
||||
"စာသားအစီအစဉ်၏ အဓိပ္ပါယ်ကို ဖမ်းဆီးရန်၊ **recurrent neural network** (RNN) ဟုခေါ်သော နယူးရယ်နက်ဝက် architecture ကို အသုံးပြုမည်ဖြစ်သည်။ RNN ကို အသုံးပြုသောအခါ၊ ကျွန်ုပ်တို့၏ စာကြောင်းကို network အတွင်းသို့ token တစ်ခုစီဖြင့် အဆင့်ဆင့် ဖြတ်သန်းပြီး၊ network သည် **state** တစ်ခုကို ထုတ်ပေးမည်ဖြစ်သည်။ ထို state ကို နောက် token နှင့်အတူ network သို့ ပြန်လည်ထည့်သွင်းမည်ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"tokens များ၏ input အစီအစဉ် $X_0,\\dots,X_n$ ကို ပေးသောအခါ၊ RNN သည် နယူးရယ်နက်ဝက် block များ၏ အစီအစဉ်တစ်ခုကို ဖန်တီးပြီး၊ ထိုအစီအစဉ်ကို backpropagation အသုံးပြု၍ အဆုံးမှ အဆုံးသို့ လေ့ကျင့်သည်။ network block တစ်ခုစီသည် $(X_i,S_i)$ ကို input အနေဖြင့် လက်ခံပြီး၊ $S_{i+1}$ ကို ရလဒ်အဖြစ် ထုတ်ပေးသည်။ နောက်ဆုံး state $S_n$ သို့မဟုတ် output $Y_n$ ကို linear classifier သို့ ပေးပို့ပြီး ရလဒ်ကို ထုတ်ယူသည်။ network block အားလုံးသည် တူညီသော weight များကို မျှဝေထားပြီး၊ တစ်ကြိမ်တည်းသော backpropagation pass ဖြင့် အဆုံးမှ အဆုံးသို့ လေ့ကျင့်သည်။\n",
|
||||
"\n",
|
||||
"> အထက်ပါပုံတွင် RNN ကို unrolled ပုံစံ (ဘယ်ဖက်တွင်) နှင့် ပိုမိုချုပ်ငြိ RNN ကိုယ်စားပြုမှု (ညာဖက်တွင်) အနေဖြင့် ပြထားသည်။ RNN Cells အားလုံးတွင် **မျှဝေနိုင်သော weight များ** ရှိသည်ကို နားလည်ရန် အရေးကြီးသည်။\n",
|
||||
"\n",
|
||||
"state vectors $S_0,\\dots,S_n$ များကို network အတွင်း ဖြတ်သန်းပေးသောကြောင့်၊ RNN သည် စကားလုံးများအကြား အစီအစဉ်ဆိုင်ရာ အချိတ်အဆက်များကို သင်ယူနိုင်သည်။ ဥပမာအားဖြင့်၊ စာကြောင်းတစ်ခုအတွင်း *not* ဟူသော စကားလုံးတစ်လုံး ပေါ်လာသောအခါ၊ state vector အတွင်းရှိ အချို့သော အရာများကို ငြင်းဆိုရန် သင်ယူနိုင်သည်။\n",
|
||||
"\n",
|
||||
"RNN cell တစ်ခုစီအတွင်းတွင် weight matrix နှစ်ခု $W_H$ နှင့် $W_I$၊ နှင့် bias $b$ တို့ ပါဝင်သည်။ RNN အဆင့်တစ်ခုစီတွင်၊ input $X_i$ နှင့် input state $S_i$ ကို ပေးသောအခါ၊ output state ကို $S_{i+1} = f(W_H\\times S_i + W_I\\times X_i+b)$ အဖြစ်တွက်ချက်သည်၊ ဤတွင် $f$ သည် activation function (အများအားဖြင့် $\\tanh$) ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"> စာသားထုတ်လုပ်မှု (ကျွန်ုပ်တို့သည် နောက်ထပ် unit တွင် လေ့လာမည့်အရာ) သို့မဟုတ် စက်ဖြင့်ဘာသာပြန်ခြင်းကဲ့သို့သော ပြဿနာများအတွက်၊ RNN အဆင့်တစ်ခုစီတွင် output တန်ဖိုးတစ်ခုကိုလည်း ရရှိလိုသည်။ ဤအခါတွင် $W_O$ ဟုခေါ်သော matrix တစ်ခုလည်း ရှိပြီး၊ output ကို $Y_i=f(W_O\\times S_i+b_O)$ အဖြစ်တွက်ချက်သည်။\n",
|
||||
"\n",
|
||||
"ယခု RNN များက ကျွန်ုပ်တို့၏ သတင်းဒေတာစုပေါင်းကို မည်သို့ ခွဲခြားနိုင်မည်ကို ကြည့်ကြရအောင်။\n",
|
||||
"\n",
|
||||
"> sandbox ပတ်ဝန်းကျင်အတွက်၊ လိုအပ်သော library ကို install လုပ်ပြီး၊ ဒေတာကို ကြိုတင်ရယူထားရန် အောက်ပါ cell ကို run လိုက်ရမည်ဖြစ်သည်။ သင်သည် local တွင် run လုပ်နေပါက၊ အောက်ပါ cell ကို ကျော်သွားနိုင်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import sys\n",
|
||||
"!{sys.executable} -m pip install --quiet tensorflow_datasets==4.4.0\n",
|
||||
"!cd ~ && wget -q -O - https://mslearntensorflowlp.blob.core.windows.net/data/tfds-ag-news.tgz | tar xz"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import tensorflow as tf\n",
|
||||
"from tensorflow import keras\n",
|
||||
"import tensorflow_datasets as tfds\n",
|
||||
"import numpy as np\n",
|
||||
"\n",
|
||||
"# We are going to be training pretty large models. In order not to face errors, we need\n",
|
||||
"# to set tensorflow option to grow GPU memory allocation when required\n",
|
||||
"physical_devices = tf.config.list_physical_devices('GPU') \n",
|
||||
"if len(physical_devices)>0:\n",
|
||||
" tf.config.experimental.set_memory_growth(physical_devices[0], True)\n",
|
||||
"\n",
|
||||
"ds_train, ds_test = tfds.load('ag_news_subset').values()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"nteract": {
|
||||
"transient": {
|
||||
"deleting": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
"အကြီးမားသောမော်ဒယ်များကိုလေ့ကျင့်နေစဉ် GPU မှတ်ဉာဏ်အသုံးပြုမှုသည်ပြဿနာဖြစ်နိုင်ပါသည်။ ဒါ့အပြင် GPU မှတ်ဉာဏ်ထဲသို့ဒေတာကိုသင့်တော်စွာထည့်နိုင်ရန်နှင့်လေ့ကျင့်မှုအမြန်နှုန်းလုံလောက်စေရန် မီနီဘတ်ချ်အရွယ်အစားများကိုစမ်းသပ်ရန်လိုအပ်နိုင်ပါသည်။ သင်၏ကိုယ်ပိုင် GPU စက်ပေါ်တွင်ဤကုဒ်ကိုအလုပ်လုပ်နေပါက လေ့ကျင့်မှုအမြန်နှုန်းကိုမြှင့်တင်ရန် မီနီဘတ်ချ်အရွယ်အစားကိုချိန်ညှိခြင်းကိုစမ်းသပ်နိုင်ပါသည်။\n",
|
||||
"\n",
|
||||
"> **Note**: NVidia driver အချို့ဗားရှင်းများသည် မော်ဒယ်ကိုလေ့ကျင့်ပြီးနောက်မှတ်ဉာဏ်ကိုလွှတ်မပေးကြောင်းသိရှိထားပါသည်။ ဤ notebook တွင် ဥပမာများစွာကိုအလုပ်လုပ်နေပြီး သင့် notebook တွင်ကိုယ်ပိုင်စမ်းသပ်မှုများပြုလုပ်နေပါက အချို့သော setup များတွင်မှတ်ဉာဏ်ကုန်ခန်းနိုင်ပါသည်။ မော်ဒယ်ကိုလေ့ကျင့်ရန်စတင်သောအခါ အဆင်မပြေသောအမှားများကြုံတွေ့ပါက notebook kernel ကိုပြန်လည်စတင်ရန်လိုအပ်နိုင်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": true,
|
||||
"jupyter": {
|
||||
"outputs_hidden": false,
|
||||
"source_hidden": false
|
||||
},
|
||||
"nteract": {
|
||||
"transient": {
|
||||
"deleting": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"batch_size = 16\n",
|
||||
"embed_size = 64"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## ရိုးရှင်းသော RNN ခွဲခြားသူ\n",
|
||||
"\n",
|
||||
"ရိုးရှင်းသော RNN ၏အခြေအနေတွင်၊ တစ်ခုချင်းစီသော recurrent unit သည် ရိုးရှင်းသော linear network တစ်ခုဖြစ်ပြီး၊ input vector နှင့် state vector တို့ကို လက်ခံပြီး၊ state vector အသစ်တစ်ခုကို ထုတ်ပေးသည်။ Keras တွင်၊ ၎င်းကို `SimpleRNN` layer ဖြင့် ကိုယ်စားပြုနိုင်သည်။\n",
|
||||
"\n",
|
||||
"RNN layer သို့ one-hot encoded tokens များကို တိုက်ရိုက်ပို့နိုင်သော်လည်း၊ ၎င်းတို့၏ အတိုင်းအတာမြင့်မားမှုကြောင့် ၎င်းသည် ကောင်းမွန်သော အကြံမဟုတ်ပါ။ ထို့ကြောင့်၊ စကားလုံး vector များ၏ အတိုင်းအတာကို လျှော့ချရန် embedding layer တစ်ခုကို အသုံးပြုမည်ဖြစ်ပြီး၊ ထို့နောက် RNN layer တစ်ခုနှင့် နောက်ဆုံးတွင် `Dense` ခွဲခြားသူတစ်ခုကို အသုံးပြုမည်ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"> **Note**: အတိုင်းအတာမမြင့်မားသည့် အခြေအနေများတွင်၊ ဥပမာအားဖြင့် character-level tokenization ကို အသုံးပြုသောအခါ၊ one-hot encoded tokens များကို RNN cell ထဲသို့ တိုက်ရိုက်ပို့ခြင်းသည် make sense ဖြစ်နိုင်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"sequential\"\n",
|
||||
"_________________________________________________________________\n",
|
||||
"Layer (type) Output Shape Param # \n",
|
||||
"=================================================================\n",
|
||||
"text_vectorization (TextVect (None, None) 0 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"embedding (Embedding) (None, None, 64) 1280000 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"simple_rnn (SimpleRNN) (None, 16) 1296 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"dense (Dense) (None, 4) 68 \n",
|
||||
"=================================================================\n",
|
||||
"Total params: 1,281,364\n",
|
||||
"Trainable params: 1,281,364\n",
|
||||
"Non-trainable params: 0\n",
|
||||
"_________________________________________________________________\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vocab_size = 20000\n",
|
||||
"\n",
|
||||
"vectorizer = keras.layers.experimental.preprocessing.TextVectorization(\n",
|
||||
" max_tokens=vocab_size,\n",
|
||||
" input_shape=(1,))\n",
|
||||
"\n",
|
||||
"model = keras.models.Sequential([\n",
|
||||
" vectorizer,\n",
|
||||
" keras.layers.Embedding(vocab_size, embed_size),\n",
|
||||
" keras.layers.SimpleRNN(16),\n",
|
||||
" keras.layers.Dense(4,activation='softmax')\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"model.summary()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **မှတ်ချက်:** ဒီနေရာမှာ ကျွန်တော်တို့ အလွယ်တကူ အသုံးပြုနိုင်ဖို့ untrained embedding layer ကို သုံးထားပါတယ်၊ ဒါပေမယ့် ပိုမိုကောင်းမွန်တဲ့ရလဒ်ရဖို့ Word2Vec ကို အသုံးပြုပြီး pretrained embedding layer ကို သုံးနိုင်ပါတယ်၊ အရင်ယူနစ်မှာ ဖော်ပြထားသလိုပဲ။ Pretrained embeddings ကို အသုံးပြုဖို့ ဒီကုဒ်ကို ပြောင်းလဲဖို့ ကြိုးစားကြည့်တာက သင့်အတွက် ကောင်းမွန်တဲ့လေ့ကျင့်ခန်းတစ်ခု ဖြစ်နိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"အခုတော့ ကျွန်တော်တို့ရဲ့ RNN ကို လေ့ကျင့်ကြည့်ရအောင်။ RNN တွေကို အထွေထွေ လေ့ကျင့်ဖို့ ခက်ခဲတတ်ပါတယ်၊ အကြောင်းကတော့ RNN cells တွေကို sequence length အတိုင်း unroll လုပ်ပြီးရင် backpropagation အတွက် ပါဝင်တဲ့ layer အရေအတွက်က အလွန်များလာတတ်လို့ပါပဲ။ ဒါကြောင့် learning rate ကို သေးငယ်တဲ့တန်ဖိုးတစ်ခုရွေးချယ်ရပြီး၊ ကောင်းမွန်တဲ့ရလဒ်ရဖို့ dataset ကြီးတစ်ခုမှာ network ကို လေ့ကျင့်ရပါတယ်။ ဒါကြောင့် အချိန်အတော်ကြာတတ်ပြီး GPU ကို အသုံးပြုရင် ပိုမိုအဆင်ပြေပါတယ်။\n",
|
||||
"\n",
|
||||
"အချိန်ကို လျှော့ချဖို့ RNN မော်ဒယ်ကို သတင်းခေါင်းစဉ်များပေါ်မှာသာ လေ့ကျင့်မှာဖြစ်ပြီး၊ ဖော်ပြချက်ကို မပါဝင်စေပါဘူး။ သင်ဖော်ပြချက်နဲ့အတူ လေ့ကျင့်ကြည့်ပြီး မော်ဒယ်ကို လေ့ကျင့်နိုင်မလား စမ်းကြည့်နိုင်ပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Training vectorizer\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def extract_title(x):\n",
|
||||
" return x['title']\n",
|
||||
"\n",
|
||||
"def tupelize_title(x):\n",
|
||||
" return (extract_title(x),x['label'])\n",
|
||||
"\n",
|
||||
"print('Training vectorizer')\n",
|
||||
"vectorizer.adapt(ds_train.take(2000).map(extract_title))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"7500/7500 [==============================] - 82s 11ms/step - loss: 0.6629 - acc: 0.7623 - val_loss: 0.5559 - val_acc: 0.7995\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7f3e0030d350>"
|
||||
]
|
||||
},
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
|
||||
"model.fit(ds_train.map(tupelize_title).batch(batch_size),validation_data=ds_test.map(tupelize_title).batch(batch_size))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"nteract": {
|
||||
"transient": {
|
||||
"deleting": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"source": [
|
||||
"**မှတ်ချက်** သတင်းခေါင်းစဉ်များပေါ်တွင်သာလေ့ကျင့်နေသောကြောင့် တိကျမှုနည်းနိုင်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Variable Sequences ကို ပြန်လည်ဆန်းစစ်ခြင်း\n",
|
||||
"\n",
|
||||
"`TextVectorization` layer သည် minibatch အတွင်းရှိ အလျားအစား မတူညီသော sequence များကို အလိုအလျောက် pad token များဖြင့် ဖြည့်စွက်ပေးမည်ဖြစ်သည်ကို သတိရပါ။ သို့သော်၊ ထို token များသည်လည်း training အတွင်း ပါဝင်လာပြီး၊ model ၏ convergence ကို ရှုပ်ထွေးစေနိုင်ပါသည်။\n",
|
||||
"\n",
|
||||
"Padding အရေအတွက်ကို လျှော့ချရန်အတွက် ကျွန်ုပ်တို့ လုပ်ဆောင်နိုင်သည့် နည်းလမ်းအချို့ ရှိပါသည်။ ထိုနည်းလမ်းများထဲမှ တစ်ခုမှာ dataset ကို sequence အလျားအစားအလိုက် ပြန်လည်စီစဉ်ပြီး၊ အရွယ်အစားတူ sequence များကို အုပ်စုဖွဲ့ခြင်းဖြစ်သည်။ ၎င်းကို `tf.data.experimental.bucket_by_sequence_length` function ကို အသုံးပြု၍ ပြုလုပ်နိုင်ပါသည် (အချက်အလက်များကို [documentation](https://www.tensorflow.org/api_docs/python/tf/data/experimental/bucket_by_sequence_length) တွင် ကြည့်ရှုနိုင်ပါသည်)။\n",
|
||||
"\n",
|
||||
"အခြားနည်းလမ်းတစ်ခုမှာ **masking** ကို အသုံးပြုခြင်းဖြစ်သည်။ Keras တွင် layer အချို့သည် training အတွင်း အဘယ် token များကို အရေးထားရမည်ကို ပြသသည့် အပို input ကို ပံ့ပိုးပေးပါသည်။ Masking ကို model အတွင်း ထည့်သွင်းရန်အတွက်၊ `Masking` layer ([docs](https://keras.io/api/layers/core_layers/masking/)) ကို သီးခြားထည့်သွင်းနိုင်သလို၊ `Embedding` layer ၏ `mask_zero=True` parameter ကို သတ်မှတ်နိုင်ပါသည်။\n",
|
||||
"\n",
|
||||
"> **Note**: ဒီ training ကို dataset အပြည့်အစုံအတွက် တစ်ခါ epoch ပြီးမြောက်ရန် ၅ မိနစ်ခန့် ကြာမြင့်မည်ဖြစ်သည်။ သည်းမခံနိုင်လျှင် training ကို မည်သည့်အချိန်တွင်မဆို ရပ်တန့်နိုင်ပါသည်။ ထို့အပြင် training အတွက် အသုံးပြုမည့် data အရေအတွက်ကို ကန့်သတ်လိုပါက `ds_train` နှင့် `ds_test` dataset များအပြီးတွင် `.take(...)` clause ကို ထည့်သွင်းနိုင်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"7500/7500 [==============================] - 371s 49ms/step - loss: 0.5401 - acc: 0.8079 - val_loss: 0.3780 - val_acc: 0.8822\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7f3dec118850>"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def extract_text(x):\n",
|
||||
" return x['title']+' '+x['description']\n",
|
||||
"\n",
|
||||
"def tupelize(x):\n",
|
||||
" return (extract_text(x),x['label'])\n",
|
||||
"\n",
|
||||
"model = keras.models.Sequential([\n",
|
||||
" vectorizer,\n",
|
||||
" keras.layers.Embedding(vocab_size,embed_size,mask_zero=True),\n",
|
||||
" keras.layers.SimpleRNN(16),\n",
|
||||
" keras.layers.Dense(4,activation='softmax')\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(batch_size),validation_data=ds_test.map(tupelize).batch(batch_size))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ယခု Masking ကို အသုံးပြုနေသောကြောင့်၊ ခေါင်းစဉ်များနှင့် ဖော်ပြချက်များ၏ အချက်အလက်စုစည်းမှုအားလုံးကို အသုံးပြု၍ မော်ဒယ်ကို လေ့ကျင့်နိုင်ပါပြီ။\n",
|
||||
"\n",
|
||||
"> **Note**: သတိထားမိပါသလား၊ ကျွန်ုပ်တို့သည် သတင်းခေါင်းစဉ်များပေါ်တွင် လေ့ကျင့်ထားသော vectorizer ကို အသုံးပြုနေပြီး၊ ဆောင်းပါး၏ အပြည့်အစုံကို မဟုတ်ပါ။ အခြား token အချို့ကို မသိသာစေခြင်း ဖြစ်နိုင်ပြီး၊ vectorizer ကို ပြန်လည်လေ့ကျင့်ခြင်းက ပိုမိုကောင်းမွန်နိုင်ပါသည်။ သို့သော်၊ ၎င်းသည် အလွန်သေးငယ်သော အကျိုးသက်ရောက်မှုသာ ရှိနိုင်ပြီး၊ ရိုးရှင်းမှုအတွက် ယခင်လေ့ကျင့်ထားသော vectorizer ကို ဆက်လက်အသုံးပြုမည်ဖြစ်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## LSTM: ရေရှည်-အတိုချုပ် မှတ်ဉာဏ်\n",
|
||||
"\n",
|
||||
"RNNs ရဲ့ အဓိကပြဿနာတစ်ခုက **gradient ပျောက်ဆုံးမှု** ဖြစ်ပါတယ်။ RNNs ဟာ အလွန်ရှည်လျားနိုင်ပြီး၊ backpropagation လုပ်စဉ်မှာ network ရဲ့ ပထမဆုံးအလွှာထိ gradient တွေကို ပြန်ပို့ဖို့ အခက်အခဲရှိနိုင်ပါတယ်။ ဒီလိုဖြစ်တဲ့အခါမှာ၊ network ဟာ အဝေးက token တွေကြားက ဆက်နွယ်မှုတွေကို သင်ယူလို့မရနိုင်ပါဘူး။ ဒီပြဿနာကို ရှောင်ရှားဖို့နည်းလမ်းတစ်ခုက **state ကို ထိန်းချုပ်မှု** ကို **gate** တွေ အသုံးပြုပြီး ထည့်သွင်းပေးတာပါ။ Gate တွေကို ထည့်သွင်းပေးတဲ့ architecture တွေထဲမှာ အများဆုံးတွေ့ရတာက **long short-term memory** (LSTM) နဲ့ **gated relay unit** (GRU) ဖြစ်ပါတယ်။ ဒီမှာတော့ LSTM တွေကို ဖော်ပြပါမယ်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"LSTM network ဟာ RNN နဲ့ ဆင်တူတဲ့ ပုံစံနဲ့ စီမံထားပြီး၊ အလွှာတစ်ခုကနေ နောက်တစ်ခုဆီကို state $c$ နဲ့ hidden vector $h$ ဆိုတဲ့ state နှစ်ခုကို ပို့ပေးပါတယ်။ Unit တစ်ခုစီမှာ hidden vector $h_{t-1}$ ကို input $x_t$ နဲ့ ပေါင်းစပ်ပြီး၊ **gate** တွေက state $c_t$ နဲ့ output $h_{t}$ ကို ထိန်းချုပ်ပေးပါတယ်။ Gate တစ်ခုစီမှာ sigmoid activation (output $[0,1]$ အတွင်း) ရှိပြီး၊ state vector ကို မျှတစွာ mask လုပ်ပေးတဲ့အခါမှာ အလုပ်လုပ်ပါတယ်။ LSTM တွေမှာ အောက်ပါ gate တွေရှိပါတယ် (အပုံမှာ ဘယ်မှညာအတိုင်း):\n",
|
||||
"* **forget gate** - vector $c_{t-1}$ ရဲ့ ဘယ် components တွေကို မေ့ပစ်ရမလဲ၊ ဘယ် components တွေကို ဆက်လက်အသုံးပြုရမလဲဆိုတာ ဆုံးဖြတ်ပေးပါတယ်။\n",
|
||||
"* **input gate** - input vector နဲ့ hidden vector ရဲ့ အရင်းအမြစ်တွေကို state vector ထဲမှာ ဘယ်လောက်ထိ ထည့်သွင်းရမလဲဆိုတာ ဆုံးဖြတ်ပေးပါတယ်။\n",
|
||||
"* **output gate** - အသစ်ရရှိတဲ့ state vector ကိုယူပြီး၊ hidden vector $h_t$ ထုတ်လုပ်ဖို့ ဘယ် components တွေကို အသုံးပြုရမလဲဆိုတာ ဆုံးဖြတ်ပေးပါတယ်။\n",
|
||||
"\n",
|
||||
"State $c$ ရဲ့ components တွေကို flag တွေလို switch on/off လုပ်နိုင်ပါတယ်။ ဥပမာ၊ sequence ထဲမှာ *Alice* ဆိုတဲ့နာမည်ကိုတွေ့တဲ့အခါ၊ အမျိုးသမီးနာမည်ဖြစ်တယ်လို့ ခန့်မှန်းပြီး၊ sentence ထဲမှာ အမျိုးသမီးနာမည်ရှိတယ်ဆိုတဲ့ flag ကို state ထဲမှာတင်ထားပါတယ်။ နောက်ပိုင်းမှာ *and Tom* ဆိုတဲ့စကားလုံးတွေကိုတွေ့တဲ့အခါ၊ plural noun ရှိတယ်ဆိုတဲ့ flag ကိုတင်ပေးပါတယ်။ ဒီလို state ကို ထိန်းချုပ်ခြင်းအားဖြင့် sentence ရဲ့ သဒ္ဒါဆိုင်ရာ အကျဉ်းချုပ်တွေကို ထိန်းသိမ်းနိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"> **Note**: LSTM ရဲ့ အတွင်းပိုင်းကို နားလည်ဖို့အတွက် အလွန်ကောင်းတဲ့ resource တစ်ခုက [Understanding LSTM Networks](https://colah.github.io/posts/2015-08-Understanding-LSTMs/) by Christopher Olah ဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"LSTM cell ရဲ့ အတွင်းပိုင်းဖွဲ့စည်းပုံဟာ ရှုပ်ထွေးနေပေမယ့်၊ Keras က `LSTM` layer ထဲမှာ ဒီ implementation ကို ဖုံးကွယ်ထားပါတယ်။ အထက်ပါဥပမာမှာ recurrent layer ကို အစားထိုးပေးရုံသာ လိုအပ်ပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"15000/15000 [==============================] - 188s 13ms/step - loss: 0.5692 - acc: 0.7916 - val_loss: 0.3441 - val_acc: 0.8870\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7f3d6af5c350>"
|
||||
]
|
||||
},
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model = keras.models.Sequential([\n",
|
||||
" vectorizer,\n",
|
||||
" keras.layers.Embedding(vocab_size, embed_size),\n",
|
||||
" keras.layers.LSTM(8),\n",
|
||||
" keras.layers.Dense(4,activation='softmax')\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(8),validation_data=ds_test.map(tupelize).batch(8))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## နှစ်ဖက်သို့လှည့်နိုင်သောနှင့် အလွှာများပါဝင်သော RNN များ\n",
|
||||
"\n",
|
||||
"ယခင်ဥပမာများတွင်၊ recurrent network များသည် အစမှ အဆုံးအထိ အစဉ်အတိုင်း လုပ်ဆောင်သည်။ ၎င်းသည် ကျွန်ုပ်တို့အတွက် သဘာဝကျသောအရာဖြစ်သည်၊ အကြောင်းမှာ ကျွန်ုပ်တို့ ဖတ်ခြင်း သို့မဟုတ် စကားနားထောင်ခြင်း၏ လမ်းကြောင်းနှင့် တူသော လမ်းကြောင်းကို လိုက်နာသောကြောင့်ဖြစ်သည်။ သို့သော်၊ input sequence ကို random access လုပ်ရန်လိုအပ်သော အခြေအနေများအတွက်၊ recurrent computation ကို နှစ်ဖက်လုံးတွင် လုပ်ဆောင်ခြင်းသည် ပိုမိုသင့်တော်သည်။ နှစ်ဖက်လုံးတွင် လုပ်ဆောင်နိုင်သော RNN များကို **bidirectional** RNN များဟုခေါ်ပြီး၊ ၎င်းတို့ကို `Bidirectional` layer အထူးလွှာဖြင့် recurrent layer ကို wrap လုပ်ခြင်းအားဖြင့် ဖန်တီးနိုင်သည်။\n",
|
||||
"\n",
|
||||
"> **Note**: `Bidirectional` layer သည် ၎င်းအတွင်းရှိ layer ကို မိတ္တူနှစ်ခု ဖန်တီးပြီး၊ မိတ္တူတစ်ခု၏ `go_backwards` property ကို `True` သတ်မှတ်ကာ sequence အတိုင်း လမ်းကြောင်းဆန့်ကျင်ဘက်သို့ သွားစေသည်။\n",
|
||||
"\n",
|
||||
"Recurrent network များ၊ unidirectional ဖြစ်စေ bidirectional ဖြစ်စေ၊ sequence အတွင်းရှိ pattern များကို ဖမ်းဆီးပြီး state vector များအဖြစ် သိမ်းဆည်းသို့မဟုတ် output အဖြစ် ပြန်လည်ပေးသည်။ Convolutional network များနှင့်တူပင်၊ ပထမ layer မှ အနိမ့်ဆုံး level pattern များကို ဖမ်းဆီးပြီး၊ အမြင့်ဆုံး level pattern များကို ဖမ်းဆီးရန် ပိုမိုမြင့်မားသော recurrent layer တစ်ခုကို တည်ဆောက်နိုင်သည်။ ၎င်းသည် **multi-layer RNN** ၏ အယူအဆသို့ ဦးတည်ပြီး၊ ၎င်းသည် recurrent network နှစ်ခု သို့မဟုတ် အများကြီးပါဝင်ပြီး၊ ယခင် layer ၏ output ကို နောက် layer ၏ input အဖြစ် ပေးပို့သည်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"*Fernando López ရေးသားထားသော [ဤအလွန်အမိုက်ဆုံး post](https://towardsdatascience.com/from-a-lstm-cell-to-a-multilayer-lstm-network-with-pytorch-2899eb5696f3) မှ ရိုက်ယူထားသော ပုံ။*\n",
|
||||
"\n",
|
||||
"Keras သည် network များကို တည်ဆောက်ရန် လွယ်ကူစေသည်၊ အကြောင်းမှာ model တွင် recurrent layer များကို ပေါင်းထည့်ရုံသာ လိုအပ်သည်။ နောက်ဆုံး layer ကို မပါဘဲ အခြား layer များအတွက် `return_sequences=True` parameter ကို သတ်မှတ်ရန်လိုအပ်သည်၊ အကြောင်းမှာ recurrent computation ၏ နောက်ဆုံး state ကိုသာမက၊ အလယ်အလတ် state များအားလုံးကို layer မှ ပြန်လည်ပေးရန်လိုအပ်သည်။\n",
|
||||
"\n",
|
||||
"အမျိုးအစားခွဲခြင်းပြဿနာအတွက် နှစ်လွှာ bidirectional LSTM တစ်ခုကို တည်ဆောက်ကြစို့။\n",
|
||||
"\n",
|
||||
"> **Note** ဤ code သည် ပြန်လည်လုပ်ဆောင်ရန် အချိန်ကြာမြင့်သော်လည်း၊ ယခင် accuracy များထက် အမြင့်ဆုံး accuracy ကို ရရှိစေသည်။ ထို့ကြောင့် အချိန်စောင့်ပြီး ရလဒ်ကို ကြည့်ရှုရန် တန်ဖိုးရှိနိုင်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"5044/7500 [===================>..........] - ETA: 2:33 - loss: 0.3709 - acc: 0.8706\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r5045/7500 [===================>..........] - ETA: 2:33 - loss: 0.3709 - acc: 0.8706"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model = keras.models.Sequential([\n",
|
||||
" vectorizer,\n",
|
||||
" keras.layers.Embedding(vocab_size, 128, mask_zero=True),\n",
|
||||
" keras.layers.Bidirectional(keras.layers.LSTM(64,return_sequences=True)),\n",
|
||||
" keras.layers.Bidirectional(keras.layers.LSTM(64)), \n",
|
||||
" keras.layers.Dense(4,activation='softmax')\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(batch_size),\n",
|
||||
" validation_data=ds_test.map(tupelize).batch(batch_size))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## RNN များကို အခြားအလုပ်များအတွက် အသုံးပြုခြင်း\n",
|
||||
"\n",
|
||||
"ယခုအချိန်အထိ RNN များကို စာသားအတိုင်းအတာများကို အမျိုးအစားခွဲရန်အတွက် အသုံးပြုခြင်းကို အဓိကထားခဲ့ပါသည်။ သို့သော် RNN များသည် စာသားဖန်တီးခြင်းနှင့် ဘာသာပြန်ခြင်းကဲ့သို့သော အလုပ်များကိုလည်း လုပ်ဆောင်နိုင်ပါသည် — အဲဒီအလုပ်များကို နောက်ယူနစ်တွင် ဆွေးနွေးမည်ဖြစ်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်မှုများတွင် အမှားများ သို့မဟုတ် မတိကျမှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာရှိသော ရင်းမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူ့ဘာသာပြန်ပညာရှင်များကို အသုံးပြု၍ ဘာသာပြန်ခြင်းကို အကြံပြုပါသည်။ ဤဘာသာပြန်မှုကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားလွဲမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernel_info": {
|
||||
"name": "conda-env-py37_tensorflow-py"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "py37_tensorflow",
|
||||
"language": "python",
|
||||
"name": "conda-env-py37_tensorflow-py"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.7.9"
|
||||
},
|
||||
"nteract": {
|
||||
"version": "nteract-front-end@1.0.0"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "81351e61f619b432ff51010a4f993194",
|
||||
"translation_date": "2025-08-30T10:29:34+00:00",
|
||||
"source_file": "lessons/5-NLP/16-RNN/RNNTF.ipynb",
|
||||
"language_code": "my"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -0,0 +1,414 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Generative networks\n",
|
||||
"\n",
|
||||
"Recurrent Neural Networks (RNNs) နှင့် Long Short Term Memory Cells (LSTMs) နှင့် Gated Recurrent Units (GRUs) ကဲ့သို့သော gated cell များသည် ဘာသာစကားမော်ဒယ်တစ်ခုအတွက် စနစ်တစ်ခုကို ပံ့ပိုးပေးနိုင်သည်။ အဆိုပါစနစ်သည် စကားလုံးများ၏ အစီအစဉ်ကို သင်ယူနိုင်ပြီး အစီအစဉ်အတွင်း နောက်တစ်ခုထွက်မည့် စကားလုံးကို ခန့်မှန်းပေးနိုင်သည်။ ဒီလိုဖြစ်တာကြောင့် RNNs ကို **ဖန်တီးမှုဆိုင်ရာလုပ်ငန်းများ** (ဥပမာ - ပုံမှန်စာသားဖန်တီးခြင်း၊ စက်ဖြင့်ဘာသာပြန်ခြင်း၊ ပုံဖော်ရေးသားခြင်း) အတွက် အသုံးပြုနိုင်သည်။\n",
|
||||
"\n",
|
||||
"ယခင်ယူနစ်တွင် ဆွေးနွေးခဲ့သည့် RNN architecture တွင် RNN unit တစ်ခုစီသည် နောက်ထွက်မည့် hidden state ကို output အဖြစ် ထုတ်ပေးသည်။ သို့သော် RNN unit တစ်ခုစီတွင် output တစ်ခုထပ်ထည့်နိုင်ပြီး၊ အဲဒီ output က **sequence** (မူရင်း sequence နှင့် အရှည်တူ) ကို ထုတ်ပေးနိုင်သည်။ ထို့အပြင်၊ RNN units များကို အဆင့်တစ်ခုစီတွင် input မလိုအပ်ဘဲ အသုံးပြုနိုင်ပြီး၊ စတင်အခြေအနေ vector တစ်ခုသာ လက်ခံပြီး output sequence တစ်ခုကို ထုတ်ပေးနိုင်သည်။\n",
|
||||
"\n",
|
||||
"ဒီ notebook တွင် စာသားဖန်တီးရန် ကူညီပေးသည့် ရိုးရှင်းသော generative models များကို အဓိကထား၍ လေ့လာသွားမည်ဖြစ်သည်။ ရိုးရှင်းစွာပြောရမည်ဆိုပါက **character-level network** တစ်ခုကို တည်ဆောက်မည်ဖြစ်ပြီး၊ ၎င်းသည် စာလုံးတစ်လုံးချင်းစီဖြင့် စာသားကို ဖန်တီးပေးမည်ဖြစ်သည်။ သင်ကြားမှုအတွင်းတွင် စာသား corpus တစ်ခုကို ယူပြီး၊ ၎င်းကို စာလုံးအစီအစဉ်များအဖြစ် ခွဲထုတ်ရန် လိုအပ်မည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Loading dataset...\n",
|
||||
"Building vocab...\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import torch\n",
|
||||
"import torchtext\n",
|
||||
"import numpy as np\n",
|
||||
"from torchnlp import *\n",
|
||||
"train_dataset,test_dataset,classes,vocab = load_dataset()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## အက္ခရာအဆင့် စာပေဗဟုသုတ တည်ဆောက်ခြင်း\n",
|
||||
"\n",
|
||||
"အက္ခရာအဆင့် ဖန်တီးမှုကွန်ရက်တစ်ခု တည်ဆောက်ရန်အတွက် စာသားကို စကားလုံးများမဟုတ်ဘဲ တစ်ခုချင်းစီ အက္ခရာများအဖြစ် ခွဲခြားရမည်။ ဒါကို အခြားသော tokenizer တစ်ခု သတ်မှတ်ခြင်းဖြင့် ပြုလုပ်နိုင်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Vocabulary size = 82\n",
|
||||
"Encoding of 'a' is 1\n",
|
||||
"Character with code 13 is c\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def char_tokenizer(words):\n",
|
||||
" return list(words) #[word for word in words]\n",
|
||||
"\n",
|
||||
"counter = collections.Counter()\n",
|
||||
"for (label, line) in train_dataset:\n",
|
||||
" counter.update(char_tokenizer(line))\n",
|
||||
"vocab = torchtext.vocab.vocab(counter)\n",
|
||||
"\n",
|
||||
"vocab_size = len(vocab)\n",
|
||||
"print(f\"Vocabulary size = {vocab_size}\")\n",
|
||||
"print(f\"Encoding of 'a' is {vocab.get_stoi()['a']}\")\n",
|
||||
"print(f\"Character with code 13 is {vocab.get_itos()[13]}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်တော်တို့ရဲ့ဒေတာစနစ်ကနေစာသားကိုဘယ်လိုကုဒ်ဖြစ်အောင်လုပ်နိုင်တယ်ဆိုတာကိုဥပမာနမူနာကြည့်ကြမယ်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"tensor([ 0, 1, 2, 2, 3, 4, 5, 6, 3, 7, 8, 1, 9, 10, 3, 11, 2, 1,\n",
|
||||
" 12, 3, 7, 1, 13, 14, 3, 15, 16, 5, 17, 3, 5, 18, 8, 3, 7, 2,\n",
|
||||
" 1, 13, 14, 3, 19, 20, 8, 21, 5, 8, 9, 10, 22, 3, 20, 8, 21, 5,\n",
|
||||
" 8, 9, 10, 3, 23, 3, 4, 18, 17, 9, 5, 23, 10, 8, 2, 2, 8, 9,\n",
|
||||
" 10, 24, 3, 0, 1, 2, 2, 3, 4, 5, 9, 8, 8, 5, 25, 10, 3, 26,\n",
|
||||
" 12, 27, 16, 26, 2, 27, 16, 28, 29, 30, 1, 16, 26, 3, 17, 31, 3, 21,\n",
|
||||
" 2, 5, 9, 1, 23, 13, 32, 16, 27, 13, 10, 24, 3, 1, 9, 8, 3, 10,\n",
|
||||
" 8, 8, 27, 16, 28, 3, 28, 9, 8, 8, 16, 3, 1, 28, 1, 27, 16, 6])"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def enc(x):\n",
|
||||
" return torch.LongTensor(encode(x,voc=vocab,tokenizer=char_tokenizer))\n",
|
||||
"\n",
|
||||
"enc(train_dataset[0][1])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Generative RNN ကိုလေ့ကျင့်ခြင်း\n",
|
||||
"\n",
|
||||
"RNN ကို စာသားထုတ်လုပ်ရန် လေ့ကျင့်ပုံမှာ အောက်ပါအတိုင်းဖြစ်ပါမည်။ အဆင့်တစ်ခုစီတွင် `nchars` အရှည်ရှိသော စာလုံးများ၏ အစဉ်အတိုင်းယူပြီး၊ နောက်ထွက်စာလုံးကို အဝင်စာလုံးတစ်ခုစီအတွက် ကွန်ယက်အားဖြင့် ထုတ်လုပ်ရန် တောင်းဆိုပါမည်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"အခြေအနေအလိုက်၊ *အဆုံးအမှတ်အသား* `<eos>` ကဲ့သို့သော အထူးအက္ခရာများကိုလည်း ထည့်သွင်းလိုတတ်ပါသည်။ သို့သော် ကျွန်ုပ်တို့အနေဖြင့် အဆုံးမရှိသော စာသားထုတ်လုပ်မှုအတွက် ကွန်ယက်ကိုသာ လေ့ကျင့်လိုသောကြောင့်၊ အစဉ်တစ်ခုစီ၏ အရွယ်အစားကို `nchars` အက္ခရာများအဖြစ် သတ်မှတ်ထားမည်ဖြစ်သည်။ ထို့ကြောင့်၊ လေ့ကျင့်မှုဥပမာတစ်ခုစီတွင် `nchars` အဝင်များနှင့် `nchars` အထွက်များ (အဝင်အစဉ်ကို ဘယ်ဘက်သို့ အက္ခရာတစ်လုံးရွှေ့ထားသောအတိုင်း) ပါဝင်မည်ဖြစ်သည်။ Minibatch တစ်ခုတွင် ဤအစဉ်များစွာ ပါဝင်မည်ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"Minibatch များကို ထုတ်လုပ်ပုံမှာ `l` အရှည်ရှိသော သတင်းစာသားတစ်ခုစီကို ယူပြီး၊ ထိုစာသားမှ အဝင်-အထွက် အစဉ်အတိုင်းဖြစ်နိုင်သမျှအားလုံးကို ထုတ်ယူမည်ဖြစ်သည် (ထိုအစဉ်များမှာ `l-nchars` ဖြစ်မည်)။ ၎င်းတို့သည် minibatch တစ်ခုကို ဖွဲ့စည်းမည်ဖြစ်ပြီး၊ လေ့ကျင့်မှုအဆင့်တစ်ခုစီတွင် minibatch များ၏ အရွယ်အစားမှာ မတူကွဲပြားနေမည်ဖြစ်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(tensor([[ 0, 1, 2, ..., 28, 29, 30],\n",
|
||||
" [ 1, 2, 2, ..., 29, 30, 1],\n",
|
||||
" [ 2, 2, 3, ..., 30, 1, 16],\n",
|
||||
" ...,\n",
|
||||
" [20, 8, 21, ..., 1, 28, 1],\n",
|
||||
" [ 8, 21, 5, ..., 28, 1, 27],\n",
|
||||
" [21, 5, 8, ..., 1, 27, 16]]),\n",
|
||||
" tensor([[ 1, 2, 2, ..., 29, 30, 1],\n",
|
||||
" [ 2, 2, 3, ..., 30, 1, 16],\n",
|
||||
" [ 2, 3, 4, ..., 1, 16, 26],\n",
|
||||
" ...,\n",
|
||||
" [ 8, 21, 5, ..., 28, 1, 27],\n",
|
||||
" [21, 5, 8, ..., 1, 27, 16],\n",
|
||||
" [ 5, 8, 9, ..., 27, 16, 6]]))"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"nchars = 100\n",
|
||||
"\n",
|
||||
"def get_batch(s,nchars=nchars):\n",
|
||||
" ins = torch.zeros(len(s)-nchars,nchars,dtype=torch.long,device=device)\n",
|
||||
" outs = torch.zeros(len(s)-nchars,nchars,dtype=torch.long,device=device)\n",
|
||||
" for i in range(len(s)-nchars):\n",
|
||||
" ins[i] = enc(s[i:i+nchars])\n",
|
||||
" outs[i] = enc(s[i+1:i+nchars+1])\n",
|
||||
" return ins,outs\n",
|
||||
"\n",
|
||||
"get_batch(train_dataset[0][1])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ယခု Generator Network ကို သတ်မှတ်ကြမယ်။ ဒါကို ယခင်ယူနစ်မှာ ဆွေးနွေးခဲ့တဲ့ Recurrent Cell (simple, LSTM, GRU) မည်သည့်အရာကိုမဆို အခြေခံပြီး ဖန်တီးနိုင်ပါတယ်။ ဥပမာအနေနဲ့ ကျွန်တော်တို့ LSTM ကို အသုံးပြုပါမယ်။\n",
|
||||
"\n",
|
||||
"Network က စာလုံးတွေကို input အနေနဲ့ လက်ခံရမှာဖြစ်ပြီး၊ Vocabulary size ကလည်း သေးငယ်တဲ့အတွက် Embedding Layer မလိုအပ်ပါဘူး၊ One-hot-encoded input ကို တိုက်ရိုက် LSTM cell ထဲသို့ ပို့နိုင်ပါတယ်။ သို့သော် စာလုံးနံပါတ်တွေကို input အနေနဲ့ ပေးရတဲ့အတွက် LSTM ထဲသို့ ပို့မီ One-hot-encode လုပ်ရပါမယ်။ ဒါကို `forward` pass အတွင်း `one_hot` function ကို ခေါ်သုံးပြီး လုပ်ဆောင်ပါတယ်။ Output Encoder က Hidden State ကို One-hot-encoded output အဖြစ် ပြောင်းလဲပေးမယ့် Linear Layer ဖြစ်ပါမယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class LSTMGenerator(torch.nn.Module):\n",
|
||||
" def __init__(self, vocab_size, hidden_dim):\n",
|
||||
" super().__init__()\n",
|
||||
" self.rnn = torch.nn.LSTM(vocab_size,hidden_dim,batch_first=True)\n",
|
||||
" self.fc = torch.nn.Linear(hidden_dim, vocab_size)\n",
|
||||
"\n",
|
||||
" def forward(self, x, s=None):\n",
|
||||
" x = torch.nn.functional.one_hot(x,vocab_size).to(torch.float32)\n",
|
||||
" x,s = self.rnn(x,s)\n",
|
||||
" return self.fc(x),s"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"လေ့ကျင့်မှုအတွင်းမှာ ကျွန်တော်တို့ ဖန်တီးထားတဲ့ စာသားကို နမူနာယူနိုင်ဖို့ လိုအပ်ပါတယ်။ အဲဒီအတွက် `generate` ဆိုတဲ့ function ကို သတ်မှတ်ပြီး `size` အရှည်ရှိတဲ့ output string ကို စတင် string `start` ကနေ စတင်ဖန်တီးမှာ ဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"အလုပ်လုပ်ပုံက အောက်ပါအတိုင်း ဖြစ်ပါတယ်။ ပထမဦးဆုံးမှာ start string အားလုံးကို network မှတဆင့် ဖြတ်သွားပြီး output state `s` နဲ့ နောက်ထပ်ခန့်မှန်းထားတဲ့ အက္ခရာ `out` ကို ရယူပါမယ်။ `out` က one-hot encoded ဖြစ်တဲ့အတွက် `argmax` ကို သုံးပြီး vocabulary ထဲမှာ အက္ခရာ `nc` ရဲ့ index ကို ရယူပါမယ်။ ထို့နောက် `itos` ကို သုံးပြီး အမှန်တကယ် အက္ခရာကို ရှာဖွေပြီး အဲဒီအက္ခရာကို `chars` ဆိုတဲ့ အက္ခရာများရဲ့ list ထဲမှာ ထည့်သွင်းပါမယ်။ အက္ခရာတစ်ခုကို ဖန်တီးတဲ့ ဒီလုပ်ငန်းစဉ်ကို `size` ကြိမ် ထပ်မံလုပ်ဆောင်ပြီး လိုအပ်တဲ့ အက္ခရာအရေအတွက်ကို ဖန်တီးပါမယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def generate(net,size=100,start='today '):\n",
|
||||
" chars = list(start)\n",
|
||||
" out, s = net(enc(chars).view(1,-1).to(device))\n",
|
||||
" for i in range(size):\n",
|
||||
" nc = torch.argmax(out[0][-1])\n",
|
||||
" chars.append(vocab.get_itos()[nc])\n",
|
||||
" out, s = net(nc.view(1,-1),s)\n",
|
||||
" return ''.join(chars)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အခုတော့ လေ့ကျင့်မှုကို စတင်ကြမယ်! လေ့ကျင့်မှု loop က အရင်က ဥပမာတွေမှာလိုပဲ ဖြစ်ပေမယ့် accuracy အစား 1000 epochs တစ်ခါစီမှာ ထုတ်လုပ်ထားတဲ့ စမ်းသပ်စာသားကို ပုံနှိပ်ပြသမှာ ဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"Loss ကိုတွက်ချက်တဲ့နည်းလမ်းကို အထူးဂရုစိုက်ဖို့ လိုအပ်ပါတယ်။ Loss ကို တစ်ခုချင်းစီ encode လုပ်ထားတဲ့ output `out` နဲ့ မျှော်မှန်းထားတဲ့စာသား `text_out` (character indices စာရင်း) ကို အသုံးပြုပြီးတွက်ချက်ရမယ်။ ကံကောင်းစွာဖြင့် `cross_entropy` function က unnormalized network output ကို ပထမ argument အနေနဲ့၊ class number ကို ဒုတိယ argument အနေနဲ့ လိုအပ်တယ်၊ ဒါက ကျွန်တော်တို့မှာရှိပြီးသားပဲ ဖြစ်ပါတယ်။ ဒါ့အပြင် minibatch size အပေါ်မှာ အလိုအလျောက် အလယ်ပျံ့တွက်ချက်မှုကိုလည်း လုပ်ဆောင်ပေးပါတယ်။\n",
|
||||
"\n",
|
||||
"လေ့ကျင့်မှုကို `samples_to_train` sample အရေအတွက်နဲ့ ကန့်သတ်ထားပြီး အချိန်မကြာအောင် လုပ်ဆောင်ထားပါတယ်။ သင်တို့ကို အတတ်နိုင်ဆုံး လေ့လာမှုကို စမ်းသပ်ဖို့ တိုက်တွန်းပါတယ်၊ အချို့သော epoch အတွက် အချိန်ပိုကြာတဲ့ လေ့ကျင့်မှုကို စမ်းသပ်ကြည့်ပါ (ဒီအခါမှာ ဒီ code အပေါ်မှာ loop တစ်ခုထပ်ထည့်ဖွဲ့စည်းဖို့ လိုအပ်ပါလိမ့်မယ်)။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Current loss = 4.398899078369141\n",
|
||||
"today sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr sr s\n",
|
||||
"Current loss = 2.161320447921753\n",
|
||||
"today and to the tor to to the tor to to the tor to to the tor to to the tor to to the tor to to the tor t\n",
|
||||
"Current loss = 1.6722588539123535\n",
|
||||
"today and the court to the could to the could to the could to the could to the could to the could to the c\n",
|
||||
"Current loss = 2.423795223236084\n",
|
||||
"today and a second to the conternation of the conternation of the conternation of the conternation of the \n",
|
||||
"Current loss = 1.702607274055481\n",
|
||||
"today and the company to the company to the company to the company to the company to the company to the co\n",
|
||||
"Current loss = 1.692358136177063\n",
|
||||
"today and the company to the company to the company to the company to the company to the company to the co\n",
|
||||
"Current loss = 1.9722288846969604\n",
|
||||
"today and the control the control the control the control the control the control the control the control \n",
|
||||
"Current loss = 1.8705692291259766\n",
|
||||
"today and the second to the second to the second to the second to the second to the second to the second t\n",
|
||||
"Current loss = 1.7626899480819702\n",
|
||||
"today and a security and a security and a security and a security and a security and a security and a secu\n",
|
||||
"Current loss = 1.5574463605880737\n",
|
||||
"today and the company and the company and the company and the company and the company and the company and \n",
|
||||
"Current loss = 1.5620026588439941\n",
|
||||
"today and the be that the be the be that the be the be that the be the be that the be the be that the be t\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"net = LSTMGenerator(vocab_size,64).to(device)\n",
|
||||
"\n",
|
||||
"samples_to_train = 10000\n",
|
||||
"optimizer = torch.optim.Adam(net.parameters(),0.01)\n",
|
||||
"loss_fn = torch.nn.CrossEntropyLoss()\n",
|
||||
"net.train()\n",
|
||||
"for i,x in enumerate(train_dataset):\n",
|
||||
" # x[0] is class label, x[1] is text\n",
|
||||
" if len(x[1])-nchars<10:\n",
|
||||
" continue\n",
|
||||
" samples_to_train-=1\n",
|
||||
" if not samples_to_train: break\n",
|
||||
" text_in, text_out = get_batch(x[1])\n",
|
||||
" optimizer.zero_grad()\n",
|
||||
" out,s = net(text_in)\n",
|
||||
" loss = torch.nn.functional.cross_entropy(out.view(-1,vocab_size),text_out.flatten()) #cross_entropy(out,labels)\n",
|
||||
" loss.backward()\n",
|
||||
" optimizer.step()\n",
|
||||
" if i%1000==0:\n",
|
||||
" print(f\"Current loss = {loss.item()}\")\n",
|
||||
" print(generate(net))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ဤဥပမာသည် အတော်လေးကောင်းမွန်သောစာသားကို ရရှိစေပြီးဖြစ်သော်လည်း အချို့အပိုင်းများကို ပိုမိုတိုးတက်စေရန် အခြားနည်းလမ်းများလည်း ရှိပါသည် -\n",
|
||||
"\n",
|
||||
"* **ပိုမိုကောင်းမွန်သော minibatch ဖန်တီးမှု**။ ကျွန်ုပ်တို့သည် သင်ကြားမှုအတွက် ဒေတာကို ပြင်ဆင်သည့်နည်းလမ်းမှာ တစ်ခုတည်းသောနမူနာမှ minibatch တစ်ခုကို ဖန်တီးခြင်းဖြစ်သည်။ ဒါဟာ အကောင်းဆုံးနည်းလမ်းမဟုတ်ပါ၊ အကြောင်းမှာ minibatch များသည် အရွယ်အစားကွဲပြားမှုရှိပြီး၊ တချို့ minibatch များကိုတော့ ဖန်တီးလို့မရနိုင်ပါ၊ အကြောင်းမှာ စာသားသည် `nchars` ထက် သေးငယ်နေခြင်းကြောင့်ဖြစ်သည်။ ထို့အပြင် သေးငယ်သော minibatch များသည် GPU ကို လုံလောက်စွာ အသုံးမပြုနိုင်ပါ။ အကောင်းဆုံးနည်းလမ်းမှာ နမူနာအားလုံးမှ စာသားတစ်ခုလုံးကို စုစည်းပြီး၊ input-output အစုံအားလုံးကို ဖန်တီးပြီး၊ shuffle ပြုလုပ်ပြီး၊ အရွယ်အစားတူညီသော minibatch များကို ဖန်တီးရန်ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"* **Multilayer LSTM**။ LSTM cell များကို အလွှာ ၂ သို့မဟုတ် ၃ အထိ စမ်းသပ်ကြည့်ရန် make sense ဖြစ်ပါသည်။ ယခင်ယူနစ်တွင် ပြောခဲ့သည့်အတိုင်း၊ LSTM ၏ အလွှာတစ်ခုစီသည် စာသားမှ အချို့သော pattern များကို ထုတ်ယူပေးပါသည်။ Character-level generator ၏ အနေဖြင့် LSTM ၏ အနိမ့်ဆုံးအလွှာသည် syllable များကို ထုတ်ယူရန် တာဝန်ရှိမည်ဟု မျှော်လင့်ရပြီး၊ အထက်ဆုံးအလွှာများသည် စကားလုံးများနှင့် စကားလုံးပေါင်းများကို ထုတ်ယူရန် တာဝန်ရှိမည်ဖြစ်သည်။ ၎င်းကို LSTM constructor သို့ အလွှာအရေအတွက် parameter ကို ပေးပို့ခြင်းဖြင့် ရိုးရှင်းစွာ အကောင်အထည်ဖော်နိုင်ပါသည်။\n",
|
||||
"\n",
|
||||
"* သင်သည် **GRU unit များ** ကိုလည်း စမ်းသပ်ကြည့်လိုနိုင်ပြီး၊ **hidden layer အရွယ်အစားကွဲပြားမှုများ** ကိုလည်း စမ်းသပ်ကြည့်နိုင်ပါသည်။ Hidden layer အရွယ်အစားသည် အလွန်ကြီးလွန်းပါက overfitting ဖြစ်စေနိုင်ပြီး (ဥပမာ - network သည် စာသားကို တိတိကျကျ သင်ယူသွားမည်ဖြစ်သည်)၊ သေးငယ်လွန်းပါက ကောင်းမွန်သောရလဒ် မရနိုင်ပါ။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Soft text generation and temperature\n",
|
||||
"\n",
|
||||
"ယခင် `generate` ကိုဖော်ပြထားသော အဓိပ္ပါယ်အရ၊ ဖန်တီးထားသော စာသားတွင် နောက်တစ်ခုထည့်ရန်အတွက် အမြင့်ဆုံး probability ရှိသော အက္ခရာကို အမြဲယူခဲ့သည်။ ဒါကြောင့် စာသားသည် အက္ခရာအဆင့်များကို ထပ်ခါတလဲလဲ ပြန်လည်အသုံးပြုနေသော အခြေအနေဖြစ်လာခဲ့သည်။ ဥပမာအားဖြင့်:\n",
|
||||
"```\n",
|
||||
"today of the second the company and a second the company ...\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"သို့သော် နောက်ထပ် အက္ခရာအတွက် probability distribution ကိုကြည့်မယ်ဆိုရင်၊ အမြင့်ဆုံး probability ရှိသော အက္ခရာများအကြား ကွာခြားမှုသည် များစွာမရှိနိုင်ပါ။ ဥပမာအားဖြင့် အက္ခရာတစ်ခုမှာ probability 0.2 ရှိနိုင်ပြီး၊ နောက်တစ်ခုမှာ 0.19 ရှိနိုင်သည်။ ဥပမာအားဖြင့် '*play*' ဆိုသော စာကြောင်းတွင် နောက်ထပ် အက္ခရာသည် space ဖြစ်နိုင်သလို၊ **e** (ဥပမာအားဖြင့် *player* စကားလုံးတွင်) ဖြစ်နိုင်ပါသည်။\n",
|
||||
"\n",
|
||||
"ဒါကြောင့် အမြင့်ဆုံး probability ရှိသော အက္ခရာကို ရွေးချယ်ခြင်းသည် အမြဲတမ်း \"တရားမျှတ\" မဖြစ်နိုင်ကြောင်း သင်ခန့်မှန်းနိုင်ပါသည်။ ဒါကြောင့် ဒုတိယမြင့်ဆုံး probability ရှိသော အက္ခရာကို ရွေးချယ်ခြင်းသည်လည်း အဓိပ္ပါယ်ရှိသော စာသားကို ဖန်တီးနိုင်စေပါသည်။ ထို့ကြောင့် network output မှပေးသော probability distribution အရ **sample** လုပ်ခြင်းသည် ပိုမိုဉာဏ်ရှိသော နည်းလမ်းဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"ဒီ sampling ကို **multinomial distribution** ဟုခေါ်သော နည်းလမ်းကို အသုံးပြုသော `multinomial` function ကို အသုံးပြု၍ ပြုလုပ်နိုင်ပါသည်။ **soft** text generation ကို အကောင်အထည်ဖော်သော function ကို အောက်တွင် ဖော်ပြထားပါသည်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"--- Temperature = 0.3\n",
|
||||
"Today and a company and complete an all the land the restrational the as a security and has provers the pay to and a report and the computer in the stand has filities and working the law the stations for a company and with the company and the final the first company and refight of the state and and workin\n",
|
||||
"\n",
|
||||
"--- Temperature = 0.8\n",
|
||||
"Today he oniis its first to Aus bomblaties the marmation a to manan boogot that pirate assaid a relaid their that goverfin the the Cappets Ecrotional Assonia Cition targets it annight the w scyments Blamity #39;s TVeer Diercheg Reserals fran envyuil that of ster said access what succers of Dour-provelith\n",
|
||||
"\n",
|
||||
"--- Temperature = 1.0\n",
|
||||
"Today holy they a 11 will meda a toket subsuaties, engins for Chanos, they's has stainger past to opening orital his thempting new Nattona was al innerforder advan-than #36;s night year his religuled talitatian what the but with Wednesday to Justment will wemen of Mark CCC Camp as Timed Nae wome a leaders\n",
|
||||
"\n",
|
||||
"--- Temperature = 1.3\n",
|
||||
"Today gpone 2.5 fech atcusion poor cocles toparsdorM.cht Line Pamage put 43 his calt lowed to the book, that has authh-the silia rruch ailing to'ory andhes beutirsimi- Aefffive heading offil an auf eacklets is charged evis, Gunymy oy) Mony has it after-sloythyor loveId out filme, the Natabl -Najuntaxiggs \n",
|
||||
"\n",
|
||||
"--- Temperature = 1.8\n",
|
||||
"Today plary, P.slan chly\\401 mardregationly #39;t 8.1Mide) closes ,filtcon alfly playin roven!\\grea.-QFBEP: Iss onfarchQ/itilia CCf Zivesigntwasta orce.-Peul-aw.uicrin of fuglinfsut aftaningwo, MIEX awayew Aice Woiduar Corvagiugge oppo esig ThusBratourid canthly-RyI.co lagitems\\eexciaishes.conBabntusmor I\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def generate_soft(net,size=100,start='today ',temperature=1.0):\n",
|
||||
" chars = list(start)\n",
|
||||
" out, s = net(enc(chars).view(1,-1).to(device))\n",
|
||||
" for i in range(size):\n",
|
||||
" #nc = torch.argmax(out[0][-1])\n",
|
||||
" out_dist = out[0][-1].div(temperature).exp()\n",
|
||||
" nc = torch.multinomial(out_dist,1)[0]\n",
|
||||
" chars.append(vocab.get_itos()[nc])\n",
|
||||
" out, s = net(nc.view(1,-1),s)\n",
|
||||
" return ''.join(chars)\n",
|
||||
" \n",
|
||||
"for i in [0.3,0.8,1.0,1.3,1.8]:\n",
|
||||
" print(f\"--- Temperature = {i}\\n{generate_soft(net,size=300,start='Today ',temperature=i)}\\n\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့သည် **အပူချိန်** ဟုခေါ်သော နောက်ထပ် parameter တစ်ခုကို မိတ်ဆက်ပေးခဲ့ပြီး၊ ၎င်းသည် အမြင့်ဆုံး probability ကို များစွာလိုက်နာသင့်ကြောင်းကို ဖော်ပြရန် အသုံးပြုသည်။ အပူချိန်သည် 1.0 ဖြစ်ပါက၊ fair multinomial sampling ကို ပြုလုပ်ပြီး၊ အပူချိန်သည် အဆုံးမရှိအထိ မြင့်တက်သွားသောအခါ - probability အားလုံးသည် တူညီသွားပြီး၊ နောက် character ကို အလွတ်ရွေးချယ်သည်။ အောက်ပါ ဥပမာတွင် အပူချိန်ကို များစွာမြှင့်တင်သည့်အခါ၊ စာသားသည် အဓိပ္ပါယ်မရှိသွားကြောင်းကို တွေ့နိုင်ပြီး၊ အပူချိန်သည် 0 အနီးသို့ ရောက်လာသောအခါ \"cycled\" အခက်အခဲဖြင့် ဖန်တီးထားသော စာသားနှင့် ဆင်တူသွားသည်ကို တွေ့နိုင်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေပါသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်မှုများတွင် အမှားများ သို့မဟုတ် မမှန်ကန်မှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းစာရွက်စာတမ်းကို ၎င်း၏ မူလဘာသာစကားဖြင့် အာဏာတရ အရင်းအမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူက ဘာသာပြန်မှုကို အသုံးပြုရန် အကြံပြုပါသည်။ ဤဘာသာပြန်မှုကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားလွဲမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.8.12 ('py38')",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "7673cd150d96c74c6d6011460094efb4",
|
||||
"translation_date": "2025-08-30T10:14:13+00:00",
|
||||
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativePyTorch.ipynb",
|
||||
"language_code": "my"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -0,0 +1,496 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Generative networks\n",
|
||||
"\n",
|
||||
"Recurrent Neural Networks (RNNs) နှင့် Long Short Term Memory Cells (LSTMs) နှင့် Gated Recurrent Units (GRUs) ကဲ့သို့သော gated cell မျိုးကွဲများသည် ဘာသာစကားမော်ဒယ်တစ်ခုအတွက် စနစ်တစ်ခုကို ပံ့ပိုးပေးခဲ့သည်။ အဆိုပါစနစ်သည် စကားလုံးများ၏ အစီအစဉ်ကို သင်ယူနိုင်ပြီး အစီအစဉ်အတွင်း နောက်တစ်ခုထွက်မည့် စကားလုံးကို ခန့်မှန်းပေးနိုင်သည်။ ၎င်းသည် RNNs ကို **ထုတ်လုပ်မှုဆိုင်ရာ လုပ်ငန်းများ** (ဥပမာ - ပုံမှန်စာသားထုတ်လုပ်မှု၊ စက်ဘာသာပြန်ခြင်း၊ ပုံဖော်ပြချက်ရေးခြင်း) အတွက် အသုံးပြုနိုင်စေသည်။\n",
|
||||
"\n",
|
||||
"ယခင်ယူနစ်တွင် ဆွေးနွေးခဲ့သည့် RNN architecture တွင် RNN unit တစ်ခုစီသည် နောက်ထွက်မည့် hidden state ကို output အဖြစ် ထုတ်ပေးသည်။ သို့သော်လည်း, RNN unit တစ်ခုစီတွင် output တစ်ခုထပ်မံထည့်သွင်းနိုင်ပြီး, ၎င်းသည် **sequence** (မူရင်း sequence နှင့် အရှည်တူ) ကို output အဖြစ် ထုတ်ပေးနိုင်သည်။ ထို့အပြင်, RNN units များကို အဆင့်တစ်ခုစီတွင် input မလိုအပ်ဘဲ, စတင်အခြေအနေ vector တစ်ခုသာ လက်ခံပြီး, ထို့နောက် output များ၏ sequence တစ်ခုကို ထုတ်ပေးစေနိုင်သည်။\n",
|
||||
"\n",
|
||||
"ဒီ notebook တွင်, စာသားထုတ်လုပ်ရန် ကူညီပေးသည့် ရိုးရှင်းသော generative models များကို အဓိကထား၍ လေ့လာသွားမည်ဖြစ်သည်။ ရိုးရှင်းစွာပြောရမည်ဆိုပါက, **character-level network** တစ်ခုကို တည်ဆောက်ကြမည်ဖြစ်ပြီး, ၎င်းသည် စာလုံးတစ်လုံးချင်းစီဖြင့် စာသားကို ထုတ်လုပ်ပေးမည်ဖြစ်သည်။ သင်ကြားမှုအတွင်း, စာသား corpus တစ်ခုကို ယူပြီး, ၎င်းကို စာလုံးအစီအစဉ်များအဖြစ် ခွဲထုတ်ရန် လိုအပ်မည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import tensorflow as tf\n",
|
||||
"from tensorflow import keras\n",
|
||||
"import tensorflow_datasets as tfds\n",
|
||||
"import numpy as np\n",
|
||||
"\n",
|
||||
"ds_train, ds_test = tfds.load('ag_news_subset').values()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## အက္ခရာအဆင့် ဝေါဟာရ တည်ဆောက်ခြင်း\n",
|
||||
"\n",
|
||||
"အက္ခရာအဆင့် ဖန်တီးမှုကွန်ရက်တစ်ခု တည်ဆောက်ရန်အတွက် စာသားကို စကားလုံးများမဟုတ်ဘဲ တစ်ခုချင်းစီ အက္ခရာများအဖြစ် ခွဲထုတ်ရမည်ဖြစ်သည်။ ယခင်က အသုံးပြုခဲ့သော `TextVectorization` layer သည် အဲဒီလိုလုပ်ဆောင်နိုင်မည်မဟုတ်သောကြောင့် အောက်ပါရွေးချယ်စရာနှစ်ခုရှိသည်-\n",
|
||||
"\n",
|
||||
"* [ဒီ Keras ရဲ့ တရားဝင် ဥပမာ](https://keras.io/examples/generative/lstm_character_level_text_generation/) တွင်ဖော်ပြထားသည့်အတိုင်း စာသားကို ကိုယ်တိုင်တင်သွင်းပြီး 'ကိုယ်တိုင်' tokenization ပြုလုပ်ရန်\n",
|
||||
"* `Tokenizer` class ကို အသုံးပြု၍ အက္ခရာအဆင့် tokenization ပြုလုပ်ရန်။\n",
|
||||
"\n",
|
||||
"ကျွန်ုပ်တို့သည် ဒုတိယရွေးချယ်စရာကို အသုံးပြုမည်ဖြစ်သည်။ `Tokenizer` သည် စကားလုံးများအဖြစ်လည်း tokenize ပြုလုပ်နိုင်သည့်အတွက် အက္ခရာအဆင့်မှ စကားလုံးအဆင့် tokenization သို့ အလွယ်တကူ ပြောင်းလဲနိုင်သည်။\n",
|
||||
"\n",
|
||||
"အက္ခရာအဆင့် tokenization ပြုလုပ်ရန် `char_level=True` parameter ကို ပေးသွင်းရမည်-\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def extract_text(x):\n",
|
||||
" return x['title']+' '+x['description']\n",
|
||||
"\n",
|
||||
"def tupelize(x):\n",
|
||||
" return (extract_text(x),x['label'])\n",
|
||||
"\n",
|
||||
"tokenizer = keras.preprocessing.text.Tokenizer(char_level=True,lower=False)\n",
|
||||
"tokenizer.fit_on_texts([x['title'].numpy().decode('utf-8') for x in ds_train])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့ **အဆင့်သတ်မှတ်ခြင်း၏ အဆုံး** ကိုဖော်ပြရန် `<eos>` ဟုခေါ်သော အထူးအမှတ်အသားတစ်ခုကိုလည်း အသုံးပြုလိုပါသည်။ ဒါကို အဘိဓာန်ထဲသို့ ကိုယ်တိုင်ထည့်သွင်းလိုက်ရအောင်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"eos_token = len(tokenizer.word_index)+1\n",
|
||||
"tokenizer.word_index['<eos>'] = eos_token\n",
|
||||
"\n",
|
||||
"vocab_size = eos_token + 1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[[48, 2, 10, 10, 5, 44, 1, 25, 5, 8, 10, 13, 78]]"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"tokenizer.texts_to_sequences(['Hello, world!'])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## RNN ကိုသင်ကြားပြီး ခေါင်းစဉ်များကို ဖန်တီးရန်\n",
|
||||
"\n",
|
||||
"RNN ကို သတင်းခေါင်းစဉ်များ ဖန်တီးရန် သင်ကြားပုံမှာ အောက်ပါအတိုင်း ဖြစ်ပါတယ်။ တစ်ခုချင်းစီအဆင့်မှာ RNN ထဲသို့ ထည့်မည့် ခေါင်းစဉ်တစ်ခုကို ရွေးပြီး၊ အင်ပွတ်အက္ခရာတစ်ခုစီအတွက် နောက်ထွက်အက္ခရာကို ဖန်တီးရန် ကွန်ယက်ကို မေးမြန်းပါမည်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"အကြောင်းအရာ၏ နောက်ဆုံးအက္ခရာအတွက် `<eos>` token ကို ဖန်တီးရန် ကွန်ယက်ကို မေးမြန်းပါမည်။\n",
|
||||
"\n",
|
||||
"ဒီနေရာမှာ အသုံးပြုမည့် generative RNN နှင့် အခြား RNN များ၏ အဓိကကွာခြားချက်မှာ RNN ၏ နောက်ဆုံး cell မှသာမက၊ အဆင့်တစ်ခုချင်းစီမှ ထွက်လာသော output ကိုလည်း အသုံးပြုမည်ဖြစ်သည်။ ဒါကို RNN cell တွင် `return_sequences` parameter ကို သတ်မှတ်ခြင်းဖြင့် ပြုလုပ်နိုင်ပါသည်။\n",
|
||||
"\n",
|
||||
"ထို့ကြောင့် သင်ကြားမှုအတွင်းမှာ ကွန်ယက်သို့ ထည့်မည့် အင်ပွတ်မှာ အချို့အရှည်ရှိသော အက္ခရာများကို encode လုပ်ထားသော အစီအစဉ်ဖြစ်ပြီး၊ output မှာ အတူတူရှည်သော အစီအစဉ်ဖြစ်သော်လည်း တစ်ခုချင်းစီကို တစ်ခုအဆင့်ရွှေ့ထားပြီး `<eos>` ဖြင့် အဆုံးသတ်ထားမည်ဖြစ်သည်။ Minibatch မှာ အစီအစဉ်များစွာ ပါဝင်မည်ဖြစ်ပြီး၊ အားလုံးကို alignment ပြုလုပ်ရန် **padding** ကို အသုံးပြုရမည်ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"အခုတော့ dataset ကို ပြောင်းလဲပေးမည့် function များကို ဖန်တီးကြစို့။ Minibatch အဆင့်မှာ sequence များကို padding ပြုလုပ်လိုသောကြောင့် dataset ကို `.batch()` ခေါ်ပြီး batch လုပ်ပြီးနောက် `map` ကို အသုံးပြု၍ ပြောင်းလဲမှုကို ပြုလုပ်မည်ဖြစ်သည်။ ထို့ကြောင့် ပြောင်းလဲမှု function မှာ minibatch တစ်ခုလုံးကို parameter အဖြစ် လက်ခံမည်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def title_batch(x):\n",
|
||||
" x = [t.numpy().decode('utf-8') for t in x]\n",
|
||||
" z = tokenizer.texts_to_sequences(x)\n",
|
||||
" z = tf.keras.preprocessing.sequence.pad_sequences(z)\n",
|
||||
" return tf.one_hot(z,vocab_size), tf.one_hot(tf.concat([z[:,1:],tf.constant(eos_token,shape=(len(z),1))],axis=1),vocab_size)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ဒီမှာ ကျွန်တော်တို့လုပ်ဆောင်တဲ့ အရေးကြီးအချက်အချို့:\n",
|
||||
"\n",
|
||||
"* ပထမဦးဆုံး ကျွန်တော်တို့ string tensor ထဲက အမှန်တကယ် text ကို extract လုပ်ပါတယ်။\n",
|
||||
"* `text_to_sequences` က string တွေကို integer tensor တွေဖြစ်အောင် ပြောင်းပေးပါတယ်။\n",
|
||||
"* `pad_sequences` က အဲ့ဒီ tensor တွေကို အများဆုံးအရှည်အတိုင်း pad လုပ်ပေးပါတယ်။\n",
|
||||
"* နောက်ဆုံးမှာ character တွေကို one-hot encode လုပ်ပြီး shifting နဲ့ `<eos>` ကို ထည့်ပေးပါတယ်။ အဲ့ဒီ character တွေကို one-hot encode လုပ်ရတဲ့ အကြောင်းကို မကြာခင်မှာ ရှင်းပြပေးပါမယ်။\n",
|
||||
"\n",
|
||||
"ဒါပေမယ့် ဒီ function က **Pythonic** ဖြစ်ပါတယ်၊ ဒါကြောင့် Tensorflow computational graph အဖြစ် အလိုအလျောက် ပြောင်းလို့မရပါဘူး။ ဒီ function ကို `Dataset.map` function ထဲမှာ တိုက်ရိုက် အသုံးပြုမယ်ဆိုရင် error တွေ ရှိလာနိုင်ပါတယ်။ ဒီ Pythonic call ကို `py_function` wrapper အသုံးပြုပြီး အုပ်ထားဖို့ လိုအပ်ပါတယ်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def title_batch_fn(x):\n",
|
||||
" x = x['title']\n",
|
||||
" a,b = tf.py_function(title_batch,inp=[x],Tout=(tf.float32,tf.float32))\n",
|
||||
" return a,b"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"> **Note**: Pythonic နှင့် Tensorflow ပြောင်းလဲမှုလုပ်ဆောင်မှုများကို ခွဲခြားဖို့ အလွန်ရှုပ်ထွေးတယ်လို့ ခံစားရနိုင်ပြီး၊ dataset ကို `fit` မှာ ပေးပို့မယ့်အခါမှာ သာမန် Python function တွေကို သုံးပြီး ပြောင်းလဲမှုလုပ်ဆောင်မှုကို မလုပ်တာ ဘာကြောင့်လဲဆိုတာကို မေးမြန်းချင်ဖြစ်နိုင်ပါတယ်။ ဒါကို လုပ်နိုင်တာ သေချာပေမယ့်၊ `Dataset.map` ကို သုံးခြင်းက အလွန်ကြီးမားတဲ့ အကျိုးကျေးဇူးရှိပါတယ်၊ အကြောင်းကတော့ data ပြောင်းလဲမှုလုပ်ဆောင်မှု pipeline ကို Tensorflow computational graph ကို အသုံးပြုပြီး အကောင်အထည်ဖော်တာကြောင့် GPU တွေကို အသုံးချနိုင်ပြီး CPU/GPU အကြား data ပေးပို့မှု လိုအပ်ချက်ကို လျှော့ချနိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"အခုတော့ generator network ကို တည်ဆောက်ပြီး training စတင်နိုင်ပါပြီ။ ဒါကို အရင် unit မှာ ဆွေးနွေးခဲ့တဲ့ recurrent cell မည်သည့်အမျိုးအစား (simple, LSTM, GRU) ကိုမဆို အခြေခံပြီး တည်ဆောက်နိုင်ပါတယ်။ ဥပမာအနေနဲ့ LSTM ကို အသုံးပြုပါမယ်။\n",
|
||||
"\n",
|
||||
"Network က အထိမ်းအမှတ်အဖြစ် character တွေကို input အနေနဲ့ ယူပြီး၊ vocabulary size က အတော်လေးသေးတဲ့အတွက် embedding layer မလိုအပ်ပါဘူး၊ one-hot-encoded input ကို တိုက်ရိုက် LSTM cell ထဲကို ပေးပို့နိုင်ပါတယ်။ Output layer ကတော့ LSTM output ကို one-hot-encoded token number တွေ အဖြစ် ပြောင်းလဲပေးမယ့် `Dense` classifier ဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"ထို့အပြင်၊ variable-length sequences တွေကို ကိုင်တွယ်နေရတဲ့အတွက် `Masking` layer ကို အသုံးပြုပြီး string ရဲ့ padded အပိုင်းကို မထည့်သွင်းဖို့ mask တစ်ခု ဖန်တီးနိုင်ပါတယ်။ ဒါဟာ မဖြစ်မနေလိုအပ်တာ မဟုတ်ပါဘူး၊ အကြောင်းကတော့ `<eos>` token ကို ကျော်လွန်သွားတဲ့ အပိုင်းအားလုံးကို အလွန်စိတ်ဝင်စားနေရတာ မဟုတ်ပေမယ့်၊ layer အမျိုးအစားကို အသုံးပြုတဲ့ အတွေ့အကြုံရဖို့အတွက် သုံးပါမယ်။ `input_shape` က `(None, vocab_size)` ဖြစ်ပြီး၊ `None` က variable length sequence ကို ရည်ညွှန်းပါတယ်၊ output shape ကလည်း `(None, vocab_size)` ဖြစ်ပါတယ်၊ `summary` မှာလည်း မြင်နိုင်ပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"sequential\"\n",
|
||||
"_________________________________________________________________\n",
|
||||
"Layer (type) Output Shape Param # \n",
|
||||
"=================================================================\n",
|
||||
"masking (Masking) (None, None, 84) 0 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"lstm (LSTM) (None, None, 128) 109056 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"dense (Dense) (None, None, 84) 10836 \n",
|
||||
"=================================================================\n",
|
||||
"Total params: 119,892\n",
|
||||
"Trainable params: 119,892\n",
|
||||
"Non-trainable params: 0\n",
|
||||
"_________________________________________________________________\n",
|
||||
"15000/15000 [==============================] - 229s 15ms/step - loss: 1.5385\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7fa40c1245e0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model = keras.models.Sequential([\n",
|
||||
" keras.layers.Masking(input_shape=(None,vocab_size)),\n",
|
||||
" keras.layers.LSTM(128,return_sequences=True),\n",
|
||||
" keras.layers.Dense(vocab_size,activation='softmax')\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"model.summary()\n",
|
||||
"model.compile(loss='categorical_crossentropy')\n",
|
||||
"\n",
|
||||
"model.fit(ds_train.batch(8).map(title_batch_fn))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## အထွက်ကို ဖန်တီးခြင်း\n",
|
||||
"\n",
|
||||
"အခုတော့ မော်ဒယ်ကို လေ့ကျင့်ပြီးဖြစ်တာကြောင့် အထွက်တစ်ခုခုကို ဖန်တီးဖို့လိုပါတယ်။ ပထမဆုံးအနေနဲ့ token နံပါတ်များစဉ်လိုက်ကိုယ်စားပြုထားတဲ့ စာသားကို ပြန်လည်ဖော်ထုတ်နိုင်တဲ့ နည်းလမ်းတစ်ခုလိုအပ်ပါတယ်။ ဒီအတွက် `tokenizer.sequences_to_texts` function ကို အသုံးပြုနိုင်ပေမယ့် character-level tokenization နဲ့ အလုပ်မလုပ်ကောင်းပါဘူး။ ဒါကြောင့် `word_index` လို့ခေါ်တဲ့ tokenizer ထဲက token တွေရဲ့ dictionary ကိုယူပြီး၊ reverse map တစ်ခုတည်ဆောက်ကာ၊ ကိုယ့်ရဲ့ decoding function ကိုရေးဖို့လိုပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"reverse_map = {val:key for key, val in tokenizer.word_index.items()}\n",
|
||||
"\n",
|
||||
"def decode(x):\n",
|
||||
" return ''.join([reverse_map[t] for t in x])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အခုတော့ စတင်မည်။ ကျွန်ုပ်တို့မှာ `start` ဆိုတဲ့ string တစ်ခုရှိပြီး၊ အဲဒါကို `inp` sequence အဖြစ် encode လုပ်ပါမည်။ ထို့နောက် တစ်ဆင့်ချင်းစီမှာ ကျွန်ုပ်တို့၏ network ကိုခေါ်ပြီး နောက် character ကို ခန့်မှန်းပါမည်။\n",
|
||||
"\n",
|
||||
"Network ရဲ့ output `out` က `vocab_size` elements ရှိတဲ့ vector ဖြစ်ပြီး၊ token တစ်ခုချင်းစီရဲ့ probability ကို ကိုယ်စားပြုထားသည်။ အများဆုံးဖြစ်နိုင်သော token နံပါတ်ကို `argmax` အသုံးပြု၍ ရှာနိုင်ပြီး၊ ဒီ character ကို generated token list ထဲသို့ ထည့်သွင်းပါမည်။ ထို့နောက် generation ကို ဆက်လက်လုပ်ဆောင်ပါမည်။ Character တစ်ခု generate လုပ်တဲ့ ဒီလုပ်ငန်းစဉ်ကို `size` ကြိမ် ထပ်လုပ်ပြီး လိုအပ်သော character အရေအတွက်ကို generate လုပ်ပါမည်။ `eos_token` ကို တွေ့ရှိသောအခါမှာတော့ အစောပိုင်းတွင် generation ကို ရပ်တန့်ပါမည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'Today #39;s lead to strike for the strike for the strike for the strike (AFP)'"
|
||||
]
|
||||
},
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def generate(model,size=100,start='Today '):\n",
|
||||
" inp = tokenizer.texts_to_sequences([start])[0]\n",
|
||||
" chars = inp\n",
|
||||
" for i in range(size):\n",
|
||||
" out = model(tf.expand_dims(tf.one_hot(inp,vocab_size),0))[0][-1]\n",
|
||||
" nc = tf.argmax(out)\n",
|
||||
" if nc==eos_token:\n",
|
||||
" break\n",
|
||||
" chars.append(nc.numpy())\n",
|
||||
" inp = inp+[nc]\n",
|
||||
" return decode(chars)\n",
|
||||
" \n",
|
||||
"generate(model)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## လေ့ကျင့်မှုအတွင်း အထွက်ကို နမူနာယူခြင်း\n",
|
||||
"\n",
|
||||
"*တိကျမှန်ကန်မှု* ကဲ့သို့သော အသုံးဝင်သော အတိုင်းအတာများမရှိသောကြောင့်၊ မော်ဒယ်က ပိုမိုကောင်းမွန်လာနေကြောင်းကို မြင်နိုင်ရန် တစ်ခုတည်းသော နည်းလမ်းမှာ **နမူနာယူခြင်း** ဖြစ်ပြီး၊ လေ့ကျင့်မှုအတွင်း ထုတ်လုပ်ထားသော စာကြောင်းများကို ကြည့်ရှုရမည်ဖြစ်သည်။ ဒါကို ပြုလုပ်ရန် **callbacks** ကို အသုံးပြုမည်ဖြစ်ပြီး၊ ၎င်းသည် `fit` function သို့ ပေးပို့နိုင်သော function များဖြစ်ပြီး၊ လေ့ကျင့်မှုအတွင်း အချိန်ကာလအလိုက် ခေါ်သုံးမည်ဖြစ်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Epoch 1/3\n",
|
||||
"15000/15000 [==============================] - 226s 15ms/step - loss: 1.2703\n",
|
||||
"Today #39;s a lead in the company for the strike\n",
|
||||
"Epoch 2/3\n",
|
||||
"15000/15000 [==============================] - 227s 15ms/step - loss: 1.2057\n",
|
||||
"Today #39;s the Market Service on Security Start (AP)\n",
|
||||
"Epoch 3/3\n",
|
||||
"15000/15000 [==============================] - 226s 15ms/step - loss: 1.1752\n",
|
||||
"Today #39;s a line on the strike to start for the start\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7fa40c74e3d0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"sampling_callback = keras.callbacks.LambdaCallback(\n",
|
||||
" on_epoch_end = lambda batch, logs: print(generate(model))\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"model.fit(ds_train.batch(8).map(title_batch_fn),callbacks=[sampling_callback],epochs=3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ဤဥပမာသည် အတော်လေးကောင်းမွန်သောစာသားကို ရAlready ထုတ်ပေးနိုင်ပြီးဖြစ်သော်လည်း အချို့နည်းလမ်းများဖြင့် ထပ်မံတိုးတက်စေနိုင်ပါသည်။\n",
|
||||
"\n",
|
||||
"* **ပိုမိုသောစာသား**။ ကျွန်ုပ်တို့၏လုပ်ငန်းအတွက် ခေါင်းစဉ်များကိုသာ အသုံးပြုထားသော်လည်း အပြည့်အစုံသောစာသားများဖြင့် စမ်းသပ်ကြည့်လိုစိတ်ရှိနိုင်ပါသည်။ သတိပြုရန်မှာ RNN များသည် ရှည်လျားသောအကြောင်းအရာများကို ကိုင်တွယ်ရာတွင် အလွန်ကောင်းမွန်သည်မဟုတ်ပါ၊ ထို့ကြောင့် စာကြောင်းတိုများအဖြစ် ခွဲထုတ်ခြင်း သို့မဟုတ် သတ်မှတ်ထားသော `num_chars` (ဥပမာ 256) တန်ဖိုးဖြင့် အမြဲတမ်းတည်ဆောက်ထားသော အတိုင်းအတာအရှည်ဖြင့် လေ့ကျင့်ခြင်းတို့ကို စဉ်းစားသင့်ပါသည်။ အထက်ပါဥပမာကို [အတည်ပြု Keras လေ့ကျင့်ရေးလမ်းညွှန်](https://keras.io/examples/generative/lstm_character_level_text_generation/) ကို အားထား၍ ထိုကဲ့သို့သောဖွဲ့စည်းမှုအဖြစ် ပြောင်းလဲကြည့်နိုင်ပါသည်။\n",
|
||||
"\n",
|
||||
"* **Multilayer LSTM**။ LSTM cells 2 သို့မဟုတ် 3 အလွှာကို စမ်းသပ်ကြည့်ရန် make sense ဖြစ်ပါသည်။ ယခင်ယူနစ်တွင် ပြောခဲ့သည့်အတိုင်း LSTM ၏ အလွှာတစ်ခုစီသည် စာသားမှ အချို့သောပုံစံများကို ထုတ်ယူပေးပြီး၊ character-level generator ၏အနေဖြင့် အနိမ့်ဆုံး LSTM အလွှာသည် သရော်အသံများကို ထုတ်ယူရန် တာဝန်ရှိပြီး၊ အမြင့်ဆုံးအလွှာများသည် စကားလုံးများနှင့် စကားလုံးပေါင်းများကို ထုတ်ယူရန် တာဝန်ရှိသည်ဟု မျှော်လင့်နိုင်ပါသည်။ ၎င်းကို LSTM constructor သို့ အလွှာအရေအတွက် parameter ကို ပေးပို့ခြင်းဖြင့် ရိုးရှင်းစွာ အကောင်အထည်ဖော်နိုင်ပါသည်။\n",
|
||||
"\n",
|
||||
"* **GRU units** ဖြင့်လည်း စမ်းသပ်ကြည့်လိုစိတ်ရှိနိုင်ပြီး၊ **hidden layer sizes များကို မတူညီစွာ** စမ်းသပ်ကြည့်နိုင်ပါသည်။ Hidden layer အရွယ်အစား အလွန်ကြီးလွန်းပါက overfitting ဖြစ်စေနိုင်ပြီး (ဥပမာ network သည် စာသားကို တိတိကျကျ သင်ယူသွားမည်ဖြစ်သည်)၊ အရွယ်အစား သေးလွန်းပါက ကောင်းမွန်သောရလဒ် မထုတ်ပေးနိုင်ပါ။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Soft text generation and temperature\n",
|
||||
"\n",
|
||||
"ယခင် `generate` ကိုဖော်ပြထားသော အဓိပ္ပါယ်အရ၊ ကျွန်ုပ်တို့သည် အမြဲတမ်း အမြင့်ဆုံး probability ရှိသော အက္ခရာကို ရွေးပြီး ထုတ်လုပ်ထားသော စာသားတွင် နောက်ထပ် အက္ခရာအဖြစ် အသုံးပြုခဲ့သည်။ ဒီနည်းလမ်းကြောင့် စာသားသည် အချို့သော အက္ခရာအလှည့်အပြောင်းများကို ထပ်တလဲလဲ ဖြစ်စေခဲ့သည်။ ဥပမာအားဖြင့်:\n",
|
||||
"```\n",
|
||||
"today of the second the company and a second the company ...\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"သို့သော်၊ နောက်ထပ် အက္ခရာအတွက် probability distribution ကိုကြည့်မယ်ဆိုရင်၊ အမြင့်ဆုံး probability ရှိသော အက္ခရာများအကြား ကွာဟချက်သည် များစွာ မကြီးမားနိုင်ပါ။ ဥပမာအားဖြင့် အက္ခရာတစ်ခုမှာ probability 0.2 ရှိနိုင်ပြီး၊ နောက်တစ်ခုမှာ 0.19 ရှိနိုင်သည်။ ဥပမာအားဖြင့် '*play*' ဆိုသော စာကြောင်းတွင် နောက်ထပ် အက္ခရာသည် space ဖြစ်နိုင်သလို၊ **e** (ဥပမာ player ဆိုသော စကားလုံးတွင်) ဖြစ်နိုင်ပါသည်။\n",
|
||||
"\n",
|
||||
"ဒီအခြေအနေကြောင့် အမြင့်ဆုံး probability ရှိသော အက္ခရာကိုသာ ရွေးချယ်ခြင်းသည် အမြဲတမ်း \"တရားမျှတ\" မဖြစ်နိုင်ပါ။ ဒုတိယမြင့်ဆုံး probability ရှိသော အက္ခရာကို ရွေးချယ်ခြင်းသည်လည်း အဓိပ္ပါယ်ရှိသော စာသားကို ရရှိစေနိုင်ပါသည်။ ထို့ကြောင့် network output မှပေးသော probability distribution ကို အသုံးပြု၍ **sample** လုပ်ခြင်းသည် ပိုပြီး ဉာဏ်ရှိသော နည်းလမ်းဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"ဒီ sampling ကို **multinomial distribution** ဟုခေါ်သော နည်းလမ်းကို အကောင်အထည်ဖော်ပေးသော `np.multinomial` function ကို အသုံးပြု၍ ပြုလုပ်နိုင်ပါသည်။ **soft** text generation ကို အကောင်အထည်ဖော်ပေးသော function ကို အောက်တွင် ဖော်ပြထားသည်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 33,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\n",
|
||||
"--- Temperature = 0.3\n",
|
||||
"Today #39;s strike #39; to start at the store return\n",
|
||||
"On Sunday PO to Be Data Profit Up (Reuters)\n",
|
||||
"Moscow, SP wins straight to the Microsoft #39;s control of the space start\n",
|
||||
"President olding of the blast start for the strike to pay <b>...</b>\n",
|
||||
"Little red riding hood ficed to the spam countered in European <b>...</b>\n",
|
||||
"\n",
|
||||
"--- Temperature = 0.8\n",
|
||||
"Today countie strikes ryder missile faces food market blut\n",
|
||||
"On Sunday collores lose-toppy of sale of Bullment in <b>...</b>\n",
|
||||
"Moscow, IBM Diffeiting in Afghan Software Hotels (Reuters)\n",
|
||||
"President Ol Luster for Profit Peaced Raised (AP)\n",
|
||||
"Little red riding hood dace on depart talks #39; bank up\n",
|
||||
"\n",
|
||||
"--- Temperature = 1.0\n",
|
||||
"Today wits House buiting debate fixes #39; supervice stake again\n",
|
||||
"On Sunday arling digital poaching In for level\n",
|
||||
"Moscow, DS Up 7, Top Proble Protest Caprey Mamarian Strike\n",
|
||||
"President teps help of roubler stepted lessabul-Dhalitics (AFP)\n",
|
||||
"Little red riding hood signs on cash in Carter-youb\n",
|
||||
"\n",
|
||||
"--- Temperature = 1.3\n",
|
||||
"Today wits flawer ro, pSIA figat's co DroftwavesIs Talo up\n",
|
||||
"On Sunday hround elitwing wint EU Powerburlinetien\n",
|
||||
"Moscow, Bazz #39;s sentries olymen winnelds' next for Olympite Huc?\n",
|
||||
"President lost securitys from power Elections in Smiltrials\n",
|
||||
"Little red riding hood vides profit, exponituity, profitmainalist-at said listers\n",
|
||||
"\n",
|
||||
"--- Temperature = 1.8\n",
|
||||
"Today #39;It: He deat: N.KA Asside\n",
|
||||
"On Sunday i arry Par aldeup patient Wo stele1\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"ename": "KeyError",
|
||||
"evalue": "0",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
||||
"\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)",
|
||||
"\u001b[0;32m<ipython-input-33-db32367a0feb>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf\"\\n--- Temperature = {i}\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mj\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mgenerate_soft\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0msize\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m300\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mstart\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mwords\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mj\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mtemperature\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
|
||||
"\u001b[0;32m<ipython-input-33-db32367a0feb>\u001b[0m in \u001b[0;36mgenerate_soft\u001b[0;34m(model, size, start, temperature)\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0mchars\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0minp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0minp\u001b[0m\u001b[0;34m+\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mnc\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 13\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mchars\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 14\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 15\u001b[0m \u001b[0mwords\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m'Today '\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'On Sunday '\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'Moscow, '\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'President '\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'Little red riding hood '\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
||||
"\u001b[0;32m<ipython-input-10-3f5fa6130b1d>\u001b[0m in \u001b[0;36mdecode\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mreverse_map\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mt\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
|
||||
"\u001b[0;32m<ipython-input-10-3f5fa6130b1d>\u001b[0m in \u001b[0;36m<listcomp>\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mreverse_map\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mt\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
|
||||
"\u001b[0;31mKeyError\u001b[0m: 0"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def generate_soft(model,size=100,start='Today ',temperature=1.0):\n",
|
||||
" inp = tokenizer.texts_to_sequences([start])[0]\n",
|
||||
" chars = inp\n",
|
||||
" for i in range(size):\n",
|
||||
" out = model(tf.expand_dims(tf.one_hot(inp,vocab_size),0))[0][-1]\n",
|
||||
" probs = tf.exp(tf.math.log(out)/temperature).numpy().astype(np.float64)\n",
|
||||
" probs = probs/np.sum(probs)\n",
|
||||
" nc = np.argmax(np.random.multinomial(1,probs,1))\n",
|
||||
" if nc==eos_token:\n",
|
||||
" break\n",
|
||||
" chars.append(nc)\n",
|
||||
" inp = inp+[nc]\n",
|
||||
" return decode(chars)\n",
|
||||
"\n",
|
||||
"words = ['Today ','On Sunday ','Moscow, ','President ','Little red riding hood ']\n",
|
||||
" \n",
|
||||
"for i in [0.3,0.8,1.0,1.3,1.8]:\n",
|
||||
" print(f\"\\n--- Temperature = {i}\")\n",
|
||||
" for j in range(5):\n",
|
||||
" print(generate_soft(model,size=300,start=words[j],temperature=i))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့သည် **အပူချိန်** ဟုခေါ်သော နောက်ထပ်ပါရာမီတာတစ်ခုကို မိတ်ဆက်ပေးခဲ့ပြီး၊ ၎င်းကို အမြင့်ဆုံးဖြစ်နိုင်မှုကို မည်မျှတင်းကြပ်စွာလိုက်နာရမည်ကို ဖော်ပြရန် အသုံးပြုသည်။ အပူချိန်သည် 1.0 ဖြစ်ပါက၊ ကျွန်ုပ်တို့သည် တရားမျှတသော multinomial sampling ကို ပြုလုပ်ပြီး၊ အပူချိန်သည် အဆုံးမရှိအထိ မြင့်တက်သွားသောအခါ - ဖြစ်နိုင်မှုအားလုံးသည် တူညီသွားပြီး၊ နောက်တစ်ခုသော အက္ခရာကို ကျပန်းရွေးချယ်သည်။ အောက်တွင်ပေးထားသော ဥပမာတွင် ကျွန်ုပ်တို့သည် အပူချိန်ကို အလွန်များစွာမြှင့်တင်သောအခါ၊ စာသားသည် အဓိပ္ပါယ်မရှိသွားကြောင်းကို တွေ့နိုင်ပြီး၊ အပူချိန်သည် 0 အနီးသို့ ရောက်လာသောအခါ \"cycled\" အခက်အခဲဖြင့် ဖန်တီးထားသော စာသားနှင့် ဆင်တူသည်ကို တွေ့နိုင်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေပါသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်မှုများတွင် အမှားများ သို့မဟုတ် မတိကျမှုများ ပါရှိနိုင်သည်ကို သတိပြုပါ။ မူရင်းဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာတရ အရင်းအမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူက ဘာသာပြန်မှု ဝန်ဆောင်မှုကို အသုံးပြုရန် အကြံပြုပါသည်။ ဤဘာသာပြန်မှုကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွဲအချော်များ သို့မဟုတ် အနားလွဲမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3.8.12 ('py38')",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "9fbb7d5fda708537649f71f5f646fcde",
|
||||
"translation_date": "2025-08-30T10:11:54+00:00",
|
||||
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.ipynb",
|
||||
"language_code": "my"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -0,0 +1,353 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# အာရုံစူးစိုက်မှု မော်ကွန်းများနှင့် Transformer မော်ဒယ်များ\n",
|
||||
"\n",
|
||||
"Recurrent networks (ပြန်လည်ဆက်သွယ်မှုကွန်ရက်များ) ရဲ့ အဓိကအားနည်းချက်တစ်ခုကတော့ စာကြောင်းတစ်ကြောင်းရဲ့ စကားလုံးအားလုံးဟာ ရလဒ်အပေါ်မှာ တူညီတဲ့ သက်ရောက်မှုရှိတယ်ဆိုတာပါပဲ။ ဒါကြောင့် Named Entity Recognition (နာမည်ပုဂ္ဂိုလ်သတ်မှတ်မှု) နဲ့ Machine Translation (စက်ဖြင့်ဘာသာပြန်ခြင်း) လိုမျိုး sequence-to-sequence (အဆက်မပြတ်အချက်အလက်) တာဝန်တွေမှာ စံပုံ LSTM encoder-decoder မော်ဒယ်တွေက အကောင်းဆုံးစွမ်းဆောင်ရည်မရနိုင်တာဖြစ်ပါတယ်။ အမှန်တရားမှာတော့ input sequence (အဝင်အဆက်မပြတ်အချက်အလက်) ရဲ့ အချို့စကားလုံးတွေက output (အထွက်) အပေါ်မှာ ပိုမိုသက်ရောက်မှုရှိတတ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"Machine translation (စက်ဖြင့်ဘာသာပြန်ခြင်း) လိုမျိုး sequence-to-sequence မော်ဒယ်တစ်ခုကို စဉ်းစားကြည့်ပါ။ ဒါကို recurrent networks နှစ်ခုနဲ့ အကောင်အထည်ဖော်ထားပါတယ်။ network တစ်ခု (**encoder**) က input sequence ကို hidden state (ဖုံးလွှမ်းထားသောအခြေအနေ) အဖြစ်သို့ ပြောင်းလဲပြီး၊ နောက်တစ်ခု (**decoder**) က အဲ့ဒီ hidden state ကို ဘာသာပြန်ရလဒ်အဖြစ် ပြန်လည်ဖော်ထုတ်ပါတယ်။ ဒီနည်းလမ်းရဲ့ ပြဿနာကတော့ network ရဲ့ နောက်ဆုံးအခြေအနေက စာကြောင်းရဲ့ အစပိုင်းကို မှတ်မိဖို့ အခက်အခဲရှိတာကြောင့် ရှည်လျားတဲ့ စာကြောင်းတွေမှာ မော်ဒယ်ရဲ့ အရည်အသွေးကျဆင်းစေတတ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"**Attention Mechanisms (အာရုံစူးစိုက်မှုစနစ်များ)** ကတော့ RNN ရဲ့ output prediction (အထွက်ခန့်မှန်းမှု) တစ်ခုစီအပေါ် input vector (အဝင်ဗက်တာ) တစ်ခုစီရဲ့ အကြောင်းအရာသက်ရောက်မှုကို အလေးပေးနိုင်တဲ့ နည်းလမ်းတစ်ခုကို ပံ့ပိုးပေးပါတယ်။ ဒီစနစ်ကို အကောင်အထည်ဖော်တဲ့နည်းလမ်းက input RNN ရဲ့ အလယ်အလတ်အခြေအနေတွေနဲ့ output RNN အကြား shortcut (တိုက်ရိုက်လမ်းကြောင်း) တွေ ဖန်တီးခြင်းဖြစ်ပါတယ်။ ဒီနည်းလမ်းနဲ့ $y_t$ output symbol ကို ဖန်တီးတဲ့အခါမှာ input hidden states $h_i$ အားလုံးကို အလေးချိန်ကွဲပြားမှု $\\alpha_{t,i}$ နဲ့အတူ စဉ်းစားပါမယ်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"*[Bahdanau et al., 2015](https://arxiv.org/pdf/1409.0473.pdf) မှ additive attention mechanism ပါတဲ့ encoder-decoder မော်ဒယ်ကို [ဒီ blog post](https://lilianweng.github.io/lil-log/2018/06/24/attention-attention.html) မှ ရယူထားသည်။*\n",
|
||||
"\n",
|
||||
"Attention matrix $\\{\\alpha_{i,j}\\}$ က output sequence (အထွက်အဆက်မပြတ်အချက်အလက်) ရဲ့ စကားလုံးတစ်လုံးကို ဖန်တီးရာမှာ input words (အဝင်စကားလုံး) တစ်ချို့ရဲ့ သက်ရောက်မှုအဆင့်ကို ကိုယ်စားပြုပါတယ်။ အောက်မှာ ဒီလို matrix ရဲ့ ဥပမာကို ကြည့်နိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"*[Bahdanau et al., 2015](https://arxiv.org/pdf/1409.0473.pdf) မှ (ပုံ ၃) ကို ရယူထားသည်။*\n",
|
||||
"\n",
|
||||
"Attention mechanisms တွေက Natural Language Processing (ဘာသာစကားအလုပ်လုပ်စနစ်) ရဲ့ လက်ရှိ state-of-the-art (အဆင့်မြင့်နည်းပညာ) မော်ဒယ်တွေမှာ အရေးပါတဲ့ အခန်းကဏ္ဍကို ထမ်းဆောင်နေပါတယ်။ သို့သော် attention ကို ထည့်သွင်းခြင်းက မော်ဒယ် parameter (မော်ဒယ်အချက်အလက်) အရေအတွက်ကို အလွန်များစေပြီး၊ RNN တွေမှာ scaling (အရွယ်အစားချဲ့ထွင်မှု) ပြဿနာတွေ ဖြစ်ပေါ်စေပါတယ်။ RNN တွေမှာ အဆက်မပြတ်အချက်အလက်တစ်ခုစီကို အစဉ်လိုက် ဆက်တိုက်လုပ်ဆောင်ရတာကြောင့် training (လေ့ကျင့်မှု) ကို batch နဲ့ parallelize (တပြိုင်နက်) လုပ်ဖို့ အခက်အခဲရှိပါတယ်။\n",
|
||||
"\n",
|
||||
"Attention mechanisms တွေကို အသုံးပြုမှုနဲ့ အထက်ပါ အကန့်အသတ်ကြောင့် ယနေ့ကျွန်တော်တို့သိပြီး အသုံးပြုနေတဲ့ BERT ကနေ OpenGPT3 အထိရှိတဲ့ လက်ရှိ state-of-the-art Transformer မော်ဒယ်တွေကို ဖန်တီးနိုင်ခဲ့ပါတယ်။\n",
|
||||
"\n",
|
||||
"## Transformer မော်ဒယ်များ\n",
|
||||
"\n",
|
||||
"တစ်ခုချင်းစီရဲ့ အရင်ဆုံးခန့်မှန်းချက်ရဲ့ context (အကြောင်းအရာ) ကို နောက်တစ်ဆင့်သို့ ပို့ပေးခြင်းအစား၊ **Transformer မော်ဒယ်များ** က **positional encodings** နဲ့ attention ကို အသုံးပြုပြီး ပေးထားတဲ့ စာသား window (အကန့်အသတ်) အတွင်းမှာ အကြောင်းအရာကို ဖမ်းဆီးပါတယ်။ အောက်ပါပုံက positional encodings နဲ့ attention က window အတွင်းမှာ context ကို ဘယ်လိုဖမ်းဆီးနိုင်တယ်ဆိုတာ ပြထားပါတယ်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"Input position တစ်ခုချင်းစီကို output position တစ်ခုချင်းစီနဲ့ လွတ်လပ်စွာ mapping လုပ်နိုင်တဲ့အတွက်၊ transformers တွေက RNN တွေထက် ပိုမို parallelize လုပ်နိုင်ပြီး၊ ပိုကြီးမားပြီး ပိုထိရောက်တဲ့ ဘာသာစကားမော်ဒယ်တွေကို ဖန်တီးနိုင်ပါတယ်။ Attention head တစ်ခုချင်းစီက စကားလုံးတွေကြားက ဆက်စပ်မှုအမျိုးမျိုးကို သင်ယူနိုင်ပြီး၊ ဒါက Downstream Natural Language Processing (နောက်ဆင့်ဘာသာစကားအလုပ်လုပ်စနစ်) တာဝန်တွေကို တိုးတက်စေပါတယ်။\n",
|
||||
"\n",
|
||||
"**BERT** (Bidirectional Encoder Representations from Transformers) က အလွှာ ၁၂ လွှာပါတဲ့ *BERT-base* နဲ့ အလွှာ ၂၄ လွှာပါတဲ့ *BERT-large* တို့ဖြင့် ဖွဲ့စည်းထားတဲ့ အလွန်ကြီးမားတဲ့ multi-layer transformer network တစ်ခုဖြစ်ပါတယ်။ ဒီမော်ဒယ်ကို စာကြောင်းထဲက masked words (ဖုံးထားသောစကားလုံးများ) ကို ခန့်မှန်းတဲ့ unsupervised training (မကြီးကြပ်သောလေ့ကျင့်မှု) နည်းလမ်းနဲ့ စာကြောင်းအများအပြား (WikiPedia + စာအုပ်များ) အပေါ်မှာ အရင်ဆုံး pre-train လုပ်ထားပါတယ်။ Pre-training လုပ်စဉ်မှာ မော်ဒယ်က ဘာသာစကားနားလည်မှုအဆင့်မြင့်တစ်ခုကို စုပ်ယူထားပြီး၊ အဲ့ဒီနားလည်မှုကို အခြား dataset တွေနဲ့ fine-tuning (အသေးစိတ်ချိန်ညှိမှု) လုပ်နိုင်ပါတယ်။ ဒီလုပ်ငန်းစဉ်ကို **transfer learning** လို့ ခေါ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"Transformer architecture တွေမှာ BERT, DistilBERT, BigBird, OpenGPT3 စတဲ့ မော်ဒယ်အမျိုးအစားအများအပြားရှိပြီး၊ အဲ့ဒီမော်ဒယ်တွေကို fine-tune လုပ်နိုင်ပါတယ်။ [HuggingFace package](https://github.com/huggingface/) က PyTorch နဲ့ အဲ့ဒီ architecture တွေကို training လုပ်ဖို့ repository တစ်ခုကို ပံ့ပိုးပေးထားပါတယ်။\n",
|
||||
"\n",
|
||||
"## BERT ကို အသုံးပြု၍ စာသားအမျိုးအစားခွဲခြားခြင်း\n",
|
||||
"\n",
|
||||
"Pre-trained BERT မော်ဒယ်ကို အသုံးပြုပြီး ကျွန်တော်တို့ရဲ့ ရိုးရာတာဝန်ဖြစ်တဲ့ sequence classification (အဆက်မပြတ်အချက်အလက်ခွဲခြားခြင်း) ကို ဘယ်လိုဖြေရှင်းမလဲဆိုတာ ကြည့်ကြရအောင်။ ကျွန်တော်တို့ရဲ့ မူရင်း AG News dataset ကို ခွဲခြားသတ်မှတ်သွားမှာ ဖြစ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"ပထမဆုံး HuggingFace library နဲ့ dataset ကို load လုပ်ရအောင်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Loading dataset...\n",
|
||||
"Building vocab...\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import torch\n",
|
||||
"import torchtext\n",
|
||||
"from torchnlp import *\n",
|
||||
"import transformers\n",
|
||||
"train_dataset, test_dataset, classes, vocab = load_dataset()\n",
|
||||
"vocab_len = len(vocab)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့သည် pre-trained BERT မော်ဒယ်ကို အသုံးပြုမည်ဖြစ်သောကြောင့် သီးခြား tokenizer တစ်ခုကို အသုံးပြုရန် လိုအပ်ပါသည်။ ပထမဦးစွာ pre-trained BERT မော်ဒယ်နှင့် ဆက်စပ်သော tokenizer ကို load လုပ်ပါမည်။\n",
|
||||
"\n",
|
||||
"HuggingFace library တွင် pre-trained မော်ဒယ်များ၏ repository တစ်ခု ပါဝင်ပြီး၊ မော်ဒယ်အမည်များကို `from_pretrained` function များတွင် argument အဖြစ် သတ်မှတ်ခြင်းဖြင့် အသုံးပြုနိုင်ပါသည်။ မော်ဒယ်အတွက် လိုအပ်သော binary ဖိုင်များအားလုံးကို အလိုအလျောက် download လုပ်ပေးပါမည်။\n",
|
||||
"\n",
|
||||
"သို့သော် တစ်ချိန်ချိန်တွင် မိမိ၏ မော်ဒယ်များကို load လုပ်ရန် လိုအပ်နိုင်ပြီး၊ ထိုအခါတွင် tokenizer အတွက် parameters, မော်ဒယ် parameters ပါဝင်သော `config.json` ဖိုင်၊ binary weights စသည်တို့ပါဝင်သည့် directory ကို သတ်မှတ်နိုင်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# To load the model from Internet repository using model name. \n",
|
||||
"# Use this if you are running from your own copy of the notebooks\n",
|
||||
"bert_model = 'bert-base-uncased' \n",
|
||||
"\n",
|
||||
"# To load the model from the directory on disk. Use this for Microsoft Learn module, because we have\n",
|
||||
"# prepared all required files for you.\n",
|
||||
"bert_model = './bert'\n",
|
||||
"\n",
|
||||
"tokenizer = transformers.BertTokenizer.from_pretrained(bert_model)\n",
|
||||
"\n",
|
||||
"MAX_SEQ_LEN = 128\n",
|
||||
"PAD_INDEX = tokenizer.convert_tokens_to_ids(tokenizer.pad_token)\n",
|
||||
"UNK_INDEX = tokenizer.convert_tokens_to_ids(tokenizer.unk_token)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"`tokenizer` အရာဝတ္ထုတွင် `encode` အလုပ်ဆောင်မှုပါရှိပြီး၊ စာသားကိုတိုက်ရိုက် encode လုပ်ရန်အသုံးပြုနိုင်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[101, 1052, 22123, 2953, 2818, 2003, 1037, 2307, 7705, 2005, 17953, 2361, 102]"
|
||||
]
|
||||
},
|
||||
"execution_count": 15,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"tokenizer.encode('PyTorch is a great framework for NLP')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ထို့နောက်၊ သင်ကြားမှုအတွင်း ဒေတာများကို ဝင်ရောက်အသုံးပြုရန်အတွက် အသုံးပြုမည့် iterators များကို ဖန်တီးကြမည်။ BERT သည် သူ၏ကိုယ်ပိုင် encoding function ကို အသုံးပြုသောကြောင့်၊ ယခင်က သတ်မှတ်ထားသော `padify` နှင့် ဆင်တူသော padding function ကို သတ်မှတ်ရန် လိုအပ်ပါမည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def pad_bert(b):\n",
|
||||
" # b is the list of tuples of length batch_size\n",
|
||||
" # - first element of a tuple = label, \n",
|
||||
" # - second = feature (text sequence)\n",
|
||||
" # build vectorized sequence\n",
|
||||
" v = [tokenizer.encode(x[1]) for x in b]\n",
|
||||
" # compute max length of a sequence in this minibatch\n",
|
||||
" l = max(map(len,v))\n",
|
||||
" return ( # tuple of two tensors - labels and features\n",
|
||||
" torch.LongTensor([t[0] for t in b]),\n",
|
||||
" torch.stack([torch.nn.functional.pad(torch.tensor(t),(0,l-len(t)),mode='constant',value=0) for t in v])\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=8, collate_fn=pad_bert, shuffle=True)\n",
|
||||
"test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=8, collate_fn=pad_bert)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့၏ကိစ္စတွင် `bert-base-uncased` ဟုခေါ်သော pre-trained BERT မော်ဒယ်ကို အသုံးပြုမည်ဖြစ်သည်။ `BertForSequenceClassfication` package ကို အသုံးပြု၍ မော်ဒယ်ကို load လုပ်ပါမည်။ ဤသည်မှာ classification အတွက် လိုအပ်သော architecture ကို မော်ဒယ်တွင် ရှိပြီးဖြစ်စေသည်၊ အပြီးသတ် classifier ကိုပါ ထည့်သွင်းထားသည်။ မော်ဒယ်၏ အပြီးသတ် classifier ၏ weight များကို initialize မလုပ်ထားသောကြောင်းနှင့် မော်ဒယ်ကို pre-training လိုအပ်မည်ဖြစ်ကြောင်းကို ပြသသော warning message ကို တွေ့မြင်ရမည် - ဤသည်မှာ အလုံးစုံအဆင်ပြေပါသည်၊ အကြောင်းမူကား ကျွန်ုပ်တို့လုပ်ဆောင်မည့်အရာမှာ အတိအကျဤအရာပင်ဖြစ်သည်!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Some weights of the model checkpoint at ./bert were not used when initializing BertForSequenceClassification: ['cls.predictions.bias', 'cls.predictions.transform.dense.weight', 'cls.predictions.transform.dense.bias', 'cls.predictions.decoder.weight', 'cls.seq_relationship.weight', 'cls.seq_relationship.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.transform.LayerNorm.bias']\n",
|
||||
"- This IS expected if you are initializing BertForSequenceClassification from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n",
|
||||
"- This IS NOT expected if you are initializing BertForSequenceClassification from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n",
|
||||
"Some weights of BertForSequenceClassification were not initialized from the model checkpoint at ./bert and are newly initialized: ['classifier.weight', 'classifier.bias']\n",
|
||||
"You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model = transformers.BertForSequenceClassification.from_pretrained(bert_model,num_labels=4).to(device)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ယခုကျွန်ုပ်တို့ သင်ကြားမှုကို စတင်ရန် အဆင်သင့်ဖြစ်ပါပြီ! BERT သည် အစဉ်အလာအတိုင်း အကြိုသင်ကြားပြီးသားဖြစ်သောကြောင့်၊ မူလအလေးချိန်များကို ပျက်စီးမသွားစေရန် သင်ကြားမှုအတွက် အလွန်သေးငယ်သော learning rate ဖြင့် စတင်လိုပါသည်။\n",
|
||||
"\n",
|
||||
"`BertForSequenceClassification` မော်ဒယ်က အဓိကအလုပ်အားလုံးကို လုပ်ဆောင်ပေးပါသည်။ သင်ကြားမှုဒေတာပေါ်တွင် မော်ဒယ်ကို ခေါ်သုံးသောအခါ၊ input minibatch အတွက် loss နှင့် network output နှစ်ခုလုံးကို ပြန်ပေးပါသည်။ loss ကို parameter optimization (`loss.backward()` သည် backward pass ကို လုပ်ဆောင်သည်) အတွက် အသုံးပြုပြီး၊ `out` ကို training accuracy ကိုတွက်ချက်ရန် အသုံးပြုပါသည်။ accuracy ကိုတွက်ချက်ရာတွင် ရရှိသော labels `labs` (ဤသည်ကို `argmax` အသုံးပြု၍ တွက်ချက်သည်) နှင့် မျှော်မှန်းထားသော `labels` ကို နှိုင်းယှဉ်ပါသည်။\n",
|
||||
"\n",
|
||||
"လုပ်ငန်းစဉ်ကို ထိန်းချုပ်နိုင်ရန်၊ loss နှင့် accuracy ကို iteration အတော်များများအတွင်း စုဆောင်းပြီး၊ `report_freq` သင်ကြားမှုစက်ဝိုင်းတိုင်းတွင် ထုတ်ပြပါသည်။\n",
|
||||
"\n",
|
||||
"ဤသင်ကြားမှုသည် အချိန်အတော်ကြာနိုင်သောကြောင့်၊ iteration အရေအတွက်ကို ကန့်သတ်ထားပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Loss = 1.1254194641113282, Accuracy = 0.585\n",
|
||||
"Loss = 0.6194715118408203, Accuracy = 0.83\n",
|
||||
"Loss = 0.46665248870849607, Accuracy = 0.8475\n",
|
||||
"Loss = 0.4309701919555664, Accuracy = 0.8575\n",
|
||||
"Loss = 0.35427074432373046, Accuracy = 0.8825\n",
|
||||
"Loss = 0.3306886291503906, Accuracy = 0.8975\n",
|
||||
"Loss = 0.30340143203735354, Accuracy = 0.8975\n",
|
||||
"Loss = 0.26139299392700194, Accuracy = 0.915\n",
|
||||
"Loss = 0.26708646774291994, Accuracy = 0.9225\n",
|
||||
"Loss = 0.3667240524291992, Accuracy = 0.8675\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"optimizer = torch.optim.Adam(model.parameters(), lr=2e-5)\n",
|
||||
"\n",
|
||||
"report_freq = 50\n",
|
||||
"iterations = 500 # make this larger to train for longer time!\n",
|
||||
"\n",
|
||||
"model.train()\n",
|
||||
"\n",
|
||||
"i,c = 0,0\n",
|
||||
"acc_loss = 0\n",
|
||||
"acc_acc = 0\n",
|
||||
"\n",
|
||||
"for labels,texts in train_loader:\n",
|
||||
" labels = labels.to(device)-1 # get labels in the range 0-3 \n",
|
||||
" texts = texts.to(device)\n",
|
||||
" loss, out = model(texts, labels=labels)[:2]\n",
|
||||
" labs = out.argmax(dim=1)\n",
|
||||
" acc = torch.mean((labs==labels).type(torch.float32))\n",
|
||||
" optimizer.zero_grad()\n",
|
||||
" loss.backward()\n",
|
||||
" optimizer.step()\n",
|
||||
" acc_loss += loss\n",
|
||||
" acc_acc += acc\n",
|
||||
" i+=1\n",
|
||||
" c+=1\n",
|
||||
" if i%report_freq==0:\n",
|
||||
" print(f\"Loss = {acc_loss.item()/c}, Accuracy = {acc_acc.item()/c}\")\n",
|
||||
" c = 0\n",
|
||||
" acc_loss = 0\n",
|
||||
" acc_acc = 0\n",
|
||||
" iterations-=1\n",
|
||||
" if not iterations:\n",
|
||||
" break"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"BERT ကို အသုံးပြု၍ ခွဲခြားသတ်မှတ်မှုလုပ်ဆောင်ရာတွင် (အထူးသဖြင့် iteration အရေအတွက်ကို တိုးမြှင့်ပြီး အချိန်အတော်ကြာစောင့်ပါက) တော်တော်ကောင်းမွန်သော တိကျမှုရလဒ်ကို ရရှိနိုင်သည်ကို တွေ့နိုင်ပါသည်။ ဒါဟာ BERT သည် ဘာသာစကား၏ ဖွဲ့စည်းပုံကို ရှင်းလင်းစွာ နားလည်ပြီးသားဖြစ်သောကြောင့် ဖြစ်ပြီး၊ ကျွန်ုပ်တို့အနေဖြင့် နောက်ဆုံး classifier ကိုသာ fine-tune လုပ်ရန် လိုအပ်သည်။ သို့သော် BERT သည် အရွယ်အစားကြီးမားသော မော်ဒယ်တစ်ခုဖြစ်သည့်အတွက်၊ လေ့ကျင့်မှု လုပ်ငန်းစဉ်တစ်ခုလုံးသည် အချိန်အတော်ကြာပြီး၊ ကြီးမားသော ကွန်ပျူတာစွမ်းအား (GPU၊ အကောင်းဆုံးအားဖြင့် တစ်ခုထက်ပိုမိုသော GPU) လိုအပ်ပါသည်။\n",
|
||||
"\n",
|
||||
"> **Note:** ကျွန်ုပ်တို့၏ ဥပမာတွင်၊ အရွယ်အစားအငယ်ဆုံးသော pre-trained BERT မော်ဒယ်တစ်ခုကို အသုံးပြုထားပါသည်။ ပိုမိုကောင်းမွန်သော ရလဒ်များကို ရရှိစေနိုင်မည့် အရွယ်အစားကြီးမားသော မော်ဒယ်များလည်း ရှိပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## မော်ဒယ်၏လုပ်ဆောင်မှုကိုအကဲဖြတ်ခြင်း\n",
|
||||
"\n",
|
||||
"အခုတော့ မော်ဒယ်၏လုပ်ဆောင်မှုကို စမ်းသပ်ဒေတာအစုပေါ်မှာ အကဲဖြတ်နိုင်ပါပြီ။ အကဲဖြတ်မှုလုပ်ငန်းစဉ်သည် လေ့ကျင့်မှုလုပ်ငန်းစဉ်နှင့် ဆင်တူပေမယ့် `model.eval()` ကိုခေါ်ပြီး မော်ဒယ်ကို အကဲဖြတ်မှုအနေအထားသို့ ပြောင်းရန် မမေ့ရပါ။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Final accuracy: 0.9047029702970297\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.eval()\n",
|
||||
"iterations = 100\n",
|
||||
"acc = 0\n",
|
||||
"i = 0\n",
|
||||
"for labels,texts in test_loader:\n",
|
||||
" labels = labels.to(device)-1 \n",
|
||||
" texts = texts.to(device)\n",
|
||||
" _, out = model(texts, labels=labels)[:2]\n",
|
||||
" labs = out.argmax(dim=1)\n",
|
||||
" acc += torch.mean((labs==labels).type(torch.float32))\n",
|
||||
" i+=1\n",
|
||||
" if i>iterations: break\n",
|
||||
" \n",
|
||||
"print(f\"Final accuracy: {acc.item()/i}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## အဓိကအချက်\n",
|
||||
"\n",
|
||||
"ဒီယူနစ်မှာ **transformers** စာကြောင်းများကို အသုံးပြုပြီး အလွယ်တကူ သင်ခန်းစာအတွက် စာသားအမျိုးအစား ခွဲခြားမှုလုပ်ဆောင်နိုင်ပုံကို ကြည့်ရှုခဲ့ပါတယ်။ အတူတူပဲ BERT မော်ဒယ်များကို entity extraction, question answering နဲ့ အခြားသော NLP လုပ်ငန်းများအတွက် အသုံးပြုနိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"Transformer မော်ဒယ်များသည် NLP ရှေ့ဆောင်နည်းပညာကို ကိုယ်စားပြုထားပြီး၊ အများဆုံးအခြေအနေများတွင် သင့်ရဲ့ custom NLP ဖြေရှင်းချက်များကို စမ်းသပ်စဉ်မှာ စတင်အသုံးပြုသင့်တဲ့ ပထမဆုံးနည်းလမ်းဖြစ်ပါတယ်။ သို့သော်၊ ဒီ module မှာ ဆွေးနွေးထားတဲ့ recurrent neural networks ရဲ့ အခြေခံအယူအဆများကို နားလည်ထားတာက အဆင့်မြင့် neural မော်ဒယ်များ တည်ဆောက်ချင်တဲ့အခါ အရေးကြီးပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်မှုများတွင် အမှားများ သို့မဟုတ် မတိကျမှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းစာရွက်စာတမ်းကို ၎င်း၏ မူရင်းဘာသာစကားဖြင့် အာဏာတရားရှိသော အရင်းအမြစ်အဖြစ် ရှုလေ့လာသင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူက ဘာသာပြန်မှု ဝန်ဆောင်မှုကို အသုံးပြုရန် အကြံပြုပါသည်။ ဤဘာသာပြန်မှုကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားလွဲမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "py37_pytorch",
|
||||
"language": "python",
|
||||
"name": "conda-env-py37_pytorch-py"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.7.7"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "753865967678a92dbce7d7efbd36d980",
|
||||
"translation_date": "2025-08-30T10:19:52+00:00",
|
||||
"source_file": "lessons/5-NLP/18-Transformers/TransformersPyTorch.ipynb",
|
||||
"language_code": "my"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
@ -0,0 +1,821 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# အာရုံစူးစိုက်မှု မော်ကွန်းများနှင့် Transformer မော်ဒယ်များ\n",
|
||||
"\n",
|
||||
"Recurrent Network (RNN) များ၏ အဓိကအားနည်းချက်တစ်ခုမှာ စာကြောင်းအတွင်းရှိ စကားလုံးအားလုံးသည် ရလဒ်အပေါ် တူညီသော သက်ရောက်မှုရှိနေခြင်းဖြစ်သည်။ ဒီအချက်ကြောင့် Named Entity Recognition (NER) နှင့် Machine Translation (MT) ကဲ့သို့သော စဉ်ဆက်မပြတ်အလုပ်များအတွက် ပုံမှန် LSTM encoder-decoder မော်ဒယ်များတွင် စွမ်းဆောင်ရည်မပြည့်စုံမှု ဖြစ်ပေါ်စေသည်။ အမှန်တကယ်တွင် input စာကြောင်းအတွင်းရှိ စကားလုံးတစ်ချို့သည် အခြားစကားလုံးများထက် sequential output များအပေါ် သက်ရောက်မှုပိုမိုရှိသည်။\n",
|
||||
"\n",
|
||||
"Machine Translation ကဲ့သို့သော sequence-to-sequence မော်ဒယ်ကို စဉ်းစားကြည့်ပါ။ ၎င်းကို recurrent network နှစ်ခုဖြင့် အကောင်အထည်ဖော်ထားပြီး၊ network တစ်ခု (**encoder**) သည် input စာကြောင်းကို hidden state အဖြစ်သို့ ပြောင်းလဲပြီး၊ အခြား network (**decoder**) သည် ထို hidden state ကို ပြန်လည်ဖွင့်လှစ်ကာ ဘာသာပြန်ရလဒ်အဖြစ် ထုတ်ပေးသည်။ ဒီနည်းလမ်း၏ ပြဿနာမှာ network ၏ နောက်ဆုံး state သည် စာကြောင်းအစကို မှတ်မိရန် အခက်အခဲရှိပြီး၊ ဒါကြောင့် ရှည်လျားသော စာကြောင်းများတွင် မော်ဒယ်အရည်အသွေးကျဆင်းစေသည်။\n",
|
||||
"\n",
|
||||
"**အာရုံစူးစိုက်မှု မော်ကွန်းများ** သည် RNN ၏ output များကို ခန့်မှန်းရာတွင် input vector တစ်ခုချင်းစီ၏ context သက်ရောက်မှုကို အလေးပေးနိုင်စေသော နည်းလမ်းတစ်ခုဖြစ်သည်။ ၎င်းကို အကောင်အထည်ဖော်ရာတွင် input RNN ၏ အလယ်အလတ် states များနှင့် output RNN အကြား shortcut များ ဖန်တီးခြင်းဖြင့် ပြုလုပ်သည်။ ဒီနည်းလမ်းဖြင့် output symbol $y_t$ ကို ထုတ်လုပ်စဉ်တွင် input hidden states $h_i$ အားလုံးကို အလေးချိန် coefficient များ $\\alpha_{t,i}$ ဖြင့် သက်ဆိုင်စွာ ထည့်သွင်းစဉ်းစားမည်ဖြစ်သည်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"*Additive attention mechanism ပါဝင်သည့် encoder-decoder မော်ဒယ် ([Bahdanau et al., 2015](https://arxiv.org/pdf/1409.0473.pdf)) ကို [ဒီ blog post](https://lilianweng.github.io/lil-log/2018/06/24/attention-attention.html) မှ ရယူထားသည်*\n",
|
||||
"\n",
|
||||
"Attention matrix $\\{\\alpha_{i,j}\\}$ သည် output စာကြောင်းအတွင်း စကားလုံးတစ်လုံးကို ဖန်တီးရာတွင် သက်ဆိုင်သော input စကားလုံးများ၏ သက်ရောက်မှုအဆင့်ကို ကိုယ်စားပြုသည်။ အောက်တွင် ထို matrix ၏ ဥပမာကို ဖော်ပြထားသည်-\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"*[Bahdanau et al., 2015](https://arxiv.org/pdf/1409.0473.pdf) (Fig.3) မှ ရယူထားသော ပုံ]*\n",
|
||||
"\n",
|
||||
"အာရုံစူးစိုက်မှု မော်ကွန်းများသည် ယနေ့ခေတ် Natural Language Processing (NLP) တွင် အဆင့်မြင့်ဆုံး နည်းလမ်းများ၏ အခြေခံအဖြစ် အရေးပါသည်။ သို့သော် အာရုံစူးစိုက်မှုကို ထည့်သွင်းခြင်းက မော်ဒယ်၏ parameter အရေအတွက်ကို အလွန်များစေပြီး၊ RNN များတွင် scale ပြုလုပ်ရာတွင် ပြဿနာများဖြစ်ပေါ်စေသည်။ RNN မော်ဒယ်များ၏ အဓိက အားနည်းချက်မှာ စဉ်ဆက်မပြတ်သော လုပ်ဆောင်မှုကြောင့် training ကို batch နှင့် parallelize ပြုလုပ်ရန် အခက်အခဲဖြစ်စေခြင်းဖြစ်သည်။ RNN တွင် စဉ်ဆက်မပြတ်သော sequence ၏ အစိတ်အပိုင်းတစ်ခုချင်းစီကို အစဉ်လိုက် လုပ်ဆောင်ရမည်ဖြစ်ပြီး၊ ၎င်းသည် parallelize ပြုလုပ်ရန် မလွယ်ကူစေပါ။\n",
|
||||
"\n",
|
||||
"အာရုံစူးစိုက်မှု မော်ကွန်းများကို အသုံးပြုခြင်းနှင့် RNN မော်ဒယ်များ၏ အကန့်အသတ်ကြောင့် ယနေ့ခေတ်တွင် အသုံးများသော BERT မှ OpenGPT3 အထိ Transformer မော်ဒယ်များကို ဖန်တီးခဲ့သည်။\n",
|
||||
"\n",
|
||||
"## Transformer မော်ဒယ်များ\n",
|
||||
"\n",
|
||||
"Prediction တစ်ခုချင်းစီ၏ context ကို နောက်တစ်ဆင့်သို့ ပို့ပေးခြင်းအစား၊ **Transformer မော်ဒယ်များ** သည် **positional encodings** နှင့် **attention** ကို အသုံးပြုကာ ပေးထားသော စာသား window အတွင်းရှိ context ကို ဖမ်းဆီးသည်။ အောက်ပါပုံသည် positional encodings နှင့် attention ကို အသုံးပြု၍ context ကို window အတွင်း ဖမ်းဆီးပုံကို ဖော်ပြထားသည်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"Input position တစ်ခုချင်းစီကို Output position တစ်ခုချင်းစီနှင့် လွတ်လပ်စွာ mapping ပြုလုပ်နိုင်သောကြောင့် Transformer မော်ဒယ်များသည် RNN မော်ဒယ်များထက် ပိုမို parallelize ပြုလုပ်နိုင်ပြီး၊ ပိုမိုကြီးမားပြီး အထိရောက်ဆုံးသော ဘာသာစကားမော်ဒယ်များကို ဖန်တီးနိုင်စေသည်။ Attention head တစ်ခုချင်းစီသည် စကားလုံးများအကြား ဆက်စပ်မှုများကို သင်ယူရန် အသုံးပြုနိုင်ပြီး၊ ၎င်းသည် Natural Language Processing (NLP) အလုပ်များတွင် ပိုမိုကောင်းမွန်စေသည်။\n",
|
||||
"\n",
|
||||
"## ရိုးရှင်းသော Transformer မော်ဒယ် တည်ဆောက်ခြင်း\n",
|
||||
"\n",
|
||||
"Keras တွင် built-in Transformer layer မပါဝင်သော်လည်း၊ ကိုယ်တိုင် တည်ဆောက်နိုင်သည်။ ယခင်ကဲ့သို့ AG News dataset ကို အသုံးပြု၍ စာသားအမျိုးအစားခွဲခြားမှုအပေါ် အာရုံစိုက်မည်ဖြစ်သော်လည်း၊ Transformer မော်ဒယ်များသည် ပိုမိုခက်ခဲသော NLP အလုပ်များတွင် အကောင်းဆုံးရလဒ်များကို ပြသသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import tensorflow as tf\n",
|
||||
"from tensorflow import keras\n",
|
||||
"import tensorflow_datasets as tfds\n",
|
||||
"import numpy as np\n",
|
||||
"\n",
|
||||
"ds_train, ds_test = tfds.load('ag_news_subset').values()\n",
|
||||
"\n",
|
||||
"def extract_text(x):\n",
|
||||
" return x['title']+' '+x['description']\n",
|
||||
"\n",
|
||||
"def tupelize(x):\n",
|
||||
" return (extract_text(x),x['label'])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Keras တွင် layer အသစ်များသည် `Layer` class ကို subclass လုပ်ရမည်ဖြစ်ပြီး `call` method ကို implement လုပ်ရမည်။ **Positional Embedding** layer ဖြင့် စတင်ကြမည်။ [Keras documentation မှ code အချို့](https://keras.io/examples/nlp/text_classification_with_transformer/) ကို အသုံးပြုမည်။ input sequences အားလုံးကို `maxlen` အရှည်သို့ pad လုပ်ထားသည်ဟု ချက်ချင်းယူဆမည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class TokenAndPositionEmbedding(keras.layers.Layer):\n",
|
||||
" def __init__(self, maxlen, vocab_size, embed_dim):\n",
|
||||
" super(TokenAndPositionEmbedding, self).__init__()\n",
|
||||
" self.token_emb = keras.layers.Embedding(input_dim=vocab_size, output_dim=embed_dim)\n",
|
||||
" self.pos_emb = keras.layers.Embedding(input_dim=maxlen, output_dim=embed_dim)\n",
|
||||
" self.maxlen = maxlen\n",
|
||||
"\n",
|
||||
" def call(self, x):\n",
|
||||
" maxlen = self.maxlen\n",
|
||||
" positions = tf.range(start=0, limit=maxlen, delta=1)\n",
|
||||
" positions = self.pos_emb(positions)\n",
|
||||
" x = self.token_emb(x)\n",
|
||||
" return x+positions"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ဤအလွှာတွင် `Embedding` အလွှာနှစ်ခုပါဝင်သည်။ Token များကို embed လုပ်ရန်အတွက် (ယခင်ကဆွေးနွေးခဲ့သည့်နည်းလမ်းဖြင့်) နှင့် token ရဲ့နေရာများကို embed လုပ်ရန်အတွက်ဖြစ်သည်။ Token ရဲ့နေရာများကို `tf.range` ကိုအသုံးပြုပြီး 0 မှ `maxlen` အထိ သဘာဝကိန်းဂဏန်းများအဖြစ်ဖန်တီးပြီးနောက် `Embedding` အလွှာထဲသို့ပို့သည်။ ထိုအလွှာမှထွက်လာသော embedding vectors နှစ်ခုကိုပေါင်းပြီး `maxlen`$\\times$`embed_dim` ပုံစံရှိသော input ၏နေရာအခြေပြု representation ကိုဖန်တီးသည်။\n",
|
||||
"\n",
|
||||
"အခုတော့ transformer block ကို implement လုပ်ကြမယ်။ ဒါဟာ ယခင်ဖော်ပြထားတဲ့ embedding layer ရဲ့ output ကိုယူပါမယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class TransformerBlock(keras.layers.Layer):\n",
|
||||
" def __init__(self, embed_dim, num_heads, ff_dim, rate=0.1):\n",
|
||||
" super(TransformerBlock, self).__init__()\n",
|
||||
" self.att = keras.layers.MultiHeadAttention(num_heads=num_heads, key_dim=embed_dim, name='attn')\n",
|
||||
" self.ffn = keras.Sequential(\n",
|
||||
" [keras.layers.Dense(ff_dim, activation=\"relu\"), keras.layers.Dense(embed_dim),]\n",
|
||||
" )\n",
|
||||
" self.layernorm1 = keras.layers.LayerNormalization(epsilon=1e-6)\n",
|
||||
" self.layernorm2 = keras.layers.LayerNormalization(epsilon=1e-6)\n",
|
||||
" self.dropout1 = keras.layers.Dropout(rate)\n",
|
||||
" self.dropout2 = keras.layers.Dropout(rate)\n",
|
||||
"\n",
|
||||
" def call(self, inputs, training):\n",
|
||||
" attn_output = self.att(inputs, inputs)\n",
|
||||
" attn_output = self.dropout1(attn_output, training=training)\n",
|
||||
" out1 = self.layernorm1(inputs + attn_output)\n",
|
||||
" ffn_output = self.ffn(out1)\n",
|
||||
" ffn_output = self.dropout2(ffn_output, training=training)\n",
|
||||
" return self.layernorm2(out1 + ffn_output)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အခုတော့ အပြည့်အစုံသော transformer မော်ဒယ်ကို သတ်မှတ်ဖို့ အဆင်သင့်ဖြစ်ပါပြီ:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"sequential_1\"\n",
|
||||
"_________________________________________________________________\n",
|
||||
"Layer (type) Output Shape Param # \n",
|
||||
"=================================================================\n",
|
||||
"text_vectorization (TextVect (None, 256) 0 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"token_and_position_embedding (None, 256, 32) 648192 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"transformer_block (Transform (None, 256, 32) 10656 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"global_average_pooling1d (Gl (None, 32) 0 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"dropout_2 (Dropout) (None, 32) 0 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"dense_2 (Dense) (None, 20) 660 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"dropout_3 (Dropout) (None, 20) 0 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"dense_3 (Dense) (None, 4) 84 \n",
|
||||
"=================================================================\n",
|
||||
"Total params: 659,592\n",
|
||||
"Trainable params: 659,592\n",
|
||||
"Non-trainable params: 0\n",
|
||||
"_________________________________________________________________\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"embed_dim = 32 # Embedding size for each token\n",
|
||||
"num_heads = 2 # Number of attention heads\n",
|
||||
"ff_dim = 32 # Hidden layer size in feed forward network inside transformer\n",
|
||||
"maxlen = 256\n",
|
||||
"vocab_size = 20000\n",
|
||||
"\n",
|
||||
"model = keras.models.Sequential([\n",
|
||||
" keras.layers.experimental.preprocessing.TextVectorization(max_tokens=vocab_size,output_sequence_length=maxlen, input_shape=(1,)),\n",
|
||||
" TokenAndPositionEmbedding(maxlen, vocab_size, embed_dim),\n",
|
||||
" TransformerBlock(embed_dim, num_heads, ff_dim),\n",
|
||||
" keras.layers.GlobalAveragePooling1D(),\n",
|
||||
" keras.layers.Dropout(0.1),\n",
|
||||
" keras.layers.Dense(20, activation=\"relu\"),\n",
|
||||
" keras.layers.Dropout(0.1),\n",
|
||||
" keras.layers.Dense(4, activation=\"softmax\")\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"model.summary()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Training tokenizer\n",
|
||||
"938/938 [==============================] - 45s 39ms/step - loss: 0.4978 - acc: 0.8068 - val_loss: 0.2808 - val_acc: 0.9124\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7f9c2427a0d0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"print('Training tokenizer')\n",
|
||||
"model.layers[0].adapt(ds_train.map(extract_text))\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(128),validation_data=ds_test.map(tupelize).batch(128))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## BERT Transformer Models\n",
|
||||
"\n",
|
||||
"**BERT** (Bidirectional Encoder Representations from Transformers) သည် *BERT-base* အတွက် အလွှာ 12 လွှာနှင့် *BERT-large* အတွက် အလွှာ 24 လွှာပါဝင်သော အလွန်ကြီးမားသော multi-layer transformer network တစ်ခုဖြစ်သည်။ ဤမော်ဒယ်ကို ပထမဦးစွာ အကြီးမားသော စာသားဒေတာများ (WikiPedia + စာအုပ်များ) ကို အသုံးပြု၍ unsupervised training (ဝါကျအတွင်းရှိ masked စကားလုံးများကို ခန့်မှန်းခြင်း) ဖြင့် pre-training ပြုလုပ်သည်။ Pre-training လုပ်စဉ်အတွင်း မော်ဒယ်သည် ဘာသာစကားနားလည်မှုအဆင့်အတန်းများကို အလွန်အမင်း စွမ်းဆောင်နိုင်စွမ်း ရရှိလာပြီး၊ ထို့နောက် အခြားသောဒေတာများနှင့်အတူ fine tuning ဖြင့် အသုံးချနိုင်သည်။ ဤလုပ်ငန်းစဉ်ကို **transfer learning** ဟုခေါ်သည်။\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"BERT, DistilBERT, BigBird, OpenGPT3 စသည်တို့အပါအဝင် Transformer architecture များ၏ အမျိုးအစားများစွာရှိပြီး၊ ထိုမော်ဒယ်များကို fine tuning ပြုလုပ်နိုင်သည်။\n",
|
||||
"\n",
|
||||
"ယခု pre-trained BERT မော်ဒယ်ကို အသုံးပြု၍ ကျွန်ုပ်တို့၏ ရိုးရာ sequence classification ပြဿနာကို ဖြေရှင်းနိုင်ပုံကို ကြည့်ကြမည်။ [တရားဝင်စာရွက်စာတမ်း](https://www.tensorflow.org/text/tutorials/classify_text_with_bert) မှ အကြံဉာဏ်နှင့် အချို့သောကုဒ်များကို ချေးယူမည်။\n",
|
||||
"\n",
|
||||
"Pre-trained မော်ဒယ်များကို load ပြုလုပ်ရန် **Tensorflow hub** ကို အသုံးပြုမည်။ ပထမဦးစွာ BERT-specific vectorizer ကို load ပြုလုပ်ကြစို့:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "ModuleNotFoundError",
|
||||
"evalue": "No module named 'tensorflow_text'",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
|
||||
"\u001b[1;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)",
|
||||
"\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_41180/4216669875.py\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mimport\u001b[0m \u001b[0mtensorflow_text\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 2\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mtensorflow_hub\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mhub\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[0mvectorizer\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mhub\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mKerasLayer\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
|
||||
"\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'tensorflow_text'"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import tensorflow_text \n",
|
||||
"import tensorflow_hub as hub\n",
|
||||
"vectorizer = hub.KerasLayer('https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'input_type_ids': <tf.Tensor: shape=(1, 128), dtype=int32, numpy=\n",
|
||||
" array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],\n",
|
||||
" dtype=int32)>,\n",
|
||||
" 'input_word_ids': <tf.Tensor: shape=(1, 128), dtype=int32, numpy=\n",
|
||||
" array([[ 101, 1045, 2293, 19081, 102, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0]], dtype=int32)>,\n",
|
||||
" 'input_mask': <tf.Tensor: shape=(1, 128), dtype=int32, numpy=\n",
|
||||
" array([[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
|
||||
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],\n",
|
||||
" dtype=int32)>}"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vectorizer(['I love transformers'])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"မူရင်း network ကို သင်ကြားခဲ့သော vectorizer ကိုပဲ အသုံးပြုရမည်ဟု အရေးကြီးပါသည်။ ထို့အပြင် BERT vectorizer သည် အောက်ပါ component သုံးခုကို ပြန်ပေးသည် -\n",
|
||||
"\n",
|
||||
"* `input_word_ids` - input စာကြောင်းအတွက် token နံပါတ်များ၏ အစီအစဉ်\n",
|
||||
"* `input_mask` - အစီအစဉ်၏ ဘယ်အပိုင်းသည် အမှန်တကယ် input ပါဝင်သည်ကို ပြသပြီး ဘယ်အပိုင်းသည် padding ဖြစ်သည်ကို ပြသသည်။ ၎င်းသည် `Masking` layer မှ ထုတ်လုပ်သော mask နှင့် ဆင်တူသည်။\n",
|
||||
"* `input_type_ids` - ဘာသာစကား မော်ဒယ်လုပ်ငန်းများအတွက် အသုံးပြုပြီး အစီအစဉ်တစ်ခုတွင် input စာကြောင်းနှစ်ခုကို သတ်မှတ်ရန် ခွင့်ပြုသည်။\n",
|
||||
"\n",
|
||||
"ထို့နောက် BERT feature extractor ကို အောက်ပါအတိုင်း instantiate လုပ်နိုင်ပါသည် -\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"bert = hub.KerasLayer('https://tfhub.dev/tensorflow/small_bert/bert_en_uncased_L-4_H-128_A-2/1')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"pooled_output -> (1, 128)\n",
|
||||
"encoder_outputs -> 4\n",
|
||||
"sequence_output -> (1, 128, 128)\n",
|
||||
"default -> (1, 128)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"z = bert(vectorizer(['I love transformers']))\n",
|
||||
"for i,x in z.items():\n",
|
||||
" print(f\"{i} -> { len(x) if isinstance(x, list) else x.shape }\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"BERT layer သည် အောက်ပါ အသုံးဝင်သော ရလဒ်များကို ပြန်ပေးသည် -\n",
|
||||
"\n",
|
||||
"* `pooled_output` သည် sequence အတွင်းရှိ token အားလုံးကို ပျမ်းမျှတွက်ချက်ထားသော ရလဒ်ဖြစ်သည်။ ၎င်းကို network တစ်ခုလုံး၏ အဓိပ္ပါယ်ဆိုင်ရာ embedding အဖြစ် သတ်မှတ်နိုင်သည်။ ၎င်းသည် ယခင်မော်ဒယ်တွင် အသုံးပြုခဲ့သော `GlobalAveragePooling1D` layer ၏ output နှင့် တူညီသည်။\n",
|
||||
"* `sequence_output` သည် နောက်ဆုံး transformer layer ၏ output ဖြစ်သည် (၎င်းသည် အထက်တွင် ဖော်ပြထားသော မော်ဒယ်အတွင်း `TransformerBlock` ၏ output နှင့် ကိုက်ညီသည်)။\n",
|
||||
"* `encoder_outputs` သည် transformer layer အားလုံး၏ output များဖြစ်သည်။ ၎င်းတွင် 4-layer BERT မော်ဒယ်ကို load လုပ်ထားသောကြောင့် (အမည်တွင် `4_H` ပါဝင်နေသည်ကို သင်ခန့်မှန်းနိုင်သည်ဟု ထင်ပါသည်)၊ ၎င်းတွင် tensor 4 ခု ပါဝင်သည်။ နောက်ဆုံး tensor သည် `sequence_output` နှင့် တူညီသည်။\n",
|
||||
"\n",
|
||||
"ယခုတွင် end-to-end classification မော်ဒယ်ကို သတ်မှတ်မည်ဖြစ်သည်။ *functional model definition* ကို အသုံးပြုမည်ဖြစ်ပြီး၊ မော်ဒယ် input ကို သတ်မှတ်ပြီးနောက်၊ output ကိုတွက်ချက်ရန် expression များစဉ်ဆက်ပေးသွားမည်ဖြစ်သည်။ ထို့အပြင် BERT မော်ဒယ်၏ weight များကို train မလုပ်ဘဲ၊ နောက်ဆုံး classifier ကိုသာ train လုပ်မည် - \n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"model\"\n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"Layer (type) Output Shape Param # Connected to \n",
|
||||
"==================================================================================================\n",
|
||||
"input_1 (InputLayer) [(None,)] 0 \n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"keras_layer (KerasLayer) {'input_type_ids': ( 0 input_1[0][0] \n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"keras_layer_1 (KerasLayer) {'pooled_output': (N 4782465 keras_layer[0][0] \n",
|
||||
" keras_layer[0][1] \n",
|
||||
" keras_layer[0][2] \n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"dropout_4 (Dropout) (None, 128) 0 keras_layer_1[0][5] \n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"dense_4 (Dense) (None, 4) 516 dropout_4[0][0] \n",
|
||||
"==================================================================================================\n",
|
||||
"Total params: 4,782,981\n",
|
||||
"Trainable params: 516\n",
|
||||
"Non-trainable params: 4,782,465\n",
|
||||
"__________________________________________________________________________________________________\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"inp = keras.Input(shape=(),dtype=tf.string)\n",
|
||||
"x = vectorizer(inp)\n",
|
||||
"x = bert(x)\n",
|
||||
"x = keras.layers.Dropout(0.1)(x['pooled_output'])\n",
|
||||
"out = keras.layers.Dense(4,activation='softmax')(x)\n",
|
||||
"model = keras.models.Model(inp,out)\n",
|
||||
"bert.trainable = False\n",
|
||||
"model.summary()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"938/938 [==============================] - 528s 559ms/step - loss: 0.8056 - acc: 0.6983 - val_loss: 0.5953 - val_acc: 0.7888\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7f9bb1e36d00>"
|
||||
]
|
||||
},
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer='adam')\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(128),validation_data=ds_test.map(tupelize).batch(128))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"သင်ကြားနိုင်သော parameters အနည်းငယ်သာရှိသော်လည်း၊ BERT feature extractor သည် တွက်ချက်မှုအလွန်လေးလံသောကြောင့် လုပ်ငန်းစဉ်သည် အတော်လေးနှေးကွေးနေပါသည်။ သင်ကြားမှုမလုံလောက်ခြင်း သို့မဟုတ် မော်ဒယ် parameters မလုံလောက်ခြင်းကြောင့် ကျွန်ုပ်တို့သည် သင့်လျော်သောတိကျမှန်ကန်မှုကို မရရှိနိုင်ခဲ့သကဲ့သို့ပင် ထင်ရပါသည်။\n",
|
||||
"\n",
|
||||
"ယခု BERT weights ကို အခဲဖြေပြီး၊ ထိုအတူတူ သင်ကြားကြည့်ပါစို့။ ဤအရာသည် အလွန်သေးငယ်သော learning rate တစ်ခုလိုအပ်ပြီး၊ **warmup** နှင့်အတူ **AdamW** optimizer ကို အသုံးပြု၍ သေချာစွာ သင်ကြားမှုမဟာဗျူဟာကိုလည်းလိုအပ်ပါသည်။ Optimizer ကို ဖန်တီးရန် `tf-models-official` package ကို အသုံးပြုမည်ဖြစ်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"model\"\n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"Layer (type) Output Shape Param # Connected to \n",
|
||||
"==================================================================================================\n",
|
||||
"input_1 (InputLayer) [(None,)] 0 \n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"keras_layer (KerasLayer) {'input_type_ids': ( 0 input_1[0][0] \n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"keras_layer_1 (KerasLayer) {'pooled_output': (N 4782465 keras_layer[0][0] \n",
|
||||
" keras_layer[0][1] \n",
|
||||
" keras_layer[0][2] \n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"dropout_4 (Dropout) (None, 128) 0 keras_layer_1[0][5] \n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"dense_4 (Dense) (None, 4) 516 dropout_4[0][0] \n",
|
||||
"==================================================================================================\n",
|
||||
"Total params: 4,782,981\n",
|
||||
"Trainable params: 4,782,980\n",
|
||||
"Non-trainable params: 1\n",
|
||||
"__________________________________________________________________________________________________\n",
|
||||
"938/938 [==============================] - 629s 664ms/step - loss: 0.6344 - acc: 0.7658 - val_loss: 0.4876 - val_acc: 0.8247\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7f9bb0bd0070>"
|
||||
]
|
||||
},
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from official.nlp import optimization \n",
|
||||
"bert.trainable=True\n",
|
||||
"model.summary()\n",
|
||||
"epochs = 3\n",
|
||||
"opt = optimization.create_optimizer(\n",
|
||||
" init_lr=3e-5,\n",
|
||||
" num_train_steps=epochs*len(ds_train),\n",
|
||||
" num_warmup_steps=0.1*epochs*len(ds_train),\n",
|
||||
" optimizer_type='adamw')\n",
|
||||
"\n",
|
||||
"model.compile(loss='sparse_categorical_crossentropy',metrics=['acc'], optimizer=opt)\n",
|
||||
"model.fit(ds_train.map(tupelize).batch(128),validation_data=ds_test.map(tupelize).batch(128))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"သင်မြင်နိုင်သည့်အတိုင်း၊ သင်တန်းပေးခြင်းသည် အတော်လေးနှေးကွေးသည် - သို့သော် သင်မတိုင်မီ အသုံးပြုပြီး မော်ဒယ်ကို အနည်းဆုံး ၅-၁၀ အကြိမ် (epochs) သင်ကြားကြည့်ပြီး ယခင်တွင် အသုံးပြုခဲ့သော နည်းလမ်းများနှင့် နှိုင်းယှဉ်၍ အကောင်းဆုံးရလဒ်ရနိုင်မလား စမ်းသပ်ကြည့်လိုနိုင်သည်။\n",
|
||||
"\n",
|
||||
"## Huggingface Transformers Library\n",
|
||||
"\n",
|
||||
"Transformer မော်ဒယ်များကို အသုံးပြုရန် အလွန်ရိုးရှင်းပြီး လူသိများသော နည်းလမ်းတစ်ခုမှာ [HuggingFace package](https://github.com/huggingface/) ဖြစ်ပြီး၊ ၎င်းသည် အမျိုးမျိုးသော သဘာဝဘာသာစကားလုပ်ငန်းများ (NLP tasks) အတွက် ရိုးရှင်းသော အဆောက်အအုံများကို ပံ့ပိုးပေးသည်။ ၎င်းကို Tensorflow နှင့် PyTorch (နောက်ထပ် လူကြိုက်များသော နယူးရယ်နက်ဝက်ဖရိမ်းဝေါ့ခ်) နှစ်ခုစလုံးအတွက် အသုံးပြုနိုင်သည်။\n",
|
||||
"\n",
|
||||
"> **Note**: သင် Transformers library အလုပ်လုပ်ပုံကို မကြည့်လိုပါက - ဒီ notebook ၏ အဆုံးသို့ ကျော်သွားနိုင်သည်၊ အကြောင်းမှာ ယခင်တွင် ကျွန်ုပ်တို့ ပြုလုပ်ခဲ့သည့်အရာများနှင့် မတူညီသော အဓိကအချက်များ မတွေ့ရလိမ့်မည်။ ကျွန်ုပ်တို့သည် BERT မော်ဒယ်ကို သင်ကြားခြင်းအဆင့်များကို ထပ်မံလုပ်ဆောင်မည်ဖြစ်ပြီး၊ ကွဲပြားသော library နှင့် အလွန်ကြီးမားသော မော်ဒယ်ကို အသုံးပြုမည်ဖြစ်သည်။ ထို့ကြောင့်၊ ၎င်းလုပ်ငန်းစဉ်တွင် အတော်လေးကြာမြင့်သော သင်ကြားမှုများ ပါဝင်မည်ဖြစ်ပြီး၊ သင်သည် ကုဒ်ကိုသာ ကြည့်ရှုလိုနိုင်သည်။ \n",
|
||||
"\n",
|
||||
"အခုတော့ [Huggingface Transformers](http://huggingface.co) ကို အသုံးပြု၍ ကျွန်ုပ်တို့၏ ပြဿနာကို မည်သို့ ဖြေရှင်းနိုင်မည်ကို ကြည့်ကြရအောင်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ပထမဆုံး ကျွန်တော်တို့ အသုံးပြုမယ့် မော်ဒယ်ကို ရွေးချယ်ဖို့ လိုအပ်ပါတယ်။ Built-in မော်ဒယ်အချို့အပြင် Huggingface မှာ [အွန်လိုင်းမော်ဒယ်ရေပိုစစ်](https://huggingface.co/models) ရှိပြီး၊ အဲဒီမှာ community က ပြင်ဆင်ပြီးသား မော်ဒယ်များစွာကို ရှာဖွေတွေ့ရှိနိုင်ပါတယ်။ အဲဒီမော်ဒယ်တွေကို မော်ဒယ်နာမည်ပေးရုံနဲ့ load လုပ်ပြီး အသုံးပြုနိုင်ပါတယ်။ မော်ဒယ်အတွက် လိုအပ်တဲ့ binary ဖိုင်တွေကို အလိုအလျောက် download လုပ်ပေးပါမယ်။\n",
|
||||
"\n",
|
||||
"တစ်ချို့အချိန်တွေမှာ ကိုယ်ပိုင်မော်ဒယ်တွေကို load လုပ်ဖို့ လိုအပ်နိုင်ပါတယ်၊ အဲဒီအခါမှာ tokenizer အတွက် parameters, `config.json` ဖိုင် (မော်ဒယ် parameters ပါဝင်တဲ့), binary weights စတဲ့ လိုအပ်တဲ့ ဖိုင်တွေပါဝင်တဲ့ directory ကို သတ်မှတ်ပေးနိုင်ပါတယ်။\n",
|
||||
"\n",
|
||||
"မော်ဒယ်နာမည်ကနေ မော်ဒယ်နဲ့ tokenizer နှစ်ခုလုံးကို instantiate လုပ်နိုင်ပါတယ်။ အရင်ဆုံး tokenizer နဲ့ စလိုက်ကြမယ်:\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import transformers\n",
|
||||
"\n",
|
||||
"# To load the model from Internet repository using model name. \n",
|
||||
"# Use this if you are running from your own copy of the notebooks\n",
|
||||
"bert_model = 'bert-base-uncased' \n",
|
||||
"\n",
|
||||
"# To load the model from the directory on disk. Use this for Microsoft Learn module, because we have\n",
|
||||
"# prepared all required files for you.\n",
|
||||
"#bert_model = './bert'\n",
|
||||
"\n",
|
||||
"tokenizer = transformers.BertTokenizer.from_pretrained(bert_model)\n",
|
||||
"\n",
|
||||
"MAX_SEQ_LEN = 128\n",
|
||||
"PAD_INDEX = tokenizer.convert_tokens_to_ids(tokenizer.pad_token)\n",
|
||||
"UNK_INDEX = tokenizer.convert_tokens_to_ids(tokenizer.unk_token)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"`tokenizer` အရာဝတ္ထုတွင် `encode` အလုပ်ဆောင်မှုပါရှိပြီး၊ စာသားကိုတိုက်ရိုက် encode လုပ်ရန်အသုံးပြုနိုင်သည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[101, 23435, 12314, 2003, 1037, 2307, 7705, 2005, 17953, 2361, 102]"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"tokenizer.encode('Tensorflow is a great framework for NLP')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်ုပ်တို့သည် tokenizer ကို အသုံးပြု၍ `token_ids`, `input_mask` fields စသည်တို့ကို အပါအဝင် မော်ဒယ်သို့ ပေးပို့ရန် သင့်လျော်သော နည်းလမ်းဖြင့် အစီအစဉ်တစ်ခုကို encode လုပ်နိုင်ပါသည်။ ထို့အပြင် `return_tensors='tf'` argument ကို ပေးသွင်းခြင်းဖြင့် Tensorflow tensors ကို ရယူလိုကြောင်း သတ်မှတ်နိုင်ပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'input_ids': <tf.Tensor: shape=(1, 5), dtype=int32, numpy=array([[ 101, 7592, 1010, 2045, 102]], dtype=int32)>, 'token_type_ids': <tf.Tensor: shape=(1, 5), dtype=int32, numpy=array([[0, 0, 0, 0, 0]], dtype=int32)>, 'attention_mask': <tf.Tensor: shape=(1, 5), dtype=int32, numpy=array([[1, 1, 1, 1, 1]], dtype=int32)>}"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"tokenizer(['Hello, there'],return_tensors='tf')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ကျွန်တော်တို့အနေဖြင့် `bert-base-uncased` ဟုခေါ်သော pre-trained BERT မော်ဒယ်ကို အသုံးပြုမည်ဖြစ်သည်။ *Uncased* ဆိုသည်မှာ မော်ဒယ်သည် အကြောင်းအရာအထိခိုက်မှုမရှိကြောင်းကို ဖော်ပြသည်။\n",
|
||||
"\n",
|
||||
"မော်ဒယ်ကို လေ့ကျင့်စဉ်တွင် tokenized sequence ကို input အဖြစ်ပေးရန်လိုအပ်ပြီး၊ ထို့ကြောင့် data processing pipeline ကို ဒီဇိုင်းဆွဲမည်ဖြစ်သည်။ `tokenizer.encode` သည် Python function ဖြစ်သောကြောင့်၊ နောက်ဆုံးယူနစ်တွင် အသုံးပြုခဲ့သည့်နည်းလမ်းတူပင် `py_function` ကို ခေါ်သုံး၍ အသုံးပြုမည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 31,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def process(x):\n",
|
||||
" return tokenizer.encode(x.numpy().decode('utf-8'),return_tensors='tf',padding='max_length',max_length=MAX_SEQ_LEN,truncation=True)[0]\n",
|
||||
"\n",
|
||||
"def process_fn(x):\n",
|
||||
" s = x['title']+' '+x['description']\n",
|
||||
" e = tf.py_function(process,inp=[s],Tout=(tf.int32))\n",
|
||||
" e.set_shape(MAX_SEQ_LEN)\n",
|
||||
" return e,x['label']"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အခုတော့ `BertForSequenceClassification` ပက်ကေ့ဂျ်ကို အသုံးပြုပြီး အမှန်တကယ်မော်ဒယ်ကို load လုပ်နိုင်ပါပြီ။ ဒါဟာ classification အတွက် လိုအပ်တဲ့ architecture ကို မော်ဒယ်မှာ ရှိပြီးသားဖြစ်စေပြီး၊ final classifier ကိုပါ ထည့်သွင်းပေးထားပါတယ်။ သင်တွေ့ရမယ့် warning message က final classifier ရဲ့ weight တွေ initialize မလုပ်ထားသေးတာနဲ့ မော်ဒယ်ကို pre-training လိုအပ်တယ်ဆိုတာကို ပြောပါလိမ့်မယ် - ဒါက အဆင်ပြေပါတယ်၊ အကြောင်းကတော့ အခုလိုလုပ်ဖို့ပဲ ကျွန်တော်တို့လုပ်နေတဲ့အရာဖြစ်လို့ပါ!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 32,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"model = transformers.TFBertForSequenceClassification.from_pretrained(bert_model,num_labels=4,output_attentions=False)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 33,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"tf_bert_for_sequence_classification_1\"\n",
|
||||
"_________________________________________________________________\n",
|
||||
"Layer (type) Output Shape Param # \n",
|
||||
"=================================================================\n",
|
||||
"bert (TFBertMainLayer) multiple 109482240 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"dropout_75 (Dropout) multiple 0 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"classifier (Dense) multiple 3076 \n",
|
||||
"=================================================================\n",
|
||||
"Total params: 109,485,316\n",
|
||||
"Trainable params: 109,485,316\n",
|
||||
"Non-trainable params: 0\n",
|
||||
"_________________________________________________________________\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.summary()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"`summary()` မှာမြင်နိုင်သည့်အတိုင်း၊ အဆိုပါမော်ဒယ်တွင် ၁၁၀ သန်းနီးပါးသော parameters ပါဝင်ပါတယ်! သဘောတရားအားဖြင့်၊ သေးငယ်သော dataset ပေါ်တွင် ရိုးရှင်းသော classification task လုပ်ဆောင်လိုပါက BERT base layer ကို training မလုပ်ချင်ပါ။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 34,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Model: \"tf_bert_for_sequence_classification_1\"\n",
|
||||
"_________________________________________________________________\n",
|
||||
"Layer (type) Output Shape Param # \n",
|
||||
"=================================================================\n",
|
||||
"bert (TFBertMainLayer) multiple 109482240 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"dropout_75 (Dropout) multiple 0 \n",
|
||||
"_________________________________________________________________\n",
|
||||
"classifier (Dense) multiple 3076 \n",
|
||||
"=================================================================\n",
|
||||
"Total params: 109,485,316\n",
|
||||
"Trainable params: 3,076\n",
|
||||
"Non-trainable params: 109,482,240\n",
|
||||
"_________________________________________________________________\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.layers[0].trainable = False\n",
|
||||
"model.summary()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"ယခု ကျွန်ုပ်တို့ သင်ကြားမှုကို စတင်ရန် အဆင်သင့်ဖြစ်ပါပြီ!\n",
|
||||
"\n",
|
||||
"> **Note**: အပြည့်အဝ BERT မော်ဒယ်ကို သင်ကြားခြင်းသည် အချိန်အလွန်များစွာ လိုအပ်နိုင်ပါသည်! ထို့ကြောင့် ကျွန်ုပ်တို့သည် ပထမ 32 batches အတွက်သာ သင်ကြားမည်ဖြစ်သည်။ ဤသည်မှာ မော်ဒယ်သင်ကြားမှုကို စီစဉ်ပုံကို ပြသရန်သာ ဖြစ်သည်။ အပြည့်အဝ သင်ကြားမှုကို စမ်းသပ်လိုပါက - `steps_per_epoch` နှင့် `validation_steps` parameters ကို ဖယ်ရှားပြီး စောင့်ဆိုင်းရန် ပြင်ဆင်ပါ!\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 30,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"32/32 [==============================] - 142s 4s/step - loss: 1.3896 - acc: 0.2500 - val_loss: 1.3863 - val_acc: 0.2480\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<tensorflow.python.keras.callbacks.History at 0x7f1d40a4b6a0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 30,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.compile('adam','sparse_categorical_crossentropy',['acc'])\n",
|
||||
"tf.get_logger().setLevel('ERROR')\n",
|
||||
"model.fit(ds_train.map(process_fn).batch(32),validation_data=ds_test.map(process_fn).batch(32),steps_per_epoch=32,validation_steps=2)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"အကယ်၍ သင် iteration အရေအတွက်ကို တိုးမြှင့်ပြီး အချိန်လုံလုံလောက်လောက်စောင့်ပြီး၊ epoch အတော်များများအထိ လေ့ကျင့်ပါက BERT classification က အကောင်းဆုံးတိကျမှန်ကန်မှုကို ပေးနိုင်မယ်လို့ မျှော်လင့်နိုင်ပါတယ်! အကြောင်းကတော့ BERT ဟာ ဘာသာစကား၏ ဖွဲ့စည်းပုံကို အတော်လေး နားလည်ပြီးသားဖြစ်ပြီး၊ နောက်ဆုံး classifier ကို fine-tune လုပ်ရုံသာ လိုအပ်လို့ပါ။ သို့သော် BERT ဟာ မော်ဒယ်ကြီးတစ်ခုဖြစ်တဲ့အတွက် လေ့ကျင့်မှု အပြည့်အစုံလုပ်ရတဲ့ အချိန်က အတော်ကြာပြီး၊ အတော်လေး အားကောင်းတဲ့ ကွန်ပျူတာစွမ်းအား (GPU၊ အထူးသဖြင့် တစ်ခုထက်ပိုများ) လိုအပ်ပါတယ်။\n",
|
||||
"\n",
|
||||
"> **Note:** ဥပမာအနေနဲ့ ကျွန်တော်တို့ အသုံးပြုနေတဲ့ မော်ဒယ်က BERT pre-trained မော်ဒယ်တွေထဲက အငယ်ဆုံးတစ်ခုဖြစ်ပါတယ်။ ပိုကြီးတဲ့ မော်ဒယ်တွေက ပိုမိုကောင်းမွန်တဲ့ ရလဒ်တွေကို ပေးနိုင်ဖို့ အလားအလာရှိပါတယ်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## အဓိကအချက်\n",
|
||||
"\n",
|
||||
"ဤယူနစ်တွင် **transformers** အခြေခံထားသော နောက်ဆုံးပေါ်မော်ဒယ်ဖွဲ့စည်းမှုများကို ကြည့်ရှုခဲ့ပါသည်။ ကျွန်ုပ်တို့၏စာသားအမျိုးအစားခွဲခြားမှုအလုပ်တွင် ထိုမော်ဒယ်များကို အသုံးပြုခဲ့ပြီး၊ BERT မော်ဒယ်များကို entity extraction, question answering နှင့် အခြားသော NLP အလုပ်များတွင်လည်း တူညီသည့်ပုံစံဖြင့် အသုံးပြုနိုင်ပါသည်။\n",
|
||||
"\n",
|
||||
"Transformer မော်ဒယ်များသည် NLP တွင် နောက်ဆုံးပေါ်နည်းပညာကို ကိုယ်စားပြုထားပြီး၊ မိမိ၏ custom NLP ဖြေရှင်းချက်များကို စတင်စမ်းသပ်မည်ဆိုပါက အဓိကရွေးချယ်မှုအဖြစ် သုံးသင့်ပါသည်။ သို့သော်၊ ဤ module တွင် ဆွေးနွေးထားသော recurrent neural networks ၏ အခြေခံအယူအဆများကို နားလည်ခြင်းသည် အဆင့်မြင့် neural မော်ဒယ်များကို တည်ဆောက်လိုပါက အလွန်အရေးကြီးပါသည်။\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"\n---\n\n**အကြောင်းကြားချက်**: \nဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှန်ကန်မှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက် ဘာသာပြန်မှုများတွင် အမှားများ သို့မဟုတ် မမှန်ကန်မှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာရှိသော ရင်းမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူ့ဘာသာပြန်ပညာရှင်များမှ ပရော်ဖက်ရှင်နယ် ဘာသာပြန်မှုကို အကြံပြုပါသည်။ ဤဘာသာပြန်မှုကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားလွဲမှုများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"interpreter": {
|
||||
"hash": "0cb620c6d4b9f7a635928804c26cf22403d89d98d79684e4529119355ee6d5a5"
|
||||
},
|
||||
"kernelspec": {
|
||||
"display_name": "py38_tensorflow",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.12"
|
||||
},
|
||||
"coopTranslator": {
|
||||
"original_hash": "ab59c532409774988ab875f2260e8e53",
|
||||
"translation_date": "2025-08-30T10:23:46+00:00",
|
||||
"source_file": "lessons/5-NLP/18-Transformers/TransformersTF.ipynb",
|
||||
"language_code": "my"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue