はじめに
『機械学習のエッセンス(http://isbn.sbcr.jp/93965/)』のPythonサンプルをJuliaで書き換えてみる。(第04章05NumPy/SciPyによる線形代数)の続きです。
rand関数を使う
Juliaではrand
関数を使います。
https://docs.julialang.org/en/v1/stdlib/Random/index.html
日本語訳はこちら。
https://code.i-harness.com/ja/docs/julia~1.0/stdlib/random/index
- 0〜1の範囲の浮動小数点数を返す
julia> rand()
0.8168800696780041
julia> rand()
0.7217680180694137
- 引数を指定すると配列を返す
julia> rand(3, 2)
3×2 Array{Float64,2}:
0.0957013 0.284191
0.0393057 0.781931
0.614824 0.77722
- 整数型の乱数を返す
julia> rand(1:4)
4
julia> rand(10:20)
15
- 範囲の後に行列のサイズを指定するとその行列を返す
julia> rand(1:5, 3, 3)
3×3 Array{Int64,2}:
5 1 1
4 5 5
3 4 3
再現性と乱数の種
function throw_dice(n)
sum(rand(1:6, n))
end
throw_dice
関数の実行
julia> include("dice1a.jl")
throw_dice (generic function with 1 method)
julia> throw_dice(10)
35
julia> throw_dice(10)
30
julia> throw_dice(10)
38
乱数の種を指定する
Juliaでseedを設定するにはRandom.seed!
関数を使います。
https://docs.julialang.org/en/v1/stdlib/Random/index.html#Generators-(creation-and-seeding)-1
引数の内容を変更する場合関数に!
を付ける慣例になっているようです。
https://docs.julialang.org/en/latest/manual/style-guide/#Append-!-to-names-of-functions-that-modify-their-arguments-1
using Random
を実行してもseed!
だけではエラーになりました。
julia> using Random
julia> seed!(10)
ERROR: UndefVarError: seed! not defined
Stacktrace:
[1] top-level scope at none:0
julia> Random.seed!(10)
MersenneTwister(UInt32[0x0000000a], Random.DSFMT.DSFMT_state(Int32[1007524736, 1073256705, 415953332, 1072893275, -601364280, 1073193666, -1335760268, 1072926448, 1521827180, 1073499520 … -439825479, 1072978026, -411693740, 1073111955, -1611334130, 1963385220, 236575170, -789052601, 382, 0]), [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0
.0, 0.0 … 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], UInt128[0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000 … 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000], 1002, 0)
julia> rand(5)
5-element Array{Float64,1}:
0.11258244478647295
0.36831406658084287
0.3444540231363058
0.05664544616214151
0.12078054506961555
julia> Random.seed!(10)
MersenneTwister(UInt32[0x0000000a], Random.DSFMT.DSFMT_state(Int32[1007524736, 1073256705, 415953332, 1072893275, -601364280, 1073193666, -1335760268, 1072926448, 1521827180, 1073499520 … -439825479, 1072978026, -411693740, 1073111955, -1611334130, 1963385220, 236575170, -789052601, 382, 0]), [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 … 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], UInt128[0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000 … 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000], 1002, 0)
julia> rand(5)
5-element Array{Float64,1}:
0.11258244478647295
0.36831406658084287
0.3444540231363058
0.05664544616214151
0.12078054506961555
julia> Random.seed!(100)
MersenneTwister(UInt32[0x00000064], Random.DSFMT.DSFMT_state(Int32[-2036630343, 1072818225, 1299231502, 1073154435, 1563612565, 1073206618, 176198161, 1073683625, 381415896, 1073699088 … 163992627, 1073241259, 385818456, 1072878963, 399273729, 595433664, 390891112, 1704156657, 382, 0]), [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 … 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], UInt128[0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000 … 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000], 1002, 0)
julia> rand(5)
5-element Array{Float64,1}:
0.2601250914736861
0.19031281518127185
0.6609109399808133
0.06719317094984745
0.9675998379215747
julia> Random.seed!(100)
MersenneTwister(UInt32[0x00000064], Random.DSFMT.DSFMT_state(Int32[-2036630343, 1072818225, 1299231502, 1073154435, 1563612565, 1073206618, 176198161, 1073683625, 381415896, 1073699088 … 163992627, 1073241259, 385818456, 1072878963, 399273729, 595433664, 390891112, 1704156657, 382, 0]), [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 … 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], UInt128[0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000 … 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000], 1002, 0)
julia> rand(5)
5-element Array{Float64,1}:
0.2601250914736861
0.19031281518127185
0.6609109399808133
0.06719317094984745
0.9675998379215747
-
Random.seed!
関数を使って、結果が再現するようにthrow_dice
を書き換える。
using Random
function throw_dice(n, random_seed = 10)
Random.seed!(random_seed)
sum(rand(1:6, n))
end
改良したthrow_dice
関数を使う
julia> include("dice1b.jl")
throw_dice (generic function with 2 methods)
julia> throw_dice(10)
31
julia> throw_dice(10)
31
julia> throw_dice(100)
363
julia> throw_dice(100)
363
よくない実装の例
- Juliaのオブジェクト指向について
Juliaはクラスベースのオブジェクト指向言語ではなく、struct
で型を決めるようです。
https://docs.julialang.org/en/v1/manual/types/#Composite-Types-1
クラスがないので、実はここの書き換えは苦労しました。struct
にはコンストラクタはあるけどメソッドの定義はできなさそうだし、下記は試行錯誤した結果です。throw
関数は個別になっています。もっといい書き方があるのかもしれません。またプロパティは.
で取得できるので、get_sum
関数は作りませんでした。
using Random
mutable struct Dice
sum_::Float64
function Dice()
Random.seed!(0)
new(0)
end
end
function throw(x::Dice)
x.sum_ += rand(1:6)
end
Diceクラスを使う
- 合計が同じになる
julia> include("dice2a.jl")
throw (generic function with 1 method)
julia> d1 = Dice()
Dice(0.0)
julia> for i in 1:10
throw(d1)
end
julia> d1.sum_
28.0
julia> d2 = Dice()
Dice(0.0)
julia> for i in 1:10
throw(d2)
end
julia> d2.sum_
28.0
- 合計が異なる
julia> d1 = Dice()
Dice(0.0)
julia> d2 = Dice()
Dice(0.0)
julia> for i in 1:10
throw(d1)
throw(d2)
end
julia> d1.sum_
24.0
julia> d2.sum_
42.0
RandomStateクラスに相当するもの
下記マニュアルを見たのですが、明確にはわかりませんでした。
https://docs.julialang.org/en/v1/stdlib/Random/#Random.seed!
Examplesを見る限りMersenneTwister
をrand
の引数に入れることで出来そうな感じだったので下記のように作ってみたところ想定した結果にはなりました。
ただし、すみませんがあまり自信はありません。
※ random_seed
のデフォルトをNone
にする部分も実装できていません。
using Random
mutable struct Dice
sum_::Float64
rng::MersenneTwister
function Dice(random_seed::Int)
rng = MersenneTwister(random_seed)
new(0, rng)
end
end
function throw(x::Dice)
x.sum_ += rand(x.rng, 1:6)
end
動作の確認
julia> include("dice2b.jl")
throw (generic function with 1 method)
julia> d1 = Dice(123)
Dice(0.0, MersenneTwister(UInt32[0x0000007b], Random.DSFMT.DSFMT_state(Int32[1464307935, 1073116007, 222134151, 1073120226, -290652630, 1072956456, -580276323, 1073476387, 1332671753, 1073438661 … 138346874, 1073030449, 1049893279, 1073166535, -1999907543, 1597138926, -775229811, 32947490, 382, 0]), [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0 … 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], UInt128[0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000 … 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000], 1002, 0))
julia> d2 = Dice(123)
Dice(0.0, MersenneTwister(UInt32[0x0000007b], Random.DSFMT.DSFMT_state(Int32[1464307935, 1073116007, 222134151, 1073120226, -290652630, 1072956456, -580276323, 1073476387, 1332671753, 1073438661 … 138346874, 1073030449, 1049893279, 1073166535, -1999907543, 1597138926, -775229811, 32947490, 382, 0]), [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 … 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], UInt128[0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000 … 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000], 1002, 0))
julia> for i in 1:10
throw(d1)
throw(d2)
end
julia> d1.sum_
33.0
julia> d2.sum_
33.0