Published Date : 2019年12月22日22:36
p5.jsとnumjsを使って何かをやろうという記事です。
This blog post is about doing something with p5.js and numjs.
何故P5なのか?Javascriptオンリーでやればいいのではないか? 単純にP5は可視化が簡単なので、P5を採用しています。
Why p5.js? Why don't you just use Javascript? You might think so. The reason is simple. Since p5.js is easy to visualize, I'm using p5.js this time.
もちろん、P5はJavascriptで作られているので、P5内でJavascriptそのものが使えます。 なので、基本P5で書いていきますが、P5では難しい文字列処理等はJavascriptでそのまま書いていきます。
Of course, p5.js is written in Javascript, so you can use it directly in p5.js. I usually write code in p5.js, but there many things that are difficult to process in p5.js (String operations, etc.), so if I encounter such a situation, I write code directly in Javascript.
目次
Table of Contents
簡単な概要です。
Here's a quick overview.
まずこの記事の目的は、NumjsというNumpy(Python)のJavascriptヴァージョンを使用して、何か面白いことができるのでは無いかと模索してみることです。
First of all, the purpose of this blog post is to explore the possibility of doing something interesting with numjs. (Javascript version of the Python's module Numpy)
まずは、Numjsの使い方を説明します。 具体的にはブラウザからライブラリを読み込み、基本的なメソッドの使用方法と Javascriptでの動作と、Pythonのように扱うためのTips等を紹介します。
First, I'll show you how to use numjs, including how to load the library from a browser, use basic methods, how to work with Javascript, and tips for working like Python.
殆どのNumjsの説明は、こちらの本家のページに詳しく書いてあります。
Most numjs description are detailed on the original page here.
NumjsをHTMLから読み込みます。 まずフォルダ構成です。
Load Numjs from HTML. First, Let's look at the folder structure.
your folder - numjsTutorial.html - numjsTutorial.js
そしてHTMLの中身です。
And the HTML content.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <!-- p5.js cdn --> <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/addons/p5.dom.min.js"></script> <!-- numjs cdn --> <script src="https://cdn.jsdelivr.net/gh/nicolaspanel/[email protected]/dist/numjs.min.js"></script> <!-- your sketch file --> <script src="numjsTutorial.js"></script> <title>Document</title> </head> <body> </body> </html>
NumjsとNumpyを比べながら使い方を見てみましょう。
Let's compare numjs and numpy and see how numjs is used.
TerminalやCommandPromptを開いて、「ipython」と打ち、コンソール画面とブラウザを見比べながらやると分かりやすいです。
It is easier to understand if you open the Terminal or Command Prompt, and type [ipython] to compare the console screen with the browser output.
「ipython」が無ければ、「pip install ipython」でインストールしましょう。 面倒くさければ「python」とだけ打てば対話型画面になります。
If you don't have "ipython", you can install it using [pip install ipython]. If for some reason you want to avoid it, just type [python] on the screen, and you'll get an interactive screen.
In [1]: import numpy as np In [2]: a = np.array([1, 2, 3]) In [3]: print(a) [1 2 3]
let a; function setup(){ createCanvas(300, 300); a = nj.array([1, 2, 3]); text(a, 150, 150); }
HTMLファイルをブラウザにドラックアンドドロップするか、ダブルクリックして開いてください。
Drag and Drop the HTML file into the browser or double-click to open it.
おそらくブラウザ画面には「array([1,2,3])」と表示されているはずです。 正確に数字だけを表示させたい場合はtolistメソッドを使用します。
You should see 「array([1,2,3])」 on your browser screen. If you want to display only numbers exactly on the screen, use the tolist method.
let a; function setup(){ createCanvas(300, 300); a = nj.array([1, 2, 3]); text(a.tolist(), 150, 150); }
ではどんどん進みましょう。
Let's keep going.
In [4]: for i in a: ...: print(i) ...: 1 2 3
let a; function setup(){ createCanvas(300, 300); a = nj.array([1, 2, 3]); for (let i = 0; i < a.tolist().length; i++){ text(a.tolist()[i].toString(), 150 + (i * 10), 150); } }
1 2 3と表示されますが、とてもわかりにくいっすよね。
It shows "1 2 3", but it's very difficult to understand.
まず「a.tolist().length」と、リストに直してから長さを取得してます。 さらに、配列の参照を使うためにまたリストに戻してから、「toString」を使い(インデックス × 10ピクセル)で文字を横にずらして重ならないように表示させていきます。
First, convert numjs object to a list using "a.tolist()", then get the length using "length". In addition, because I want to use an array reference, I convert the numjs object to a list using "tolist()", and then use "toString" to convert the referenced value back to characters. Then use "i(index) times 10 pixels" to shift characters from 0 to 20 pixels horizontally so that they do not overlap.
もっと簡単な方法があります。
But, there is an easier way.
let a; function setup(){ createCanvas(300, 300); a = nj.array([1, 2, 3]).tolist(); for (let [index, element] of a.entries()) { text(element, 150 + (index * 10), 150); } }
「entries メソッド」はインデックス番号と配列の要素をリストにして取り出してくれます。Pythonでいう「enumerate」です。
"entries method" will fetch a list of index numbers and array elements. "enumerate" in python.
In [5]: for i,e in enumerate(a): ...: print(f"index number: {i}\nelement: {e}\n") ...: index number: 0 element: 1 index number: 1 element: 2 index number: 2 element: 3
このように若干表示や配列の操作がややこしくなってしまいますが、 Numpyのメソッド自体はほぼ同じです。
In this way, the display and array operations become slightly more complex. However, the numpy method itself is similar. like this.
import numpy as np # sigmoid function def sigmoid(arg): return 1 / (1 + np.exp(-arg)) # softmax function def softmax(arg): exp_arg = np.exp(arg - np.max(arg)) sum_exp_arg = np.sum(exp_arg) return exp_arg / sum_exp_arg def setup(): a = np.array([1,2,3]) b = np.zeros([3,3]) c = np.ones([3,3,3], dtype='float32') -> d = np.random.rand(3,3) e = np.arange(3) f = np.arange(9,54,6) g = np.arange(9).reshape(3, 3) h = g.shape i = g.ndim j = g.dtype -> k = g[2, 1] -> l = g.copy() -> l[1, 1] = 4 m = np.ones([3,3]) -> n = np.add(m, m) -> o = np.subtract(n, m) -> p = np.power(o, m) q = p.flatten() r = q.T s = np.identity(3) -> t = softmax(s) -> u = sigmoid(s) v = np.exp(s) w = np.arange(18).reshape(6,3) x = np.dot(w, np.add(s, 6)) arr = [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x]; for var in arr: print(var) In [2]: setup() [1 2 3] [[0. 0. 0.] [0. 0. 0.] [0. 0. 0.]] [[[1. 1. 1.] [1. 1. 1.] [1. 1. 1.]] [[1. 1. 1.] [1. 1. 1.] [1. 1. 1.]] [[1. 1. 1.] [1. 1. 1.] [1. 1. 1.]]] [[0.46998273 0.30529273 0.0922263 ] [0.76240678 0.30847944 0.70136193] [0.19057421 0.57756481 0.28406048]] [0 1 2] [ 9 15 21 27 33 39 45 51] [[0 1 2] [3 4 5] [6 7 8]] (3, 3) 2 int32 7 [[0 1 2] [3 4 5] [6 7 8]] [[1. 1. 1.] [1. 1. 1.] [1. 1. 1.]] [[2. 2. 2.] [2. 2. 2.] [2. 2. 2.]] [[1. 1. 1.] [1. 1. 1.] [1. 1. 1.]] [[1. 1. 1.] [1. 1. 1.] [1. 1. 1.]] [1. 1. 1. 1. 1. 1. 1. 1. 1.] [1. 1. 1. 1. 1. 1. 1. 1. 1.] [[1. 0. 0.] [0. 1. 0.] [0. 0. 1.]] [[0.19203896 0.07064719 0.07064719] [0.07064719 0.19203896 0.07064719] [0.07064719 0.07064719 0.19203896]] [[0.73105858 0.5 0.5 ] [0.5 0.73105858 0.5 ] [0.5 0.5 0.73105858]] [[2.71828183 1. 1. ] [1. 2.71828183 1. ] [1. 1. 2.71828183]] [[ 0 1 2] [ 3 4 5] [ 6 7 8] [ 9 10 11] [12 13 14] [15 16 17]] [[ 18. 19. 20.] [ 75. 76. 77.] [132. 133. 134.] [189. 190. 191.] [246. 247. 248.] [303. 304. 305.]]
function setup(){ let a = nj.array([1,2,3]); let b = nj.zeros([3,3]); let c = nj.ones([3,3,3], 'float32'); -> let d = nj.random([3,3]); let e = nj.arange(3); let f = nj.arange(9,54,6); let g = nj.arange(9).reshape(3, 3); let h = g.shape; let i = g.ndim; let j = g.dtype; -> let k = g.get(2,1); -> let l = g.set(1,1,4); let m = nj.ones([3,3]); -> let n = m.add(m); -> let o = n.subtract(m); -> let p = o.pow(m); let q = p.flatten(); let r = q.T let s = nj.identity(3); -> let t = nj.softmax(s); -> let u = nj.sigmoid(s); let v = nj.exp(s); let w = nj.arange(18).reshape(6,3); let x = nj.dot(w, s.add(6)); let arr = [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x]; for (let i = 0; i < arr.length; i++) { print(arr[i].toString()); } }
nj.array([1,2,3]); array([ 1, 2, 3]) nj.zeros([3,3]); array([[ 0, 0, 0], [ 0, 0, 0], [ 0, 0, 0]]) nj.ones([3,3,3], 'float32'); array([[[ 1, 1, 1], [ 1, 1, 1], [ 1, 1, 1]], [[ 1, 1, 1], [ 1, 1, 1], [ 1, 1, 1]], [[ 1, 1, 1], [ 1, 1, 1], [ 1, 1, 1]]], dtype=float32) nj.random([3,3]); array([[ 0.88514, 0.81867, 0.18705], [ 0.27225, 0.07831, 0.31183], [ 0.26983, 0.69685, 0.22055]], dtype=float64) nj.arange(3); array([ 0, 1, 2]) nj.arange(9,54,6); array([ 9, 15, 21, ..., 39, 45, 51]) nj.arange(9).reshape(3, 3); array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8]]) g.shape; 3,3 g.ndim; 2 g.dtype; array g.get(2,1); 7 g.set(1,1,4); 4 nj.ones([3,3]); array([[ 1, 1, 1], [ 1, 1, 1], [ 1, 1, 1]]) m.add(m); array([[ 2, 2, 2], [ 2, 2, 2], [ 2, 2, 2]]) n.subtract(m); array([[ 1, 1, 1], [ 1, 1, 1], [ 1, 1, 1]]) o.pow(m); array([[ 1, 1, 1], [ 1, 1, 1], [ 1, 1, 1]]) p.flatten(); array([ 1, 1, 1, ..., 1, 1, 1]) q.T array([ 1, 1, 1, ..., 1, 1, 1]) nj.identity(3); array([[ 1, 0, 0], [ 0, 1, 0], [ 0, 0, 1]]) nj.softmax(s); array([[ 0.19204, 0.07065, 0.07065], [ 0.07065, 0.19204, 0.07065], [ 0.07065, 0.07065, 0.19204]]) nj.sigmoid(s); array([[ 0.73106, 0.5, 0.5], [ 0.5, 0.73106, 0.5], [ 0.5, 0.5, 0.73106]]) nj.exp(s); array([[ 2.71828, 1, 1], [ 1, 2.71828, 1], [ 1, 1, 2.71828]]) nj.arange(18).reshape(6,3); array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11], [ 12, 13, 14], [ 15, 16, 17]]) nj.dot(w, s.add(6)); array([[ 18, 19, 20], [ 75, 76, 77], [ 132, 133, 134], [ 189, 190, 191], [ 246, 247, 248], [ 303, 304, 305]])
一応NumjsとNumpyの異なる部分を矢印で示しました。
I used arrows to show the differences between Numjs and Numpy.
これといった違いはあまり無いです。 ただ、NumjsはSigmoidとSoftmax関数が付いているのが嬉しいですね。
There is not much difference. But I'm glad that Numjs comes with Sigmoid and Softmax function.
キャンバスにテキスト表示させるとこんな具合です。
It looks like this when we display text on the canvas.