본문 바로가기
코딩과 알고리즘

파도(17) - 자바스크립트와 파이스크립트, 손잡다!

반응형

🍬 '파도'는 크레이의 파이스크립트 도전기의 줄임말입니다.

지난 게시글에서 연재되는 글입니다.
https://itadventure.tistory.com/558

 

파도(16) - 파이스크립트의 특좌앙~점으로 머신러닝!

🐳 '파도'는 크레이가 도전하고 있는 파이스크립트 도전기의 줄임말입니다. 지난 게시글에서 연재되는 글입니다. : https://itadventure.tistory.com/557 파도!(15) - 라쏘회귀와 4차방정식까지 🍿 '파도'는

itadventure.tistory.com

 

지난 게시글에서는 웹브라우저에서 알고리즘 종류와 알파값을 선택상자에 있는 옵션을 선택하여
결과 그래프를 도출하는 부분을 살펴보았는데요.

 

파이스크립트와 자바스크립트, 친해질 수 있을까요?

 

이번 시간에는, 해당 모듈을 불러와 사용하는 방법에 대해 알아보도록 하겠습니다.

드디어 파이스크립트와 자바스크립트와 콜라보~, 협력하여 상호 작용하는 부분을 알아냈습니다.

지난 시간에 설명드렸다시피 파이스크립트는 웹브라우저 내부적으로 파이썬을 작동하고 있는데요.
이 파이썬은 웹 어셈블리 방식라는 기술로 작동하기 때문에 일반적으로 자바스크립트 방법으로는 접근하기 어렵습니다.
그렇다면 방법이 없을까요? 물론~ 있지요. 아니라면 이 글을 쓸 이유조차 없겠지요? :)
대단히 어려운 것도 아닙니다. 파이스크립트에 방법이 이미 마련되어 있기 때문이지요.

자바스크립트와 파이썬이 쉽게 만나기 위해서는 다음 2개의 모듈이 필요합니다. 

from js import document
from pyodide import create_proxy

 

첫번째 도큐먼트 모듈

 

첫번째, document 는 웹페이지의 문서를 관리하는데요. 돔(DOM)이라고도 불립니다.
웹페이지에 다음과 같이 아이디(id)가 'algorithm'이라는 선택상자가 있다면,

<select id="algorithm">
  <option value="">알고리즘을 선택하세요</option>
  <option value="릿지">릿지 회귀 (Ridge Regression)</option>
  <option value="라쏘">라쏘 회귀 (Lasso Regression)</option>
</select><br/>

파이스크립트에서 이 선택상자의 값을 알아내기 위해서는 아래 속성을 확인하면 됩니다.
물론 document 모듈을 경우해서 확인하는 것이지요.

document.getElementById("algorithm").value


기본적으로 document 모듈은 선언하지 않아도 사용 가능합니다만,
현재 파이스크립트가 알파버전이고 추후 버전이 바뀌면 갑자기 안될 수 있어
기본적으로 선언하고 들어가는 걸로 하겠습니다.

 

두번째, 프록시 모듈

 

두번째 모듈은 create_proxy 모듈입니다.
'proxy' 는 영어사전에서 위임권, 대리인 등의 뜻을 찾아볼 수 있는데요.
여기서는 웹브라우저에서 발생하는 자바스크립트 이벤트파이스크립트로 연결해주는 것을 의미합니다.

그래서 보통 선택상자에서 무언가를 선택할 경우 아래와 같은 자바스크립트 이벤트가 발생이 되는데요. ( 빨간색 )


<select id="algorithm" onchange="이벤트함수()">


요새 자바스크립트는 이것보다는 약간 고오~급스런 방법을 씁니다.
보통 아래와 같이 사용하지요.


let e1 = document.getElementById('algorithm');
e1.addEventListener('change', function(event){
    : // 작동할 자바스크립트 소스
});


파이스크립트는 아래와 같이 사용합니다. 매우 비슷하지요? :)


e1 = document.getElementById("algorithm")
e1.addEventListener("change", create_proxy(이벤트함수))


이 때 이벤트 함수는 자바스크립트가 아닌 파이썬 함수이어야 하구요.
아래와 같은 형태로 함수를 선언해주면 됩니다.
뒤에 파라미터 (event)가 따라 붙어야 한다는 점만 지켜주면 되지요.


def 이벤트함수(event):
    : # 작동할 코드


위 내용은 어디까지나 <pyscript> 태그 안에서의 방법이고 create_proxy 모듈을 통해 사용할 수 있습니다.

 

실제 적용

 

이제 2개의 모듈의 사용법을 알았으니 실제 적용과정을 알아볼까요?

선택상자는 2개를 사용할텐데요.

각각 알고리즘 종류를 선택하는 선택 상자와, 알고리즘의 과적합을 방지할 알파값을 선택하는 선택 상자입니다.
이 선택상자가 선택될 때마다 머신러닝으로 데이터를 다시 훈련하고, 그래프도 다시 그리도록 할텐데요.

각각의 id값은 "algorithm", "alpha_value"입니다. HTML  소스는 아래와 같구요.

알고리즘 선택 :
<select id="algorithm">
  <option value="">알고리즘을 선택하세요</option>
  <option value="릿지">릿지 회귀 (Ridge Regression)</option>
  <option value="라쏘">라쏘 회귀 (Lasso Regression)</option>
</select><br/>

알파값 선택 : 
<select id="alpha_value">
  <option value="0.001">0.001</option>
  <option value="0.01">0.01</option>
  <option value="0.1">0.1</option>
  <option value="1">1</option>
  <option value="10">10</option>
  <option value="100">100</option>
</select><br/>


그리고 이 선택상자를 선택할 때마다 '그래프함수'를 호출하도록 파이스크립트를 구성합니다.

# 자바스크립트와 통신
from js import document
from pyodide import create_proxy

e1 = document.getElementById("algorithm")
e1.addEventListener("change", create_proxy(그래프함수))  

e2 = document.getElementById("alpha_value")
e2.addEventListener("change", create_proxy(그래프함수))


이제 그래프함수를 구현하면 되는데요.
그래프함수 내 csv 파일을 불러오는 부분부터 시작해서 모든 소스를 다 넣어도 됩니다만,
여기서는 한번만 실행해도 되는 부분은 미리 실행해버리고,
그래프함수에서는 변경되거나 필수로 작동해야 하는 부분만 실행하도록 하겠습니다.

기본적으로  csv  파일을 불러와 데이터를 가공하는 부분은 릿지모델이나 라쏘모델이나 똑같습니다. 그리고 그래프 모듈을 불러와 한글 폰트를 적용하는 부분도 동일하기 되기 때문에,
해당 부분은 선택상자와 무관하게 1번만 수행합니다.

<py-script>
import pandas as pd
from pyodide.http import open_url
from common import *
import numpy as np

from datetime import datetime

        :
        :
        :
        
# 개별 폰트 적용
NanumMyengjo = fm.FontProperties(
  fname='./NANUMMYEONGJO.TTF'
)
NanumMyengjoBold = fm.FontProperties(
  fname='./NANUMMYEONGJOBOLD.TTF'
)


이제 선택상자를 선택할 때 작동할 '그래프함수'를 선언합니다.

def 그래프함수(event):

그리고 선택한 알고리즘이 무엇인지, 알파값이 얼마인지를 받아오는데요.
이 때도 document 모듈을 사용합니다.

알고리즘 = document.getElementById("algorithm").value
알파값 = float(document.getElementById("alpha_value").value)

 

선택된 알고리즘에 따라 각기 다른 처리를 하도록 하겠습니다.
릿지와 라쏘에 대한 처리를 나누어 수행할텐데요.

if 알고리즘=='릿지':
  : # 릿지 알고리즘일 때 처리할 코드
else:
  : # 그 외 알고리즘일 ㅐ 처리할 코

릿지 알고리즘일 때는 릿지 모델을 정의해 훈련을 하고,

if 알고리즘=='릿지':
    #=====================================
    # 릿지모델
    릿지모델 = Ridge(alpha=알파값)
    릿지모델.fit(훈련용데이터_가공, 훈련용목표)

    훈련점수=릿지모델.score(훈련용데이터_가공, 훈련용목표)
    테스트점수=릿지모델.score(테스트데이터_가공, 테스트목표)
       :
    훈련용목표예측 = 릿지모델.predict(훈련용데이터_가공)
    테스트목표예측 = 릿지모델.predict(테스트데이터_가공)

라쏘 알고리즘일 때는 라쏘 모델을 정의해서 훈련을 하는데요.

  else:
    #=====================================
    # 라쏘모델
    라쏘모델 = Lasso(alpha=알파값)
    라쏘모델.fit(훈련용데이터_가공, 훈련용목표)
    
    훈련점수=라쏘모델.score(훈련용데이터_가공, 훈련용목표)
    테스트점수=라쏘모델.score(테스트데이터_가공, 테스트목표)
      :
    훈련용목표예측 = 라쏘모델.predict(훈련용데이터_가공)
    테스트목표예측 = 라쏘모델.predict(테스트데이터_가공)


훈련 점수와 테스트 점수를 표현하기 위해 print() 함수를 쓰는 대신,
해당 요소들을 표시할 HTML 태그를 미리 준비해두면,

훈련점수 : <span id="train_score" style=''></span><br/>
테스트점수 : <span id="test_score" style=''></span><br/>


아래처럼 document 모듈을 통해 내용을 직접 갱신할 수 있습니다.
그러면 점수가 2, 3번 화면에 표시될 일도 없습니다.

  if 알고리즘=='릿지':
  
         :
         
    document.getElementById("train_score").innerHTML=훈련점수
    document.getElementById("test_score").innerHTML=테스트점수
    
         :
         
  else:
  
         :
         
    document.getElementById("train_score").innerHTML=훈련점수
    document.getElementById("test_score").innerHTML=테스트점수
    
         :


그래프를 그리는 위치 또한 정의할 수 있는데요.
역시 사전에 HTML 태그를 마련해 두고,

<div id="graph"></div>

그래프를 그리는 부분을 아래와 같이 변경해주면 됩니다.
그러면 그래프 또한 2, 3번 표시될 일이 없습니다.

<변경전>

fig

<변경후>

pyscript.write("graph",fig)

 

자유로운 UI 적용


그리고 HTML 의 css 스타일 시트를 잘 활용하실 수 있다면 
아래처럼 우측 상단에 그래프를 표시하는 등의 방법으로 자유롭게 화면을 구성하실 수 있습니다.

최종 소스에는 없지만 아래 태그를 <body> 아래 넣어주시면
그래프가 우측 상단에 딱 고정되어 표시됩니다.

<style>
#graph {
  position:fixed;
  right:20px;
  top:20px;
  border:1px solid;
  width:1000px;
  height:500px;
}
</style>


참고로 이 글의 최종소스는 지난 게시글을 참조해 주세요.
https://itadventure.tistory.com/558

 

마무~리

 

이상으로 파이스크립트에서 아보카도로 머신러닝하는 방법에 대해 살펴보았는데요.
이번시간에는 특히 파이스크립트와 자바스크립트간 연동하는 부분에 대해 살펴보았습니다.


아무쪼록 필요하신 분께 도움이 되셨을지요 :)
방문해주시는 모든 분들께 늘 감사드립니다.

유익하셨다면 공감  한방, 댓글은 굿잡!
감사합니다~


다음 게시글 : https://itadventure.tistory.com/560

 

파도(18) - 랜덤고양이 이미지 불러오기

※ '파도'는 크레이의 '파이스크립트 도전기'의 줄임말입니다. 지난 게시글에서 연재되는 글입니다. : https://itadventure.tistory.com/559 파도(17) - 자바스크립트와 파이스크립트, 손잡다! 🍬 '파도'는

itadventure.tistory.com

 

반응형