{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "name": "lesson_12-R.ipynb", "provenance": [], "collapsed_sections": [] }, "kernelspec": { "name": "ir", "display_name": "R" }, "language_info": { "name": "R" }, "coopTranslator": { "original_hash": "fab50046ca413a38939d579f8432274f", "translation_date": "2025-09-04T02:34:52+00:00", "source_file": "4-Classification/3-Classifiers-2/solution/R/lesson_12-R.ipynb", "language_code": "ja" } }, "cells": [ { "cell_type": "markdown", "metadata": { "id": "jsFutf_ygqSx" }, "source": [ "# 分類モデルを構築する: 美味しいアジア料理とインド料理\n" ] }, { "cell_type": "markdown", "metadata": { "id": "HD54bEefgtNO" }, "source": [ "## 料理分類器 2\n", "\n", "この2回目の分類レッスンでは、カテゴリカルデータを分類するための`さらなる方法`を探ります。また、どの分類器を選ぶかによる影響についても学びます。\n", "\n", "### [**講義前のクイズ**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/23/)\n", "\n", "### **前提条件**\n", "\n", "前のレッスンを完了していることを前提としています。なぜなら、以前学んだいくつかの概念を引き継ぐからです。\n", "\n", "このレッスンでは、以下のパッケージが必要です:\n", "\n", "- `tidyverse`: [tidyverse](https://www.tidyverse.org/)は、データサイエンスをより速く、簡単に、そして楽しくするために設計された[Rパッケージのコレクション](https://www.tidyverse.org/packages)です。\n", "\n", "- `tidymodels`: [tidymodels](https://www.tidymodels.org/)フレームワークは、モデリングと機械学習のための[パッケージのコレクション](https://www.tidymodels.org/packages/)です。\n", "\n", "- `themis`: [themisパッケージ](https://themis.tidymodels.org/)は、不均衡データに対処するための追加のレシピステップを提供します。\n", "\n", "以下のようにしてインストールできます:\n", "\n", "`install.packages(c(\"tidyverse\", \"tidymodels\", \"kernlab\", \"themis\", \"ranger\", \"xgboost\", \"kknn\"))`\n", "\n", "または、以下のスクリプトを使用して、このモジュールを完了するために必要なパッケージがインストールされているか確認し、足りない場合は自動的にインストールすることもできます。\n" ] }, { "cell_type": "code", "metadata": { "id": "vZ57IuUxgyQt" }, "source": [ "suppressWarnings(if (!require(\"pacman\"))install.packages(\"pacman\"))\n", "\n", "pacman::p_load(tidyverse, tidymodels, themis, kernlab, ranger, xgboost, kknn)" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "z22M-pj4g07x" }, "source": [ "## **1. 分類マップ**\n", "\n", "[前回のレッスン](https://github.com/microsoft/ML-For-Beginners/tree/main/4-Classification/2-Classifiers-1)では、複数のモデルの中からどのように選ぶべきかという質問に取り組みました。選択は主にデータの特性や解決したい問題の種類(例えば、分類や回帰)に依存します。\n", "\n", "以前、Microsoftのチートシートを使ってデータを分類する際のさまざまな選択肢について学びました。Pythonの機械学習フレームワークであるScikit-learnは、さらに詳細なチートシートを提供しており、分類器(別名エスティメーター)を絞り込む際に役立ちます。\n", "\n", "

\n", " \n", "

\n" ] }, { "cell_type": "markdown", "metadata": { "id": "u1i3xRIVg7vG" }, "source": [ "> ヒント: [このマップをオンラインで見る](https://scikit-learn.org/stable/tutorial/machine_learning_map/)と、ドキュメントを読むために道筋をクリックできます。\n", ">\n", "> [Tidymodelsのリファレンスサイト](https://www.tidymodels.org/find/parsnip/#models)も、さまざまなモデルタイプに関する優れたドキュメントを提供しています。\n", "\n", "### **計画** 🗺️\n", "\n", "このマップはデータをしっかり理解した後に非常に役立ちます。道筋をたどることで意思決定に至ることができます:\n", "\n", "- サンプルが50以上ある\n", "\n", "- カテゴリーを予測したい\n", "\n", "- ラベル付きデータがある\n", "\n", "- サンプル数が10万未満である\n", "\n", "- ✨ Linear SVCを選択できる\n", "\n", "- それがうまくいかない場合、数値データがあるので\n", "\n", " - ✨ KNeighbors Classifierを試すことができる\n", "\n", " - それでもうまくいかない場合は、✨ SVCや✨ Ensemble Classifiersを試してみる\n", "\n", "この道筋は非常に役立ちます。それでは、[tidymodels](https://www.tidymodels.org/)モデリングフレームワークを使って始めましょう。これは、良い統計的実践を促進するために開発された、Rパッケージの一貫性があり柔軟なコレクションです 😊。\n", "\n", "## 2. データを分割し、不均衡なデータセットに対処する\n", "\n", "前回のレッスンで、私たちの料理ジャンル間で共通する要素があることを学びました。また、料理ジャンルの数にかなりの偏りがあることも分かりました。\n", "\n", "これらに対処するために以下を行います:\n", "\n", "- 異なる料理ジャンル間で混乱を引き起こす最も一般的な要素を`dplyr::select()`を使って削除します。\n", "\n", "- データを前処理してモデリングの準備をするために、`recipe`を使用し、`オーバーサンプリング`アルゴリズムを適用します。\n", "\n", "これらは前回のレッスンで既に見た内容なので、簡単に進められるはずです 🥳!\n" ] }, { "cell_type": "code", "metadata": { "id": "6tj_rN00hClA" }, "source": [ "# Load the core Tidyverse and Tidymodels packages\n", "library(tidyverse)\n", "library(tidymodels)\n", "\n", "# Load the original cuisines data\n", "df <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/4-Classification/data/cuisines.csv\")\n", "\n", "# Drop id column, rice, garlic and ginger from our original data set\n", "df_select <- df %>% \n", " select(-c(1, rice, garlic, ginger)) %>%\n", " # Encode cuisine column as categorical\n", " mutate(cuisine = factor(cuisine))\n", "\n", "\n", "# Create data split specification\n", "set.seed(2056)\n", "cuisines_split <- initial_split(data = df_select,\n", " strata = cuisine,\n", " prop = 0.7)\n", "\n", "# Extract the data in each split\n", "cuisines_train <- training(cuisines_split)\n", "cuisines_test <- testing(cuisines_split)\n", "\n", "# Display distribution of cuisines in the training set\n", "cuisines_train %>% \n", " count(cuisine) %>% \n", " arrange(desc(n))" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "zFin5yw3hHb1" }, "source": [ "### 不均衡データへの対処\n", "\n", "不均衡データは、モデルの性能に悪影響を及ぼすことがよくあります。多くのモデルは観測数が均等である場合に最も良いパフォーマンスを発揮し、不均衡なデータでは苦戦する傾向があります。\n", "\n", "不均衡データセットに対処する方法は主に2つあります:\n", "\n", "- 少数派クラスに観測値を追加する: `オーバーサンプリング` 例えば、SMOTEアルゴリズムを使用して、少数派クラスの新しい例をこれらのケースの近傍を基に合成的に生成する方法。\n", "\n", "- 多数派クラスから観測値を削除する: `アンダーサンプリング`\n", "\n", "前回のレッスンでは、`recipe` を使用して不均衡データセットに対処する方法を示しました。`recipe` は、データセットをデータ分析の準備が整うようにするためにどのステップを適用すべきかを記述した設計図のようなものと考えることができます。今回の場合、`training set` における料理の数を均等に分布させたいと考えています。それでは、始めましょう。\n" ] }, { "cell_type": "code", "metadata": { "id": "cRzTnHolhLWd" }, "source": [ "# Load themis package for dealing with imbalanced data\n", "library(themis)\n", "\n", "# Create a recipe for preprocessing training data\n", "cuisines_recipe <- recipe(cuisine ~ ., data = cuisines_train) %>%\n", " step_smote(cuisine) \n", "\n", "# Print recipe\n", "cuisines_recipe" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "KxOQ2ORhhO81" }, "source": [ "さあ、モデルのトレーニングを始めましょう 👩‍💻👨‍💻!\n", "\n", "## 3. 多項ロジスティック回帰モデルを超えて\n", "\n", "前回のレッスンでは、多項ロジスティック回帰モデルについて学びました。今回は、分類のためのより柔軟なモデルを探っていきましょう。\n", "\n", "### サポートベクターマシン\n", "\n", "分類の文脈において、`Support Vector Machines`(サポートベクターマシン)は、クラスを「最適に」分離する*ハイパープレーン*を見つけようとする機械学習手法です。簡単な例を見てみましょう:\n", "\n", "

\n", " \n", "

https://commons.wikimedia.org/w/index.php?curid=22877598
\n" ] }, { "cell_type": "markdown", "metadata": { "id": "C4Wsd0vZhXYu" }, "source": [ "H1~はクラスを分けません。H2~は分けますが、余白は小さいです。H3~は最大の余白でクラスを分けます。\n", "\n", "#### 線形サポートベクター分類器\n", "\n", "サポートベクタークラスタリング(SVC)は、機械学習技術の一つであるサポートベクターマシン(SVM)ファミリーに属します。SVCでは、ハイパープレーンはトレーニングデータの`ほとんど`を正しく分離するように選ばれますが、`一部の観測値を誤分類する可能性`があります。一部のポイントが誤った側に位置することを許容することで、SVMは外れ値に対してより頑健になり、新しいデータへの一般化能力が向上します。この違反を調整するパラメータは`cost`と呼ばれ、デフォルト値は1です(`help(\"svm_poly\")`を参照してください)。\n", "\n", "ポリノミアルSVMモデルで`degree = 1`を設定することで、線形SVCを作成してみましょう。\n" ] }, { "cell_type": "code", "metadata": { "id": "vJpp6nuChlBz" }, "source": [ "# Make a linear SVC specification\n", "svc_linear_spec <- svm_poly(degree = 1) %>% \n", " set_engine(\"kernlab\") %>% \n", " set_mode(\"classification\")\n", "\n", "# Bundle specification and recipe into a worklow\n", "svc_linear_wf <- workflow() %>% \n", " add_recipe(cuisines_recipe) %>% \n", " add_model(svc_linear_spec)\n", "\n", "# Print out workflow\n", "svc_linear_wf" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "rDs8cWNkhoqu" }, "source": [ "ワークフローに前処理ステップとモデル仕様をまとめたので、線形SVCをトレーニングし、その結果を評価してみましょう。パフォーマンス指標として、以下を評価するメトリックセットを作成します:`accuracy`、`sensitivity`、`Positive Predicted Value`、および `F Measure`。\n", "\n", "> `augment()` は、指定されたデータに予測結果の列を追加します。\n" ] }, { "cell_type": "code", "metadata": { "id": "81wiqcwuhrnq" }, "source": [ "# Train a linear SVC model\n", "svc_linear_fit <- svc_linear_wf %>% \n", " fit(data = cuisines_train)\n", "\n", "# Create a metric set\n", "eval_metrics <- metric_set(ppv, sens, accuracy, f_meas)\n", "\n", "\n", "# Make predictions and Evaluate model performance\n", "svc_linear_fit %>% \n", " augment(new_data = cuisines_test) %>% \n", " eval_metrics(truth = cuisine, estimate = .pred_class)" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "0UFQvHf-huo3" }, "source": [ "#### サポートベクターマシン\n", "\n", "サポートベクターマシン(SVM)は、クラス間の非線形な境界を扱うためにサポートベクトル分類器を拡張したものです。本質的に、SVMは*カーネルトリック*を使用して特徴空間を拡大し、クラス間の非線形な関係に適応します。SVMで使用される一般的で非常に柔軟なカーネル関数の1つが*放射基底関数*です。それが私たちのデータでどのように機能するか見てみましょう。\n" ] }, { "cell_type": "code", "metadata": { "id": "-KX4S8mzhzmp" }, "source": [ "set.seed(2056)\n", "\n", "# Make an RBF SVM specification\n", "svm_rbf_spec <- svm_rbf() %>% \n", " set_engine(\"kernlab\") %>% \n", " set_mode(\"classification\")\n", "\n", "# Bundle specification and recipe into a worklow\n", "svm_rbf_wf <- workflow() %>% \n", " add_recipe(cuisines_recipe) %>% \n", " add_model(svm_rbf_spec)\n", "\n", "\n", "# Train an RBF model\n", "svm_rbf_fit <- svm_rbf_wf %>% \n", " fit(data = cuisines_train)\n", "\n", "\n", "# Make predictions and Evaluate model performance\n", "svm_rbf_fit %>% \n", " augment(new_data = cuisines_test) %>% \n", " eval_metrics(truth = cuisine, estimate = .pred_class)" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "QBFSa7WSh4HQ" }, "source": [ "ずっと良いですね 🤩!\n", "\n", "> ✅ こちらもご覧ください:\n", ">\n", "> - [*サポートベクターマシン*](https://bradleyboehmke.github.io/HOML/svm.html), Hands-on Machine Learning with R\n", ">\n", "> - [*サポートベクターマシン*](https://www.statlearning.com/), An Introduction to Statistical Learning with Applications in R\n", ">\n", "> さらなる学習のために。\n", "\n", "### 最近傍法分類器\n", "\n", "*K*-最近傍法 (KNN) は、各観測値を他の観測値との「類似性」に基づいて予測するアルゴリズムです。\n", "\n", "これをデータに適用してみましょう。\n" ] }, { "cell_type": "code", "metadata": { "id": "k4BxxBcdh9Ka" }, "source": [ "# Make a KNN specification\n", "knn_spec <- nearest_neighbor() %>% \n", " set_engine(\"kknn\") %>% \n", " set_mode(\"classification\")\n", "\n", "# Bundle recipe and model specification into a workflow\n", "knn_wf <- workflow() %>% \n", " add_recipe(cuisines_recipe) %>% \n", " add_model(knn_spec)\n", "\n", "# Train a boosted tree model\n", "knn_wf_fit <- knn_wf %>% \n", " fit(data = cuisines_train)\n", "\n", "\n", "# Make predictions and Evaluate model performance\n", "knn_wf_fit %>% \n", " augment(new_data = cuisines_test) %>% \n", " eval_metrics(truth = cuisine, estimate = .pred_class)" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "HaegQseriAcj" }, "source": [ "このモデルはあまり良いパフォーマンスを発揮していないようです。おそらく、`help(\"nearest_neighbor\")`を参照してモデルの引数を変更すれば、パフォーマンスが向上する可能性があります。ぜひ試してみてください。\n", "\n", "> ✅ 以下を参照してください:\n", ">\n", "> - [Hands-on Machine Learning with R](https://bradleyboehmke.github.io/HOML/)\n", ">\n", "> - [An Introduction to Statistical Learning with Applications in R](https://www.statlearning.com/)\n", ">\n", "> *K*-Nearest Neighbors分類器について詳しく学ぶにはこちらをご覧ください。\n", "\n", "### アンサンブル分類器\n", "\n", "アンサンブルアルゴリズムは、複数の基本推定器を組み合わせることで最適なモデルを作成します。その方法は以下のいずれかです:\n", "\n", "`bagging`: 基本モデルの集合に対して*平均化関数*を適用する\n", "\n", "`boosting`: 一連のモデルを順次構築し、それぞれが前のモデルを改善することで予測性能を向上させる\n", "\n", "まずは、ランダムフォレストモデルを試してみましょう。このモデルは、多数の決定木を構築し、それに平均化関数を適用することで、全体としてより優れたモデルを作成します。\n" ] }, { "cell_type": "code", "metadata": { "id": "49DPoVs6iK1M" }, "source": [ "# Make a random forest specification\n", "rf_spec <- rand_forest() %>% \n", " set_engine(\"ranger\") %>% \n", " set_mode(\"classification\")\n", "\n", "# Bundle recipe and model specification into a workflow\n", "rf_wf <- workflow() %>% \n", " add_recipe(cuisines_recipe) %>% \n", " add_model(rf_spec)\n", "\n", "# Train a random forest model\n", "rf_wf_fit <- rf_wf %>% \n", " fit(data = cuisines_train)\n", "\n", "\n", "# Make predictions and Evaluate model performance\n", "rf_wf_fit %>% \n", " augment(new_data = cuisines_test) %>% \n", " eval_metrics(truth = cuisine, estimate = .pred_class)" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "RGVYwC_aiUWc" }, "source": [ "よくやった 👏!\n", "\n", "では、Boosted Treeモデルを試してみましょう。\n", "\n", "Boosted Treeは、逐次的な決定木のシリーズを作成するアンサンブル手法を定義します。このシリーズでは、各木が前の木の結果に依存し、誤差を段階的に減らそうとします。この手法は、誤分類された項目の重み付けに焦点を当て、次の分類器の適合を調整して修正を試みます。\n", "\n", "このモデルを適合させる方法はいくつかあります(`help(\"boost_tree\")`を参照してください)。この例では、`xgboost`エンジンを使用してBoosted Treeを適合させます。\n" ] }, { "cell_type": "code", "metadata": { "id": "Py1YWo-micWs" }, "source": [ "# Make a boosted tree specification\n", "boost_spec <- boost_tree(trees = 200) %>% \n", " set_engine(\"xgboost\") %>% \n", " set_mode(\"classification\")\n", "\n", "# Bundle recipe and model specification into a workflow\n", "boost_wf <- workflow() %>% \n", " add_recipe(cuisines_recipe) %>% \n", " add_model(boost_spec)\n", "\n", "# Train a boosted tree model\n", "boost_wf_fit <- boost_wf %>% \n", " fit(data = cuisines_train)\n", "\n", "\n", "# Make predictions and Evaluate model performance\n", "boost_wf_fit %>% \n", " augment(new_data = cuisines_test) %>% \n", " eval_metrics(truth = cuisine, estimate = .pred_class)" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "zNQnbuejigZM" }, "source": [ "> ✅ ぜひ以下をご覧ください:\n", ">\n", "> - [Machine Learning for Social Scientists](https://cimentadaj.github.io/ml_socsci/tree-based-methods.html#random-forests)\n", ">\n", "> - [Hands-on Machine Learning with R](https://bradleyboehmke.github.io/HOML/)\n", ">\n", "> - [An Introduction to Statistical Learning with Applications in R](https://www.statlearning.com/)\n", ">\n", "> - - AdaBoostモデルについて解説しており、xgboostの良い代替案となります。\n", ">\n", "> アンサンブル分類器についてさらに学ぶために。\n", "\n", "## 4. 追加 - 複数モデルの比較\n", "\n", "このラボでは、かなり多くのモデルを適用しました 🙌。異なる前処理やモデル仕様のセットから多くのワークフローを作成し、それぞれの性能指標を一つずつ計算するのは、面倒で手間がかかることがあります。\n", "\n", "これを解決するために、トレーニングセットに対して複数のワークフローを適用し、テストセットに基づいて性能指標を返す関数を作成してみましょう。[purrr](https://purrr.tidyverse.org/)パッケージの`map()`と`map_dfr()`を使用して、リスト内の各要素に関数を適用します。\n", "\n", "> [`map()`](https://purrr.tidyverse.org/reference/map.html)関数を使用すると、多くのforループをより簡潔で読みやすいコードに置き換えることができます。[`map()`](https://purrr.tidyverse.org/reference/map.html)関数について学ぶ最適な場所は、R for Data Scienceの[反復処理の章](http://r4ds.had.co.nz/iteration.html)です。\n" ] }, { "cell_type": "code", "metadata": { "id": "Qzb7LyZnimd2" }, "source": [ "set.seed(2056)\n", "\n", "# Create a metric set\n", "eval_metrics <- metric_set(ppv, sens, accuracy, f_meas)\n", "\n", "# Define a function that returns performance metrics\n", "compare_models <- function(workflow_list, train_set, test_set){\n", " \n", " suppressWarnings(\n", " # Fit each model to the train_set\n", " map(workflow_list, fit, data = train_set) %>% \n", " # Make predictions on the test set\n", " map_dfr(augment, new_data = test_set, .id = \"model\") %>%\n", " # Select desired columns\n", " select(model, cuisine, .pred_class) %>% \n", " # Evaluate model performance\n", " group_by(model) %>% \n", " eval_metrics(truth = cuisine, estimate = .pred_class) %>% \n", " ungroup()\n", " )\n", " \n", "} # End of function" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "Fwa712sNisDA" }, "source": [] }, { "cell_type": "code", "metadata": { "id": "3i4VJOi2iu-a" }, "source": [ "# Make a list of workflows\n", "workflow_list <- list(\n", " \"svc\" = svc_linear_wf,\n", " \"svm\" = svm_rbf_wf,\n", " \"knn\" = knn_wf,\n", " \"random_forest\" = rf_wf,\n", " \"xgboost\" = boost_wf)\n", "\n", "# Call the function\n", "set.seed(2056)\n", "perf_metrics <- compare_models(workflow_list = workflow_list, train_set = cuisines_train, test_set = cuisines_test)\n", "\n", "# Print out performance metrics\n", "perf_metrics %>% \n", " group_by(.metric) %>% \n", " arrange(desc(.estimate)) %>% \n", " slice_head(n=7)\n", "\n", "# Compare accuracy\n", "perf_metrics %>% \n", " filter(.metric == \"accuracy\") %>% \n", " arrange(desc(.estimate))\n" ], "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "KuWK_lEli4nW" }, "source": [ "[**workflowset**](https://workflowsets.tidymodels.org/) パッケージは、ユーザーが多数のモデルを作成し簡単に適合させることを可能にしますが、主に `クロスバリデーション` のようなリサンプリング技術と連携するよう設計されています。このアプローチについてはまだ学んでいません。\n", "\n", "## **🚀チャレンジ**\n", "\n", "これらの技術には多くのパラメータがあり、例えば SVM の `cost`、KNN の `neighbors`、ランダムフォレストの `mtry`(ランダムに選択された予測子)などを調整することができます。\n", "\n", "各モデルのデフォルトパラメータを調べ、それらのパラメータを調整することでモデルの品質にどのような影響があるかを考えてみましょう。\n", "\n", "特定のモデルとそのパラメータについて詳しく知りたい場合は、次のコマンドを使用してください: `help(\"model\")` 例: `help(\"rand_forest\")`\n", "\n", "> 実際には、これらの *最適な値* を *推定* するために、多くのモデルを `シミュレーションデータセット` でトレーニングし、それらのモデルがどれだけうまく機能するかを測定します。このプロセスは **チューニング** と呼ばれます。\n", "\n", "### [**講義後のクイズ**](https://gray-sand-07a10f403.1.azurestaticapps.net/quiz/24/)\n", "\n", "### **復習と自己学習**\n", "\n", "これらのレッスンには専門用語が多く含まれているため、[このリスト](https://docs.microsoft.com/dotnet/machine-learning/resources/glossary?WT.mc_id=academic-77952-leestott) を確認して役立つ用語を復習する時間を取ってください!\n", "\n", "#### 感謝の言葉:\n", "\n", "[`Allison Horst`](https://twitter.com/allison_horst/) に感謝します。彼女は R をより親しみやすく魅力的にする素晴らしいイラストを作成してくれました。彼女の [ギャラリー](https://www.google.com/url?q=https://github.com/allisonhorst/stats-illustrations&sa=D&source=editors&ust=1626380772530000&usg=AOvVaw3zcfyCizFQZpkSLzxiiQEM) でさらに多くのイラストを見ることができます。\n", "\n", "[Cassie Breviu](https://www.twitter.com/cassieview) と [Jen Looper](https://www.twitter.com/jenlooper) に感謝します。このモジュールの元となる Python バージョンを作成してくれました ♥️\n", "\n", "楽しく学びましょう!\n", "\n", "[Eric](https://twitter.com/ericntay)、Gold Microsoft Learn Student Ambassador\n", "\n", "

\n", " \n", "

@allison_horst によるアートワーク
\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n---\n\n**免責事項**: \nこの文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を期すよう努めておりますが、自動翻訳には誤りや不正確な表現が含まれる可能性があります。元の言語で記載された原文を公式な情報源としてご参照ください。重要な情報については、専門の人間による翻訳を推奨します。本翻訳の利用に起因する誤解や誤認について、当社は一切の責任を負いません。\n" ] } ] }