ドキュメンテーション センター

  • 評価版
  • 製品アップデート

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

乱数発生器の制御

この例では、乱数発生器を制御する関数 rng を使用する方法を示します。

MATLAB の (疑似) 乱数は、関数 randrandi、および randn で生成されます。他の多くの関数がこの 3 つの関数を呼び出しますが、これらは基本ブロックです。3 つの関数はすべて、rng を使って制御できる 1 つの共有乱数発生器に依存します。

MATLAB の "乱数" は予測不可能ですが、決定性アルゴリズムによって生成されるということを理解しておいてください。このアルゴリズムは、アルゴリズムを知らなければその出力が独立した乱数列に "見える" ように十分に複雑になるように設計されていて、ランダム性のさまざまな統計検定にも合格できます。ここで紹介する関数を使用すると、次の項目を実行するために確定性を利用できます。

  • 乱数に関連する計算を反復して同じ結果を取得する。

  • 反復計算で異なる乱数が使用されることを保証する。

また、見かけのランダム性を利用して個々の計算結果の組み合わせが正しいことを証明します。

"やり直し"

新しい MATLAB セッションで randrandi、または randn の出力を確認すると、MATLAB を再起動するたびに同じ数列が返されることに気付きます。これは、実際に MATLAB を再起動しなくても乱数発生器を起動時の状態にリセットできるので多くの場面で役立ちます。たとえば、乱数を含む計算を反復して同じ結果を得る必要がある場合などです。

rng を使用すると、乱数発生器を既定の設定に簡単に戻すことができます。

rng default
rand % returns the same value as at startup
ans =

    0.8147

MATLAB の起動時の "既定の" 乱数設定はどのような内容で、rng default にはどのような機能があるのでしょう。入力なしで rng を呼び出すと、シードが 0 の Mersenne Twister 発生器アルゴリズムであることがわかります。

rng
ans = 

     Type: 'twister'
     Seed: 0
    State: [625x1 uint32]

State フィールドなどの上記の出力を使用して MATLAB が乱数を生成する方法を制御および変更する方法の詳細は、以下を参照してください。ここでは、発生器 randrandi、および randn が現在使用しているものを確認するために使用されています。

非反復性

randrandi、または randn は呼び出されるたびに共有乱数発生器から新しい値を取り出し、連続した値は統計的に独立した値として処理されます。しかし前述のように、MATLAB を再起動するたびにこれらの関数はリセットされて同じ数列を返します。"同一の乱数" を使用する計算が統計的に独立しているとは考えられないことは明らかです。そのため、複数の MATLAB セッションで実行される計算が統計的に "独立しているように" その計算を組み合わせる必要がある場合、既定の発生器の設定は使用できません。

新しい MATLAB セッションで同じ乱数が繰り返されないようにするには、乱数発生器に異なるシードを選択する方法が簡単です。rng を使うと、現在時刻に基づいたシードを作成することによって同じ乱数の発生を簡単に回避できます。

rng shuffle
rand
ans =

    0.7631

'shuffle' は、使用されるたびに異なるシードで発生器を再シードします。入力なしで rng を呼び出すと、実際に使用されるシードの内容を確認できます。

rng
ans = 

     Type: 'twister'
     Seed: 1874111095
    State: [625x1 uint32]

rng shuffle % creates a different seed each time
rng
ans = 

     Type: 'twister'
     Seed: 1874111099
    State: [625x1 uint32]

rand
ans =

    0.6030

'shuffle' を使用すると、乱数発生器の再シードが非常に簡単です。MATLAB で "本来の" ランダム性を確保するには shuffle の使用が便利な場合も必要な場合もあります。ただし、多くの場合、'shuffle' を必ず使用しなければならないということではありません。現在時刻に基づいてシードを選択すると、randrandi、および randn から得られる値の統計的な特性は向上せず、本当の意味で "ランダム性を高める" ことはできません。MATLAB の起動時や乱数を含む大規模な計算を実行する前に発生器を再シードしてもよいですが、乱数の統計的な特性に影響を及ぼす可能性があるため、実際には 1 つのセッションで何回も発生器の再シードを行うのはお勧めできません。

'shuffle' を使用すると同一の値の系列の繰り返しを回避できますが、これが重要な場合もあれば、"便利" であるにすぎない場合もあり、さほど重要でない場合がほとんどです。'shuffle' を使用する場合は、後で計算を繰り返せるように rng が作成したシードを保存することを忘れないでください。以下にその方法を示します。

反復性と非反復性の強力な制御

これまでのところ、乱数発生器を既定の設定にリセットする方法と、現在時刻から作成されるシードを使用して発生器を再シードする方法を確認してきました。また、rng を使用すると特定のシードを使って発生器を再シードできることも説明しました。

同じシードを何回も使用して同じ計算を繰り返すことができます。たとえば、次のコードを 2 回実行します。

rng(1) % the seed is any non-negative integer < 2^32
x = randn(1,5)
x =

   -0.6490    1.1812   -0.7585   -1.1096   -0.8456

rng(1)
x = randn(1,5)
x =

   -0.6490    1.1812   -0.7585   -1.1096   -0.8456

... まったく同じ結果が得られます。これを実行するのは、特定の値を使用して x に依存するその後の計算内容を繰り返すことができるように、消去後に x を再び作成する場合などです。

一方で、同じ計算を繰り返さないように、"異なる" シードを選択する場合があります。たとえば、1 つの MATLAB セッションで次のコードを実行します。

rng(2)
x2 = sum(randn(50,1000),1); % 1000 trials of a random walk

別のセッションでは次のコードを実行します。

rng(3)
x3 = sum(randn(50,1000),1);

... 2 つの結果を組み合わせると、単に 2 回繰り返されて同じ結果になったのではないことがわかります。

x = [x2 x3];

'shuffle' と同様に、MATLAB の乱数発生器を再シードする際は注意してください。randrandi、および randn のその後のすべての出力に影響するためです。反復性または一意性が必要ない場合、一般的には発生器を再シードしないで単に乱数を生成することをお勧めします。発生器を再シードする必要がある場合は、コマンド ラインで行うか、コード内の見落としにくい場所で行ってください。

発生器のタイプの選択

前述のように乱数発生器を再シードできるだけでなく、使用する乱数発生器のタイプを選択することもできます。発生器のタイプが異なると発生する乱数列も異なります。たとえば統計的な特性に基づいて特定のタイプを選択する場合もあります。また、MATLAB の古いバージョンで使われていた別の既定の発生器タイプの結果を再作成する場合もあります。

他に発生器のタイプを選択する理由として、"ランダムな" 入力データを生成する検証試験を記述して、その検定で常にまったく同じ予測どおりの結果が得られることを保証する場合があります。入力データを作成する前にシードで rng を呼び出すと、乱数発生器が再シードされます。しかし、何らかの理由で発生器のタイプが変更されていると、randrandi、および randn の出力はそのシードから予測される出力とは異なる内容になります。したがって、反復性を確実にするには、発生器のタイプも指定します。

たとえば、次のコマンドを実行します。

rng(0,'twister')

これにより、randrandi、および randn はメルセンヌ・ツイスター発生器アルゴリズムを 0 でシードしてから使用します。

次のように 'combRecursive' を使用するとします。

rng(0,'combRecursive')

これにより、Combined Multiplicative Recursive 発生器アルゴリズムが選択されます。このアルゴリズムは、メルセンヌ・ツイスターではサポートされないいくつかの並列機能をサポートします。

次のコマンドを実行するとします。

rng(0,'v4')

これにより、MATLAB 4.0 の既定の設定だった発生器アルゴリズムが選択されます。

次のコマンドは乱数発生器を既定の設定に戻します。

rng default

ただし、乱数発生器の既定の設定は MATLAB リリース間で変更されている場合があることから、'default' による予測結果については長期的な保証はありません。'default' は乱数発生器をリセットするには便利ですが、より高い予想精度を求める場合は、発生器のタイプとシードを指定してください。

一方、対話的に操作して反復性が必要な場合は、シードを指定して rng を呼び出す方法が簡単であり、通常はこの方法で十分です。

乱数発生器の設定内容の保存と復元

入力なしで rng を呼び出すと、前述の 2 つの情報である、発生器のタイプと発生器を前回再シードしたときの整数値を含むスカラー構造体が返されます。

s = rng
s = 

     Type: 'twister'
     Seed: 0
    State: [625x1 uint32]

3 番目のフィールド State には、発生器の現在の状態ベクトルのコピーが含まれています。この状態ベクトルは、発生器が乱数列の次の値を生成するために内部で保持する情報です。randrandi、または randn が呼び出されるたびに、これらが共有する発生器は内部状態を更新します。したがって、rng によって返される設定構造体の状態ベクトルは、その状態がキャプチャされた点から始まる数列を繰り返すために必要な情報を含んでいます。

この出力を確認することも有益ですが、rng "入力" として設定構造体を受け入れるため、状態ベクトルなどの設定内容を保存し、それを復元して後で計算を繰り返すことができます。設定には発生器のタイプも含まれるため、出力の内容を正確に把握できます。また、上述の "後で" は、同じ MATLAB セッションの数秒後から、いくつもの MATLAB リリースを経た数年後まで含まれます。発生器の設定を保存した乱数列の点から結果を繰り返すことができます。例を次に示します。

x1 = randn(10,10); % move ahead in the random number sequence
s = rng;           % save the settings at this point
x2 = randn(1,5)
x2 =

    0.8404   -0.8880    0.1001   -0.5445    0.3035

x3 = randn(5,5);   % move ahead in the random number sequence
rng(s);            % return the generator back to the saved state
x2 = randn(1,5)    % repeat the same numbers
x2 =

    0.8404   -0.8880    0.1001   -0.5445    0.3035

再シードでは大まかな再初期化が行われるだけですが、設定構造体を使用して発生器の状態を保存および復元すると、乱数列の "どの部分" でも繰り返すことができます。

設定構造体の一般的な使用方法は、発生器の状態の復元です。ただし、構造体には状態だけでなく発生器のタイプとシードも含まれているため、発生器のタイプを一時的に切り替えるときにも便利です。たとえば、MATLAB 5.0 の従来の発生器のいずれかを使用して値を作成する場合は、古い発生器を使用するために切り替えるのと同時に現在の設定を保存できます。

previousSettings = rng(0,'v5uniform')
previousSettings = 

     Type: 'twister'
     Seed: 0
    State: [625x1 uint32]

... さらに、後で元の設定を復元できます。

rng(previousSettings)

設定構造体のフィールドの内容を変更する必要はありません。具体的には、独自の状態ベクトルを構成する必要がなく、発生器の状態の形式にも影響されません。

簡潔で柔軟性の高いコードの記述

rng を使用すると、次のいずれかを実行できます。

  • 乱数発生器の再シード

  • 乱数発生器の設定の保存と復元

発生器のタイプを把握する必要はありません。また、乱数発生器の設定内容を知らなくても、既定の設定に戻すことができます。発生器のタイプを指定する必要がある場合でも、rng を使用すると指定する必要がなくなります。

発生器のタイプを指定する必要がなくなれば、使用する発生器が異なる場合にもコードが自動的に適合して、新しい既定の乱数発生器のタイプがもつ改良された特性を自動的に活用することができます。

レガシ モードと rng

MATLAB 7.7 以前のバージョンでは、'seed'、'state'、または 'twister' 入力で rand または randn を直接呼び出すことによって乱数発生器の内部状態を制御していました。たとえば、以下のようなものがあります。

rand('state',1234)

この構文は推奨されません。この構文は MATLAB を "レガシ乱数モード" に切り替えます。このモードでは randrandn は個々の古い発生器を使用し、MATLAB 7.7 以前のバージョンと同様に機能します。可能であれば、古い構文を使用する既存のコードを更新して、代わりに rng を使用してください。そのためには、古いコードの意図をよく検討してください。提案事項と例は、ユーザー ガイドの「乱数発生器構文の更新乱数発生器構文の更新」を参照してください。

実行したコードで MATLAB をレガシ モードにする rand('state',1234) のようなコマンドが実行された場合は、次のコマンドを使用できます。

rng default

上記のコマンドを使用すると、レガシ モードから既定の起動時の発生器に戻ることができます。変更できない、または変更が許可されていないコードがある場合は、次のコマンドを使用すると古いコードから保護できます。

s = rng; % save current settings of the generator

% call code using legacy random number generator syntaxes

rng(s) % restore previous settings of the generator

他のコードで従来の乱数発生器が使用されていないことを確認してください。

rng および RandStream

一般的な必要性に応じて MATLAB で乱数発生器を制御するには、rng が最も便利です。ただし、複数の乱数ストリームや並列乱数生成を含む複雑な状況では、より複雑なツールが必要です。RandStream クラスがそのツールで、乱数生成を最も強力に制御できます。この 2 つのツールは相補的な関係にあり、rng では RandStream の柔軟性に基づいて構築される単純で簡潔な構文を作成できます。

この情報は役に立ちましたか?