Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Juliaってどんなことができるの? for JuliaTokai #16

Juliaってどんなことができるの? for JuliaTokai #16

JuliaTokai #16 LT資料

GOTOH Shunsuke

October 01, 2023
Tweet

More Decks by GOTOH Shunsuke

Other Decks in Technology

Transcript

  1. 自己紹介 • 名前:後藤 俊介 • 所属:有限会社 来栖川電算 • コミュニティ:🌟機械学習名古屋, 🌟JuliaTokai,

    ⭐Python東海, ⭐Ruby東海, ⭐jl.dev, … • 言語:Julia, Python, Ruby, … • SNS等:                  (@antimon2) • SNS等(2):      (@antimon2.jl) • 著書:実践Julia入門
  2. Julia とは?(1) • The Julia Language • 最新 v1.9.3(2023/08/24) ◦

    LTS:v1.6.7(2022/07/19) ◦ 次期:v1.10.0-β2(2023/08/17) • 科学技術計算に強い! • 動作が速い!(LLVM JIT コンパイル)
  3. Julia とは?(2) • Rのように中身がぐちゃぐちゃでなく、 • Rubyのように遅くなく、 • Lispのように原始的またはエレファントでなく、 • Prologのように変態的なところはなく、

    • Javaのように硬すぎることはなく、 • Haskellのように抽象的すぎない ほどよい言語である 引用元:http://www.slideshare.net/Nikoriks/julia-28059489/8
  4. Julia とは?(3) • C のように高速だけど、 Ruby のようなダイナミズムを併せ持っている • Lisp のような真のマクロを持ちながら、

    MATLAB のような直感的な数式表現もできる • Python のように総合的なプログラミングができて、 R のように統計処理も得意で、 Perl のように文字列処理もできて、 MATLAB のように線形代数もできて、 shell のように複数のプログラムを組み合わせることもできる • 超初心者にも習得は容易でありながら、 ハッカーの満足にも応えられる • インタラクティブな動作環境もあって、コンパイルもできる (Why We Created Julia から抜粋・私訳)
  5. Juliaでできること(よくある答え) • 数値計算 ◦ 数値線形代数、非線形方程式の求解、数値積分、常微分方程式、最適化問題、etc… • データ解析 ◦ 統計、検定、データ操作、データプロット、時系列解析、etc… •

    機械学習 ◦ パターン認識、分析・予測、最適化、生成(LLM)、etc… ↑ • これらは実践Julia入門でも簡単に紹介しているしググればいくらでも情報出て くる(ようになってきた(ので今さら(なので割愛
  6. SOLID原則(2) • S: 単一責任の原則 (Single-Responsibility Principle) • O: オープン・クローズドの原則(Open/Closed Principle)

    • L: リスコフの置換原則(Liskov Substitution Principle) • I: インターフェース分離の原則 (Interface Segregation Principle) • D: 依存性逆転の原則(Dependency Inversion Principle)
  7. SOLID原則(2) • S: 単一責任の原則 (Single-Responsibility Principle) • O: オープン・クローズドの原則(Open/Closed Principle)

    • L: リスコフの置換原則(Liskov Substitution Principle) • I: インターフェース分離の原則 (Interface Segregation Principle) • D: 依存性逆転の原則(Dependency Inversion Principle)
  8. オープン・クローズドの原則(Open/Closed Principle) • software entities (classes, modules, functions, etc.) should

    be open for extension, but closed for modification. • (参考訳:ソフトウェアの実体(クラス、モジュール、関数など)は、拡張に対して開 かれているべきであり、修正に対して閉じていなければならない) ↓ • 意訳:機能拡張が必要な場合に、既存のコードには修正を加えず に新しくコードを追加するだけで対応できるべきである
  9. オープン・クローズドの原則(for Julia)(2) 具体例: • Base.show() 関数 (文字列化時や REPL での表示など) •

    を、ユーザ定義型に適 用する例→ julia> @kwdef struct 犬 鳴き声::String = "わん" end 犬 julia> dog1 = 犬(鳴き声="にゃー") 犬("にゃー") # `Base.show()` を多重定義していない場合のデフォルト表示 julia> # `Base.show()` を多重定義して機能拡張 Base.show(io::IO, dog::犬) = print(io, "これは", '"', dog.鳴き声, '"', "と鳴く犬です。") julia> dog1 これは"にゃー"と鳴く犬です。 # `Base.show()` を多重定義している場合の表示
  10. オープン・クローズドの原則(for Julia)(3) 具体例: • 鳴く() 関数を定義 • Julia 標準の型にも 適用する例→

    julia> 鳴く(dog::犬) = dog.鳴き声 鳴く (generic function with 1 method) julia> 鳴く(dog1) "にゃー" julia> 鳴く(::AbstractVector) = "きゅー" 鳴く (generic function with 2 methods) julia> 鳴く(1:10) "きゅー" julia> 鳴く([1 2; 3 4]) # 行列は鳴かない(定義されていなければエラーになる) ERROR: MethodError: no method matching 鳴く(::Matrix{Int64}) # : 《以下略》
  11. インターフェース分離の原則 (Interface Segregation Principle) • Many client-specific interfaces are better

    than one general-purpose interface. • (参考訳:汎用なインターフェースが一つあるよりも、各クライアントに特化したイ ンターフェースがたくさんあった方がよい) ↓ • 意訳:不要なメソッドが存在する状況を作るな!
  12. インターフェース分離の原則 (for Julia)(1) そもそも… • Julia には 継承はない! • Julia

    には インターフェースもない! ◦ 言語仕様としてのMix-inやトレイトもないが、型システムと多重ディ スパッチを利用した Holyトレイト というトリックは存在 • Julia の関数は 総称関数(Generic Function) と言い、これ がそもそも抽象メソッドやインターフェースの役割 ◦ 振る舞い(関数)は(特定の)型に依存しない!(重要) ◦ シグニチャにより呼び出される各実体を メソッド と呼ぶ
  13. インターフェース分離の原則 (for Julia)(2) 結局 Julia の場合… • まず「関数」を宣言し、役割を与える。 • 必要な「型」(の組合せ(=シグニチャ))にだけその関数を

    適用できるように、関数を定義(多重定義)する。 (基本はこれでOK!) • いくつかの型に共通の振る舞い(共通実装)を与えたいな ら、Holyトレイト の仕組みを活用する。
  14. インターフェース分離の原則 (for Julia)(3) 具体例: • 桜 型と 花の色() 関 数を定義

    • Julia 標準の型にも 適用する例 • かつ、不要な型には適 用しない例 julia> @kwdef struct 桜 色::String = "桜色" end 桜 julia> 花の色(blossom::桜) = blossom.色 花の色 (generic function with 1 method) julia> 淡墨桜 = 桜(色="薄墨色"); julia> 花の色(淡墨桜) "薄墨色" julia> 鳴く(淡墨桜) # 桜は鳴かない(定義されていなければエラーになる) ERROR: MethodError: no method matching 鳴く(::桜) # : 《略》 julia> 花の色(犬()) # 犬は花が咲かない(同様のエラー) ERROR: MethodError: no method matching 花の色(::犬) # : 《略》
  15. SOLID原則(3) 他の原則について… • 単一責任の原則(S): 型の定義分け。設計だけの問題。 • リスコフの置換原則(L): ある意味当たり前、ある意味「継承のな い Julia

    には当てはまらない」 • 依存性逆転の原則(D): 関数による抽象化と、それを利用した依 存性注入(DI)が可能なので普通にできる(要設計スキル)
  16. デザインパターン(2) Julia 標準に組み込み or よく利用されるデザインパターン… • Factory Method パターン •

    Singleton パターン • Iterator パターン • Strategy パターン • Producer-Consumer パターン
  17. Factory Method パターン (for Julia) • 抽象型に外部コンスト ラクタ(のような関数) を定義して、引数に応 じて派生型のインスタ ンスを生成

    • Holyトレイトのトレイ ト型を生成する目的 で多用されている julia> subtypes(Base.IteratorSize) 4-element Vector{Any}: Base.HasLength Base.HasShape Base.IsInfinite Base.SizeUnknown julia> Base.IteratorSize(typeof([1 2;3 4])) # Matrix{Int64} Base.HasShape{2}() julia> Base.IteratorSize(Base.EachLine) Base.SizeUnknown()
  18. Singleton パターン (for Julia) • フィールドのない struct は Singleton Type と

    なりインスタンスは1 つしか生成されない • Julia 標準では、π(を 初めとする定数)、 nothing、missing などがシングルトン • 拙著「4-6-4. シング ルトン型」等参照 julia> struct SampleSingleton end julia> sngltn1 = SampleSingleton() SampleSingleton() julia> sngltn2 = SampleSingleton() SampleSingleton() julia> sngltn1 === sngltn2 # オブジェクトレベルで同一 true
  19. Iterator パターン (for Julia) • コレクションの要素を 列挙する仕組み • Julia ではイテレータ オブジェクトを作るの

    ではなく、「次の値と 『状態オブジェクト』を 返す関数」への定義追 加(多重定義)という かたちで実装される • 拙著「第6章 イテレー ション」等参照 julia> iterate([31, 41, 59, 26, 53]) (31, 2) julia> iterate([31, 41, 59, 26, 53], 2) (41, 3) julia> iterate([31, 41, 59, 26, 53], 5) (53, 6) julia> iterate([31, 41, 59, 26, 53], 6) === nothing true # ↑列挙終了は「戻り値が `nothing` かどうか」で判定
  20. Strategy パターン (for Julia) • 多重ディスパッチ(ポ リモーフィズム)を利 用して、引数の違いで 異なるアルゴリズムを 選択出来る •

    sort() の alg=~ キーワード引数指定 で内部でstrategyパ ターンを適用 julia> nums = [31, 41, 59, 26, 53, 58, 97, 93]; julia> sort(nums) # デフォルトソートアルゴリズム利用 #> [26, 31, 41, 53, 58, 59, 93, 97] julia> sort(nums; alg=QuickSort) # クイックソート #> [26, 31, 41, 53, 58, 59, 93, 97] julia> sort(nums; alg=MergeSort) # マージソート #> [26, 31, 41, 53, 58, 59, 93, 97]
  21. Producer-Consumer パターン (for Julia) • データの 生成 と 消 費 を非同期で行う

    (並行・並列処理のパ ターン) • Julia では Channel で実現される • 拙著「9-1. タスクと チャネル」等参照 julia> function collatz_channel(n) Channel{Int}() do chnl put!(chnl, n) while n != 1 n = iseven(n) ? n ÷ 2 : 3n + 1 put!(chnl, n) end end end collatz_channel (generic function with 1 method) julia> collect(collatz_channel(27)) 112-element Vector{Int64}: 27 82 ⋮ 2 1
  22. Template Method パターン (for Julia) • (先述の通り)Julia の関数はそもそも抽 象メソッドのような ものなので、それを そのまま利用すれば

    OK • 例:実践Julia入門 第5章 多重ディス パッチ「5-2-3. 実 例」など参照 abstract type AbstractTime end function gethour end # ←コレ function getminute end # ←コレ function getsecond end # ←コレ function Base.show(io::IO, time::AbstractTime) print(io, string(gethour(time), pad=2), # ←ココ ':', string(getminute(time), pad=2), # ←ココ ':', string(getsecond(time), pad=2)) # ←ココ end struct MyTime <: AbstractTime hour::Int minute::Int second::Int end gethour(time::MyTime) = time.hour getminute(time::MyTime) = time.minute getsecond(time::MyTime) = time.second struct MyTime2 <: AbstractTime seconds::Int end gethour(time::MyTime2) = time.seconds ÷ 3600 getminute(time::MyTime2) = time.seconds ÷ 60 % 60 getsecond(time::MyTime2) = time.seconds % 60
  23. 参考文献・リンク等 • 実践Julia入門(拙著) • Hands-On Design Patterns and Best Practices

    with Julia(さっき紹介したヤツ、洋書) • 研鑽Rubyプログラミング(後半のネタを思いついたきっかけの 本、訳書、原著:Polished Ruby Programming) • julialang.org(Julia 本家サイト)