#Julia言語 グローバル変数Aを参照する

S(x) = S(A, x)

の類の函数の定義は計算効率重視なら避けるべき。

しかし、これができないと途方に暮れる人もいるかもしれない。

そういう人は

github.com/genkuroki/publ…

github.com/genkuroki/publ…

のスタイルをパクればよい。
#Julia言語

あと、初心者のうちは、内部コンストラクタを使わざるを得ない場合を除いて、内部コンストラクタを定義しない方が無難だと思う。要するに、初心者段階では

struct Foo{A, B}
a::A
b::B
function Foo(~) ~ new(a, b) end
end

のようにできるだけ書かないようにする。続く
#Julia言語 代わりに、単に

struct Foo{A, B}
a::A
b::B
end

と書くか、必要に応じて外部コンストラクタを

function Foo(~) ~ Foo(a, b) end

のように定義しておく。続く
#Julia言語 可能ならば、内部コンストラクタを使いたくない理由は、内部コンストラクタを定義すると、そうしなかった場合に自動的に定義されるデフォルトのコンストラクタが失われることです。

デバッグのときに不自由する場合があります。
#Julia言語 この辺の事情に疎い場合には、struct ~ end の間にコンストラクタを書かないことによって、デフォルトで定義されるコンストラクタを有効にしておいた方が無難だと思う。

(自己参照のような内部コンストラクタでなければできないことをする場合には、内部コンストラクタを使う。)
#Julia言語

struct Foo{A, B}
a::A
b::B
end

とするだけで、

Foo(a, b)



Foo{A, B}(a, b)

の2つのコンストラクタを使用できます。

内部コンストラクタの使用のようなリスクを伴う難しいことをする必要はない。
#Julia言語 あと、後で最適化によるスピードアップを試みる予定ならば、「表示しながら計算する函数」「ファイルに結果を保存しながら計算する函数」は書かない方がよいです。

計算するための函数と表示や保存の函数を分離して、計算のための函数単体でテストできるようにしておく必要があります。
「計算するための函数と表示や保存の函数を分離して、計算のための函数単体でテストできるようにしておく」だとか、「問題を記述するパラメータ群をグローバル変数達にべた書きしたりしない」というようなことは、#Julia言語 と無関係に常識になって欲しいです。
#Julia言語 函数を引数とする函数を

apply(f::Function, x) = f(x)

のように書くと、f(x)の形式で使えるオブジェクトの一部を引数として受け取れない函数が出来上がります。

添付画像のFoo(sinpi)はFunction型ではありません。

引数の型を書かずに、

apply(f, x) = f(x)

と書く方が勝ります。 Image
#Julia言語

函数の引数の型を適切な範囲に制限することはかなり難しいです。

自信がなかったり、面倒だと思ったら、函数の引数の型を書かずに済ませるという手抜きが良い選択肢になる場合が多い。
#Julia言語 あと、mutable structを避けられるなら避けた方がお得。immutableなstructのmutableなフィールドの内容はいくらでも変更可能なので、mutable structが必要な場合が少ない。

struct Foo{A} a::A end
foo = Foo(zeros(3))
foo.a[1] = 99.9
push!(foo.a, 123.456)

のようなことをできます。 Image
#Julia言語 次のように小さなmutable structを定義するのは損になることが多いです。

❌非推奨
mutable struct Point
x::Float64
y::Float64
end

似た例はBaseのComplex型(複素数型)。

Complex型はmutableでないstructで定義されています。

これを真似ればよい。
github.com/JuliaLang/juli… Image
#Julia言語 複素数と同じような感覚で使えるimmutableでサイズが固定されたベクトルは StaticArrays.jl で SVector という名で定義されています。

長さ30以下程度の短いベクトルの扱いでは非常にお勧め。

「3次元空間の点を動かす」のようなコードを書くときにはまずこれの使用を考える。
#Julia言語 で複素数値函数が欲しければ返り値がComplex型の函数のコードを書くのが普通ですが、それと同じような感覚で、n⪅30のとき、n次元ベクトル値函数が欲しければ返り値がSVector型の函数を書く。

Vector型を返り値にする場合と違って無駄なアロケーション発生を防げます。
#Julia言語 高次元ベクトルの時間発展を扱いたい場合の最適化では、作業領域として確保しておいたVectorを使い回すコードを書く必要が生じます。

使い回さずに素朴に書くとメモリ割り当てが増えて死ぬ。

アロケーションの節約はJuliaに限らず、最適化のイロハのイになる。
#Julia言語 低次元でStaticArrays.jlが便利なのは、行列とベクトルの積をSMatrixとSVectorで実装する場合も同様です。

具体例が

github.com/genkuroki/publ…

にある。
#Julia言語 SVectorの乱数生成は結構面倒な場合があります。無駄なアロケーションを避けることと、SVectorの長さを既知にしないと型不安定になってしまうことの2つが問題になる。

そのための面倒な場合の工夫が、既出の最新ノートブック

github.com/genkuroki/publ…

にあります。
#Julia言語 最初は面倒だと思うかもしれませんが、rand函数(randnでも同様)を、rand()の形式ではなく、乱数発生器をrngとするときの rand(rng) の形式で使うようにしておくと、後で乱数発生器を好きなものに変更可能になって便利です。

さらに、Julia v1.6.2だとrand(rng)の方が明らかに速いです。
#Julia言語 ベクトルの乱数を rand(n) または rand(rng, n) の形式で生成すると、メモリアロケーションが発生するので、ループの内側でそれらを使うことは避けたい。

using Randomし、ループの外側で長さnのベクトルtmpを用意しておいて、rand!(rng, tmp)を使うとよいです。
#Julia言語 を使い始める人達の多くが世間一般の中では相対的数学強者なので、最初から結構な複雑さを持つコードの最適化に挑戦する場合が多い。

それが結構罠で、シンプル過ぎると思われるような場合から出発しないと、一度に多くのことを学習しなければいけなくなって大変になる。私もそうでした。
#Julia言語 具体的には、常微分方程式の数値解法の場合には。Runge-Kuttaやleapfrogをやる前に、最単純なEuler法の最適化をやっておくとよいと思う。

際単純なEuler法もJuliaでの「最適化ゲーム」として十分に面白いです。
#Julia言語 最単純なオイラー法でも面白くなる理由は、Juliaでは函数の引数の型を書く必要がなくて、函数の実行時には、引数の型の組み合わせに最適化されたネイティブコードにコンパイルされて実行されるからです。

続く
#Julia言語 オイラー法の実装では、原則として函数の引数の型を一切書かずに、可能な限り広い場合に型安定になるコードを書くようにすれば、

 完全に同一のコード

で、

 実数値
 複素数値
 ベクトル値
 行列値
 幅を持った数値

などの場合にオイラー法を適用できるようになります。
#Julia言語 完全に同じコードで、Float64, Float32, Fliat128, BigFloat など様々な精度の浮動小数点数を扱えるようにすることは結構よい練習問題。
#Julia言語 「Float128の函数には q をつける」というような面倒ごとから完全に離脱できる。

引数の型を Float64 とかに決め打ちすることがどれだけ損であるかもわかる。
#Julia言語 で、オイラー法によるexp(x)の近似計算を実行すれば、完全に同一のコードで、xの型がFloat64, Float32, BigFloat, ComplexF64, Matrix{Float64}, Matrix{ComplexF64}, ...の場合の exp(x) の近似計算が可能になる。

しかも、各型ごとに別々に最適化されたネイティブコードが実行される!
#Julia言語 サイズが小さな行列の場合に限っては、SMatrix型の場合の方が速いことも確認できるだろう。
#Julia言語 個人的にずっとびっくりさせられ続けていることの1つは、「函数の引数の型を書かないこと」を嫌がる人達が結構いること。

引数の型を書かなくてもC並に速さで計算してくれるJuliaを使っているのに、引数の型を書かないと落ち着かないらしい。

この辺は「過学習」に問題だと思う。
#Julia言語 Juliaで函数の引数の型を十分な理解抜きに書くと、様々な問題が生じます。場合によっては思わぬバグ発生の原因になる。

色々理解していれば、「ドキュメント」として函数の引数の型を書いても害はないと思いますが、実際にはそうでもない。viewやSubStringでハマる人が続出するだろう。
#Julia言語

函数の引数に型を書くことを「コメント」の代わりに使うと、有害な副作用の問題を気にする必要がある。

有害な副作用を防ぐうまいやり方は、函数のdoc stringに函数に関するコメントを残しておくことです。REPLなどでの?で閲覧できるので、# を使ったコメントより便利です。
#Julia言語

"""
f(A, x)のAは行列でxはベクトルのつもり
"""
f(A, x) = A*x

と書いておくと、

?f



f(A, x)のAは行列でxはベクトルのつもり

が表示されるようになります。

doc stringを書いてくれているパッケージは使い易いです。そうじゃない主要パッケージも結構あってつらい。

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with 黒木玄 Gen Kuroki

黒木玄 Gen Kuroki Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @genkuroki

14 Sep
#Julia言語 『数値計算の常識』という有名な本があって第5章のタイトルが「逆行列よさようなら」です。

Juliaでは計画行列Xによるバックスラッシュ演算

β̂ = X \ y

の一発で最小二乗法も計算できます。

github.com/genkuroki/publ…
#数楽 Xが縦長の行列で、β, y が縦ベクトルのときの、βの成分に関する連立一次方程式

Xβ = y

は一般に解を持たないのですが、Xβとyのユークリッド距離を最小にするようなβをβ̂と書いて、「解」とみなすのが最小二乗法の考え方です。その「解」を

β̂ = X \ y

と書くことは記号法的に自然です。
#Julia言語 Juliaがバックスラッシュ二項演算子で最小二乗法も可能にしていることの背景には以上のような数学が隠れています。
Read 13 tweets
13 Sep
#統計 #数楽 この短い動画も非常にためになるし楽しめる。

「変分ベイズ」「変分推論」のように呼ばれる方法は、計算が大変な真の分布φ(w)を特別な形の分布ψ(w)でφ(w)から最も出て来やすいもので近似する方法。続く
#統計 Kullback-Leibler情報量 D(ψ||φ) は、Sanovの定理より、「分布φのサンプルの分布として分布ψに近いものの出て来やすさ」を意味する。

もしも分布ψの台が分布φの台よりも真に大きいならば、そのはみ出した部分の値はφから出て来ないので、D(ψ||φ) = ∞ となる。

続く
#統計 D(ψ||φ) < ∞ ならばψの台はφの台に含まれる。

固定されたφに対して、特別な形のψを動かして、D(ψ||φ) を最小化すると(変分推論!)、分布ψは分布φよりも狭い部分に集中した感じの分布になり易い。

以下のリンク先の場合には実際に概ねそうなっているように見える。
Read 16 tweets
12 Sep
素晴らしいスレッドだったので大量にRTしました。

しかし、最後に「立式」という聴き慣れない有害で特殊な意味を持つ算数教育用語を使ってしまっている点は、人権問題に発展するかもしれないので注意が必要だと思いました。😝

「式  答え 」のスタイルそのものが子供を悪しき枠にはめている。
多くの人が誤解していることですが、「立式」という用語は国語辞典にも載っていない用語で、単に「式を作る」というようなニュートラルな意味を持つ無害な用語ではありません。

子供を害するちょー算数の中核部分と関係している極めて有害な用語なので取り扱い注意です。
「立式」という特殊な用語が歴史的にどのように使われていたかについては、以下のスレッドを参照。

「立式の意図」を以下のリンク先の意味で子供に問う行為は、人権問題に発展する恐れが十分にあります。😝
Read 6 tweets
12 Sep
東京大学出版会の『統計学入門』を運悪く「真面目」に読んでしまい、それに従って、「確率ではなく、割合だ」というスタイルで「信頼区間警察」をやっている側が狼藉之義也の「ヒャッハー」達だという問題。

へたをするとこれが高校数学にも伝搬する恐れがある。
最近の例では

tjo.hatenablog.com/entry/2021/07/…
渋谷駅前で働くデータサイエンティストのブログ
2021-07-16
95%信頼区間の「95%」の意味

がひどい。

教科書に書いてあるという事実は正しいことの証拠にはなりません。
#統計 正しい考え方

* 信頼区間の計算では通常パラメータを持つモデル(例えば正規分布モデルや二項分布モデルなど)が使われる。

* 95%信頼区間の95%はそのモデル内での標本分布で測った確率(の近似値)になる。

* 使用したモデルが現実において妥当でなければ、信頼区間は信頼できないものになる。
Read 22 tweets
12 Sep
一般に印象操作に一所懸命な変な人の意見は適当にスルーした方がよいと思いました。
一般に、難しいことを理解できない人たちで周囲を固めている人の観測範囲内でそれが受け入れられていないことと、それが実際に有用であるか否かは無関係。
大学で統計学が専門じゃないのに統計学の講義を受け持つことになった人にとって、カイヤンさんが説明してくれていることの多くが参考になると思います。

ついつい「流行っている」という理由でベイズ統計の話題に触れるときに、注意するべきことがあります。「主義」に関わる話題は本当に要注意。
Read 6 tweets
11 Sep
#Julia言語 1万人に一人あたり100万円配って、その後ランダムに誰かから1万円を取り上げて(破産していたら取るのを諦める)、別の誰かに配ることを繰り返したときの、保有金額の分布の推移のアニメーション。

分布の収束先は不平等な指数分布。

これは「税額一定」の場合。

github.com/genkuroki/publ…
#Julia言語 不平等な指数分布になった後に、今度はランダムに誰かを選んで保有金額の5%の税金を徴収して別の誰かに配ることを繰り返すとこうなる。

分布の収束先はかなり平等的なガンマ分布。

証明は知らない。誰か教えて!(笑)

(((わざと真剣に考えていない)))

github.com/genkuroki/publ…
#Julia言語 ここからが真に面白い話になる。

さて、ついさっき税額ではなく、税率を一定にしたランダムな富の分配で平等に近付けることができることを紹介した。

税率は5%だった。

問題:税率を50%に上げるとさらに平等になるか?
Read 21 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!

Follow Us on Twitter!

:(