[AI 인공지능 머신러닝 딥러닝/Julia] - Julia 프로그래밍 - 언어 및 강의 소개
Julia 프로그래밍 - 언어 및 강의 소개
Julia 프로그래밍 언어줄리아(Julia)는 고성능의 수치 해석 및 계산과학의 필요 사항을 만족시키면서 일반 목적 프로그래밍에도 효과적으로 사용될 수 있도록 설계된 고급 동적 프로그래밍 언어이
inner-game.tistory.com
[AI 인공지능 머신러닝 딥러닝/Julia] - Julia 프로그래밍 - Julia 설치
Julia 프로그래밍 - Julia 설치
이전 글[AI 인공지능 머신러닝 딥러닝/Julia] - Julia 프로그래밍 - 언어 및 강의 소개 Julia 프로그래밍 - 언어 및 강의 소개Julia 프로그래밍 언어줄리아(Julia)는 고성능의 수치 해석 및 계산과학의 필
inner-game.tistory.com
[AI 인공지능 머신러닝 딥러닝/Julia] - Julia 프로그래밍 - 유형, 제어 흐름, 함수 및 다중 디스패치
Julia 프로그래밍 - 유형, 제어 흐름, 함수 및 다중 디스패치
[AI 인공지능 머신러닝 딥러닝/Julia] - Julia 프로그래밍 - 언어 및 강의 소개 Julia 프로그래밍 - 언어 및 강의 소개Julia 프로그래밍 언어줄리아(Julia)는 고성능의 수치 해석 및 계산과학의 필요 사항
inner-game.tistory.com
[AI 인공지능 머신러닝 딥러닝/Julia] - Julia 프로그래밍 - 배열 및 선형 대수
Julia 프로그래밍 - 배열 및 선형 대수
[AI 인공지능 머신러닝 딥러닝/Julia] - Julia 프로그래밍 - 언어 및 강의 소개 Julia 프로그래밍 - 언어 및 강의 소개Julia 프로그래밍 언어줄리아(Julia)는 고성능의 수치 해석 및 계산과학의 필요 사항
inner-game.tistory.com
[AI 인공지능 머신러닝 딥러닝/Julia] - Julia 프로그래밍 - 플롯과 데이터 프레임
Julia 프로그래밍 - 플롯과 데이터 프레임
[AI 인공지능 머신러닝 딥러닝/Julia] - Julia 프로그래밍 - 언어 및 강의 소개 Julia 프로그래밍 - 언어 및 강의 소개Julia 프로그래밍 언어줄리아(Julia)는 고성능의 수치 해석 및 계산과학의 필요 사항
inner-game.tistory.com

사전
--사전 반복
세트
사용자 정의 유형
--추상 유형
--하위 유형
--유형 주석
--유형에 따라 배송
--사용자 정의 생성자
--추상 유형에 대한 디스패칭
--변경 가능한 유형
--호출 가능 유형
고급 사용자 정의 유형
--매개변수 합성 유형
--성능
--사용자 정의 유형의 함수 확장 ⁽⁺⁾
----예쁜 인쇄
----기지 운영자
--OOP와 Multiple dispatch 비교 ⁽⁺⁾
Julia에서는 사전을 key => value쌍으로 정의합니다.
capitals
Dict
"Germany"
"Berlin"
"Vietnam"
"Hanoi"
"Lebanon"
"Beirut"
"France"
"Paris"
capitals = Dict(
"France" => "Paris",
"Germany" => "Berlin",
"Lebanon" => "Beirut",
"Vietnam" => "Hanoi",
)
사전을 사용하면 알려진 키를 사용하여 값을 찾을 수 있습니다.
"Berlin"
capitals["Germany"]
키가 사전의 일부가 아닌 경우 실패할 수 있습니다.
Error message
KeyError: 키 "USA"를 찾을 수 없습니다.
Show stack trace...
capitals["USA"] # errors!
이 오류는 사전에 특정 키가 포함되어 있는지 확인하여 방지할 수 있습니다.
false
haskey(capitals, "USA")
get또는 기본 반환 값을 허용하는 함수를 사용합니다 .
"default return value"
get(capitals, "USA", "default return value")
사전은 자동으로 키-값 쌍으로 구조 분해됩니다.
for (k, v) in capitals
@info "$v is the capital of $k"
end
Berlin is the capital of Germany
Hanoi is the capital of Vietnam
Beirut is the capital of Lebanon
Paris is the capital of France
모든 키와 값에 직접 액세스할 수도 있습니다.
KeySet
"Germany"
"Vietnam"
"Lebanon"
"France"
keys(capitals)
ValueIterator for a Dict{String, String} with 4 entries. Values: "Berlin" "Hanoi" "Beirut" "Paris"
values(capitals)
팁
get!사전은 변경 가능하며 , pop!, , merge, 등 의 함수를 제공합니다 . Julia의 사전 관련 문서 를 참조하세요 .
수학의 집합과 비슷하게, 이 Set유형은 원소의 모임을 설명합니다.
a의 모든 요소는 Set고유하며 순서는 중요하지 않습니다.
s1
Set
0
2
3
1
s1 = Set([0, 1, 2, 3])
s2
Set
0
2
3
1
s2 = Set([3, 3, 2, 2, 1, 1, 0, 0])
true
s2 == s1
우리는 집합에서 요소를 추가하거나 제거할 수 있습니다:
begin
# Define a set
s3 = Set([1, 2, 3, 4])
@info s3
# Add a new number to the set
push!(s3, 6)
@info s3
# Remove number from set
pop!(s3, 2)
@info s3
# All elements of a set are unique, we can't add duplicates
push!(s3, 3)
@info s3
end

우리는 집합의 합집합과 교집합을 취할 수 있습니다.
Set
0
4
6
2
3
1
union(s1, s3)
Set
3
1
1
intersect(s1, s3)
팁
여러 다른 연산이 존재합니다(예 issubset: , isdisjoint, isempty, ). 집합에 대한 Julia 문서issetequal 를 살펴보세요 .
우리는 이미 Lesson 01: Basics I 에서 유형 계층 구조를 살펴보았습니다 .
간단히 요약하고 객체 지향 프로그래밍 언어의 은유를 사용하여 유형을 소개해 보겠습니다. 동물 .
가장 간단한 유형인 추상 유형부터 소개합니다. 추상 유형은 종종 접두사를 사용하여 명명됩니다 Abstract.
abstract type AbstractAnimal end
추상 유형은 인스턴스화할 수 없습니다. 추상 유형은 하위 유형 집합을 설명하는 데 사용됩니다 .
하위 유형은 .를 사용하여 정의합니다 <: ParentType. 또한 추상 유형이 될 수도 있는데, 이를 통해 여러 계층의 유형 계층을 정의할 수 있습니다.
abstract type AbstractMammal <: AbstractAnimal end
abstract type AbstractBird <: AbstractAnimal end
이제 첫 번째 구체적 유형인 고양이를 정의해 보겠습니다. 각 고양이에는 이름이 있어야 합니다.
struct Cat <: AbstractMammal
name
end
carlos
Cat
"Carlos"
carlos = Cat("Carlos")
이건 좀 문제가 있어요. 고양이의 이름을 정수로 지을 수 있거든요!
weird_name_cat
Cat
1.2
1
weird_name_cat = Cat(1.2)
유형을 정의할 때 유형 주석을 사용하면 더 나은 결과를 얻을 수 있습니다 Dog.
1
2
3
struct Dog <: AbstractMammal
name::String # <- additional type annotation!
end
이렇게 하면 String이름에 s만 사용할 수 있습니다.
david
Dog
"David"
david = Dog("David")

OOP에서처럼 "클래스 함수"를 작성하는 대신, 우리는 사용자 정의 유형에 대한 메서드를 정의합니다.
make_sound (generic function with 1 method)
make_sound(d::Dog) = "Woof!"
우리는 또한 우리 유형의 필드에 접근할 수 있습니다:
make_sound (generic function with 2 methods)
make_sound(c::Cat) = "Meow! My name is $(c.name)!"
시도해 봅시다:
"Woof!"
make_sound(david)
"Meow! My name is Carlos!"
make_sound(carlos)
Cat지금까지 우리는 구조체 와 구조체를 생성할 때 생성된 기본 생성자만 사용했습니다 Dog.
좀 더 화려하게 유형(🦜)을 도입 Parrot하고 앵무새가 대문자 이름만 좋아한다고 가정해 보겠습니다.
내부 생성자 | Inner constructors
구조체 내부에서 함수를 사용하여 내부 생성자를 정의할 수 있습니다 new. 내부 생성자는 불변식을 강제하는 데 사용됩니다. 예를 들어 인수가 허용 범위 내에 있는지 확인하는 데 사용됩니다.
외부 생성자 | Outer constructors
구조체 외부에서는 여러 개의 디스패치를 사용하여 임의로 많은 외부 생성자를 추가할 수 있습니다.
내부 생성자를 사용하여 모든 이름이 대문자가 되도록 해 보겠습니다. 또한 모든 앵무새의 기본 이름으로 "PATTY"를 구현하는 외부 생성자를 구현해 보겠습니다.
Parrot
begin
struct Parrot <: AbstractBird
name::String
Parrot(name) = new(uppercase(name)) # inner constructor
end
Parrot() = Parrot("PATTY") # outer constructor
end
paula
Parrot
"PAULA"
paula = Parrot("Paula")
patty
Parrot
"PATTY"
patty = Parrot()
팁
모든 생성자를 begin ... end블록으로 모으는 것은 Pluto 노트북에서만 필요합니다.
추상 유형에 대해서도 전달할 수 있습니다.
is_mammal각각의 구체적인 동물 유형( Cat, Dog, )을 정의하는 대신 Parrot, 가장 일반적인 유형에 대한 대체 메서드를 정의 AbstractAnimal하고 두 번째 메서드를 추가합니다 AbstractMammal.
is_mammal (generic function with 1 method)
is_mammal(m::AbstractAnimal) = false
is_mammal (generic function with 2 methods)
is_mammal(m::AbstractMammal) = true
BitVector:
true
true
false
false
is_mammal.([david, carlos, paula, patty])
구조체는 변경 가능하게 만들 수 있는데, 이는 구조체가 생성된 후에 필드를 수정할 수 있다는 것을 의미합니다.
이러한 유연성의 단점은 이러한 객체가 일반적으로 힙에 할당되기 때문에 성능 저하가 발생한다는 것입니다. 따라서 변경 가능한 타입은 피하는 것이 좋습니다!
mutable struct Student
name::String
id::Int
end
begin
# Add student
kim = Student("Kim", 456543)
@info kim.id
# change student ID number
kim.id = 456544
@info kim.id
end
456543
456544
모든 유형은 해당 유형에 메서드를 추가하여 "호출 가능"하게 만들 수 있습니다. Julia 문서에서는 이를 함수형 객체 또는 펑터(Funtor)라고 합니다.
begin
# Implements ax²+bx+c
struct QuadraticFunction
a::Float64
b::Float64
c::Float64
end
(q::QuadraticFunction)(x) = q.a^2 * x + q.b * x + q.c # add method
(q::QuadraticFunction)() = q(42) # we can also use multiple dispatch here
end
times_two_plus_one
QuadraticFunction
0.0
2.0
1.0
times_two_plus_one = QuadraticFunction(0.0, 2.0, 1.0)
11.0
times_two_plus_one(5.0)
85.0
times_two_plus_one()
팁
이는 __call__여러 개의 디스패치가 추가된 Python과 유사합니다.
좀 더 진보적이고 실용적인 예를 구현해 보겠습니다. 바로 우리만의 복소수 유형입니다.
1단원: 기초 I 에서 Rational및 Complex유형이 매개변수 합성 유형임을 확인했습니다 . 복소수도 같은 방식으로 구현해 보겠습니다.
struct MyComplex{T<:Real} <: Number
re::T
im::T
end
{T<:Real}이전 구조체와 비교했을 때 가장 큰 변화는 . 뒤의 중괄호 안에 있는 타입 매개변수입니다 MyComplex. 이는 다음과 같이 해석할 수 있습니다.
팁
4번 항목은 선택 사항입니다. 간단히 다음과 같이 작성할 수도 있습니다.
struct MyComplex{T} <: Number
re::T
im::T
end
하지만 이렇게 쓰면 eg가 허용되지 않는다는 MyComplex{T<:Real}것을 명시하게 됩니다 .MyComplex{String}
시도해 봅시다:
ci
MyComplex
1
3
ci = MyComplex(1, 3)
cf
MyComplex
1.2
3.0
cf = MyComplex(1.2, 3.0)
MyComplex{Int64}
typeof(ci)
MyComplex{Float64}
typeof(cf)
팁
여러 유형 매개변수를 갖는 구조체를 정의하는 것도 가능합니다. 예를 들어, 다음과 같이 정의할 수 있습니다.
struct MyComplex{T1, T2} <: Number
re::T1
im::T2
end
자세한 내용은 Julia 설명서 에서 확인할 수 있습니다 .
경고:
Julia 코드에서 최상의 성능을 얻으려면 유형 주석에 매개변수 및 구체적 유형만 사용 하고 추상 유형 (예 Number: , Real)은 절대 사용하지 마세요.
또한 유형 주석을 사용하지 않는 것도 피해야 합니다. 이렇게 하면 기본적으로 추상 유형이 사용되기 때문입니다 Any.
Point2D 좌표를 추적하고 이를 추가할 수 있는 구조체의 여러 변형을 구현하여 이를 보여드리겠습니다 .
# Bad performance: no type annotations used, defaults to abstract type Any
struct PointNoType
x # same as x::Any
y # same as y::Any
end
# Bad performance: abstract type used in type annotation
struct PointAbstract
x::Real
y::Real
end
# Good performance, but not flexible: only works with concrete type Int64
struct PointConcrete
x::Int64
y::Int64
end
# Good performance and very flexible: uses parametric type
struct PointParametric{T<:Real}
x::T
y::T
end
이러한 모든 지점에 대해 동일한 덧셈 연산을 정의해 보겠습니다.
add (generic function with 4 methods)
begin
add(a::PointNoType, b::PointNoType) = PointNoType(a.x + b.x, a.y + b.y)
add(a::PointAbstract, b::PointAbstract) = PointAbstract(a.x + b.x, a.y + b.y)
add(a::PointConcrete, b::PointConcrete) = PointConcrete(a.x + b.x, a.y + b.y)
add(a::PointParametric, b::PointParametric) = PointParametric(a.x + b.x, a.y + b.y)
end
using BenchmarkTools
이러한 모든 구조체에 대한 추가는 동일한 올바른 결과를 계산합니다.
begin
a_notype = b_notype = PointNoType(1, 2)
a_abstract = b_abstract = PointAbstract(1, 2)
a_concrete = b_concrete = PointConcrete(1, 2)
a_param = b_param = PointParametric(1, 2)
@info add(a_notype, b_notype)
@info add(a_abstract, b_abstract)
@info add(a_concrete, b_concrete)
@info add(a_param, b_param)
end

하지만 성능은 매우 다양합니다.


이러한 성능 차이는 Julia가 구조체 필드(여기서는 x와 y)의 타입을 유추할 수 있는지 여부에 따라 달라집니다. 타입을 유추할 수 있다면 Julia는 더욱 전문화되고 따라서 성능이 향상된 코드를 생성할 수 있습니다.
는 훨씬 더 유연하면서도 PointParametric동일한 성능을 제공 합니다.PointConcrete
PointParametric
1.2
3.4
PointParametric(1.2, 3.4) # Works with all subtypes of Real and is very performant!

PointConcrete(1.2, 3.4) # Error: can only create a PointConcrete with Int64s
팁
일반적으로 유형 매개변수를 사용하는 것이 좋습니다!
여러 디스패치를 사용하면 자체 유형을 사용하여 새로운 메서드를 추가하여 Julia Base나 다른 패키지의 함수를 확장할 수 있습니다.
예쁜 인쇄
확장하려는 가장 일반적인 함수는 입니다 Base.show. 이 함수는 Julia REPL과 노트북에서 사용자 정의 유형이 출력되는 방식을 정의합니다.
function Base.show(io::IO, c::MyComplex)
return println(io, "$(c.re)+$(c.im)im")
end
기지 운영자
MyComplex아무것도 계산할 수 없다면 우리의 데이터 유형은 쓸모가 없습니다. 따라서 데모 목적으로 복소수의 덧셈과 곱셈을 구현해 보겠습니다.
Julia Base에서 연산자를 확장하려면 연산자를 명시적으로 가져와야 합니다. 그런 다음 덧셈과 곱셈의 함수 형태 +(a, b)와 를 사용하여 *(a, b)에 대해 연산자를 재정의할 수 있습니다 MyComplex.
우리는 단순히 여러 디스패치를 사용하여 추가적인 메서드를 정의하고 있습니다!
convert (generic function with 224 methods)
begin
import Base: +, *, zero, convert
# Addition & multiplication with real numbers
+(a::MyComplex, b::Real) = MyComplex(a.re + b, a.im)
*(a::MyComplex, b::Real) = MyComplex(a.re * b, a.im * b)
# Addition & multiplication are commutative! Let's avoid code duplication
+(a::Real, b::MyComplex) = b + a # calls previous method
*(a::Real, b::MyComplex) = b * a # calls previous method
# Addition of complex numbers
+(a::MyComplex, b::MyComplex) = MyComplex(a.re + b.re, a.im + b.im)
# Multiplication of complex numbers
function *(a::MyComplex, b::MyComplex)
re = a.re * b.re - a.im * b.im
im = a.re * b.im + a.im * b.re
return MyComplex(re, im)
end
# Let's also define the additive identity (x + zero(x) = x):
zero(::MyComplex{T}) where {T} = MyComplex(zero(T), zero(T))
# In case of type promotion we should make it use zero
convert(::Type{MyComplex{T1}}, x::T2) where {T1,T2<:Real} = MyComplex(convert(T1, x), zero(T1))
end
경고:
이 유형은 완전한 기능을 갖춘 복소수 유형이 아니므- 로 대부분의 기본 연산자( , , ...)와 더 많은 함수를 다시 정의해야 합니다 /. 하지만 이 글을 통해 Julia가 이러한 기능들을 어떻게 구현하는지 감을 잡을 수 있기를 바랍니다!
다시 말해, 이 모든 방법을 begin ... end블록으로 모으는 것은 Pluto 노트북 내부에서만 필요합니다.
몇 줄의 코드만으로 이제 복소수를 원활하게 사용할 수 있습니다!
1+2im
3+4im
a, b = MyComplex(1, 2), MyComplex(3, 4)
2+4im
1
2 * a
8+4im
1
b + 5
6+6im
1
1
그리고 우리의 메서드가 Julia 소스 코드 내부에서도 실행되기 때문에 복소수도 행렬에서도 작동합니다!
begin
# Let's define two complex matrices A ∈ ℝ¹ˣ³, B ∈ ℝ³ˣ⁴
A_re = rand(-9:9, 1, 3)
A_im = rand(-9:9, 1, 3)
B_re = rand(-9:9, 3, 4)
B_im = rand(-9:9, 3, 4)
# Our complex numbers
A1 = MyComplex.(A_re, A_im)
B1 = MyComplex.(B_re, B_im)
# Julia's complex numbers
A2 = Complex.(A_re, A_im)
B2 = Complex.(B_re, B_im)
end;
1×4 Matrix{MyComplex{Int64}}: 49+59im -39+5im -37+-36im -20+46im
1
1×4 Matrix{Complex{Int64}}: 49+59im -39+5im -37-36im -20+46im
1
팁
호기심이 생기셨다면 해당 유형의 실제 Julia 소스 코드 를 살펴보세요 Complex. 엄선된 소스는 다음과 같습니다.
참고: 이는 저의 개인적인 의견입니다.
이 강의에서는 객체 지향 프로그래밍(OOP)의 은유를 사용하여 Julia 프로그래밍 개념을 소개했습니다. 이제 우리 코드를 객체 지향 Python으로 구현한 예를 살펴보겠습니다.
class Dog(Mammal):
def __init__(self, name):
self.name = name
def make_sound(self):
return "Woof!"
파이썬은 객체 클래스에 대한 단일 디스패치make_sound(self) 의 인스턴스로 볼 수 있습니다 . 단일 입력 함수 나 엄격한 유형 제한이 있는 함수의 경우, 단일 디스패치는 매우 적합한 패턴입니다.make_sound
OOP의 단점
그러나 두 가지 서로 다른 입력 유형을 갖는 함수(예: 함수)에 대해 생각하면 상황은 더욱 복잡해집니다 interact(animal1, animal2).
다중 발송의 단점
Julia의 다중 디스패치 구현에도 단점이 있습니다.
두 철학 모두 유사점이 있지만, 매우 다른 설계 접근 방식이 필요합니다. Julia Base 및 다른 패키지의 기능을 확장하는 것은 쉽지만, 이러한 확장 기능들이 얼마나 잘 구성되는지는 항상 명확하지 않습니다. 인터페이스를 구현하는 여러 Julia 패키지가 있지만, 이 문제는 대개 광범위한 패키지 테스트를 통해 완화되는데, 이에 대해서는 8단원: 워크플로 에서 배우게 됩니다.
다음강의: [AI 인공지능 머신러닝 딥러닝/Julia] - 줄리아 프로그래밍 - 자동 미분 Automatic differentiation | Forward- & Reverse-Mode AD
줄리아 프로그래밍 - 자동 미분 Automatic differentiation | Forward- & Reverse-Mode AD
첫 강의: [AI 인공지능 머신러닝 딥러닝/Julia] - Julia 프로그래밍 - 언어 및 강의 소개 Julia 프로그래밍 - 언어 및 강의 소개Julia 프로그래밍 언어줄리아(Julia)는 고성능의 수치 해석 및 계산과학의 필
inner-game.tistory.com
[AI 인공지능 머신러닝 딥러닝/머신러닝] - Julia 프로그래밍 - 머신 러닝을 위한 Julia
Julia 프로그래밍 - 머신 러닝을 위한 Julia
[AI 인공지능 머신러닝 딥러닝/Julia] - Julia 프로그래밍 - 언어 및 강의 소개 Julia 프로그래밍 - 언어 및 강의 소개Julia 프로그래밍 언어줄리아(Julia)는 고성능의 수치 해석 및 계산과학의 필요 사항
inner-game.tistory.com