Week 8: グループワーク2(1回目)
今日やること
はじめに
最初に少し講義をします。
その後、チームに分かれて作業を行います。
内包表記
便利ですが慣れないとわかりにくい記法として、内包表記があります。これは、数学の集合記法に似ています。例えば、\(x\)が\(1\)から\(5\)までの整数の集合を考えます。 この集合の各要素を二乗した集合である\(\mathcal{S}\)を考えたいとします。これは数式としてはセットビルダーノテーションを用いて次のように書けます。
\[ \mathcal{S} = \{x^2 \mid x \in \{1, \dots, 5\}\} \]これと同様の処理が、juliaでは次のように書けます。
S = [x^2 for x in 1:5]
この結果は次のようになります。
5-element Vector{Int64}:
1
4
9
16
25
ここでは得られるものは集合ではなくベクトルですが、数式の場合と同様の処理を実現できています。
また、この表記は多次元にも拡張できます。以下のように、iとjから行列を構成できます。
[2i + j for i in 1:4, j in 1:3]
4×3 Matrix{Int64}:
3 4 5
5 6 7
7 8 9
9 10 11
時間計測
juliaで作業の時間を計測するには、関数の先頭に@timeをつければよいです。例えば大きな行列を2つ作り、その行列積にかかる時間を計測してみましょう。
A = rand(1000, 1000)
B = rand(1000, 1000)
@time C = A * B
0.093328 seconds (2 allocations: 7.629 MiB)
(以下、行列の中身が表示される)
ちなみに、juliaは「最初の1回の実行は遅い」という特性があります。上記を2回実行すると、2回目のほうがずっと早いかもしれません。
また、ベンチマークツールを用いることもできます。まず、BenchmarkToolsというパッケージをインストールしましょう。 以下を実行してください。これは一度だけでOKです。
import Pkg
Pkg.add("BenchmarkTools")
これは、パッケージを追加するためのパッケージであるPkgを読み込み、それを経由してBenchmarkToolsをインストールしています。 このパッケージは初期状態では準備されていないので、上記を用いてインストールする必要があります。
ひとたびインストールすると、これを使える様になります。以下のようにしてBenchmarkToolsパッケージを インポートしましょう。
using BenchmarkTools
これも、プログラムの中で1度行うだけでいいです。
次に、実際に計測してみましょう。
@benchmark C = A * B
ここでは自動的に処理を何度も実行し、以下のようにビジュアルに結果を出力してくれます。
BenchmarkTools.Trial: 45 samples with 1 evaluation.
Range (min … max): 73.526 ms … 188.175 ms ┊ GC (min … max): 0.00% … 0.00%
Time (median): 114.416 ms ┊ GC (median): 0.00%
Time (mean ± σ): 112.045 ms ± 22.360 ms ┊ GC (mean ± σ): 0.12% ± 0.32%
▂█ ▂▂
▅▅▅██▁▁▅▅█▁█▁▁▁▁▁▅█▅█████▁▅▅▁██▁▁█▅▁▅▁▅▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▅ ▁
73.5 ms Histogram: frequency by time 188 ms <
Memory estimate: 7.63 MiB, allocs estimate: 2.
関数に「!」マーク
関数名の最後に!をつけると、その関数は「破壊的」であることを示します。これは、関数が引数を変更することを意味します。 例えば次を考えましょう。
arr = [10; 20; 30]
push!(arr, 40)
4-element Vector{Int64}:
10
20
30
40
ここでは、push!という関数は、ベクトルの一番最後に要素を追加してくれます。この関数は、引数であるベクトルarrの 中身を変更します。なので、関数名に!がついています。同様に、pop!という関数は、ベクトルの一番最後の要素を取り除いてくれます。
pop!(arr)
arr # 表示
3-element Vector{Int64}:
10
20
30
この!をつけるという操作はjuliaにおける慣習であり、単なる命名規則になっています。皆さんも、自分で関数を作る際に、それが引数を変更する場合は!をつけるようにしましょう。
BigInt / BigFloat
さて、Juliaを始め通常プログラミング言語では、整数や少数を表すために使うビット数には上限があります。例えば以下を実行してみましょう。
a = 2^63-1
println("a's type: ", typeof(a))
println("a = ", a)
println("a + 1 = ", a + 1)
ここでは結果は次のようになります
a's type: Int64
a = 9223372036854775807
a + 1 = -9223372036854775808
これはすなわち、特に指定しなければ整数にはInt64の型が割り振られる、すなわち64bitの情報で整数を表現するということになります。 64bitで正負の数字を表現する関係上、2^63の数字までは正しく処理できるのですが、2^63 + 1になると正しく表現できなくなります(そのビット列は負の数に割り当てられているため、負の数になります)。 ちなみにここでなぜこのような変な巨大な数になるか知りたい方は私の別の講義の2の補数というところをご参照ください。
Juliaには、大きな数であっても扱える特別な型であるBigIntが準備されています。これを用いると、次のように、64bitの限界を超える整数演算も実行することが出来ます。
b = BigInt(2^63 - 1)
println("b's type: ", typeof(b))
println("b = ", b)
println("b + 1 = ", b + 1)
この結果は次のようになり、正しく表現できています。
b's type: BigInt
b = 9223372036854775807
b + 1 = 9223372036854775808
計算の途中で変数の値の限界を超えてしまうという場合は、これらを試してみてもいいでしょう。この少数版であるBigFloatも準備されています。
ちなみに、最初からすべての変数をBigIntやBigFloatにしておけばいいのでは?と思うかもしれません。しかし、変数はとてもプリミティブなものであり、固定長のビットで表現されているからこそ、演算を高速に行えることが出来ます。全てをBigIntなどにしてしまうと、演算がとても遅くなってしまい、またメモリ消費量も増加してしまいます。
やってみよう:
上記を写経しましょう
複雑な内包表記を書いてみましょう。
これまでに作ったプログラムについて、時間を計測してみましょう。
これまでに作ってプログラムについて、内容を変更するものがあったなら、
!をつけてみましょう。少数演算において正しく表現ができない例を調べ、それに対し
BigFloatを適用してみましょう。
チーム作業
それではチームに分かれてもらいます。
線形代数に関するトピックを調べ、それらをJuliaで実装してみてください。
線形代数の講義の内容で納得のいっていない点とか、いまいち腑に落ちない点とかを議論してください。
それらをJuliaで実装してみてください。
例えば、
線形独立という概念がよくわからない。実際にJuliaでランダムベクトルを作って検証してみる。
逆行列が計算できる例とできない例を作ってみる。
などです。今週と来週に色々実装してもらい、その次の週に発表を行ってもらいます。
トピックについて、例えば下記の書籍の目次などが参考になるかもしれません。
M. P. Deisenroth+, "機械学習のための数学", 共立出版: 機械学習に進む人にとって難しすぎない、必要十分な範囲の数学を学べる本です。今後AI分野などに進みたい人は、この本を一冊読んでおくといいかもしれません。原著は有名な教科書で、pdfが無料公開されています。
ボイドら、"スタンフォード ベクトル・行列からはじめる最適化数学",講談社: 最小二乗法を基本とした初等的な最適化問題について、平易な言葉で説明されています。Juliaによるソースコードが配布されています。
山中 勇毅, "セガ的 基礎線形代数講座", 日本評論社: ゲーム会社のセガの人たちが書いた線形代数の教科書だそうです。ゲームのキャラクタの回転運動などは線形代数で表現されます。ゲームに興味のある人は面白いかもしれません。
室田 一雄ら,"基礎系 数学 線形代数I (東京大学工学教程)", 丸善出版: 薄いですが、線形代数の基本が書かれています。前半は証明を丁寧に、後半の応用パートは証明は省き気味になっており、諦めずに実際に概観を理解することを重視した構成になっています。
ストラング、"線形代数とその応用", 産業図書: 有名なギルバートストラング先生による名著です。ストラング先生の本は色々出版されていますので、最近の本も読んでみるといいかもしれません。
今週と来週に色々実装してもらい、その次の週に発表を行ってもらいます。