14. AI技術: 機械学習(Deep Learning)入門 2

Photo by Claudio Schwarz on Unsplash

入門2 機械学習用フレームワークの利用

Flux パッケージ

ここまで感じただろうが,今現在の深層学習には一定の「やりかた」があり,それに沿うならばプログラムはどうしたってかなり似たようなものになる. ならば,そうした点を共通化し,かつ,計算時間の掛かりそうな箇所に高速なライブラリを組み込むような使いやすいフレームワークライブラリがあればユーザは大助かりだ.

そうした需要にこたえ,深層学習用の多くのフレームワークが存在する. Julia についてもやはり存在し,パッケージに Flux というものがあるので今回はこれを使ってみよう.

このパッケージも阪大情報教育システムやサイバーメディアセンターの JupyterHubサービス環境では既にインストール済みだ. 個人環境で未インストールの場合は下記のようにしてインストールしておこう.

1
2
using Pkg
pkg.add("Flux")

ちなみに,Flux の使い方については Flux マニュアル を見るとよいだろう. なお,サンプルが Flux Model Zoo に載っているので,参考にするとよいだろう.

有名な機械学習用ライブラリ/フレームワークとして他に Caffe, Keras (高水準ライブラリ,TensorFlow などの他の低水準ライブラリを下部に使う), TensorFlow, Chainer などが知られている(主に他の言語用だが).

今回のターゲット問題

今回は典型的(かつ有名)な学習問題である「手書き数字の認識問題」をターゲットとしよう. 学習に使える実データとして有名なものに MNIST というものがある.

これは 70,000枚(学習用 60,000枚 + 学習成果検証用 10,000枚)の手書き数字画像とその「正解」情報からなるデータセットで,各画像は以下のようになっている.

  • 色はモノクロ.濃淡が 0以上1以下の実数で表されている.
  • サイズは 28 $\times$ 28 ドット.
  • 本来のデータは 20 $\times$ 20 ドットの白黒二色のものだが,anti-aliasing アルゴリズムで 0以上1未満の濃淡に変換するなどしている. サイズが大きくなっているのは畳み込みなどの画像処理をしやすくするために各辺に「余白」をつけているのだと思われる. ただ,単に余白を足したのではなく,「大きめのキャンバスの中心に画像の中心をあわせて配置」しているので,余白は必ずしも各辺で 4ドットずつになっていないので要注意.

たとえばその 10枚目のデータを画像として見てみると

となっている(この画像では 0 $\cong$ 黒, 1 $\cong$ 白として表示されている).ちなみにこれは数字の「4」だそうな.

MNIST のデータは本家の web からダウンロードしてもよいが,それだとちょいとした前処理が必要となる. しかし実は,Flux パッケージは綺麗に処理された MNIST データをダウンロードする機能をもっているので,その機能を使おう(どうやるかはプログラムを見ればわかる).

今回用意する neural netowrk

少し要素数などが先週より大きいので,丁寧に準備しよう. ただし,以下では意外に小さい NN を用意するので驚くかもね.

さて,今回は,

  • 入力は要素数 784 ($= 28\times 28$) の実数ベクトル
  • 出力は数字 0 ~ 9 に対する「確率」を表すベクトル. つまり,要素数 10 の実数ベクトル $\boldsymbol{p}$で,$0 \leq p_i \leq 1$ かつ $\sum_i p_i = 1$.
  • 通常の密結合 NN を用いる.中間(network)層は 2つ.
  • 1つ目の中間層の出力サイズは 32 で,活性関数は ReLU.
  • 2つ目の中間層の出力サイズは 10 で,活性関数の代わりに softmax 関数で正規化して出力が確率分布として成り立つようにする.(注: 2つ目の中間層の出力が最終出力)

という NN を Flux で用意して,この中に含まれるパラメータを(学習によって)修正することにしよう.

なお,12. AI技術: 機械学習(Deep Learning)入門のプログラム中にも登場したが, softmax 関数というのは実数の列(負の実数もOK)を確率分布として解釈できる数列に(かつ,各要素は単調に)変換する関数の一つで, ベクトル $\boldsymbol{a} = \{ a_i \}$ に対して

$\displaystyle\mbox{ SoftMax }(\boldsymbol{a})_i = \frac{\exp(a_i)}{\sum_i \exp(a_i)}$

と定義できる. $\exp$ 関数で強引に正の値に変換してから合計値で正規化しているという,シンプルな変換だ. 単調性と確率分布の性質を満たそうとするとたぶんこれが最初の候補だろう. ちなみに,すべての $a_i$ が正ならば, $\exp$ での変換が不要で,合計値で割って単純に正規化したほうが楽だろうな.

あと,これまた同じ回のプログラム中に登場したが,出力の「誤差」を測る方法として出力ベクトル $\boldsymbol{y}$ と真値ベクトル $\boldsymbol{z}$ に対する Cross Entropy

$\displaystyle\mbox{ CrossEntropy }(\boldsymbol{y}, \boldsymbol{z}) = - \sum_i \, z_i \, \exp( y_i )$

を使う.

入力独立変数に対して非対称な関数なので入力の順序に注意.目くじら立てるほどの本質的な違いはないと思ってもまあいいが.順序は定義によるので,プログラムの source を確認しておく必要がある.Flux パッケージの crossentropy 関数は上の順序になっている.

実際にやってみる

あとは少しずつプログラムを作っていくだけだ.

まずはいつものように Flux などのパッケージの使用宣言だ.

1
2
3
4
5
6
using Flux
using Flux: onehotbatch, onecold, params, crossentropy, train!, throttle
using DataFrames
using MLDatasets
using Statistics
using Base.Iterators: repeated

次に、MLDatasets package の機能で MNIST データを使わせていただこう. それには関数 MNIST を呼び出せばよい.

ただし,この関数を初めて呼び出したときにデータが(一回だけ)ダウンロードされるので解説しよう. 実際は,下記のように,このデータについてごく簡単な説明があり,それを理解した上でダウンロードするのか,y/n で尋ねられる. そこで stdin> に "y" (と Enter)を入力しよう. するとダウンロードが始まる.少しだけ待とう.

1
MNIST()
stdin> ■■■■■■

This program has requested access to the data dependency MNIST.
which is not currently installed. It can be installed automatically, and you will not see this message again.

Dataset: THE MNIST DATABASE of handwritten digits
Authors: Yann LeCun, Corinna Cortes, Christopher J.C. Burges
Website: http://yann.lecun.com/exdb/mnist/

[LeCun et al., 1998a]
    Y. LeCun, L. Bottou, Y. Bengio, and P. Haffner.
    "Gradient-based learning applied to document recognition."
    Proceedings of the IEEE, 86(11):2278-2324, November 1998

The files are available for download at the offical
website linked above. Note that using the data
responsibly and respecting copyright remains your
responsibility. The authors of MNIST aren't really
explicit about any terms of use, so please read the
website to make sure you want to download the
dataset.

Do you want to download the dataset from
["https://ossci-datasets.s3.amazonaws.com/mnist/train-images-idx3-ubyte.gz",
 "https://ossci-datasets.s3.amazonaws.com/mnist/train-labels-idx1-ubyte.gz",
 "https://ossci-datasets.s3.amazonaws.com/mnist/t10k-images-idx3-ubyte.gz",
 "https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz"]
to "c:\julia\PKG\v1.8\datadeps\MNIST"? [y/n]

すると次のような出力が出て,どんな形式でダウンロードされたかと,この呼出し方だと学習用データ(60,000個)が得られるということがわかる.

dataset MNIST:
  metadata  =>    Dict{String, Any} with 3 entries
  split     =>    :train
  features  =>    28×28×60000 Array{Float32, 3}
  targets   =>    60000-element Vector{Int64}

次に,これを変数に入れよう.

1
2
3
# 学習に使うデータ.60000個ある.
raw_imgs = MNIST().features
labels   = MNIST().targets

raw_imgs 変数に画像データが, labels 変数にその画像がどの数字を描いたものか,が入る.

ただ,raw_imgs 変数は画像が 90度回転した格好で格納されているので,次のようにして(人間に)見やすいものにしておこう.

1
2
3
# 扱いやすいように変換しておく.
data_number = size(labels)[1]
imgs = [ raw_imgs[:,:,i]' for i in 1:data_number ]

さて,念のためにもダウンロードしたデータをちょっと見ておこう.

もとは画像データなのだから,当然,画像で見てみるのが良いだろう. 次のようにすると,行列データを(以下の場合はグレイ表現の)画像で見ることができる.

1
2
using Plots
Gray.( imgs[1] )

ちなみにこれは 0から9 のどの数字かというと,

1
labels[1]

5

ということで,正解は 5 だそうだ.

次に,これらを,学習プログラムに渡せるよう,固まりのデータに変換する.

1
2
3
4
5
6
7
# 「画像 = 行列」となっているデータをベクトルに変換し,
# それを横にくっつけて一つの大きな行列に.
X = hcat( reshape.(imgs, :)... )

# 正解の値を,0:9 に対応するように,要素が 「真偽値」(= 1 or 0) の
# 10次元ベクトルに変換する
Y = onehotbatch(labels, 0:9)

変換した結果を見ておこう. 特に,Y が何を意味するのか,よくみるとわかるだろう.

1
X
784×60000 Matrix{Float32}:
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.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  0.0  0.0  0.0  0.0
…略…
1
Y
10×60000 OneHotMatrix(::Vector{UInt32}) with eltype Bool:
 ⋅  1  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  …  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅
 ⋅  ⋅  ⋅  1  ⋅  ⋅  1  ⋅  1  ⋅  ⋅  ⋅  ⋅     ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  1  ⋅  ⋅  ⋅  ⋅  ⋅
 ⋅  ⋅  ⋅  ⋅  ⋅  1  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅     ⋅  ⋅  ⋅  1  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅
 ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  1  ⋅  ⋅  1  ⋅  1     ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  1  ⋅  ⋅  ⋅
 ⋅  ⋅  1  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  1  ⋅  ⋅  ⋅     ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅
 1  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  1  ⋅  …  ⋅  ⋅  ⋅  ⋅  ⋅  1  ⋅  ⋅  ⋅  1  ⋅  ⋅
 ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅     ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  1  ⋅
 ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅     1  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅
 ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅     ⋅  1  ⋅  ⋅  ⋅  ⋅  ⋅  1  ⋅  ⋅  ⋅  1
 ⋅  ⋅  ⋅  ⋅  1  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅     ⋅  ⋅  1  ⋅  1  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅  ⋅

では,NN を作ろう. Flux では大変簡単に,以下のように NN を構成できる.

1
2
3
4
5
6
7
8
m = Chain(
  Dense(28^2, 32, relu),
  # 密結合第1層.28^2 の入力を受けて,32 の出力を返す.活性関数は ReLU.
  Dense(32, 10),
  # 密結合第2層.32 の入力を受けて 10 の出力をそのまま返す.
  softmax
  # 出力直前に 正規化
  )

意味は,上の注釈でわかるだろう.

さて,この学習「していない」 NN での出力を念の為に確認しておこう. 1つ目のデータを入れるとどういう答えが返ってくるか…

1
r = m( X[:,1] )
10-element Array{Float32,1}:
 0.09637651
 0.12438649
 0.08440215
 0.09990795
 0.0857012
 0.11381065
 0.11615292
 0.11861699
 0.09201259
 0.06863261

これが NN の出力で,この画像が「 0 ~ 9 である確率 」を並べたもの,と解釈することになる. わかりやすいようにグラフで見ておこう.

1
2
3
using Plots

bar( 0:9, r )

これだと,この画像は "2" である確率が一番高いことになり,正解の "5" を当てられていないことがわかる.

同様にもう二つほど見ておこう. データの 2つ目は

1
Gray.( imgs[2] )

となっていて,明らかに正解は "0" だ.まあ確認しておくか.

1
labels[2]
0

ふむ.ではこの画像データを NN に入れると…

1
bar( 0:9, m( X[:,2] ) )

これも当然うまくいってない.

データの3つ目も確認しておこう. (画像をみるのはもう省略して)真値は

1
labels[3]
4

となるので "4" が真値で,NN が出す確率は

1
bar( 0:9, m( X[:,3] ) )

となっていてこれももちろんうまくいってない.

さて,では学習に必要な関数の準備をしよう.

1
2
3
4
5
# 損失関数.要は出力誤差.今回は Cross Entropy で.
loss(x, y) = crossentropy(m(x), y)

# 正解率.この文脈だと精度ともいう.
accuracy(x, y) = mean(onecold(m(x)) .== onecold(y))

NN の正解率を測ることができるようになったので,学習していない現状の NN での正解率をみておこう.

1
2
# 初期のパラメータの NN だと精度は?
accuracy(X, Y)
0.048916666666666664

ふ~む.ランダムな状態の NN での正解率が 4.9% ということで,まあこんなものかな(ランダムに数字を一つだせば,正解率は平均で 10% になるはずなので).

ではデータセットの設定と,パラメータをどうやって修正していくかの方法の指定,そして画面表示設定等をしてしまおう.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# データセット.大きくすれば結果は良くなるが,時間もかかる.
# コンパイル用に小さなデータを,本番用に大きなデータを用意しておく.
small_dataset = repeated((X, Y), 1)
large_dataset = repeated((X, Y), 500)

# 損失関数を小さくする方向をどう決めるか.学習をどう行うか.
# ADAM 法がよく使われるようだ.パラメータは適当.
opt = ADAM(0.01)

# 学習が進んでいく途中での画面表示等を設定.
# cb とは call back のこと.
evalcb = () -> @show(loss(X, Y))

これで準備ができたので,早速実行しよう. ただし,一回小さなデータで関数をコンパイルしておく.

1
train!(loss, params(m), small_dataset, opt, cb = throttle(evalcb, 10))
loss(X, Y) = 2.0165222f0

では,大きめのデータで学習させてみよう.

1
@time train!(loss, params(m), large_dataset, opt, cb = throttle(evalcb, 10))
loss(X, Y) = 1.6647032f0
loss(X, Y) = 0.22654326f0
loss(X, Y) = 0.15942372f0
loss(X, Y) = 0.11917354f0
loss(X, Y) = 0.0933378f0
loss(X, Y) = 0.07503337f0
loss(X, Y) = 0.061352428f0
loss(X, Y) = 0.050547197f0
loss(X, Y) = 0.0419089f0
loss(X, Y) = 0.0345261f0
 99.593398 seconds (62.96 k allocations: 116.684 GiB, 8.53% gc time)

計算時間は CPU 等によってひどく異なるので,私有環境で上の 10倍以上の時間がかかっても不思議ではない.

さて,学習が終了したようなので,結果をチェックしてみよう.

1
2
# 学習後の NN の精度.
accuracy(X, Y)
0.9925833333333334

ふむ.正解率は 99.25% か.学習前は 4.9% だったことを考えると,2分弱の学習としてはたいへん上出来だ.

最初の 3つのデータについて,個別に学習結果をチェックしてみよう. まずは 1つ目のデータに対する NN の回答は,

1
bar( 0:9, m( X[:,1] ) )

となる.これだと "5" である確率がほぼ 100%で,正解をきちんと当てていると言えるな.

次に 2つ目のデータだ.

1
bar( 0:9, m( X[:,2] ) )

"0" である確率がほぼ 100% だ.これも正解を完全に当てている.

3つ目も見てみよう.

1
bar( 0:9, m( X[:,3] ) )

これも "4" である確率が約 90% で,正解をきちんと当てている.

次に,学習に使っていない,テスト用データを対象としてこの NN の性能を見よう. まず,テスト用データのダウンロードと整形だ.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# テスト用に使うデータ.10000個.上と内容は重複なしのはず.
raw_imgs_check = MNIST(:test).features
labels_check   = MNIST(:test).targets

# 使いやすいように転置.
check_number = size(labels_check)[1]
imgs_check = [ raw_imgs_check[:,:,i]' for i in 1:check_number ]

# Flux 用の形に.
X_check = hcat( reshape.(imgs_check, :)... )
Y_check = Flux.onehotbatch(labels_check, 0:9)

この NN を適用した場合の精度を見よう.

1
accuracy(X_check, Y_check)
0.9623

ふむ,未知のデータに対しても約 96% の確率で正解を出せるということだな. どうやらこの NN の学習はうまくいった,と言ってよいだろう.

おまけ: GPU を使った場合

上記の計算は小さめとはいえ約 5分かかっている. これに対し,特殊なハードウェアの力を借りて計算したらどうなるか,という例を示しておこう. 今回は nVIDIA 社の GPU (まあ,要はグラフィックカードだ) を使ってみる,という例になる.

残念ながら下記の code は nVIDIA 社の GPU がインストールされていない環境では動かない. nVIDIA 社のグラフィックカードが刺さっている環境で試そう.

準備

nVIDIA 社の GPU を Flux から使うには,事前に

  • グラフィックカードのデバイスドライバ: まあこれは Flux に関係なくインストールしているだろう.
  • CUDA Toolkit : CUDA という専用言語で GPU を扱うためのライブラリ.nVIDIA製. Windows だと,ダウンロードしてダブルクリックするだけでインストールできる. ただし,ファイルサイズが 2GB を超えるのでダウンロードの際は覚悟しよう.
  • cuDNN : 深層 NN 用ライブラリ.nVIDIA製.cuDNN のインストール方法 を読むと(デバイスドライバと CUDA Toolkit も含めて)インストール方法がわかる.まあ,解凍してファイルをいくつかコピーするだけだ.

のインストールを上の順序でしておく必要がある…のだが,実は,下記のCUDA パッケージ1をインストールすると自動でやってくれる.楽だ.

というわけで,NVidia 社の GPUボードが入っている PC を使っている環境であるならば,CUDA パッケージを使えるように下記のようにしてインストールしよう.

1
2
using Pkg
Pkg.add("CUDA")

ちなみに,阪大情報教育システムだと CUDA パッケージはインストールされているが,肝心のハードウェアが無いので,実際に CUDA の機能を使おうとしたときに

Info: The GPU function is being called but the GPU is not accessible. 

というメッセージが出て使えないことがわかるぞ.

そして,サイバーメディアセンターの JupyterHubサービス環境(β)では,この CUDA がインストールされているうえ,起動時にGPU付き環境を選択すれば実際に使えるぞ.ここで試してみるのも良いだろう.

あとは次のように,必要なデータや計算ルーチンを GPU に渡すようにしてプログラムを書けば良い.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using Flux
using Flux: onehotbatch, onecold, crossentropy, params, train!, throttle
using DataFrames
using MLDatasets
using Statistics
using Base.Iterators: repeated
using CUDA

raw_imgs = MNIST().features
labels   = MNIST().targets
data_number = size(labels)[1]
imgs = [ raw_imgs[:,:,i]' for i in 1:data_number ]

oX = hcat(float.(reshape.(imgs, :))...)
oY = onehotbatch(labels, 0:9)

X = copy(oX)  |> gpu
Y = copy(oY) |> gpu

m = Chain(
  Dense(28^2, 32, relu),
  Dense(32, 10),
  softmax) |> gpu

loss(x, y) = crossentropy(m(x), y)

function accuracy(m, x, y)
    m = m |> cpu
    r = mean( (onecold(m(x))) .== (onecold(y)))
    m = m |> gpu
    return r
end

# コンパイル用に小さなデータを,本番用に大きなデータを用意しておく.
small_dataset = repeated((X, Y), 1) |> gpu
large_dataset = repeated((X, Y), 300) |> gpu # GPU ボードの問題で,少しサイズを小さくした.
opt = ADAM()
evalcb = () -> @show(loss(X, Y))

  GPU に渡すデータのサイズをむやみに大きくしないようにしよう. 上の例で言えば,large_dataset をあまり大きくすると,GPU の挙動が変になったりして,OS までトラブったりするぞ.

これで準備ができた. 念の為に初期の精度を測っておく.

1
accuracy(m, oX, oY)
0.12608333333333333

ふむ.平均正解率 12.6% というところで,まあ妥当だな.

では学習させてみよう. ただし,一回小さなデータで関数をコンパイルしておく.

1
train!(loss, params(m), small_dataset, opt, cb = throttle(evalcb, 10))

では,大きめのデータで学習させてみよう. このデータ(ただしサイズ 500)を CPU で学習したときは 100秒近くかかったが…

1
@time train!(loss, params(m), large_dataset, opt, cb = throttle(evalcb, 10))
loss(X, Y) = 2.2181697f0
  3.170826 seconds (594.81 k allocations: 39.628 MiB, 2.81% gc time, 0.78% compilation time)

おお! さすが. データサイズ 500 で CPU だと 100秒かかったこの学習(データサイズを 300 にそろえて考えると 60秒)が,データサイズ 300 で この環境だとたった 3秒で学習が終わる. おおよそ 20倍は速くなった,ということだな.

ちなみに,サイバーの JupyterHubサービスの GPU付き環境だと(データサイズはすべて 500で揃えて) CPU のみで 109秒,GPU で 2.54 sec. なので,40倍ぐらい高速化している. 高速化の度合いはハードウェアの問題なので,より新しく,より良い GPUボードを積んでいればそれだけ高速化できるだろう,ということだね.

さて,学習後の NN の精度も見てみよう.

1
accuracy(m, oX, oY)
0.9519166666666666

正解率が 95% ということで,確かによく学習できているようだ.

未知のデータについてもこの NN の能力を確かめておこう.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# テスト用に使うデータ.10000個.上と内容は重複なしのはず.
raw_imgs_check = MNIST(:test).features
labels_check   = MNIST(:test).targets

# 使いやすいように変換.
check_number = size(labels_check)[1]
imgs_check = [ raw_imgs_check[:,:,i]' for i in 1:check_number ]

# Flux 用の形に.
X_check = hcat( reshape.(imgs_check, :)... )
Y_check = Flux.onehotbatch(labels_check, 0:9)

accuracy(m, X_check, Y_check)
0.9467

未知のデータに対しても 95% の正答率だ.たった数秒の学習なのに,大変よく出来たと言えよう.

ということで,GPU などの特殊なハードウェアの力を借りることができれば,こうした学習も大変速く行えることがわかる.デスクトップ PC 用のグラフィックカードであればそう高いものでもないので,機械学習を少し勉強して見るならばこうしたハードウェアの調達も検討しておくと良いだろう.

レポート

下記要領でレポートを出してみよう.

  • e-mail にて,
  • 題名を 2022-numerical-analysis-report-14 として,
  • 教官宛(アドレスは web の "TOP" を見よう)に,
  • 自分の学籍番号と名前を必ず書き込んで,
  • 内容はテキストでも良いし,pdf などの電子ファイルを添付しても良いので,

下記の内容を実行して,結果や解析,感想等をレポートとして提出しよう.

  1. 上の例で NN の中間層を増やしてみよう.ただし,計算時間は増大するので,バランスが厳しいかも.

  2. nVIDIA のグラフィックカードが刺さっている PC環境を探すなどして,可能ならば GPU での計算例も試してみよう.

  3. Flux Model Zoo を見て,他の例を試してみよう.ただし,知らないことばかりの場合は無理しなくて良い.

  1. 少し前までは Julia では NVidia 社の GPU を使うには CuArrays package を使うもの,だったが,今は CUDA package を使え,ということになっている. ↩︎