딥러닝 모델을 학습하고 데모를 하기 위해 별도의 web application을 만드는 경우가 종종있다. 하지만, 간단한 데모를 우해서 backend와 frontend를 만드는 과정이 귀찮고 번거로울 수 있다. 우리가 평소에 자주쓰는 Jupyter notebook위에서 notebook를 frontend로 사용하여 동적인 작업을 위한 Javascript를 추가하고 notebook kernel과 연결하면 양뱡향 통신이 가능하도록 할수 있다.
1. Notebook에 Javascript 삽입
input.html
<script type="text/Javascript">
var pixels = [];
for (var i = 0; i < 28*28; i++) pixels[i] = 0;
var click = 0;
var canvas = document.querySelector("canvas");
canvas.addEventListener("mousemove", function(e){
if (e.buttons == 1) {
click = 1;
canvas.getContext("2d").fillStyle = "rgb(0,0,0)";
canvas.getContext("2d").fillRect(e.offsetX, e.offsetY, 8, 8);
x = Math.floor(e.offsetY * 0.2);
y = Math.floor(e.offsetX * 0.2) + 1;
for (var dy = 0; dy < 2; dy++){
for (var dx = 0; dx < 2; dx++){
if ((x + dx < 28) && (y + dy < 28)){
pixels[(y+dy)+(x+dx)*28] = 1;
}
}
}
} else {
if (click == 1) set_value();
click = 0;
}
});
function clear_value(){
canvas.getContext("2d").fillStyle = "rgb(255,255,255)";
canvas.getContext("2d").fillRect(0, 0, 140, 140);
for (var i = 0; i < 28*28; i++) pixels[i] = 0;
}
function set_value(){
var result = "[["
for (var i = 0; i < 28; i++) {
result += "["
for (var j = 0; j < 28; j++) {
result += pixels [i * 28 + j]
if (j < 27) {
result += ", "
}
}
result += "]"
if (i < 27) {
result += ", "
}
}
result += "]]"
var kernel = IPython.notebook.kernel;
kernel.execute("data = " + result)
}
</script>
<table>
<td style="border-style: none;">
<div style="border: solid 2px #666; width: 143px; height: 144px;">
<canvas width="140" height="140"></canvas>
</div></td>
<td style="border-style: none;">
<button onclick="clear_value()">Clear</button>
</td>
</table>
demo.ipynb
from IPython.display import HTML
HTML(open("./input.html").read())
위의 코드를 실행하면 아래와 같이 주피터 노트북에 javascript를 삽입할수 있다.
2. Javascript에서 notebook kernel 호출
frontend에서 저장된 결과를 notebook으로 가져오기 위해선 notebook의 kernel에 접근해야한다.
function set_value(){
var result = "[["
for (var i = 0; i < 28; i++) {
result += "["
for (var j = 0; j < 28; j++) {
result += pixels [i * 28 + j]
if (j < 27) {
result += ", "
}
}
result += "]"
if (i < 27) {
result += ", "
}
}
result += "]]"
var kernel = IPython.notebook.kernel;
kernel.execute("data = " + result)
}
위 코드에서 var kernel = IPython.notebook.kernel; 은 python kernel을 frontend에서 접근가능하게 해준다.
kernel.execute(command, callbacks, options) 를 통하여 문자열 형식의 python code를 kernel을 통해 실행 할수 있게한다. "data = "[[0, 0, 0 ...]]"" 이 kernel에 실행되는 코드이며 이는 python data variable에 string을 할당하게 된다.
3. Kernel 실행결과 Javascript로 전송
반대로 notebook의 결과를 frontend로 전송하기 위해선 callbacks을 이용하면 된다.
function get_notebook_variable(){
var callbacks = {iopub : {
output : handle_output,
}
}
var kernel = IPython.notebook.kernel;
kernel.execute("img", callbacks, {silent:false})
}
function handle_output(data){
inf_image.src = "data:image/png;base64," + data.content.data["image/png"]
inf_image.onload = function() {
context.drawImage(inf_image, 0, 0, canvas.width, canvas.height);
};
}
kernel.execute에서 callbacks을 사용하게되면 command를 실행시킨 결과가 callbacks을 통하여 frontend에서 접근가능해진다. 이때 data는 실행시킨 python코드에 따라 달라지는데 현재 "img"는 pil image 로 image/png 형식의 base64 encoding되어 있다. 이를 canvas에 그릴 수 있다.
Reference
- jakevdp.github.io/blog/2013/06/01/ipython-notebook-javascript-python-communication/
- https://aws.amazon.com/ko/blogs/machine-learning/amazon-sagemaker-now-supports-pytorch-and-tensorflow-1-8/
IPython Notebook: Javascript/Python Bi-directional Communication | Pythonic Perambulations
Examining the code, we see that when the button is clicked, the set_value() function is called, which constructs a simple Python statement assigning var_value to the variable given by var_name. As mentioned above, the key to interaction between Javascript
jakevdp.github.io
Amazon SageMaker now supports PyTorch and TensorFlow 1.8 | Amazon Web Services
Starting today, you can easily train and deploy your PyTorch deep learning models in Amazon SageMaker. This is the fourth deep learning framework that Amazon SageMaker has added support for, in addition to TensorFlow, Apache MXNet, and Chainer. Just like
aws.amazon.com
'Pytorch' 카테고리의 다른 글
[Pytorch] permute vs view (0) | 2020.05.09 |
---|