ホームページ > バックエンド開発 > Python チュートリアル > 宝くじのクエストが私を PyTorch のパワーに導いた経緯

宝くじのクエストが私を PyTorch のパワーに導いた経緯

Linda Hamilton
リリース: 2025-01-01 04:19:16
オリジナル
642 人が閲覧しました

導入

宝くじに当たる確率は非常に低いということを一度は聞いたことがあるでしょう。確率に関連するすべてのことと同様、複数の試行によって結果が有利になる可能性があります。さて、多くの宝くじに参加した場合、さらに何回参加したかに応じて、当選の可能性は少し高くなります。これは、最終的に当選するという保証はまだありませんが、均一な分布の場合です。そして、大数の法則 (この場合は多数の抽選を意味します) に従うと、比較的可能性の高い可能性に到達できます。

新しい宝くじはそれぞれ独立しており、同じ宝くじの「チケット番号」が (大数の法則に従って) 多くの異なる宝くじに当たる可能性があることを理解することが重要です。運が悪いと、何度試しても、毎回の宝くじで間違った数字を選んでしまう可能性もあります。現在、2 つのオプションがあります:

  1. 毎回乱数を試すことができます。
  2. 毎回同じ番号を試すことができます。

理論的に (そして数学的に)、両方のシナリオが発生する可能性は同じです。ただし、シナリオ 2 の方がわずかに有利になります。回数が無限に近づくと、最終的にはすべての数字が選択されます。問題は、シナリオ 1 では、その時点で選んだ数字が勝ちの数字と一致することを期待して、さらに何度も試行する必要があることです。シナリオ 2 では、試行は無限に進む傾向があるため、ある時点であなたの番号が「勝つ」ことが確実です。このブログ投稿では、シナリオ 2 を使用します。

それでは、私が答えを言う前に、この質問に答えられると思いますか?

「あなたの周りのすべての宝くじにちょうど 100 万人分のスロットがあり、プレイした全員に同じチケット [x] を選択した場合、最終的に当選者になるには何回の宝くじをプレイする必要がありますか?」 (最初の答えが何であったかについてお気軽にコメントしてください)

答えは...
How a Lottery Quest Led Me to The Powers of PyTorch

1,440万回

このブログ投稿の残りの部分では、どのようにしてその値に到達したか、シミュレーションがどのように行われたか、およびいくつかの注意点について説明します。ここからはさらに技術的な話になります。
How a Lottery Quest Led Me to The Powers of PyTorch

論理

100 万人の宝くじのチケット番号は、1 ~ 1,000,000 (または 0 ~ 999,999) の範囲になります。プレイヤーは各宝くじでその範囲内の数字のみを選択でき、当選チケットはその範囲からのみ選択できます。基本的に、100 万個の数値のセットがあると言えます。

ユーザーがその範囲内の任意の数値を選択できるという事実を考慮すると、セット内のすべての項目が少なくとも 1 回ヒットするという条件を満たす必要があります。これは、すべての番号が少なくとも 1 回コールされていれば、プレーヤーが選択できるすべてのチケット番号がカバーされるためです。これは、各数値が実行される回数を気にしないことも意味し、「セット」がシミュレーションに使用する理想的な Python データ構造になります。空のセットから開始し、セットに指定された範囲内のすべての数値が含まれるまで、反復ごとにランダムに生成された数値をそのセットに入力します。 Python セットは数値を繰り返さないため、一意性の確保について心配する必要はありません。

def calculate_lottery_chances(lottery_players_count):
  number_set = set()
  count = 0

  while len(number_set) < lottery_players_count:
    gen_number = random.randint(1, lottery_players_count)
    number_set.add(gen_number)
    count += 1

  return count
ログイン後にコピー
ログイン後にコピー

1,000,000 人の宝くじの場合、関数呼び出しは Calculate_lottery_chances(1000000) のようになり、当選するまでの宝くじの試行回数が返されます。このようにコードを配置すると、非常に拡張可能になります。

How a Lottery Quest Led Me to The Powers of PyTorch

問題

一言で言えば、問題の根本原因は「ばらつき」です。初めて関数を実行したとき、値として「1,310 万」回を取得しました。再実行したところ、1,390 万程度の値が得られました。これをさらに何度も繰り返したところ、さまざまな答えが得られ、ある時点で 1,500 万を獲得しました。これを実行して平均値を見つける必要があることは明らかでした。これまでの既存のパターンに従って、平均化する反復回数が無限に近づくにつれて、1 つ の信頼できる答えに近づくだろうと考えました。これを高速に実行できるものが必要だったので、この関数を作成することにしました。

def average_over_n_times(function, function_arg, n):
  """
  This returns the average of the returned value of a function
  when it is called n times, with its (one) arg
  """
  total = 0
  for x in range(0, n):
    total += function(function_arg)

  return round(total/n)
ログイン後にコピー

その後、すべてが次のように修正されます:

num_of_trials = average_over_n_times(calculate_lottery_chances, lottery_players_count, n)

ログイン後にコピー

ここで、「n」は結果を平均化する回数を表します。ただし、これは次のセクションで説明する別の問題を引き起こします。

「ん」は何にすべきでしょうか?

n の値が大きいほど、「平均的な場合」の結果に近づきます。ただし、まだ絶対や確実性がないことを考えると、この一連の作業を何度も実行すると生産性が低下します。私がこれを言うのは次の理由からです:

  • 時間は無限ではなく、これらの計算を無限に実行することはできません。つまり、計算を実行するたびに (どんなに小さくても) 常に変動があり、「絶対」という考えは無効になります。
  • 計算リソースは有限です。
  • この実験の前提の 1 つは、コンピューターによって生成される「ランダム性」が現実を正確に模倣できるということです。
  • アルゴリズムの実行時間と同様に、より小さな規模はより大きな規模と同じくらい重要ではなくなります。 13,000,000 を超える値を扱う場合、約 100,000 の変動はそれほど重要ではありません。

これらを念頭に置いて、「n」を次の値でテストしました: 10、20、30、50、100、1000、および 5000 回

PyTorch はどこに登場するのでしょうか?

この時点で、ブログ投稿のタイトルにある「PyTorch」という単語がなぜ言及されていないのか疑問に思われたかもしれません。さて、さまざまな値で n をテストすると述べましたが、それはすべてのテストに使用したのと同じコードではありませんでした。

これらは計算量の多い実験であり、私の CPU は私に連絡をくれました。以前に共有したコード スニペットは、外部パッケージの依存関係がまったくない 1 つのファイルに書かれており、そのファイルは、実行時間を追跡するために time コマンドを先頭に付けて bash シェルで実行されました。 CPU のみを使用した場合の実行時間は次のようになります:

n Time (min and sec)
10 1m34.494s
20 3m2.591s
30 5m19.903s
50 10m58.844s
100 14m56.157s

1000 で、プログラムを動作させることができなくなりました。途中で切れて実行停止に失敗したのかは分かりませんでしたが、4時間57分後にキャンセルしました。これにはいくつかの要因が影響していると思われますが、それについては「注意事項」セクションで説明します。とにかく、ファンの音がうるさかったので、ラップトップのそれほど強力ではない CPU を少し使いすぎたのかもしれないと思いました。私は敗北を受け入れることを拒否し、少なくとも 4 桁の反復を実行するにはどうすればよいかを考えていたとき、PyTorch を使っていた友人が私に言ったことを思い出しました。

「一般に、GPU は CPU よりも大量の計算処理において効率的です。」

PyTorch は GPU を使用するため、この作業に最適なツールです。

リファクタリング

今回の目的では PyTorch が計算に使用されるため、既存の Calculate_lottery_chances() コードをリファクタリングすることは、CPU に依存した数値演算を変更し、適切な PyTorch データ構造に切り替えることを意味します。一言で言えば:

  • Python set() データ型ではもう不十分です。
  • Python randint() 関数は、同等の PyTorch 関数に置き換えられます。
  • set() データ型では不十分であるため、数値が以前に当選したかどうかを示すブール値を使用して、lottery_players_count のサイズに一致するゼロのテンソルを生成するように切り替えられます。

calculate_lottery_chances のリファクタリングは次のようになります:

def calculate_lottery_chances(lottery_players_count):
  number_set = set()
  count = 0

  while len(number_set) < lottery_players_count:
    gen_number = random.randint(1, lottery_players_count)
    number_set.add(gen_number)
    count += 1

  return count
ログイン後にコピー
ログイン後にコピー

私のコンピューターでは PyTorch がサポートするインテル グラフィックス GPU を使用しているため、デバイスを「xpu」に設定しました。

出力

実行中に GPU が使用されていることを確認するために、実行前に Windows タスク マネージャーを開き、「パフォーマンス」セクションに移動しました。実行すると、GPU リソースの使用量が顕著に急増していることがわかりました。
コンテキストのために、前と後を次に示します:

前:

How a Lottery Quest Led Me to The Powers of PyTorch
GPU 使用率が 1% であることに注目してください

後:

How a Lottery Quest Led Me to The Powers of PyTorch
GPU 使用率が 49% であることに注目してください

n の値を変化させた場合のランタイムでは、GPU は数倍高速でした。 100 未満の n の値を 1 分未満で一貫して実行し、5000 (5,000!)

の n の値を計算することができました。

GPU を使用したランタイムの表は次のとおりです:

n Time (min and sec)
10 0m13.920s
20 0m18.797s
30 0m24.749s
50 0m34.076s
100 1m12.726s
1000 16m9.831s

この実験での GPU 操作と CPU 操作のパフォーマンスの差がどれほど大きかったかを視覚的に理解するために、以下のデータ視覚化を考慮してください。

How a Lottery Quest Led Me to The Powers of PyTorch

CPU から現実的に「タイムリーな」出力を得ることができなくなり、GPU と比較する余地がなくなったため、X 軸の上限は 100 になりました。 1,000 ~ 5,000 の範囲の数値で実験を実行すると、結果として「1,440 万回」ほどの結果が得られることが多かったです。それが先ほどの答えです。

注意事項

この実験では仮説を立て、特定の方法に依存しました。さらに、私には PyTorch の経験が浅いため、より効率的なアプローチがあった可能性があります。 結果の精度または実行時間に影響を与えた可能性があると考えられる、考慮すべきいくつかの要因を以下に示します。

  1. 私は、コンピュータで生成されたランダム性が現実世界 (物理世界) のランダム性を模倣しているという微妙な仮定を立てました。
  2. PyTorch を使用するようにロジックを少し切り替えましたが、コードの残りの部分は依然として CPU に依存していました。たとえば、average_over_n_times() 関数では、ループ内の加算と平均化の両方が PyTorch の同等の機能の恩恵を受けている可能性があります。パフォーマンスが向上したのではないかと思います。
  3. 使用したバッチサイズが精度とパフォーマンスに与える影響がわかりません。
  4. すべての CPU と GPU のテストは、マシンが最高の状態で動作できるように、PC に接続した状態で行われました。バッテリー電源でデバイスを使用して実行すると、実行時間が長くなる可能性があります。
  5. PyTorch の CUDA は「XPU」よりも優れている可能性がありますが、私の PC は前者をサポートしていません。
  6. テスト中は PC を「スリープ」状態にしないようにしました。コンピューターがスリープ状態の場合、テストの実行に時間がかかる可能性があります。

最後に、私は PyTorch を初めて使用したのですが、そのパフォーマンスに非常に感銘を受けたことを指摘しておきます。

結論

これを使ってウサギの穴に落ちたとき、これほどパフォーマンスが向上するとは予想していませんでした。私はテンソルの背後にある考え方と、さらに計算的に複雑なタスクの背後にあるサポートメカニズムについていくつか学びました。コード スニペットを自由に使用、複製、変更することができます。

お楽しみいただきありがとうございます。楽しくお読みいただければ幸いです。

次回まで

乾杯。 ?

以上が宝くじのクエストが私を PyTorch のパワーに導いた経緯の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート