探索的なノートブックの使い方[ベストプラクティス]

探検的なノートブックの活用法 【ベストプラクティス】

ジュピターノートブックは、データサイエンスコミュニティで最も論争の的となってきたツールの一つです。一部には意見がはっきりと分かれる批判的な意見を持つ人々もいれば、熱狂的なファンもいます。それにもかかわらず、多くのデータサイエンティストは、適切に使用すれば非常に価値があると認識しています。そして、この記事では、私の「ソフトウェアパターンシリーズ」の2つ目の記事として、探索的データ分析におけるジュピターノートブックのベストプラクティスを紹介します。

しかし、まずは、なぜノートブックが科学コミュニティで確立されたのかを理解する必要があります。データサイエンスが魅力的だった時代、ノートブックはまだ存在しませんでした。それ以前は、RStudioやMatlabの働き方に似せようとしたSpyderなどの統合開発環境に組み込まれたIPythonがありました。これらのツールは研究者の間で広く採用されました。

2014年、Project JupyterがIPythonから進化しました。主に産業界での勤務経験を持つ研究者たちによって推進され、その使用は急速に拡大しました。しかし、科学的なプロジェクトに適したノートブックの使用方法は、企業のビジネスや製品部門のための分析には必ずしも適用されないことがあります。大学卒業直後に採用されたデータサイエンティストが、分析の構造やプレゼンテーションに関する新たな期待に対応するのに苦労することは珍しくありません。

この記事では、ジュピターノートブックをビジネスや製品の視点から特に取り上げます。すでに述べたように、ジュピターノートブックは論議の的となるトピックですので、私の意見にすぐに入りましょう。

ジュピターノートブックは、純粋な探索的なタスクやアドホックな分析にのみ使用すべきです

ノートブックは、レポートに過ぎません。それに含まれるコードは全く重要ではありません。重要なのは、それが生成する結果だけです。理想的には、質問に答える手段に過ぎないコードをノートブックに隠すことができるはずです。

例えば:これらのテーブルの統計的特徴は何ですか?このトレーニングデータセットの特性は何ですか?このモデルを本番環境に展開することの影響は何ですか?以前のモデルよりもこのモデルを改良するためにどのようにすれば良いですか?このABテストはどのように実施されましたか?

ジュピターノートブックはさまざまな領域や目的で役立ちます
ジュピターノートブックはさまざまな領域や目的で役立ちます | 出典: 著者

ジュピターノートブック:効果的なストーリーテリングのガイドライン

ジュピターノートブックを書くことは、あなたが調査している問題についてのストーリーを語ったり、質問に答えたりする方法です。しかし、それはあなたの結論に至るまでの作業を明示的に表示する必要があるという意味ではありません。

ノートブックは洗練される必要があります。

それらは、ライターが問題を理解するために作成されるだけでなく、仲間の同僚が問題に深く立ち入ることなくその知識を得るためにも作成されます。

範囲

ノートブックには、通常の探索ストリームで答えに至らなかった無関係なセクションが含まれる非線形かつツリー状のデータセットの探索方法は、最終的なノートブックの形ではないはずです。ノートブックには、対象の質問に最も適した最小のコンテンツが含まれるべきです。各仮定や結論についてコメントし、理論的根拠を示すことが常に推奨されます。エグゼクティブサマリーは常にお勧めです。曖昧な関心を持つステークホルダーや時間の制約がある人々にとって理想的なものです。また、レビューアがフルノートブックに深入りする準備をするための素晴らしい方法でもあります。

対象読者

ノートブックの対象読者は、通常は技術的な知識があり、ビジネスに詳しい人々です。したがって、高度な専門用語を使用することが期待されます。しかし、エグゼクティブサマリーや結論は常に簡単な言葉で書かれ、より詳細で深い説明へのリンクが含まれるべきです。非技術的な対象読者向けにノートブックを作成するのに苦労している場合は、代わりにスライドデッキを作成することを検討してみると良いでしょう。そこでは、インフォグラフィックやカスタムビジュアライゼーション、そしてアイデアを説明するための広い方法を使用することができます。

データサイエンティストの様々な利害関係者は異なる要求を持っています
データサイエンティストの様々な利害関係者は異なる要求を持っています。|出典:著者

コンテキスト

問題に関連するコンテキストを常に提供してください。データ単体では、一貫したストーリーを作成するためには不十分です。分析全体を、対象としているドメインに組み込む必要があります。リンクを使用して、会社の既存の知識ベースをサポートし、ノートブックの専用セクションにすべての参考文献を収集してください。

Jupyterノートブックのコンテンツを構造化する方法

このセクションでは、通常使用するノートブックのレイアウトを説明します。多くの作業に見えるかもしれませんが、以下のセクションを含むノートブックテンプレートを作成し、タスクの具体的な部分のためのプレースホルダを残すことをお勧めします。このようなカスタマイズされたテンプレートは、時間を節約し、複数のノートブック間での一貫性を保証します。

  1. タイトル:関連するJIRAタスクの名前(または他の問題追跡ソフトウェア)に最適です。これにより、読者は明確に質問(JIRAタスク)と回答(ノートブック)を結びつけることができます。
  2. 説明:このタスクで何を達成したいのかを簡潔に説明してください。
  3. 目次:各見出しにリンクを設定し、読者が興味を持つ部分にジャンプできるようにします(Jupyterは、riginal headline through headline.lower().replace(” “, “-“)から派生した、各見出しのHTMLアンカーを作成するので、[セクションタイトル](#セクションタイトル)のようなプレーンなMarkdownリンクを使用してそれにリンクすることができます。また、<a id=’your-anchor’></a>をマークダウンセルに追加することで、自分自身のアンカーを配置することもできます)。
  4. 参考文献:ノートブックで提示される分析に使用された内部または外部のドキュメントへのリンク。
  5. TL;DRまたはエグゼクティブサマリ:全体の探索結果を非常に簡潔に説明し、得られた主要な結論(または質問)を強調して説明してください。
  6. イントロダクション&バックグラウンド:タスクを何かの文脈に置き、問題の周りの主要なビジネス先例に関する情報を追加し、タスクを詳しく説明します。
  7. インポート:ライブラリのインポートと設定。 matplotlibやseabornなどのサードパーティのライブラリの設定、探索ウィンドウの修正のための日付などの環境変数を追加します。
  8. 探索するデータ:調査/分析しているテーブルやデータセットを概説し、それらのソースを参照したり、データカタログのエントリにリンクしたりします。理想的には、各データセットまたはテーブルがどのように作成され、どのように頻繁に更新されるかを示します。このセクションを他のドキュメントへリンクすることもできます。
  9. 分析セル
  10. 結論:分析セクションで得られた主要な結果について、読者が詳細な説明を見つけられるノートブックの特定の部分へのリンクを含めて詳しく説明してください。

ヘッダには常にMarkdown書式設定を使用し、重要な文や引用を強調してください。さまざまなMarkdown構文オプションは、Markdown Cells — Jupyter Notebook 6.5.2 documentationで確認できます。

探索的ノートブックの例のテンプレート
探索的ノートブックの例のテンプレート|出典:著者

Jupyterノートブックでコードを整理する方法

探索的なタスクでは、SQLクエリの作成、pandasによるデータ整理、プロットの作成などのコードは読者にとって重要ではありません。

ただし、レビュアーにとっては重要ですので、品質と可読性を維持する必要があります。

ノートブックでコードを扱う際の私のコツは次のとおりです:

補助関数をプレーンPythonモジュールに移動する

一般的には、Pythonモジュールに定義された関数をインポートする方が、ノートブック内で定義するよりも良いです。なぜなら、.pyファイル内のGitの差分はノートブックよりも読みやすいからです。また、関数が内部で何をしているかを読者が知る必要はありません。

たとえば、データの読み込み、SQLクエリの実行、データセットの前処理、変換、拡張などの関数が典型的です。これらすべてを.pyファイルに移動してからノートブックにインポートするようにして、読者が関数呼び出しのみを見るようにします。レビュワーが詳細を知りたい場合は、常にPythonモジュールを直接参照できます。

特にプロット関数の場合、これは特に便利です。典型的には、同じ関数をノートブック内で複数回使用できます。データセットの異なるセットや異なるタイトルの使用など、細かな変更が必要かもしれませんが、プロットのレイアウトとスタイルは同じです。同じコードスニペットをコピー&ペーストする代わりに、utils/plots.pyモジュールを作成し、引数を指定してインポートおよび適応できる関数を作成します。

次は非常に単純な例です:

import matplotlib.pyplot as plt
import numpy as np
 
def create_barplot(data, x_labels, title='', xlabel='', ylabel='', bar_color='b', bar_width=0.8, style='seaborn', figsize=(8, 6)):
    """Matplotlibを使用してカスタマイズ可能なバープロットを作成します。
 
    パラメータ:
    - data:プロットするデータのリストまたは配列。
    - x_labels:x軸のラベルのリスト。
    - title:プロットのタイトル。
    - xlabel:x軸のラベル。
    - ylabel:y軸のラベル。
    - bar_color:バーの色(デフォルトは青)。
    - bar_width:バーの幅(デフォルトは0.8)。
    - style:適用するMatplotlibスタイル('seaborn'、'ggplot'、'default'など)。
    - figsize:図のサイズ(幅、高さ)を指定するタプル。
 
    戻り値:
    - なし
    """
    # Matplotlibのスタイルを設定する
    plt.style.use(style)
 
    # プロット用の図と軸を作成する
    fig, ax = plt.subplots(figsize=figsize)
 
    # バーのx位置を生成する
    x = np.arange(len(data))
 
    # バープロットを作成する
    ax.bar(x, data, color=bar_color, width=bar_width)
 
    # x軸のラベルを設定する
    ax.set_xticks(x)
    ax.set_xticklabels(x_labels)
 
    # ラベルとタイトルを設定する
    ax.set_xlabel(xlabel)
    ax.set_ylabel(ylabel)
    ax.set_title(title)
 
    # プロットを表示する
    plt.show()
 
# ノートブックのセル内での使用例:
create_barplot(
    data,
    x_labels,
    title="カスタマイズ可能なバープロット",
    xlabel="カテゴリ",
    ylabel="値",
    bar_color="skyblue",
    bar_width=0.6,
    style="seaborn",
    figsize=(10,6)
)

これらのPythonモジュールを作成する際には、コードが引き続き探索的な分析の一部であることを忘れないでください。したがって、プロジェクトの他の部分で使用しない限り、完全である必要はありません。レビュワーが読みやすく理解できる程度にするだけで十分です。

プロット、データの読み込み、データの準備、評価メトリックの実装などの関数をプレーンなPythonモジュールに配置すると、Jupyterノートブックは探索的な分析に集中できます
プロット、データの読み込み、データの準備、評価メトリックの実装などの関数をプレーンなPythonモジュールに配置すると、Jupyterノートブックは探索的な分析に集中できます | 出典:著者

Jupyterセルで直接SQLを使用する

データがメモリ上にない場合(たとえば、pandasのDataFrameではなく、会社のデータウェアハウス(たとえばRedshift)にある場合など)、データの探索と前処理のほとんどはSQLを使用して行われます。

SQLを使用するためのいくつかの方法があります。 JupySQLを使用すると、SQLコードを直接ノートブックのセルに記述し、クエリの結果をpandasのDataFrameのように表示できます。また、SQLスクリプトを関連ファイルに格納するか、前述の補助的なPythonモジュール内に格納することもできます。

どちらを使用するべきかは、主に目標によって異なります:

データウェアハウスから複数のテーブルを使用してデータの探査を行い、データの品質と妥当性を同僚に示したい場合は、ノートブック内にSQLクエリを表示するのが通常最善の選択肢です。レビュアーは、これらのテーブルにどのようにクエリを実行し、特定のビューに到達するためにどのような結合を行う必要があり、どのようなフィルターを適用する必要があるかなどを直接確認できることを評価するでしょう。

ただし、機械学習モデルを検証するためのデータセットを生成し、ノートブックの主な焦点が異なるメトリクスと説明性の出力を表示することである場合は、データセットの抽出をできるだけ隠して、クエリを別々のSQLスクリプトまたはPythonモジュールに保持することをお勧めします。

ここでは、両方のオプションの使用例を見ていきます。

.sqlスクリプトから読み込みおよび実行する

ノートブックから開かれ、データベースコネクタライブラリを介して実行される .sql ファイルを使用することができます。

まず、select_purchases.sql ファイルに次のクエリがあるとしましょう:

SELECT * FROM public.ecommerce_purchases WHERE product_id = 123

次に、SQLスクリプトを実行するための関数を定義することができます:

import psycopg2
 
def execute_sql_script(filename, connection_params):
    """
    psycopg2を使用してファイルからSQLスクリプトを実行します。
 
    パラメータ:
    - ファイル名:実行するSQLスクリプトファイルの名前。
    - connection_params:'host'、'port'、'database'、'user'、および 'password' などのPostgreSQL接続パラメータを含む辞書。
 
    戻り値:
    - 無し
    """
    # 接続パラメータを抽出する
    host = connection_params.get('host', 'localhost')
    port = connection_params.get('port', '5432')
    database = connection_params.get('database', '')
    user = connection_params.get('user', '')
    password = connection_params.get('password', '')
 
    # データベース接続を確立する
    try:
        conn = psycopg2.connect(
            host=host,
            port=port,
            database=database,
            user=user,
            password=password
        )
        cursor = conn.cursor()
 
        # SQLスクリプトを読み込んで実行する
        with open(filename, 'r') as sql_file:
            sql_script = sql_file.read()
            cursor.execute(sql_script)
        
        # 結果をPandasのDataFrameに取得する
        result = cursor.fetchall()
        column_names = [desc[0] for desc in cursor.description]
        df = pd.DataFrame(result, columns=column_names)

        # 変更をコミットして接続を閉じる
        conn.commit()
        conn.close()
        return df

    except Exception as e:
        print(f"Error: {e}")
        if 'conn' in locals():
            conn.rollback()
            conn.close()

データベース接続パラメータのデフォルト値を指定していることに注意してください。これにより、毎回それらを指定する必要はありません。ただし、秘密情報やその他の機密情報をPythonスクリプト内に保存しないようにしてください!(後のシリーズで、この問題に対するさまざまな解決策について説明します。)

今、次のワンライナーをノートブック内で使用してスクリプトを実行できます:

df = execute_sql_script('select_purchases.sql', connection_params)

JupySQLの使用

従来、SQLをクエリするためのツールとしては、ipython-sql が選択されてきました。しかし、元の作者によって2023年4月に廃止され、 JupySQL への切り替えが推奨されています。JupySQLは、現在もメンテナンスされている派生版です。今後は、すべての改善と新機能はJupySQLにのみ追加されます。

Redshiftを使用するためにライブラリをインストールするには、次のコマンドを実行します:

pip install jupysql sqlalchemy-redshift redshift-connector 'sqlalchemy<2'

snowflakeduckdb などの他のデータベースとも併用できます)

Jupyterノートブックでは、SQLを有効にするために %load_ext sql 魔術コマンドを使い、次のスニペットを使用して sqlalchemy の Redshift エンジンを作成できます:

from os import environ
from sqlalchemy import create_engine
from sqlalchemy.engine import URL

user = environ["REDSHIFT_USERNAME"]
password = environ["REDSHIFT_PASSWORD"]
host = environ["REDSHIFT_HOST"]

url = URL.create(
    drivername="redshift+redshift_connector",
    username=user,
    password=password,
    host=host,
    port=5439,
    database="dev",
)

engine = create_engine(url)

エンジンを magic コマンドに渡すだけです:

%sql engine --alias redshift-sqlalchemy

あとは簡単にマジックコマンドを使って実行したいクエリを書くだけで、セルの出力に結果が表示されます:

%sql
SELECT * FROM public.ecommerce_purchases WHERE product_id = 123

セルは順番に実行されるようにしてください

ノートブックをリポジトリに push する前に、常にすべてのコードセルを実行することをおすすめします。Jupyter ノートブックは各セルの実行時の出力状態を保存します。つまり、書いたコードや編集したコードがセルの表示出力と一致しないことがあります。

ノートブックを上から下まで実行することは、ノートブックが正しく実行されるためにユーザーの入力に依存しているかどうかをテストする良い方法でもあります。理想的には、何も手を加えずにすべてがスムーズに実行されるはずです。もし実行できなかった場合、分析結果はおそらく他の人や将来の自分によって再現できません。

どのようにノートブックが順番に実行されたかをチェックする方法の1つは、nbcheckorder の pre-commit フックを使用することです。これにより、セルの出力番号が連続しているかどうかが確認されます。連続していない場合、それはノートブックのセルが一つずつ順番に実行されていないことを示し、Git コミットが通らないようになります。

Sample .pre-commit-config.yaml:

- repo: local
   rev: v0.2.0
   hooks:
     - id: nbcheckorder

まだ pre-commit を使っていないのであれば、この小さなツールを使うことを強くおすすめします。最初に Elliot Jordan によるこのpre-commitの紹介から学ぶことをおすすめします。その後、充実したドキュメントを参照して、全ての機能を理解すると良いでしょう。

セルの出力をクリアする

前のヒントよりもさらに良い方法は、ノートブックのすべてのセルの出力をクリアすることです。これにより、セルの状態と出力を無視することができますが、一方で、レビュアーには結果を見るためにローカルでコードを実行する必要があります。これを自動化する方法はいくつかあります。

nbstripout を、GitHub 上のFlorian Rathgeberによる説明に従って、pre-commit と一緒に使用することができます:

- repo: local
  rev: 0.6.1
  hooks:
    - id: nbstripout

nbconvert –ClearOutputpPreprocessorを、Yury Zhauniarovichが説明するように、カスタムの pre-commit フックで使用することもできます:

  - repo: local
    hooks:
      - id: jupyter-nb-clear-output
        name: jupyter-nb-clear-output
        files: \.ipynb$
        stages: [ commit ]
        language: python
        entry: jupyter nbconvert --ClearOutputPreprocessor.enabled=True --inplace
        additional_dependencies: [ 'nbconvert' ]

Jupyter notebook でレポートを作成して共有する

そして、業界でまだうまく解決されていない問題が出てきます。チームや外部の利害関係者とのノートブックの共有方法は、最善の方法は何でしょうか?

ユピターノートブックからの分析結果の共有に関して、この分野は異なる作業方法を促進する3つの異なるタイプのチームに分かれています。

翻訳者チーム

これらのチームは、ビジネスや製品のユニットからの人々がユピターノートブックを読むことには不快感を感じると信じています。そのため、彼らは分析とレポートを予想される観客に合わせて適応します。

翻訳者チームはノートブックからの調査結果を会社の知識システム(Confluence、Googleスライドなど)に追加します。ノートブックの追跡性の一部を失うという否定的な副作用がありますが、それにもかかわらず、彼らは結果と分析を関係者に効果的に伝えることができると主張します。

これを行いたい場合は、エクスポートしたドキュメントとユピターノートブックの間にリンクを保持することをおすすめします。このセットアップでは、テキストと結論が少ないノートブックを保持し、生の事実やデータ証拠に重点を置きます。ドキュメンテーションシステムを使用して、各調査結果に関するエグゼクティブサマリーやコメントを展開します。これにより、探索コードと結果の調査結果という2つの成果物を切り離すことができます。

社内の全てのチーム

これらのチームは、ローカルのユピターノートブックを使用し、会社の知識システムとインフラストラクチャに合わせたソリューションを他のビジネスユニットと共有します。彼らはビジネスと製品の利害関係者がデータサイエンティストのノートブックを理解できる必要があると信じ、結果から生データへの完全に追跡可能な系譜を維持する必要性に強く意識しています。

しかし、財務チームがGitHubやBitbucketにアクセスしてノートブックを読むことはほぼないでしょう。

この領域では、いくつかのソリューションが実装されているのを見ました。たとえば、ユピターノートブックからPDFを生成したり、HTMLページとしてエクスポートしたりするためにnbconvertなどのツールを使用して、技術チーム以外の人々と簡単に共有できます。

これらのノートブックをS3に移動し、レンダリングビューとして静的ウェブサイトとしてホストすることもできます。コードが特定のブランチにマージされると、CI/CDワークフローを使用してノートブックのHTMLレンダリングを作成し、S3にプッシュすることもできます。

サードパーティツールの提唱者

これらのチームは、ノートブックの開発だけでなく、組織内の他の人々との共有も可能にするツールを使用しています。これには、内部データウェアハウス、データレイク、データベースへの安全で簡単なアクセスを確保するといった複雑さへの取り組みが一般的に含まれます。

この領域で最も広く採用されているツールのいくつかはDeepnoteAmazon SageMakerGoogle Vertex AIAzure Machine Learningです。これらはすべて、ノートブックを実行するためにリモートマシン上で仮想環境を起動することができる、完全なプラットフォームです。対話型のプロットやデータ、実験の探索機能を提供し、データサイエンスのライフサイクルを簡素化します。たとえば、Sagemakerでは、Sagemaker Experimentsで追跡したすべての実験情報を視覚化することができ、DeepnoteではChart Blocksを使用したポイントアンドクリックの視覚化も提供しています。

さらに、DeepnoteとSageMakerでは、ノートブックを同じ実行環境でリアルタイムに共有したり、同僚と共有したりすることもできます。

JupyterHubなどのオープンソースの代替品もありますが、それを運用するために必要なセットアップ作業やメンテナンスはそれほどの価値がありません。オンプレミスでJupyterHubを立ち上げることは最適な解決策ではなく、特定のハードウェアが必要な特殊なタイプのワークロードにのみ適しています(たとえば、非常に専門的なワークロード)。クラウドサービスを使用することで、他の企業が提供できるものよりもはるかに優れた耐障害アーキテクチャを保証することができる経済的な規模のメリットを活用できます。初期のセットアップコストを想定し、データサイエンティストのために稼働し続けるプラットフォーム運用チームにメンテナンスを委任し、データのセキュリティとプライバシーを保証する必要があります。したがって、管理されたサービスへの信頼は、インフラストラクチャに関する無限の頭痛を回避する上で望ましいものです。

これらの製品を探索するための一般的なアドバイス:もしも既にAWS、Google Cloud Platform、またはAzureのようなクラウドプロバイダを使用している場合、会社のインフラへのアクセスが簡単でリスクが少なくなるため、彼らのノートブックソリューションを採用するのが良いアイデアかもしれません。

Jupyterノートブックの効果的な活用

本記事では、Jupyterノートブックの最適化に関するベストプラクティスとアドバイスについてご紹介しました。

最も重要なポイントは:

常にノートブックの作成には対象の読者と最終目標を考慮してアプローチしてください。そのようにすることで、ノートブックの異なる要素(コード、解析、執行サマリーなど)にどれだけの焦点を置くかがわかります。

総括すると、データサイエンティストにはJupyterノートブックの使用をお勧めしますが、探索的な質問や報告の目的に限定して使用してください。

モデル、データセット、またはハイパーパラメータなどの本番の成果物は、ノートブックに遡らせるべきではありません。これらは、再現可能で再実行可能な本番システムに由来する必要があります。例えば、SageMaker PipelinesAirflow DAGsのような、よくメンテナンスされて徹底的にテストされたシステムです。

トレーサビリティ、再現性、および起源に関するこれらの考えは、私のデータサイエンスとMLエンジニアリングのソフトウェアパターンシリーズの次の記事の出発点となります。次の記事では、ETLスキルを向上させる方法に焦点を当て、データサイエンティストによってしばしば無視されることがあるものの、私はETLの習得が機械学習プロジェクトの成功に不可欠であり、重要だと信じています。

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

機械学習

ウェイト、バイアス、ロスのアンボクシング:ディープラーニングに集中する

ディープラーニングは、大量のデータを自動的に利用して、コンピュータが人間と同様に学ぶために層状のニューラルネットワー...

人工知能

「世界中のさらに多くの人々に生成型AIを検索にもたらす」

「我々は、より多くの人々にSearch(SGE)での生成的AI機能を提供し、Search Labsをインドと日本で利用可能にしています」

データサイエンス

『ELS+ Stream Tool』

ELS+は、企業がデータから有益な洞察を抽出し、意思決定を改善し、パフォーマンスを向上させるためのAIパワードアナリティク...

機械学習

このAI論文では、ディープラーニングモデルを用いたAIS(アンドロゲン不感症)のテストに関する研究が紹介されています

AISはAndrogen Insensitivity Syndromeの略です。AISは若い世代に影響を与え、彼らの生活をさらに悪化させる脊髄脳の問題です...

人工知能

AI字幕生成ツール(短縮形式のコンテンツ用)

30秒以内で、短いコンテンツに対して絵文字付きのキャプションを生成することができます

AI研究

イェール大学とGoogle DeepMindの研究者は、大規模な言語モデルに対する高度な微調整技術を使用して数学の問題解決の成功を解き明かしました

“`html 最も先進的な大型言語モデル(LLMs)であるGPT-4やPaLM 2でも、数学の問題を解くのは困難です。なぜなら、それ...