Julia Plots.jl에서 애니메이션이있는 단일 회귀선을 작성했습니다.

9845 단어 JuliaPlots.jl
안녕하세요, 첫 게시물이므로 어태프터하고 있습니다.

점차 Julia를 사용하여 데이터 분석을 실시하게 되어 왔습니다만, 별건으로 GIF 출력을 부탁받았으므로 샘플을 만들어 보았습니다.
그냥 Python에서 가져온 최소 제곱법이 있었으므로, 이것으로 시도해 보면 샘플을 늘리면 안정되어 오는 모습이 잘 알았기 때문에 투고 해 보겠습니다.

우리 쪽의 환경은 이하입니다.
OS OSX Catalina
개발 환경 JuliaPro 1.4.2-1
따라서 ATOM + Juno + Julia 1.4.2와 거의 동일합니다.

먼저 완성품을 부디





이제 코드를 설명합니다.

사용한 라이브러리는
using Statistics
using Plots
using Printf
using Random

비교적 짧은 코드로, 코멘트를 많이 포함하고 있으므로, 실제로 무엇을 하고 있는지는 읽고 받는 것이 빠릅니다만,

GIF 작성 흐름



Plots.jl을 사용한 애니메이션 (GIF) 생성의 흐름을 간략하게 설명하면

1. 애니메이션을 사용하기 위한 인스턴스를 준비
2. 그래프 등을 한 장 작성
3. 애니메이션용 인스턴스에 추가
4. 필요한 경우 2로 돌아가기
5.Gif 출력

라는 간단한 흐름입니다.

샘플의 수가 늘어나면 빨간색 직선이 그다지 움직이지 않게 되어 안정된 결과가 되는 것이 잘 알 수 있습니다.
논리로서는 알고 있어도 다시 눈으로 보면 재미있는 것입니다

데모 데이터 만들기



n = 500 # 데모 데이터 수
이것은 편의를 위해 500으로 만들었지만 특별한 이유는 없습니다.
GIF를 바라보는데 딱 좋을까 생각했기 때문입니다.
gif(anim, "test.gif", fps = 30) # 30 프레임/Sec에서 gif 출력
이 부분의 프레임 수를 늘리면 데모 데이터 수를 늘려도 멋지다고 생각됩니다.
dx = randn(n) # 난수를 지정 개수 발생
dy = randn(n)/2 .+ dx # 좋은 소금 매실에 멋지게 소음을 더한다
이 dy에 관해서는 dx와 같으면 직선상에 나란히 흥미롭지 않기 때문에
적당히 난수를 더하는 것으로 노이즈를 발생시키고 있습니다.
randn(n)/2 .+ dx
이 의미는 발생한 난수를 2로 나눈 값을 dx 배열의 개별 요소에 추가한다는 의미입니다.

샘플 코드



test.jl
#=
    単回帰分析 Simple regression analysis
=#
using Statistics    # LinRegの中で使用する統計関数の使用宣言

# 単回帰分析
function LinReg(x, y)
    #=
        linear regression
        2つの配列を受取り、単回帰分析を行う
        x,yの配列の大きさは同じである事が前提。
        配列の大きさが異なる場合にはエラーで落ちる
        面倒なので、チェックをしていない

        もっと早い手法もあるが、可読性重視とした
    =#
        b = Statistics.cov(x,y) / Statistics.std(x)^2
        a = Statistics.mean(y) - b * Statistics.mean(x)
        return b, a
end

using Plots     # 散布図と直線を描く為に使用
using Printf    # @sprintfを氏要すために使用
using Random    # サンプルデータにノイズを加えるために使用

#アニメーションのインスタンス生成
anim = Animation()

# デモデータの作成
n = 500                   # デモデータの個数
dx = randn(n)             # 乱数を指定個数発生
dy = randn(n) / 2 .+ dx   # 良い塩梅に見栄え良くノイズを加える


# 散布図と直線を描画したグラフをn枚作成しながら、
# アニメーション用のフレームに追加していく
for dn = 2:n # 2から始めないと直線が書けないので
    # 散布図を作成
    ps = plot(
        dx[1:dn],
        dy[1:dn],
        seriestype = :scatter,
        title  = "Linear regression Demonstration",
        lab    = "Data $(dn) / $(n) ",
        xlabel = "xlabel",
        ylabel = "ylabel",
        legend = :topleft,
        c = :green,
        xlims  = (-3, 3),
        ylims  = (-3, 3)   # お好みでグラフを表示する範囲を指定しておく
    )

    # Y = aX + b の a,bを求める
    a, b = LinReg(dx[1:dn], dy[1:dn])

    # 直線描画
    plot!(
        ps, # 分散図に追加描画 (省略可能)
        x -> a * x + b,
        findmin(dx)[1],
        findmax(dx)[1],    # 横軸の最小値、最大値を求め、その間を描画する
        lab = @sprintf(    # 見栄えの為
            "y = %s * x + %s",
            string(round(b, digits = 4)), # 小数点4桁だけ表示
            string(round(a, digits = 4))
        ),
        lw = 3,
        c = :red,
    )
    frame(anim, ps) # フレームとして追加する
end

# フレームが出来たので出力する
popdisplay()        # Plotsを使うときには記述した方がベター
gif(anim, "test.gif", fps = 30) # 30フレーム/Secでgifを出力


이상입니다.

좋은 웹페이지 즐겨찾기