diff --git a/.gitignore b/.gitignore index 03a95f60..7447087c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ -_site -.sass-cache -.jekyll-metadata -Gemfile.lock - -vendor -bin +__site/ +.DS_Store +franklin +franklin.pub +node_modules/ +Manifest.toml diff --git a/Project.toml b/Project.toml new file mode 100644 index 00000000..8f357c56 --- /dev/null +++ b/Project.toml @@ -0,0 +1,3 @@ +[deps] +Franklin = "713c75ef-9fc9-4b05-94a9-213340da978e" +NodeJS = "2bd173c7-0d6d-553b-b6af-13a54713934c" \ No newline at end of file diff --git a/assets/images/FluxGitHubPreview.png b/_assets/FluxGitHubPreview.png similarity index 100% rename from assets/images/FluxGitHubPreview.png rename to _assets/FluxGitHubPreview.png diff --git a/_assets/favicon_io/android-chrome-192x192.png b/_assets/favicon_io/android-chrome-192x192.png new file mode 100644 index 00000000..7aafc3b7 Binary files /dev/null and b/_assets/favicon_io/android-chrome-192x192.png differ diff --git a/_assets/favicon_io/android-chrome-512x512.png b/_assets/favicon_io/android-chrome-512x512.png new file mode 100644 index 00000000..349452ad Binary files /dev/null and b/_assets/favicon_io/android-chrome-512x512.png differ diff --git a/_assets/favicon_io/apple-touch-icon.png b/_assets/favicon_io/apple-touch-icon.png new file mode 100644 index 00000000..0600206d Binary files /dev/null and b/_assets/favicon_io/apple-touch-icon.png differ diff --git a/_assets/favicon_io/favicon-16x16.png b/_assets/favicon_io/favicon-16x16.png new file mode 100644 index 00000000..d1f35ba6 Binary files /dev/null and b/_assets/favicon_io/favicon-16x16.png differ diff --git a/_assets/favicon_io/favicon-32x32.png b/_assets/favicon_io/favicon-32x32.png new file mode 100644 index 00000000..f6c1630b Binary files /dev/null and b/_assets/favicon_io/favicon-32x32.png differ diff --git a/_assets/favicon_io/favicon.ico b/_assets/favicon_io/favicon.ico new file mode 100644 index 00000000..5fa3624d Binary files /dev/null and b/_assets/favicon_io/favicon.ico differ diff --git a/_assets/favicon_io/site.webmanifest b/_assets/favicon_io/site.webmanifest new file mode 100644 index 00000000..45dc8a20 --- /dev/null +++ b/_assets/favicon_io/site.webmanifest @@ -0,0 +1 @@ +{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file diff --git a/_assets/friends/FluxGitHubPreview.png b/_assets/friends/FluxGitHubPreview.png new file mode 100644 index 00000000..a0e643a9 Binary files /dev/null and b/_assets/friends/FluxGitHubPreview.png differ diff --git a/assets/images/alan-turing.jpg b/_assets/friends/alan-turing.jpg similarity index 100% rename from assets/images/alan-turing.jpg rename to _assets/friends/alan-turing.jpg diff --git a/assets/images/beacon_biosignals.jpg b/_assets/friends/beacon_biosignals.jpg similarity index 100% rename from assets/images/beacon_biosignals.jpg rename to _assets/friends/beacon_biosignals.jpg diff --git a/assets/images/cambridge.jpg b/_assets/friends/cambridge.jpg similarity index 100% rename from assets/images/cambridge.jpg rename to _assets/friends/cambridge.jpg diff --git a/assets/images/cmu-logo.png b/_assets/friends/cmu-logo.png similarity index 100% rename from assets/images/cmu-logo.png rename to _assets/friends/cmu-logo.png diff --git a/assets/images/edinburgh.png b/_assets/friends/edinburgh.png similarity index 100% rename from assets/images/edinburgh.png rename to _assets/friends/edinburgh.png diff --git a/assets/images/invenia-logo.png b/_assets/friends/invenia-logo.png similarity index 100% rename from assets/images/invenia-logo.png rename to _assets/friends/invenia-logo.png diff --git a/assets/images/juliac-logo.png b/_assets/friends/juliac-logo.png similarity index 100% rename from assets/images/juliac-logo.png rename to _assets/friends/juliac-logo.png diff --git a/assets/images/mit-logo.png b/_assets/friends/mit-logo.png similarity index 100% rename from assets/images/mit-logo.png rename to _assets/friends/mit-logo.png diff --git a/assets/images/rai-logo.png b/_assets/friends/rai-logo.png similarity index 100% rename from assets/images/rai-logo.png rename to _assets/friends/rai-logo.png diff --git a/assets/images/ucl-logo.png b/_assets/friends/ucl-logo.png similarity index 100% rename from assets/images/ucl-logo.png rename to _assets/friends/ucl-logo.png diff --git a/assets/images/uoft_logo.png b/_assets/friends/uoft_logo.png similarity index 100% rename from assets/images/uoft_logo.png rename to _assets/friends/uoft_logo.png diff --git a/assets/images/washington.jpg b/_assets/friends/washington.jpg similarity index 100% rename from assets/images/washington.jpg rename to _assets/friends/washington.jpg diff --git a/assets/2021-12-1-flux-numfocus/flux.png b/_assets/logo.png similarity index 100% rename from assets/2021-12-1-flux-numfocus/flux.png rename to _assets/logo.png diff --git a/script/default.css b/_css/script_default.css similarity index 100% rename from script/default.css rename to _css/script_default.css diff --git a/_css/site.css b/_css/site.css new file mode 100644 index 00000000..045a85dc --- /dev/null +++ b/_css/site.css @@ -0,0 +1,241 @@ +@import url("https://fonts.googleapis.com/css?family=Lato:400,400i"); + +.octicon { + display: inline-block; + vertical-align: text-bottom; + fill: currentColor +} + +body { + background: #143c3c; + font-family: Lato, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + line-height: 1.7 +} + +.logo { + font-style: italic +} + +.navbar .logo { + text-shadow: 2px 2px 5px rgba(0,0,0,0.1) +} + +.content { + background: #f0fafa +} + +.content .container { + background: white; + padding-top: 2em; + padding-bottom: 2em +} + +.content h1 { + font-size: 20pt; + padding-bottom: 0.2em; + border-bottom: 3px solid #ebf5eb; + text-align: center; + font-weight: bold; + margin-bottom: 1em +} + +.content h2 { + font-size: 18pt; + text-align: right; + margin-top: 2em +} + +.content h3 { + font-size: 12pt; + font-weight: bold +} + +.content blockquote { + font-style: italic; + border-left: 5px solid #ebf5eb; + padding-left: 1em; + margin-left: 1em +} + +.content .author { + text-align: right; + font-style: italic; + color: #009696 +} + +.content .attrib { + font-style: italic; + color: #003232 +} + +.lighter { + font-weight: 300; + letter-spacing: 1px +} + +p a:hover, p a:visited:hover { + color: #006464; + text-decoration: none +} + +p a, p a:visited { + color: #006464; + border-bottom: 2px solid #b4dcdc +} + +p a:hover { + border-bottom: 2px solid #0aa +} + +.feature a:hover, .feature a:visited:hover { + color: #006464; + text-decoration: none +} + +.feature a, .feature a:visited { + color: #006464; + border-bottom: 2px solid #b4dcdc +} + +.feature a:hover { + border-bottom: 2px solid #0aa +} + +.call { + padding-top: 2em; + padding-bottom: 2em; + text-align: center +} + +.call p:last-child { + margin: 0 +} + +.footer { + margin-top: 1.5rem; + margin-bottom: 3rem; + color: white +} + +pre { + margin: 0 +} + +pre code.hljs { + background: #f5ffff; + border: 2px solid #c8f0f0; + border-radius: 5px; + padding-left: 1em; + padding-right: 1em +} + +.navbar-collapse.collapse.in { + display: block !important +} + +.jumbotron { + margin-bottom: 0; + position: relative; + border-bottom: 1px thick; +} + +.jumbotron .container { + max-width: 750px; + box-shadow: 2px; + position: relative; + padding: none; + text-align: center; +} + +.jumbotron .buttons { + padding: 10px; +} + +@media (min-width: 576px){ + .jumbotron .container{ + padding: calc(1rem + 30px) 15px; + } +} + +.jumbotron hr { + border-top: 1px solid rgb(100, 150, 150); +} + +.jumbotron h1 { + font-family: lato; + font-style: italic; +} + +/* Description */ +.jumbotron { + padding: 0; +} + +.jumbotron p { + font-size: 1.1em; + margin-bottom: 1.5rem; +} + +.btn-primary { + color: rgb(30, 50, 50); + border-color: rgb(150, 200, 200); + background: none; + border-width: 2px; +} + +.jumbotron .btn-primary:hover { + color: rgb(0, 0, 0); + border-color: rgb(30, 80, 80); + background: none; + border-width: 2px; +} + +/*Features*/ +.features { + background:white; + padding-top:2em; +} + +.feature { + padding-top: 1em; + padding-bottom: 2rem; + letter-spacing: 0.1px; +} + +.feature-title { + text-align:center; + color:rgb(100,130,130) +} + +.paper { + padding: 1em; +} + +.feature h5, .paper h5 { + font-style: italic; + padding-bottom: 0.5em; +} + +.friends{ + background: #fff; +} +.friends *{ + text-align: center; + padding:10px; +} +.friends h3{ + margin-top: 50px; +} +.friends ul{ + display: flex; + -webkit-justify-content: space-evenly; + justify-content: space-evenly; + flex-wrap: wrap; + list-style: none; + align-items: center; +} +.friends ul li img{ + max-width: 200px; + max-height: 100px; + height: auto; +} diff --git a/_layout/foot.html b/_layout/foot.html new file mode 100644 index 00000000..4d252996 --- /dev/null +++ b/_layout/foot.html @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + diff --git a/_layout/head.html b/_layout/head.html new file mode 100644 index 00000000..a2fa2c9c --- /dev/null +++ b/_layout/head.html @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Flux – Elegant ML + + + + {{insert navbar.html}} + + diff --git a/_layout/navbar.html b/_layout/navbar.html new file mode 100644 index 00000000..f32470d9 --- /dev/null +++ b/_layout/navbar.html @@ -0,0 +1,44 @@ + + diff --git a/_layout/page_foot.html b/_layout/page_foot.html new file mode 100644 index 00000000..433fb251 --- /dev/null +++ b/_layout/page_foot.html @@ -0,0 +1,5 @@ + diff --git a/_layout/tag.html b/_layout/tag.html new file mode 100644 index 00000000..979b60c3 --- /dev/null +++ b/_layout/tag.html @@ -0,0 +1,18 @@ + + + + + + + + Tag: {{fill fd_tag}} + + + {{insert header.html}} +
+

Tag: {{fill fd_tag}}

+ {{taglist}} + {{insert page_foot.html}} +
+ + diff --git a/_layouts/blog.html b/_layouts/blog.html deleted file mode 100644 index c6a52642..00000000 --- a/_layouts/blog.html +++ /dev/null @@ -1,9 +0,0 @@ ---- -layout: page ---- - -

{{page.title}}

- -{{content}} - -

– {{page.author}}

diff --git a/_layouts/default.html b/_layouts/default.html deleted file mode 100644 index ce7db836..00000000 --- a/_layouts/default.html +++ /dev/null @@ -1,125 +0,0 @@ ---- ---- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Flux – {{page.title}} - - - - - - - {{content}} - - - - - - - - - - - - - - diff --git a/_layouts/page.html b/_layouts/page.html deleted file mode 100644 index 5c462601..00000000 --- a/_layouts/page.html +++ /dev/null @@ -1,40 +0,0 @@ ---- -layout: default ---- - - - -
-
- - {{content}} - -
-
- - - - \ No newline at end of file diff --git a/_layouts/tutorials.html b/_layouts/tutorials.html deleted file mode 100755 index c6a52642..00000000 --- a/_layouts/tutorials.html +++ /dev/null @@ -1,9 +0,0 @@ ---- -layout: page ---- - -

{{page.title}}

- -{{content}} - -

– {{page.author}}

diff --git a/script/highlight.pack.js b/_libs/highlight.pack.js similarity index 99% rename from script/highlight.pack.js rename to _libs/highlight.pack.js index dd12ef1d..f9d410c2 100644 --- a/script/highlight.pack.js +++ b/_libs/highlight.pack.js @@ -1,2 +1,2 @@ /*! highlight.js v9.12.0 | BSD3 License | git.io/hljslicense */ -!function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/&/g,"&").replace(//g,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return w(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||w(i))return i}function o(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset"}function u(e){s+=""}function c(e){("start"===e.event?o:u)(e.node)}for(var l=0,s="",f=[];e.length||r.length;){var g=i();if(s+=n(a.substring(l,g[0].offset)),l=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===l);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return s+n(a.substr(l))}function l(e){return e.v&&!e.cached_variants&&(e.cached_variants=e.v.map(function(n){return o(e,{v:null},n)})),e.cached_variants||e.eW&&[o(e)]||[e]}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var o={},u=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");o[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?u("keyword",a.k):x(a.k).forEach(function(e){u(e,a.k[e])}),a.k=o}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]),a.c=Array.prototype.concat.apply([],a.c.map(function(e){return l("self"===e?a:e)})),a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var c=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=c.length?t(c.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function l(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function p(e,n,t,r){var a=r?"":I.classPrefix,i='',i+n+o}function h(){var e,t,r,a;if(!E.k)return n(k);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(k);r;)a+=n(k.substring(t,r.index)),e=l(E,r),e?(B+=e[1],a+=p(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(k);return a+n(k.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!y[E.sL])return n(k);var t=e?f(E.sL,k,!0,x[E.sL]):g(k,E.sL.length?E.sL:void 0);return E.r>0&&(B+=t.r),e&&(x[E.sL]=t.top),p(t.language,t.value,!1,!0)}function b(){L+=null!=E.sL?d():h(),k=""}function v(e){L+=e.cN?p(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(k+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?k+=n:(t.eB&&(k+=n),b(),t.rB||t.eB||(k=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?k+=n:(a.rE||a.eE||(k+=n),b(),a.eE&&(k=n));do E.cN&&(L+=C),E.skip||(B+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"")+'"');return k+=n,n.length||1}var N=w(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var R,E=i||N,x={},L="";for(R=E;R!==N;R=R.parent)R.cN&&(L=p(R.cN,"",!0)+L);var k="",B=0;try{for(var M,j,O=0;;){if(E.t.lastIndex=O,M=E.t.exec(t),!M)break;j=m(t.substring(O,M.index),M[0]),O=M.index+j}for(m(t.substr(O)),R=E;R.parent;R=R.parent)R.cN&&(L+=C);return{r:B,value:L,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function g(e,t){t=t||I.languages||x(y);var r={r:0,value:n(e)},a=r;return t.filter(w).forEach(function(n){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function p(e){return I.tabReplace||I.useBR?e.replace(M,function(e,n){return I.useBR&&"\n"===e?"
":I.tabReplace?n.replace(/\t/g,I.tabReplace):""}):e}function h(e,n,t){var r=n?L[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function d(e){var n,t,r,o,l,s=i(e);a(s)||(I.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):n=e,l=n.textContent,r=s?f(s,l,!0):g(l),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),l)),r.value=p(r.value),e.innerHTML=r.value,e.className=h(e.className,s,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function b(e){I=o(I,e)}function v(){if(!v.called){v.called=!0;var e=document.querySelectorAll("pre code");E.forEach.call(e,d)}}function m(){addEventListener("DOMContentLoaded",v,!1),addEventListener("load",v,!1)}function N(n,t){var r=y[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function R(){return x(y)}function w(e){return e=(e||"").toLowerCase(),y[e]||y[L[e]]}var E=[],x=Object.keys,y={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="
",I={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};return e.highlight=f,e.highlightAuto=g,e.fixMarkup=p,e.highlightBlock=d,e.configure=b,e.initHighlighting=v,e.initHighlightingOnLoad=m,e.registerLanguage=N,e.listLanguages=R,e.getLanguage=w,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("julia",function(e){var r={keyword:"in isa where baremodule begin break catch ccall const continue do else elseif end export false finally for function global if import importall let local macro module quote return true try using while type immutable abstract bitstype typealias ",literal:"true false ARGS C_NULL DevNull ENDIAN_BOM ENV I Inf Inf16 Inf32 Inf64 InsertionSort JULIA_HOME LOAD_PATH MergeSort NaN NaN16 NaN32 NaN64 PROGRAM_FILE QuickSort RoundDown RoundFromZero RoundNearest RoundNearestTiesAway RoundNearestTiesUp RoundToZero RoundUp STDERR STDIN STDOUT VERSION catalan e|0 eu|0 eulergamma golden im nothing pi γ π φ ",built_in:"ANY AbstractArray AbstractChannel AbstractFloat AbstractMatrix AbstractRNG AbstractSerializer AbstractSet AbstractSparseArray AbstractSparseMatrix AbstractSparseVector AbstractString AbstractUnitRange AbstractVecOrMat AbstractVector Any ArgumentError Array AssertionError Associative Base64DecodePipe Base64EncodePipe Bidiagonal BigFloat BigInt BitArray BitMatrix BitVector Bool BoundsError BufferStream CachingPool CapturedException CartesianIndex CartesianRange Cchar Cdouble Cfloat Channel Char Cint Cintmax_t Clong Clonglong ClusterManager Cmd CodeInfo Colon Complex Complex128 Complex32 Complex64 CompositeException Condition ConjArray ConjMatrix ConjVector Cptrdiff_t Cshort Csize_t Cssize_t Cstring Cuchar Cuint Cuintmax_t Culong Culonglong Cushort Cwchar_t Cwstring DataType Date DateFormat DateTime DenseArray DenseMatrix DenseVecOrMat DenseVector Diagonal Dict DimensionMismatch Dims DirectIndexString Display DivideError DomainError EOFError EachLine Enum Enumerate ErrorException Exception ExponentialBackOff Expr Factorization FileMonitor Float16 Float32 Float64 Function Future GlobalRef GotoNode HTML Hermitian IO IOBuffer IOContext IOStream IPAddr IPv4 IPv6 IndexCartesian IndexLinear IndexStyle InexactError InitError Int Int128 Int16 Int32 Int64 Int8 IntSet Integer InterruptException InvalidStateException Irrational KeyError LabelNode LinSpace LineNumberNode LoadError LowerTriangular MIME Matrix MersenneTwister Method MethodError MethodTable Module NTuple NewvarNode NullException Nullable Number ObjectIdDict OrdinalRange OutOfMemoryError OverflowError Pair ParseError PartialQuickSort PermutedDimsArray Pipe PollingFileWatcher ProcessExitedException Ptr QuoteNode RandomDevice Range RangeIndex Rational RawFD ReadOnlyMemoryError Real ReentrantLock Ref Regex RegexMatch RemoteChannel RemoteException RevString RoundingMode RowVector SSAValue SegmentationFault SerializationState Set SharedArray SharedMatrix SharedVector Signed SimpleVector Slot SlotNumber SparseMatrixCSC SparseVector StackFrame StackOverflowError StackTrace StepRange StepRangeLen StridedArray StridedMatrix StridedVecOrMat StridedVector String SubArray SubString SymTridiagonal Symbol Symmetric SystemError TCPSocket Task Text TextDisplay Timer Tridiagonal Tuple Type TypeError TypeMapEntry TypeMapLevel TypeName TypeVar TypedSlot UDPSocket UInt UInt128 UInt16 UInt32 UInt64 UInt8 UndefRefError UndefVarError UnicodeError UniformScaling Union UnionAll UnitRange Unsigned UpperTriangular Val Vararg VecElement VecOrMat Vector VersionNumber Void WeakKeyDict WeakRef WorkerConfig WorkerPool "},t="[A-Za-z_\\u00A1-\\uFFFF][A-Za-z_0-9\\u00A1-\\uFFFF]*",a={l:t,k:r,i:/<\//},n={cN:"number",b:/(\b0x[\d_]*(\.[\d_]*)?|0x\.\d[\d_]*)p[-+]?\d+|\b0[box][a-fA-F0-9][a-fA-F0-9_]*|(\b\d[\d_]*(\.[\d_]*)?|\.\d[\d_]*)([eEfF][-+]?\d+)?/,r:0},o={cN:"string",b:/'(.|\\[xXuU][a-zA-Z0-9]+)'/},i={cN:"subst",b:/\$\(/,e:/\)/,k:r},l={cN:"variable",b:"\\$"+t},c={cN:"string",c:[e.BE,i,l],v:[{b:/\w*"""/,e:/"""\w*/,r:10},{b:/\w*"/,e:/"\w*/}]},s={cN:"string",c:[e.BE,i,l],b:"`",e:"`"},d={cN:"meta",b:"@"+t},u={cN:"comment",v:[{b:"#=",e:"=#",r:10},{b:"#",e:"$"}]};return a.c=[n,o,c,s,d,u,e.HCM,{cN:"keyword",b:"\\b(((abstract|primitive)\\s+)type|(mutable\\s+)?struct)\\b"},{b:/<:/}],i.c=a.c,a}); \ No newline at end of file +!function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/&/g,"&").replace(//g,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return w(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||w(i))return i}function o(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset"}function u(e){s+=""}function c(e){("start"===e.event?o:u)(e.node)}for(var l=0,s="",f=[];e.length||r.length;){var g=i();if(s+=n(a.substring(l,g[0].offset)),l=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===l);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return s+n(a.substr(l))}function l(e){return e.v&&!e.cached_variants&&(e.cached_variants=e.v.map(function(n){return o(e,{v:null},n)})),e.cached_variants||e.eW&&[o(e)]||[e]}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var o={},u=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");o[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?u("keyword",a.k):x(a.k).forEach(function(e){u(e,a.k[e])}),a.k=o}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]),a.c=Array.prototype.concat.apply([],a.c.map(function(e){return l("self"===e?a:e)})),a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var c=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=c.length?t(c.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function l(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function p(e,n,t,r){var a=r?"":I.classPrefix,i='',i+n+o}function h(){var e,t,r,a;if(!E.k)return n(k);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(k);r;)a+=n(k.substring(t,r.index)),e=l(E,r),e?(B+=e[1],a+=p(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(k);return a+n(k.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!y[E.sL])return n(k);var t=e?f(E.sL,k,!0,x[E.sL]):g(k,E.sL.length?E.sL:void 0);return E.r>0&&(B+=t.r),e&&(x[E.sL]=t.top),p(t.language,t.value,!1,!0)}function b(){L+=null!=E.sL?d():h(),k=""}function v(e){L+=e.cN?p(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(k+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?k+=n:(t.eB&&(k+=n),b(),t.rB||t.eB||(k=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?k+=n:(a.rE||a.eE||(k+=n),b(),a.eE&&(k=n));do E.cN&&(L+=C),E.skip||(B+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"")+'"');return k+=n,n.length||1}var N=w(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var R,E=i||N,x={},L="";for(R=E;R!==N;R=R.parent)R.cN&&(L=p(R.cN,"",!0)+L);var k="",B=0;try{for(var M,j,O=0;;){if(E.t.lastIndex=O,M=E.t.exec(t),!M)break;j=m(t.substring(O,M.index),M[0]),O=M.index+j}for(m(t.substr(O)),R=E;R.parent;R=R.parent)R.cN&&(L+=C);return{r:B,value:L,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function g(e,t){t=t||I.languages||x(y);var r={r:0,value:n(e)},a=r;return t.filter(w).forEach(function(n){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function p(e){return I.tabReplace||I.useBR?e.replace(M,function(e,n){return I.useBR&&"\n"===e?"
":I.tabReplace?n.replace(/\t/g,I.tabReplace):""}):e}function h(e,n,t){var r=n?L[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function d(e){var n,t,r,o,l,s=i(e);a(s)||(I.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):n=e,l=n.textContent,r=s?f(s,l,!0):g(l),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),l)),r.value=p(r.value),e.innerHTML=r.value,e.className=h(e.className,s,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function b(e){I=o(I,e)}function v(){if(!v.called){v.called=!0;var e=document.querySelectorAll("pre code");E.forEach.call(e,d)}}function m(){addEventListener("DOMContentLoaded",v,!1),addEventListener("load",v,!1)}function N(n,t){var r=y[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function R(){return x(y)}function w(e){return e=(e||"").toLowerCase(),y[e]||y[L[e]]}var E=[],x=Object.keys,y={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="
",I={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};return e.highlight=f,e.highlightAuto=g,e.fixMarkup=p,e.highlightBlock=d,e.configure=b,e.initHighlighting=v,e.initHighlightingOnLoad=m,e.registerLanguage=N,e.listLanguages=R,e.getLanguage=w,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("julia",function(e){var r={keyword:"in isa where baremodule begin break catch ccall const continue do else elseif end export false finally for function global if import importall let local macro module quote return true try using while type immutable abstract bitstype typealias ",literal:"true false ARGS C_NULL DevNull ENDIAN_BOM ENV I Inf Inf16 Inf32 Inf64 InsertionSort JULIA_HOME LOAD_PATH MergeSort NaN NaN16 NaN32 NaN64 PROGRAM_FILE QuickSort RoundDown RoundFromZero RoundNearest RoundNearestTiesAway RoundNearestTiesUp RoundToZero RoundUp STDERR STDIN STDOUT VERSION catalan e|0 eu|0 eulergamma golden im nothing pi γ π φ ",built_in:"ANY AbstractArray AbstractChannel AbstractFloat AbstractMatrix AbstractRNG AbstractSerializer AbstractSet AbstractSparseArray AbstractSparseMatrix AbstractSparseVector AbstractString AbstractUnitRange AbstractVecOrMat AbstractVector Any ArgumentError Array AssertionError Associative Base64DecodePipe Base64EncodePipe Bidiagonal BigFloat BigInt BitArray BitMatrix BitVector Bool BoundsError BufferStream CachingPool CapturedException CartesianIndex CartesianRange Cchar Cdouble Cfloat Channel Char Cint Cintmax_t Clong Clonglong ClusterManager Cmd CodeInfo Colon Complex Complex128 Complex32 Complex64 CompositeException Condition ConjArray ConjMatrix ConjVector Cptrdiff_t Cshort Csize_t Cssize_t Cstring Cuchar Cuint Cuintmax_t Culong Culonglong Cushort Cwchar_t Cwstring DataType Date DateFormat DateTime DenseArray DenseMatrix DenseVecOrMat DenseVector Diagonal Dict DimensionMismatch Dims DirectIndexString Display DivideError DomainError EOFError EachLine Enum Enumerate ErrorException Exception ExponentialBackOff Expr Factorization FileMonitor Float16 Float32 Float64 Function Future GlobalRef GotoNode HTML Hermitian IO IOBuffer IOContext IOStream IPAddr IPv4 IPv6 IndexCartesian IndexLinear IndexStyle InexactError InitError Int Int128 Int16 Int32 Int64 Int8 IntSet Integer InterruptException InvalidStateException Irrational KeyError LabelNode LinSpace LineNumberNode LoadError LowerTriangular MIME Matrix MersenneTwister Method MethodError MethodTable Module NTuple NewvarNode NullException Nullable Number ObjectIdDict OrdinalRange OutOfMemoryError OverflowError Pair ParseError PartialQuickSort PermutedDimsArray Pipe PollingFileWatcher ProcessExitedException Ptr QuoteNode RandomDevice Range RangeIndex Rational RawFD ReadOnlyMemoryError Real ReentrantLock Ref Regex RegexMatch RemoteChannel RemoteException RevString RoundingMode RowVector SSAValue SegmentationFault SerializationState Set SharedArray SharedMatrix SharedVector Signed SimpleVector Slot SlotNumber SparseMatrixCSC SparseVector StackFrame StackOverflowError StackTrace StepRange StepRangeLen StridedArray StridedMatrix StridedVecOrMat StridedVector String SubArray SubString SymTridiagonal Symbol Symmetric SystemError TCPSocket Task Text TextDisplay Timer Tridiagonal Tuple Type TypeError TypeMapEntry TypeMapLevel TypeName TypeVar TypedSlot UDPSocket UInt UInt128 UInt16 UInt32 UInt64 UInt8 UndefRefError UndefVarError UnicodeError UniformScaling Union UnionAll UnitRange Unsigned UpperTriangular Val Vararg VecElement VecOrMat Vector VersionNumber Void WeakKeyDict WeakRef WorkerConfig WorkerPool "},t="[A-Za-z_\\u00A1-\\uFFFF][A-Za-z_0-9\\u00A1-\\uFFFF]*",a={l:t,k:r,i:/<\//},n={cN:"number",b:/(\b0x[\d_]*(\.[\d_]*)?|0x\.\d[\d_]*)p[-+]?\d+|\b0[box][a-fA-F0-9][a-fA-F0-9_]*|(\b\d[\d_]*(\.[\d_]*)?|\.\d[\d_]*)([eEfF][-+]?\d+)?/,r:0},o={cN:"string",b:/'(.|\\[xXuU][a-zA-Z0-9]+)'/},i={cN:"subst",b:/\$\(/,e:/\)/,k:r},l={cN:"variable",b:"\\$"+t},c={cN:"string",c:[e.BE,i,l],v:[{b:/\w*"""/,e:/"""\w*/,r:10},{b:/\w*"/,e:/"\w*/}]},s={cN:"string",c:[e.BE,i,l],b:"`",e:"`"},d={cN:"meta",b:"@"+t},u={cN:"comment",v:[{b:"#=",e:"=#",r:10},{b:"#",e:"$"}]};return a.c=[n,o,c,s,d,u,e.HCM,{cN:"keyword",b:"\\b(((abstract|primitive)\\s+)type|(mutable\\s+)?struct)\\b"},{b:/<:/}],i.c=a.c,a}); diff --git a/_rss/head.xml b/_rss/head.xml new file mode 100644 index 00000000..4c9f62b1 --- /dev/null +++ b/_rss/head.xml @@ -0,0 +1,37 @@ + + + + + + + <![CDATA[ {{fd2rss website_title}} ]]> + + {{website_url}} + + + + + diff --git a/_rss/item.xml b/_rss/item.xml new file mode 100644 index 00000000..07f65064 --- /dev/null +++ b/_rss/item.xml @@ -0,0 +1,60 @@ + + + + <![CDATA[ {{fd2rss rss_title}} ]]> + + {{fd_full_url}} + {{fd_full_url}} + + + + + + {{if rss_full_content}} + + + + {{end}} + + + {{RFC822 rss_pubdate}} + + + {{isnotempty rss_author}} + {{rss_author}} + {{end}} + {{isnotempty author}} + + {{author}} + + {{end}} + + {{isnotempty rss_category}} + {{rss_category}} + {{end}} + + {{isnotempty rss_comments}} + {{rss_comments}} + {{end}} + + {{isnotempty rss_enclosure}} + {{rss_enclosure}} + {{end}} + diff --git a/assets/2019-03-05-dp-vs-rl/bptt.png b/assets/2019-03-05-dp-vs-rl/bptt.png deleted file mode 100644 index d11f1b26..00000000 Binary files a/assets/2019-03-05-dp-vs-rl/bptt.png and /dev/null differ diff --git a/assets/2019-03-05-dp-vs-rl/cartpole-flow.png b/assets/2019-03-05-dp-vs-rl/cartpole-flow.png deleted file mode 100644 index dcda8ce0..00000000 Binary files a/assets/2019-03-05-dp-vs-rl/cartpole-flow.png and /dev/null differ diff --git a/assets/2019-03-05-dp-vs-rl/cartpole.gif b/assets/2019-03-05-dp-vs-rl/cartpole.gif deleted file mode 100644 index 90833bf1..00000000 Binary files a/assets/2019-03-05-dp-vs-rl/cartpole.gif and /dev/null differ diff --git a/assets/2019-03-05-dp-vs-rl/pendulum-dp.gif b/assets/2019-03-05-dp-vs-rl/pendulum-dp.gif deleted file mode 100644 index 1c22143f..00000000 Binary files a/assets/2019-03-05-dp-vs-rl/pendulum-dp.gif and /dev/null differ diff --git a/assets/2019-03-05-dp-vs-rl/pendulum-training.gif b/assets/2019-03-05-dp-vs-rl/pendulum-training.gif deleted file mode 100644 index dccbf1a8..00000000 Binary files a/assets/2019-03-05-dp-vs-rl/pendulum-training.gif and /dev/null differ diff --git a/assets/2019-03-05-dp-vs-rl/trebuchet-basic.gif b/assets/2019-03-05-dp-vs-rl/trebuchet-basic.gif deleted file mode 100644 index 21476ec2..00000000 Binary files a/assets/2019-03-05-dp-vs-rl/trebuchet-basic.gif and /dev/null differ diff --git a/assets/2019-03-05-dp-vs-rl/trebuchet-flow.png b/assets/2019-03-05-dp-vs-rl/trebuchet-flow.png deleted file mode 100644 index e577bc91..00000000 Binary files a/assets/2019-03-05-dp-vs-rl/trebuchet-flow.png and /dev/null differ diff --git a/assets/2019-03-05-dp-vs-rl/trebuchet-hit.gif b/assets/2019-03-05-dp-vs-rl/trebuchet-hit.gif deleted file mode 100644 index cf453f1f..00000000 Binary files a/assets/2019-03-05-dp-vs-rl/trebuchet-hit.gif and /dev/null differ diff --git a/assets/2019-03-05-dp-vs-rl/trebuchet-miss.gif b/assets/2019-03-05-dp-vs-rl/trebuchet-miss.gif deleted file mode 100644 index b6c97ab9..00000000 Binary files a/assets/2019-03-05-dp-vs-rl/trebuchet-miss.gif and /dev/null differ diff --git a/assets/2019-03-05-dp-vs-rl/trebuchet-wind.gif b/assets/2019-03-05-dp-vs-rl/trebuchet-wind.gif deleted file mode 100644 index fb838e15..00000000 Binary files a/assets/2019-03-05-dp-vs-rl/trebuchet-wind.gif and /dev/null differ diff --git a/assets/2020-06-29-acclerating-flux-torch/combined_benchmarks_2.png b/assets/2020-06-29-acclerating-flux-torch/combined_benchmarks_2.png deleted file mode 100644 index 17d0a0b3..00000000 Binary files a/assets/2020-06-29-acclerating-flux-torch/combined_benchmarks_2.png and /dev/null differ diff --git a/assets/2020-06-29-acclerating-flux-torch/resnet101.png b/assets/2020-06-29-acclerating-flux-torch/resnet101.png deleted file mode 100644 index 2a27e6ea..00000000 Binary files a/assets/2020-06-29-acclerating-flux-torch/resnet101.png and /dev/null differ diff --git a/assets/2020-12-20-Flux3D/bm_metrics.png b/assets/2020-12-20-Flux3D/bm_metrics.png deleted file mode 100644 index 1a878528..00000000 Binary files a/assets/2020-12-20-Flux3D/bm_metrics.png and /dev/null differ diff --git a/assets/2020-12-20-Flux3D/bm_pcloud.png b/assets/2020-12-20-Flux3D/bm_pcloud.png deleted file mode 100644 index 6d4d0cec..00000000 Binary files a/assets/2020-12-20-Flux3D/bm_pcloud.png and /dev/null differ diff --git a/assets/2020-12-20-Flux3D/bm_trimesh.png b/assets/2020-12-20-Flux3D/bm_trimesh.png deleted file mode 100644 index 5f2ffe21..00000000 Binary files a/assets/2020-12-20-Flux3D/bm_trimesh.png and /dev/null differ diff --git a/assets/2020-12-20-Flux3D/fitmesh_anim.gif b/assets/2020-12-20-Flux3D/fitmesh_anim.gif deleted file mode 100644 index ba01ece5..00000000 Binary files a/assets/2020-12-20-Flux3D/fitmesh_anim.gif and /dev/null differ diff --git a/assets/2020-12-20-Flux3D/visualize.png b/assets/2020-12-20-Flux3D/visualize.png deleted file mode 100644 index 1c1ae731..00000000 Binary files a/assets/2020-12-20-Flux3D/visualize.png and /dev/null differ diff --git a/assets/2020-12-20-Flux3D/visualize_anim.gif b/assets/2020-12-20-Flux3D/visualize_anim.gif deleted file mode 100644 index b86a0525..00000000 Binary files a/assets/2020-12-20-Flux3D/visualize_anim.gif and /dev/null differ diff --git a/assets/2021-10-8-dcgan-mnist/cat_gan.png b/assets/2021-10-8-dcgan-mnist/cat_gan.png deleted file mode 100644 index a3b59c5a..00000000 Binary files a/assets/2021-10-8-dcgan-mnist/cat_gan.png and /dev/null differ diff --git a/assets/2021-10-8-dcgan-mnist/output.gif b/assets/2021-10-8-dcgan-mnist/output.gif deleted file mode 100644 index 33435edb..00000000 Binary files a/assets/2021-10-8-dcgan-mnist/output.gif and /dev/null differ diff --git a/assets/2021-12-1-flux-numfocus/flux_numfocus.png b/assets/2021-12-1-flux-numfocus/flux_numfocus.png deleted file mode 100644 index e43b32a7..00000000 Binary files a/assets/2021-12-1-flux-numfocus/flux_numfocus.png and /dev/null differ diff --git a/assets/charges/maingif.gif b/assets/charges/maingif.gif deleted file mode 100644 index 56d830b3..00000000 Binary files a/assets/charges/maingif.gif and /dev/null differ diff --git a/assets/charges/plot1.png b/assets/charges/plot1.png deleted file mode 100644 index d3ab55e4..00000000 Binary files a/assets/charges/plot1.png and /dev/null differ diff --git a/assets/charges/plot2.png b/assets/charges/plot2.png deleted file mode 100644 index e1b2b6e2..00000000 Binary files a/assets/charges/plot2.png and /dev/null differ diff --git a/assets/charges/plot3.png b/assets/charges/plot3.png deleted file mode 100644 index c2557948..00000000 Binary files a/assets/charges/plot3.png and /dev/null differ diff --git a/assets/css/style.css b/assets/css/style.css deleted file mode 100644 index cad41b69..00000000 --- a/assets/css/style.css +++ /dev/null @@ -1,12 +0,0 @@ -#cppn{ - position:absolute; - top:0; - bottom:0; - height: 100%; - width: 100vw; -} - -iframe { - display: block; - border-style:none; -} diff --git a/assets/images/amd-logo.png b/assets/images/amd-logo.png deleted file mode 100644 index cb80abf7..00000000 Binary files a/assets/images/amd-logo.png and /dev/null differ diff --git a/assets/js/script.js b/assets/js/script.js deleted file mode 100644 index 6c1f1066..00000000 --- a/assets/js/script.js +++ /dev/null @@ -1,144 +0,0 @@ -(function(){ -function Screen(ele, w, h){ - this.frames = []; - this.isDrawing = false; - - this.index = 0; - var l = w*h; - var canvas = ele; - - this.addFrame = function(data){ - this.frames.push(data); - } - - this.next = function(){ - if(this.frames.length ==0) return; - - this.index = Math.floor((this.index + 1)%(this.frames.length)); - if(!this.isDrawing) - requestAnimationFrame(this.draw_); - } - - - this.draw_ = function(){ - if(this.isDrawing || this.frames.length == 0)return; - - this.isDrawing = true; - var data = this.frames[this.index]; - - var img = []; - for(var i = 0; i< w*h; i++){ - c = data[i]*255; - img.push(c, c, c, 255); - } - - var uint8 = new Uint8ClampedArray(img); - var imgData = new ImageData(uint8,w,h); - - - canvas.getContext("2d", {alpha: false}).putImageData(imgData, 0, 0) - this.isDrawing = false; - } - - this.draw_ = this.draw_.bind(this); - this.frameCount = ()=> this.frames.length; -} - - -function CPPN(canvas, {z_dim=2, w=100, h=100, rate=1, max=1, frames = 1000, func=Math.sin}={}){ - canvas.width = w; - canvas.height = h; - - // scaling canvas since CSS scaling is faster - canvas.style.width = w + "px"; - canvas.style.height = h + "px"; - var scaleX = window.innerWidth/ canvas.width; - var scaleY = canvas.parentElement.offsetHeight / canvas.height; - canvas.style.transform = "scaleX("+ scaleX +") scaleY(" + scaleY +")"; - canvas.style.transformOrigin = "0 0"; - - - var screen = new Screen(canvas, w, h); - var model_ = null; - - var counter = new Array(z_dim); - var speed = 2*Math.PI/frames; - var factor = Math.min(w, h); - var coords = getCoords(); - var zArr = new Array(frames); - - tf.randomUniform([z_dim]).data().then((counter)=>{ - for(var i = 0; i< frames; i++){ - var z_ = new Array(z_dim); - for(var j = 0; j< z_dim; j++){ - var n = counter[j] + speed; - z_[j] = max*func(rate*n); - counter[j] = n; - } - zArr[i] = z_; - } - }) - - function getCoords(){ - var x, y, r, collection = []; - for(var i=0; i< w; i++){ - x = (i/factor) - 0.5 - for(var j=0; j< h; j++){ - y = (j/factor) - 0.5 - r = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); - collection.push([x, y, r]); - } - } - return collection; - } - - var next = z => requestAnimationFrame( call( draw, z)); - - var draw = function(){ - // console.log("draw ") - if(screen.frameCount() >= frames){ - screen.next(); - return next(); - } - var index = screen.frameCount(); - - var l = coords.length - var collection = new Array(l); - - - var z = zArr[index]; - for(var j = 0; j< l; j++){ - collection[j] = coords[j].concat(z); - } - - var input = tf.tensor(collection, [l, 3 + z_dim]); - var output = model_(input); - tf.dispose(input); - - output.data().then(r=>{ - screen.addFrame(r); - screen.next(); - tf.dispose(output); - }) - - next(); - } - - this.start = function(model){ - model_ = e => tf.tidy(() => model(e)); - - next(); - } -} - -var canvas = document.querySelector("#cppn"); -var cppn = new CPPN(canvas); - -function call(f){ - var f_ = f; - arguments[0] = this - return ()=> f_.call(...Array.from(arguments)); -} - -window.__init__ = ()=> cppn.start(model); -})(); diff --git a/blog/_posts/2017-08-24-generic-gpu.md b/blog/_posts/2017-08-24-generic-gpu.md deleted file mode 100755 index 5df9cb56..00000000 --- a/blog/_posts/2017-08-24-generic-gpu.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Generic GPU Kernels -external: http://mikeinnes.github.io/2017/08/24/cudanative.html ---- diff --git a/blog/_posts/2017-12-06-ml-pl.md b/blog/_posts/2017-12-06-ml-pl.md deleted file mode 100755 index f55cca1d..00000000 --- a/blog/_posts/2017-12-06-ml-pl.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: On Machine Learning & Programming Languages -external: https://julialang.org/blog/2017/12/ml-pl/ ---- diff --git a/blog/_posts/2018-12-03-ml-language-compiler.md b/blog/_posts/2018-12-03-ml-language-compiler.md deleted file mode 100755 index 39b62ba1..00000000 --- a/blog/_posts/2018-12-03-ml-language-compiler.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Building a Language and Compiler for Machine Learning -external: https://julialang.org/blog/2018/12/ml-language-compiler/ ---- diff --git a/blog/_posts/2019-02-07-what-is-differentiable-programming.md b/blog/_posts/2019-02-07-what-is-differentiable-programming.md deleted file mode 100755 index f2845be5..00000000 --- a/blog/_posts/2019-02-07-what-is-differentiable-programming.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: What Is Differentiable Programming? -author: Mike Innes -layout: blog ---- - -> With four parameters I can fit an elephant, and with five I can make him wiggle his trunk.
– John Von Neumann - -The idea of "differentiable programming" is coming up a lot in the machine learning world. To many, it's not clear if this term reflects a real shift in how researchers think about machine learning, or is just (another) rebranding of "deep learning". This post clarifies what new things differentiable programming (or ∂P) brings to the machine learning table. - -Most importantly, differentiable programming is actually a shift _opposite_ from the direction taken by deep learning; from increasingly heavily parameterised models to simpler ones that take more advantage of problem structure. - - -## Brute Force with Benefits - -Differentiability is the core idea that makes deep learning so successful. Where a brute force search over even a few hundred model parameters would be far too expensive, gradients mean that we can take a pseudo-random walk around interesting parts of parameter space and find a good set. Doing the next-dumbest thing to brute force gives up surprisingly little generality; it's far from obvious that we can come up with a differentiable objective when, say, working with sequences in language translation, but it turns out to be straightforward with a little ingenuity. - -What about biological neurons and [[y = σ(W \times x + b)]]? There's nothing particularly special about this formula; it's just a simple and flexible example of a highly-parameterised non-linear function. In fact, it's probably the worst such function in most cases. A single neural net layer can, in principle, classify cat pictures, but only by the relatively uninteresting trick of acting as a lookup table. It's _guaranteed_ to work! – but the small print warns that you may need more parameters than there are atoms in the universe. To actually make it work you need to *encode problem structure in the model* – which is where it starts to look a lot more like traditional programming. - -For example, ConvNets have a huge advantage over the perceptron because they re-use [image kernels](https://en.wikipedia.org/wiki/Kernel_(image_processing)), which are long known to exploit translational invariance. An edge is an edge whether it shows up in the top left of an image or the centre, but where a perceptron would have to learn this case by case, a kernel can respond to any part of the image at once. It's hard to analyse convolutional nets in statistical terms, but much easier to see them as an auto-tuned version of what image processing experts used to write by hand. The image kernel is the first and simplest differentiable program. - - -## Encoding Structure, Redux - -ML toolkits increasingly support algorithmic differentiation (AD), allowing us to differentiate models with for loops, branches and recursion – or any program built on a set of differentiable mathematical primitives. This has led to more complex architectures: NLP models increasingly look more like classical grammar parsers with [stack-augmented](https://arxiv.org/abs/1603.06021) models, and one can even implement a [Turing machine analog](https://arxiv.org/pdf/1410.5401.pdf) or a [programming language interpreter](https://arxiv.org/abs/1605.06640) in a differentiable way. - -The final step taken by differentiable programming is to no longer see matrix multiplies, convolutions and RNNs as the fundamental building blocks of deep learning, but instead as mere special cases. We can apply the techniques of deep learning to *any* parameterised, differentiable function [[f(x)]]. [[f]] could be a matrix multiply, but functions as complex as physics simulators or ray tracers can be differentiated and optimised just as well. Even [quantum computation](https://arxiv.org/abs/1803.00745) can fit into this framework. - -Scientists have long used mechanistic models that sit between explicit programming and machine learning. Differential equations fit to data via sensitivities – as in physics, epidemiology or pharmacodynamics – are [equivalent in all but terminology to neural networks](https://julialang.org/blog/2019/01/fluxdiffeq). They are just far more constrained in what functions they can represent, making it easier to get a good result. - -The really powerful advance is this: pervasive differentiability means all these techniques snap together like lego bricks. Rather than always writing new programs for ML, we can incorporate existing ones, enabling [physics engines inside deep learning-based robotics models](https://arxiv.org/abs/1611.01652). Where current reinforcement learning algorithms need to build a detailed model of the external world from only a coarse-grained reward signal (which [sounds like a brute force problem](https://twitter.com/emilecontal/status/1089011610566385664) if anything does), we can instead just drop in detailed, precise knowledge of physical systems before training even begins. - -Even the most mature areas of deep learning are not left out; after the convolution kernel, a natural next step for image models is the [differentiable ray tracer](https://people.csail.mit.edu/tzumao/diffrt/). A 3D renderer contains a *lot* of structural knowledge about how scenes map to pixels, and this, too, can go in our melting pot. Say a model makes decisions in a simulated environment, rendered as pixels that the model uses as input. In principle we can now make the whole loop differentiable, letting us directly see the influence of the environment on the model's decisions and vice versa. This could greatly increase the power of realistic simulated environments for training models like self-driving cars. - -As in the sciences, hybrid models can both be more effective and resolve some of the tradeoffs between deep learning and explicit programming. For example, a drone's flight-path planner might have a neural network component that can only make provably small adjustments to a reliable explicit program, making its overall behaviour analysable while still adapting to empirical data. This is also good for interpretability: parameters of mechanistic models and simulations typically have clear physical interpretations, so if a model estimates parameters internally, it's making a clear statement about what it thinks is happening outside. - -If this is all so wonderful, why isn't everybody doing it already? Unfortunately, [limitations of current frameworks](https://julialang.org/blog/2017/12/ml&pl) make it difficult to build models of this complexity, and impossible to reuse the wealth of knowledge embedded in existing scientific code. The need to re-implement physics engines from scratch, in a constrained modelling language – usually with significant limitations – turns what should be a ten-line script into a multi-year research project. But advances in [language and compiler technology](https://julialang.org/blog/2018/12/ml-language-compiler), especially [automatic differentiation](https://arxiv.org/abs/1810.07951), are bringing us closer to the holy grail: "just differentiate my game engine, please." - - -## So, what is differentiable programming? - -Differentiable programming applies the techniques of deep learning to *complex existing programs*, taking advantage of the huge amount of knowledge embedded within them. Deep learning, statistics, programming and the sciences all have something to say about modelling the world around us, and it's time to put these fields [into a particle collider](https://arxiv.org/pdf/1702.00748.pdf). This will both improve current models and enable ML to be applied in areas where its current limitations – either interpretability or its computational and data requirements – make it infeasible alone. - -

Thanks to Hannah Lepper and James Bradbury for feedback on this post.

diff --git a/blog/_posts/2019-03-05-dp-vs-rl.md b/blog/_posts/2019-03-05-dp-vs-rl.md deleted file mode 100755 index de121d53..00000000 --- a/blog/_posts/2019-03-05-dp-vs-rl.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -title: Differentiable Control Problems -author: Mike Innes, Neethu Maria Joy, Tejan Karmali -layout: blog ---- - -We've discussed the idea of [differentiable programming](https://fluxml.ai/2019/02/07/what-is-differentiable-programming.html), where we incorporate existing programs into deep learning models. This article shows what ∂P can bring to some simple but classic control problems, where we would normally use black-box Reinforcement Learning (RL). ∂P-based models not only learn far more effective control strategies, but also train orders of magnitude faster. The [code](https://github.com/FluxML/model-zoo/tree/master/contrib/games/differentiable-programming/trebuchet) is all available to run for yourself – they will mostly train in a few seconds on any laptop. - - -## Follow the Gradient - -Differentiation is what makes deep learning tick; given a function [[y = f(x)]] we use the gradient [[\frac{dy}{dx}]] to figure out how a change in [[x]] will affect [[y]]. Despite the mathematical clothing, gradients are actually a very general and intuitive concept. Forget the formulas you had to stare at in school; let's do something more fun, like throwing stuff. - - - -When we throw things with a trebuchet, our [[x]] represents a setting (say, the size of the counterweight, or the angle of release), and [[y]] is the distance the projectile travels before landing. If you're trying to aim, the gradient tells you something very useful – whether a change in aim will increase or decrease the distance. To maximise distance, just follow the gradient. - -Alright, but how can we get this magical number? The trick is a process called [algorithmic differentiation](https://github.com/FluxML/Zygote.jl), which is able to differentiate not only simple formulas like you learned in school, but also _programs_ of any complexity – like our trebuchet simulator. The upshot is that we can take a [simple simulator](https://github.com/Roboneet/Trebuchet.jl), written in Julia and [DiffEq](https://github.com/JuliaDiffEq/DifferentialEquations.jl) with no deep learning in mind, and get gradients for it in a single function call. - -```julia -# what you did in school -gradient(x -> 3x^2 + 2x + 1, 5) # (32,) -# something a little more advanced -gradient((wind, angle, weight) -> Trebuchet.shoot(wind, angle, weight), - -2, 45, 200) # (4.02, -0.99, 0.051) -``` - -Now we have that, let's do something interesting with it. - - -## Throwing Stuff - -A simple way to use this is to aim the trebuchet at a target, using gradients to fine-tune the angle of release; this kind of thing is common under the name of _parameter estimation_, and we've [covered examples like it before](https://julialang.org/blog/2019/01/fluxdiffeq). We can make things more interesting by going meta: instead of aiming the trebuchet given a single target, we'll optimise a neural network that can aim it given _any_ target. Here's how it works: the neural net takes two inputs, the target distance in metres and the current wind speed. The network spits out trebuchet settings (the mass of the counterweight and the angle of release) that get fed into the simulator, which calculates the achieved distance. We then compare to our target, and _backpropagate through the entire chain_, end to end, to adjust the weights of the network. Our "dataset" is a randomly chosen set of targets and wind speeds. - - - -A nice property of this simple model is that training it is _fast_, because we've expressed exactly what we want from the model in a fully differentiable way. Initially it looks like this: - - - -After about five minutes of training (on a single core of my laptop's CPU), it looks like this: - - - -If you want to try pushing it, turn up the wind speed: - - - -It's only off by 16cm, or about 0.3%. - -What about just aiming the trebuchet directly? It is easy to do this by gradient descent given that we have gradients. However, this is a slow iterative process that takes around 100ms each time. In contrast, running the neural network takes 5μs (twenty thousand times faster) with only a small loss in accuracy. This "approximate function inversion via gradients" trick is a very general one that can not only be used with dynamical systems, but also lies behind the [fast style transfer](https://github.com/lengstrom/fast-style-transfer) algorithm. - -This is about the simplest possible control problem, which we use mainly for illustrative purposes. But we can apply the same techniques, in more advanced ways, to classic RL problems as well. - - -## Cart, meet Pole - -A more recognisable control problem is [CartPole](https://gym.openai.com/envs/CartPole-v0/), the "hello world" for reinforcement learning. The task is to learn to balance an upright pole by nudging its base left or right. Our setup is broadly similar to the trebuchet case: a [Julia implementation](https://github.com/tejank10/Gym.jl) means we can directly treat the reward produced by the environment as a loss. ∂P allows us to switch seamlessly from model-free to model-based RL. - - - -The astute reader may notice a snag. The action space for cartpole – nudge left or right – is discrete, and therefore not differentiable. We solve this by introducing a _differentiable discretisation_, defined [like so](https://github.com/FluxML/model-zoo/blob/cdda5cad3e87b216fa67069a5ca84a3016f2a604/games/differentiable-programming/cartpole/DiffRL.jl#L32): - -$[[\begin{aligned} - f(x) &= - \begin{cases} - 1 & x \ge 0 \\\ - -1 & x < 0 - \end{cases} \\\ - \frac{df}{dx} &= 1 -\end{aligned}]] - -In other words, we force the gradient to behave as if [[f]] were the identity function. Given how much the mathematical idea of differentiability already gets abused in ML, it's perhaps not surprising that we can just cheat here; for training all we need is a signal to inform our pseudo-random walk around parameter space, and the rest is details. - -The results speak for themselves. Where RL methods need to train for hundreds of episodes before solving the problem, the ∂P model only needs around 5 episodes to win conclusively. - - - - -## The Pendulum & Backprop through Time - -An important aim for RL is to handle _delayed reward_, when an action doesn't help us until several steps in the future. ∂P allows this too, and in a very familiar way: when the environment is differentiable, we can actually train the agent using backpropagation through time, just like a recurrent net! In this case the environmental state becomes the "hidden state" that changes between time steps. - - - -To demonstrate this technique we looked at the [pendulum](https://github.com/openai/gym/wiki/Pendulum-v0) environment, where the task is to swing a pendulum until it stands upright, keeping it balanced with minimal effort. This is hard for RL models; after around 20 episodes of training the problem is solved, but often the route to a solution is visibly sub-optimal. In contrast, BPTT can beat the [RL leaderboard](https://github.com/openai/gym/wiki/Leaderboard#pendulum-v0) in _a single episode of training_. It's instructive to actually watch this episode unfold; at the beginning of the recording the strategy is random, and the model improves over time. The pace of learning is almost alarming. - - - -Despite only experiencing a single episode, the model generalises well to handle any initial angle, and has something pretty close to the optimal strategy. When restarted the model looks more like this. - - - -This is just the beginning; we'll get the real wins applying DP to environments that are too hard for RL to work with at all, where rich simulations and models already exist (as in much of engineering and the sciences), and where interpretability is an important factor (as in medicine). - - -## The Map Is Not The Territory - -The limitation of these toy models is that they equate the simulated training environment with the test environment; of course, the real world is not differentiable. In a more realistic model the simulation gives us a coarse outline of behaviour that is refined with data. That data informs (say) the simulated effect of wind, in turn improving the quality of gradients the simulator passes to the controller. Models can even form part of a controller's forward pass, enabling it to refine its predictions without having to learn system dynamics from scratch. Exploring these new architectures will make for exciting future work. - - -## Coda - -The core idea is that _differentiable programming_, where we simply write an arbitrary numerical program and optimise it via gradients, is a powerful way to come up with better deep learning-like models and architectures – especially when we have a large library of differentiable code to hand. The toy models described are really only previews, but we hope they give an intuition for how these ideas can be applied in more realistic ways. - -Just as functional programming involves reasoning about and expressing algorithms using functional patterns, differentiable programming involves expressing algorithms using differentiable patterns. Many such design patterns have already been developed by the deep learning community, such as for handling control problems or sequence and tree structured data. As the field matures, many more will be invented, and the resulting programs are likely to make even the most advanced current deep learning architectures look crude by comparison. \ No newline at end of file diff --git a/blog/_posts/2019-05-31-JSoC-Cohort.md b/blog/_posts/2019-05-31-JSoC-Cohort.md deleted file mode 100755 index 378526ed..00000000 --- a/blog/_posts/2019-05-31-JSoC-Cohort.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: JSoC Cohort -author: Tejan Karmali, Shreyas Kowshik, Kartikey Gupta, Manjunath Bhat, Avik Pal, Raghvendra Gupta -layout: blog ---- - -We are excited to introduce our JSoC students accepted this year! Flux is hosting 6 JSoC students this time. They are a mix of students funded by [Google Summer of Code](https://summerofcode.withgoogle.com/) and Julia Season of Contributions, which is run by the community, thanks to the generous support from [NumFOCUS](https://numfocus.org/). Large parts of Flux ecosystem were created or improved by the students accepted through JSoC, many of whom have gone on to become long time contributors to FluxML. This year, we are proud to have students who will be working on a variety of sub-domains of Machine Learning, ranging from Differentiable Programming and Reinforcement Learning to GAN and Ray Tracing; to demonstrate a fresh approach to these paradigms using Julia. - - -## Shreyas Kowshik: _Addition Of Baseline Models To Flux.jl_ - -The current state of the art algorithms in terms of reinforcement learning and generative models are not yet available in [Flux](https://github.com/FluxML). This project aims to add the following models with explicit documentation in the form of [blog](https://shreyas-kowshik.github.io/) and code : - -* CycleGAN -* pix2pix -* Proximal Policy Optimization -* Trust Region Policy Optimization -* Neural Image Captioning -* Deep Recurrent Q Networks -* Super Resolution GAN - -## Kartikey Gupta: _Reinforcement Learning Environments for Julia_ - -This project aims at providing a collection of Reinforcement Learning environments, to facilitate research and experimentation in RL, in spirit of the OpenAI Gym. This includes the classic control environments, algorithmic environments, toy text examples, 2D game environments, Atari 2600 based game environments and a major part of the MuJoCo based robotic environments, along with their documentation and working examples. A differentiable NES (Nintendo Entertainment System) emulator will also added and available to this collection. Progress can be tracked [here](https://github.com/FluxML/Gym.jl). -[Link to Project Blog](https://nextjournal.com/kraftpunk97) - -## Manjunath Bhat: _Enriching Model Zoo with Deep Learning Models_ - -The aim of this project is to enrich Flux Model Zoo with unsupervised deep learning models, in particular variants of Generative Adversarial Networks. This project proposes to add the following models: -* Spatial Transformer Networks -* StarGAN for facial expression synthesis -* VAE-GAN -* Energy Based GAN -* Gated Recurrent Convolutional Neural Network - -[Link to Project Blog](https://medium.com/@manjunathbhat9920) - -## Raghvendra Gupta: _Sparsifying Neural Networks using Sensitivity Driven Regularization_ - -This project aims to quantify the output sensitivity to the parameters i.e. their relevance to network output and introduce a regularization term that gradually lowers the absolute value of sub-sensitive parameters. Thus a very large fraction of parameters approach zero and are eventually set to zero by simple thresholding. The models on which the sparsification experiment would be carried out are: -* VGG16 -* VGG19 -* MobileNet -* ResNet -* RL models (extended goal) - -The success of the experiment would be measured using Memory Footprint of the parameters, Compression Ratio and Runtime Performance of the models. -[Link to Project Blog](https://medium.com/@raghav090897) - -## Avik Pal: _Differentiable Ray Tracing_ - -Ray Tracing is a rendering technique which allows us to create photorealistic images given the scene information. However, at times given an image, we want to infer the state of the scene, i.e., the light sources, materials of the objects, the orientation of the camera, etc. Being able to incorporate the ability to differentiate through the ray tracer allows us to calculate gradients wrt arbitrary scene parameters and in turn, optimize them to obtain their exact values. Apart from this, the ray tracer can be used to train a self-driving car using BPTT (Back Propagation through Time). The package is available at [here](https://github.com/avik-pal/RayTracer.jl). - -## Tejan Karmali: _Differentiable Duckietown_ - -[Duckietown](https://www.duckietown.org/) is an environment for autonomous vehicles research. It is a miniature town through which a car (or bot) needs to be navigated through. The town has multiple maps, which are different tasks the bot has to perform. The maps vary from a simple straight road to full fledged town. Over the summer I’ll be building this environment in julia, integrating it with the differentiable ray tracer to render the scene, and training the the bot for different tasks mentioned above. The package and progress can be tracked [here](https://github.com/tejank10/Duckietown.jl) diff --git a/blog/_posts/2019-09-11-simulating-the-motion-of-charges.md b/blog/_posts/2019-09-11-simulating-the-motion-of-charges.md deleted file mode 100755 index 6b7cb7ce..00000000 --- a/blog/_posts/2019-09-11-simulating-the-motion-of-charges.md +++ /dev/null @@ -1,171 +0,0 @@ ---- -title: Simulating the Motion of Charged Bodies -author: Sudhanshu Agrawal sudhanshuagr27@ucla.edu -layout: blog ---- - -> “We demand rigidly defined areas of doubt and uncertainty!” – Douglas Adams, The Hitchhiker's Guide To The Galaxy - -## What do charges like doing? - -The answer is quite simple: like charges like to move apart and unlike charges like to move closer. If I were to place a 100 charges in a circle of radius 5cm and tell them to do their thing they would contentedly move around so that they attain the most stable state – where the total potential energy of the system is minimum. The problem is that even though charges know what their purpose is in life, and we know more or less what they’d tend to do, it’s quite difficult to predict their exact movements. Most of us can predict the movement of 3 or 4 charged bodies, but when it comes to accounting for the interactions of a 100 charges, the teachings of H.C. Verma and Resnick Halliday aren’t enough to help us. - -## The Main Idea - -What is the objective of my system of 100 charges? To minimise the total value of this potential energy. (Coincidentally this is the objective of the entire universe as well) -What is the objective of a typical machine learning model? To minimise the total cost/loss. Hmm… - -I’m going to see if I can predict the behaviour of a system of a 100 charges by differentiating the total potential energy and performing gradient descent on the x and y coordinates of each charge. What should happen is that the x and y coordinates start changing themselves to minimise the total potential energy. Therefore, the charges start moving to minimise the total potential energy, mimicking what would happen in the real world. - -## The Obvious Approach vs My Approach - -### The Obvious Approach - -The solution to this problem that immediately comes to mind is to use the amazing computing power we possess to resolve the vector components of the 99 forces on each of the 100 charges we have, use that net force to predict the acceleration of the charges, use that acceleration to produce movement in the charges, and repeat the process within a very short time interval to produce as continuous and as accurate a movement as possible. - -### My Approach - -Why do charges move? Due to acceleration. -Where does acceleration come from? Force. -Why is force applied? To lower potential energy. -Therefore, it’s potential energy that’s really pulling the strings. -What I’ve done is cut out the middleman that is force. I’ve changed my objective from simulating the effect that force has on charged bodies to directly simulating the effect that potential energy has on it. -(This may seem like the same thing, and the fact that it does is why I can do it) -The main advantage to doing so is that potential energy is a scalar quantity whereas force is a vector. Calculating the net potential energy of a system of 100 charges is a lot easier than calculating the net force on each charge in a 100-charge system. - -## The Science Part of It - -Let’s look at our classic formula to calculate potential energy - -$[[U = \frac{1}{4 \pi \epsilon_0}\frac{q_1q_2}{r}]] - -It quantifies the potential energy [[U]] of a system of two point-charges with magnitudes q1 and q2, separated by a distance r in free space (vacuum). - -If we want the total potential energy of a system of [[n]] charges, we just apply this formula [[^nC_2]] times. - -## Let's Begin - -I’m going to create a system of 100 charged bodies and initialise them with random charge values. I’m sampling from a Gaussian Distribution since I’d like there to be a few slightly larger charges in the mix to make things interesting. - -```julia -struct Vertex # represents the charged body - charge::Float64 - pos::Vector{Float64} # x,y coordinates -end - -# Create the req no. of charges with random positions and amplitudes -function create_env(no_ch) - [Vertex(randn(), rand(-5:0.001:5, 2)) for _ in 1:no_ch] -end -``` - -I’m also going to place these charges randomly in a circle of radius 5cm centred at the origin. - -Later on, I’ll make sure that these charges never leave this circle. Why is this important? If I happen to get a couple of large charges with the same sign and these charges were allowed to go anywhere they wanted to, they would simply move apart to infinity, dragging all the smaller charges with them, and we wouldn’t get to see much. - -I’m also going to create a simple function to calculate potential. - -```julia -function potential(a::Vertex, b::Vertex) # classic potential formula - return (8.9e9)*a.charge*b.charge/(sqrt(sum(abs2.(a.pos .- b.pos)))) -end - -function potential(a::Vector) # potential for a system of charges - pot = 0 - for i in 1:length(a) # nC2 - for j in i+1:length(a) - pot = pot+potential(a[i],a[j]) - end - end - return pot -end -``` - -Now I’m going to define my loss function. Why can’t I just use my potential function? The reason is that I want to constrain my charges to a circle. The way I do that is by applying a high penalty(loss) every time a charge tries to move out of the circle. - -```julia -function loss(env::Vector) - s = 0 - for i in 1: length(env) - # if charge moves outside circle of radius 5 centred at origin, - # give it a high penalty - # this is to constrain it otherwise large like charges would - # just go to infinity and we wouldn't see much - if distance(env[i], [0,0])-5>0 - s = s+100*(distance(env[i],[0,0])-5) - end - end - # scaling potential so the distance moved is acceptably small - l = s + 1.0e-9*potential(env) - return l -end -``` - -Since the potential function gives a very high value of the order of 109 we need to scale it so that the loss is a low enough value to produce an acceptable movement in my charges. - -Let’s create the environment of charges - -```julia -env = create_env(100) -``` - -I’m using 2 main machine learning libraries. Zygote, for its AD capabilities, and Flux, for its optimisers. - -```julia -using Zygote -using Flux -``` - -Let’s start moving these charges around - -```julia -opt = ADAM(0.01) -for i in 1:200 - gs = Zygote.gradient(loss, env) - for j in 1: length(gs[1]) # each j is a charge - # making sure we update only the positions not the charge value - Flux.Optimise.update!(opt, env[j].pos, gs[1][j].pos) - end -end -``` - -Using some basic plotting functions, I graphed my charges at every training iteration and put them all together in a gif. - -![](/assets/charges/maingif.gif) - -*Red charges are positive, Blue charges are negative and size of the dot is proportional to the absolute value of charge.* - -## The Big Question. It looks cool, but does it work? - -A high-level observation shows that the like charges tend to move apart and the unlike charges tend to move closer. We can take a step further and notice that as time progresses, the charges tend to move less and less since they are more or less in a stable position. A sure sign of convergence. - -Let’s prove this. - -Let’s take a trivial case and define a system of two charges: one positive and one negative. Let’s place them diametrically opposite with respect to the origin. - -![](/assets/charges/plot1.png) - -What do we expect to happen? The charges should move together. - -![](/assets/charges/plot2.png) - -And they do! - -_(What’s interesting is that they seem to have overshot and actually crossed each other at one point, only to get drawn to each other once more. An apt parallel is charges overshooting due to inertia of motion)_ - -Let’s go back to that system of 100 charges and plot the potential energy at every training iteration. -![](/assets/charges/plot3.png) - -It’s safe to say that the system has converged at a value of approximately -1360 . - -You’re probably wondering why the graph is so bumpy and what these extreme minimas are. The minimas are simply the points in the training loop when the charges got a bit overconfident and tried to escape the constraining circle. They are then immediately brought back to valid positions by the loss function. -They may also occur when a positive and a negative charge briefly overlap with each other giving a potential of negative infinity. Of course, such a situation is impossible in the real world. - -## Conclusion - -It works! -I created this simulation because it’s an interesting and very visual way to get a real feel of how charges move around when affected by almost a 100 different forces. -It also shows how it’s possible to solve a problem more easily by reframing the question being asked. -~~Simulate the effect of force on charged bodies?~~ -Simulate the effect of potential energy on charged bodies? -Most of all it shows the power of gradient descent in solving a problem that would be unwieldy to solve using classic approaches. diff --git a/blog/_posts/2020-06-29-acclerating-flux-torch.md b/blog/_posts/2020-06-29-acclerating-flux-torch.md deleted file mode 100755 index 335515c2..00000000 --- a/blog/_posts/2020-06-29-acclerating-flux-torch.md +++ /dev/null @@ -1,138 +0,0 @@ ---- -title: Accelerating Flux.jl with PyTorch kernels -author: Dhairya Gandhi, Mike Innes -layout: blog ---- - -Julia and Flux provide a flexible [differentiable programming](./2019-03-05-dp-vs-rl.md) system. Flux does not trade flexibility and abstraction for performance, and in fact strives to achieve both in the same package. For example, Flux is able to target multiple hardware accelerators such as [GPUs](https://fluxml.ai/Flux.jl/stable/gpu/) and [TPUs](https://arxiv.org/pdf/1810.09868.pdf). As a result, it is one of the pillars of Julia's [deep learning ecosystem](https://juliahub.com/ui/Packages/CUDAnative/4Zu2W/3.1.0?t=2), with almost 40 packages leveraging it. - -Here, we introduce [Torch.jl](https://github.com/FluxML/Torch.jl), a package that wraps optimised kernels from [PyTorch](https://pytorch.org). Even though Julia's [GPU compiler](https://developer.nvidia.com/blog/gpu-computing-julia-programming-language/) is already pretty good for [general use](https://juliahub.com/ui/Packages/CUDAnative/4Zu2W/3.1.0?t=2) and under [heavy development](https://github.com/JuliaGPU/CUDA.jl), we provide Torch.jl to leverage well-debugged high performance kernels that have been built by the PyTorch community, much in the same way we use BLAS and LAPACK for Linear Algebra. - -For popular object detection models - ResNet50, ResNet101 and VGG19 - we compare inference times for Flux using Torch.jl with our native tooling, and find Flux+Torch to be 2-3x faster. On larger batch sizes, the difference is much higher, since Julia's GPU stack needs further development in the area of memory management and GC. - -

- - -

- -All runs are with a Tesla K40 (12 GB), julia v1.4.2, Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz and 32 GB of DDR3 Memory. - -This project achieves two things. It brings state of the art performance to Julia users who need it today with no fuss, while simulatneously providing benchmarks to identify areas of improvement in the Julia GPU compiler stack, and [track them](https://speed.juliagpu.org/). - -## Usage - -Adding Torch.jl is easy. It assumes the presence of a CUDA enabled GPU on the device it is being added to, and assumes a linux system. - -### Moving models over to PyTorch kernels; introducing `torch` - -Users of Flux are familiar with calling the `gpu(model)` API to accelerate their models with GPUs. The API for Torch.jl is just as simple - `torch(model)`. - -```julia -julia> using Metalhead - -julia> resnet = ResNet() - -julia> torch_resnet = resnet |> torch -``` - -Of course this is not just limited to `ResNet`. Many architectures would benefit from this - such as `VGG`, `DenseNet`, `Inception` etc. Check out [Metalhead.jl](https://github.com/FluxML/Metalhead.jl) for some common computer vision models. It also helps improve performance in models such as YOLO via [ObjectDetector.jl](https://github.com/r3tex/ObjectDetector.jl). In addition, large hard to train models like RCNNs also benefit from these kernels. - -### Installation - -```julia -# Type `]` to enter Pkg mode in the Julia REPL. -pkg> add Torch -[...] # Note that this downloads the Torch artifact, which is quite large - -julia> using Torch -``` - -## Simple, intuitive API - -Our APIs make the PyTorch `Tensor`s mimic Julia arrays closely, in order to provide a Julian experience to Flux users. Torch.jl provides the `Tensor` type which closely follows the semantics of a regular Julia array, albeit while being managed by PyTorch. One can create a tensor with an API similar to `rand` or `zeros`. - -```julia -julia> z = Tensor(3,3) -3×3 Tensor{Float32,2} : - 0.0 0.0 0.0 - 0.0 0.0 0.0 - 0.0 0.0 0.0 -``` - -Controlling the device the tensor is loaded on (the default being on CPU) is done via the `dev` keyword, available in most functions. - -```julia -julia> z = Tensor(3,3, dev = 0) -3×3 Tensor{Float32,2} : - 0.0 0.0 0.0 - 0.0 0.0 0.0 - 0.0 0.0 0.0 -``` - -Note that setting `dev` to `-1` implies the CPU, and `[0,...]` represents the ID of the GPU we intend to load the tensor on. The default GPU is assumed to be `0`. Torch.jl also defines the `torch` function which behaves like the `gpu` function already in Flux, moving over structs to Torch instead of CUDA.jl. - -```julia -julia> using Flux, Metalhead, Torch - -julia> using Torch: torch - -julia> resnet = ResNet() # from Metalhead -ResNet() - -julia> tresnet = resnet |> torch -ResNet() -``` - -We can verify that that we have moved the model parameters to Torch.jl by checking out `params`. - -```julia -julia> typeof.(Flux.params(tresnet)) -212-element Array{DataType,1}: - Tensor{Float32,4} - Tensor{Float32,1} -[...] -``` - -It is also possible to move regular Julia arrays back and forth from Torch.jl using the `tensor` helper function. - -```julia -julia> r = rand(Float32, 3,3) -3×3 Array{Float32,2}: - 0.435017 0.287086 0.105608 - 0.636305 0.398222 0.0682819 - 0.74551 0.944293 0.387852 - -julia> tr = tensor(r, dev = 0) # 0 => GPU:0 -3×3 Tensor {Float32,2}: - 0.435017 0.287086 0.105608 - 0.636305 0.398222 0.0682819 - 0.74551 0.944293 0.387852 - -julia> collect(tr) -3×3 Array{Float32,2}: - 0.435017 0.287086 0.105608 - 0.636305 0.398222 0.0682819 - 0.74551 0.944293 0.387852 -``` - -## Taking gradients - -We can use the [Zygote.jl](https://github.com/Flux/Zygote.jl) reverse mode AD to differentiate the models using Torch.jl tensors, just like we would with regular Julia `Array`s. - -```julia -julia> ip = rand(Float32, 224, 224, 3, 1); - -julia> tip = tensor(ip, dev = 0); - -julia> gs = gradient(Flux.params(tresnet)) do - sum(tresnet(tip)) - end; -``` - -We can now use this gradient to train our models. - -## Additional Remarks - -In Torch.jl, our aim is also to change as little user code as possible, making it easy to get started with. We invite the community to contribute more kernels and provide features from PyTorch that Julia users might be interested in. For feature requests and issues that you might run into with Torch.jl, please open issues on our [GitHub issue tracker](https://github.com/FluxML/Torch.jl/issues). Contributions via pull requests are highly encouraged! - -We look forward to seeing folks try it out and let us know on [discourse](https://discourse.julialang.org) about their experiences. Cheers! diff --git a/blog/_posts/2020-12-20-Flux3D.md b/blog/_posts/2020-12-20-Flux3D.md deleted file mode 100644 index c7d15168..00000000 --- a/blog/_posts/2020-12-20-Flux3D.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: Flux3D.jl, 3D Vision Library in Julia -author: Nirmal Suthar, Avik Pal, Dhairya Gandhi -layout: blog ---- - -3D computer vision involves various computer vision techniques like classification, segmentation, object detection, super-resolution and many more. Modeling these problems becomes significantly easier when there is a general purpose differentiation library available, alongside the litany of tools needed to solve a train ML model, which FluxML already supports. - -Performing 3D vision tasks involve preparing datasets to fit a certain representation and applying transforms to them. Further, Flux3D exports common 3D metrics for use in designing the loss objective and various 3D layers, which have been optimised for performance for large datasets, typical in vision-based tasks. - -## What is Flux3D.jl - -
- -
- -Flux3D.jl is a 3D vision library, written completely in Julia. This package utilizes Flux.jl and Zygote.jl as its building blocks for training 3D vision models and for supporting differentiation. This package also has the support of CUDA GPU acceleration with CUDA.jl. Some of the roles of Flux3D are: - -* 3D Structures - Accelerated Batched Data structure for PointCloud, VoxelGrid and TriMesh for storing and computation. -* Transforms - Multiple transforms for PointCloud, VoxelGrid and TriMesh -* Metrics - metrics like chamfer_distance, laplacian loss and edge loss for defining loss objectives. -* Dataset - ModelNet10/40 (in multiple variants like pointcloud, mesh, voxel) and a Minimal Custom Dataset wrapper. -* Conversions - Interconversion between different 3D structure (this also help in building different variants of the dataset) -* Visualize - visualizing PointCloud, TriMesh and VoxelGrid -* 3D Deep Learning - Implementations of some commonly used 3D layers and models. - -Flux3D.jl : [github.com/FluxML/Flux3D.jl](https://github.com/FluxML/Flux3D.jl) - -Docs : [fluxml.ai/Flux3D.jl/stable](https://fluxml.ai/Flux3D.jl/stable) - -## Benchmarks for Flux3D.jl - -Kaolin is a popular 3D vision library based on PyTorch. Flux3D.jl is overall faster than Kaolin in terms of applying transforms on PointCloud/TriMesh and comparable with Kaolin in terms of applying metrics. However, there must be work done to improve the back pass in laplacian loss which uses `SparseArrays`. From the benchmarks, we can tell that Flux3D can outperform Kaolin. Some key-differences between the two are discussed later in this post. - -

- - - -

- -## Short Walkthrough of the Flux3D.jl - - -A basic training pipeline requires preparing the datasets, defining the model, the loss function and finally training it. -Let's go through each step along with visualising and evaluating the results. - -### 1. Handling 3D DataPoint - -Pointcloud, triangle mesh and voxels are three widely used representation for 3D data and most of the 3D vision work is also based on these structures. To apply transforms to our data, we need to initialise it. - -```julia -julia> using Flux3D - -julia> m = load_trimesh("airplane.off", "teapot.obj") |> gpu -TriMesh{Float32, UInt32, CUDA.CuArray} Structure: - Batch size: 2 - Max verts: 17443 - Max faces: 17116 - offset: -1 - Storage type: CuArray - -julia> p = PointCloud(m) -PointCloud{Float32} Structure: - Batch size: 2 - Points: 3000 - Normals: 0 - Storage type: CuArray{Float32,3} - -julia> v = VoxelGrid(m) -VoxelGrid{Float32} Structure: - Batch size: 2 - Voxels features: 64 - Storage type: CuArray{Float32,4} - -julia> t = NormalizeTriMesh(inplace=false) -NormalizeTriMesh(;inplace=false) - -julia> m2 = t(m) -TriMesh{Float32, UInt32, CUDA.CuArray} Structure: - Batch size: 2 - Max verts: 17443 - Max faces: 17116 - offset: -1 - Storage type: CuArray - -julia> save_trimesh("normalize_aiplane.obj",m2,1) - -``` - -### 2. Preparing Dataset - -ModelNet10/40 is one of the widely used 3D dataset, and we can easily access and preprocess this dataset for use in various vision-based tasks using Flux3D. We can also use conversion transforms for using ModelNet10/40 in multiple representations like `PointCloud`, `TriMesh`, `VoxelGrid`. - -```julia -julia> using Flux3D, Makie - -julia> dset = ModelNet10(categories=["monitor","chair"]) -ModelNet Dataset: - root: /root/.julia/packages/Flux3D/9bMbc/datasets/ - train: true - length: 1354 - transform: nothing - categories: 2 - -julia> dset[1] -DataPoint: - idx: 1 - data: TriMesh{Float32,UInt32,Array} - ground_truth: 1 - category_name: monitor -``` - -We can use conversion transforms to convert the dataset to `VoxelGrid`. Similarily we can convert `VoxelGrid`, `TriMesh` and `PointCloud` to any 3D structure either using transforms or simply using the regular constructor. - -```julia -julia> t = Chain(NormalizeTriMesh(), TriMeshToVoxelGrid(64)) -Chain(NormalizeTriMesh(;inplace=true), TriMeshToVoxelGrid(resolution=64)) - -julia> dset2 = ModelNet10(train=false, transform=t) -dset2 = ModelNet Dataset: - root: /root/.julia/packages/Flux3D/9bMbc/datasets/ - train: false - length: 908 - transform: Chain(NormalizeTriMesh(;inplace=true), TriMeshToVoxelGrid(resolution=64)) - categories: 10 - -julia> dset2[1] -DataPoint: - idx: 1 - data: VoxelGrid{Float32} - ground_truth: 1 - category_name: bathtub -``` - -### 3. Defining Model/Loss - -Loss objectives and designing model solely depend upon the requirement of tasks, and with the help of FLuxML ecosystem, we can define any custom model as well as loss. There are some commonly used metrics and predefined 3D models which can assist in 3D specific tasks like chamfer_distance, laplacian_loss and edge_loss. - -```julia -julia> chamfer_distance(p,p) -1.58147f-5 - -julia> laplacian_loss(m) -6.72288 - -julia> edge_loss(m) -2110.6 -``` - -### 4. Training - -Flux and Zygote takes care of everything here :) - -Additonally, 3D structures and all relevant transforms, as well as metrics, are compatible with Zygote for supporting differentiation. - -
- -
- -### 5. Visualization and Evaluation - -Flux3D provides a function visualize for visualizing 3D structures. This function uses Makie for plotting. We can use this same function for visualizing all three 3D structures PointCloud, TriMesh, and VoxelGrid - -```julia - -julia> using Makie - -julia> vbox( - hbox( - visualize(m,1),visualize(p,1,markersize=25) - ), - hbox( - visualize(v,1), visualize(v,1,algo=:MarchingCubes) - ), - ) - -``` - -
- -
- -## Why use Julia and FluxML ecosystem - -Kaolin is written majorly in the lower language C++ and uses CUDA-C for using GPU which is integrated with python for API interface. But with Flux3D, it is written purely in Julia and with the help of **CUDA.jl** we are also able to leverage GPU acceleration with the same code. This surely emphasizes the benefit of using Julia Language for intense computation like 3D vision while using high-level functions like any other modern language. - -**FluxML** ecosystem uses **Zygote** as the AD engine which doesn't require the input and variable to be present in any special form (like Tensors in PyTorch), instead, we can simply define a function without doing mutation and Zygote will calculate gradients for us. Therefore we can make this package compatible with FluxML ecosystem without doing any extra work and even with many other packages like SciML differential equations ecosystem. - -There are various Julia packages (thanks to awesome Julia community!) which make Flux3D.jl possible. With the help of **Makie** ecosystem, we can easily interact, visualize 3D structures, save the plots and gifs. **NearestNeighbors.jl** which is high performance nearest neighbour search library also makes it possible to perform intense computation metrics like chamfer distance even on CPU. - -## Conclusion - -As all the batched structure for PointCloud, TriMesh, and VoxelGrid are stable enough, we can easily define any arbitrary or custom functions on top of it and using Zygote we can easily differentiate through it. There are a lot of interesting applications of Flux3D.jl along with other interesting packages in Julia like DiffEqFlux, worth exploring. - -Some of the things which would be interesting to have in future releases are:- - -* Cache-based Custom dataset wrapper, as 3D data are expensive in terms of space and computation (especially in VoxelGrid). -* Some more metrics for 3D data like normal_consistency, cloud_to_surface_distance and some more loss. -* Add support for textures in case of TriMesh which will open a lot more applications. -* Integration with Differentiable Graphics Frameworks (like RayTracer.jl) - -Any suggestions, issues and pull requests are most appreciated. Cheers! diff --git a/blog/_posts/2021-12-1-flux-numfocus.md b/blog/_posts/2021-12-1-flux-numfocus.md deleted file mode 100644 index 71a7eac4..00000000 --- a/blog/_posts/2021-12-1-flux-numfocus.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Flux <3 NumFOCUS -author: Dhairya Gandhi, Logan Kilpatrick -layout: blog ---- - -

- -

- -We are very excited to announce that [FluxML](https://fluxml.ai) is partnering with [NumFOCUS](https://numfocus.org) as an affiliated project to further the cause of open and reproducible science and growing the adoption of the FluxML ecosystem. Flux has always had the mission of being a simple, hackable and performant approach to machine learning, which is extended to a number of domains in science by means of differentiable programming. - -This milestone is the result of the coming together of the Julia community to support the vision of producing high performance machine learning tools which are flexible towards the needs of novel use cases such as: graph neural networks, scientific machine learning, and differentiable programming. The support of the community as well as the contributions made to that end have helped catapult Flux to this stage, so we want to take this moment to thank the Julia community for their continued support, guidance, and encouragement. - -This partnership will help us in growing the community, bringing new contributors into the ecosystem, and help us manage the funds from future grants we raise for a number of upcoming projects - be they compiler related tools for our AD, or support for low precision math on GPUs in a flexible and generic manner. - -We hope to announce a lot more exciting news in the times to come and thank you all so much once again for helping us reach this exciting milestone in our journey! There is a lot more that we want to do, and this is definitely only the start. - -Cheers - -About NumFOCUS: The mission of NumFOCUS is to promote open practices in research, data, and scientific computing by serving as a fiscal sponsor for open source projects and organizing community-driven educational programs. NumFOCUS is a 501(c)(3) public charity in the United States. diff --git a/config.md b/config.md new file mode 100644 index 00000000..2640bfd7 --- /dev/null +++ b/config.md @@ -0,0 +1,21 @@ ++++ +author = "FluxML" +mintoclevel = 2 + +website_title = "Flux.jl" +website_descr = "The elegant machine learning library" +website_url = "https://fluxml.ai" +website_img = "/assets/images/FluxGitHubPreview.png" +website_footer = """ + Flux: A Deep Learning Library for the Julia Programming Language + """ +website_twitter = "Follow @FluxML" +website_twitter_url = "https://twitter.com/FluxML?ref_src=twsrc%5Etfw" + +ignore = ["_old/"] + +# Adjust when moving to prod (note: if fluxml.ai, then no need for prepath) +prepath = "fluxml-franklin" ++++ + +\newcommand{\totop}{~~~

⇧ back to top

~~~} diff --git a/ecosystem.md b/ecosystem.md new file mode 100644 index 00000000..99fa2859 --- /dev/null +++ b/ecosystem.md @@ -0,0 +1,236 @@ ++++ +title="Ecosystem" ++++ + +{{redirect /ecosystem.html}} +{{redirect /models/}} + + +~~~ + +~~~ + + +~~~ +
+
+~~~ + + +# Ecosystem + +This section lists tools that complement Flux in typical machine learning and deep learning workflows. +To add your project please [send a PR](https://github.com/FluxML/fluxml.github.io/edit/master/ecosystem.md). +See also academic work [citing Flux](https://scholar.google.com/scholar?oi=bibs&hl=en&cites=9731162218836700005), [or Zygote](https://scholar.google.com/scholar?oi=bibs&hl=en&cites=11943854577624257878). + +~~~ + +

Table of contents

+ + +~~~ + + +~~~ +

Advanced models

+ +
    +
  • FluxArchitectures is a collection of slightly more advanced network architectures.
  • +
+ +~~~ + +\totop + + +~~~ +

Computer Vision

+ +
    +
  • ObjectDetector.jl provides ready-to-go image analysis via YOLO.
  • +
  • Metalhead.jl includes many state-of-the-art computer vision models which can easily be used for transfer learning.
  • +
  • UNet.jl is a generic UNet implementation.
  • +
+~~~ + +\totop + + +~~~ +

Datasets

+ +
    +
  • MLDatasets.jl focuses on downloading, unpacking, and accessing benchmark datasets.
  • +
+~~~ + +\totop + + +~~~ +

Differentiable programming

+ +
    +
  • The SciML ecosystem uses Flux and Zygote to mix neural nets with differential equations, to get the best of black box and mechanistic modelling.
  • +
  • DiffEqFlux provides tools for creating Neural Differential Equations.
  • +
  • Flux3D shows off machine learning on 3D data.
  • +
  • RayTracer.jl combines ML with computer vision via a differentiable renderer.
  • +
  • Duckietown.jl Differentiable Duckietown simulator.
  • +
  • The Yao project uses Flux and Zygote for Quantum Differentiable Programming.
  • +
  • AtomicGraphNets.jl enables learning graph based models on atomic systems used in chemistry
  • +
  • DiffImages.jl differentiable computer vision modeling in Julia with the Images.jl ecosystem
  • +
+~~~ + +\totop + + +~~~ +

Generative models

+ +
    +
  • Adversarial attacks for Neural Networks written with FluxML.
  • +
+~~~ + +\totop + + +~~~ +

Graph learning

+ +
    +
  • GeometricFlux makes it easy to build fast neural networks over graphs.
  • +
  • NeuralOperators enables training infinite dimensional PDEs by learning a continuous function instead of using the finite element method.
  • +
  • SeaPearl.jl is a Constraint Programming solver that uses Reinforcement Learning based on graphs as input.
  • +
+~~~ + +\totop + + +~~~ +

Miscellaneous

+ +

*AdversarialPrediction.jl provides a way to easily optimize generic performance metrics in supervised learning settings using the Adversarial Prediction framework.

+
    +
  • Mill helps to prototype flexible multi-instance learning models.
  • +
  • MLMetrics.jl is a utility for scoring models in data science and machine learning.
  • +
  • MLPlots.jl contains common plotting recipes for statistics and machine learning.
  • +
  • Torch.jl exposes torch in Julia.
  • +
  • ValueHistories.jl is a utility for efficient tracking of optimization histories, training curves or other information of arbitrary types and at arbitrarily spaced sampling times
  • +
+~~~ + +\totop + + +~~~ +

Natural language processing

+ +
    +
  • Transformers.jl provides components for Transformer models for NLP, as well as providing several trained models out of the box.
  • +
  • TextAnalysis.jl provides several NLP algorithms that use Flux models under the hood.
  • +
+~~~ + +\totop + +~~~ +

Pipeline extensions

+ +
    +
  • DLPipelines.jl is an interface for defining deep learning data pipelines.
  • +
+~~~ + +\totop + +~~~ +

Plumbing

+ +

Tools to put data into the right order for creating a model.

+ +
    +
  • Augmentor.jl is a real-time library augmentation library for increasing the number of training images.
  • +
  • DataAugmentation.jl aims to make it easy to build stochastic label-preserving augmentation pipelines for your datasets.
  • +
  • MLDataUtils.jl is a utility for generating, loading, partitioning, and processing Machine Learning datasets.
  • +
  • MLLabelUtils.j is a utility for working with classification targets. It provides the necessary functionality for interpreting class-predictions, as well as converting classification targets from one encoding to another.
  • +
+~~~ + +\totop + +~~~ +

Probabilistic programming

+ +
    +
  • Turing.jl extends Flux’s differentiable programming capabilities to probabilistic programming.
  • +
  • Omega is a research project aimed at causal, higher-order probabilistic programming.
  • +
  • Stheno provides flexible Gaussian processes.
  • +
+~~~ + +\totop + +~~~ +

Reinforcement learning

+ +
    +
  • AlphaZero.jl provides a generic, simple and fast implementation of Deepmind’s AlphaZero algorithm.
  • +
  • ReinforcementLearning.jl offers a collection of tools for doing reinforcement learning research in Julia.
  • +
+ +~~~ + +\totop + + + +~~~ +
+
+~~~ + +~~~ + + + +~~~ diff --git a/experiments/breakout/assets/js/Board.js b/experiments/breakout/assets/js/Board.js deleted file mode 100644 index 12c8f573..00000000 --- a/experiments/breakout/assets/js/Board.js +++ /dev/null @@ -1,15 +0,0 @@ -function Board(container, {env}={}){ - this.container = container - this.render = ()=>{ - env.render(); - if(env.done()){ - show($$(".overlay #gameOver")) - }else{ - hide($$(".overlay #gameOver")) - } - }; - - this.removeStartScreen = ()=>{ - hide($$(".overlay #start")); - } -} diff --git a/experiments/breakout/assets/js/Breakout.js b/experiments/breakout/assets/js/Breakout.js deleted file mode 100644 index afc80560..00000000 --- a/experiments/breakout/assets/js/Breakout.js +++ /dev/null @@ -1,94 +0,0 @@ -/****************************************************** -======================================================= -Breakout Game -======================================================= -******************************************************/ -function Breakout(canvas,{width=500, height=400, brick_height=20, brick_width=50, paddle_width=50, paddle_height=10, ball_radius=5}={}){ - var score = 0; - canvas.width = width; - canvas.height = height; - var components = { - paddle: new Paddle(new Vector(Math.floor(width/2), canvas.height - paddle_height), { - width:paddle_width, - height:paddle_height, - total_width: width - }), - bricks: new BrickCollection(6, {width, brick_width, height, brick_height, padding: 40, colors: ["#c84848", "#c66c3a", "#b47a30", "#a2a22a", "#48a048","#4248c8"]}), - ball: new Ball(new Vector(Math.floor(width/2), Math.floor(height/2)), new Vector(-5, -5), {radius:ball_radius}) - } - - this.draw = ()=>{ - var ctx = canvas.getContext('2d'); - //background - ctx.fillStyle = "#000"; - ctx.fillRect(0, 0, canvas.width, canvas.height); - - for( var c in components){ - components[c].draw(canvas); - } - ctx.font = '18px arial'; - ctx.fillStyle = "#fff"; - ctx.textAlign = "right"; - ctx.textBaseline = "top" - ctx.fillText('Score: '+ score, canvas.width - 10, 10); - } - - - this.play = ()=>{ - this.step(); - if(!this.done()) - requestAnimationFrame(this.play); - } - - this.step = (dir)=>{ - components.ball.move(); - - this.action(dir); - this.movePaddle(); - - var reward = this.collisionDetector(); - score += reward; - this.draw(); - return reward; - } - - this.collisionDetector = function(){ - var ball = components.ball; - var brickHit = components.bricks.detectCollision(ball); // collision with bricks - var reward = 0; - if(brickHit){ - - brickHit.deactivate(); - reward = 10; - ball.rebound([1, -1]); - } - var paddleHit = components.paddle.detectCollision(ball); // collision with paddle - if(paddleHit){ - ball.rebound([1, -1]); - } - var wallHit = components.ball.detectCollision(width, height); // collision with walls - wallHit.forEach(w=> ball.rebound(w)); - return reward; - } - - this.done = function(){ - return components.bricks.allHit() || components.ball.pos.y > height; - } - - this.movePaddle = ()=> components.paddle.move(); - - this.action = (dir)=>{ - components.paddle.setDirection(dir); - } - - this.reset = function(){ - components.ball.pos = new Vector(Math.floor(width/2), Math.floor(height/2)); - components.ball.speed = new Vector(-5, -5); - components.bricks.activateAll(); - score = 0; - } - - - this.render = this.draw; - this.config = ()=>{return null}; -} \ No newline at end of file diff --git a/experiments/breakout/assets/js/components.js b/experiments/breakout/assets/js/components.js deleted file mode 100644 index 3930e451..00000000 --- a/experiments/breakout/assets/js/components.js +++ /dev/null @@ -1,77 +0,0 @@ -/****************************************************** -======================================================= -Components -======================================================= -******************************************************/ - -function Brick(pos, active, {color="#0f0", width=50, height=10}={}){ - this.pos = pos; - this.active = active; - - this.draw = (canvas)=>{ - var ctx = canvas.getContext('2d'); - if(this.active){ - ctx.fillStyle = color; - ctx.fillRect(this.pos.x, this.pos.y, width, height); - // ctx.strokeStyle="#fff"; - // ctx.strokeRect(this.pos.x, this.pos.y, width, height); - } - } - - this.detectCollision = (ball)=>{ - if(!this.active)return null - - if((ball.pos.x > this.pos.x && ball.pos.x < this.pos.x + width) - && (ball.pos.y > this.pos.y && ball.pos.y < this.pos.y + height)){ - return this - } - - return null - } - - this.deactivate = ()=>{ - this.active = false; - } - - this.activate = ()=>{ - this.active = true; - } -} - -function BrickCollection(layers, {width, brick_width, height, brick_height, padding, colors}){ - var max_blocks = Math.floor(width/brick_width); - - this.contents = (new Array(layers*max_blocks)).fill(0).map((_, i)=> { - var color = colors[Math.floor(i/max_blocks)]; - var x = Math.floor((i% max_blocks)*brick_width); - var y = Math.floor(i/max_blocks)*brick_height + padding; - - return new Brick( - new Vector(x, y), - true, {width: brick_width, height: brick_height, color}) - }); - - this.draw = (canvas)=> { this.contents.forEach(e=>e.draw(canvas)); }; - - this.detectCollision = (ball)=>{ - if( ball.pos.y - ball.radius > layers*height + padding) return null; - - for (var brick of this.contents){ - if(brick.detectCollision(ball)) - return brick; - } - - return null; - } - - this.allHit = ()=>{ - for (var brick of this.contents){ - if(brick.active)return false; - } - return true; - } - - this.activateAll = ()=>{ - this.contents.forEach(brick => brick.activate()) - } -} diff --git a/experiments/breakout/assets/js/script.js b/experiments/breakout/assets/js/script.js deleted file mode 100644 index 1c98bdf7..00000000 --- a/experiments/breakout/assets/js/script.js +++ /dev/null @@ -1,27 +0,0 @@ -var __init__ = (function(){ - - var env = new Breakout(document.querySelector("#playground")); - var board = new Board(document.querySelector(".board"), {env}); - var game = new Game(env, board, null); - - document.addEventListener('keydown', event => { - var code = event.keyCode; - - if(code == 13){ - // remove startScreen - board.removeStartScreen(); - return game.play(); - } - - if(code != 39 && code != 37)return; - - game.action(code - 38); - }) - - document.addEventListener('keyup', event => { - game.action(0); - }) - env.draw(); -}) - -window.onload = __init__; \ No newline at end of file diff --git a/experiments/breakout/index.html b/experiments/breakout/index.html deleted file mode 100644 index fb17e5ce..00000000 --- a/experiments/breakout/index.html +++ /dev/null @@ -1,21 +0,0 @@ ---- -layout: default -game: breakout ---- - -{% include experiments/game/headers.html %} - -{% assign game = site.data.experiments[page.game] %} -{% include experiments/game/content.html game=game %} - -{% include experiments/game/footer.html %} - - - - - - \ No newline at end of file diff --git a/experiments/cartPole/assets/bson/dqn.bson b/experiments/cartPole/assets/bson/dqn.bson deleted file mode 100644 index 602169cd..00000000 Binary files a/experiments/cartPole/assets/bson/dqn.bson and /dev/null differ diff --git a/experiments/cartPole/assets/css/cartpole.css b/experiments/cartPole/assets/css/cartpole.css deleted file mode 100644 index 2f6350a2..00000000 --- a/experiments/cartPole/assets/css/cartpole.css +++ /dev/null @@ -1,72 +0,0 @@ -#playground{ - /*background: linear-gradient(to bottom right, var(--dark), #5f924d, var(--dark)); */ - background: var(--medium); - margin-bottom: 10px; -} - -div{ - position:relative; -} - -#playground, #controls{ - /*box-shadow: 2px 2px 8px #060638;*/ -} - -#playground, #controls, .board, .demo_wrapper{ - width: 60vw; -} - -#playground, .board{ - min-height: 200px; - border-bottom-left-radius: 6px; - border-bottom-right-radius: 6px; - overflow: hidden; -} - -.demo_wrapper{ - margin: 0px auto; - height: 90%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -@media only screen and (max-width:768px){ - #playground, #controls, .board, .demo_wrapper{ - width: 90vw; - } -} - -.levels{ - flex: 1; - /* align-items: flex-end; */ - display: flex; - flex-direction: row; - justify-content: flex-end; - align-items: center; -} - -.levels > div{ - padding: 0px 10px; - border: 1px solid; - margin: 0 10px 0 0; - border-radius: 6px; - cursor: pointer; - transition: all 0.4s linear; -} - -.levels .selected{ - background: var(--dark); - color: var(--light); -} - -.stats{ - display: flex; - flex-direction: row; - /*justify-content: ;*/ - padding: 20px; -} -.stats > p{ - margin: 0 5px; -} \ No newline at end of file diff --git a/experiments/cartPole/assets/css/keyboard.css b/experiments/cartPole/assets/css/keyboard.css deleted file mode 100644 index 69ba34be..00000000 --- a/experiments/cartPole/assets/css/keyboard.css +++ /dev/null @@ -1,74 +0,0 @@ -.keyboard{ - position: absolute; -} - -.arrowkey{ - position: absolute; - top: 0; - border: 1px solid #fff; - left: 0; - width: 27%; - height: 44%; - border-radius: 3px; -} - -.keyboard .up, .keyboard .down{ - left: 34%; -} - -.keyboard .down,.keyboard .right,.keyboard .left{ - top: 51%; -} - -.keyboard .right{ - left: 66%; -} - - -.keyboard .left{ - left: 2%; -} - -.keyboard .up:before, .keyboard .left:before, .keyboard .right:before, .keyboard .down:before{ - position: absolute; - content: ''; - height: 0; - width: 0; - border: 5px solid transparent; -} - -.keyboard .up:before{ - top: calc(40% - 5px); - left: calc(50% - 5px); - border-bottom: 5px solid #fff; -} - -.keyboard .down:before{ - top: calc(60% - 5px); - left: calc(50% - 5px); - border-top: 5px solid #fff; -} - -.keyboard .right:before{ - top: calc(50% - 5px); - left: calc(60% - 5px); - border-left: 5px solid #fff; -} - -.keyboard .left:before{ - top: calc(50% - 5px); - left: calc(40% - 5px); - border-right: 5px solid #fff; -} - -.keyboard .highlight{ - background: #fff; -} - -.keyboard .highlight[data-key="left"]:before{ - border-right-color: #288228; -} - -.keyboard .highlight[data-key="right"]:before{ - border-left-color: #288228; -} \ No newline at end of file diff --git a/experiments/cartPole/assets/js/Board.js b/experiments/cartPole/assets/js/Board.js deleted file mode 100644 index a90fa90b..00000000 --- a/experiments/cartPole/assets/js/Board.js +++ /dev/null @@ -1,119 +0,0 @@ -(function(obj){ - - Object.assign(obj, {Board}); - - // render board - function Board(container, { - cartColor="#333", - poleColor="#fff" - }={}){ - const template = ( - '\ -
\ -

Game Over

\ -
\ -

Score: 0

\ -

\ -
\ -
\ -
' - ) - container.innerHTML = template; - - this.container = container; - this.cartColor = cartColor; - this.poleColor = poleColor; - this.keyboard = new Keyboard(container.querySelector('.keyboard')); - this.canvas = container.querySelector('#playground'); - this.ctx = this.canvas.getContext('2d'); - this.overlay = container.querySelector('.overlay'); - this.score = this.overlay.querySelector('.score span'); - this.apm = this.overlay.querySelector('.apm'); - this.gameOverScreen = this.overlay.querySelector('.game-over'); - } - - - Board.prototype.render = function({ - state, - action, - score, - cart_height, - cart_length, - pole_length, - pole_diameter, - done, - x_threshold, - kicked, - apm - }){ - // console.log(kicked); - ({x, theta} = state); - - var scaleToPixelsX = this.canvas.width*0.5/(cart_length/2 + x_threshold); - var scaleToPixelsY = this.canvas.height*0.5/(cart_height + pole_length); - - this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); - - var cartX = (this.canvas.width/2 + scaleToPixelsX*(x - cart_length/2)); - var cartY = this.canvas.height - scaleToPixelsY*cart_height; - var rotateAngle = theta - Math.PI/2; - - // draw pole - this.ctx.translate(cartX + scaleToPixelsX*cart_length/2, cartY + scaleToPixelsY*pole_diameter/2); - this.ctx.fillStyle = this.poleColor; - this.ctx.rotate(rotateAngle); - this.ctx.scale(scaleToPixelsY, scaleToPixelsX); // needs to be (y, x) as this is rotated - this.ctx.fillRect(-pole_diameter/2, -pole_diameter/2, pole_length, pole_diameter); - this.ctx.scale(1/scaleToPixelsY, 1/scaleToPixelsX); - this.ctx.rotate(-rotateAngle); - this.ctx.translate(-(cartX + scaleToPixelsX*cart_length/2), -(cartY + scaleToPixelsY*pole_diameter/2)); - - // draw cart - this.ctx.fillStyle = this.cartColor; - this.ctx.fillRect(cartX, cartY, scaleToPixelsX*cart_length, scaleToPixelsY*cart_height); - - var dir = (d) => d == 1? 'left': 'right'; - - // highlight key - if(action != 0){ - this.keyboard.highlight(dir(action)); - } - if(kicked != 0){ - // console.log("draw") - var img = new Image(); - img.src = "./assets/red__" + dir(kicked)+ "_arrow.png"; - var ctx = this.ctx; - img.onload = function(){ - // this.ctx.drawImage(img, x, cartY - cart_height, cartY, cartY); - // console.log() - var v = kicked*2 - 3; - var dy = cart_height*scaleToPixelsY; - var ax = ctx.canvas.width/2 + scaleToPixelsX*(x - v*cart_length/2); - var ay = ctx.canvas.height - dy; - // console.log(v) - if(v == 1){ - ax -= dy; - } - // console.log(dy, ax); - ctx.drawImage(img, ax, ay, dy, dy); - } - } - if(apm != -1){ - this.apm.innerText = "APM: " + apm; - }else{ - this.apm.innerText = ""; - } - - // change score - this.score.innerText = score; - - // game over screen - if(done){ - this.gameOverScreen.className = this.gameOverScreen.className.replace("hidden-screen", ""); - }else{ - if(this.overlay.querySelector('.hidden-screen') == null){ - this.gameOverScreen.className += " hidden-screen"; - } - } - } -})(window) \ No newline at end of file diff --git a/experiments/cartPole/assets/js/CartPole.js b/experiments/cartPole/assets/js/CartPole.js deleted file mode 100644 index af130ba2..00000000 --- a/experiments/cartPole/assets/js/CartPole.js +++ /dev/null @@ -1,83 +0,0 @@ -(function(obj){ - - Object.assign(obj, {CartPole}) - - // cartPole env - function CartPole(){ - // ported from https://github.com/JuliaML/Reinforce.jl/blob/master/src/envs/cartpole.jl - const gravity = 9.8; - const mass_cart = 1.0; - const mass_pole = 0.1; - const total_mass = mass_cart + mass_pole; - const pole_length = 0.5; - const mass_pole_length = mass_pole * pole_length; - const force_mag = 10.0; - const tau = 0.02 ; - - const theta_threshold = Math.PI * 0.25 - const x_threshold = 2.4 - - //display settings - const cart_length = .4 - const cart_height = .05 - const pole_diameter = 0.02 - - var total_reward = 0; - var state = {x: 0, xvel: 0, theta: 0, thetavel: 0}; - var action = 0; - - - this.reset = ()=>{ - state = {x:0, theta: 0, xvel:0, thetavel: 0} - total_reward = 0; - action = 0; - } - - this.step = (a)=>{ - if(this.done()){ - return 0; - } - - action = a; - ({ x, xvel , theta, thetavel } = state); - - force = (action == 1 ? -1 : (a==2)?1:0) * force_mag; // extra action 0 for the case when user doesn't press any key - tmp = (force + mass_pole_length * Math.sin(theta) * (thetavel^2)) / total_mass - thetaacc = (gravity * Math.sin(theta) - tmp * Math.cos(theta)) / (pole_length * (4/3 - mass_pole * (Math.cos(theta)^2) / total_mass)) - xacc = tmp - mass_pole_length * thetaacc * Math.cos(theta) / total_mass; - state.x = (x += tau * xvel) - state.xvel = (xvel += tau * xacc) - state.theta = (theta += tau * thetavel) - state.thetavel = (thetavel += tau * thetaacc); - - var reward = this.done() || a == 0? 0.0 : 1.0; - total_reward += reward; - return reward - } - - this.done = ()=>{ - ({x, xvel , theta, thetavel } = state); - return !(Math.abs(x) <= x_threshold && Math.abs(theta) <= theta_threshold); - } - - this.config = ()=>{ - var done = this.done(); - - return ({ - state, - action, - score: total_reward, - cart_height, - cart_length, - pole_length, - pole_diameter, - x_threshold, - done - }); - - } - - this.state = () => state; - } - -})(window) \ No newline at end of file diff --git a/experiments/cartPole/assets/js/Keyboard.js b/experiments/cartPole/assets/js/Keyboard.js deleted file mode 100644 index 51d5fed9..00000000 --- a/experiments/cartPole/assets/js/Keyboard.js +++ /dev/null @@ -1,29 +0,0 @@ -(function(obj){ - Object.assign(obj, {Keyboard}); - - function Keyboard(container){ - const template = ( - '
\ -
\ -
\ -
' - ) - - container.innerHTML = template; - - this.highlight = (data)=>{ - - var old = container.querySelector('.highlight'); - if(old != null) - old.className = old.className.replace('highlight', ''); - - var key = container.querySelector('[data-key="'+ data +'"]'); - key.className += " highlight"; - setTimeout(()=>{ - key.className = key.className.replace('highlight', ''); - }, 200) - - - } - } -})(window) \ No newline at end of file diff --git a/experiments/cartPole/assets/js/dqn.js b/experiments/cartPole/assets/js/dqn.js deleted file mode 100644 index 3f04f539..00000000 --- a/experiments/cartPole/assets/js/dqn.js +++ /dev/null @@ -1,17 +0,0 @@ -let model = (function () { - let math = tf; - function mandrill(guineafowl) { - return math.add(math.vectorTimesMatrix(guineafowl, model.weights[0]), model.weights[1]); - }; - function buffalo(elk) { - return math.tanh(math.add(math.vectorTimesMatrix(elk, model.weights[2]), model.weights[3])); - }; - function barracuda(owl) { - return math.tanh(math.add(math.vectorTimesMatrix(owl, model.weights[4]), model.weights[5])); - }; - function model(raven) { - return mandrill(buffalo(barracuda(raven))); - }; - model.weights = []; - return model; -})(); \ No newline at end of file diff --git a/experiments/cartPole/assets/js/script.js b/experiments/cartPole/assets/js/script.js deleted file mode 100644 index 21275453..00000000 --- a/experiments/cartPole/assets/js/script.js +++ /dev/null @@ -1,96 +0,0 @@ -// Game -> CartPole , ( Board --> Keyboard ) - -Game.prototype.play = async function(){ - clearTimeout(this.playTimeout); - if(this.env.done())return; - - var scope = this; - switch(this.state){ - case this.states.H: - this.move(this.newAction); - // newAction = 0; - break; - case this.states.C: - this.kick(); - var a = await this.predict(this.env.state()) - var action = await this.transform.action(a); - this.move(action); - tf.dispose(a); - break; - default: - console.log("Invalid state", this.state); - } -} - -Game.prototype.kick = function(){ - this.env.step(this.newAction); - this.kicked = this.newAction; - this.newAction = this.defaultAction(); // we only kick once, not continously -} - -Game.prototype.display = function(){ - var s = this.defaultAction() - var kicked = s; - var apm = -1; - if(this.state == this.states.C){ - kicked = this.kicked; - apm = 60*1000/this.timeInt; - } - this.kicked = s; - - this.out.render(Object.assign({}, this.env.config(), {kicked, apm})); -} - - -var board = new Board(document.querySelector('.board')) - -function __init__(){ - - var cp = new CartPole(); - var game = new Game(cp, board, (e) => tf.tidy(()=>model(e))); - game.setState("human"); - - var reset = () => { - game.setState(game.state); - } - - var eachEl = (p, e, cb) => - Array.from(p.querySelectorAll(e)).forEach(el=> - el.addEventListener('click', (event) =>cb(el, event, p)) - ) - - - eachEl(document.querySelector('.options'), '.option', (el, event, p) => { - game.setState(el.getAttribute('data-state')); - highlight(el, p); - }) - - eachEl(document.querySelector('.levels'), 'div', (el, event, p) => { - // console.log(parseInt(el.getAttribute('data-time'))) - game.timeInt = parseInt(el.getAttribute('data-time')); - highlight(el, p); - }) - // set level to easy - game.setTimeInt(100); - - - // event listeners for keyboard - document.addEventListener('keydown', function(event){ - if(event.keyCode == 39){ // right - game.action(2); - }else if(event.keyCode == 37){ // left - game.action(1); - } - }) - var keyboard = document.querySelector('.keyboard') - keyboard.querySelector('.left').addEventListener('click', function(){ - game.action(1); - }) - keyboard.querySelector('.right').addEventListener('click', function(){ - game.action(2); - }) -} - -loadWeights("assets/bson/dqn.bson", document.querySelector('.board'), __init__, model); - - diff --git a/experiments/cartPole/assets/red__left_arrow.png b/experiments/cartPole/assets/red__left_arrow.png deleted file mode 100644 index 970855c7..00000000 Binary files a/experiments/cartPole/assets/red__left_arrow.png and /dev/null differ diff --git a/experiments/cartPole/assets/red__right_arrow.png b/experiments/cartPole/assets/red__right_arrow.png deleted file mode 100644 index 19cc4b69..00000000 Binary files a/experiments/cartPole/assets/red__right_arrow.png and /dev/null differ diff --git a/experiments/cartPole/index.html b/experiments/cartPole/index.html deleted file mode 100644 index 506a91af..00000000 --- a/experiments/cartPole/index.html +++ /dev/null @@ -1,49 +0,0 @@ ---- -layout: default ---- - - - - - - - - - - - -
-
-

Flux Experiment: CartPole Game

-
-
-
CartPole
-
-
Easy
-
Hard
-
-
-
-
-
-
-
-
-

Instructions

-

A pole is attached by an un-actuated joint to a cart, which moves along a frictionless track. Use the arrow keys to apply a force on the cart. The pendulum starts upright, and the goal is to prevent it from falling over. A score of +1 is provided for every move that the pole remains upright. The game ends when the pole is more than 15 degrees from vertical, or the cart touches the edges.

- -
-
-
-
- - - - - - - - - - - diff --git a/experiments/chess/assets/chessboardjs/LICENSE.txt b/experiments/chess/assets/chessboardjs/LICENSE.txt deleted file mode 100644 index 4d3575ea..00000000 --- a/experiments/chess/assets/chessboardjs/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -Copyright 2013 Chris Oakman -http://chessboardjs.com/ - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/experiments/chess/assets/chessboardjs/css/chessboard-0.3.0.css b/experiments/chess/assets/chessboardjs/css/chessboard-0.3.0.css deleted file mode 100644 index e987b528..00000000 --- a/experiments/chess/assets/chessboardjs/css/chessboard-0.3.0.css +++ /dev/null @@ -1,70 +0,0 @@ -/*! - * chessboard.js v0.3.0 - * - * Copyright 2013 Chris Oakman - * Released under the MIT license - * https://github.com/oakmac/chessboardjs/blob/master/LICENSE - * - * Date: 10 Aug 2013 - */ - -/* clearfix */ -.clearfix-7da63 { - clear: both; -} - -/* board */ -.board-b72b1 { - border: 2px solid #404040; - -moz-box-sizing: content-box; - box-sizing: content-box; -} - -/* square */ -.square-55d63 { - float: left; - position: relative; - - /* disable any native browser highlighting */ - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -/* white square */ -.white-1e1d7 { - background-color: #f0d9b5; - color: #b58863; -} - -/* black square */ -.black-3c85d { - background-color: #b58863; - color: #f0d9b5; -} - -/* highlighted square */ -.highlight1-32417, .highlight2-9c5d2 { - -webkit-box-shadow: inset 0 0 3px 3px yellow; - -moz-box-shadow: inset 0 0 3px 3px yellow; - box-shadow: inset 0 0 3px 3px yellow; -} - -/* notation */ -.notation-322f9 { - cursor: default; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - position: absolute; -} -.alpha-d2270 { - bottom: 1px; - right: 3px; -} -.numeric-fc462 { - top: 2px; - left: 2px; -} \ No newline at end of file diff --git a/experiments/chess/assets/chessboardjs/css/chessboard-0.3.0.min.css b/experiments/chess/assets/chessboardjs/css/chessboard-0.3.0.min.css deleted file mode 100644 index ae68ca06..00000000 --- a/experiments/chess/assets/chessboardjs/css/chessboard-0.3.0.min.css +++ /dev/null @@ -1,2 +0,0 @@ -/*! chessboard.js v0.3.0 | (c) 2013 Chris Oakman | MIT License chessboardjs.com/license */ -.clearfix-7da63{clear:both}.board-b72b1{border:2px solid #fff;-moz-box-sizing:content-box;box-sizing:content-box}.square-55d63{float:left;position:relative;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.white-1e1d7{background-color:#f0d9b5;color:#b58863}.black-3c85d{background-color:#b58863;color:#f0d9b5}.highlight1-32417,.highlight2-9c5d2{-webkit-box-shadow:inset 0 0 3px 3px yellow;-moz-box-shadow:inset 0 0 3px 3px yellow;box-shadow:inset 0 0 3px 3px yellow}.notation-322f9{cursor:default;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;position:absolute}.alpha-d2270{bottom:1px;right:3px}.numeric-fc462{top:2px;left:2px} \ No newline at end of file diff --git a/experiments/chess/assets/chessboardjs/js/chessboard-0.3.0.js b/experiments/chess/assets/chessboardjs/js/chessboard-0.3.0.js deleted file mode 100644 index 8f1ac2d4..00000000 --- a/experiments/chess/assets/chessboardjs/js/chessboard-0.3.0.js +++ /dev/null @@ -1,1714 +0,0 @@ -/*! - * chessboard.js v0.3.0 - * - * Copyright 2013 Chris Oakman - * Released under the MIT license - * http://chessboardjs.com/license - * - * Date: 10 Aug 2013 - */ - -// start anonymous scope -;(function() { -'use strict'; - -//------------------------------------------------------------------------------ -// Chess Util Functions -//------------------------------------------------------------------------------ -var COLUMNS = 'abcdefgh'.split(''); - -function validMove(move) { - // move should be a string - if (typeof move !== 'string') return false; - - // move should be in the form of "e2-e4", "f6-d5" - var tmp = move.split('-'); - if (tmp.length !== 2) return false; - - return (validSquare(tmp[0]) === true && validSquare(tmp[1]) === true); -} - -function validSquare(square) { - if (typeof square !== 'string') return false; - return (square.search(/^[a-h][1-8]$/) !== -1); -} - -function validPieceCode(code) { - if (typeof code !== 'string') return false; - return (code.search(/^[bw][KQRNBP]$/) !== -1); -} - -// TODO: this whole function could probably be replaced with a single regex -function validFen(fen) { - if (typeof fen !== 'string') return false; - - // cut off any move, castling, etc info from the end - // we're only interested in position information - fen = fen.replace(/ .+$/, ''); - - // FEN should be 8 sections separated by slashes - var chunks = fen.split('/'); - if (chunks.length !== 8) return false; - - // check the piece sections - for (var i = 0; i < 8; i++) { - if (chunks[i] === '' || - chunks[i].length > 8 || - chunks[i].search(/[^kqrbnpKQRNBP1-8]/) !== -1) { - return false; - } - } - - return true; -} - -function validPositionObject(pos) { - if (typeof pos !== 'object') return false; - - for (var i in pos) { - if (pos.hasOwnProperty(i) !== true) continue; - - if (validSquare(i) !== true || validPieceCode(pos[i]) !== true) { - return false; - } - } - - return true; -} - -// convert FEN piece code to bP, wK, etc -function fenToPieceCode(piece) { - // black piece - if (piece.toLowerCase() === piece) { - return 'b' + piece.toUpperCase(); - } - - // white piece - return 'w' + piece.toUpperCase(); -} - -// convert bP, wK, etc code to FEN structure -function pieceCodeToFen(piece) { - var tmp = piece.split(''); - - // white piece - if (tmp[0] === 'w') { - return tmp[1].toUpperCase(); - } - - // black piece - return tmp[1].toLowerCase(); -} - -// convert FEN string to position object -// returns false if the FEN string is invalid -function fenToObj(fen) { - if (validFen(fen) !== true) { - return false; - } - - // cut off any move, castling, etc info from the end - // we're only interested in position information - fen = fen.replace(/ .+$/, ''); - - var rows = fen.split('/'); - var position = {}; - - var currentRow = 8; - for (var i = 0; i < 8; i++) { - var row = rows[i].split(''); - var colIndex = 0; - - // loop through each character in the FEN section - for (var j = 0; j < row.length; j++) { - // number / empty squares - if (row[j].search(/[1-8]/) !== -1) { - var emptySquares = parseInt(row[j], 10); - colIndex += emptySquares; - } - // piece - else { - var square = COLUMNS[colIndex] + currentRow; - position[square] = fenToPieceCode(row[j]); - colIndex++; - } - } - - currentRow--; - } - - return position; -} - -// position object to FEN string -// returns false if the obj is not a valid position object -function objToFen(obj) { - if (validPositionObject(obj) !== true) { - return false; - } - - var fen = ''; - - var currentRow = 8; - for (var i = 0; i < 8; i++) { - for (var j = 0; j < 8; j++) { - var square = COLUMNS[j] + currentRow; - - // piece exists - if (obj.hasOwnProperty(square) === true) { - fen += pieceCodeToFen(obj[square]); - } - - // empty space - else { - fen += '1'; - } - } - - if (i !== 7) { - fen += '/'; - } - - currentRow--; - } - - // squeeze the numbers together - // haha, I love this solution... - fen = fen.replace(/11111111/g, '8'); - fen = fen.replace(/1111111/g, '7'); - fen = fen.replace(/111111/g, '6'); - fen = fen.replace(/11111/g, '5'); - fen = fen.replace(/1111/g, '4'); - fen = fen.replace(/111/g, '3'); - fen = fen.replace(/11/g, '2'); - - return fen; -} - -window['ChessBoard'] = window['ChessBoard'] || function(containerElOrId, cfg) { -'use strict'; - -cfg = cfg || {}; - -//------------------------------------------------------------------------------ -// Constants -//------------------------------------------------------------------------------ - -var MINIMUM_JQUERY_VERSION = '1.7.0', - START_FEN = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR', - START_POSITION = fenToObj(START_FEN); - -// use unique class names to prevent clashing with anything else on the page -// and simplify selectors -var CSS = { - alpha: 'alpha-d2270', - black: 'black-3c85d', - board: 'board-b72b1', - chessboard: 'chessboard-63f37', - clearfix: 'clearfix-7da63', - highlight1: 'highlight1-32417', - highlight2: 'highlight2-9c5d2', - notation: 'notation-322f9', - numeric: 'numeric-fc462', - piece: 'piece-417db', - row: 'row-5277c', - sparePieces: 'spare-pieces-7492f', - sparePiecesBottom: 'spare-pieces-bottom-ae20f', - sparePiecesTop: 'spare-pieces-top-4028b', - square: 'square-55d63', - white: 'white-1e1d7' -}; - -//------------------------------------------------------------------------------ -// Module Scope Variables -//------------------------------------------------------------------------------ - -// DOM elements -var containerEl, - boardEl, - draggedPieceEl, - sparePiecesTopEl, - sparePiecesBottomEl; - -// constructor return object -var widget = {}; - -//------------------------------------------------------------------------------ -// Stateful -//------------------------------------------------------------------------------ - -var ANIMATION_HAPPENING = false, - BOARD_BORDER_SIZE = 2, - CURRENT_ORIENTATION = 'white', - CURRENT_POSITION = {}, - SQUARE_SIZE, - DRAGGED_PIECE, - DRAGGED_PIECE_LOCATION, - DRAGGED_PIECE_SOURCE, - DRAGGING_A_PIECE = false, - SPARE_PIECE_ELS_IDS = {}, - SQUARE_ELS_IDS = {}, - SQUARE_ELS_OFFSETS; - -//------------------------------------------------------------------------------ -// JS Util Functions -//------------------------------------------------------------------------------ - -// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript -function createId() { - return 'xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx'.replace(/x/g, function(c) { - var r = Math.random() * 16 | 0; - return r.toString(16); - }); -} - -function deepCopy(thing) { - return JSON.parse(JSON.stringify(thing)); -} - -function parseSemVer(version) { - var tmp = version.split('.'); - return { - major: parseInt(tmp[0], 10), - minor: parseInt(tmp[1], 10), - patch: parseInt(tmp[2], 10) - }; -} - -// returns true if version is >= minimum -function compareSemVer(version, minimum) { - version = parseSemVer(version); - minimum = parseSemVer(minimum); - - var versionNum = (version.major * 10000 * 10000) + - (version.minor * 10000) + version.patch; - var minimumNum = (minimum.major * 10000 * 10000) + - (minimum.minor * 10000) + minimum.patch; - - return (versionNum >= minimumNum); -} - -//------------------------------------------------------------------------------ -// Validation / Errors -//------------------------------------------------------------------------------ - -function error(code, msg, obj) { - // do nothing if showErrors is not set - if (cfg.hasOwnProperty('showErrors') !== true || - cfg.showErrors === false) { - return; - } - - var errorText = 'ChessBoard Error ' + code + ': ' + msg; - - // print to console - if (cfg.showErrors === 'console' && - typeof console === 'object' && - typeof console.log === 'function') { - console.log(errorText); - if (arguments.length >= 2) { - console.log(obj); - } - return; - } - - // alert errors - if (cfg.showErrors === 'alert') { - if (obj) { - errorText += '\n\n' + JSON.stringify(obj); - } - window.alert(errorText); - return; - } - - // custom function - if (typeof cfg.showErrors === 'function') { - cfg.showErrors(code, msg, obj); - } -} - -// check dependencies -function checkDeps() { - // if containerId is a string, it must be the ID of a DOM node - if (typeof containerElOrId === 'string') { - // cannot be empty - if (containerElOrId === '') { - window.alert('ChessBoard Error 1001: ' + - 'The first argument to ChessBoard() cannot be an empty string.' + - '\n\nExiting...'); - return false; - } - - // make sure the container element exists in the DOM - var el = document.getElementById(containerElOrId); - if (! el) { - window.alert('ChessBoard Error 1002: Element with id "' + - containerElOrId + '" does not exist in the DOM.' + - '\n\nExiting...'); - return false; - } - - // set the containerEl - containerEl = $(el); - } - - // else it must be something that becomes a jQuery collection - // with size 1 - // ie: a single DOM node or jQuery object - else { - containerEl = $(containerElOrId); - - if (containerEl.length !== 1) { - window.alert('ChessBoard Error 1003: The first argument to ' + - 'ChessBoard() must be an ID or a single DOM node.' + - '\n\nExiting...'); - return false; - } - } - - // JSON must exist - if (! window.JSON || - typeof JSON.stringify !== 'function' || - typeof JSON.parse !== 'function') { - window.alert('ChessBoard Error 1004: JSON does not exist. ' + - 'Please include a JSON polyfill.\n\nExiting...'); - return false; - } - - // check for a compatible version of jQuery - if (! (typeof window.$ && $.fn && $.fn.jquery && - compareSemVer($.fn.jquery, MINIMUM_JQUERY_VERSION) === true)) { - window.alert('ChessBoard Error 1005: Unable to find a valid version ' + - 'of jQuery. Please include jQuery ' + MINIMUM_JQUERY_VERSION + ' or ' + - 'higher on the page.\n\nExiting...'); - return false; - } - - return true; -} - -function validAnimationSpeed(speed) { - if (speed === 'fast' || speed === 'slow') { - return true; - } - - if ((parseInt(speed, 10) + '') !== (speed + '')) { - return false; - } - - return (speed >= 0); -} - -// validate config / set default options -function expandConfig() { - if (typeof cfg === 'string' || validPositionObject(cfg) === true) { - cfg = { - position: cfg - }; - } - - // default for orientation is white - if (cfg.orientation !== 'black') { - cfg.orientation = 'white'; - } - CURRENT_ORIENTATION = cfg.orientation; - - // default for showNotation is true - if (cfg.showNotation !== false) { - cfg.showNotation = true; - } - - // default for draggable is false - if (cfg.draggable !== true) { - cfg.draggable = false; - } - - // default for dropOffBoard is 'snapback' - if (cfg.dropOffBoard !== 'trash') { - cfg.dropOffBoard = 'snapback'; - } - - // default for sparePieces is false - if (cfg.sparePieces !== true) { - cfg.sparePieces = false; - } - - // draggable must be true if sparePieces is enabled - if (cfg.sparePieces === true) { - cfg.draggable = true; - } - - // default piece theme is wikipedia - if (cfg.hasOwnProperty('pieceTheme') !== true || - (typeof cfg.pieceTheme !== 'string' && - typeof cfg.pieceTheme !== 'function')) { - cfg.pieceTheme = 'img/chesspieces/wikipedia/{piece}.png'; - } - - // animation speeds - if (cfg.hasOwnProperty('appearSpeed') !== true || - validAnimationSpeed(cfg.appearSpeed) !== true) { - cfg.appearSpeed = 200; - } - if (cfg.hasOwnProperty('moveSpeed') !== true || - validAnimationSpeed(cfg.moveSpeed) !== true) { - cfg.moveSpeed = 200; - } - if (cfg.hasOwnProperty('snapbackSpeed') !== true || - validAnimationSpeed(cfg.snapbackSpeed) !== true) { - cfg.snapbackSpeed = 50; - } - if (cfg.hasOwnProperty('snapSpeed') !== true || - validAnimationSpeed(cfg.snapSpeed) !== true) { - cfg.snapSpeed = 25; - } - if (cfg.hasOwnProperty('trashSpeed') !== true || - validAnimationSpeed(cfg.trashSpeed) !== true) { - cfg.trashSpeed = 100; - } - - // make sure position is valid - if (cfg.hasOwnProperty('position') === true) { - if (cfg.position === 'start') { - CURRENT_POSITION = deepCopy(START_POSITION); - } - - else if (validFen(cfg.position) === true) { - CURRENT_POSITION = fenToObj(cfg.position); - } - - else if (validPositionObject(cfg.position) === true) { - CURRENT_POSITION = deepCopy(cfg.position); - } - - else { - error(7263, 'Invalid value passed to config.position.', cfg.position); - } - } - - return true; -} - -//------------------------------------------------------------------------------ -// DOM Misc -//------------------------------------------------------------------------------ - -// calculates square size based on the width of the container -// got a little CSS black magic here, so let me explain: -// get the width of the container element (could be anything), reduce by 1 for -// fudge factor, and then keep reducing until we find an exact mod 8 for -// our square size -function calculateSquareSize() { - var containerWidth = parseInt(containerEl.css('width'), 10); - - // defensive, prevent infinite loop - if (! containerWidth || containerWidth <= 0) { - return 0; - } - - // pad one pixel - var boardWidth = containerWidth - 1; - - while (boardWidth % 8 !== 0 && boardWidth > 0) { - boardWidth--; - } - - return (boardWidth / 8); -} - -// create random IDs for elements -function createElIds() { - // squares on the board - for (var i = 0; i < COLUMNS.length; i++) { - for (var j = 1; j <= 8; j++) { - var square = COLUMNS[i] + j; - SQUARE_ELS_IDS[square] = square + '-' + createId(); - } - } - - // spare pieces - var pieces = 'KQRBNP'.split(''); - for (var i = 0; i < pieces.length; i++) { - var whitePiece = 'w' + pieces[i]; - var blackPiece = 'b' + pieces[i]; - SPARE_PIECE_ELS_IDS[whitePiece] = whitePiece + '-' + createId(); - SPARE_PIECE_ELS_IDS[blackPiece] = blackPiece + '-' + createId(); - } -} - -//------------------------------------------------------------------------------ -// Markup Building -//------------------------------------------------------------------------------ - -function buildBoardContainer() { - var html = '
'; - - if (cfg.sparePieces === true) { - html += '
'; - } - - html += '
'; - - if (cfg.sparePieces === true) { - html += '
'; - } - - html += '
'; - - return html; -} - -/* -var buildSquare = function(color, size, id) { - var html = '
'; - - if (cfg.showNotation === true) { - - } - - html += '
'; - - return html; -}; -*/ - -function buildBoard(orientation) { - if (orientation !== 'black') { - orientation = 'white'; - } - - var html = ''; - - // algebraic notation / orientation - var alpha = deepCopy(COLUMNS); - var row = 8; - if (orientation === 'black') { - alpha.reverse(); - row = 1; - } - - var squareColor = 'white'; - for (var i = 0; i < 8; i++) { - html += '
'; - for (var j = 0; j < 8; j++) { - var square = alpha[j] + row; - - html += '
'; - - if (cfg.showNotation === true) { - // alpha notation - if ((orientation === 'white' && row === 1) || - (orientation === 'black' && row === 8)) { - html += '
' + - alpha[j] + '
'; - } - - // numeric notation - if (j === 0) { - html += '
' + - row + '
'; - } - } - - html += '
'; // end .square - - squareColor = (squareColor === 'white' ? 'black' : 'white'); - } - html += '
'; - - squareColor = (squareColor === 'white' ? 'black' : 'white'); - - if (orientation === 'white') { - row--; - } - else { - row++; - } - } - - return html; -} - -function buildPieceImgSrc(piece) { - if (typeof cfg.pieceTheme === 'function') { - return cfg.pieceTheme(piece); - } - - if (typeof cfg.pieceTheme === 'string') { - return cfg.pieceTheme.replace(/{piece}/g, piece); - } - - // NOTE: this should never happen - error(8272, 'Unable to build image source for cfg.pieceTheme.'); - return ''; -} - -function buildPiece(piece, hidden, id) { - var html = ''; - - return html; -} - -function buildSparePieces(color) { - var pieces = ['wK', 'wQ', 'wR', 'wB', 'wN', 'wP']; - if (color === 'black') { - pieces = ['bK', 'bQ', 'bR', 'bB', 'bN', 'bP']; - } - - var html = ''; - for (var i = 0; i < pieces.length; i++) { - html += buildPiece(pieces[i], false, SPARE_PIECE_ELS_IDS[pieces[i]]); - } - - return html; -} - -//------------------------------------------------------------------------------ -// Animations -//------------------------------------------------------------------------------ - -function animateSquareToSquare(src, dest, piece, completeFn) { - // get information about the source and destination squares - var srcSquareEl = $('#' + SQUARE_ELS_IDS[src]); - var srcSquarePosition = srcSquareEl.offset(); - var destSquareEl = $('#' + SQUARE_ELS_IDS[dest]); - var destSquarePosition = destSquareEl.offset(); - - // create the animated piece and absolutely position it - // over the source square - var animatedPieceId = createId(); - $('body').append(buildPiece(piece, true, animatedPieceId)); - var animatedPieceEl = $('#' + animatedPieceId); - animatedPieceEl.css({ - display: '', - position: 'absolute', - top: srcSquarePosition.top, - left: srcSquarePosition.left - }); - - // remove original piece from source square - srcSquareEl.find('.' + CSS.piece).remove(); - - // on complete - var complete = function() { - // add the "real" piece to the destination square - destSquareEl.append(buildPiece(piece)); - - // remove the animated piece - animatedPieceEl.remove(); - - // run complete function - if (typeof completeFn === 'function') { - completeFn(); - } - }; - - // animate the piece to the destination square - var opts = { - duration: cfg.moveSpeed, - complete: complete - }; - animatedPieceEl.animate(destSquarePosition, opts); -} - -function animateSparePieceToSquare(piece, dest, completeFn) { - var srcOffset = $('#' + SPARE_PIECE_ELS_IDS[piece]).offset(); - var destSquareEl = $('#' + SQUARE_ELS_IDS[dest]); - var destOffset = destSquareEl.offset(); - - // create the animate piece - var pieceId = createId(); - $('body').append(buildPiece(piece, true, pieceId)); - var animatedPieceEl = $('#' + pieceId); - animatedPieceEl.css({ - display: '', - position: 'absolute', - left: srcOffset.left, - top: srcOffset.top - }); - - // on complete - var complete = function() { - // add the "real" piece to the destination square - destSquareEl.find('.' + CSS.piece).remove(); - destSquareEl.append(buildPiece(piece)); - - // remove the animated piece - animatedPieceEl.remove(); - - // run complete function - if (typeof completeFn === 'function') { - completeFn(); - } - }; - - // animate the piece to the destination square - var opts = { - duration: cfg.moveSpeed, - complete: complete - }; - animatedPieceEl.animate(destOffset, opts); -} - -// execute an array of animations -function doAnimations(a, oldPos, newPos) { - ANIMATION_HAPPENING = true; - - var numFinished = 0; - function onFinish() { - numFinished++; - - // exit if all the animations aren't finished - if (numFinished !== a.length) return; - - drawPositionInstant(); - ANIMATION_HAPPENING = false; - - // run their onMoveEnd function - if (cfg.hasOwnProperty('onMoveEnd') === true && - typeof cfg.onMoveEnd === 'function') { - cfg.onMoveEnd(deepCopy(oldPos), deepCopy(newPos)); - } - } - - for (var i = 0; i < a.length; i++) { - // clear a piece - if (a[i].type === 'clear') { - $('#' + SQUARE_ELS_IDS[a[i].square] + ' .' + CSS.piece) - .fadeOut(cfg.trashSpeed, onFinish); - } - - // add a piece (no spare pieces) - if (a[i].type === 'add' && cfg.sparePieces !== true) { - $('#' + SQUARE_ELS_IDS[a[i].square]) - .append(buildPiece(a[i].piece, true)) - .find('.' + CSS.piece) - .fadeIn(cfg.appearSpeed, onFinish); - } - - // add a piece from a spare piece - if (a[i].type === 'add' && cfg.sparePieces === true) { - animateSparePieceToSquare(a[i].piece, a[i].square, onFinish); - } - - // move a piece - if (a[i].type === 'move') { - animateSquareToSquare(a[i].source, a[i].destination, a[i].piece, - onFinish); - } - } -} - -// returns the distance between two squares -function squareDistance(s1, s2) { - s1 = s1.split(''); - var s1x = COLUMNS.indexOf(s1[0]) + 1; - var s1y = parseInt(s1[1], 10); - - s2 = s2.split(''); - var s2x = COLUMNS.indexOf(s2[0]) + 1; - var s2y = parseInt(s2[1], 10); - - var xDelta = Math.abs(s1x - s2x); - var yDelta = Math.abs(s1y - s2y); - - if (xDelta >= yDelta) return xDelta; - return yDelta; -} - -// returns an array of closest squares from square -function createRadius(square) { - var squares = []; - - // calculate distance of all squares - for (var i = 0; i < 8; i++) { - for (var j = 0; j < 8; j++) { - var s = COLUMNS[i] + (j + 1); - - // skip the square we're starting from - if (square === s) continue; - - squares.push({ - square: s, - distance: squareDistance(square, s) - }); - } - } - - // sort by distance - squares.sort(function(a, b) { - return a.distance - b.distance; - }); - - // just return the square code - var squares2 = []; - for (var i = 0; i < squares.length; i++) { - squares2.push(squares[i].square); - } - - return squares2; -} - -// returns the square of the closest instance of piece -// returns false if no instance of piece is found in position -function findClosestPiece(position, piece, square) { - // create array of closest squares from square - var closestSquares = createRadius(square); - - // search through the position in order of distance for the piece - for (var i = 0; i < closestSquares.length; i++) { - var s = closestSquares[i]; - - if (position.hasOwnProperty(s) === true && position[s] === piece) { - return s; - } - } - - return false; -} - -// calculate an array of animations that need to happen in order to get -// from pos1 to pos2 -function calculateAnimations(pos1, pos2) { - // make copies of both - pos1 = deepCopy(pos1); - pos2 = deepCopy(pos2); - - var animations = []; - var squaresMovedTo = {}; - - // remove pieces that are the same in both positions - for (var i in pos2) { - if (pos2.hasOwnProperty(i) !== true) continue; - - if (pos1.hasOwnProperty(i) === true && pos1[i] === pos2[i]) { - delete pos1[i]; - delete pos2[i]; - } - } - - // find all the "move" animations - for (var i in pos2) { - if (pos2.hasOwnProperty(i) !== true) continue; - - var closestPiece = findClosestPiece(pos1, pos2[i], i); - if (closestPiece !== false) { - animations.push({ - type: 'move', - source: closestPiece, - destination: i, - piece: pos2[i] - }); - - delete pos1[closestPiece]; - delete pos2[i]; - squaresMovedTo[i] = true; - } - } - - // add pieces to pos2 - for (var i in pos2) { - if (pos2.hasOwnProperty(i) !== true) continue; - - animations.push({ - type: 'add', - square: i, - piece: pos2[i] - }) - - delete pos2[i]; - } - - // clear pieces from pos1 - for (var i in pos1) { - if (pos1.hasOwnProperty(i) !== true) continue; - - // do not clear a piece if it is on a square that is the result - // of a "move", ie: a piece capture - if (squaresMovedTo.hasOwnProperty(i) === true) continue; - - animations.push({ - type: 'clear', - square: i, - piece: pos1[i] - }); - - delete pos1[i]; - } - - return animations; -} - -//------------------------------------------------------------------------------ -// Control Flow -//------------------------------------------------------------------------------ - -function drawPositionInstant() { - // clear the board - boardEl.find('.' + CSS.piece).remove(); - - // add the pieces - for (var i in CURRENT_POSITION) { - if (CURRENT_POSITION.hasOwnProperty(i) !== true) continue; - - $('#' + SQUARE_ELS_IDS[i]).append(buildPiece(CURRENT_POSITION[i])); - } -} - -function drawBoard() { - boardEl.html(buildBoard(CURRENT_ORIENTATION)); - drawPositionInstant(); - - if (cfg.sparePieces === true) { - if (CURRENT_ORIENTATION === 'white') { - sparePiecesTopEl.html(buildSparePieces('black')); - sparePiecesBottomEl.html(buildSparePieces('white')); - } - else { - sparePiecesTopEl.html(buildSparePieces('white')); - sparePiecesBottomEl.html(buildSparePieces('black')); - } - } -} - -// given a position and a set of moves, return a new position -// with the moves executed -function calculatePositionFromMoves(position, moves) { - position = deepCopy(position); - - for (var i in moves) { - if (moves.hasOwnProperty(i) !== true) continue; - - // skip the move if the position doesn't have a piece on the source square - if (position.hasOwnProperty(i) !== true) continue; - - var piece = position[i]; - delete position[i]; - position[moves[i]] = piece; - } - - return position; -} - -function setCurrentPosition(position) { - var oldPos = deepCopy(CURRENT_POSITION); - var newPos = deepCopy(position); - var oldFen = objToFen(oldPos); - var newFen = objToFen(newPos); - - // do nothing if no change in position - if (oldFen === newFen) return; - - // run their onChange function - if (cfg.hasOwnProperty('onChange') === true && - typeof cfg.onChange === 'function') { - cfg.onChange(oldPos, newPos); - } - - // update state - CURRENT_POSITION = position; -} - -function isXYOnSquare(x, y) { - for (var i in SQUARE_ELS_OFFSETS) { - if (SQUARE_ELS_OFFSETS.hasOwnProperty(i) !== true) continue; - - var s = SQUARE_ELS_OFFSETS[i]; - if (x >= s.left && x < s.left + SQUARE_SIZE && - y >= s.top && y < s.top + SQUARE_SIZE) { - return i; - } - } - - return 'offboard'; -} - -// records the XY coords of every square into memory -function captureSquareOffsets() { - SQUARE_ELS_OFFSETS = {}; - - for (var i in SQUARE_ELS_IDS) { - if (SQUARE_ELS_IDS.hasOwnProperty(i) !== true) continue; - - SQUARE_ELS_OFFSETS[i] = $('#' + SQUARE_ELS_IDS[i]).offset(); - } -} - -function removeSquareHighlights() { - boardEl.find('.' + CSS.square) - .removeClass(CSS.highlight1 + ' ' + CSS.highlight2); -} - -function snapbackDraggedPiece() { - // there is no "snapback" for spare pieces - if (DRAGGED_PIECE_SOURCE === 'spare') { - trashDraggedPiece(); - return; - } - - removeSquareHighlights(); - - // animation complete - function complete() { - drawPositionInstant(); - draggedPieceEl.css('display', 'none'); - - // run their onSnapbackEnd function - if (cfg.hasOwnProperty('onSnapbackEnd') === true && - typeof cfg.onSnapbackEnd === 'function') { - cfg.onSnapbackEnd(DRAGGED_PIECE, DRAGGED_PIECE_SOURCE, - deepCopy(CURRENT_POSITION), CURRENT_ORIENTATION); - } - } - - // get source square position - var sourceSquarePosition = - $('#' + SQUARE_ELS_IDS[DRAGGED_PIECE_SOURCE]).offset(); - - // animate the piece to the target square - var opts = { - duration: cfg.snapbackSpeed, - complete: complete - }; - draggedPieceEl.animate(sourceSquarePosition, opts); - - // set state - DRAGGING_A_PIECE = false; -} - -function trashDraggedPiece() { - removeSquareHighlights(); - - // remove the source piece - var newPosition = deepCopy(CURRENT_POSITION); - delete newPosition[DRAGGED_PIECE_SOURCE]; - setCurrentPosition(newPosition); - - // redraw the position - drawPositionInstant(); - - // hide the dragged piece - draggedPieceEl.fadeOut(cfg.trashSpeed); - - // set state - DRAGGING_A_PIECE = false; -} - -function dropDraggedPieceOnSquare(square) { - removeSquareHighlights(); - - // update position - var newPosition = deepCopy(CURRENT_POSITION); - delete newPosition[DRAGGED_PIECE_SOURCE]; - newPosition[square] = DRAGGED_PIECE; - setCurrentPosition(newPosition); - - // get target square information - var targetSquarePosition = $('#' + SQUARE_ELS_IDS[square]).offset(); - - // animation complete - var complete = function() { - drawPositionInstant(); - draggedPieceEl.css('display', 'none'); - - // execute their onSnapEnd function - if (cfg.hasOwnProperty('onSnapEnd') === true && - typeof cfg.onSnapEnd === 'function') { - cfg.onSnapEnd(DRAGGED_PIECE_SOURCE, square, DRAGGED_PIECE); - } - }; - - // snap the piece to the target square - var opts = { - duration: cfg.snapSpeed, - complete: complete - }; - draggedPieceEl.animate(targetSquarePosition, opts); - - // set state - DRAGGING_A_PIECE = false; -} - -function beginDraggingPiece(source, piece, x, y) { - // run their custom onDragStart function - // their custom onDragStart function can cancel drag start - if (typeof cfg.onDragStart === 'function' && - cfg.onDragStart(source, piece, - deepCopy(CURRENT_POSITION), CURRENT_ORIENTATION) === false) { - return; - } - - // set state - DRAGGING_A_PIECE = true; - DRAGGED_PIECE = piece; - DRAGGED_PIECE_SOURCE = source; - - // if the piece came from spare pieces, location is offboard - if (source === 'spare') { - DRAGGED_PIECE_LOCATION = 'offboard'; - } - else { - DRAGGED_PIECE_LOCATION = source; - } - - // capture the x, y coords of all squares in memory - captureSquareOffsets(); - - // create the dragged piece - draggedPieceEl.attr('src', buildPieceImgSrc(piece)) - .css({ - display: '', - position: 'absolute', - left: x - (SQUARE_SIZE / 2), - top: y - (SQUARE_SIZE / 2) - }); - - if (source !== 'spare') { - // highlight the source square and hide the piece - $('#' + SQUARE_ELS_IDS[source]).addClass(CSS.highlight1) - .find('.' + CSS.piece).css('display', 'none'); - } -} - -function updateDraggedPiece(x, y) { - // put the dragged piece over the mouse cursor - draggedPieceEl.css({ - left: x - (SQUARE_SIZE / 2), - top: y - (SQUARE_SIZE / 2) - }); - - // get location - var location = isXYOnSquare(x, y); - - // do nothing if the location has not changed - if (location === DRAGGED_PIECE_LOCATION) return; - - // remove highlight from previous square - if (validSquare(DRAGGED_PIECE_LOCATION) === true) { - $('#' + SQUARE_ELS_IDS[DRAGGED_PIECE_LOCATION]) - .removeClass(CSS.highlight2); - } - - // add highlight to new square - if (validSquare(location) === true) { - $('#' + SQUARE_ELS_IDS[location]).addClass(CSS.highlight2); - } - - // run onDragMove - if (typeof cfg.onDragMove === 'function') { - cfg.onDragMove(location, DRAGGED_PIECE_LOCATION, - DRAGGED_PIECE_SOURCE, DRAGGED_PIECE, - deepCopy(CURRENT_POSITION), CURRENT_ORIENTATION); - } - - // update state - DRAGGED_PIECE_LOCATION = location; -} - -function stopDraggedPiece(location) { - // determine what the action should be - var action = 'drop'; - if (location === 'offboard' && cfg.dropOffBoard === 'snapback') { - action = 'snapback'; - } - if (location === 'offboard' && cfg.dropOffBoard === 'trash') { - action = 'trash'; - } - - // run their onDrop function, which can potentially change the drop action - if (cfg.hasOwnProperty('onDrop') === true && - typeof cfg.onDrop === 'function') { - var newPosition = deepCopy(CURRENT_POSITION); - - // source piece is a spare piece and position is off the board - //if (DRAGGED_PIECE_SOURCE === 'spare' && location === 'offboard') {...} - // position has not changed; do nothing - - // source piece is a spare piece and position is on the board - if (DRAGGED_PIECE_SOURCE === 'spare' && validSquare(location) === true) { - // add the piece to the board - newPosition[location] = DRAGGED_PIECE; - } - - // source piece was on the board and position is off the board - if (validSquare(DRAGGED_PIECE_SOURCE) === true && location === 'offboard') { - // remove the piece from the board - delete newPosition[DRAGGED_PIECE_SOURCE]; - } - - // source piece was on the board and position is on the board - if (validSquare(DRAGGED_PIECE_SOURCE) === true && - validSquare(location) === true) { - // move the piece - delete newPosition[DRAGGED_PIECE_SOURCE]; - newPosition[location] = DRAGGED_PIECE; - } - - var oldPosition = deepCopy(CURRENT_POSITION); - - var result = cfg.onDrop(DRAGGED_PIECE_SOURCE, location, DRAGGED_PIECE, - newPosition, oldPosition, CURRENT_ORIENTATION); - if (result === 'snapback' || result === 'trash') { - action = result; - } - } - - // do it! - if (action === 'snapback') { - snapbackDraggedPiece(); - } - else if (action === 'trash') { - trashDraggedPiece(); - } - else if (action === 'drop') { - dropDraggedPieceOnSquare(location); - } -} - -//------------------------------------------------------------------------------ -// Public Methods -//------------------------------------------------------------------------------ - -// clear the board -widget.clear = function(useAnimation) { - widget.position({}, useAnimation); -}; - -/* -// get or set config properties -// TODO: write this, GitHub Issue #1 -widget.config = function(arg1, arg2) { - // get the current config - if (arguments.length === 0) { - return deepCopy(cfg); - } -}; -*/ - -// remove the widget from the page -widget.destroy = function() { - // remove markup - containerEl.html(''); - draggedPieceEl.remove(); - - // remove event handlers - containerEl.unbind(); -}; - -// shorthand method to get the current FEN -widget.fen = function() { - return widget.position('fen'); -}; - -// flip orientation -widget.flip = function() { - widget.orientation('flip'); -}; - -/* -// TODO: write this, GitHub Issue #5 -widget.highlight = function() { - -}; -*/ - -// move pieces -widget.move = function() { - // no need to throw an error here; just do nothing - if (arguments.length === 0) return; - - var useAnimation = true; - - // collect the moves into an object - var moves = {}; - for (var i = 0; i < arguments.length; i++) { - // any "false" to this function means no animations - if (arguments[i] === false) { - useAnimation = false; - continue; - } - - // skip invalid arguments - if (validMove(arguments[i]) !== true) { - error(2826, 'Invalid move passed to the move method.', arguments[i]); - continue; - } - - var tmp = arguments[i].split('-'); - moves[tmp[0]] = tmp[1]; - } - - // calculate position from moves - var newPos = calculatePositionFromMoves(CURRENT_POSITION, moves); - - // update the board - widget.position(newPos, useAnimation); - - // return the new position object - return newPos; -}; - -widget.orientation = function(arg) { - // no arguments, return the current orientation - if (arguments.length === 0) { - return CURRENT_ORIENTATION; - } - - // set to white or black - if (arg === 'white' || arg === 'black') { - CURRENT_ORIENTATION = arg; - drawBoard(); - return; - } - - // flip orientation - if (arg === 'flip') { - CURRENT_ORIENTATION = (CURRENT_ORIENTATION === 'white') ? 'black' : 'white'; - drawBoard(); - return; - } - - error(5482, 'Invalid value passed to the orientation method.', arg); -}; - -widget.position = function(position, useAnimation) { - // no arguments, return the current position - if (arguments.length === 0) { - return deepCopy(CURRENT_POSITION); - } - - // get position as FEN - if (typeof position === 'string' && position.toLowerCase() === 'fen') { - return objToFen(CURRENT_POSITION); - } - - // default for useAnimations is true - if (useAnimation !== false) { - useAnimation = true; - } - - // start position - if (typeof position === 'string' && position.toLowerCase() === 'start') { - position = deepCopy(START_POSITION); - } - - // convert FEN to position object - if (validFen(position) === true) { - position = fenToObj(position); - } - - // validate position object - if (validPositionObject(position) !== true) { - error(6482, 'Invalid value passed to the position method.', position); - return; - } - - if (useAnimation === true) { - // start the animations - doAnimations(calculateAnimations(CURRENT_POSITION, position), - CURRENT_POSITION, position); - - // set the new position - setCurrentPosition(position); - } - // instant update - else { - setCurrentPosition(position); - drawPositionInstant(); - } -}; - -widget.resize = function() { - // calulate the new square size - SQUARE_SIZE = calculateSquareSize(); - - // set board width - boardEl.css('width', (SQUARE_SIZE * 8) + 'px'); - - // set drag piece size - draggedPieceEl.css({ - height: SQUARE_SIZE, - width: SQUARE_SIZE - }); - - // spare pieces - if (cfg.sparePieces === true) { - containerEl.find('.' + CSS.sparePieces) - .css('paddingLeft', (SQUARE_SIZE + BOARD_BORDER_SIZE) + 'px'); - } - - // redraw the board - drawBoard(); -}; - -// set the starting position -widget.start = function(useAnimation) { - widget.position('start', useAnimation); -}; - -//------------------------------------------------------------------------------ -// Browser Events -//------------------------------------------------------------------------------ - -function isTouchDevice() { - return ('ontouchstart' in document.documentElement); -} - -// reference: http://www.quirksmode.org/js/detect.html -function isMSIE() { - return (navigator && navigator.userAgent && - navigator.userAgent.search(/MSIE/) !== -1); -} - -function stopDefault(e) { - e.preventDefault(); -} - -function mousedownSquare(e) { - // do nothing if we're not draggable - if (cfg.draggable !== true) return; - - var square = $(this).attr('data-square'); - - // no piece on this square - if (validSquare(square) !== true || - CURRENT_POSITION.hasOwnProperty(square) !== true) { - return; - } - - beginDraggingPiece(square, CURRENT_POSITION[square], e.pageX, e.pageY); -} - -function touchstartSquare(e) { - // do nothing if we're not draggable - if (cfg.draggable !== true) return; - - var square = $(this).attr('data-square'); - - // no piece on this square - if (validSquare(square) !== true || - CURRENT_POSITION.hasOwnProperty(square) !== true) { - return; - } - - e = e.originalEvent; - beginDraggingPiece(square, CURRENT_POSITION[square], - e.changedTouches[0].pageX, e.changedTouches[0].pageY); -} - -function mousedownSparePiece(e) { - // do nothing if sparePieces is not enabled - if (cfg.sparePieces !== true) return; - - var piece = $(this).attr('data-piece'); - - beginDraggingPiece('spare', piece, e.pageX, e.pageY); -} - -function touchstartSparePiece(e) { - // do nothing if sparePieces is not enabled - if (cfg.sparePieces !== true) return; - - var piece = $(this).attr('data-piece'); - - e = e.originalEvent; - beginDraggingPiece('spare', piece, - e.changedTouches[0].pageX, e.changedTouches[0].pageY); -} - -function mousemoveWindow(e) { - // do nothing if we are not dragging a piece - if (DRAGGING_A_PIECE !== true) return; - - updateDraggedPiece(e.pageX, e.pageY); -} - -function touchmoveWindow(e) { - // do nothing if we are not dragging a piece - if (DRAGGING_A_PIECE !== true) return; - - // prevent screen from scrolling - e.preventDefault(); - - updateDraggedPiece(e.originalEvent.changedTouches[0].pageX, - e.originalEvent.changedTouches[0].pageY); -} - -function mouseupWindow(e) { - // do nothing if we are not dragging a piece - if (DRAGGING_A_PIECE !== true) return; - - // get the location - var location = isXYOnSquare(e.pageX, e.pageY); - - stopDraggedPiece(location); -} - -function touchendWindow(e) { - // do nothing if we are not dragging a piece - if (DRAGGING_A_PIECE !== true) return; - - // get the location - var location = isXYOnSquare(e.originalEvent.changedTouches[0].pageX, - e.originalEvent.changedTouches[0].pageY); - - stopDraggedPiece(location); -} - -function mouseenterSquare(e) { - // do not fire this event if we are dragging a piece - // NOTE: this should never happen, but it's a safeguard - if (DRAGGING_A_PIECE !== false) return; - - if (cfg.hasOwnProperty('onMouseoverSquare') !== true || - typeof cfg.onMouseoverSquare !== 'function') return; - - // get the square - var square = $(e.currentTarget).attr('data-square'); - - // NOTE: this should never happen; defensive - if (validSquare(square) !== true) return; - - // get the piece on this square - var piece = false; - if (CURRENT_POSITION.hasOwnProperty(square) === true) { - piece = CURRENT_POSITION[square]; - } - - // execute their function - cfg.onMouseoverSquare(square, piece, deepCopy(CURRENT_POSITION), - CURRENT_ORIENTATION); -} - -function mouseleaveSquare(e) { - // do not fire this event if we are dragging a piece - // NOTE: this should never happen, but it's a safeguard - if (DRAGGING_A_PIECE !== false) return; - - if (cfg.hasOwnProperty('onMouseoutSquare') !== true || - typeof cfg.onMouseoutSquare !== 'function') return; - - // get the square - var square = $(e.currentTarget).attr('data-square'); - - // NOTE: this should never happen; defensive - if (validSquare(square) !== true) return; - - // get the piece on this square - var piece = false; - if (CURRENT_POSITION.hasOwnProperty(square) === true) { - piece = CURRENT_POSITION[square]; - } - - // execute their function - cfg.onMouseoutSquare(square, piece, deepCopy(CURRENT_POSITION), - CURRENT_ORIENTATION); -} - -//------------------------------------------------------------------------------ -// Initialization -//------------------------------------------------------------------------------ - -function addEvents() { - // prevent browser "image drag" - $('body').on('mousedown mousemove', '.' + CSS.piece, stopDefault); - - // mouse drag pieces - boardEl.on('mousedown', '.' + CSS.square, mousedownSquare); - containerEl.on('mousedown', '.' + CSS.sparePieces + ' .' + CSS.piece, - mousedownSparePiece); - - // mouse enter / leave square - boardEl.on('mouseenter', '.' + CSS.square, mouseenterSquare); - boardEl.on('mouseleave', '.' + CSS.square, mouseleaveSquare); - - // IE doesn't like the events on the window object, but other browsers - // perform better that way - if (isMSIE() === true) { - // IE-specific prevent browser "image drag" - document.ondragstart = function() { return false; }; - - $('body').on('mousemove', mousemoveWindow); - $('body').on('mouseup', mouseupWindow); - } - else { - $(window).on('mousemove', mousemoveWindow); - $(window).on('mouseup', mouseupWindow); - } - - // touch drag pieces - if (isTouchDevice() === true) { - boardEl.on('touchstart', '.' + CSS.square, touchstartSquare); - containerEl.on('touchstart', '.' + CSS.sparePieces + ' .' + CSS.piece, - touchstartSparePiece); - $(window).on('touchmove', touchmoveWindow); - $(window).on('touchend', touchendWindow); - } -} - -function initDom() { - // build board and save it in memory - containerEl.html(buildBoardContainer()); - boardEl = containerEl.find('.' + CSS.board); - - if (cfg.sparePieces === true) { - sparePiecesTopEl = containerEl.find('.' + CSS.sparePiecesTop); - sparePiecesBottomEl = containerEl.find('.' + CSS.sparePiecesBottom); - } - - // create the drag piece - var draggedPieceId = createId(); - $('body').append(buildPiece('wP', true, draggedPieceId)); - draggedPieceEl = $('#' + draggedPieceId); - - // get the border size - BOARD_BORDER_SIZE = parseInt(boardEl.css('borderLeftWidth'), 10); - - // set the size and draw the board - widget.resize(); -} - -function init() { - if (checkDeps() !== true || - expandConfig() !== true) return; - - // create unique IDs for all the elements we will create - createElIds(); - - initDom(); - addEvents(); -} - -// go time -init(); - -// return the widget object -return widget; - -}; // end window.ChessBoard - -// expose util functions -window.ChessBoard.fenToObj = fenToObj; -window.ChessBoard.objToFen = objToFen; - -})(); // end anonymous wrapper diff --git a/experiments/chess/assets/chessboardjs/js/chessboard-0.3.0.min.js b/experiments/chess/assets/chessboardjs/js/chessboard-0.3.0.min.js deleted file mode 100644 index 81a29a1a..00000000 --- a/experiments/chess/assets/chessboardjs/js/chessboard-0.3.0.min.js +++ /dev/null @@ -1,31 +0,0 @@ -/*! chessboard.js v0.3.0 | (c) 2013 Chris Oakman | MIT License chessboardjs.com/license */ -(function(){function l(f){return"string"!==typeof f?!1:-1!==f.search(/^[a-h][1-8]$/)}function Q(f){if("string"!==typeof f)return!1;f=f.replace(/ .+$/,"");f=f.split("/");if(8!==f.length)return!1;for(var b=0;8>b;b++)if(""===f[b]||8m;m++){for(var l=f[m].split(""),r=0,w=0;wm;m++){for(var l=0;8>l;l++){var r=B[l]+n;!0===f.hasOwnProperty(r)?(r=f[r].split(""),r="w"===r[0]?r[1].toUpperCase(): -r[1].toLowerCase(),b+=r):b+="1"}7!==m&&(b+="/");n--}b=b.replace(/11111111/g,"8");b=b.replace(/1111111/g,"7");b=b.replace(/111111/g,"6");b=b.replace(/11111/g,"5");b=b.replace(/1111/g,"4");b=b.replace(/111/g,"3");return b=b.replace(/11/g,"2")}var B="abcdefgh".split("");window.ChessBoard=window.ChessBoard||function(f,b){function n(){return"xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx".replace(/x/g,function(a){return(16*Math.random()|0).toString(16)})}function m(a){return JSON.parse(JSON.stringify(a))}function X(a){a= -a.split(".");return{major:parseInt(a[0],10),minor:parseInt(a[1],10),patch:parseInt(a[2],10)}}function r(a,e,c){if(!0===b.hasOwnProperty("showErrors")&&!1!==b.showErrors){var d="ChessBoard Error "+a+": "+e;"console"===b.showErrors&&"object"===typeof console&&"function"===typeof console.log?(console.log(d),2<=arguments.length&&console.log(c)):"alert"===b.showErrors?(c&&(d+="\n\n"+JSON.stringify(c)),window.alert(d)):"function"===typeof b.showErrors&&b.showErrors(a,e,c)}}function w(a){return"fast"=== -a||"slow"===a?!0:parseInt(a,10)+""!==a+""?!1:0<=a}function I(){for(var a=0;a=b;b++){var c=B[a]+b;s[c]=c+"-"+n()}b="KQRBNP".split("");for(a=0;a';!0===b.sparePieces&&(a+='
');a+='
';!0===b.sparePieces&&(a+='
'); -return a+""}function A(a){"black"!==a&&(a="white");var e="",c=m(B),d=8;"black"===a&&(c.reverse(),d=1);for(var C="white",f=0;8>f;f++){for(var e=e+('
'),k=0;8>k;k++){var g=c[k]+d,e=e+('
');if(!0===b.showNotation){if("white"===a&&1===d||"black"===a&&8===d)e+='
'+c[k]+"
";0===k&&(e+='
'+d+"
")}e+="
";C="white"===C?"black":"white"}e+='
';C="white"===C?"black":"white";"white"===a?d--:d++}return e}function Y(a){if("function"===typeof b.pieceTheme)return b.pieceTheme(a);if("string"===typeof b.pieceTheme)return b.pieceTheme.replace(/{piece}/g,a);r(8272,"Unable to build image source for cfg.pieceTheme.");return""}function D(a,b,c){var d=''}function N(a){var b="wK wQ wR wB wN wP".split(" ");"black"===a&&(b="bK bQ bR bB bN bP".split(" "));a="";for(var c=0;c=d?c:d}function la(a){for(var b=[],c=0;8>c;c++)for(var d=0;8>d;d++){var g=B[c]+(d+1);a!==g&&b.push({square:g,distance:ka(a,g)})}b.sort(function(a,b){return a.distance-b.distance});a=[];for(c=0;c=d.left&&a=d.top&&b=a)p=0;else{for(a-=1;0!==a%8&&0=1E8*b.major+1E4*b.minor+b.patch;return a?!0:(window.alert("ChessBoard Error 1005: Unable to find a valid version of jQuery. Please include jQuery 1.7.0 or higher on the page.\n\nExiting..."), -!1)}()){if("string"===typeof b||!0===F(b))b={position:b};"black"!==b.orientation&&(b.orientation="white");u=b.orientation;!1!==b.showNotation&&(b.showNotation=!0);!0!==b.draggable&&(b.draggable=!1);"trash"!==b.dropOffBoard&&(b.dropOffBoard="snapback");!0!==b.sparePieces&&(b.sparePieces=!1);!0===b.sparePieces&&(b.draggable=!0);if(!0!==b.hasOwnProperty("pieceTheme")||"string"!==typeof b.pieceTheme&&"function"!==typeof b.pieceTheme)b.pieceTheme="img/chesspieces/wikipedia/{piece}.png";if(!0!==b.hasOwnProperty("appearSpeed")|| -!0!==w(b.appearSpeed))b.appearSpeed=200;if(!0!==b.hasOwnProperty("moveSpeed")||!0!==w(b.moveSpeed))b.moveSpeed=200;if(!0!==b.hasOwnProperty("snapbackSpeed")||!0!==w(b.snapbackSpeed))b.snapbackSpeed=50;if(!0!==b.hasOwnProperty("snapSpeed")||!0!==w(b.snapSpeed))b.snapSpeed=25;if(!0!==b.hasOwnProperty("trashSpeed")||!0!==w(b.trashSpeed))b.trashSpeed=100;!0===b.hasOwnProperty("position")&&("start"===b.position?g=m(fa):!0===Q(b.position)?g=K(b.position):!0===F(b.position)?g=m(b.position):r(7263,"Invalid value passed to config.position.", -b.position));W=!0}W&&(I(),ya(),xa());return q};window.ChessBoard.fenToObj=K;window.ChessBoard.objToFen=L})(); \ No newline at end of file diff --git a/experiments/chess/assets/js/Board.js b/experiments/chess/assets/js/Board.js deleted file mode 100644 index b9ab7253..00000000 --- a/experiments/chess/assets/js/Board.js +++ /dev/null @@ -1,24 +0,0 @@ -function Board(id, config){ - this.board = new ChessBoard(id,config); - - console.log(this.board) - this.render = function({ - state, - done, - action, - turn - }){ - var fen = state.split(" ")[0]; - if(this.board.fen().valueOf() == fen.valueOf()) - this.board.position(fen, true); - - var ele = $$("." + (turn=="b"?"comp":"human")); - highlight(ele, $$(".options")) - - if(done){ - show($$(".overlay #gameOver")) - }else{ - hide($$(".overlay #gameOver")) - } - } -} \ No newline at end of file diff --git a/experiments/chess/assets/js/Env.js b/experiments/chess/assets/js/Env.js deleted file mode 100644 index d31a8662..00000000 --- a/experiments/chess/assets/js/Env.js +++ /dev/null @@ -1,25 +0,0 @@ -function Env(){ - this.chess = new Chess(); - var action = null; - - this.done = function(){ - return this.chess.game_over(); - } - - this.step = function(a){ - action = a; - return this.chess.move(a); - } - - this.state = function(){ - return this.chess.fen(); - } - - this.config = function(){ - return {state: this.state(), done: this.done(), action, turn: this.chess.turn()}; - } - - this.reset = function(){ - return chess.reset(); - } -} \ No newline at end of file diff --git a/experiments/chess/assets/js/extenstions.js b/experiments/chess/assets/js/extenstions.js deleted file mode 100644 index e128e79d..00000000 --- a/experiments/chess/assets/js/extenstions.js +++ /dev/null @@ -1,22 +0,0 @@ -Game.prototype.isValidAction = function(action){ - // computer -> black piece - // human -> white piece - var nextColor = this.env.chess.turn() - var color = action.peice[0]; - if((color != nextColor) - // || (this.state == this.states.C && color == "w") || (this.state == this.states.H && action.peice[0] == "b") - ){ - return false; - } - - var res = this.env.chess.move(action); - if(res)this.env.chess.undo(); - - return res != null; -} - -Game.prototype.nextGameState = function(curr) { - // return (curr + 1)%2; - return curr -}; - diff --git a/experiments/chess/assets/js/script.js b/experiments/chess/assets/js/script.js deleted file mode 100644 index 2c70634f..00000000 --- a/experiments/chess/assets/js/script.js +++ /dev/null @@ -1,28 +0,0 @@ -var __init__ = function(){ - var start = "", end = "", env = new Env(); - - var board_config = { - draggable: true, - dropOffBoard: 'snapback', // this is the default - position: 'start', - onDragStart: dragStart, - onDrop: drop - } - var board = new Board("playground", board_config); - var game = new Game(env, board, null, {mode:"async"}); - - function dragStart(source, peice, state, orientation){ - // if(peice[0] == "b")return false; // user can't move black peices - } - - function drop(source, target, peice, newPos, oldPos, orientation){ - if(source == target)return; // no action - if(!game.action({from: source, to: target, nextState: ChessBoard.objToFen(newPos), peice})){ - return 'snapback'; - } - - return true; - } -} - -__init__() \ No newline at end of file diff --git a/experiments/chess/img/chesspieces/wikipedia/bB.png b/experiments/chess/img/chesspieces/wikipedia/bB.png deleted file mode 100644 index 42b1e747..00000000 Binary files a/experiments/chess/img/chesspieces/wikipedia/bB.png and /dev/null differ diff --git a/experiments/chess/img/chesspieces/wikipedia/bK.png b/experiments/chess/img/chesspieces/wikipedia/bK.png deleted file mode 100644 index 0aad81e5..00000000 Binary files a/experiments/chess/img/chesspieces/wikipedia/bK.png and /dev/null differ diff --git a/experiments/chess/img/chesspieces/wikipedia/bN.png b/experiments/chess/img/chesspieces/wikipedia/bN.png deleted file mode 100644 index 2eee2e21..00000000 Binary files a/experiments/chess/img/chesspieces/wikipedia/bN.png and /dev/null differ diff --git a/experiments/chess/img/chesspieces/wikipedia/bP.png b/experiments/chess/img/chesspieces/wikipedia/bP.png deleted file mode 100644 index afa0c9d4..00000000 Binary files a/experiments/chess/img/chesspieces/wikipedia/bP.png and /dev/null differ diff --git a/experiments/chess/img/chesspieces/wikipedia/bQ.png b/experiments/chess/img/chesspieces/wikipedia/bQ.png deleted file mode 100644 index c6810d85..00000000 Binary files a/experiments/chess/img/chesspieces/wikipedia/bQ.png and /dev/null differ diff --git a/experiments/chess/img/chesspieces/wikipedia/bR.png b/experiments/chess/img/chesspieces/wikipedia/bR.png deleted file mode 100644 index c7eb127a..00000000 Binary files a/experiments/chess/img/chesspieces/wikipedia/bR.png and /dev/null differ diff --git a/experiments/chess/img/chesspieces/wikipedia/wB.png b/experiments/chess/img/chesspieces/wikipedia/wB.png deleted file mode 100644 index bdee3d05..00000000 Binary files a/experiments/chess/img/chesspieces/wikipedia/wB.png and /dev/null differ diff --git a/experiments/chess/img/chesspieces/wikipedia/wK.png b/experiments/chess/img/chesspieces/wikipedia/wK.png deleted file mode 100644 index a475d80b..00000000 Binary files a/experiments/chess/img/chesspieces/wikipedia/wK.png and /dev/null differ diff --git a/experiments/chess/img/chesspieces/wikipedia/wN.png b/experiments/chess/img/chesspieces/wikipedia/wN.png deleted file mode 100644 index f1d1ce9e..00000000 Binary files a/experiments/chess/img/chesspieces/wikipedia/wN.png and /dev/null differ diff --git a/experiments/chess/img/chesspieces/wikipedia/wP.png b/experiments/chess/img/chesspieces/wikipedia/wP.png deleted file mode 100644 index a83a3004..00000000 Binary files a/experiments/chess/img/chesspieces/wikipedia/wP.png and /dev/null differ diff --git a/experiments/chess/img/chesspieces/wikipedia/wQ.png b/experiments/chess/img/chesspieces/wikipedia/wQ.png deleted file mode 100644 index e7960684..00000000 Binary files a/experiments/chess/img/chesspieces/wikipedia/wQ.png and /dev/null differ diff --git a/experiments/chess/img/chesspieces/wikipedia/wR.png b/experiments/chess/img/chesspieces/wikipedia/wR.png deleted file mode 100644 index c4d6fb01..00000000 Binary files a/experiments/chess/img/chesspieces/wikipedia/wR.png and /dev/null differ diff --git a/experiments/chess/index.html b/experiments/chess/index.html deleted file mode 100644 index 667792de..00000000 --- a/experiments/chess/index.html +++ /dev/null @@ -1,23 +0,0 @@ ---- -layout: default -game: chess ---- - -{% include experiments/game/headers.html %} - - - - - - -{% assign game = site.data.experiments[page.game] %} -{% include experiments/game/content.html game=game %} - -{% include experiments/game/footer.html %} - - - - \ No newline at end of file diff --git a/experiments/experiments.css b/experiments/experiments.css deleted file mode 100644 index e93ba659..00000000 --- a/experiments/experiments.css +++ /dev/null @@ -1,34 +0,0 @@ -body{ - min-height: 100vh; - display: flex; - flex-direction: column; -} - -.content{ - flex:2; - display: flex; -} -.demo-menu{ - padding: 10px; -} - -.demo-menu *{ - list-style: none; - text-decoration: none; - color: inherit; -} - -.demo-menu li{ - background: var(--light); - margin: 20px 0; - padding: 20px; -} - -.content li p{ - margin: 0; -} - -.content li p a{ - border-bottom: none; - font-weight: 600; -} \ No newline at end of file diff --git a/experiments/go/assets/bson/base_net.bson b/experiments/go/assets/bson/base_net.bson deleted file mode 100644 index 82388982..00000000 Binary files a/experiments/go/assets/bson/base_net.bson and /dev/null differ diff --git a/experiments/go/assets/bson/policy.bson b/experiments/go/assets/bson/policy.bson deleted file mode 100644 index 377b4f01..00000000 Binary files a/experiments/go/assets/bson/policy.bson and /dev/null differ diff --git a/experiments/go/assets/bson/value.bson b/experiments/go/assets/bson/value.bson deleted file mode 100644 index 84a9ed5d..00000000 Binary files a/experiments/go/assets/bson/value.bson and /dev/null differ diff --git a/experiments/go/assets/css/style.css b/experiments/go/assets/css/style.css deleted file mode 100644 index c208e97e..00000000 --- a/experiments/go/assets/css/style.css +++ /dev/null @@ -1,83 +0,0 @@ -.board { height: 500px; } -.pass{ - margin: 0 15px; - border: 1px solid var(--dark); - border-radius: 3px; - padding: 3px 15px; - cursor: pointer -} - -.pass.active{ - background: #dcdcdc; -} - - -.stats div{ - width: 100%; - justify-content: flex-end; - display: flex; -} - -.stats{ - padding: 0 20px; - background: #ebf5eb; - color: #41822a; - display: flex; -} - -.stats div p{ - display: flex; - align-items: center; - justify-content: space-around; -} - -.dot{ - width: 0; - height: 0; - border: 10px solid; - font-size: 0; - margin: 0 5px; - border-radius: 50%; -} - -.dot.black{ - border-color: #666; -} - -.dot.white{ - border-color: #fff; -} - -.pbar{ - position: absolute; - bottom: 0; - width: 0; - left: 0; - height: 3px; - background: var(--dark); - transition: width .7s cubic-bezier(0.69, 0.18, 0.74, 1.31); - border-top-right-radius: 6px; - /*border-bottom-right-radius: 50%;*/ -} - -#controls{ - position: relative; -} - -.wgo-board{ - border-top: none !important; - -} - -.num_readouts{ - width: 50px; - padding: 0 5px; - margin: 0 10px; - border: none; - border-bottom: 1px solid #95a595; -} - -.num_readouts:focus{ - outline: none; - border-bottom: 1px solid #556355; -} \ No newline at end of file diff --git a/experiments/go/assets/js/Board.js b/experiments/go/assets/js/Board.js deleted file mode 100644 index 76fa114b..00000000 --- a/experiments/go/assets/js/Board.js +++ /dev/null @@ -1,48 +0,0 @@ -function Board(board){ - - this.render = (config)=>{ - board.render(config); - - highlight($$("." + (config.turn==1?"human":"comp")), $$(".options")) - - var addS = (n, str) => n <= 1? str : str + "s"; - // var stats= $$("#game .stats"); - // if(stats == null){ - // stats = document.createElement('div'); - // stats.className = "stats" - // $$("#game").insertBefore(stats, $$("#game .board")) - // } - - // stats.innerHTML = "

Captures

\ - //
\ - //

" + config.capCount[WGo.B]+ " " + addS(config.capCount[WGo.B], "stone")+ "

\ - //

" + config.capCount[WGo.W]+ " " + addS(config.capCount[WGo.W], "stone")+ "

\ - //
" - - - - if(config.lastMove && config.lastMove.type == "pass"){ - var n = $$(".pass").className; - if(n.match("active") == null) $$(".pass").className = n + " active"; - setTimeout(()=>{ - var n = $$(".pass").className; - if(n.match("active") != null) $$(".pass").className = n.replace(" active", ""); - }, 1000) - } - - if(config.done){ - show($$(".overlay #gameOver")) - var score_ = $$(".overlay #gameOver .score"); - var info = "Black scores " + config.score + " points. " + (config.score > 0? "Black": "White") + " wins!"; - if(score_ == null){ - score_ = document.createElement('p'); - score_.className = "score" - $$(".overlay #gameOver").appendChild(score_); - } - score_.innerText = info; - }else{ - hide($$(".overlay #gameOver")) - } - }; -} - diff --git a/experiments/go/assets/js/Env.js b/experiments/go/assets/js/Env.js deleted file mode 100644 index 754d8e80..00000000 --- a/experiments/go/assets/js/Env.js +++ /dev/null @@ -1,188 +0,0 @@ -(function(obj){ - -Object.assign(obj, {Env}) - -function Env(s=9, repeat="KO"){ - this.s = s; - this.repeat = repeat; - this.env = new WGo.Game(s, repeat); - this.size = () => this.env.size; - this.n_moves = () => this.env.stack.length - 1; - this.moves = []; - this.model = null; - this.passes = []; -} - -Env.prototype.turn = function(){ - return this.env.turn; -} - -Env.prototype.state = function(){return getState(this.env)} - -Env.prototype.config = function(){ - var capCount = {}; - capCount[WGo.W] = this.env.getCaptureCount(WGo.W); - capCount[WGo.B] = this.env.getCaptureCount(WGo.B); - var score = this.find_score(this.env.getPosition()); - return {state: this.state(), done: this.done(), turn: this.turn(), capCount, lastMove: this.moves.slice(-1)[0], score} -} - -Env.prototype.setModel = function (m){ - this.model = m; -} - -Env.prototype.step = function(a){ - // console.log(a, "action") - this.moves.push(a) - if(a.type== "stone"){ - this.passes = []; - var k = this.env.play(a.x, a.y, a.c); - if(k instanceof Object)this.model.play_move(a); - } - else if(a.type == "pass"){ - if(this.passes.indexOf(a.c) == -1)this.passes.push(a.c); - this.env.pass(a.c); - this.model.play_move(a); - } -} - -Env.prototype.next = function(stack, a){ - var n = this.new_env(stack, a.c); - if(a.type== "stone"){ - n.play(a.x, a.y, a.c); - } - else if(a.type == "pass"){ - n.pass(a.c); - } - return n; -} - -Env.prototype.done = function(){ - return (this.passes.length >= 2); -} - -Env.prototype.reset = function(){ - this.env.firstPosition(); - this.passes = []; - this.model.__init__(this) -} - -Env.prototype.stack = function(){ - return this.env.stack.slice(); -} - -Env.prototype.getPosition = function(){ - return this.env.getPosition(); -} - -Env.prototype.new_env = function(stack, to_play){ - var n = new WGo.Game(this.s, this.repeat) - n.stack = stack.slice(); - n.turn = to_play || n.turn - return n; -} - -Env.prototype.all_legal_moves = function(stack, to_play){ - var s = this.size(); - var legal = new Array(s * s + 1).fill(1) - for(var x = 0; x< s; x++){ - for(var y = 0; y < s; y++){ - var n = this.new_env(stack, to_play) - var result = n.play(x, y, to_play) - - if(!(result instanceof Object)){ - var obj = {x, y, type: "stone"}; - legal[MCTS.to_flat(obj, s) - 1] = 0; - } - delete n - } - } - legal[81] = 1; - return legal; -} - -Env.prototype.check_if_done = function(moves){ - var pass = this.env.size * this.env.size + 1; - // console.log(moves) - out = moves.length >= 2 && moves.slice(-2).reduce((acc,e) => acc && (e == pass), true) - // console.log(out) - return out; -} - -var empty = 0; -var visited = 2; -var unknown = -2; - -Env.prototype.find_score = function({capCount, schema}={}){ - var board = schema.slice() - var n =this.size(); - board = MCTS.partition(board, n); - - - var i = 0; - var path = [], curr = null; - while((i = chooseEmpty(board, n)) && i ){ - var boundary = frontier({board, x: i[0], y: i[1], n}); - if(boundary.length == 0) break; - var same = true; - var h = boundary[0]; - for(var j of boundary){ - if(j != h){ - same =false; - break; - } - } - if(!same){ - h = unknown; - } - - for(var x = 0; x< n; x++){ - for(var y = 0; y< n; y++){ - if(board[x][y] == visited){ - board[x][y] = h; - } - } - } - - } - - var blackStones = schema.filter(e => e == WGo.B).length; - var whiteStones = schema.filter(e => e == WGo.W).length + 0.5; - var score = (blackStones - whiteStones); - // console.log("score: ", score) - return score; -} - -function chooseEmpty(board, n){ - for(var i = 0; i< n; i++){ - for(var j = 0; j< n; j++){ - if(board[i][j] == empty)return [i, j]; - } - } - return null; - } - -function frontier({board, x, y, n}){ - if(x < 0 || y< 0 || x >= n || y >= n || board[x][y] == visited) return []; - if(board[x][y]== WGo.B || board[x][y] == WGo.W)return [board[x][y]] - - var set = neighbours(board, x, y, n); - board[x][y] = visited; - var list = []; - for(var i of set){ - var [a, b] = i; - list.concat(frontier({board, x: a, b:y, n})); - } - return list; -} - -function neighbours(board, x, y, n){ - return [[x -1, y], [x, y -1], [x + 1, y], [x, y + 1]] - -} - -Env.prototype.lastMove = function(){ - return this.moves.slice(-1); -} - -})(window); \ No newline at end of file diff --git a/experiments/go/assets/js/MCTS/MCTSNode.js b/experiments/go/assets/js/MCTS/MCTSNode.js deleted file mode 100644 index a5366819..00000000 --- a/experiments/go/assets/js/MCTS/MCTSNode.js +++ /dev/null @@ -1,301 +0,0 @@ -/********** -=========== - -Original code at https://github.com/tejank10/AlphaGo.jl - -=========== -**********/ - -(function(obj){ - -obj.MCTS = obj.MCTS || {} - -Object.assign(obj.MCTS, {Node, DummyNode}) - -var MCTS = obj.MCTS; - -var c_puct = 0.96; -var val = (n, v) => new Array(n).fill(v); -var zeros = (n) => val(n, 0); -var ones = (n) => val(n, 1); -// var defObj = (n) => ({...zeros(n), "null":0, "-1":0}); - - -function Node(position, {parent, fmove=null, board_size=9, max_game_length, stack}={}){ - this.max_game_length = max_game_length || Math.floor((Math.pow(board_size,2) * 7) / 5); - this.parent = parent || new DummyNode(board_size); - this.board_size = board_size; - this.position = position; - this.fmove = fmove; - this.is_expanded = false; - this.losses_applied = 0; - - var total_moves = board_size * board_size + 1; - this.child_N = zeros(total_moves) - this.child_W = tf.zeros([total_moves]) - - // this.original_prior = zeros(total_moves) - this.child_prior = tf.zeros([total_moves]) - - this.children = {} - this.stack = stack || [position.schema()] - this.free = false; -} - -var node = Node.prototype; - -node.N = function(){ - return this.parent.child_N[this.fmove - 1]; -} - -node.set_N = function(value){ - this.parent.child_N[this.fmove - 1] = value; -} - -node.W = function(){ - return this.parent.child_W.buffer().get(this.fmove - 1); -} - -node.set_W = function(value){ - var x = this; - var l = x.parent.child_W.buffer(); - tf.dispose(x.parent.child_W); - l.set(value, x.fmove - 1) - x.parent.child_W = l.toTensor(); - return x.parent.child_W -} - -node.select_leaf = async function(nextLeaves){ - var current = this; - var n = this.board_size; - var pass_move = n * n + 1; - return (await this.select_leaf_loop(current, pass_move, n, nextLeaves)) -} - -node.select_leaf_loop = async function(current, pass_move, n, nextLeaves){ - var readouts = 0; - - var stop = (leaf) => !leaf.is_expanded || leaf.is_done() - - var d; - if((d = nextLeaves.splice(0,1)) && d.length == 1){ - current = d[0] - } - - while(readouts < 3){ - readouts++; - var current_new_N = current.N() + 1 - current.set_N(current_new_N) - - if (stop(current)){ - break; - } - - // if(current.fmove == 82) debugger - // if (current.position.last_move == pass_move - // && current.child_N[pass_move - 1] == 0){ - // current = current.maybe_add_child(pass_move) - // continue; - // } - cas = current.child_action_score() - // console.log("cas", this.child_N, current.child_N) - best_move = tf.tidy(()=>tf.argMax(cas).dataSync()[0] + 1) - tf.dispose(cas); - current = current.maybe_add_child(best_move) - } - - - - if (current.position.last_move == pass_move - && current.child_N[pass_move - 1] == 0 && !current.is_done()){ - // definetly explore this next - nextLeaves.push(current.maybe_add_child(pass_move)) - } - - if(stop(current))return [current, nextLeaves]; - else{ - var x= this; - return new Promise(function(resolve, reject){ - requestAnimationFrame(()=>{ - x.select_leaf_loop(current, pass_move, n, nextLeaves).then(out =>{ - resolve(out) - }) - }) - }) - } - -} - -function childname(node){ - if(node instanceof DummyNode || node.parent instanceof DummyNode)return "Dummy" - return childname(node.parent) +" >> " + node.fmove; -} - -node.maybe_add_child = function(move){ - // console.log("maybe_add_child", move) - - if(!this.children[move]){ - // console.log("add child:", childname(this), ">>", move) - var new_pos = this.position.play_move(move); - this.children[move] = new Node(new_pos, {fmove:move, parent:this, max_game_length: this.max_game_length}) - } - - return this.children[move]; -} - -node.child_action_score = function(){ - return tf.tidy(() =>{ - var larr = tf.tensor(this.legal_moves().map(e => 1000 *( 1 - e))); - var qarr = this.child_Q(); - // debugger; - var uarr = this.child_U(); - var l = this.board_size * this.board_size + 1; - var x = this; - return tf.sub(tf.add(tf.mul(qarr, tf.scalar(x.position.to_play)), uarr),larr) - }); -} - -node.child_Q = function(){ - var x = this; - var out = tf.tidy(() => (tf.div(x.child_W, tf.add(tf.scalar(1), tf.tensor(x.child_N))))) - // debugger; - return out; -} - -node.child_U = function(){ - var x = this; - return tf.tidy(() => tf.mul(tf.scalar(c_puct * Math.sqrt(1 + x.N())), - tf.div(x.child_prior, tf.add(tf.scalar(1), tf.tensor(x.child_N))))) -} - -node.legal_moves = function () { return this.position.legal_moves() }; - -node.backup_value = function(value, root_){ - this.set_W(this.W() + value); - if( this.parent == null || this == root_ )return; - this.parent.backup_value(value, root_); -} -node.add_virtual_loss = function(root_){ - this.losses_applied += 1; - var loss = this.position.to_play - this.set_W(this.W() + loss) - if (this.parent == null || this == root_) return; - this.parent.add_virtual_loss(root_) -} - -node.revert_virtual_loss = function(root_){ - this.losses_applied -= 1 - var revert = -1 * this.position.to_play; - this.set_W(this.W() + revert) - if (this.parent == null || this == root_) return; - - this.parent.revert_virtual_loss(root_) -} - -node.incorporate_results = function(move_probs, value, up_to){ - // console.log("incorporate_results", value, this.is_done()) - if (this.is_expanded){ - this.revert_visits(up_to) - return - } - this.is_expanded = true - // this.original_prior = move_probs.slice(); - tf.dispose(this.child_prior); - this.child_prior = move_probs; - - var len = this.board_size * this.board_size + 1 - tf.dispose(this.child_W) - this.child_W = tf.fill([len], value) - this.backup_value(value, up_to) -} - - -node.revert_visits = function(up_to){ - this.set_N(this.N() - 1) - // console.log(this.child_N) - if (this.parent == null || this == up_to )return; - this.parent.revert_visits(up_to); -} - -node.children_as_pi = function(squash=false){ - var probs = this.child_N; - var l = probs.length; - if(squash){ - for(var i = 0; i< l; i++){ - probs[i]= Math.pow(probs[i], 0.98) - } - } - var sum = 0; - for(var i = 0; i= this.max_game_length -} - -node.get_feats = function(){ - var last_eight = this.get_stack(8); - return this.position.get_feats(last_eight); -} - -node.get_stack = function(n){ - if(n == 0) return []; - if(this.isRoot) return this.stack.slice(0, n); - - return [this.position.schema()].concat(this.parent.get_stack(n - 1)); -} - -node.set_stack = function(n){ - this.stack = this.get_stack(n); -} - -node.set_dummy_parent = function(child_N){ - // debugger - this.parent.free_node(this.fmove); - this.parent = new DummyNode(this.board_size, child_N); - this.parent.child_N = child_N; -} - -node.free_node = function(savechild=-1){ - if(this.free) return; - tf.dispose(this.child_W); - tf.dispose(this.child_prior); - this.free = true; - for (var child in this.children){ - if(child != savechild) - this.children[child].free_node() - } - this.children = {} - if(this.parent != this) - this.parent.free_node(); -} - -function DummyNode(n){ - this.parent = null; - this.child_N = zeros(n*n + 1); - this.child_W = tf.zeros([n*n + 1]); - this.free = false; -} - -DummyNode.prototype = Object.create(node); - -DummyNode.prototype.get_stack = function(){ - return []; -}; - -DummyNode.prototype.free_node = function(){ - tf.dispose(this.child_W); - this.free = true; -} - -})(window); \ No newline at end of file diff --git a/experiments/go/assets/js/MCTS/MCTSPlayer.js b/experiments/go/assets/js/MCTS/MCTSPlayer.js deleted file mode 100644 index 83d9255a..00000000 --- a/experiments/go/assets/js/MCTS/MCTSPlayer.js +++ /dev/null @@ -1,189 +0,0 @@ -/********** -=========== - -Original code at https://github.com/tejank10/AlphaGo.jl - -=========== -**********/ - -(function(obj){ - -obj.MCTS = obj.MCTS || {} -Object.assign(obj.MCTS, {Player}) - -var MCTS = obj.MCTS; -var doNothing = () => null - -function Player(network, {layer, progress, num_readouts = 1, two_player_mode = false, resign_threshold = -0.9, board_size = 9, max_game_length}={}){ - this.board_size = board_size; - this.tau_threshold = two_player_mode ? -1 : (board_size * board_size / 12) / 2 * 2 - this.network = network; - this.num_readouts = num_readouts; - this.two_player_mode = two_player_mode; - this.qs = []; - this.searches_pi = []; - this.result = 0; - this.result_string = ""; - this.root = null - this.resign_threshold = resign_threshold; - this.position = null; - this.max_game_length = max_game_length; - this.layer = layer || doNothing; - this.progress = progress || doNothing; - this.current_readouts = 0; -} - -var player = Player.prototype; - -player.__init__ = function(pos){ - - this.root = new MCTS.Node(pos, { - max_game_length: this.max_game_length, - board_size: this.board_size - }); - this.result = 0 - this.searches_pi = []; - this.qs = []; -} - -player.suggest_move = async function(){ - if(this.root.legal_moves().filter(e => e == 1).length == 1){ - // pass move is the only legal move left - return MCTS.to_obj(this.board_size * this.board_size + 1, this.root.position.to_play, this.board_size); - } - // console.log("suggest move") - this.current_readouts = this.root.N(); - // console.log(cb) - return (await this.search_loop.bind(this)()); -} - -player.search_loop = async function(){ - if(this.root.N() >= this.current_readouts + this.num_readouts) - return this.pick_move(); - - await this.tree_search(); - this.layer(this.best_n(3)); - this.progress((this.root.N() - this.current_readouts)/this.num_readouts); - return (await this.search_loop.bind(this)()); -} - -player.tree_search = async function(parallel_readouts=8){ - var leaves = []; - var failsafe = 0; - - var leaves = await this.tree_search_loop(leaves, failsafe, parallel_readouts, []) - if(leaves.length == 0) return []; - - var { move_probs, values } = this.network.process(leaves) - - var len = this.board_size*this.board_size + 1 - - val = values.dataSync(); - tf.dispose(values) - for (var i in leaves){ - var leaf = leaves[i]; - var move_prob = move_probs.slice(0, 1).as1D() - var value = val[i]; - leaf.revert_virtual_loss(this.root) - leaf.incorporate_results(move_prob, value, this.root) - tf.dispose(move_prob); - } - tf.dispose(move_probs) - - return leaves -} - -player.tree_search_loop = async function(leaves, failsafe, parallel_readouts, nextLeaves){ - if(!(leaves.length < parallel_readouts && failsafe < 2 * parallel_readouts)) - return leaves; - - var count = 0; - - while((leaves.length < parallel_readouts && failsafe < 2 * parallel_readouts) && count < 2){ - count++; - failsafe += 1 - var res = await this.root.select_leaf(nextLeaves); - leaf = res[0] - nextLeaves = res[1] - - if (leaf.is_done()){ - value = (leaf.position.score() > 0 ? 1 : -1); - leaf.backup_value(value, this.root) - continue - } - - - - leaf.add_virtual_loss(this.root) - leaves.push(leaf) - } - - var scope = this; - return new Promise(function(resolve,reject){ - setTimeout(()=>{ - scope.tree_search_loop(leaves, failsafe, parallel_readouts, nextLeaves).then(out =>{ - resolve(out) - }); - }, 50) - }) -} - -player.get_feats = function(){ - return this.root.position.get_feats(); -} - -player.best_n = function(n){ - var arr = this.root.child_N.slice(); - var min = Math.min(...arr); - var best = []; - for(var i =0; i< n; i++){ - var index = MCTS.argMax(arr); - best.push(index); - arr[index] = min; - } - return best; -} - -player.pick_move = function(){ - var fcoord; - - - if (this.root.position.n >= this.tau_threshold){ - fcoord = MCTS.argMax(this.root.child_N) + 1; - }else{ - var cdf = tf.tidy(() => tf.cumsum(tf.tensor(this.root.child_N)).dataSync()); - var n = cdf.slice(-2)[0]; - var o = cdf.length - for(var i =0; i< o; i++){ - cdf[i] = MCTS.safe_div(cdf[i], n); - } - selection = Math.random() - var m = MCTS.searchsortedfirst(cdf, selection); - var l = this.board_size* this.board_size; - m = m == -1 || m >= l ? Math.floor(Math.random()*l): m - fcoord = m + 1 - - } - // console.log("fcoord....", fcoord) - return MCTS.to_obj(fcoord, this.root.position.to_play, this.board_size); -} - -player.play_move = function(c){ - // console.log("play", c); - c = MCTS.to_flat(c, this.board_size); - - if (!this.two_player_mode){ - this.searches_pi.push( - this.root.children_as_pi(this.root.position.n <= this.tau_threshold)) - } - this.qs.push(this.root.Q()) - - this.root = this.root.maybe_add_child(c); - - this.position = this.root.position - this.root.set_dummy_parent(this.root.parent.child_N); - - return true -} - -})(window); \ No newline at end of file diff --git a/experiments/go/assets/js/MCTS/Position.js b/experiments/go/assets/js/MCTS/Position.js deleted file mode 100644 index f0064446..00000000 --- a/experiments/go/assets/js/MCTS/Position.js +++ /dev/null @@ -1,77 +0,0 @@ -(function(obj){ - -obj.MCTS = obj.MCTS || {} - -Object.assign(obj.MCTS, {Position}) - -var MCTS = obj.MCTS - -var pos_to_board = (pos, n) => partition(pos.schema.slice(), n) - -// MCTS's representation of env -function Position(env, stack, moves, turn, n=0){ - this.position = stack.slice(-1)[0]; - this.size = env.size(); - this.stack = stack.slice(); - this.to_play = turn; - this.n = n; - this.last_move = moves.slice(-1)[0]; - this.env = env; - this.store = {} - this.recent = moves.slice(-2) -} - -var pos = Position.prototype; - -// doesn't affect the real environment -pos.play_move = function(f){ - var k = this.env.next(this.stack, MCTS.to_obj(f, this.to_play, this.size)); - return new Position(this.env, k.stack, this.recent.concat(f), k.turn, this.n + 1) -}; - -pos.schema = function(){ - return this.position.schema.slice(); -} - -pos.legal_moves = function(){ - // since it needs to be calculated only once for this stack - return this.store["legal_moves"] ? this.store["legal_moves"] : (()=>{ - var l = this.env.all_legal_moves(this.stack, this.to_play) - this.store["legal_moves"] = l; - return l; - })(); -} - -pos.is_done = function(){ - return this.env.check_if_done(this.recent) -} -pos.score = function(){ - return this.env.find_score(this.position) -} - -pos.get_feats = function(last_eight){ - return tf.tidy(() => tf.concat([this.stone_features(last_eight),this.color_to_play_feature()])); -} - -pos.stone_features = function(last_eight){ - while(last_eight.length < 8){ - last_eight.push(last_eight.slice(-1)[0]); - } - - var features = last_eight.reduce((acc, e) =>{ - var p = e.slice(); - var o = e.slice(); - p = p.map(f => (f == this.to_play) + 0); - o = o.map(f => (f == -1 * this.to_play) + 0); - acc.push(p, o) - return acc - }, []) - return tf.tidy(() => tf.tensor(features, [16, 81]).reshape([16, 9, 9])); -} - -pos.color_to_play_feature = function() { - return tf.tidy(() =>tf.fill([1, this.size, this.size], this.to_play)); -}; - - -})(window) \ No newline at end of file diff --git a/experiments/go/assets/js/MCTS/utils.js b/experiments/go/assets/js/MCTS/utils.js deleted file mode 100644 index 2c2fba90..00000000 --- a/experiments/go/assets/js/MCTS/utils.js +++ /dev/null @@ -1,60 +0,0 @@ -(function(obj){ - -obj.MCTS = obj.MCTS || {} - - -var to_flat = (l, n) => l.type=="pass" ? n * n + 1 : l.y + l.x * n + 1; -var to_obj = (f, c, n) => f == n * n + 1? ({type:"pass", c}):({type: "stone", x: Math.floor((f - 1)/n), y: Math.floor((f - 1) % n), c }) -var safe_div = (n, d) => d == 0? n*1000/Math.random() : n/d; - -function argMax(arr){ - var i = 0; - for(var j = 0; j< arr.length; j++){ - if(arr[j]> arr[i]) - i = j; - } - return i -} - - -function partition(array, n){ - return partition_(array.slice(),n) -} - -function partition_ (array, n){ - if(isNaN(n))debugger; - - var l = array.length; - var m = l/n - if(m != Math.floor(m)) throw Error("Invalid partition size") - var res = new Array(m); - var acc = new Array(n); - for(var i = 0; i e > x) - return bs(arr, x, 0, arr.length) -} - -function bs(arr, nee, beg, end){ - if(beg >= end) return beg; - - var mid = Math.floor((beg + end)/2) - - if( arr[mid] == nee) return mid; - else if( arr[mid] > nee) return bs(arr, nee, beg, mid - 1) - else return bs(arr, nee, mid + 1, end) -} - -Object.assign(obj.MCTS, {to_flat, to_obj, safe_div, argMax, partition, searchsortedfirst}) - -})(window); \ No newline at end of file diff --git a/experiments/go/assets/js/base_net.js b/experiments/go/assets/js/base_net.js deleted file mode 100644 index 69bf30e6..00000000 --- a/experiments/go/assets/js/base_net.js +++ /dev/null @@ -1,152 +0,0 @@ -/*********************** -Generated using FluxJS.jl -************************/ - -let base_net = (function () { - let math = tf; - function porcupine(hummingbird) { - return hummingbird; - }; - function okapi(cod) { - let monkey = cod[String("shape")][String("length")]; - let mink = Array(monkey).fill(1) - let mammoth = cod[String("shape")]; - mink[monkey - 2] = mammoth[mammoth[String("length")] - (monkey - 1)]; - return math.add(math.mul(math.div(math.sub(cod, math.reshape(model.weights[0], [mink[3], mink[2], mink[1], mink[0]])), math.reshape(model.weights[1], [mink[3], mink[2], mink[1], mink[0]])), math.reshape(model.weights[2], [mink[3], mink[2], mink[1], mink[0]])), math.reshape(model.weights[3], [mink[3], mink[2], mink[1], mink[0]])); - }; - function kinkajou(porpoise) { - return math.add(math.transpose(math.conv2d(math.transpose(porpoise, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[4], [2, 3, 1, 0], porpoise), [0, 1]), [1, 1], 1), [0, 3, 1, 2]), model.weights[5]); - }; - function snake(caterpillar) { - let camel = caterpillar[String("shape")][String("length")]; - let raven = Array(camel).fill(1) - let snail = caterpillar[String("shape")]; - raven[camel - 2] = snail[snail[String("length")] - (camel - 1)]; - return math.add(math.mul(math.div(math.sub(caterpillar, math.reshape(model.weights[6], [raven[3], raven[2], raven[1], raven[0]])), math.reshape(model.weights[7], [raven[3], raven[2], raven[1], raven[0]])), math.reshape(model.weights[8], [raven[3], raven[2], raven[1], raven[0]])), math.reshape(model.weights[9], [raven[3], raven[2], raven[1], raven[0]])); - }; - function crab(pig) { - return math.add(math.transpose(math.conv2d(math.transpose(pig, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[10], [2, 3, 1, 0], pig), [0, 1]), [1, 1], 1), [0, 3, 1, 2]), model.weights[11]); - }; - function cattle(sealion) { - return math.relu(math.add(porcupine(sealion), okapi(kinkajou(math.relu(snake(crab(flux.slice(sealion)))))))); - }; - function ape(eagle) { - return eagle; - }; - function bison(jellyfish) { - let mandrill = jellyfish[String("shape")][String("length")]; - let ferret = Array(mandrill).fill(1) - let shrew = jellyfish[String("shape")]; - ferret[mandrill - 2] = shrew[shrew[String("length")] - (mandrill - 1)]; - return math.add(math.mul(math.div(math.sub(jellyfish, math.reshape(model.weights[12], [ferret[3], ferret[2], ferret[1], ferret[0]])), math.reshape(model.weights[13], [ferret[3], ferret[2], ferret[1], ferret[0]])), math.reshape(model.weights[14], [ferret[3], ferret[2], ferret[1], ferret[0]])), math.reshape(model.weights[15], [ferret[3], ferret[2], ferret[1], ferret[0]])); - }; - function dogfish(redpanda) { - return math.add(math.transpose(math.conv2d(math.transpose(redpanda, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[16], [2, 3, 1, 0], redpanda), [0, 1]), [1, 1], 1), [0, 3, 1, 2]), model.weights[17]); - }; - function toad(aardvark) { - let badger = aardvark[String("shape")][String("length")]; - let gnat = Array(badger).fill(1); - let sandpiper = aardvark[String("shape")]; - gnat[badger - 2] = sandpiper[sandpiper[String("length")] - (badger - 1)]; - return math.add(math.mul(math.div(math.sub(aardvark, math.reshape(model.weights[18], [gnat[3], gnat[2], gnat[1], gnat[0]])), math.reshape(model.weights[19], [gnat[3], gnat[2], gnat[1], gnat[0]])), math.reshape(model.weights[20], [gnat[3], gnat[2], gnat[1], gnat[0]])), math.reshape(model.weights[21], [gnat[3], gnat[2], gnat[1], gnat[0]])); - }; - function beaver(dunlin) { - return math.add(math.transpose(math.conv2d(math.transpose(dunlin, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[22], [2, 3, 1, 0], dunlin), [0, 1]), [1, 1], 1), [0, 3, 1, 2]), model.weights[23]); - }; - function kouprey(tapir) { - return math.relu(math.add(ape(tapir), bison(dogfish(math.relu(toad(beaver(flux.slice(tapir)))))))); - }; - function oyster(yak) { - return yak; - }; - function dog(reddeer) { - let ibex = reddeer[String("shape")][String("length")]; - let wombat = Array(ibex).fill(1); - let dragonfly = reddeer[String("shape")]; - wombat[ibex - 2] = dragonfly[dragonfly[String("length")] - (ibex - 1)]; - return math.add(math.mul(math.div(math.sub(reddeer, math.reshape(model.weights[24], [wombat[3], wombat[2], wombat[1], wombat[0]])), math.reshape(model.weights[25], [wombat[3], wombat[2], wombat[1], wombat[0]])), math.reshape(model.weights[26], [wombat[3], wombat[2], wombat[1], wombat[0]])), math.reshape(model.weights[27], [wombat[3], wombat[2], wombat[1], wombat[0]])); - }; - function cockroach(tarsier) { - return math.add(math.transpose(math.conv2d(math.transpose(tarsier, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[28], [2, 3, 1, 0], tarsier), [0, 1]), [1, 1], 1), [0, 3, 1, 2]), model.weights[29]); - }; - function alpaca(kudu) { - let komodo = kudu[String("shape")][String("length")]; - let narwhal = Array(komodo).fill(1); - let crow = kudu[String("shape")]; - narwhal[komodo - 2] = crow[crow[String("length")] - (komodo - 1)]; - return math.add(math.mul(math.div(math.sub(kudu, math.reshape(model.weights[30], [narwhal[3], narwhal[2], narwhal[1], narwhal[0]])), math.reshape(model.weights[31], [narwhal[3], narwhal[2], narwhal[1], narwhal[0]])), math.reshape(model.weights[32], [narwhal[3], narwhal[2], narwhal[1], narwhal[0]])), math.reshape(model.weights[33], [narwhal[3], narwhal[2], narwhal[1], narwhal[0]])); - }; - function guineapig(grouse) { - return math.add(math.transpose(math.conv2d(math.transpose(grouse, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[34], [2, 3, 1, 0], grouse), [0, 1]), [1, 1], 1), [0, 3, 1, 2]), model.weights[35]); - }; - function chinchilla(lark) { - return math.relu(math.add(oyster(lark), dog(cockroach(math.relu(alpaca(guineapig(flux.slice(lark)))))))); - }; - function spider(albatross) { - return albatross; - }; - function cobra(lion) { - let panther = lion[String("shape")][String("length")]; - let partridge = Array(panther).fill(1); - let chamois = lion[String("shape")]; - partridge[panther - 2] = chamois[chamois[String("length")] - (panther - 1)]; - return math.add(math.mul(math.div(math.sub(lion, math.reshape(model.weights[36], [partridge[3], partridge[2], partridge[1], partridge[0]])), math.reshape(model.weights[37], [partridge[3], partridge[2], partridge[1], partridge[0]])), math.reshape(model.weights[38], [partridge[3], partridge[2], partridge[1], partridge[0]])), math.reshape(model.weights[39], [partridge[3], partridge[2], partridge[1], partridge[0]])); - }; - function pony(chough) { - return math.add(math.transpose(math.conv2d(math.transpose(chough, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[40], [2, 3, 1, 0], chough), [0, 1]), [1, 1], 1), [0, 3, 1, 2]), model.weights[41]); - }; - function lemur(wren) { - let rhinoceros = wren[String("shape")][String("length")]; - let cheetah = Array(rhinoceros).fill(1); - let wildebeest = wren[String("shape")]; - cheetah[rhinoceros - 2] = wildebeest[wildebeest[String("length")] - (rhinoceros - 1)]; - return math.add(math.mul(math.div(math.sub(wren, math.reshape(model.weights[42], [cheetah[3], cheetah[2], cheetah[1], cheetah[0]])), math.reshape(model.weights[43], [cheetah[3], cheetah[2], cheetah[1], cheetah[0]])), math.reshape(model.weights[44], [cheetah[3], cheetah[2], cheetah[1], cheetah[0]])), math.reshape(model.weights[45], [cheetah[3], cheetah[2], cheetah[1], cheetah[0]])); - }; - function magpie(dove) { - return math.add(math.transpose(math.conv2d(math.transpose(dove, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[46], [2, 3, 1, 0], dove), [0, 1]), [1, 1], 1), [0, 3, 1, 2]), model.weights[47]); - }; - function hare(antelope) { - return math.relu(math.add(spider(antelope), cobra(pony(math.relu(lemur(magpie(flux.slice(antelope)))))))); - }; - function elk(moose) { - return moose; - }; - function gaur(curlew) { - let anteater = curlew[String("shape")][String("length")]; - let cassowary = Array(anteater).fill(1); - let swan = curlew[String("shape")]; - cassowary[anteater - 2] = swan[swan[String("length")] - (anteater - 1)]; - return math.add(math.mul(math.div(math.sub(curlew, math.reshape(model.weights[48], [cassowary[3], cassowary[2], cassowary[1], cassowary[0]])), math.reshape(model.weights[49], [cassowary[3], cassowary[2], cassowary[1], cassowary[0]])), math.reshape(model.weights[50], [cassowary[3], cassowary[2], cassowary[1], cassowary[0]])), math.reshape(model.weights[51], [cassowary[3], cassowary[2], cassowary[1], cassowary[0]])); - }; - function lapwing(goosander) { - return math.add(math.transpose(math.conv2d(math.transpose(goosander, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[52], [2, 3, 1, 0], goosander), [0, 1]), [1, 1], 1), [0, 3, 1, 2]), model.weights[53]); - }; - function jaguar(rook) { - let emu = rook[String("shape")][String("length")]; - let wolverine = Array(emu).fill(1); - let locust = rook[String("shape")]; - wolverine[emu - 2] = locust[locust[String("length")] - (emu - 1)]; - return math.add(math.mul(math.div(math.sub(rook, math.reshape(model.weights[54], [wolverine[3], wolverine[2], wolverine[1], wolverine[0]])), math.reshape(model.weights[55], [wolverine[3], wolverine[2], wolverine[1], wolverine[0]])), math.reshape(model.weights[56], [wolverine[3], wolverine[2], wolverine[1], wolverine[0]])), math.reshape(model.weights[57], [wolverine[3], wolverine[2], wolverine[1], wolverine[0]])); - }; - function ibis(hippopotamus) { - return math.add(math.transpose(math.conv2d(math.transpose(hippopotamus, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[58], [2, 3, 1, 0], hippopotamus), [0, 1]), [1, 1], 1), [0, 3, 1, 2]), model.weights[59]); - }; - function pelican(crane) { - return math.relu(math.add(elk(crane), gaur(lapwing(math.relu(jaguar(ibis(flux.slice(crane)))))))); - }; - function guanaco(barracuda) { - let dotterel = barracuda[String("shape")][String("length")]; - let goldfinch = Array(dotterel).fill(1); - let reindeer = barracuda[String("shape")]; - goldfinch[dotterel - 2] = reindeer[reindeer[String("length")] - (dotterel - 1)]; - return math.relu(math.add(math.mul(math.div(math.sub(barracuda, math.reshape(model.weights[60], [goldfinch[3], goldfinch[2], goldfinch[1], goldfinch[0]])), math.reshape(model.weights[61], [goldfinch[3], goldfinch[2], goldfinch[1], goldfinch[0]])), math.reshape(model.weights[62], [goldfinch[3], goldfinch[2], goldfinch[1], goldfinch[0]])), math.reshape(model.weights[63], [goldfinch[3], goldfinch[2], goldfinch[1], goldfinch[0]]))); - }; - function rabbit(whale) { - return math.add(math.transpose(math.conv2d(math.transpose(whale, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[64], [2, 3, 1, 0], whale), [0, 1]), [1, 1], 1), [0, 3, 1, 2]), model.weights[65]); - }; - function model(falcon) { - return cattle(kouprey(chinchilla(hare(pelican(guanaco(rabbit(falcon))))))); - }; - model.weights = []; - return model; -})(); diff --git a/experiments/go/assets/js/config.js b/experiments/go/assets/js/config.js deleted file mode 100644 index 2d2520d7..00000000 --- a/experiments/go/assets/js/config.js +++ /dev/null @@ -1,8 +0,0 @@ -// config -var config = { - board_size: 9, - num_readouts: 64, - two_player_mode: true, - resign_threshold: -0.9, - max_game_length: 100 -} \ No newline at end of file diff --git a/experiments/go/assets/js/extensions.js b/experiments/go/assets/js/extensions.js deleted file mode 100644 index aad74a55..00000000 --- a/experiments/go/assets/js/extensions.js +++ /dev/null @@ -1,53 +0,0 @@ -WGo.Board.prototype.render = function(config){ - this.restoreState(config.state); -} - -Game.prototype.nextGameState = function(curr){ - // console.log("turn....", this.env.turn()) - if(this.env.turn() == WGo.B)return this.states.H; - return this.states.C; -} - -Game.prototype.defaultAction = () => ({x: -1, y: -1, c: 1, type:"stone"}) - -Game.prototype.play = function(){ - clearTimeout(this.playTimeout); - if(this.env.done())return; - - var scope = this; - switch(this.state){ - case this.states.H: - this.move(this.newAction); - // newAction = 0; - break; - case this.states.C: - var move = this.move.bind(this) - this.model(this.env.state()).then( a => move(a)) - break; - default: - console.log("Invalid state", this.state); - } -} - -Game.prototype.startState = function (){ - return this.states.H; -} - - -function getState(env){ - var n = env.size; - var k = env.position.schema.slice(); - - var objects = []; - for(var i = 0; i< n; i++){ - var o = []; - for(var j = 0; j< n; j++){ - var c = k[i*n + j]; - if(c != 0)o.push([{x: i, y: j, c }]) - else o.push([]) - } - objects.push(o); - } - - return ({ objects }); -} diff --git a/experiments/go/assets/js/model.js b/experiments/go/assets/js/model.js deleted file mode 100644 index ccb5dd21..00000000 --- a/experiments/go/assets/js/model.js +++ /dev/null @@ -1,32 +0,0 @@ -function Model(model, config){ - this.mctsPlayer = new MCTS.Player(this, config); - this.model = model; - - this.predict = async function(config, cb){ - var a = await this.mctsPlayer.suggest_move(); - return a; - } - this.predict = this.predict.bind(this) -} - -Model.prototype.process = function(input){ - var l= input.length; - var p = new Array(l); - var [pi, val] = tf.tidy(() =>{ - for(var i=0; i document.querySelector(e); - var doNothing = async function (e){ return e}; - - function tidyWrap(f){ - return (x) => tf.tidy(() => f(x)) - } - - for(var i in model){ - model[i] = tidyWrap(model[i]); - } - - - - var pBar = document.createElement("div"); - pBar.className = "pbar"; - var controls = $$("#controls"); - controls.appendChild(pBar); - - board = new WGo.Board(document.querySelector("#playground"), { - width: 500, - section: { - top: -1, - left: -1, - right: -1, - bottom: -1 - } - }); - board.setSize(9) - - - config.layer = add_best; - config.progress = function(val){ - var w = val * controls.offsetWidth; - pBar.style.width = w + "px" - } - - env = new Env(config.board_size, "KO"); - model = new Model(model, config); - - env.setModel(model); - env.reset(); - - game = new Game(env, new Board(board), model.predict.bind(this), { - mode: "async", - transform: { - state: doNothing, - action: doNothing - } - }) - - board.addEventListener("click", function(x, y){ - // console.log(x, y, env.turn()) - if(env.turn() == WGo.B){ - game.action({type: "stone", x, y, c: WGo.B}); - } - }) - - $$("#controls .pass").addEventListener("click", function(event){ - game.action({type: "pass", c:WGo.b}) - }) - - drawCoords(board); - drawBest(board); - drawIllegal(board); - game.display(); - - var inc = document.createElement('div'); - var input = document.createElement('input') - var label = document.createElement('label') - inc.appendChild(label) - inc.appendChild(input) - $$(".demo_wrapper").insertBefore(inc, $$(".instructions")); - label.innerText = "Number of searches"; - input.type = "number"; - input.className="num_readouts" - input.value = model.mctsPlayer.num_readouts; - input.onchange = function(){ - model.mctsPlayer.num_readouts = parseInt(event.target.value); - } - - -} - -function drawCoords(){ - - var coordinates = { - // draw on grid layer - grid: { - draw: function(args, board) { - - var ch, t, xright, xleft, ytop, ybottom; - - this.fillStyle = "rgba(0,0,0,0.7)"; - this.textBaseline="middle"; - this.textAlign="center"; - this.font = board.stoneRadius+"px "+(board.font || ""); - - xright = board.getX(-0.75); - xleft = board.getX(board.size-0.25); - ytop = board.getY(-0.75); - ybottom = board.getY(board.size-0.25); - - for(var i = 0; i < board.size; i++) { - ch = i+"A".charCodeAt(0); - if(ch >= "I".charCodeAt(0)) ch++; - - t = board.getY(i); - this.fillText(board.size-i, xright, t); - this.fillText(board.size-i, xleft, t); - - t = board.getX(i); - this.fillText(String.fromCharCode(ch), t, ytop); - this.fillText(String.fromCharCode(ch), t, ybottom); - } - - this.fillStyle = "black"; - } - } - } - board.addCustomObject(coordinates); -} - - -var container = { - best: [], - getBest: function(){ - return this.best; - }, - setBest: function(arr){ - this.best = arr; - } -} - -var colors = ["#009688"] - -function drawBest(board){ - var best_layer = { - grid: { - draw: function(args, board){ - $$(".pass").style.borderStyle = "solid"; - var best = container.getBest(); - if(best.length == 0) return - for(var i = 0; i< best.length; i++){ - var fmove = best[i] + 1; - var {x, y, type} = MCTS.to_obj(fmove, -1, board.size); - // console.log(type, x, y) - if(x == -1 || y == -1) continue; - if(type == "pass"){ - $$(".pass").style.borderStyle = "dashed"; - continue - } - - var xr = board.getX(x), - yr = board.getY(y), - sr = ((board.stoneRadius - 2)/(i + 1)); - - this.beginPath(); - this.strokeStyle = colors[i] || colors[colors.length - 1]; - this.lineWidth = 2; - this.setLineDash([2]) - this.arc(xr, yr, sr, 0, 2*Math.PI, true); - this.stroke(); - this.setLineDash([]) - container.setBest([]); - } - } - } - } - board.addCustomObject(best_layer); -} - -function add_best (arr) { - container.setBest(arr) - board.redraw() -} - -function drawIllegal(board){ - var iLayer = { - grid:{ - draw:function(){ - var illegal = model.mctsPlayer.root.legal_moves() - .map((e,i)=> [e, i]).filter((e)=> e[0] == 0); - - if(illegal.length == 0) return - for(var i = 0; i< illegal.length; i++){ - var fmove = illegal[i][1] + 1; - var {x, y, type} = MCTS.to_obj(fmove, -1, board.size); - // console.log(type, x, y) - if(x == -1 || y == -1) continue; - - var xr = board.getX(x), - yr = board.getY(y), - sr = ((board.stoneRadius - 2)/(i + 1)); - - this.beginPath(); - this.fillStyle = "#8a1c1c"; - this.arc(xr, yr, 3, 0, 2*Math.PI, true); - this.fill(); - } - } - } - } - board.addCustomObject(iLayer); -} - - -}()); \ No newline at end of file diff --git a/experiments/go/assets/js/value.js b/experiments/go/assets/js/value.js deleted file mode 100644 index 1e058bc8..00000000 --- a/experiments/go/assets/js/value.js +++ /dev/null @@ -1,39 +0,0 @@ -/*********************** -Generated using FluxJS.jl -************************/ - -let value = (function () { - let math = tf; - function porcupine(hummingbird) { - return math.tanh(math.add(math.matMul(hummingbird, model.weights[0]), model.weights[1])); - }; - function okapi(cod) { - return math.relu(math.add(math.matMul(cod, model.weights[2]), model.weights[3])); - }; - function monkey(mink, mammoth) { - return (mink[String("size")]/mammoth); - }; - function kinkajou(porpoise, snake) { - return (porpoise*snake); - }; - function caterpillar(camel) { - let raven = camel[String("shape")]; - let snail = raven[raven[String("length")] - 4]; - return math.reshape(camel, [snail, monkey(camel, kinkajou(1, snail))]); - }; - function crab(pig) { - let cattle = pig[String("shape")][String("length")]; - let sealion = Array(cattle).fill(1); - let ape = pig[String("shape")]; - sealion[cattle - 2] = ape[ape[String("length")] - (cattle - 1)]; - return math.relu(math.add(math.mul(math.div(math.sub(pig, math.reshape(model.weights[4], [sealion[3], sealion[2], sealion[1], sealion[0]])), math.reshape(model.weights[5], [sealion[3], sealion[2], sealion[1], sealion[0]])), math.reshape(model.weights[6], [sealion[3], sealion[2], sealion[1], sealion[0]])), math.reshape(model.weights[7], [sealion[3], sealion[2], sealion[1], sealion[0]]))); - }; - function eagle(bison) { - return math.add(math.transpose(math.conv2d(math.transpose(bison, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[8], [2, 3, 1, 0], bison), [0, 1]), [1, 1], 0), [0, 3, 1, 2]), model.weights[9]); - }; - function model(jellyfish) { - return porcupine(okapi(caterpillar(crab(eagle(jellyfish))))); - }; - model.weights = []; - return model; -})(); diff --git a/experiments/go/assets/wgo/black_128.png b/experiments/go/assets/wgo/black_128.png deleted file mode 100644 index cc257497..00000000 Binary files a/experiments/go/assets/wgo/black_128.png and /dev/null differ diff --git a/experiments/go/assets/wgo/black_64.png b/experiments/go/assets/wgo/black_64.png deleted file mode 100644 index cd158a27..00000000 Binary files a/experiments/go/assets/wgo/black_64.png and /dev/null differ diff --git a/experiments/go/assets/wgo/wgo.min.js b/experiments/go/assets/wgo/wgo.min.js deleted file mode 100644 index 5eeb6cbc..00000000 --- a/experiments/go/assets/wgo/wgo.min.js +++ /dev/null @@ -1,51 +0,0 @@ -/*! MIT license, more info: wgo.waltheri.net */(function(v,q){var m=document.getElementsByTagName("script"),g={version:"2.3.1",B:1,W:-1,ERROR_REPORT:!0,DIR:m[m.length-1].src.split("?")[0].split("/").slice(0,-1).join("/")+"/",lang:"en",i18n:{en:{}}};g.opera=-1!=navigator.userAgent.search(/(opera)(?:.*version)?[ \/]([\w.]+)/i);g.webkit=-1!=navigator.userAgent.search(/(webkit)[ \/]([\w.]+)/i);g.msie=-1!=navigator.userAgent.search(/(msie) ([\w.]+)/i);g.mozilla=-1!=navigator.userAgent.search(/(mozilla)(?:.*? rv:([\w.]+))?/i)&&!g.webkit&&!g.msie;g.t= -function(a){var b=g.i18n[g.lang][a]||g.i18n.en[a];if(b){for(var c=1;c/g,">"):a};var h=function(a,b){b=b||{};for(var c in b)this[c]=b[c];for(c in g.Board.default)this[c]===q&&(this[c]=g.Board.default[c]);for(c in h.themes.default)this.theme[c]===q&&(this.theme[c]=h.themes.default[c]);this.tx=this.section.left;this.ty=this.section.top;this.bx=this.size-1-this.section.right;this.by=this.size-1-this.section.bottom;this.init();a.appendChild(this.element);this.pixelRatio=v.devicePixelRatio||1;this.width&&this.height? -this.setDimensions(this.width,this.height):this.width?this.setWidth(this.width):this.height&&this.setHeight(this.height)};h.themes={};h.themes.old={shadowColor:"rgba(32,32,32,0.5)",shadowTransparentColor:"rgba(32,32,32,0)",shadowBlur:0,shadowSize:function(a){return a.shadowSize},markupBlackColor:"rgba(255,255,255,0.8)",markupWhiteColor:"rgba(0,0,0,0.8)",markupNoneColor:"rgba(0,0,0,0.8)",markupLinesWidth:function(a){return a.autoLineWidth?a.stoneRadius/7:a.lineWidth},gridLinesWidth:1,gridLinesColor:function(a){return"rgba(0,0,0,"+ -Math.min(1,a.stoneRadius/15)+")"},starColor:"#000",starSize:function(a){return a.starSize*(a.width/300+1)},stoneSize:function(a){return a.stoneSize*Math.min(a.fieldWidth,a.fieldHeight)/2},coordinatesColor:"rgba(0,0,0,0.7)",font:function(a){return a.font},linesShift:.5};h.themes.default={shadowColor:"rgba(62,32,32,0.5)",shadowTransparentColor:"rgba(62,32,32,0)",shadowBlur:function(a){return.1*a.stoneRadius},shadowSize:1,markupBlackColor:"rgba(255,255,255,0.9)",markupWhiteColor:"rgba(0,0,0,0.7)",markupNoneColor:"rgba(0,0,0,0.7)", -markupLinesWidth:function(a){return a.stoneRadius/8},gridLinesWidth:function(a){return a.stoneRadius/15},gridLinesColor:"#654525",starColor:"#531",starSize:function(a){return a.stoneRadius/8+1},stoneSize:function(a){return Math.min(a.fieldWidth,a.fieldHeight)/2},coordinatesColor:"#531",variationColor:"rgba(0,32,128,0.8)",font:"calibri",linesShift:.25};var k=function(a,b){return"function"==typeof b.theme[a]?b.theme[a](b):b.theme[a]},m={draw:function(a,b){var c=b.getX(a.x),e=b.getY(a.y),d=b.stoneRadius; -this.beginPath();var f=k("shadowBlur",b),d=Math.max(0,d-.5),n=this.createRadialGradient(c-b.ls,e-b.ls,d-1-f,c-b.ls,e-b.ls,d+f);n.addColorStop(0,k("shadowColor",b));n.addColorStop(1,k("shadowTransparentColor",b));this.fillStyle=n;this.arc(c-b.ls,e-b.ls,d+f,0,2*Math.PI,!0);this.fill()},clear:function(a,b){var c=b.getX(a.x),e=b.getY(a.y),d=b.stoneRadius;this.clearRect(c-1.1*d-b.ls,e-1.1*d-b.ls,2.2*d,2.2*d)}},p=function(a,b,c){return a.obj_arr[b][c][0].c==g.B?k("markupBlackColor",a):a.obj_arr[b][c][0].c== -g.W?k("markupWhiteColor",a):k("markupNoneColor",a)},D=function(a,b,c){return a.obj_arr[b][c][0]&&a.obj_arr[b][c][0].c==g.W||a.obj_arr[b][c][0].c==g.B},w,y=function(a){for(var b=a.angle,c=a.angle,e=0;el?(k=(n-h)/(f-l),r=Math.atan(k)):f==l?r=Math.PI/2:(k=(n-h)/(f-l),r=Math.atan(k)-Math.PI);g*=m;k=Math.sin(r)*g;r=Math.cos(r)*g;g=l+k;m=h-r;k=f+k;r=n-r;d.moveTo(l,h);d.bezierCurveTo(g,m,k,r,f,n);d.stroke()}};h.drawHandlers={NORMAL:{stone:{draw:function(a,b){var c=b.getX(a.x),e=b.getY(a.y),d=b.stoneRadius,f;a.c==g.W?(f=this.createRadialGradient(c-2*d/5,e-2*d/5,d/3,c-d/5,e-d/5,5*d/5),f.addColorStop(0,"#fff"),f.addColorStop(1,"#aaa")):(f=this.createRadialGradient(c- -2*d/5,e-2*d/5,1,c-d/5,e-d/5,4*d/5),f.addColorStop(0,"#666"),f.addColorStop(1,"#000"));this.beginPath();this.fillStyle=f;this.arc(c-b.ls,e-b.ls,Math.max(0,d-.5),0,2*Math.PI,!0);this.fill()}},shadow:m},PAINTED:{stone:{draw:function(a,b){var c=b.getX(a.x),e=b.getY(a.y),d=b.stoneRadius,f;a.c==g.W?(f=this.createRadialGradient(c-2*d/5,e-2*d/5,2,c-d/5,e-d/5,4*d/5),f.addColorStop(0,"#fff"),f.addColorStop(1,"#ddd")):(f=this.createRadialGradient(c-2*d/5,e-2*d/5,1,c-d/5,e-d/5,4*d/5),f.addColorStop(0,"#111"), -f.addColorStop(1,"#000"));this.beginPath();this.fillStyle=f;this.arc(c-b.ls,e-b.ls,Math.max(0,d-.5),0,2*Math.PI,!0);this.fill();this.beginPath();this.lineWidth=d/6;a.c==g.W?(this.strokeStyle="#999",this.arc(c+d/8,e+d/8,d/2,0,Math.PI/2,!1)):(this.strokeStyle="#ccc",this.arc(c-d/8,e-d/8,d/2,Math.PI,1.5*Math.PI));this.stroke()}},shadow:m},GLOW:{stone:{draw:function(a,b){var c=b.getX(a.x),e=b.getY(a.y),d=b.stoneRadius,f;a.c==g.W?(f=this.createRadialGradient(c-2*d/5,e-2*d/5,d/3,c-d/5,e-d/5,8*d/5),f.addColorStop(0, -"#fff"),f.addColorStop(1,"#666")):(f=this.createRadialGradient(c-2*d/5,e-2*d/5,1,c-d/5,e-d/5,3*d/5),f.addColorStop(0,"#555"),f.addColorStop(1,"#000"));this.beginPath();this.fillStyle=f;this.arc(c-b.ls,e-b.ls,Math.max(0,d-.5),0,2*Math.PI,!0);this.fill()}},shadow:m},SHELL:{stone:{draw:function(a,b){var c,e,d=b.stoneRadius;w=w||Math.ceil(9999999*Math.random());c=b.getX(a.x);e=b.getY(a.y);var f;f=a.c==g.W?"#aaa":"#000";this.beginPath();this.fillStyle=f;this.arc(c-b.ls,e-b.ls,Math.max(0,d-.5),0,2*Math.PI, -!0);this.fill();if(a.c==g.W){f=w%(3+a.x*b.size+a.y)%3;var n=b.size*b.size+a.x*b.size+a.y,n=2/n*(w%n);0==f?y({ctx:this,x:c,y:e,radius:d,angle:n,lines:[.1,.12,.11,.1,.09,.09,.09,.09],factor:.25,thickness:1.75}):1==f?y({ctx:this,x:c,y:e,radius:d,angle:n,lines:[.1,.09,.08,.07,.06,.06,.06,.06,.06,.06,.06],factor:.2,thickness:1.5}):y({ctx:this,x:c,y:e,radius:d,angle:n,lines:[.12,.14,.13,.12,.12,.12],factor:.3,thickness:2});f=this.createRadialGradient(c-2*d/5,e-2*d/5,d/3,c-d/5,e-d/5,5*d/5);f.addColorStop(0, -"rgba(255,255,255,0.9)");f.addColorStop(1,"rgba(255,255,255,0)")}else f=this.createRadialGradient(c+.4*d,e+.4*d,0,c+.5*d,e+.5*d,d),f.addColorStop(0,"rgba(32,32,32,1)"),f.addColorStop(1,"rgba(0,0,0,0)"),this.beginPath(),this.fillStyle=f,this.arc(c-b.ls,e-b.ls,Math.max(0,d-.5),0,2*Math.PI,!0),this.fill(),f=this.createRadialGradient(c-.4*d,e-.4*d,1,c-.5*d,e-.5*d,1.5*d),f.addColorStop(0,"rgba(64,64,64,1)"),f.addColorStop(1,"rgba(0,0,0,0)");this.beginPath();this.fillStyle=f;this.arc(c-b.ls,e-b.ls,Math.max(0, -d-.5),0,2*Math.PI,!0);this.fill()}},shadow:m},MONO:{stone:{draw:function(a,b){var c=b.getX(a.x),e=b.getY(a.y),d=b.stoneRadius,f=k("markupLinesWidth",b)||1;this.fillStyle=a.c==g.W?"white":"black";this.beginPath();this.arc(c,e,Math.max(0,d-f),0,2*Math.PI,!0);this.fill();this.lineWidth=f;this.strokeStyle="black";this.stroke()}}},CR:{stone:{draw:function(a,b){var c=b.getX(a.x),e=b.getY(a.y),d=b.stoneRadius;this.strokeStyle=a.c||p(b,a.x,a.y);this.lineWidth=a.lineWidth||k("markupLinesWidth",b)||1;this.beginPath(); -this.arc(c-b.ls,e-b.ls,d/2,0,2*Math.PI,!0);this.stroke()}}},LB:{stone:{draw:function(a,b){var c=b.getX(a.x),e=b.getY(a.y),d=b.stoneRadius,f=a.font||k("font",b)||"";this.fillStyle=a.c||p(b,a.x,a.y);this.font=1==a.text.length?Math.round(1.5*d)+"px "+f:2==a.text.length?Math.round(1.2*d)+"px "+f:Math.round(d)+"px "+f;this.beginPath();this.textBaseline="middle";this.textAlign="center";this.fillText(a.text,c,e,2*d)}},grid:{draw:function(a,b){if(!D(b,a.x,a.y)&&!a._nodraw){var c=b.getX(a.x),e=b.getY(a.y), -d=b.stoneRadius;this.clearRect(c-d,e-d,2*d,2*d)}},clear:function(a,b){if(!D(b,a.x,a.y)){a._nodraw=!0;var c;b.grid.clear();b.grid.draw(b);for(var e=0;e=this.size?-1:b,y:a>=this.size?-1:a}},C=function(){this.element.style.width=this.width/this.pixelRatio+"px";this.element.style.height= -this.height/this.pixelRatio+"px";this.stoneRadius=k("stoneSize",this);this.ls=k("linesShift",this);for(var a=0;aa||0>b||a>=this.size||b>=this.size?q:this.schema[a*this.size+b]},set:function(a,b,c){this.schema[a*this.size+b]=c;return this},clear:function(){for(var a=0;ac||c>=a.size||0>e||e>=a.size)return!0;if(0==a.get(c,e))return!1;if(!0==b.get(c,e)||a.get(c,e)==-d)return!0;b.set(c,e,!0);return u(a,b,c,e-1,d)&&u(a,b,c,e+1,d)&&u(a,b,c-1,e,d)&&u(a,b,c+1,e,d)},l=function(a,b,c,e){var d=[];if(0<=b&&b=m;p--)if(this.stack[p].get(a,b)==d.get(a,b)){for(var k=!0,q=0;q'+b.t("show")+""}};m.infoList="black white AN CP DT EV GN GC HA ON OT RE RO RU SO TM US PC KM".split(" "); -b.Kifu=m;var c=function(c,a,e){for(var h=0;h=a.size&&"tt"==k[0]?{pass:!0,c:"B"==e?b.B:b.W}:{x:k[0].charCodeAt(0)-97,y:k[0].charCodeAt(1)-97,c:"B"==e?b.B:b.W}};f.AB=f.AW=function(a,d,k,e){for(var c in k)d.addSetup({x:k[c].charCodeAt(0)-97,y:k[c].charCodeAt(1)-97,c:"AB"==e?b.B:b.W})};f.AE=function(a,d,b){for(var e in b)d.addSetup({x:b[e].charCodeAt(0)-97,y:b[e].charCodeAt(1)- -97})};f.PL=function(a,d,k){d.turn="b"==k[0]||"B"==k[0]?b.B:b.W};f.C=function(a,d,b){d.comment=b.join()};f.LB=function(a,d,b){for(var e in b)d.addMarkup({x:b[e].charCodeAt(0)-97,y:b[e].charCodeAt(1)-97,type:"LB",text:b[e].substr(3)})};f.CR=f.SQ=f.TR=f.SL=f.MA=function(a,d,b,e){for(var c in b)d.addMarkup({x:b[c].charCodeAt(0)-97,y:b[c].charCodeAt(1)-97,type:e})};f.SZ=function(a,d,b){a.size=parseInt(b[0])};f.BR=f.WR=g.bind(this,"rank","BR");f.PB=f.PW=g.bind(this,"name","PB");f.BT=f.WT=g.bind(this,"team", -"BT");f.TM=function(a,d,b,e){a.info[e]=b[0];d.BL=b[0];d.WL=b[0]};var l=/\(|\)|(;(\s*[A-Z]+(\s*((\[\])|(\[(.|\s)*?([^\\]\]))))+)*)/g,d=/[A-Z]+(\s*((\[\])|(\[(.|\s)*?([^\\]\]))))+/g,k=/[A-Z]+/,a=/(\[\])|(\[(.|\s)*?([^\\]\]))/g;b.SGF.parse=function(h){var f=[],g,e,c,q=new b.Kifu,r=null;h=h.match(l);for(var p in h)if("("==h[p])f.push(r);else if(")"==h[p])r=f.pop();else{r&&q.nodeCount++;r=r?r.appendChild(new b.KNode):q.root;g=h[p].match(d)||[];q.propertyCount+=g.length;for(var w in g){c=k.exec(g[w])[0]; -e=g[w].match(a);for(var v in e)e[v]=e[v].substring(1,e[v].length-1).replace(/\\(?!\\)/g,"");if(b.SGF.properties[c])b.SGF.properties[c](q,r,e,c);else 1>=e.length&&(e=e[0]),r.parent?r[c]=e:q.info[c]=e}}return q}})(WGo);(function(b){var p=function(c,a){this.name="FileError";this.message=1==a?"File '"+c+"' is empty.":2==a?"Network error. It is not possible to read '"+c+"'.":"File '"+c+"' hasn't been found on server."};p.prototype=Error();p.prototype.constructor=p;b.FileError=p;var g=b.loadFromUrl=function(c,a){var e=new XMLHttpRequest;e.onreadystatechange=function(){if(4==e.readyState)if(200==e.status){if(0==e.responseText.length)throw new p(c,1);a(e.responseText)}else throw new p(c);};try{e.open("GET",c,!0),e.send()}catch(d){throw new p(c, -2);}},f=function(c){c.change&&this.board.update(c.change);this.temp_marks&&this.board.removeObject(this.temp_marks);var a=[];this.notification();c.node.move&&this.config.markLastMove&&(c.node.move.pass?this.notification(b.t((c.node.move.c==b.B?"b":"w")+"pass")):a.push({type:"CR",x:c.node.move.x,y:c.node.move.y}));if(1c.offsetHeight&&"auto"==window.getComputedStyle(c).overflow?!0:d(c.parentNode,a)},k=function(c){var a=c.wheelDelta||-1*c.detail;return d(c.target,this)?!0:0>a?(this.next(),this.config.lockScroll&&c.preventDefault&&c.preventDefault(),!this.config.lockScroll):0WGo.js Player 2.0

WGo.js Player is extension of WGo.js, HTML5 library for purposes of game of go. It allows to replay go game records and it has many features like score counting. It is also designed to be easily extendable.

WGo.js is open source licensed under MIT license. You can use and modify any code from this project.

You can find more information at wgo.waltheri.net/player

Copyright © 2013 Jan Prokop

", -black:"Black",white:"White",DT:"Date",KM:"Komi",HA:"Handicap",AN:"Annotations",CP:"Copyright",GC:"Game comments",GN:"Game name",ON:"Fuseki",OT:"Overtime",TM:"Basic time",RE:"Result",RO:"Round",RU:"Rules",US:"Recorder",PC:"Place",EV:"Event",SO:"Source",none:"none",bpass:"Black passed.",wpass:"White passed."},e;for(e in m)b.i18n.en[e]=m[e]})(WGo);(function(b){var p=0,g=function(d,b,a){var h={};h.element=document.createElement("div");h.element.className="wgo-player-"+d;h.wrapper=document.createElement("div");h.wrapper.className="wgo-player-"+d+"-wrapper";h.element.appendChild(h.wrapper);b.appendChild(h.element);a||(h.element.style.display="none");return h},f=function(d){var b;if(b=this.currentLayout.layout?this.currentLayout.layout[d]:this.currentLayout[d]){this.regions[d].element.style.display="block";b.constructor!=Array&&(b=[b]);for(var a in b)this.components[b[a]]|| -(this.components[b[a]]=new l.component[b[a]](this)),this.components[b[a]].appendTo(this.regions[d].wrapper),this.components[b[a]]._detachFromPlayer=!1}else this.regions[d].element.style.display="none"},l=b.extendClass(b.Player,function(d,k){this.config=k;for(var a in l.default)void 0===this.config[a]&&void 0!==l.default[a]&&(this.config[a]=l.default[a]);for(a in b.Player.default)void 0===this.config[a]&&void 0!==b.Player.default[a]&&(this.config[a]=b.Player.default[a]);this.element=d;this.element.innerHTML= -"";this.classes=(this.element.className?this.element.className+" ":"")+"wgo-player-main";this.element.className=this.classes;this.element.id||(this.element.id="wgo_"+p++);this.dom={};this.dom.center=document.createElement("div");this.dom.center.className="wgo-player-center";this.dom.board=document.createElement("div");this.dom.board.className="wgo-player-board";this.regions={};this.regions.left=g("left",this.element);this.element.appendChild(this.dom.center);this.regions.right=g("right",this.element); -this.regions.top=g("top",this.dom.center);this.dom.center.appendChild(this.dom.board);this.regions.bottom=g("bottom",this.dom.center);this.board=new b.Board(this.dom.board,this.config.board);this.init();this.components={};window.addEventListener("resize",function(){this.noresize||this.updateDimensions()}.bind(this));this.updateDimensions();this.initGame()});l.prototype.appendTo=function(d){d.appendChild(this.element);this.updateDimensions()};l.prototype.updateDimensions=function(){for(var d=window.getComputedStyle(this.element), -b=[];this.element.firstChild;)b.push(this.element.firstChild),this.element.removeChild(this.element.firstChild);for(var a=parseInt(d.width),h=parseInt(d.height),n=parseInt(d.maxHeight)||0,d=0;d=this.width)||b[h].conditions.maxHeight&&a&&!(b[h].conditions.maxHeight>=a)||b[h].conditions.custom&&!b[h].conditions.custom.call(this))){b=b[h];break a}b=void 0}if((this.currentLayout=b)&&this.lastLayout!=this.currentLayout){this.element.className=this.currentLayout.className?this.classes+" "+this.currentLayout.className:this.classes;for(var g in this.components)this.components[g]._detachFromPlayer= -!0;f.call(this,"left");f.call(this,"right");f.call(this,"top");f.call(this,"bottom");for(g in this.components)this.components[g]._detachFromPlayer&&this.components[g].element.parentNode&&this.components[g].element.parentNode.removeChild(this.components[g].element);this.lastLayout=this.currentLayout}b=this.dom.board.clientWidth;(g=this.height||this.maxHeight)&&(g-=this.regions.top.element.offsetHeight+this.regions.bottom.element.offsetHeight);g&&g"+d.name+"

"+d.message+'

If this message isn\'t correct, please report it by clicking here, otherwise contact maintainer of this site.

'); -break;case "FileError":this.showMessage("

"+d.name+"

"+d.message+"

Please contact maintainer of this site. Note: it is possible to read files only from this host.

");break;default:this.showMessage("

"+d.name+"

"+d.message+"

"+d.stacktrace+'

Please contact maintainer of this site. You can also report it here.

')}};l.component={};l.layouts={one_column:{top:[],bottom:[]},no_comment:{top:[],bottom:[]},right_top:{top:[],right:[]},right:{right:[]}, -minimal:{bottom:[]}};l.dynamicLayout=[{conditions:{minWidth:650},layout:l.layouts.right_top,className:"wgo-twocols wgo-large"},{conditions:{minWidth:550,minHeight:600},layout:l.layouts.one_column,className:"wgo-medium"},{conditions:{minWidth:350},layout:l.layouts.no_comment,className:"wgo-small"},{layout:l.layouts.no_comment,className:"wgo-xsmall"}];l.default={layout:l.dynamicLayout};b.i18n.en["BP:closemsg"]="click anywhere to close this window";l.attributes={"data-wgo":function(b){b&&("("==b[0]? -this.sgf=b:this.sgfFile=b)},"data-wgo-board":function(b){this.board=eval("({"+b+"})")},"data-wgo-onkifuload":function(b){this.kifuLoaded=new Function(b)},"data-wgo-onupdate":function(b){this.update=new Function(b)},"data-wgo-onfrozen":function(b){this.frozen=new Function(b)},"data-wgo-onunfrozen":function(b){this.unfrozen=new Function(b)},"data-wgo-layout":function(b){this.layout=eval("({"+b+"})")},"data-wgo-enablewheel":function(b){"false"==b.toLowerCase()&&(this.enableWheel=!1)},"data-wgo-lockscroll":function(b){"false"== -b.toLowerCase()&&(this.lockScroll=!1)},"data-wgo-enablekeys":function(b){"false"==b.toLowerCase()&&(this.enableKeys=!1)},"data-wgo-rememberpath":function(b){"false"==b.toLowerCase()&&(this.rememberPath=!1)},"data-wgo-allowillegal":function(b){"false"!=b.toLowerCase()&&(this.allowIllegalMoves=!0)},"data-wgo-move":function(b){var f=parseInt(b);this.move=f?f:eval("({"+b+"})")},"data-wgo-marklastmove":function(b){"false"==b.toLowerCase()&&(this.markLastMove=!1)},"data-wgo-diagram":function(b){b&&("("== -b[0]?this.sgf=b:this.sgfFile=b,this.enableWheel=this.enableKeys=this.markLastMove=!1,this.layout={top:[],right:[],left:[],bottom:[]})}};b.BasicPlayer=l;window.addEventListener("load",function(){for(var b=document.querySelectorAll("[data-wgo],[data-wgo-diagram]"),f=0;fa.offsetHeight)for(d-=2;a.scrollHeight>a.offsetHeight&&1a.offsetHeight&&(a.style.fontSize=d-4+"px")}},l=function(a){a.node.BL&&this.setPlayerTime("black",a.node.BL);a.node.WL&&this.setPlayerTime("white",a.node.WL);void 0!==a.position.capCount.black&&(this.black.info.caps.val.innerHTML= -a.position.capCount.black);void 0!==a.position.capCount.white&&(this.white.info.caps.val.innerHTML=a.position.capCount.white)},d=WGo.extendClass(WGo.BasicPlayer.component.Component,function(a){this.super(a);this.element.className="wgo-infobox";b.call(this,"white");b.call(this,"black");this.element.appendChild(this.white.box);this.element.appendChild(this.black.box);a.addEventListener("kifuLoaded",g.bind(this));a.addEventListener("update",l.bind(this))});d.prototype.setPlayerTime=function(a,b){var d= -Math.floor(b/60),f=Math.round(b)%60;this[a].info.time.val.innerHTML=d+":"+(10>f?"0"+f:f)};d.prototype.updateDimensions=function(){f(this.black.name);f(this.white.name)};var k=WGo.BasicPlayer.layouts;k.right_top.right.push("InfoBox");k.right.right.push("InfoBox");k.one_column.top.push("InfoBox");k.no_comment.top.push("InfoBox");WGo.i18n.en.rank="Rank";WGo.i18n.en.caps="Caps";WGo.i18n.en.time="Time";WGo.BasicPlayer.component.InfoBox=d})(WGo);(function(b,p){var g=function(a){var b,d;b=a.charCodeAt(0)-97;0>b&&(b+=32);7");for(var g in a)f+='
'+g+''+a[g]+"
";return f+""},k=b.extendClass(b.BasicPlayer.component.Component,function(a){this.super(a);this.player=a;this.element.className="wgo-commentbox";this.box=document.createElement("div"); -this.box.className="wgo-box-wrapper wgo-comments-wrapper";this.element.appendChild(this.box);this.comments_title=document.createElement("div");this.comments_title.className="wgo-box-title";this.comments_title.innerHTML=b.t("comments");this.box.appendChild(this.comments_title);this.comments=document.createElement("div");this.comments.className="wgo-comments-content";this.box.appendChild(this.comments);this.help=document.createElement("div");this.help.className="wgo-help";this.help.style.display="none"; -this.comments.appendChild(this.help);this.notification=document.createElement("div");this.notification.className="wgo-notification";this.notification.style.display="none";this.comments.appendChild(this.notification);this.comment_text=document.createElement("div");this.comment_text.className="wgo-comment-text";this.comments.appendChild(this.comment_text);a.addEventListener("kifuLoaded",function(h){h.kifu.hasComments()?(this.comments_title.innerHTML=b.t("comments"),this.element.className="wgo-commentbox", -this._update=function(a){this.setComments(a)}.bind(this),a.addEventListener("update",this._update)):(this.comments_title.innerHTML=b.t("gameinfo"),this.element.className="wgo-commentbox wgo-gameinfo",this._update&&(a.removeEventListener("update",this._update),delete this._update),this.comment_text.innerHTML=d(h.target.getGameInfo()))}.bind(this));a.notification=function(a){a?(this.notification.style.display="block",this.notification.innerHTML=a,this.is_notification=!0):(this.notification.style.display= -"none",this.is_notification=!1)}.bind(this);a.help=function(a){a?(this.help.style.display="block",this.help.innerHTML=a,this.is_help=!0):(this.help.style.display="none",this.is_help=!1)}.bind(this)});k.prototype.setComments=function(a){this.player._tmp_mark&&f.call(this.player);var b="";a.node.parent||(b=d(a.target.getGameInfo(),!0));this.comment_text.innerHTML=b+this.getCommentText(a.node.comment,this.player.config.formatNicks,this.player.config.formatMoves);this.player.config.formatMoves&&this.comment_text.childNodes&& -this.comment_text.childNodes.length&&l(this.comment_text.childNodes,this.player)};k.prototype.getCommentText=function(a,d,f){return a?(a="

"+b.filterHTML(a).replace(/\n/g,"

")+"

",d&&(a=a.replace(/(

)([^:]{3,}:)\s/g,'

$2 ')),f&&(a=a.replace(/\b[a-zA-Z]1?\d\b/g,'$&')),a):""};b.BasicPlayer.default.formatNicks=!0;b.BasicPlayer.default.formatMoves=!0;b.BasicPlayer.attributes["data-wgo-formatnicks"]= -function(a){"false"==a.toLowerCase()&&(this.formatNicks=!1)};b.BasicPlayer.attributes["data-wgo-formatmoves"]=function(a){"false"==a.toLowerCase()&&(this.formatMoves=!1)};b.BasicPlayer.layouts.right_top.right.push("CommentBox");b.BasicPlayer.layouts.right.right.push("CommentBox");b.BasicPlayer.layouts.one_column.bottom.push("CommentBox");b.i18n.en.comments="Comments";b.i18n.en.gameinfo="Game info";b.BasicPlayer.component.CommentBox=k})(WGo);(function(b,p){var g=b.extendClass(b.BasicPlayer.component.Component,function(a){this.super(a);this.widgets=[];this.element.className="wgo-player-control";this.iconBar=document.createElement("div");this.iconBar.className="wgo-control-wrapper";this.element.appendChild(this.iconBar);var b,d;for(d in g.widgets)b=new g.widgets[d].constructor(a,g.widgets[d].args),b.appendTo(this.iconBar),this.widgets.push(b)});g.prototype.updateDimensions=function(){this.element.className=340>this.element.clientWidth? -"wgo-player-control wgo-340":440>this.element.clientWidth?"wgo-player-control wgo-440":"wgo-player-control"};var f=b.BasicPlayer.control={},l=function(a){a.node.parent||this.disabled?a.node.parent&&this.disabled&&this.enable():this.disable()},d=function(a){a.node.children.length||this.disabled?a.node.children.length&&this.disabled&&this.enable():this.disable()},k=function(a){(this._disabled=this.disabled)||this.disable()},a=function(a){this._disabled||this.enable();delete this._disabled};f.Widget= -function(a,b){this.element=this.element||document.createElement(b.type||"div");this.element.className="wgo-widget-"+b.name;this.init(a,b)};f.Widget.prototype={constructor:f.Widget,init:function(a,b){b&&(b.disabled&&this.disable(),b.init&&b.init.call(this,a))},appendTo:function(a){a.appendChild(this.element)},disable:function(){this.disabled=!0;-1==this.element.className.search("wgo-disabled")&&(this.element.className+=" wgo-disabled")},enable:function(){this.disabled=!1;this.element.className=this.element.className.replace(" wgo-disabled", -"");this.element.disabled=""}};f.Group=b.extendClass(f.Widget,function(a,b){this.element=document.createElement("div");this.element.className="wgo-ctrlgroup wgo-ctrlgroup-"+b.name;var d,f;for(f in b.widgets)d=new b.widgets[f].constructor(a,b.widgets[f].args),d.appendTo(this.element)});f.Clickable=b.extendClass(f.Widget,function(a,b){this.super(a,b)});f.Clickable.prototype.init=function(a,b){var d,f=this;d=b.togglable?function(){f.disabled||(b.click.call(f,a)?f.select():f.unselect())}:function(){f.disabled|| -b.click.call(f,a)};this.element.addEventListener("click",d);this.element.addEventListener("touchstart",function(a){a.preventDefault();d();b.multiple&&(f._touch_i=0,f._touch_int=window.setInterval(function(){500"+b.t("RE")+"

";m=d.length+n.length+this.originalPosition.capCount.black;e=f.length+h.length+this.originalPosition.capCount.white+parseFloat(this.komi);a+="

"+b.t("black")+": "+d.length+" + "+(n.length+this.originalPosition.capCount.black)+ -" = "+m+"
";a+=b.t("white")+": "+f.length+" + "+(h.length+this.originalPosition.capCount.white)+" + "+this.komi+" = "+e+"

";a=m>e?a+("

"+b.t("bwin",m-e)+"

"):a+("

"+b.t("wwin",e-m)+"

");this.output(a)};p.prototype.calculate=function(){var b,f,a,h,n,m;b=this.position;for(m=!0;m;){m=!1;for(var e=0;el;l++)a[l]==g.BLACK_STONE||a[l]==g.BLACK_CANDIDATE?h=!0:a[l]==g.WHITE_STONE||a[l]==g.WHITE_CANDIDATE?n=!0:a[l]==g.NEUTRAL&&(n=h=!0);a=!1;h&&n?a=g.NEUTRAL:h?a=g.BLACK_CANDIDATE:n&&(a=g.WHITE_CANDIDATE);a&&f!=a&&(m=!0,b.set(c,e,a))}}};b.ScoreMode=p;b.BasicPlayer&&b.BasicPlayer.component.Control&&b.BasicPlayer.component.Control.menu.push({constructor:b.BasicPlayer.control.MenuItem,args:{name:"scoremode",togglable:!0,click:function(d){if(this.selected)return d.setFrozen(!1), -this._score_mode.end(),delete this._score_mode,d.notification(),d.help(),!1;d.setFrozen(!0);d.help("

"+b.t("help_score")+"

");this._score_mode=new b.ScoreMode(d.kifuReader.game.position,d.board,d.kifu.info.KM||.5,d.notification);this._score_mode.start();return!0}}});b.i18n.en.scoremode="Count score";b.i18n.en.score="Score";b.i18n.en.bwin="Black wins by $ points.";b.i18n.en.wwin="White wins by $ points.";b.i18n.en.help_score="Click on stones to mark them dead or alive. You can also set and unset territory points by clicking on them. Territories must be completely bordered."})(WGo);(function(b,p){var g={active:!0,query:{}},f=function(b){try{g.query=JSON.parse('{"'+window.location.hash.substr(1).replace("=",'":')+"}")}catch(f){g.query={}}};window.addEventListener("hashchange",function(){if(""!=window.location.hash&&g.active){f();for(var b in g.query){var k=document.getElementById(b);k&&k._wgo_player&&k._wgo_player.goTo(l)}}});window.addEventListener("DOMContentLoaded",function(){""!=window.location.hash&&g.active&&f()});window.addEventListener("load",function(){if(""!=window.location.hash&& -g.active)for(var b in g.query){var f=document.getElementById(b);if(f&&f._wgo_player){f.scrollIntoView();break}}});var l=function(){if(g.query[this.element.id])return g.query[this.element.id].goto};b.Player.default.move=l;b.BasicPlayer&&b.BasicPlayer.component.Control&&b.BasicPlayer.component.Control.menu.push({constructor:b.BasicPlayer.control.MenuItem,args:{name:"permalink",click:function(d){var f=location.href.split("#")[0]+"#"+d.element.id+'={"goto":'+JSON.stringify(d.kifuReader.path)+"}";d.showMessage("

"+ -b.t("permalink")+'

')}}});b.Player.permalink=g;b.i18n.en.permalink="Permanent link"})(WGo); diff --git a/experiments/go/assets/wgo/white_128.png b/experiments/go/assets/wgo/white_128.png deleted file mode 100644 index 5d3a6acb..00000000 Binary files a/experiments/go/assets/wgo/white_128.png and /dev/null differ diff --git a/experiments/go/assets/wgo/white_64.png b/experiments/go/assets/wgo/white_64.png deleted file mode 100644 index 38bc59eb..00000000 Binary files a/experiments/go/assets/wgo/white_64.png and /dev/null differ diff --git a/experiments/go/assets/wgo/wood1.jpg b/experiments/go/assets/wgo/wood1.jpg deleted file mode 100644 index e3a88a9a..00000000 Binary files a/experiments/go/assets/wgo/wood1.jpg and /dev/null differ diff --git a/experiments/go/assets/wgo/wood_1024.jpg b/experiments/go/assets/wgo/wood_1024.jpg deleted file mode 100644 index 278e1f51..00000000 Binary files a/experiments/go/assets/wgo/wood_1024.jpg and /dev/null differ diff --git a/experiments/go/assets/wgo/wood_512.jpg b/experiments/go/assets/wgo/wood_512.jpg deleted file mode 100644 index 5c2c8e1d..00000000 Binary files a/experiments/go/assets/wgo/wood_512.jpg and /dev/null differ diff --git a/experiments/go/index.html b/experiments/go/index.html deleted file mode 100644 index d79deb52..00000000 --- a/experiments/go/index.html +++ /dev/null @@ -1,29 +0,0 @@ ---- -layout: default -game: go ---- - -{% include experiments/game/headers.html %} - - - - - -{% assign game = site.data.experiments[page.game] %} -{% include experiments/game/content.html game=game %} - - -{% include experiments/game/footer.html %} - - - - - - - - - - - - - \ No newline at end of file diff --git a/experiments/index.html b/experiments/index.html deleted file mode 100644 index bf354d22..00000000 --- a/experiments/index.html +++ /dev/null @@ -1,17 +0,0 @@ ---- -layout: default -title: Experiments ---- - - -
-
-

Flux Experiments

- -
-
diff --git a/experiments/mnist/assets/bson/mnist-conv.bson b/experiments/mnist/assets/bson/mnist-conv.bson deleted file mode 100644 index 322b86e2..00000000 Binary files a/experiments/mnist/assets/bson/mnist-conv.bson and /dev/null differ diff --git a/experiments/mnist/assets/bson/mnist-mlp.bson b/experiments/mnist/assets/bson/mnist-mlp.bson deleted file mode 100644 index d0a0fafc..00000000 Binary files a/experiments/mnist/assets/bson/mnist-mlp.bson and /dev/null differ diff --git a/experiments/mnist/assets/css/style.css b/experiments/mnist/assets/css/style.css deleted file mode 100644 index 4ee8ad47..00000000 --- a/experiments/mnist/assets/css/style.css +++ /dev/null @@ -1,110 +0,0 @@ -/* basic styles */ -*{ - margin: 0; - padding: 0; - -} - -.heading{ - font-size: 30px; - background: #555; - color: #fff; - padding: 30px 50px; - z-index: 3; - box-shadow: 0 3px 5px #aaa; - height: 11vh; - box-sizing: border-box; -} - -.options{ - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; -} - -.demo_wrapper{ - display: flex; -} - -#number{ - transform: scale(1); - margin: 20px 0; - -} -#editor{ - border: 16px solid var(--dark); - background: var(--light); -} - -.render_editor{ - flex:1; - padding: 50px; - box-sizing: border-box; - position:relative; -} - -.options button{ - font-size: 16px; - margin: 30px 0; - margin-right: 10px; - padding: 10px 20px; - border-radius: 6px; - background: var(--light); - color: #000; - cursor: pointer; - border: 2px solid var(--dark); - transition: all .5s linear; - width: 110px; -} - -.options button:hover{ - background: #eee; -} - -.options button:active, -.options button:focus{ - outline: none; -} - -.render_editor h1, .render_image h1{ - /*padding: 30px 0;*/ - /*border-bottom: 1px solid #000;*/ -} - -.render_editor > div{ - display: flex; - justify-content: center; -} - -.render_editor > div > div{ - margin: 0 50px; -} - -@media only screen and (max-width: 768px){ - .render_editor{ - /*width: 100vw;*/ - height: auto; - padding: 20px 0; - } - - .demo_wrapper{ - flex-direction: column; - text-align: center; - } - - .options button{ - margin: 30px auto; - } - - .render_editor > div{ - flex-direction:column; - } - - #result{ - margin-top:0px; - } - -} - - diff --git a/experiments/mnist/assets/js/Editor.js b/experiments/mnist/assets/js/Editor.js deleted file mode 100644 index a1983a3d..00000000 --- a/experiments/mnist/assets/js/Editor.js +++ /dev/null @@ -1,175 +0,0 @@ -(function(){ - -Object.assign(window, {Editor}) - -// editor -function Editor(ele, - { - strokeWidth=15, - // color="#555", - color=getComputedStyle(document.body).getPropertyValue('--medium'), - scale=1 - }={}) -{ - this.canvas = ele; - this.ctx = ele.getContext('2d'); - this.strokeWidth = strokeWidth; - this.color = color; - this.prevPoint = null; - - this.ctx.scale(scale, scale); - this.ctx.clearRect(0,0, this.canvas.width, this.canvas.height); - this.callback = null; -} - -Editor.prototype = Object.create(EventTarget.prototype) - -Editor.prototype.draw = function({clientX, clientY}={}){ - // event end might trigger clientX = 0 and clientY = 0 - if(clientX == 0 && clientY == 0)return; - - var editorOffsets = this.canvas.getClientRects()[0]; - var dx = clientX - editorOffsets.left - 16; - var dy = clientY - editorOffsets.top - 16; - if(this.prevPoint){ - this.ctx.beginPath(); - this.ctx.strokeStyle = this.color; - this.ctx.moveTo(this.prevPoint.dx, this.prevPoint.dy); - this.ctx.lineWidth = this.strokeWidth; - var xc = (this.prevPoint.dx + dx) / 2; - var yc = (this.prevPoint.dy + dy) / 2; - this.ctx.quadraticCurveTo(xc, yc, dx, dy); - this.ctx.stroke(); - this.ctx.beginPath(); - this.ctx.fillStyle = this.color; - this.ctx.arc(dx, dy, this.strokeWidth*.5, 0, Math.PI * 2, true); - this.ctx.fill(); - } - this.prevPoint = {dx, dy}; -} - -Editor.prototype.handleDrawEvent = function(event){ - event.preventDefault(); - var scope = this; - if(event instanceof MouseEvent){ - this.draw(event); - }else if(event instanceof TouchEvent){ - Array.prototype.forEach.call(event.touches,( t ) => scope.draw(t)) - } -} - -Editor.prototype.setUp = function(){ - var scope = this; - scope.handleDrawEvent = scope.handleDrawEvent.bind(scope); - if(window.innerWidth > 768){ - scope.canvas.addEventListener('mousedown', function(event){ - scope.canvas.addEventListener('mousemove',scope.handleDrawEvent, true) - }) - - scope.canvas.addEventListener('mouseup', function(event){ - scope.canvas.removeEventListener('mousemove',scope.handleDrawEvent, true) - scope.prevPoint = null; - scope.drawEnd(); - }) - }else{ - scope.canvas.addEventListener('touchstart', function(event){ - scope.canvas.addEventListener('touchmove',scope.handleDrawEvent, true) - }) - - scope.canvas.addEventListener('touchend', function(event){ - scope.canvas.removeEventListener('touchmove',scope.handleDrawEvent, true) - scope.prevPoint = null; - scope.drawEnd(); - }) - } -} - -Editor.prototype.setDrawEndCallback = function(callback){ - this.callback = callback; -} - -Editor.prototype.drawEnd = function(){ - if(this.callback != null){ - var image = this.getImage(); - this.callback(image) - } -} - -Editor.prototype.clear = function(){ - var scope = this; - scope.ctx.clearRect(0, 0, scope.canvas.width, scope.canvas.height); - scope.prevPoint = null; -} - -Editor.prototype.getImage = function() { - var cropped = cropToCenter(this.canvas); - return scale(cropped, 28, 28); -}; - -function scale(imgSrc, nwidth, nheight){ - // create a hidden canvas, render the image as 28*28 and then extract data - var hiddenCanvas = document.createElement('canvas'); - hiddenCanvas.width = nwidth; - hiddenCanvas.height = nheight; - var hctx = hiddenCanvas.getContext('2d'); - hctx.drawImage(imgSrc,0, 0, imgSrc.width, imgSrc.height,0, 0, nwidth, nheight); - return hctx.getImageData(0, 0, nwidth, nheight); -} - - -function cropToCenter(imgSrc) { - var imgData = imgSrc.getContext("2d").getImageData(0, 0, imgSrc.width, imgSrc.height) - var { data, width, height } = imgData - - let [xmin, ymin] = [width, height] - let [xmax, ymax] = [-1, -1] - for (var i = 0; i < width; i++) { - for (var j = 0; j < height; j++) { - var idx = i + j * width - if (data[4 * idx + 3] > 0) { - if (i < xmin) xmin = i - if (i > xmax) xmax = i - if (j < ymin) ymin = j - if (j > ymax) ymax = j - } - } - } - - xmin -= 10 - xmax += 10 - ymin -= 10 - ymax += 10 - - let [widthNew, heightNew] = [xmax - xmin + 1, ymax - ymin + 1] - if (widthNew < heightNew) { - var half = Math.floor((heightNew - widthNew) / 2) - xmax += heightNew - widthNew - half - xmin -= half - widthNew = xmax - xmin + 1 - } else if (widthNew > heightNew) { - var half = Math.floor((widthNew - heightNew) / 2) - ymax += widthNew - heightNew - half - ymin -= half - heightNew = ymax - ymin + 1 - } - var dataNew = new Uint8ClampedArray(widthNew * heightNew * 4) - for (var i = xmin; i <= xmax; i++) { - for (var j = ymin; j <= ymax; j++) { - if (i >= 0 && i < width && j >= 0 && j < height) { - var idx = i + j * width - var idxNew = i - xmin + (j - ymin) * widthNew - dataNew[4 * idxNew + 3] = data[4 * idx + 3] - } - } - } - - var nImgData = new ImageData(dataNew, widthNew, heightNew) - var nImgSrc = document.createElement("canvas"); - nImgSrc.height = nImgData.height; - nImgSrc.width = nImgData.width; - nImgSrc.getContext("2d").putImageData(nImgData, 0, 0); - return nImgSrc; - -} - -})(window); \ No newline at end of file diff --git a/experiments/mnist/assets/js/Model.js b/experiments/mnist/assets/js/Model.js deleted file mode 100644 index 1d92e40d..00000000 --- a/experiments/mnist/assets/js/Model.js +++ /dev/null @@ -1,58 +0,0 @@ -(function(obj){ - - Object.assign(obj, {Model}) - - function Model(editor, result, model){ - this.editor = editor; - this.result = result; - this.model = model; - - var scope = this; - this.editor.setDrawEndCallback(callback.bind(scope)) - - function callback(image){ - this.findResult(image) - } - } - - Model.prototype.findResult = function(image){ - var scope = this; - var input = this.blackAndWhite(image.data); - - var output = tf.tidy(() => { - var tensor = tf.tensor(input, [28, 28]).transpose().reshape([1, 1, 28,28]); - return this.model(tensor); - }); - - output.data().then(function(val){ - (scope.showResult.bind(scope))(val); - tf.dispose(output); - }) - } - - // 28*28*4 rgba Unit8 array into 28*28 grayscale Float32Array - Model.prototype.blackAndWhite = function(imageData){ - return ( - (new Float32Array(784)).fill(0.0) - .map((_, i) => imageData[i*4 + 3]) - .map(reduceToGrayScale) - ); - } - - Model.prototype.showResult = function(val){ - this.result.update(val) - } - -})(window) - - -Float32Array.prototype.group = Array.prototype.group = function group(size){ - return this.reduce((acc, e)=>{ - acc.a.push(e); - if(acc.a.length == size){ - acc.b.push(acc.a); - acc.a = [] - } - return acc - }, {a:[], b:[]}).b -} \ No newline at end of file diff --git a/experiments/mnist/assets/js/Result.js b/experiments/mnist/assets/js/Result.js deleted file mode 100644 index dddb1e5a..00000000 --- a/experiments/mnist/assets/js/Result.js +++ /dev/null @@ -1,82 +0,0 @@ -(function(){ - -Object.assign(window, {Result}); - -function Result (ele, - { - labels=[...Array(10).keys()], // default labels from 0 to 9 - max=1, - maxHeight=100, - barWidth=10, - horizontalSpacing=10, - color=getComputedStyle(document.body).getPropertyValue('--medium'), - fontSize=16, - fontFamily="arial", - verticalSpacing=20, - highlight=getComputedStyle(document.body).getPropertyValue('--dark'), - padding=20 - }={}) -{ - this.canvas = ele; - this.ctx = this.canvas.getContext('2d'); - this.labels = labels; - this.max = max; - this.maxHeight = maxHeight; - this.barWidth = barWidth; - this.horizontalSpacing = horizontalSpacing; - this.color = color; - this.fontSize = fontSize; - this.fontFamily = fontFamily; - this.verticalSpacing = verticalSpacing; - this.highlight = highlight; - this.padding = padding; - this.topMargin = this.canvas.height - (2*this.padding + this.fontSize + this.maxHeight + this.verticalSpacing); -} - -Result.prototype.setUp = function(){ - var labelTopOffset = this.topMargin + this.maxHeight + this.verticalSpacing + this.padding; - var labelLeftOffset = this.padding; - this.ctx.fillStyle = this.color; - this.ctx.font = this.fontSize + "px " + this.fontFamily; - - for(var label of this.labels){ - this.ctx.fillText(label, labelLeftOffset, labelTopOffset); - labelLeftOffset += this.barWidth + this.horizontalSpacing; - } -} - -Result.prototype.update = function(values){ - var scope = this; - var max_i = 0; - - scope.ctx.clearRect(0, 0, scope.canvas.width, scope.canvas.height); - this.setUp(); // write the labels again ( remove highlighting ) - - // draw as histogram - values.forEach((val, i)=>{ - fill(val, i, scope.color); - if(val> values[max_i]){ - max_i = i; - } - }) - - // highlight highest bar - fill(values[max_i], max_i, scope.highlight); - var labelTopOffset = this.topMargin + this.maxHeight + this.verticalSpacing + this.padding; - var labelLeftOffset = max_i * ( this.barWidth + this.horizontalSpacing ) + this.padding; - this.ctx.fillStyle = this.highlight; - this.ctx.font = this.fontSize + "px " + this.fontFamily; - this.ctx.fillText(this.labels[max_i], labelLeftOffset, labelTopOffset); - - // for filling each bar - function fill(val, i, color){ - var height = scope.maxHeight * (val/scope.max); - var leftOffset = i*(scope.horizontalSpacing + scope.barWidth) + scope.padding; - var topOffset = scope.topMargin + (scope.maxHeight - height) + scope.padding; - - scope.ctx.fillStyle = color; - scope.ctx.fillRect(leftOffset, topOffset, scope.barWidth, height); - } -} - -})(window) \ No newline at end of file diff --git a/experiments/mnist/assets/js/flux.js b/experiments/mnist/assets/js/flux.js deleted file mode 100644 index f82dec35..00000000 --- a/experiments/mnist/assets/js/flux.js +++ /dev/null @@ -1,99 +0,0 @@ -flux = (function () { - -let Buffer = new BSON().serialize({}).constructor - -function blobAsArrayBuffer(blob) { - return new Promise((resolve, reject) => { - let reader = new FileReader(); - reader.addEventListener("loadend", function() { - resolve(reader.result); - }); - reader.readAsArrayBuffer(blob); - }); -} - -async function fetchBytes(url) { - let resp = await fetch(url); - if (!resp.ok) throw(resp); - let blob = await resp.blob(); - let buf = await blobAsArrayBuffer(blob); - return new Buffer(buf); -} - -async function fetchData(url) { - let buf = await fetchBytes(url); - return new BSON().deserialize(buf); -} - -// `buf` is a Uint8Array from BSON -function readFloat32(buf) { - let view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength); - let data = new Float32Array(view.byteLength/4); - for (let i = 0; i < data.length; i++) { - data[i] = view.getFloat32(i*4, true); - } - return data; -} - -function readInt32(buf) { - let view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength); - let data = new Int32Array(view.byteLength/4); - for (let i = 0; i < data.length; i++) { - data[i] = view.getInt32(i*4, true); - } - return data; -} - -function toTensor_(spec) { - let type = spec.type.name; - type = type[type.length-1]; - if (type == 'Float32') spec.data = readFloat32(spec.data.buffer); - else if (type == 'Int32') spec.data = readInt32(spec.data.buffer); - else throw `Array type ${spec.type.name} not supported.`; - let array = tf.tensor(spec.data, spec.size.reverse()); - return array -} - -function convertArrays_(data) { - if (!(typeof data == "object")) return data - if (data.tag == "array") { - return toTensor_(data); - } else { - for (let k of Object.keys(data)) { - data[k] = convertArrays_(data[k]) - } - } - return data; -} - -async function fetchBlob(url) { - data = await fetchData(url); - return convertArrays_(data) -} - -async function fetchWeights(url) { - ws = await fetchBlob(url); - return ws.weights; -} - -const _data = t => (t instanceof tf.Tensor)? t.dataSync(): t; -const slice = t => (t instanceof tf.Tensor)? t.clone():( - t instanceof Array ? t.slice() : t); -const iterate = (arr, i=1) => ([arr[i - 1], i + 1]); -function getindex(arr, ...i){ - if(arr instanceof tf.Tensor){ - return arr.dataSync()[i - 1] - }else if(arr instanceof Array){ - return arr[i - 1]; - } -} - -function invindex(arr, ...i){ - if(arr instanceof Array){ - return arr[arr.length - i]; - } -} - -return {fetchData, fetchWeights, fetchBlob, data: _data, slice, convertArrays_, iterate, invindex, getindex}; - -})(); diff --git a/experiments/mnist/assets/js/mnist-conv.js b/experiments/mnist/assets/js/mnist-conv.js deleted file mode 100644 index 1de381dd..00000000 --- a/experiments/mnist/assets/js/mnist-conv.js +++ /dev/null @@ -1,59 +0,0 @@ -let model = (function () { - let math = tf; - model.weights = []; - function starling(sanddollar) { - return sanddollar; - }; - function flamingo(fish) { - return starling(math.add(math.matMul(fish, model.weights[0]), model.weights[1])); - }; - function bat(giraffe) { - return giraffe[String("shape")]; - }; - function cassowary(chinchilla, penguin) { - return (chinchilla[String("size")]/penguin); - }; - function narwhal(seahorse, quetzal) { - return (seahorse*quetzal); - }; - function salmon(donkey) { - let redpanda = flux.invindex(bat(donkey), 4); - return math.reshape(donkey, [redpanda, cassowary(donkey, narwhal(1, redpanda))]); - }; - function monkey(reddeer) { - return math.transpose(math.maxPool(math.transpose(reddeer, [0, 2, 3, 1]), [2, 2], [2, 2], 0, "floor"), [0, 3, 1, 2]); - }; - function quail(cheetah) { - return cheetah; - }; - function echidna(kangaroo) { - return quail(math.relu(math.add(math.transpose(math.conv2d(math.transpose(kangaroo, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[2], [2, 3, 1, 0], kangaroo), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[3]))); - }; - function llama(crow) { - return math.transpose(math.maxPool(math.transpose(crow, [0, 2, 3, 1]), [2, 2], [2, 2], 0, "floor"), [0, 3, 1, 2]); - }; - function baboon(crocodile) { - return crocodile; - }; - function termite(kinkajou) { - return baboon(math.relu(math.add(math.transpose(math.conv2d(math.transpose(kinkajou, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[4], [2, 3, 1, 0], kinkajou), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[5]))); - }; - function snake(kouprey) { - return math.transpose(math.maxPool(math.transpose(kouprey, [0, 2, 3, 1]), [2, 2], [2, 2], 0, "floor"), [0, 3, 1, 2]); - }; - function louse(seal) { - return seal; - }; - function reindeer(lyrebird) { - return louse(math.relu(math.add(math.transpose(math.conv2d(math.transpose(lyrebird, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[6], [2, 3, 1, 0], lyrebird), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[7]))); - }; - function model(elk) { - return math.softmax(flamingo(salmon(monkey(echidna(llama(termite(snake(reindeer(elk))))))))); - }; - model.setWeights = (function (ws) { - model.weights = ws; - return; - }); - return model; -})(); -loadWeights('assets/bson/mnist-conv.bson', document.querySelector('.render_editor'), __init__, model) diff --git a/experiments/mnist/assets/js/mnist-mlp.js b/experiments/mnist/assets/js/mnist-mlp.js deleted file mode 100644 index 390c650e..00000000 --- a/experiments/mnist/assets/js/mnist-mlp.js +++ /dev/null @@ -1,16 +0,0 @@ -let model = (function () { - let math = tf; - function seal(otter) { - return math.add(math.matrixTimesVector(model.weights[0], otter), model.weights[1]); - }; - function hare(snake) { - return math.relu(math.add(math.matrixTimesVector(model.weights[2], snake), model.weights[3])); - }; - function model(kangaroo) { - return math.softmax(seal(hare(kangaroo))); - }; - model.weights = []; - return model; -})(); - -loadWeights('assets/bson/mnist-mlp.bson', document.querySelector('.render_editor'), __init__) \ No newline at end of file diff --git a/experiments/mnist/assets/js/script.js b/experiments/mnist/assets/js/script.js deleted file mode 100644 index 7552bdf3..00000000 --- a/experiments/mnist/assets/js/script.js +++ /dev/null @@ -1,62 +0,0 @@ -var editor, result; - -// initial setup -function __init__(){ - editor = new Editor(document.querySelector("#editor")); - editor.setUp(); - - result = new Result(document.querySelector("#result")); - result.setUp(); - - document.querySelector("#clearEditor").addEventListener('click', function(){ - editor.clear(); - }); - - model = new Model(editor, result, model); -} - -// draw a number from grayscale float data -function drawImage(numberCanvas, data){ - var ctx = numberCanvas.getContext('2d'); - ctx.clearRect(0, 0, 28, 28); - var rgbaArray = floatToUint8Clamped(data.map(i=> i*255)); - var imgData = ctx.createImageData(28,28); - imgData.data.map((e, i)=>{ - imgData.data[i] = rgbaArray[i]; - }) - ctx.putImageData(imgData, 0, 0); - return [imgData.width, imgData.height]; -} - -//convert float array into rgba Unit8ClampedArray -function floatToUint8Clamped(floatArray){ - var uint8Array = new Uint8ClampedArray(floatArray); - var rgbaArray = new Uint8ClampedArray(uint8Array.length * 4); - uint8Array.forEach((e, i)=>{ - rgbaArray[i*4] = e; - rgbaArray[i*4 + 1] = e; - rgbaArray[i*4 + 2] = e; - rgbaArray[i*4 + 3] = 255; - }) - return rgbaArray; -} - -// invert color value -function invertColor(color){ - return 255 - color -} - -// grayscale for mnist classifier -function reduceToGrayScale(i){ - return i/255; -} - -// returns index in the transposed matrix -function transpose(i, row, col){ - return ((i%col)*row + Math.floor(i/row)) -} - -// for reverse traversal -function reverse(i, size){ - return size - i - 1; -} diff --git a/experiments/mnist/index.html b/experiments/mnist/index.html deleted file mode 100644 index b15f2852..00000000 --- a/experiments/mnist/index.html +++ /dev/null @@ -1,43 +0,0 @@ ---- -layout: default ---- - - - - - - - - -
-
-

Flux Experiment: MNIST Classifier

-
-
-
-
- -
- - -
-
-
- -
-
-
- -
-
-
- - - - - - - - - - diff --git a/experiments/pong/assets/js/Board.js b/experiments/pong/assets/js/Board.js deleted file mode 100644 index 12c8f573..00000000 --- a/experiments/pong/assets/js/Board.js +++ /dev/null @@ -1,15 +0,0 @@ -function Board(container, {env}={}){ - this.container = container - this.render = ()=>{ - env.render(); - if(env.done()){ - show($$(".overlay #gameOver")) - }else{ - hide($$(".overlay #gameOver")) - } - }; - - this.removeStartScreen = ()=>{ - hide($$(".overlay #start")); - } -} diff --git a/experiments/pong/assets/js/Pong.js b/experiments/pong/assets/js/Pong.js deleted file mode 100644 index 1671233f..00000000 --- a/experiments/pong/assets/js/Pong.js +++ /dev/null @@ -1,115 +0,0 @@ -/****************************************************** -======================================================= -Pong Game -======================================================= -******************************************************/ -function Pong(canvas,{width=500, height=400, paddle_width=10, paddle_height=50, ball_radius=5}={}){ - var score = 0; - canvas.width = width; - canvas.height = height; - var components = { - - paddles: new PaddleCollection( - [ - new Vector(0, Math.floor(height/2)), - new Vector(width-paddle_width, Math.floor(height/2)) - ], { - width:paddle_width, - height:paddle_height, - total_height: height, - color: "#fff" - }), - ball: new Ball(new Vector(Math.floor(width/2), Math.floor(height/2)), new Vector(5, 0), {radius:ball_radius, color: "#fff"}) - } - - var paddleController = new PaddleController(components.paddles.collection[0]); - - this.draw = ()=>{ - var ctx = canvas.getContext('2d'); - //background - ctx.fillStyle = "#000"; - ctx.fillRect(0, 0, canvas.width, canvas.height); - - ctx.strokeStyle = "#fff"; - ctx.lineWidth = 5; - ctx.beginPath(); - ctx.setLineDash([10, 15]); - ctx.moveTo(width/2, 0); - ctx.lineTo(width/2, height); - ctx.stroke(); - - for( var c in components){ - components[c].draw(canvas); - } - - ctx.fillStyle = "#fff"; - ctx.font = "48px sans-serif" - ctx.textBaseline = "top"; - ctx.textAlign = "right"; - ctx.fillText(components.paddles.collection[0].score, width/2 - 20, 20); - ctx.textAlign = "left"; - ctx.fillText(components.paddles.collection[1].score, width/2 + 20, 20); - } - - - this.play = ()=>{ - score += this.step(); - if(!this.done()) - requestAnimationFrame(this.play); - } - - this.step = (dir)=>{ - components.ball.move(); - - this.action(1, dir); - paddleController.next(components.ball); - this.movePaddles(); - - this.collisionDetector(); - this.draw(); - - if(components.ball.pos.x < 0) { - components.paddles.incScore(1); - return 1; - } - if(components.ball.pos.x > width){ - components.paddles.incScore(0); - return -1; - } - return 0; - } - - this.collisionDetector = function(){ - var ball = components.ball; - - var paddleHit = components.paddles.detectCollision(ball); // collision with paddle - if(paddleHit){ - paddleHit.rebound(ball); - } - var wallHit = components.ball.detectCollision(width, height); // collision with walls - wallHit.forEach(w=> ball.rebound(w)); - - } - - this.done = function(){ - var cond = components.ball.pos.x < 0 || components.ball.pos.x > width; - return cond; - } - - this.movePaddles = ()=> components.paddles.move(); - - this.action = (id, dir)=>{ - // console.log(id, dir) - components.paddles.setDirection(id, dir); - } - - this.reset = () => { - components.ball.pos.x = Math.floor(width/2); - components.ball.pos.y = Math.floor(height/2); - components.ball.speed.x = Math.sign(components.ball.speed.x)*5; - components.ball.speed.y = 0; - } - - this.render = this.draw; - this.config = ()=>{return null}; -} \ No newline at end of file diff --git a/experiments/pong/assets/js/components.js b/experiments/pong/assets/js/components.js deleted file mode 100644 index 73c9e258..00000000 --- a/experiments/pong/assets/js/components.js +++ /dev/null @@ -1,76 +0,0 @@ -/****************************************************** -======================================================= -Components -======================================================= -******************************************************/ - -function PaddleCollection(positions, config){ - this.collection = positions.map(e=>new Paddle(e, config)); - - this.move = ()=>{ - this.collection.forEach(p => p.move()); - } - - this.setDirection = (id, dir)=>{ - this.collection[id].setDirection(dir); - } - - this.detectCollision = (ball)=>{ - for (var paddle of this.collection) - if(paddle.detectCollision(ball))return paddle; - - return null; - } - - this.draw = (canvas)=>{ - this.collection.forEach(paddle=>paddle.draw(canvas)); - } - - this.incScore = (id)=>{ - this.collection[id].score += 1; - } -} - - -function PaddleController(paddle){ - - this.next = (ball)=>{ - if(Math.sign(ball.pos.x - paddle.pos.x) == Math.sign(ball.speed.x))return; // ball is moving away - - if(ball.pos.y >= paddle.pos.y && ball.pos.y <= paddle.pos.y + paddle.height) - return paddle.setDirection(0) - - var dir = Math.sign(ball.pos.y - paddle.height/2 - paddle.pos.y); - paddle.setDirection(dir); - } -} - -/*** overriding a few functions ***/ -Ball.prototype.detectCollision = function(width, height) { // with top & bottom walls - var collisions = []; - if(this.pos.y - this.radius < 0 || this.pos.y + this.radius > height)collisions.push([1, -1]); - - return collisions; -}; - -Paddle.prototype.move = function (){ - this.pos.add(new Vector(0, this.dir*5)); - if(this.pos.y < 0)this.pos.y = 0; - else if(this.pos.y + this.height > this.total_height) this.pos.y = this.total_height - this.height; -} - -Paddle.prototype.detectCollision = function (ball) { - if(ball.pos.x + ball.radius > this.pos.x && ball.pos.y + ball.radius > this.pos.y && ball.pos.x < this.pos.x + this.width && ball.pos.y - ball.radius < this.pos.y + this.height){ - return this - } - return null -} - -Paddle.prototype.rebound = function (ball){ - var diff = this.pos.y + this.height/2 - ball.pos.y; - ball.rebound([-1, 1]); - ball.speed.x += Math.sign(ball.speed.x); - ball.speed.y = ball.speed.x*diff/this.height; -} - -Paddle.prototype.score = 0; \ No newline at end of file diff --git a/experiments/pong/assets/js/script.js b/experiments/pong/assets/js/script.js deleted file mode 100644 index b3581ab3..00000000 --- a/experiments/pong/assets/js/script.js +++ /dev/null @@ -1,33 +0,0 @@ -(function(){ - - var env = new Pong(document.querySelector("#playground")); - var board = new Board(document.querySelector(".board"), {env}); - var game = new Game(env, board, null); - - document.addEventListener('keydown', event => { - - var code = event.keyCode; - - if(code == 13){ - board.removeStartScreen(); - return game.play(); - } - - if(code == 38 || code == 40){ - event.preventDefault(); - game.action(code - 39); - return; - } - }) - - document.addEventListener('keyup', event => { - var code = event.keyCode; - - if(code == 38 || code == 40){ - game.action(0); - return; - } - }) - - env.draw(); -})() \ No newline at end of file diff --git a/experiments/pong/index.html b/experiments/pong/index.html deleted file mode 100644 index 9dc7991f..00000000 --- a/experiments/pong/index.html +++ /dev/null @@ -1,23 +0,0 @@ ---- -layout: default -game: pong ---- - -{% include experiments/game/headers.html %} - -{% assign game = site.data.experiments[page.game] %} -{% include experiments/game/content.html game=game %} - - -{% include experiments/game/footer.html %} - - - - - - - \ No newline at end of file diff --git a/experiments/styleTransfer/assets/bson/abstract_art_fluxjs.bson b/experiments/styleTransfer/assets/bson/abstract_art_fluxjs.bson deleted file mode 100644 index 435e7559..00000000 Binary files a/experiments/styleTransfer/assets/bson/abstract_art_fluxjs.bson and /dev/null differ diff --git a/experiments/styleTransfer/assets/bson/popsty_fluxjs.bson b/experiments/styleTransfer/assets/bson/popsty_fluxjs.bson deleted file mode 100644 index 48647d91..00000000 Binary files a/experiments/styleTransfer/assets/bson/popsty_fluxjs.bson and /dev/null differ diff --git a/experiments/styleTransfer/assets/bson/starry_night_fluxjs.bson b/experiments/styleTransfer/assets/bson/starry_night_fluxjs.bson deleted file mode 100644 index e71c9617..00000000 Binary files a/experiments/styleTransfer/assets/bson/starry_night_fluxjs.bson and /dev/null differ diff --git a/experiments/styleTransfer/assets/css/style.css b/experiments/styleTransfer/assets/css/style.css deleted file mode 100644 index 46d66dfd..00000000 --- a/experiments/styleTransfer/assets/css/style.css +++ /dev/null @@ -1,238 +0,0 @@ -.tree{ - margin: 50px; -} - -h4{ - line-height: 2em; -} - -.level{ - /*min-height: 100px;*/ - /*background: #ebf5eb;*/ - margin: 0 10px; - display: flex; - -webkit-justify-content: center; - justify-content: center; - - /*height: 50%;*/ -} - -.tree .level:nth-of-type(2) img, -.tree .level:nth-of-type(4) img{ - width: 200px; - height: 200px; - border: none; - box-shadow: none; - outline: none; - background: #ddd; - border-radius: 3px; -} - -.element{ - min-height: 300px; - /*min-width: 300px;*/ - - margin: 0 10px; - border-radius: 6px; - position: relative; - display: flex; - justify-content: center; - align-items: flex-end; -} - -.sibling{ - display: flex; - flex-direction: column; - justify-content: center; - -} - -.connector{ - min-height: 100px; - position:relative; - margin: 0 10px; - flex:2; -} - -.connector *{ - position: absolute; - background: #aaa; - transition: all .4s linear; -} - -.connector.two div:first-child{ - width: 50%; - height: 2px; - left: 25%; - top: 50%; -} - -.connector.two div:nth-child(2){ - width: 2px; - height: 50%; - left: 25%; - top: 0; -} - -.connector.two div:nth-child(3){ - width: 2px; - height: 50%; - left: 75%; - top: 0; -} - -.connector.two div:nth-child(4){ - width: 2px; - height: 50%; - left: 50%; - top: 50%; -} - -.connector.one div{ - width: 2px; - height: 100%; - left: 50%; - top: 0; -} - - -.select_style ul{ - display: flex; - justify-content: center; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - flex-wrap: wrap; - padding: 0; - margin: 0; -} - -.select_style li{ - margin: 5px 3px; - padding:0; - flex: 1; - text-align: center; - background: transparent; - cursor: pointer; - width: fit-content; -} - -.select_style img{ - width: 70px; - height: 70px; - /*border: 5px solid transparent;*/ -} - - -.pane{ - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-justify-content: center; - justify-content: center; - -webkit-align-items: center; - align-items: center; - height: fit-content; - padding: 20px; - background: var(--light); -} - -.pane.disabled { - background: #dddddd; -} - -.pane.disabled video{ - background: #eeeeee; -} - -.pretty_button{ - border-radius: 3px; - border: none; - background: #fff; - margin: 10px 0; - padding: 10px; - cursor: pointer; -} - -.pretty_button.disabled{ - cursor: initial; -} - -.pretty_button:not(.disabled), -.select_style img{ - transition: all .4s linear; - box-shadow: 2px 2px 5px #333; -} - -.pretty_button:not(.disabled):active, -.pretty_button:not(.disabled):focus{ - outline: none; - border: none; - box-shadow: none; -} - -.pretty_button:not(.disabled):hover, -.select_style li:hover img{ - box-shadow: 0px 0px 0px #333; - transform: translate(2px, 2px); -} - - -.down{ - margin: 30px 5px 10px !important; -} - -.fade.in{ - opacity: 1; -} - -.msg{ - text-align: center; -} - -li{ - list-style: none; -} - -.tree[green=true] .connector *{ - box-shadow: 2px 2px 2px var(--medium); -} -.pane{ - border: 1px solid transparent; - transition: all .4s linear; -} - -.tree[green=true] .pane{ - border: 1px solid var(--medium); -} - -@media only screen and (max-width: 768px){ - .connector{ - display: none; - } - - .w-50{ - width: 100% !important; - } - - .tree{ - margin: 20px 5px; - } - - .level{ - flex-direction:column; - } - .element{ - min-height: 0px; - margin: 10px 0 !important; - } - - .pane{ - width: 100%; - } - - .select_style ul{ - flex-direction: column; - } -} \ No newline at end of file diff --git a/experiments/styleTransfer/assets/img/abstract.jpg b/experiments/styleTransfer/assets/img/abstract.jpg deleted file mode 100644 index f348d79c..00000000 Binary files a/experiments/styleTransfer/assets/img/abstract.jpg and /dev/null differ diff --git a/experiments/styleTransfer/assets/img/popsty.jpg b/experiments/styleTransfer/assets/img/popsty.jpg deleted file mode 100644 index 8ea6ca12..00000000 Binary files a/experiments/styleTransfer/assets/img/popsty.jpg and /dev/null differ diff --git a/experiments/styleTransfer/assets/img/starry-night.jpg b/experiments/styleTransfer/assets/img/starry-night.jpg deleted file mode 100644 index f5fdd1fc..00000000 Binary files a/experiments/styleTransfer/assets/img/starry-night.jpg and /dev/null differ diff --git a/experiments/styleTransfer/assets/img/weeping-woman.jpg b/experiments/styleTransfer/assets/img/weeping-woman.jpg deleted file mode 100644 index 3864edc7..00000000 Binary files a/experiments/styleTransfer/assets/img/weeping-woman.jpg and /dev/null differ diff --git a/experiments/styleTransfer/assets/js/fluxjs/abstract_art_fluxjs.js b/experiments/styleTransfer/assets/js/fluxjs/abstract_art_fluxjs.js deleted file mode 100644 index aaf66e0a..00000000 --- a/experiments/styleTransfer/assets/js/fluxjs/abstract_art_fluxjs.js +++ /dev/null @@ -1,221 +0,0 @@ -let abstract_art = (function () { - let math = tf; - function rhinoceros(koala) { - return math.add(math.transpose(math.conv2dTranspose(math.transpose(koala, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[0], [2, 3, 1, 0], koala), [0, 1]), flux.ctOutSize(koala, model.weights[1], [1, 1], [1, 1], [1, 1], [0, 0]), [1, 1], 1, "floor"), [0, 3, 1, 2]), model.weights[2]); - }; - let walrus = math.tensor(1.0e-5); - function turkey(porcupine) { - let guineafowl = porcupine[String("shape")][String("length")]; - let bison = [].fill.apply(Array(guineafowl), [1]); - let squirrel = [].concat.call(flux.range(1, (guineafowl-2)), guineafowl); - let eland = math.mean(porcupine, [(porcupine[String("shape")][String("length")]-squirrel[0]), (porcupine[String("shape")][String("length")]-squirrel[1]), (porcupine[String("shape")][String("length")]-squirrel[2])], true); - let flamingo = math.pow(math.sub(porcupine, eland), model.weights[4]); - bison[(guineafowl-2)] = porcupine[String("shape")][(porcupine[String("shape")][String("length")]-(guineafowl-1))]; - return math.relu(math.add(math.mul(math.reshape(model.weights[3], [bison[3], bison[2], bison[1], bison[0]]), math.div(math.sub(porcupine, eland), tf.sqrt(math.add(math.mean(flamingo, [(flamingo[String("shape")][String("length")]-squirrel[0]), (flamingo[String("shape")][String("length")]-squirrel[1]), (flamingo[String("shape")][String("length")]-squirrel[2])], true), walrus)))), math.reshape(model.weights[5], [bison[3], bison[2], bison[1], bison[0]]))); - }; - function tapir(donkey) { - return math.add(math.transpose(math.conv2dTranspose(math.transpose(donkey, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[6], [2, 3, 1, 0], donkey), [0, 1]), flux.ctOutSize(donkey, model.weights[7], [2, 2], [1, 1], [1, 1], [1, 1]), [2, 2], 1, "floor"), [0, 3, 1, 2]), model.weights[8]); - }; - let shrew = math.tensor(1.0e-5); - function yak(dog) { - let butterfly = dog[String("shape")][String("length")]; - let gnu = [].fill.apply(Array(butterfly), [1]); - let quetzal = [].concat.call(flux.range(1, (butterfly-2)), butterfly); - let skunk = math.mean(dog, [(dog[String("shape")][String("length")]-quetzal[0]), (dog[String("shape")][String("length")]-quetzal[1]), (dog[String("shape")][String("length")]-quetzal[2])], true); - let cassowary = math.pow(math.sub(dog, skunk), model.weights[10]); - gnu[(butterfly-2)] = dog[String("shape")][(dog[String("shape")][String("length")]-(butterfly-1))]; - return math.relu(math.add(math.mul(math.reshape(model.weights[9], [gnu[3], gnu[2], gnu[1], gnu[0]]), math.div(math.sub(dog, skunk), tf.sqrt(math.add(math.mean(cassowary, [(cassowary[String("shape")][String("length")]-quetzal[0]), (cassowary[String("shape")][String("length")]-quetzal[1]), (cassowary[String("shape")][String("length")]-quetzal[2])], true), shrew)))), math.reshape(model.weights[11], [gnu[3], gnu[2], gnu[1], gnu[0]]))); - }; - function waterbuffalo(nightingale) { - return math.add(math.transpose(math.conv2dTranspose(math.transpose(nightingale, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[12], [2, 3, 1, 0], nightingale), [0, 1]), flux.ctOutSize(nightingale, model.weights[13], [2, 2], [1, 1], [1, 1], [1, 1]), [2, 2], 1, "floor"), [0, 3, 1, 2]), model.weights[14]); - }; - let penguin = math.tensor(1.0e-5); - function lobster(curlew) { - let mandrill = curlew[String("shape")][String("length")]; - let toad = [].fill.apply(Array(mandrill), [1]); - let polarbear = [].concat.call(flux.range(1, (mandrill-2)), mandrill); - let lion = math.mean(curlew, [(curlew[String("shape")][String("length")]-polarbear[0]), (curlew[String("shape")][String("length")]-polarbear[1]), (curlew[String("shape")][String("length")]-polarbear[2])], true); - let moose = math.pow(math.sub(curlew, lion), model.weights[16]); - toad[(mandrill-2)] = curlew[String("shape")][(curlew[String("shape")][String("length")]-(mandrill-1))]; - return math.add(math.mul(math.reshape(model.weights[15], [toad[3], toad[2], toad[1], toad[0]]), math.div(math.sub(curlew, lion), tf.sqrt(math.add(math.mean(moose, [(moose[String("shape")][String("length")]-polarbear[0]), (moose[String("shape")][String("length")]-polarbear[1]), (moose[String("shape")][String("length")]-polarbear[2])], true), penguin)))), math.reshape(model.weights[17], [toad[3], toad[2], toad[1], toad[0]])); - }; - function raven(starling) { - return math.add(math.transpose(math.conv2d(math.transpose(starling, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[18], [2, 3, 1, 0], starling), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[19]); - }; - let gull = math.tensor(1.0e-5); - function zebra(crane) { - let crocodile = crane[String("shape")][String("length")]; - let mosquito = [].fill.apply(Array(crocodile), [1]); - let ape = [].concat.call(flux.range(1, (crocodile-2)), crocodile); - let lapwing = math.mean(crane, [(crane[String("shape")][String("length")]-ape[0]), (crane[String("shape")][String("length")]-ape[1]), (crane[String("shape")][String("length")]-ape[2])], true); - let goosander = math.pow(math.sub(crane, lapwing), model.weights[21]); - mosquito[(crocodile-2)] = crane[String("shape")][(crane[String("shape")][String("length")]-(crocodile-1))]; - return math.add(math.mul(math.reshape(model.weights[20], [mosquito[3], mosquito[2], mosquito[1], mosquito[0]]), math.div(math.sub(crane, lapwing), tf.sqrt(math.add(math.mean(goosander, [(goosander[String("shape")][String("length")]-ape[0]), (goosander[String("shape")][String("length")]-ape[1]), (goosander[String("shape")][String("length")]-ape[2])], true), gull)))), math.reshape(model.weights[22], [mosquito[3], mosquito[2], mosquito[1], mosquito[0]])); - }; - function goldfinch(dogfish) { - return math.add(math.transpose(math.conv2d(math.transpose(dogfish, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[23], [2, 3, 1, 0], dogfish), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[24]); - }; - function giraffe(komodo) { - return math.add(komodo, lobster(raven(math.relu(zebra(goldfinch(komodo)))))); - }; - let chamois = math.tensor(1.0e-5); - function tiger(sardine) { - let hare = sardine[String("shape")][String("length")]; - let caribou = [].fill.apply(Array(hare), [1]); - let ram = [].concat.call(flux.range(1, (hare-2)), hare); - let sheep = math.mean(sardine, [(sardine[String("shape")][String("length")]-ram[0]), (sardine[String("shape")][String("length")]-ram[1]), (sardine[String("shape")][String("length")]-ram[2])], true); - let snail = math.pow(math.sub(sardine, sheep), model.weights[26]); - caribou[(hare-2)] = sardine[String("shape")][(sardine[String("shape")][String("length")]-(hare-1))]; - return math.add(math.mul(math.reshape(model.weights[25], [caribou[3], caribou[2], caribou[1], caribou[0]]), math.div(math.sub(sardine, sheep), tf.sqrt(math.add(math.mean(snail, [(snail[String("shape")][String("length")]-ram[0]), (snail[String("shape")][String("length")]-ram[1]), (snail[String("shape")][String("length")]-ram[2])], true), chamois)))), math.reshape(model.weights[27], [caribou[3], caribou[2], caribou[1], caribou[0]])); - }; - function sandpiper(lyrebird) { - return math.add(math.transpose(math.conv2d(math.transpose(lyrebird, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[28], [2, 3, 1, 0], lyrebird), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[29]); - }; - let wildebeest = math.tensor(1.0e-5); - function emu(pheasant) { - let guanaco = pheasant[String("shape")][String("length")]; - let anteater = [].fill.apply(Array(guanaco), [1]); - let salmon = [].concat.call(flux.range(1, (guanaco-2)), guanaco); - let mouse = math.mean(pheasant, [(pheasant[String("shape")][String("length")]-salmon[0]), (pheasant[String("shape")][String("length")]-salmon[1]), (pheasant[String("shape")][String("length")]-salmon[2])], true); - let manatee = math.pow(math.sub(pheasant, mouse), model.weights[31]); - anteater[(guanaco-2)] = pheasant[String("shape")][(pheasant[String("shape")][String("length")]-(guanaco-1))]; - return math.add(math.mul(math.reshape(model.weights[30], [anteater[3], anteater[2], anteater[1], anteater[0]]), math.div(math.sub(pheasant, mouse), tf.sqrt(math.add(math.mean(manatee, [(manatee[String("shape")][String("length")]-salmon[0]), (manatee[String("shape")][String("length")]-salmon[1]), (manatee[String("shape")][String("length")]-salmon[2])], true), wildebeest)))), math.reshape(model.weights[32], [anteater[3], anteater[2], anteater[1], anteater[0]])); - }; - function jay(quail) { - return math.add(math.transpose(math.conv2d(math.transpose(quail, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[33], [2, 3, 1, 0], quail), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[34]); - }; - function dragonfly(sealion) { - return math.add(sealion, tiger(sandpiper(math.relu(emu(jay(sealion)))))); - }; - let raccoon = math.tensor(1.0e-5); - function okapi(swan) { - let mink = swan[String("shape")][String("length")]; - let duck = [].fill.apply(Array(mink), [1]); - let heron = [].concat.call(flux.range(1, (mink-2)), mink); - let chough = math.mean(swan, [(swan[String("shape")][String("length")]-heron[0]), (swan[String("shape")][String("length")]-heron[1]), (swan[String("shape")][String("length")]-heron[2])], true); - let jaguar = math.pow(math.sub(swan, chough), model.weights[36]); - duck[(mink-2)] = swan[String("shape")][(swan[String("shape")][String("length")]-(mink-1))]; - return math.add(math.mul(math.reshape(model.weights[35], [duck[3], duck[2], duck[1], duck[0]]), math.div(math.sub(swan, chough), tf.sqrt(math.add(math.mean(jaguar, [(jaguar[String("shape")][String("length")]-heron[0]), (jaguar[String("shape")][String("length")]-heron[1]), (jaguar[String("shape")][String("length")]-heron[2])], true), raccoon)))), math.reshape(model.weights[37], [duck[3], duck[2], duck[1], duck[0]])); - }; - function monkey(chimpanzee) { - return math.add(math.transpose(math.conv2d(math.transpose(chimpanzee, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[38], [2, 3, 1, 0], chimpanzee), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[39]); - }; - let octopus = math.tensor(1.0e-5); - function wasp(oyster) { - let locust = oyster[String("shape")][String("length")]; - let ibis = [].fill.apply(Array(locust), [1]); - let wallaby = [].concat.call(flux.range(1, (locust-2)), locust); - let jackal = math.mean(oyster, [(oyster[String("shape")][String("length")]-wallaby[0]), (oyster[String("shape")][String("length")]-wallaby[1]), (oyster[String("shape")][String("length")]-wallaby[2])], true); - let gnat = math.pow(math.sub(oyster, jackal), model.weights[41]); - ibis[(locust-2)] = oyster[String("shape")][(oyster[String("shape")][String("length")]-(locust-1))]; - return math.add(math.mul(math.reshape(model.weights[40], [ibis[3], ibis[2], ibis[1], ibis[0]]), math.div(math.sub(oyster, jackal), tf.sqrt(math.add(math.mean(gnat, [(gnat[String("shape")][String("length")]-wallaby[0]), (gnat[String("shape")][String("length")]-wallaby[1]), (gnat[String("shape")][String("length")]-wallaby[2])], true), octopus)))), math.reshape(model.weights[42], [ibis[3], ibis[2], ibis[1], ibis[0]])); - }; - function kouprey(hummingbird) { - return math.add(math.transpose(math.conv2d(math.transpose(hummingbird, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[43], [2, 3, 1, 0], hummingbird), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[44]); - }; - function termite(otter) { - return math.add(otter, okapi(monkey(math.relu(wasp(kouprey(otter)))))); - }; - let fish = math.tensor(1.0e-5); - function cat(goshawk) { - let seal = goshawk[String("shape")][String("length")]; - let louse = [].fill.apply(Array(seal), [1]); - let ibex = [].concat.call(flux.range(1, (seal-2)), seal); - let cockroach = math.mean(goshawk, [(goshawk[String("shape")][String("length")]-ibex[0]), (goshawk[String("shape")][String("length")]-ibex[1]), (goshawk[String("shape")][String("length")]-ibex[2])], true); - let eel = math.pow(math.sub(goshawk, cockroach), model.weights[46]); - louse[(seal-2)] = goshawk[String("shape")][(goshawk[String("shape")][String("length")]-(seal-1))]; - return math.add(math.mul(math.reshape(model.weights[45], [louse[3], louse[2], louse[1], louse[0]]), math.div(math.sub(goshawk, cockroach), tf.sqrt(math.add(math.mean(eel, [(eel[String("shape")][String("length")]-ibex[0]), (eel[String("shape")][String("length")]-ibex[1]), (eel[String("shape")][String("length")]-ibex[2])], true), fish)))), math.reshape(model.weights[47], [louse[3], louse[2], louse[1], louse[0]])); - }; - function prairiedog(dolphin) { - return math.add(math.transpose(math.conv2d(math.transpose(dolphin, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[48], [2, 3, 1, 0], dolphin), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[49]); - }; - let kangaroo = math.tensor(1.0e-5); - function elk(falcon) { - let alpaca = falcon[String("shape")][String("length")]; - let caterpillar = [].fill.apply(Array(alpaca), [1]); - let panda = [].concat.call(flux.range(1, (alpaca-2)), alpaca); - let beaver = math.mean(falcon, [(falcon[String("shape")][String("length")]-panda[0]), (falcon[String("shape")][String("length")]-panda[1]), (falcon[String("shape")][String("length")]-panda[2])], true); - let boar = math.pow(math.sub(falcon, beaver), model.weights[51]); - caterpillar[(alpaca-2)] = falcon[String("shape")][(falcon[String("shape")][String("length")]-(alpaca-1))]; - return math.add(math.mul(math.reshape(model.weights[50], [caterpillar[3], caterpillar[2], caterpillar[1], caterpillar[0]]), math.div(math.sub(falcon, beaver), tf.sqrt(math.add(math.mean(boar, [(boar[String("shape")][String("length")]-panda[0]), (boar[String("shape")][String("length")]-panda[1]), (boar[String("shape")][String("length")]-panda[2])], true), kangaroo)))), math.reshape(model.weights[52], [caterpillar[3], caterpillar[2], caterpillar[1], caterpillar[0]])); - }; - function peafowl(cod) { - return math.add(math.transpose(math.conv2d(math.transpose(cod, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[53], [2, 3, 1, 0], cod), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[54]); - }; - function ferret(wombat) { - return math.add(wombat, cat(prairiedog(math.relu(elk(peafowl(wombat)))))); - }; - let dunlin = math.tensor(1.0e-5); - function donkey(kudu) { - let aardvark = kudu[String("shape")][String("length")]; - let elephant = [].fill.apply(Array(aardvark), [1]); - let bat = [].concat.call(flux.range(1, (aardvark-2)), aardvark); - let magpie = math.mean(kudu, [(kudu[String("shape")][String("length")]-bat[0]), (kudu[String("shape")][String("length")]-bat[1]), (kudu[String("shape")][String("length")]-bat[2])], true); - let pelican = math.pow(math.sub(kudu, magpie), model.weights[56]); - elephant[(aardvark-2)] = kudu[String("shape")][(kudu[String("shape")][String("length")]-(aardvark-1))]; - return math.add(math.mul(math.reshape(model.weights[55], [elephant[3], elephant[2], elephant[1], elephant[0]]), math.div(math.sub(kudu, magpie), tf.sqrt(math.add(math.mean(pelican, [(pelican[String("shape")][String("length")]-bat[0]), (pelican[String("shape")][String("length")]-bat[1]), (pelican[String("shape")][String("length")]-bat[2])], true), dunlin)))), math.reshape(model.weights[57], [elephant[3], elephant[2], elephant[1], elephant[0]])); - }; - function bee(seahorse) { - return math.add(math.transpose(math.conv2d(math.transpose(seahorse, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[58], [2, 3, 1, 0], seahorse), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[59]); - }; - let loris = math.tensor(1.0e-5); - function tarsier(fox) { - let salamander = fox[String("shape")][String("length")]; - let hedgehog = [].fill.apply(Array(salamander), [1]); - let mammoth = [].concat.call(flux.range(1, (salamander-2)), salamander); - let crab = math.mean(fox, [(fox[String("shape")][String("length")]-mammoth[0]), (fox[String("shape")][String("length")]-mammoth[1]), (fox[String("shape")][String("length")]-mammoth[2])], true); - let ant = math.pow(math.sub(fox, crab), model.weights[61]); - hedgehog[(salamander-2)] = fox[String("shape")][(fox[String("shape")][String("length")]-(salamander-1))]; - return math.add(math.mul(math.reshape(model.weights[60], [hedgehog[3], hedgehog[2], hedgehog[1], hedgehog[0]]), math.div(math.sub(fox, crab), tf.sqrt(math.add(math.mean(ant, [(ant[String("shape")][String("length")]-mammoth[0]), (ant[String("shape")][String("length")]-mammoth[1]), (ant[String("shape")][String("length")]-mammoth[2])], true), loris)))), math.reshape(model.weights[62], [hedgehog[3], hedgehog[2], hedgehog[1], hedgehog[0]])); - }; - function eagle(horse) { - return math.add(math.transpose(math.conv2d(math.transpose(horse, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[63], [2, 3, 1, 0], horse), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[64]); - }; - function goose(partridge) { - return math.add(partridge, donkey(bee(math.relu(tarsier(eagle(partridge)))))); - }; - let gerbil = math.tensor(1.0e-5); - function chinchilla(rook) { - let lark = rook[String("shape")][String("length")]; - let barracuda = [].fill.apply(Array(lark), [1]); - let herring = [].concat.call(flux.range(1, (lark-2)), lark); - let antelope = math.mean(rook, [(rook[String("shape")][String("length")]-herring[0]), (rook[String("shape")][String("length")]-herring[1]), (rook[String("shape")][String("length")]-herring[2])], true); - let mongoose = math.pow(math.sub(rook, antelope), model.weights[66]); - barracuda[(lark-2)] = rook[String("shape")][(rook[String("shape")][String("length")]-(lark-1))]; - return math.relu(math.add(math.mul(math.reshape(model.weights[65], [barracuda[3], barracuda[2], barracuda[1], barracuda[0]]), math.div(math.sub(rook, antelope), tf.sqrt(math.add(math.mean(mongoose, [(mongoose[String("shape")][String("length")]-herring[0]), (mongoose[String("shape")][String("length")]-herring[1]), (mongoose[String("shape")][String("length")]-herring[2])], true), gerbil)))), math.reshape(model.weights[67], [barracuda[3], barracuda[2], barracuda[1], barracuda[0]]))); - }; - function narwhal(chicken) { - return math.add(math.transpose(math.conv2d(math.transpose(chicken, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[68], [2, 3, 1, 0], chicken), [0, 1]), [2, 2], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[69]); - }; - let hippopotamus = math.tensor(1.0e-5); - function coyote(finch) { - let reddeer = finch[String("shape")][String("length")]; - let cobra = [].fill.apply(Array(reddeer), [1]); - let pigeon = [].concat.call(flux.range(1, (reddeer-2)), reddeer); - let reindeer = math.mean(finch, [(finch[String("shape")][String("length")]-pigeon[0]), (finch[String("shape")][String("length")]-pigeon[1]), (finch[String("shape")][String("length")]-pigeon[2])], true); - let cormorant = math.pow(math.sub(finch, reindeer), model.weights[71]); - cobra[(reddeer-2)] = finch[String("shape")][(finch[String("shape")][String("length")]-(reddeer-1))]; - return math.relu(math.add(math.mul(math.reshape(model.weights[70], [cobra[3], cobra[2], cobra[1], cobra[0]]), math.div(math.sub(finch, reindeer), tf.sqrt(math.add(math.mean(cormorant, [(cormorant[String("shape")][String("length")]-pigeon[0]), (cormorant[String("shape")][String("length")]-pigeon[1]), (cormorant[String("shape")][String("length")]-pigeon[2])], true), hippopotamus)))), math.reshape(model.weights[72], [cobra[3], cobra[2], cobra[1], cobra[0]]))); - }; - function gaur(weasel) { - return math.add(math.transpose(math.conv2d(math.transpose(weasel, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[73], [2, 3, 1, 0], weasel), [0, 1]), [2, 2], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[74]); - }; - let opossum = math.tensor(1.0e-5); - function fly(sloth) { - let whale = sloth[String("shape")][String("length")]; - let leopard = [].fill.apply(Array(whale), [1]); - let camel = [].concat.call(flux.range(1, (whale-2)), whale); - let cheetah = math.mean(sloth, [(sloth[String("shape")][String("length")]-camel[0]), (sloth[String("shape")][String("length")]-camel[1]), (sloth[String("shape")][String("length")]-camel[2])], true); - let pony = math.pow(math.sub(sloth, cheetah), model.weights[76]); - leopard[(whale-2)] = sloth[String("shape")][(sloth[String("shape")][String("length")]-(whale-1))]; - return math.relu(math.add(math.mul(math.reshape(model.weights[75], [leopard[3], leopard[2], leopard[1], leopard[0]]), math.div(math.sub(sloth, cheetah), tf.sqrt(math.add(math.mean(pony, [(pony[String("shape")][String("length")]-camel[0]), (pony[String("shape")][String("length")]-camel[1]), (pony[String("shape")][String("length")]-camel[2])], true), opossum)))), math.reshape(model.weights[77], [leopard[3], leopard[2], leopard[1], leopard[0]]))); - }; - function frog(goat) { - return math.add(math.transpose(math.conv2d(math.transpose(goat, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[78], [2, 3, 1, 0], goat), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[79]); - }; - function model(grouse) { - return rhinoceros(turkey(tapir(yak(waterbuffalo(giraffe(dragonfly(termite(ferret(goose(chinchilla(narwhal(coyote(gaur(fly(frog(grouse)))))))))))))))); - }; - model.weights = []; - return model; -})(); \ No newline at end of file diff --git a/experiments/styleTransfer/assets/js/fluxjs/flux.js b/experiments/styleTransfer/assets/js/fluxjs/flux.js deleted file mode 100644 index 5a21b466..00000000 --- a/experiments/styleTransfer/assets/js/fluxjs/flux.js +++ /dev/null @@ -1,111 +0,0 @@ -flux = (function () { - -let Buffer = new BSON().serialize({}).constructor - -function blobAsArrayBuffer(blob) { - return new Promise((resolve, reject) => { - let reader = new FileReader(); - reader.addEventListener("loadend", function() { - resolve(reader.result); - }); - reader.readAsArrayBuffer(blob); - }); -} - -async function fetchBytes(url) { - let resp = await fetch(url); - if (!resp.ok) throw(resp); - let blob = await resp.blob(); - let buf = await blobAsArrayBuffer(blob); - return new Buffer(buf); -} - -async function fetchData(url) { - let buf = await fetchBytes(url); - return new BSON().deserialize(buf); -} - -// `buf` is a Uint8Array from BSON -function readFloat32(buf) { - let view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength); - let data = new Float32Array(view.byteLength/4); - for (let i = 0; i < data.length; i++) { - data[i] = view.getFloat32(i*4, true); - } - return data; -} - -function readInt32(buf) { - let view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength); - let data = new Int32Array(view.byteLength/4); - for (let i = 0; i < data.length; i++) { - data[i] = view.getInt32(i*4, true); - } - return data; -} - -function toTensor_(spec) { - let type = spec.type.name; - type = type[type.length-1]; - if (type == 'Float32') spec.data = readFloat32(spec.data.buffer); - else if (type == 'Int32') spec.data = readInt32(spec.data.buffer); - else throw `Array type ${spec.type.name} not supported.`; - let array = tf.tensor(spec.data, spec.size.reverse()); - return array -} - -function convertArrays_(data) { - if (!(typeof data == "object")) return data - if (data.tag == "array") { - return toTensor_(data); - } else { - for (let k of Object.keys(data)) { - data[k] = convertArrays_(data[k]) - } - } - return data; -} - -async function fetchBlob(url) { - data = await fetchData(url); - return convertArrays_(data) -} - -async function fetchWeights(url) { - ws = await fetchBlob(url); - return ws.weights; -} - -const _data = t => (t instanceof tf.Tensor)? t.dataSync(): t; -const slice = t => (t instanceof tf.Tensor)? t.clone():( - t instanceof Array ? t.slice() : t); -const tensor = t => (t instanceof tf.Tensor)? t : ( - t instanceof Array ? tf.tensor(t) : tf.tensor([t])); - -const range = (start, stop) => [...Array(stop - start + 1).keys()].map(i => i + start) - -return {fetchData, fetchWeights, fetchBlob, convertArrays_, data: _data, slice, range}; - -})(); - - -// for custom convTranspose layer in FastStyleTransfer.jl -function out_size(stride, pad, dilation, kernel, xdims, output_pad){ - var dims = [] - var n = (stride.length) - - for (k =0; k< n; k++) { - var i = [0, stride[k], pad[k], dilation[k], kernel[k], xdims[k], output_pad[k]] - dims.push(i[1] * (i[5] - 1) + (i[4] - 1) * i[3] - 2 * i[2] + 1 + i[6]) - } - return dims -} - -function ctos(x, w, stride, pad, dilation, output_pad){ - var a = out_size(stride, pad, dilation, w.shape.slice(2).reverse(), x.shape.slice(2).reverse(), output_pad) - var b = ([...a, w.shape[1], x.shape[0]]).reverse() - return [b[0], b[2], b[3], b[1]] - -} - -flux.ctOutSize = ctos diff --git a/experiments/styleTransfer/assets/js/fluxjs/popsty_fluxjs.js b/experiments/styleTransfer/assets/js/fluxjs/popsty_fluxjs.js deleted file mode 100644 index 208032f6..00000000 --- a/experiments/styleTransfer/assets/js/fluxjs/popsty_fluxjs.js +++ /dev/null @@ -1,221 +0,0 @@ -let popsty = (function () { - let math = tf; - function rhinoceros(koala) { - return math.add(math.transpose(math.conv2dTranspose(math.transpose(koala, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[0], [2, 3, 1, 0], koala), [0, 1]), flux.ctOutSize(koala, model.weights[1], [1, 1], [1, 1], [1, 1], [0, 0]), [1, 1], 1, "floor"), [0, 3, 1, 2]), model.weights[2]); - }; - let walrus = math.tensor(1.0e-5); - function turkey(porcupine) { - let guineafowl = porcupine[String("shape")][String("length")]; - let bison = [].fill.apply(Array(guineafowl), [1]); - let squirrel = [].concat.call(flux.range(1, (guineafowl-2)), guineafowl); - let eland = math.mean(porcupine, [(porcupine[String("shape")][String("length")]-squirrel[0]), (porcupine[String("shape")][String("length")]-squirrel[1]), (porcupine[String("shape")][String("length")]-squirrel[2])], true); - let flamingo = math.pow(math.sub(porcupine, eland), model.weights[4]); - bison[(guineafowl-2)] = porcupine[String("shape")][(porcupine[String("shape")][String("length")]-(guineafowl-1))]; - return math.relu(math.add(math.mul(math.reshape(model.weights[3], [bison[3], bison[2], bison[1], bison[0]]), math.div(math.sub(porcupine, eland), tf.sqrt(math.add(math.mean(flamingo, [(flamingo[String("shape")][String("length")]-squirrel[0]), (flamingo[String("shape")][String("length")]-squirrel[1]), (flamingo[String("shape")][String("length")]-squirrel[2])], true), walrus)))), math.reshape(model.weights[5], [bison[3], bison[2], bison[1], bison[0]]))); - }; - function tapir(donkey) { - return math.add(math.transpose(math.conv2dTranspose(math.transpose(donkey, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[6], [2, 3, 1, 0], donkey), [0, 1]), flux.ctOutSize(donkey, model.weights[7], [2, 2], [1, 1], [1, 1], [1, 1]), [2, 2], 1, "floor"), [0, 3, 1, 2]), model.weights[8]); - }; - let shrew = math.tensor(1.0e-5); - function yak(dog) { - let butterfly = dog[String("shape")][String("length")]; - let gnu = [].fill.apply(Array(butterfly), [1]); - let quetzal = [].concat.call(flux.range(1, (butterfly-2)), butterfly); - let skunk = math.mean(dog, [(dog[String("shape")][String("length")]-quetzal[0]), (dog[String("shape")][String("length")]-quetzal[1]), (dog[String("shape")][String("length")]-quetzal[2])], true); - let cassowary = math.pow(math.sub(dog, skunk), model.weights[10]); - gnu[(butterfly-2)] = dog[String("shape")][(dog[String("shape")][String("length")]-(butterfly-1))]; - return math.relu(math.add(math.mul(math.reshape(model.weights[9], [gnu[3], gnu[2], gnu[1], gnu[0]]), math.div(math.sub(dog, skunk), tf.sqrt(math.add(math.mean(cassowary, [(cassowary[String("shape")][String("length")]-quetzal[0]), (cassowary[String("shape")][String("length")]-quetzal[1]), (cassowary[String("shape")][String("length")]-quetzal[2])], true), shrew)))), math.reshape(model.weights[11], [gnu[3], gnu[2], gnu[1], gnu[0]]))); - }; - function waterbuffalo(nightingale) { - return math.add(math.transpose(math.conv2dTranspose(math.transpose(nightingale, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[12], [2, 3, 1, 0], nightingale), [0, 1]), flux.ctOutSize(nightingale, model.weights[13], [2, 2], [1, 1], [1, 1], [1, 1]), [2, 2], 1, "floor"), [0, 3, 1, 2]), model.weights[14]); - }; - let penguin = math.tensor(1.0e-5); - function lobster(curlew) { - let mandrill = curlew[String("shape")][String("length")]; - let toad = [].fill.apply(Array(mandrill), [1]); - let polarbear = [].concat.call(flux.range(1, (mandrill-2)), mandrill); - let lion = math.mean(curlew, [(curlew[String("shape")][String("length")]-polarbear[0]), (curlew[String("shape")][String("length")]-polarbear[1]), (curlew[String("shape")][String("length")]-polarbear[2])], true); - let moose = math.pow(math.sub(curlew, lion), model.weights[16]); - toad[(mandrill-2)] = curlew[String("shape")][(curlew[String("shape")][String("length")]-(mandrill-1))]; - return math.add(math.mul(math.reshape(model.weights[15], [toad[3], toad[2], toad[1], toad[0]]), math.div(math.sub(curlew, lion), tf.sqrt(math.add(math.mean(moose, [(moose[String("shape")][String("length")]-polarbear[0]), (moose[String("shape")][String("length")]-polarbear[1]), (moose[String("shape")][String("length")]-polarbear[2])], true), penguin)))), math.reshape(model.weights[17], [toad[3], toad[2], toad[1], toad[0]])); - }; - function raven(starling) { - return math.add(math.transpose(math.conv2d(math.transpose(starling, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[18], [2, 3, 1, 0], starling), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[19]); - }; - let gull = math.tensor(1.0e-5); - function zebra(crane) { - let crocodile = crane[String("shape")][String("length")]; - let mosquito = [].fill.apply(Array(crocodile), [1]); - let ape = [].concat.call(flux.range(1, (crocodile-2)), crocodile); - let lapwing = math.mean(crane, [(crane[String("shape")][String("length")]-ape[0]), (crane[String("shape")][String("length")]-ape[1]), (crane[String("shape")][String("length")]-ape[2])], true); - let goosander = math.pow(math.sub(crane, lapwing), model.weights[21]); - mosquito[(crocodile-2)] = crane[String("shape")][(crane[String("shape")][String("length")]-(crocodile-1))]; - return math.add(math.mul(math.reshape(model.weights[20], [mosquito[3], mosquito[2], mosquito[1], mosquito[0]]), math.div(math.sub(crane, lapwing), tf.sqrt(math.add(math.mean(goosander, [(goosander[String("shape")][String("length")]-ape[0]), (goosander[String("shape")][String("length")]-ape[1]), (goosander[String("shape")][String("length")]-ape[2])], true), gull)))), math.reshape(model.weights[22], [mosquito[3], mosquito[2], mosquito[1], mosquito[0]])); - }; - function goldfinch(dogfish) { - return math.add(math.transpose(math.conv2d(math.transpose(dogfish, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[23], [2, 3, 1, 0], dogfish), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[24]); - }; - function giraffe(komodo) { - return math.add(komodo, lobster(raven(math.relu(zebra(goldfinch(komodo)))))); - }; - let chamois = math.tensor(1.0e-5); - function tiger(sardine) { - let hare = sardine[String("shape")][String("length")]; - let caribou = [].fill.apply(Array(hare), [1]); - let ram = [].concat.call(flux.range(1, (hare-2)), hare); - let sheep = math.mean(sardine, [(sardine[String("shape")][String("length")]-ram[0]), (sardine[String("shape")][String("length")]-ram[1]), (sardine[String("shape")][String("length")]-ram[2])], true); - let snail = math.pow(math.sub(sardine, sheep), model.weights[26]); - caribou[(hare-2)] = sardine[String("shape")][(sardine[String("shape")][String("length")]-(hare-1))]; - return math.add(math.mul(math.reshape(model.weights[25], [caribou[3], caribou[2], caribou[1], caribou[0]]), math.div(math.sub(sardine, sheep), tf.sqrt(math.add(math.mean(snail, [(snail[String("shape")][String("length")]-ram[0]), (snail[String("shape")][String("length")]-ram[1]), (snail[String("shape")][String("length")]-ram[2])], true), chamois)))), math.reshape(model.weights[27], [caribou[3], caribou[2], caribou[1], caribou[0]])); - }; - function sandpiper(lyrebird) { - return math.add(math.transpose(math.conv2d(math.transpose(lyrebird, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[28], [2, 3, 1, 0], lyrebird), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[29]); - }; - let wildebeest = math.tensor(1.0e-5); - function emu(pheasant) { - let guanaco = pheasant[String("shape")][String("length")]; - let anteater = [].fill.apply(Array(guanaco), [1]); - let salmon = [].concat.call(flux.range(1, (guanaco-2)), guanaco); - let mouse = math.mean(pheasant, [(pheasant[String("shape")][String("length")]-salmon[0]), (pheasant[String("shape")][String("length")]-salmon[1]), (pheasant[String("shape")][String("length")]-salmon[2])], true); - let manatee = math.pow(math.sub(pheasant, mouse), model.weights[31]); - anteater[(guanaco-2)] = pheasant[String("shape")][(pheasant[String("shape")][String("length")]-(guanaco-1))]; - return math.add(math.mul(math.reshape(model.weights[30], [anteater[3], anteater[2], anteater[1], anteater[0]]), math.div(math.sub(pheasant, mouse), tf.sqrt(math.add(math.mean(manatee, [(manatee[String("shape")][String("length")]-salmon[0]), (manatee[String("shape")][String("length")]-salmon[1]), (manatee[String("shape")][String("length")]-salmon[2])], true), wildebeest)))), math.reshape(model.weights[32], [anteater[3], anteater[2], anteater[1], anteater[0]])); - }; - function jay(quail) { - return math.add(math.transpose(math.conv2d(math.transpose(quail, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[33], [2, 3, 1, 0], quail), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[34]); - }; - function dragonfly(sealion) { - return math.add(sealion, tiger(sandpiper(math.relu(emu(jay(sealion)))))); - }; - let raccoon = math.tensor(1.0e-5); - function okapi(swan) { - let mink = swan[String("shape")][String("length")]; - let duck = [].fill.apply(Array(mink), [1]); - let heron = [].concat.call(flux.range(1, (mink-2)), mink); - let chough = math.mean(swan, [(swan[String("shape")][String("length")]-heron[0]), (swan[String("shape")][String("length")]-heron[1]), (swan[String("shape")][String("length")]-heron[2])], true); - let jaguar = math.pow(math.sub(swan, chough), model.weights[36]); - duck[(mink-2)] = swan[String("shape")][(swan[String("shape")][String("length")]-(mink-1))]; - return math.add(math.mul(math.reshape(model.weights[35], [duck[3], duck[2], duck[1], duck[0]]), math.div(math.sub(swan, chough), tf.sqrt(math.add(math.mean(jaguar, [(jaguar[String("shape")][String("length")]-heron[0]), (jaguar[String("shape")][String("length")]-heron[1]), (jaguar[String("shape")][String("length")]-heron[2])], true), raccoon)))), math.reshape(model.weights[37], [duck[3], duck[2], duck[1], duck[0]])); - }; - function monkey(chimpanzee) { - return math.add(math.transpose(math.conv2d(math.transpose(chimpanzee, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[38], [2, 3, 1, 0], chimpanzee), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[39]); - }; - let octopus = math.tensor(1.0e-5); - function wasp(oyster) { - let locust = oyster[String("shape")][String("length")]; - let ibis = [].fill.apply(Array(locust), [1]); - let wallaby = [].concat.call(flux.range(1, (locust-2)), locust); - let jackal = math.mean(oyster, [(oyster[String("shape")][String("length")]-wallaby[0]), (oyster[String("shape")][String("length")]-wallaby[1]), (oyster[String("shape")][String("length")]-wallaby[2])], true); - let gnat = math.pow(math.sub(oyster, jackal), model.weights[41]); - ibis[(locust-2)] = oyster[String("shape")][(oyster[String("shape")][String("length")]-(locust-1))]; - return math.add(math.mul(math.reshape(model.weights[40], [ibis[3], ibis[2], ibis[1], ibis[0]]), math.div(math.sub(oyster, jackal), tf.sqrt(math.add(math.mean(gnat, [(gnat[String("shape")][String("length")]-wallaby[0]), (gnat[String("shape")][String("length")]-wallaby[1]), (gnat[String("shape")][String("length")]-wallaby[2])], true), octopus)))), math.reshape(model.weights[42], [ibis[3], ibis[2], ibis[1], ibis[0]])); - }; - function kouprey(hummingbird) { - return math.add(math.transpose(math.conv2d(math.transpose(hummingbird, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[43], [2, 3, 1, 0], hummingbird), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[44]); - }; - function termite(otter) { - return math.add(otter, okapi(monkey(math.relu(wasp(kouprey(otter)))))); - }; - let fish = math.tensor(1.0e-5); - function cat(goshawk) { - let seal = goshawk[String("shape")][String("length")]; - let louse = [].fill.apply(Array(seal), [1]); - let ibex = [].concat.call(flux.range(1, (seal-2)), seal); - let cockroach = math.mean(goshawk, [(goshawk[String("shape")][String("length")]-ibex[0]), (goshawk[String("shape")][String("length")]-ibex[1]), (goshawk[String("shape")][String("length")]-ibex[2])], true); - let eel = math.pow(math.sub(goshawk, cockroach), model.weights[46]); - louse[(seal-2)] = goshawk[String("shape")][(goshawk[String("shape")][String("length")]-(seal-1))]; - return math.add(math.mul(math.reshape(model.weights[45], [louse[3], louse[2], louse[1], louse[0]]), math.div(math.sub(goshawk, cockroach), tf.sqrt(math.add(math.mean(eel, [(eel[String("shape")][String("length")]-ibex[0]), (eel[String("shape")][String("length")]-ibex[1]), (eel[String("shape")][String("length")]-ibex[2])], true), fish)))), math.reshape(model.weights[47], [louse[3], louse[2], louse[1], louse[0]])); - }; - function prairiedog(dolphin) { - return math.add(math.transpose(math.conv2d(math.transpose(dolphin, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[48], [2, 3, 1, 0], dolphin), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[49]); - }; - let kangaroo = math.tensor(1.0e-5); - function elk(falcon) { - let alpaca = falcon[String("shape")][String("length")]; - let caterpillar = [].fill.apply(Array(alpaca), [1]); - let panda = [].concat.call(flux.range(1, (alpaca-2)), alpaca); - let beaver = math.mean(falcon, [(falcon[String("shape")][String("length")]-panda[0]), (falcon[String("shape")][String("length")]-panda[1]), (falcon[String("shape")][String("length")]-panda[2])], true); - let boar = math.pow(math.sub(falcon, beaver), model.weights[51]); - caterpillar[(alpaca-2)] = falcon[String("shape")][(falcon[String("shape")][String("length")]-(alpaca-1))]; - return math.add(math.mul(math.reshape(model.weights[50], [caterpillar[3], caterpillar[2], caterpillar[1], caterpillar[0]]), math.div(math.sub(falcon, beaver), tf.sqrt(math.add(math.mean(boar, [(boar[String("shape")][String("length")]-panda[0]), (boar[String("shape")][String("length")]-panda[1]), (boar[String("shape")][String("length")]-panda[2])], true), kangaroo)))), math.reshape(model.weights[52], [caterpillar[3], caterpillar[2], caterpillar[1], caterpillar[0]])); - }; - function peafowl(cod) { - return math.add(math.transpose(math.conv2d(math.transpose(cod, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[53], [2, 3, 1, 0], cod), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[54]); - }; - function ferret(wombat) { - return math.add(wombat, cat(prairiedog(math.relu(elk(peafowl(wombat)))))); - }; - let dunlin = math.tensor(1.0e-5); - function donkey(kudu) { - let aardvark = kudu[String("shape")][String("length")]; - let elephant = [].fill.apply(Array(aardvark), [1]); - let bat = [].concat.call(flux.range(1, (aardvark-2)), aardvark); - let magpie = math.mean(kudu, [(kudu[String("shape")][String("length")]-bat[0]), (kudu[String("shape")][String("length")]-bat[1]), (kudu[String("shape")][String("length")]-bat[2])], true); - let pelican = math.pow(math.sub(kudu, magpie), model.weights[56]); - elephant[(aardvark-2)] = kudu[String("shape")][(kudu[String("shape")][String("length")]-(aardvark-1))]; - return math.add(math.mul(math.reshape(model.weights[55], [elephant[3], elephant[2], elephant[1], elephant[0]]), math.div(math.sub(kudu, magpie), tf.sqrt(math.add(math.mean(pelican, [(pelican[String("shape")][String("length")]-bat[0]), (pelican[String("shape")][String("length")]-bat[1]), (pelican[String("shape")][String("length")]-bat[2])], true), dunlin)))), math.reshape(model.weights[57], [elephant[3], elephant[2], elephant[1], elephant[0]])); - }; - function bee(seahorse) { - return math.add(math.transpose(math.conv2d(math.transpose(seahorse, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[58], [2, 3, 1, 0], seahorse), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[59]); - }; - let loris = math.tensor(1.0e-5); - function tarsier(fox) { - let salamander = fox[String("shape")][String("length")]; - let hedgehog = [].fill.apply(Array(salamander), [1]); - let mammoth = [].concat.call(flux.range(1, (salamander-2)), salamander); - let crab = math.mean(fox, [(fox[String("shape")][String("length")]-mammoth[0]), (fox[String("shape")][String("length")]-mammoth[1]), (fox[String("shape")][String("length")]-mammoth[2])], true); - let ant = math.pow(math.sub(fox, crab), model.weights[61]); - hedgehog[(salamander-2)] = fox[String("shape")][(fox[String("shape")][String("length")]-(salamander-1))]; - return math.add(math.mul(math.reshape(model.weights[60], [hedgehog[3], hedgehog[2], hedgehog[1], hedgehog[0]]), math.div(math.sub(fox, crab), tf.sqrt(math.add(math.mean(ant, [(ant[String("shape")][String("length")]-mammoth[0]), (ant[String("shape")][String("length")]-mammoth[1]), (ant[String("shape")][String("length")]-mammoth[2])], true), loris)))), math.reshape(model.weights[62], [hedgehog[3], hedgehog[2], hedgehog[1], hedgehog[0]])); - }; - function eagle(horse) { - return math.add(math.transpose(math.conv2d(math.transpose(horse, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[63], [2, 3, 1, 0], horse), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[64]); - }; - function goose(partridge) { - return math.add(partridge, donkey(bee(math.relu(tarsier(eagle(partridge)))))); - }; - let gerbil = math.tensor(1.0e-5); - function chinchilla(rook) { - let lark = rook[String("shape")][String("length")]; - let barracuda = [].fill.apply(Array(lark), [1]); - let herring = [].concat.call(flux.range(1, (lark-2)), lark); - let antelope = math.mean(rook, [(rook[String("shape")][String("length")]-herring[0]), (rook[String("shape")][String("length")]-herring[1]), (rook[String("shape")][String("length")]-herring[2])], true); - let mongoose = math.pow(math.sub(rook, antelope), model.weights[66]); - barracuda[(lark-2)] = rook[String("shape")][(rook[String("shape")][String("length")]-(lark-1))]; - return math.relu(math.add(math.mul(math.reshape(model.weights[65], [barracuda[3], barracuda[2], barracuda[1], barracuda[0]]), math.div(math.sub(rook, antelope), tf.sqrt(math.add(math.mean(mongoose, [(mongoose[String("shape")][String("length")]-herring[0]), (mongoose[String("shape")][String("length")]-herring[1]), (mongoose[String("shape")][String("length")]-herring[2])], true), gerbil)))), math.reshape(model.weights[67], [barracuda[3], barracuda[2], barracuda[1], barracuda[0]]))); - }; - function narwhal(chicken) { - return math.add(math.transpose(math.conv2d(math.transpose(chicken, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[68], [2, 3, 1, 0], chicken), [0, 1]), [2, 2], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[69]); - }; - let hippopotamus = math.tensor(1.0e-5); - function coyote(finch) { - let reddeer = finch[String("shape")][String("length")]; - let cobra = [].fill.apply(Array(reddeer), [1]); - let pigeon = [].concat.call(flux.range(1, (reddeer-2)), reddeer); - let reindeer = math.mean(finch, [(finch[String("shape")][String("length")]-pigeon[0]), (finch[String("shape")][String("length")]-pigeon[1]), (finch[String("shape")][String("length")]-pigeon[2])], true); - let cormorant = math.pow(math.sub(finch, reindeer), model.weights[71]); - cobra[(reddeer-2)] = finch[String("shape")][(finch[String("shape")][String("length")]-(reddeer-1))]; - return math.relu(math.add(math.mul(math.reshape(model.weights[70], [cobra[3], cobra[2], cobra[1], cobra[0]]), math.div(math.sub(finch, reindeer), tf.sqrt(math.add(math.mean(cormorant, [(cormorant[String("shape")][String("length")]-pigeon[0]), (cormorant[String("shape")][String("length")]-pigeon[1]), (cormorant[String("shape")][String("length")]-pigeon[2])], true), hippopotamus)))), math.reshape(model.weights[72], [cobra[3], cobra[2], cobra[1], cobra[0]]))); - }; - function gaur(weasel) { - return math.add(math.transpose(math.conv2d(math.transpose(weasel, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[73], [2, 3, 1, 0], weasel), [0, 1]), [2, 2], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[74]); - }; - let opossum = math.tensor(1.0e-5); - function fly(sloth) { - let whale = sloth[String("shape")][String("length")]; - let leopard = [].fill.apply(Array(whale), [1]); - let camel = [].concat.call(flux.range(1, (whale-2)), whale); - let cheetah = math.mean(sloth, [(sloth[String("shape")][String("length")]-camel[0]), (sloth[String("shape")][String("length")]-camel[1]), (sloth[String("shape")][String("length")]-camel[2])], true); - let pony = math.pow(math.sub(sloth, cheetah), model.weights[76]); - leopard[(whale-2)] = sloth[String("shape")][(sloth[String("shape")][String("length")]-(whale-1))]; - return math.relu(math.add(math.mul(math.reshape(model.weights[75], [leopard[3], leopard[2], leopard[1], leopard[0]]), math.div(math.sub(sloth, cheetah), tf.sqrt(math.add(math.mean(pony, [(pony[String("shape")][String("length")]-camel[0]), (pony[String("shape")][String("length")]-camel[1]), (pony[String("shape")][String("length")]-camel[2])], true), opossum)))), math.reshape(model.weights[77], [leopard[3], leopard[2], leopard[1], leopard[0]]))); - }; - function frog(goat) { - return math.add(math.transpose(math.conv2d(math.transpose(goat, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[78], [2, 3, 1, 0], goat), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[79]); - }; - function model(grouse) { - return rhinoceros(turkey(tapir(yak(waterbuffalo(giraffe(dragonfly(termite(ferret(goose(chinchilla(narwhal(coyote(gaur(fly(frog(grouse)))))))))))))))); - }; - model.weights = []; - return model; -})(); \ No newline at end of file diff --git a/experiments/styleTransfer/assets/js/fluxjs/starry_night_fluxjs.js b/experiments/styleTransfer/assets/js/fluxjs/starry_night_fluxjs.js deleted file mode 100644 index ada8158e..00000000 --- a/experiments/styleTransfer/assets/js/fluxjs/starry_night_fluxjs.js +++ /dev/null @@ -1,221 +0,0 @@ -let starry_night = (function () { - let math = tf; - function rhinoceros(koala) { - return math.add(math.transpose(math.conv2dTranspose(math.transpose(koala, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[0], [2, 3, 1, 0], koala), [0, 1]), flux.ctOutSize(koala, model.weights[1], [1, 1], [1, 1], [1, 1], [0, 0]), [1, 1], 1, "floor"), [0, 3, 1, 2]), model.weights[2]); - }; - let walrus = math.tensor(1.0e-5); - function turkey(porcupine) { - let guineafowl = porcupine[String("shape")][String("length")]; - let bison = [].fill.apply(Array(guineafowl), [1]); - let squirrel = [].concat.call(flux.range(1, (guineafowl-2)), guineafowl); - let eland = math.mean(porcupine, [(porcupine[String("shape")][String("length")]-squirrel[0]), (porcupine[String("shape")][String("length")]-squirrel[1]), (porcupine[String("shape")][String("length")]-squirrel[2])], true); - let flamingo = math.pow(math.sub(porcupine, eland), model.weights[4]); - bison[(guineafowl-2)] = porcupine[String("shape")][(porcupine[String("shape")][String("length")]-(guineafowl-1))]; - return math.relu(math.add(math.mul(math.reshape(model.weights[3], [bison[3], bison[2], bison[1], bison[0]]), math.div(math.sub(porcupine, eland), tf.sqrt(math.add(math.mean(flamingo, [(flamingo[String("shape")][String("length")]-squirrel[0]), (flamingo[String("shape")][String("length")]-squirrel[1]), (flamingo[String("shape")][String("length")]-squirrel[2])], true), walrus)))), math.reshape(model.weights[5], [bison[3], bison[2], bison[1], bison[0]]))); - }; - function tapir(donkey) { - return math.add(math.transpose(math.conv2dTranspose(math.transpose(donkey, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[6], [2, 3, 1, 0], donkey), [0, 1]), flux.ctOutSize(donkey, model.weights[7], [2, 2], [1, 1], [1, 1], [1, 1]), [2, 2], 1, "floor"), [0, 3, 1, 2]), model.weights[8]); - }; - let shrew = math.tensor(1.0e-5); - function yak(dog) { - let butterfly = dog[String("shape")][String("length")]; - let gnu = [].fill.apply(Array(butterfly), [1]); - let quetzal = [].concat.call(flux.range(1, (butterfly-2)), butterfly); - let skunk = math.mean(dog, [(dog[String("shape")][String("length")]-quetzal[0]), (dog[String("shape")][String("length")]-quetzal[1]), (dog[String("shape")][String("length")]-quetzal[2])], true); - let cassowary = math.pow(math.sub(dog, skunk), model.weights[10]); - gnu[(butterfly-2)] = dog[String("shape")][(dog[String("shape")][String("length")]-(butterfly-1))]; - return math.relu(math.add(math.mul(math.reshape(model.weights[9], [gnu[3], gnu[2], gnu[1], gnu[0]]), math.div(math.sub(dog, skunk), tf.sqrt(math.add(math.mean(cassowary, [(cassowary[String("shape")][String("length")]-quetzal[0]), (cassowary[String("shape")][String("length")]-quetzal[1]), (cassowary[String("shape")][String("length")]-quetzal[2])], true), shrew)))), math.reshape(model.weights[11], [gnu[3], gnu[2], gnu[1], gnu[0]]))); - }; - function waterbuffalo(nightingale) { - return math.add(math.transpose(math.conv2dTranspose(math.transpose(nightingale, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[12], [2, 3, 1, 0], nightingale), [0, 1]), flux.ctOutSize(nightingale, model.weights[13], [2, 2], [1, 1], [1, 1], [1, 1]), [2, 2], 1, "floor"), [0, 3, 1, 2]), model.weights[14]); - }; - let penguin = math.tensor(1.0e-5); - function lobster(curlew) { - let mandrill = curlew[String("shape")][String("length")]; - let toad = [].fill.apply(Array(mandrill), [1]); - let polarbear = [].concat.call(flux.range(1, (mandrill-2)), mandrill); - let lion = math.mean(curlew, [(curlew[String("shape")][String("length")]-polarbear[0]), (curlew[String("shape")][String("length")]-polarbear[1]), (curlew[String("shape")][String("length")]-polarbear[2])], true); - let moose = math.pow(math.sub(curlew, lion), model.weights[16]); - toad[(mandrill-2)] = curlew[String("shape")][(curlew[String("shape")][String("length")]-(mandrill-1))]; - return math.add(math.mul(math.reshape(model.weights[15], [toad[3], toad[2], toad[1], toad[0]]), math.div(math.sub(curlew, lion), tf.sqrt(math.add(math.mean(moose, [(moose[String("shape")][String("length")]-polarbear[0]), (moose[String("shape")][String("length")]-polarbear[1]), (moose[String("shape")][String("length")]-polarbear[2])], true), penguin)))), math.reshape(model.weights[17], [toad[3], toad[2], toad[1], toad[0]])); - }; - function raven(starling) { - return math.add(math.transpose(math.conv2d(math.transpose(starling, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[18], [2, 3, 1, 0], starling), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[19]); - }; - let gull = math.tensor(1.0e-5); - function zebra(crane) { - let crocodile = crane[String("shape")][String("length")]; - let mosquito = [].fill.apply(Array(crocodile), [1]); - let ape = [].concat.call(flux.range(1, (crocodile-2)), crocodile); - let lapwing = math.mean(crane, [(crane[String("shape")][String("length")]-ape[0]), (crane[String("shape")][String("length")]-ape[1]), (crane[String("shape")][String("length")]-ape[2])], true); - let goosander = math.pow(math.sub(crane, lapwing), model.weights[21]); - mosquito[(crocodile-2)] = crane[String("shape")][(crane[String("shape")][String("length")]-(crocodile-1))]; - return math.add(math.mul(math.reshape(model.weights[20], [mosquito[3], mosquito[2], mosquito[1], mosquito[0]]), math.div(math.sub(crane, lapwing), tf.sqrt(math.add(math.mean(goosander, [(goosander[String("shape")][String("length")]-ape[0]), (goosander[String("shape")][String("length")]-ape[1]), (goosander[String("shape")][String("length")]-ape[2])], true), gull)))), math.reshape(model.weights[22], [mosquito[3], mosquito[2], mosquito[1], mosquito[0]])); - }; - function goldfinch(dogfish) { - return math.add(math.transpose(math.conv2d(math.transpose(dogfish, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[23], [2, 3, 1, 0], dogfish), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[24]); - }; - function giraffe(komodo) { - return math.add(komodo, lobster(raven(math.relu(zebra(goldfinch(komodo)))))); - }; - let chamois = math.tensor(1.0e-5); - function tiger(sardine) { - let hare = sardine[String("shape")][String("length")]; - let caribou = [].fill.apply(Array(hare), [1]); - let ram = [].concat.call(flux.range(1, (hare-2)), hare); - let sheep = math.mean(sardine, [(sardine[String("shape")][String("length")]-ram[0]), (sardine[String("shape")][String("length")]-ram[1]), (sardine[String("shape")][String("length")]-ram[2])], true); - let snail = math.pow(math.sub(sardine, sheep), model.weights[26]); - caribou[(hare-2)] = sardine[String("shape")][(sardine[String("shape")][String("length")]-(hare-1))]; - return math.add(math.mul(math.reshape(model.weights[25], [caribou[3], caribou[2], caribou[1], caribou[0]]), math.div(math.sub(sardine, sheep), tf.sqrt(math.add(math.mean(snail, [(snail[String("shape")][String("length")]-ram[0]), (snail[String("shape")][String("length")]-ram[1]), (snail[String("shape")][String("length")]-ram[2])], true), chamois)))), math.reshape(model.weights[27], [caribou[3], caribou[2], caribou[1], caribou[0]])); - }; - function sandpiper(lyrebird) { - return math.add(math.transpose(math.conv2d(math.transpose(lyrebird, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[28], [2, 3, 1, 0], lyrebird), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[29]); - }; - let wildebeest = math.tensor(1.0e-5); - function emu(pheasant) { - let guanaco = pheasant[String("shape")][String("length")]; - let anteater = [].fill.apply(Array(guanaco), [1]); - let salmon = [].concat.call(flux.range(1, (guanaco-2)), guanaco); - let mouse = math.mean(pheasant, [(pheasant[String("shape")][String("length")]-salmon[0]), (pheasant[String("shape")][String("length")]-salmon[1]), (pheasant[String("shape")][String("length")]-salmon[2])], true); - let manatee = math.pow(math.sub(pheasant, mouse), model.weights[31]); - anteater[(guanaco-2)] = pheasant[String("shape")][(pheasant[String("shape")][String("length")]-(guanaco-1))]; - return math.add(math.mul(math.reshape(model.weights[30], [anteater[3], anteater[2], anteater[1], anteater[0]]), math.div(math.sub(pheasant, mouse), tf.sqrt(math.add(math.mean(manatee, [(manatee[String("shape")][String("length")]-salmon[0]), (manatee[String("shape")][String("length")]-salmon[1]), (manatee[String("shape")][String("length")]-salmon[2])], true), wildebeest)))), math.reshape(model.weights[32], [anteater[3], anteater[2], anteater[1], anteater[0]])); - }; - function jay(quail) { - return math.add(math.transpose(math.conv2d(math.transpose(quail, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[33], [2, 3, 1, 0], quail), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[34]); - }; - function dragonfly(sealion) { - return math.add(sealion, tiger(sandpiper(math.relu(emu(jay(sealion)))))); - }; - let raccoon = math.tensor(1.0e-5); - function okapi(swan) { - let mink = swan[String("shape")][String("length")]; - let duck = [].fill.apply(Array(mink), [1]); - let heron = [].concat.call(flux.range(1, (mink-2)), mink); - let chough = math.mean(swan, [(swan[String("shape")][String("length")]-heron[0]), (swan[String("shape")][String("length")]-heron[1]), (swan[String("shape")][String("length")]-heron[2])], true); - let jaguar = math.pow(math.sub(swan, chough), model.weights[36]); - duck[(mink-2)] = swan[String("shape")][(swan[String("shape")][String("length")]-(mink-1))]; - return math.add(math.mul(math.reshape(model.weights[35], [duck[3], duck[2], duck[1], duck[0]]), math.div(math.sub(swan, chough), tf.sqrt(math.add(math.mean(jaguar, [(jaguar[String("shape")][String("length")]-heron[0]), (jaguar[String("shape")][String("length")]-heron[1]), (jaguar[String("shape")][String("length")]-heron[2])], true), raccoon)))), math.reshape(model.weights[37], [duck[3], duck[2], duck[1], duck[0]])); - }; - function monkey(chimpanzee) { - return math.add(math.transpose(math.conv2d(math.transpose(chimpanzee, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[38], [2, 3, 1, 0], chimpanzee), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[39]); - }; - let octopus = math.tensor(1.0e-5); - function wasp(oyster) { - let locust = oyster[String("shape")][String("length")]; - let ibis = [].fill.apply(Array(locust), [1]); - let wallaby = [].concat.call(flux.range(1, (locust-2)), locust); - let jackal = math.mean(oyster, [(oyster[String("shape")][String("length")]-wallaby[0]), (oyster[String("shape")][String("length")]-wallaby[1]), (oyster[String("shape")][String("length")]-wallaby[2])], true); - let gnat = math.pow(math.sub(oyster, jackal), model.weights[41]); - ibis[(locust-2)] = oyster[String("shape")][(oyster[String("shape")][String("length")]-(locust-1))]; - return math.add(math.mul(math.reshape(model.weights[40], [ibis[3], ibis[2], ibis[1], ibis[0]]), math.div(math.sub(oyster, jackal), tf.sqrt(math.add(math.mean(gnat, [(gnat[String("shape")][String("length")]-wallaby[0]), (gnat[String("shape")][String("length")]-wallaby[1]), (gnat[String("shape")][String("length")]-wallaby[2])], true), octopus)))), math.reshape(model.weights[42], [ibis[3], ibis[2], ibis[1], ibis[0]])); - }; - function kouprey(hummingbird) { - return math.add(math.transpose(math.conv2d(math.transpose(hummingbird, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[43], [2, 3, 1, 0], hummingbird), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[44]); - }; - function termite(otter) { - return math.add(otter, okapi(monkey(math.relu(wasp(kouprey(otter)))))); - }; - let fish = math.tensor(1.0e-5); - function cat(goshawk) { - let seal = goshawk[String("shape")][String("length")]; - let louse = [].fill.apply(Array(seal), [1]); - let ibex = [].concat.call(flux.range(1, (seal-2)), seal); - let cockroach = math.mean(goshawk, [(goshawk[String("shape")][String("length")]-ibex[0]), (goshawk[String("shape")][String("length")]-ibex[1]), (goshawk[String("shape")][String("length")]-ibex[2])], true); - let eel = math.pow(math.sub(goshawk, cockroach), model.weights[46]); - louse[(seal-2)] = goshawk[String("shape")][(goshawk[String("shape")][String("length")]-(seal-1))]; - return math.add(math.mul(math.reshape(model.weights[45], [louse[3], louse[2], louse[1], louse[0]]), math.div(math.sub(goshawk, cockroach), tf.sqrt(math.add(math.mean(eel, [(eel[String("shape")][String("length")]-ibex[0]), (eel[String("shape")][String("length")]-ibex[1]), (eel[String("shape")][String("length")]-ibex[2])], true), fish)))), math.reshape(model.weights[47], [louse[3], louse[2], louse[1], louse[0]])); - }; - function prairiedog(dolphin) { - return math.add(math.transpose(math.conv2d(math.transpose(dolphin, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[48], [2, 3, 1, 0], dolphin), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[49]); - }; - let kangaroo = math.tensor(1.0e-5); - function elk(falcon) { - let alpaca = falcon[String("shape")][String("length")]; - let caterpillar = [].fill.apply(Array(alpaca), [1]); - let panda = [].concat.call(flux.range(1, (alpaca-2)), alpaca); - let beaver = math.mean(falcon, [(falcon[String("shape")][String("length")]-panda[0]), (falcon[String("shape")][String("length")]-panda[1]), (falcon[String("shape")][String("length")]-panda[2])], true); - let boar = math.pow(math.sub(falcon, beaver), model.weights[51]); - caterpillar[(alpaca-2)] = falcon[String("shape")][(falcon[String("shape")][String("length")]-(alpaca-1))]; - return math.add(math.mul(math.reshape(model.weights[50], [caterpillar[3], caterpillar[2], caterpillar[1], caterpillar[0]]), math.div(math.sub(falcon, beaver), tf.sqrt(math.add(math.mean(boar, [(boar[String("shape")][String("length")]-panda[0]), (boar[String("shape")][String("length")]-panda[1]), (boar[String("shape")][String("length")]-panda[2])], true), kangaroo)))), math.reshape(model.weights[52], [caterpillar[3], caterpillar[2], caterpillar[1], caterpillar[0]])); - }; - function peafowl(cod) { - return math.add(math.transpose(math.conv2d(math.transpose(cod, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[53], [2, 3, 1, 0], cod), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[54]); - }; - function ferret(wombat) { - return math.add(wombat, cat(prairiedog(math.relu(elk(peafowl(wombat)))))); - }; - let dunlin = math.tensor(1.0e-5); - function donkey(kudu) { - let aardvark = kudu[String("shape")][String("length")]; - let elephant = [].fill.apply(Array(aardvark), [1]); - let bat = [].concat.call(flux.range(1, (aardvark-2)), aardvark); - let magpie = math.mean(kudu, [(kudu[String("shape")][String("length")]-bat[0]), (kudu[String("shape")][String("length")]-bat[1]), (kudu[String("shape")][String("length")]-bat[2])], true); - let pelican = math.pow(math.sub(kudu, magpie), model.weights[56]); - elephant[(aardvark-2)] = kudu[String("shape")][(kudu[String("shape")][String("length")]-(aardvark-1))]; - return math.add(math.mul(math.reshape(model.weights[55], [elephant[3], elephant[2], elephant[1], elephant[0]]), math.div(math.sub(kudu, magpie), tf.sqrt(math.add(math.mean(pelican, [(pelican[String("shape")][String("length")]-bat[0]), (pelican[String("shape")][String("length")]-bat[1]), (pelican[String("shape")][String("length")]-bat[2])], true), dunlin)))), math.reshape(model.weights[57], [elephant[3], elephant[2], elephant[1], elephant[0]])); - }; - function bee(seahorse) { - return math.add(math.transpose(math.conv2d(math.transpose(seahorse, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[58], [2, 3, 1, 0], seahorse), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[59]); - }; - let loris = math.tensor(1.0e-5); - function tarsier(fox) { - let salamander = fox[String("shape")][String("length")]; - let hedgehog = [].fill.apply(Array(salamander), [1]); - let mammoth = [].concat.call(flux.range(1, (salamander-2)), salamander); - let crab = math.mean(fox, [(fox[String("shape")][String("length")]-mammoth[0]), (fox[String("shape")][String("length")]-mammoth[1]), (fox[String("shape")][String("length")]-mammoth[2])], true); - let ant = math.pow(math.sub(fox, crab), model.weights[61]); - hedgehog[(salamander-2)] = fox[String("shape")][(fox[String("shape")][String("length")]-(salamander-1))]; - return math.add(math.mul(math.reshape(model.weights[60], [hedgehog[3], hedgehog[2], hedgehog[1], hedgehog[0]]), math.div(math.sub(fox, crab), tf.sqrt(math.add(math.mean(ant, [(ant[String("shape")][String("length")]-mammoth[0]), (ant[String("shape")][String("length")]-mammoth[1]), (ant[String("shape")][String("length")]-mammoth[2])], true), loris)))), math.reshape(model.weights[62], [hedgehog[3], hedgehog[2], hedgehog[1], hedgehog[0]])); - }; - function eagle(horse) { - return math.add(math.transpose(math.conv2d(math.transpose(horse, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[63], [2, 3, 1, 0], horse), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[64]); - }; - function goose(partridge) { - return math.add(partridge, donkey(bee(math.relu(tarsier(eagle(partridge)))))); - }; - let gerbil = math.tensor(1.0e-5); - function chinchilla(rook) { - let lark = rook[String("shape")][String("length")]; - let barracuda = [].fill.apply(Array(lark), [1]); - let herring = [].concat.call(flux.range(1, (lark-2)), lark); - let antelope = math.mean(rook, [(rook[String("shape")][String("length")]-herring[0]), (rook[String("shape")][String("length")]-herring[1]), (rook[String("shape")][String("length")]-herring[2])], true); - let mongoose = math.pow(math.sub(rook, antelope), model.weights[66]); - barracuda[(lark-2)] = rook[String("shape")][(rook[String("shape")][String("length")]-(lark-1))]; - return math.relu(math.add(math.mul(math.reshape(model.weights[65], [barracuda[3], barracuda[2], barracuda[1], barracuda[0]]), math.div(math.sub(rook, antelope), tf.sqrt(math.add(math.mean(mongoose, [(mongoose[String("shape")][String("length")]-herring[0]), (mongoose[String("shape")][String("length")]-herring[1]), (mongoose[String("shape")][String("length")]-herring[2])], true), gerbil)))), math.reshape(model.weights[67], [barracuda[3], barracuda[2], barracuda[1], barracuda[0]]))); - }; - function narwhal(chicken) { - return math.add(math.transpose(math.conv2d(math.transpose(chicken, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[68], [2, 3, 1, 0], chicken), [0, 1]), [2, 2], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[69]); - }; - let hippopotamus = math.tensor(1.0e-5); - function coyote(finch) { - let reddeer = finch[String("shape")][String("length")]; - let cobra = [].fill.apply(Array(reddeer), [1]); - let pigeon = [].concat.call(flux.range(1, (reddeer-2)), reddeer); - let reindeer = math.mean(finch, [(finch[String("shape")][String("length")]-pigeon[0]), (finch[String("shape")][String("length")]-pigeon[1]), (finch[String("shape")][String("length")]-pigeon[2])], true); - let cormorant = math.pow(math.sub(finch, reindeer), model.weights[71]); - cobra[(reddeer-2)] = finch[String("shape")][(finch[String("shape")][String("length")]-(reddeer-1))]; - return math.relu(math.add(math.mul(math.reshape(model.weights[70], [cobra[3], cobra[2], cobra[1], cobra[0]]), math.div(math.sub(finch, reindeer), tf.sqrt(math.add(math.mean(cormorant, [(cormorant[String("shape")][String("length")]-pigeon[0]), (cormorant[String("shape")][String("length")]-pigeon[1]), (cormorant[String("shape")][String("length")]-pigeon[2])], true), hippopotamus)))), math.reshape(model.weights[72], [cobra[3], cobra[2], cobra[1], cobra[0]]))); - }; - function gaur(weasel) { - return math.add(math.transpose(math.conv2d(math.transpose(weasel, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[73], [2, 3, 1, 0], weasel), [0, 1]), [2, 2], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[74]); - }; - let opossum = math.tensor(1.0e-5); - function fly(sloth) { - let whale = sloth[String("shape")][String("length")]; - let leopard = [].fill.apply(Array(whale), [1]); - let camel = [].concat.call(flux.range(1, (whale-2)), whale); - let cheetah = math.mean(sloth, [(sloth[String("shape")][String("length")]-camel[0]), (sloth[String("shape")][String("length")]-camel[1]), (sloth[String("shape")][String("length")]-camel[2])], true); - let pony = math.pow(math.sub(sloth, cheetah), model.weights[76]); - leopard[(whale-2)] = sloth[String("shape")][(sloth[String("shape")][String("length")]-(whale-1))]; - return math.relu(math.add(math.mul(math.reshape(model.weights[75], [leopard[3], leopard[2], leopard[1], leopard[0]]), math.div(math.sub(sloth, cheetah), tf.sqrt(math.add(math.mean(pony, [(pony[String("shape")][String("length")]-camel[0]), (pony[String("shape")][String("length")]-camel[1]), (pony[String("shape")][String("length")]-camel[2])], true), opossum)))), math.reshape(model.weights[77], [leopard[3], leopard[2], leopard[1], leopard[0]]))); - }; - function frog(goat) { - return math.add(math.transpose(math.conv2d(math.transpose(goat, [0, 2, 3, 1]), math.reverse(math.transpose(model.weights[78], [2, 3, 1, 0], goat), [0, 1]), [1, 1], 1, "NHWC", [1, 1], "floor"), [0, 3, 1, 2]), model.weights[79]); - }; - function model(grouse) { - return rhinoceros(turkey(tapir(yak(waterbuffalo(giraffe(dragonfly(termite(ferret(goose(chinchilla(narwhal(coyote(gaur(fly(frog(grouse)))))))))))))))); - }; - model.weights = []; - return model; -})(); \ No newline at end of file diff --git a/experiments/styleTransfer/assets/js/helpers.js b/experiments/styleTransfer/assets/js/helpers.js deleted file mode 100644 index 2a475acc..00000000 --- a/experiments/styleTransfer/assets/js/helpers.js +++ /dev/null @@ -1,50 +0,0 @@ -// general -var $$ = (e)=> document.querySelector(e); - -function getImageCanvas(screen, width, height){ - var canvas = document.createElement('canvas'); - canvas.width = width; - canvas.height = height; - canvas.getContext('2d').drawImage(screen, 0, 0, height, width); - return canvas -} - -function _transformInput(canvas){ - return canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height) -} - -function _transformOutput(res){ - return imagedata_to_image(res) -} - -var timeOut = null; - -function showErr(msg){ - $$(".msg").innerText = msg; - if(timeOut == null) - $$(".msg").className += " in"; - clearTimeout(timeOut); - timeOut = setTimeout(()=>{ - $$(".msg").className = $$(".msg").className.replace(" in", ""); - timeOut = null; - }, 3000); -} - -function getImageData(img){ - var canvas = document.createElement('canvas'); - var context = canvas.getContext('2d'); - var img = document.getElementById('myimg'); - canvas.width = img.width; - canvas.height = img.height; - context.drawImage(img, 0, 0 ); - return context.getImageData(0, 0, img.width, img.height); -} - -function imagedata_to_uri(imagedata) { - var canvas = document.createElement('canvas'); - var ctx = canvas.getContext('2d'); - canvas.width = imagedata.width; - canvas.height = imagedata.height; - ctx.putImageData(imagedata, 0, 0); - return canvas.toDataURL(); -} \ No newline at end of file diff --git a/experiments/styleTransfer/assets/js/mediaStream.js b/experiments/styleTransfer/assets/js/mediaStream.js deleted file mode 100644 index 4e070f6c..00000000 --- a/experiments/styleTransfer/assets/js/mediaStream.js +++ /dev/null @@ -1,27 +0,0 @@ -// setup media stream -var constraints = { - video: {width: {exact: 256}, height: {exact: 256}} -}; - -function hasGetUserMedia() { - return !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia); -} - -function handleSuccess(stream) { - $$('#screenshot-video').srcObject = stream; -} - -function handleError(error) { - console.log("media access rejected", error) - $$(".webcam_input").className += " disabled"; - $$(".webcam_input .pretty_button").className += " disabled"; - $$(".webcam_input .pretty_button").setAttribute("disabled", true) -} - -if (hasGetUserMedia()) { - navigator.mediaDevices.getUserMedia(constraints) - .then(handleSuccess) - .catch(handleError); -} else { - console.log('getUserMedia() is not supported by your browser'); -} diff --git a/experiments/styleTransfer/assets/js/model.js b/experiments/styleTransfer/assets/js/model.js deleted file mode 100644 index 5cc7d8a8..00000000 --- a/experiments/styleTransfer/assets/js/model.js +++ /dev/null @@ -1,86 +0,0 @@ -// dummy model -// var model = { -// predict : () => { return new Promise((a, b)=>{ setTimeout(() => a(null), 100) }) }, -// loadWeights: ()=> { } -// } -(function(obj){ - -var mean = [123.675 ,116.79, 104.04] - -function Model(name, model, loaded=false){ - var _input = null; - this.load = function(){ - if(loaded) return; - console.log("loading", name) - loadWeights('./assets/bson/' + name +'_fluxjs.bson', document.querySelector('.demo_wrapper'), this.onload.bind(this), model) - } - - this.onload = function(){ - console.log("loaded") - loaded = true; - model = wrap(model); - if(_input) this.predict(_input) - } - - this.predict = function(data){ - if(!loaded) { - _input = data - this.load(); - } - - var input = this.pre(data); - var out = model(input); - tf.dispose(input) - return out.data().then(res =>{ - tf.dispose(out) - _input = null - res = this.post(res, data.width, data.height) - - var i = new Uint8ClampedArray(res); - var idata = new ImageData(i, data.width, data.height) - return idata; - }) - - } - - this.pre = function(data){ - var rgb = data.data; - var input = [[], [], []]; - for(var i =0; i< data.height; i++){ - var r = []; - var g = []; - var b = []; - for(var j =0; j< data.width; j++){ - r.push(data.data[i*data.width*4 + j*4] - mean[0]) - g.push(data.data[i*data.width*4 + j*4 + 1] - mean[1]) - b.push(data.data[i*data.width*4 + j*4 + 2] - mean[2]) - } - input[0].push(r) - input[1].push(g) - input[2].push(b) - } - input = tf.tensor([input]) - return input; - } - - this.post = function(res, w,h){ - var t = new Array(w*h*4).fill(255); - for(var c = 0; c< 3; c++){ - for(var i = 0; i< h; i++){ - for(var j = 0; j< w; j++){ - t[i*w*4 + j*4 + c] = res[c*w*h + i*h + j] + mean[c]; - } - } - } - return t; - } - -} - -function wrap(m){ - return (x) => tf.tidy(() => m(x)) -} - -Object.assign(obj, {Model}) - -})(window); \ No newline at end of file diff --git a/experiments/styleTransfer/assets/js/script.js b/experiments/styleTransfer/assets/js/script.js deleted file mode 100644 index 6c3e52e0..00000000 --- a/experiments/styleTransfer/assets/js/script.js +++ /dev/null @@ -1,62 +0,0 @@ - -var __init__ = function (){ - var models = { abstract_art, popsty, starry_night } - - function wrap(n, x){ - return new Model(n, x); - } - - for(var i in models){ - models[i] = wrap(i, models[i]) - } - - // event listeners - $$('#screenshot-button').onclick = function() { - var video = $$('#screenshot-video'); - var canvas = getImageCanvas(video, video.videoWidth, video.videoHeight); - $$('#content-img').src = canvas.toDataURL('image/webp'); - }; - - Array.from($$(".select_style ul").children) - .forEach(e => { - e.onclick = (event)=>{ - $$("#style-img").setAttribute("src", e.querySelector("img").getAttribute("src")); - var name = e.querySelector("img").getAttribute("data-name"); - $$("#style-img").setAttribute("data-name", name); - models[name].load(); - } - }) - - $$("#upload_button").onclick = ()=>{ - $$('#imageReader').click(); - } - - - $$("#generate").onclick = ()=>{ - var conImg = $$("#content-img") - var conCanvas = getImageCanvas(conImg, conImg.width, conImg.height); - var styleName = $$("#style-img").getAttribute("data-name"); - if(conImg.src == ""){ - return showErr("Please choose a content image") - }else if(styleName == null){ - return showErr("Please choose a style image") - } - var model = models[styleName]; - var input = _transformInput(conCanvas); - model.predict(input).then((out)=>{ - if(out != null){ - $$("#output-img").src = imagedata_to_uri(out); - }else{ - console.log(out); - } - }) - } - - $$("#imageReader").onchange = function(){ - var file = this.files[0]; - $$("#content-img").src = window.URL.createObjectURL(file); - } - -} - -__init__(); \ No newline at end of file diff --git a/experiments/styleTransfer/index.html b/experiments/styleTransfer/index.html deleted file mode 100644 index 8c1934f5..00000000 --- a/experiments/styleTransfer/index.html +++ /dev/null @@ -1,119 +0,0 @@ ---- -layout: default ---- - - - - - - - - - - -
-
-

Flux Experiment: Style Transfer Demo

-
- -
-
-
-
-
-
- - -
- -
-
-
- - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
    -
  • -
  • -
  • - -
-
-
-
-
-
-
-
-
-
-
-
-

Content Image

- -
-
-
-
-

Style Image

- -
-
-
-
-
-
-
-
-
- -
-
-
-

Stylized Content

- -
- - -
-
- - -
-
-
-
- gvjhk -
-
-
-
- - - - - - - - - - - - diff --git a/index.html b/index.html deleted file mode 100755 index 34c47061..00000000 --- a/index.html +++ /dev/null @@ -1,323 +0,0 @@ ---- -layout: default -title: Elegant ML ---- - - - - -
-
- -

The Elegant Machine Learning Stack

- Flux is a 100% pure-Julia stack and provides lightweight abstractions on top of Julia's native GPU - and AD support. It makes the easy things easy while remaining fully hackable. - -
-
- - -
-
-
-
-

Features

- Flux has features that sets it apart among ML systems. -
-
-
-
-
Compiled Eager Code
-

- Flux provides a single, intuitive way to define models, just like mathematical notation. - Julia transparently compiles your code, optimising and fusing kernels for the GPU, for the best performance. -

-
- -
-
Differentiable Programming
-

- Existing Julia libraries are differentiable and can be incorporated directly into Flux models. - Cutting edge models such as Neural ODEs are first class, and Zygote enables overhead-free gradients. -

-
- -
-
First-class GPU support
-

- GPU kernels can be written directly in Julia via CUDA.jl. - Flux is uniquely hackable and any part can be tweaked, from GPU code to custom gradients and layers. -

-
-
-
-
-
The Model Zoo
-

- A rich collection of Flux scripts to learn from, or tweak to your own data. - Trained Flux models can be used from TextAnalysis or Metalhead. -

-
- -
-
TPUs & Colab
-

- Flux models can be compiled to TPUs for cloud supercomputing, and run from Google Colab notebooks. -

-
-
-
-
- -
-
-
-
-

- Ecosystem - See all -

- Flux has a diverse ecosystem that includes models available for reuse and other useful packages. -
-
-
- -
-
Probabilistic Programming
-

- The Turing.jl and Stheno libraries enable probabilistic programming, bayesian inference and Gaussian processes on top of Flux. -

-
- -
-
GeometricFlux
-

- GeometricFlux.jl is a geometric deep learning library for Flux and has support of CUDA GPU acceleration with CUDA. -

-
- -
-
Metalhead
-

- Metalhead.jl includes many state-of-the-art computer vision models which can easily be used for transfer learning. -

-
-
-
-
-
SciML
-

- The SciML ecosystem uses Flux and Zygote to mix neural nets with differential equations, to get the best of black box and mechanistic modelling. -

-
- -
-
Transformers
-

- Transformers.jl provides components for Transformer models for NLP, as well as providing several trained models out of the box. -

-
- -
-
DiffEqFlux
-

- DiffEqFlux.jl provides tools for creating Neural Differential Equations. -

-
-
- -
-
- -
-
-
-
-

Community

- Get in touch with the Flux community. -
-
-
-
-
Community team
-

- Join the group of community maintainers supporting the FluxML ecosystem. Talk to us on Zulip! 👉 -

-
- -
-
Slack
-

- Official Julia Slack for casual conversation. See #flux-bridged and #machine-learning. -

-
- -
-
Zulip
-

- Zulip server for the Julia programming language community. See #ml-contributors and #machine-learning. -

-
-
-
-
-
Discourse forum
-

- Machine Learning in Julia community. -

-
- -
-
Stack Overflow
-

- Ask questions about Flux.jl. -

-
-
- -
-
- -
-
-
-
-

Why Flux?

-
-
-
- -
-
-
- - -
-
-
-

Researchers, users, and developers of Flux

-
-
    -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
  • -
-
-
diff --git a/index.md b/index.md new file mode 100644 index 00000000..8e1c4975 --- /dev/null +++ b/index.md @@ -0,0 +1,206 @@ + +@@jumbotron,jumbotron-fluid,no-pad + @@container + ~~~ + +

The Elegant Machine Learning Stack

+ Flux is a 100% pure-Julia stack and provides lightweight abstractions on top of Julia's native GPU and AD support. It makes the easy things easy while remaining fully hackable. + ~~~ + + @@buttons + ~~~ + Try It Out + GitHub + Follow on Twitter + ~~~ + @@ + @@ +@@ + +@@features + @@container + @@row + @@col-md-12,feature-title + ~~~ +

Features

+ ~~~ + Flux has features that sets it apart among ML systems. + @@ + @@ + + @@row + @@col-md,feature + ~~~ +
Compiled Eager Code
+ ~~~ + Flux provides a single, intuitive way to define models, just like mathematical notation. Julia transparently [compiles your code](https://julialang.org/blog/2018/12/ml-language-compiler), optimising and fusing kernels for the GPU, for the best performance. + @@ + @@col-md,feature + ~~~ +
Differentiable Programming
+ ~~~ + Existing Julia libraries are differentiable and can be incorporated directly into Flux models. Cutting edge models such as [Neural ODEs](https://julialang.org/blog/2019/01/fluxdiffeq) are first class, and [Zygote](https://github.com/FluxML/Zygote.jl) enables overhead-free gradients. + @@ + @@col-md,feature + ~~~ +
First-class GPU support
+ ~~~ + GPU kernels can be written directly in Julia via [CUDA.jl](https://github.com/JuliaGPU/CUDA.jl). Flux is uniquely hackable and any part can be tweaked, from GPU code to custom gradients and layers. + @@ + @@ + @@ +@@ + + +@@features + @@container + @@row + @@col-md-12,feature-title + ~~~ +

+ Ecosystem + See all +

+ ~~~ + Flux has a diverse ecosystem that includes models available for reuse and other useful packages. + @@ + @@ + + @@row + @@col-md,feature + ~~~ +
Probabilistic Programming
+ ~~~ + The [Turing.jl](https://github.com/TuringLang/Turing.jl) and [Stheno.jl](https://github.com/willtebbutt/Stheno.jl) libraries enable probabilistic programming, Bayesian inference and Gaussian processes on top of Flux. + @@ + @@col-md,feature + ~~~ +
Graph Neural Networks
+ ~~~ + [GraphNeuralNetworks.jl](https://github.com/CarloLucibello/GraphNeuralNetworks.jl) is a graph neural network library for Flux and supports CUDA GPU acceleration. + @@ + @@col-md,feature + ~~~ +
Computer Vision
+ ~~~ + [Metalhead.jl](https://github.com/FluxML/Metalhead.jl) includes many state-of-the-art computer vision models with pre-trained weights. + @@ + @@ + + @@row + @@col-md,feature + ~~~ +
SciML
+ ~~~ + The [SciML](https://sciml.ai/) ecosystem uses the FluxML stack to mix neural nets with differential equations, to get the best of black box and mechanistic modelling. + @@ + @@col-md,feature + ~~~ +
Natural Language Processing
+ ~~~ + [Transformers.jl](https://github.com/chengchingwen/Transformers.jl) provides components for transformer architectures for language modeling, as well as providing several trained models out of the box. + @@ + @@ + @@ +@@ + +@@features + @@container + @@row + @@col-md-12,feature-title + ~~~ +

Community

+ ~~~ + Get in touch with the Flux community. + @@ + @@ + + @@row + @@col-md,feature + ~~~ +
Community team
+ ~~~ + Join the [group of community maintainers](/governance) supporting the FluxML ecosystem. Talk to us on Zulip! 👉 + @@ + @@col-md,feature + ~~~ +
Slack
+ ~~~ + [Official Julia Slack](https://julialang.org/slack/) for casual conversation. See `#flux-bridged` and `#machine-learning`. + @@ + @@col-md,feature + ~~~ +
Zulip
+ ~~~ + [Zulip server](https://julialang.zulipchat.com) for the Julia programming language community. See `#ml-contributors` and `#machine-learning`. + @@ + @@ + + @@row + @@col-md,feature + ~~~ +
Discourse forum
+ ~~~ + [Machine Learning in Julia](https://discourse.julialang.org/c/domain/ML/24) community. + @@ + @@col-md,feature + ~~~ +
Stack Overflow
+ ~~~ + [Ask questions](https://stackoverflow.com/questions/tagged/flux.jl) about Flux.jl. + @@ + @@ + @@ +@@ + + +@@features + @@container + @@row + @@col-md-12,feature-title + ~~~ +

Why Flux?

+ ~~~ + @@ + @@ + + @@row + ~~~ + + ~~~ + @@ + @@ +@@ + + + +@@friends + @@container + @@row + @@col-md-12,feature-title + ~~~ +

Researchers, users, and developers of Flux

+ ~~~ + @@ + @@ + + @@row + ~~~ +
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
+ ~~~ + @@ + @@ +@@ diff --git a/tools/colors/colors.css b/tools/colors/colors.css deleted file mode 100644 index 9cefab42..00000000 --- a/tools/colors/colors.css +++ /dev/null @@ -1,6 +0,0 @@ -/* define colors */ -:root{ - --dark: #213b3b; - --light: #f2faf9; - --medium: #478383; -} \ No newline at end of file diff --git a/tools/fluxjs/flux.js b/tools/fluxjs/flux.js deleted file mode 100644 index 38f05b78..00000000 --- a/tools/fluxjs/flux.js +++ /dev/null @@ -1,75 +0,0 @@ -flux = (function () { - -let Buffer = new BSON().serialize({}).constructor - -function blobAsArrayBuffer(blob) { - return new Promise((resolve, reject) => { - let reader = new FileReader(); - reader.addEventListener("loadend", function() { - resolve(reader.result); - }); - reader.readAsArrayBuffer(blob); - }); -} - -async function fetchBytes(url) { - let resp = await fetch(url); - if (!resp.ok) throw(resp); - let blob = await resp.blob(); - let buf = await blobAsArrayBuffer(blob); - return new Buffer(buf); -} - -async function fetchData(url) { - let buf = await fetchBytes(url); - return new BSON().deserialize(buf); -} - -// `buf` is a Uint8Array from BSON -function readFloat32(buf) { - let view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength); - let data = new Float32Array(view.byteLength/4); - for (i = 0; i < data.length; i++) { - data[i] = view.getFloat32(i*4, true); - } - return data; -} - -function toTensor_(spec) { - let type = spec.type.name; - type = type[type.length-1]; - if (type == 'Float32') spec.data = readFloat32(spec.data.buffer); - else throw `Array type ${spec.type.name} not supported.`; - let array = tf.tensor(spec.data, spec.size.reverse()); - return array -} - -function convertArrays_(data) { - if (!(typeof data == "object")) return data - if (data.tag == "array") { - return toTensor_(data); - } else { - for (k of Object.keys(data)) { - data[k] = convertArrays_(data[k]) - } - } - return data; -} - -async function fetchBlob(url) { - data = await fetchData(url); - return convertArrays_(data) -} - -async function fetchWeights(url) { - ws = await fetchBlob(url); - return ws.weights; -} - -const _data = t => (t instanceof tf.Tensor)? t.dataSync(): t; -const slice = t => (t instanceof tf.Tensor)? t.clone():( - t instanceof Array ? t.slice() : t ); - -return {fetchData, fetchWeights, fetchBlob, convertArrays_, data: _data, slice}; - -})(); diff --git a/tools/game/css/overlay.css b/tools/game/css/overlay.css deleted file mode 100644 index e97b8782..00000000 --- a/tools/game/css/overlay.css +++ /dev/null @@ -1,34 +0,0 @@ -.overlay{ - pointer-events: none; -} - -.overlay > * { - top:0; - bottom: 0; - left: 0; - right: 0; - background: rgba(0, 0,0, .4); - transition: all .5s linear; - opacity: 1; - z-index: 999; - pointer-events: none; -} - -#start, #gameOver{ - display: flex; - -webkit-justify-content: center; - justify-content: center; - align-items: center; - flex-direction: column; -} - -#overlay p{ - height: fit-content; - font-size: 28px; -} - -.hidden{ - opacity: 0; - pointer-events: none; -} - diff --git a/tools/game/css/style.css b/tools/game/css/style.css deleted file mode 100644 index 65114327..00000000 --- a/tools/game/css/style.css +++ /dev/null @@ -1,138 +0,0 @@ -.demo_wrapper { - margin: 0px auto; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -.instructions{ - margin: 40px 0 0 0; - background: var(--light); - padding: 20px; - border-radius: 6px; - /* box-sizing: border-box; */ - text-align: justify; - width: 100%; -} - -.code_link{ - width: fit-content; - /* background: #ffffff; */ - border: 1px solid; - padding: 5px 10px; - border-radius: 3px; - color: var(--dark); - float: right; - font-weight: 900; -} - -.board{ - position: relative; - color: #fff; -} - -.board > *, .overlay > *{ - position: absolute; -} - -.board > *, .game-over{ - top:0; - left:0; - right: 0; - bottom: 0; -} - -.overlay .keyboard{ - - right: 10px !important; - top: 10px; - width: 100px; - height: 50px; - -} - -.game-over{ - display: flex; - justify-content: center; - align-items: center; - background: rgba(0,0,0,0.7); - transition: all .4s linear; - opacity: 1; -} - -.hidden-screen{ - opacity: 0; -} - -.game-over p{ - font-size: 2em; -} - -#controls{ - background: var(--light); - color: var(--dark); - /*margin: 10px;*/ - border-top-left-radius: 6px; - border-top-right-radius: 6px; - - box-sizing: border-box; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-justify-content: space-between; - justify-content: space-between; - -} - -#controls .heading{ - padding: 20px; - font-size: 1.2em; -} - -#controls .options{ - display: flex; - justify-content: space-between; - align-items: center; -} - - -#controls .comp{ - background: url("../img/comp.png") 0 0 no-repeat; - background-size: 20px; -} - -#controls .human{ - background: url("../img/human.png") 0 0 no-repeat; - background-size: 20px; -} - -#controls .comp, #controls .human{ - cursor: pointer; - width: 30px; - height: 30px; - margin: 10px 20px 10px 0; - background-position: center; - /*border-left: 1px solid #aaa;*/ -} - -#controls .option{ - border-radius: 50%; - background-color: #777; - /*transition: all .6s linear;*/ -} - -#controls .options .selected{ - background-color: var(--dark); - transform: scale(1.1); - box-shadow: 0 2px 2px #333; -} - -#game { - width: 500px; - margin: 30px auto; - box-shadow: 2px 3px 5px #aaa; - border-radius: 6px; - overflow: hidden; -} diff --git a/tools/game/img/comp.png b/tools/game/img/comp.png deleted file mode 100644 index 0f362b0f..00000000 Binary files a/tools/game/img/comp.png and /dev/null differ diff --git a/tools/game/img/human.png b/tools/game/img/human.png deleted file mode 100644 index 51d41f8b..00000000 Binary files a/tools/game/img/human.png and /dev/null differ diff --git a/tools/game/js/Ball.js b/tools/game/js/Ball.js deleted file mode 100644 index af9d3348..00000000 --- a/tools/game/js/Ball.js +++ /dev/null @@ -1,31 +0,0 @@ -function Ball(pos, speed, {color="#00f", radius=10}={}){ - this.pos = pos; - this.speed = speed; - this.radius = radius; - this.color = color; -} - -Ball.prototype.draw = function (canvas) { - var ctx = canvas.getContext('2d'); - ctx.beginPath(); - ctx.fillStyle = this.color; - ctx.arc(this.pos.x, this.pos.y, this.radius, 0, 2*Math.PI); - ctx.fill(); -} - -Ball.prototype.move = function () { - this.pos.add(this.speed); -} - -Ball.prototype.detectCollision = function (width, height) { // with top, left & right walls - var collisions = []; - if(this.pos.x - this.radius <= 0 || this.pos.x + this.radius >= width)collisions.push([-1, 1]); - if(this.pos.y - this.radius <= 0)collisions.push([1, -1]); - - return collisions; -} - -Ball.prototype.rebound = function ([mx, my]) { - this.speed.x *= mx; - this.speed.y *= my; -} \ No newline at end of file diff --git a/tools/game/js/Game.js b/tools/game/js/Game.js deleted file mode 100644 index 6eac7aaa..00000000 --- a/tools/game/js/Game.js +++ /dev/null @@ -1,180 +0,0 @@ -/***************** - -Game Controller -================ - -env : { - done : () => { done ? (bool) } - step : (action) => { go to next state } - state : () => { return state } - config : () => { rendering info } - reset : () => { reset env } -} - -out : { - render : () { draw } -} - -model : (input tf vector) => { output tf vector } - -*****************/ - - -// interact with env -function Game(env, out, model, { - state=0, - mode="timer", // mode: "async" | "timer" - timeInt=20, - callBacks={}, - transform={ - state: function(state){ - ({ x, xvel , theta, thetavel } = state); - return tf.tensor([x, xvel, theta, thetavel]) - }, - action: function(a){ - var b = tf.argMax(a) - return b.data().then(d => { - tf.dispose(b); - return d[0] + 1; - }); - } - }, - autoReset=false - }={}){ - this.state = state; - this.gameOver = false; - this.env = env; - this.out = out; - this.model = model; - this.mode = mode; - this.timeInt = timeInt; - this.callBacks = callBacks; - this.transform = transform; - this.states = { - H : 0, - C : 1, - "human": 0, - "computer": 1 - }; - this.playTimeout = null; - this.newAction = this.defaultAction(); - this.autoReset = autoReset; -} - -Game.prototype.setTimeInt = function(t){ - this.timeInt = t; -} - -Game.prototype.nextGameState = function(curr){ - return curr; -} - -Game.prototype.startState = function(){ - return this.state -} - -Game.prototype.gameOverHandler = function(){ - this.setState(this.startState()); - this.reset(); -} - -Game.prototype.isValidAction = function(action){ - return true; -} - -Game.prototype.turn = function(string){ - return this.state == this.states[string]; -} - -Game.prototype.action = function(a){ - if(this.gameOver) - return this.gameOverHandler(); - - if(!this.isValidAction(a))return false; - - this.newAction = a; - switch(this.state){ - case this.states.H: - if(this.mode == "async")this.move(this.newAction); // action initiates a move - break; - case this.states.C: - break; - } - - if(typeof(this.callBacks.action) == "function")return this.callBacks.action(a); - return true; -} - -Game.prototype.play = async function(){ - clearTimeout(this.playTimeout); - if(this.env.done())return; - - var scope = this; - switch(this.state){ - case this.states.H: - this.move(this.newAction); - // newAction = 0; - break; - case this.states.C: - var a = await this.predict(this.env.state()) - var action = await this.transform.action(a); - this.move(action); - tf.dispose(a); - break; - default: - console.log("Invalid state", this.state); - } -} - -Game.prototype.next = function(){ - this.state = this.nextGameState(this.state) - if(!this.env.done()){ - var play = this.play.bind(this); - if(this.mode=="timer" || this.state == this.states.C) // play initiates a move - this.playTimeout = setTimeout(play, this.timeInt); - }else{ - var scope = this; - if(this.autoReset)this.gameOverHandler(); - else{ - setTimeout(()=>{ - scope.gameOver = true; // wait 400 ms before resetting - }, 400) - } - } - -} - -Game.prototype.display = function(){ - this.out.render(this.env.config()); -} - -Game.prototype.move = function(a){ - this.env.step(a); - this.display(); - this.next(); -} -Game.prototype.predict = function(state){ - return tf.tidy(()=>{ - var input = this.transform.state(state); - return this.model(input); - }) -} -Game.prototype.reset = function(){ - this.env.reset(); - this.newAction = this.defaultAction(); - this.gameOver = false; - this.display(); -} - -Game.prototype.setState = function(newState){ - this.reset(); - if(typeof(newState) == "string") - this.state = this.states[newState]; - else - this.state = newState; - this.play(); -} - -Game.prototype.defaultAction = function(){ - return 0; -} \ No newline at end of file diff --git a/tools/game/js/Paddle.js b/tools/game/js/Paddle.js deleted file mode 100644 index 159bcf0d..00000000 --- a/tools/game/js/Paddle.js +++ /dev/null @@ -1,39 +0,0 @@ -function Paddle(pos, {color="#f00", width=50, height=10, total_width, total_height}={}){ - this.pos = pos; - this.dir = 0; - - this.total_width = total_width; - this.total_height = total_height; - this.width = width; - this.height = height; - this.color= color; -} - -Paddle.prototype.draw = function (canvas) { - var ctx = canvas.getContext('2d'); - ctx.fillStyle = this.color; - ctx.fillRect(this.pos.x, this.pos.y, this.width, this.height); -} - -Paddle.prototype.move = function () { - this.pos.add(new Vector(this.dir*10, 0)); - if(this.pos.x < 0)this.pos.x = 0; - else if(this.pos.x + this.width > this.total_width) this.pos.x = this.total_width - this.width; -} - -Paddle.prototype.detectCollision = function(ball){ - if(ball.pos.x + ball.radius >= this.pos.x && ball.pos.y + ball.radius >= this.pos.y && ball.pos.x - ball.radius <= this.pos.x + this.width && ball.pos.y <= this.pos.y + this.height){ - return this - } - return null -} - -Paddle.prototype.setDirection = function (d) {this.dir = d;} - -Paddle.prototype.rebound = function (ball) { - var diff = this.pos.x + this.width/2 - ball.pos.x; - ball.rebound([-1, 1]); - ball.speed.y += Math.sign(ball.speed.y); - ball.speed.x = ball.speed.y*diff/this.width; - -} diff --git a/tools/game/js/helpers.js b/tools/game/js/helpers.js deleted file mode 100644 index f2198538..00000000 --- a/tools/game/js/helpers.js +++ /dev/null @@ -1,53 +0,0 @@ -// general helper -function Vector(x, y){ - this.x = x; - this.y = y; - - this.add = (other)=>{ - this.x += other.x; - this.y += other.y; - } -} - -function CircBuf(size){ - this.size = size; - this.buf = new Array(size); - this.index = 0; -} -CircBuf.prototype.fill = function(n){this.buf.fill(n)} -CircBuf.prototype.set = function(n){ - this.buf[this.index] = n; -} -CircBuf.prototype.next = function() { - this.index = (this.index + 1) % this.size; -}; -CircBuf.prototype.sum = function(){ - return this.buf.reduce((acc, ele) => acc + ele, 0) -} - -function randColor(){ - return "#" + Math.floor(Math.random()*999); -} - -function show(ele){ - if(ele.className.match(" hidden") != null){ - ele.className = ele.className.replace(" hidden", ""); - } -} - -function hide(ele){ - if(ele.className.match(" hidden") == null){ - ele.className += " hidden"; - } -} - -var $$ = (s)=>document.querySelector(s); - -function highlight(el, container){ - var old = container.querySelector('.selected'); - if( old != el){ - if(old) - old.className = old.className.replace("selected", ""); - el.className += " selected"; - } -} \ No newline at end of file diff --git a/tools/img/comp.png b/tools/img/comp.png deleted file mode 100644 index 9b12bfe8..00000000 Binary files a/tools/img/comp.png and /dev/null differ diff --git a/tools/img/human.png b/tools/img/human.png deleted file mode 100644 index 09bee02c..00000000 Binary files a/tools/img/human.png and /dev/null differ diff --git a/tools/loadWeights/loadWeights.js b/tools/loadWeights/loadWeights.js deleted file mode 100644 index fc7f43fe..00000000 --- a/tools/loadWeights/loadWeights.js +++ /dev/null @@ -1,38 +0,0 @@ -function loadWeights(url, pc, func, model=null){ - return _loadWeights([{url, model: (model || window.model)}], pc, func); -} - -function _loadWeights(configArr, progressContainer, __init__){ - - let Buffer = new BSON().serialize({}).constructor - - // send an xhr Request so as to show event progress - var config = configArr.map((c)=>{ - var weightsRequest = new XMLHttpRequest(); - weightsRequest.open('GET', c.url); - weightsRequest.responseType = "arraybuffer"; - return Object.assign({}, c, {xhr: weightsRequest}) - }); - - // initialise progress bar - var pbar = new ProgressBar({ - config, - container: progressContainer, - done: function(results){ - results.forEach(({event, model})=>{ - { - var target = (event.currentTarget || event.target); - var response = new Buffer(target.response); - var data = new BSON().deserialize(response); - model.weights = flux.convertArrays_(data).weights; - } - }); - __init__() - }, - err: console.log - }) - - - pbar.start(); - config.forEach(({xhr}) => xhr.send()); -} \ No newline at end of file diff --git a/tools/progressBar/css/progressBar.css b/tools/progressBar/css/progressBar.css deleted file mode 100644 index 4dc8fc7d..00000000 --- a/tools/progressBar/css/progressBar.css +++ /dev/null @@ -1,46 +0,0 @@ -.progress-backdrop{ - position: absolute; - top: 0; - right: 0; - left:0; - bottom:0; - background: rgba(255, 255, 255, 0.7); - display: flex; - -webkit-justify-content: center; - justify-content: center; - align-items: center; -} - -.progress-lightbox{ - padding: 30px; - background: #fff; - box-shadow: 0px 3px 5px #aaa; - - border-radius: 6px; - width: 400px; - -} - -.progress-lightbox h3{ - color: #555; - font-size: 1em; -} - -.progress-bar-fill{ - position: absolute; - background: #555; - top: 0; - bottom: 0; - left: 0; - width: 0; - transition: all .5s linear; - border-radius: 3px; -} - -.progress-bar{ - width: 100%; - position: relative; - height: 5px; - margin: 20px 0; - background: #FFF; -} \ No newline at end of file diff --git a/tools/progressBar/js/ProgressBar.js b/tools/progressBar/js/ProgressBar.js deleted file mode 100644 index fbf67ca1..00000000 --- a/tools/progressBar/js/ProgressBar.js +++ /dev/null @@ -1,63 +0,0 @@ -(function(obj){ - - Object.assign(obj, {ProgressBar}); - - function ProgressBar({ config, container, done, err }){ - this.container = container; - this.progress = new Array(config.length).fill(0); - - var scope = this; - - var promises = config.map(({xhr, model, url}, index)=>{ - xhr.addEventListener('progress', (event)=>{ - if(event.currentTarget.status == 200){ - var p = event.loaded/event.total; - this.progress[index] = p; - scope.update(); - } - }) - - return new Promise((accept, reject)=>{ - xhr.addEventListener('load', function(event){ - if(event.currentTarget.readyState == 4 && event.currentTarget.status == 200){ - accept({ event, model}); - } - }); - xhr.addEventListener('error', (e)=> reject(url, e)); - }) - }) - - Promise.all(promises).then((results)=>{ - scope.dismiss(); - done(results) - }).catch(err); - } - - ProgressBar.prototype.start = function(){ - var backdrop = document.createElement('div'); - backdrop.className = 'progress-backdrop'; - backdrop.innerHTML = ('
\ -

Loading Weights ... 0%

\ -
\ -
\ -
\ -
') - - this.backdrop = backdrop; - this.container.appendChild(backdrop); - this.fill = backdrop.querySelector('.progress-bar-fill'); - this.status = backdrop.querySelector('.progress-status'); - } - - - ProgressBar.prototype.update = function(){ - var frac = Math.min(...this.progress) - this.total = this.backdrop.querySelector('.progress-bar').getClientRects()[0].width; - this.fill.style.width = (this.total*frac) + 'px'; - this.status.innerText = Math.round(frac*100); - } - - ProgressBar.prototype.dismiss = function(){ - this.container.removeChild(this.backdrop); - } -})(window) \ No newline at end of file diff --git a/tutorials/_posts/2020-09-15-deep-learning-flux.md b/tutorials/_posts/2020-09-15-deep-learning-flux.md deleted file mode 100755 index fc7ba069..00000000 --- a/tutorials/_posts/2020-09-15-deep-learning-flux.md +++ /dev/null @@ -1,437 +0,0 @@ ---- -title: Deep Learning with Flux - A 60 Minute Blitz -author: Saswat Das, Mike Innes, Andrew Dinhobl, Ygor Canalli, Sudhanshu Agrawal, João Felipe Santos -layout: blog -tag: Learning Flux ---- - -This is a quick intro to [Flux](https://github.com/FluxML/Flux.jl) loosely based on [PyTorch's tutorial](https://pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html). It introduces basic Julia programming, as well Zygote, a source-to-source automatic differentiation (AD) framework in Julia. We'll use these tools to build a very simple neural network. - -## Arrays - -The starting point for all of our models is the `Array` (sometimes referred to as a `Tensor` in other frameworks). This is really just a list of numbers, which might be arranged into a shape like a square. Let's write down an array with three elements. - -```julia -x = [1, 2, 3] -``` - -Here's a matrix – a square array with four elements. - -```julia -x = [1 2; 3 4] -``` - -We often work with arrays of thousands of elements, and don't usually write them down by hand. Here's how we can create an array of 5×3 = 15 elements, each a random number from zero to one. - -```julia -x = rand(5, 3) -``` - -There's a few functions like this; try replacing `rand` with `ones`, `zeros`, or `randn` to see what they do. - -By default, Julia works stores numbers is a high-precision format called `Float64`. In ML we often don't need all those digits, and can ask Julia to work with `Float32` instead. We can even ask for more digits using `BigFloat`. - -```julia -x = rand(BigFloat, 5, 3) - -x = rand(Float32, 5, 3) -``` - -We can ask the array how many elements it has. - -```julia -length(x) -``` - -Or, more specifically, what size it has. - -```julia -size(x) -``` - -We sometimes want to see some elements of the array on their own. - -```julia -x - -x[2, 3] -``` - -This means get the second row and the third column. We can also get every row of the third column. - -```julia -x[:, 3] -``` - -We can add arrays, and subtract them, which adds or subtracts each element of the array. - -```julia -x + x - -x - x -``` - -Julia supports a feature called *broadcasting*, using the `.` syntax. This tiles small arrays (or single numbers) to fill bigger ones. - -```julia -x .+ 1 -``` - -We can see Julia tile the column vector `1:5` across all rows of the larger array. - -```julia -zeros(5,5) .+ (1:5) -``` - -The x' syntax is used to transpose a column `1:5` into an equivalent row, and Julia will tile that across columns. - -```julia -zeros(5,5) .+ (1:5)' -``` - -We can use this to make a times table. - -```julia -(1:5) .* (1:5)' -``` - -Finally, and importantly for machine learning, we can conveniently do things like matrix multiply. - -```julia -W = randn(5, 10) -x = rand(10) -W * x -``` - -Julia's arrays are very powerful, and you can learn more about what they can do [here](https://docs.julialang.org/en/v1/manual/arrays/). - -## CUDA Arrays - -CUDA functionality is provided separately by the [CUDA package](https://github.com/JuliaGPU/CUDA.jl). If you have a GPU and CUDA available, you can run `] add CUDA` in a REPL or IJulia to get it. - -Once CUDA is loaded you can move any array to the GPU with the `cu` function, and it supports all of the above operations with the same syntax. - -```julia -using CUDA -x = cu(rand(5, 3)) -``` - -## Automatic Differentiation - -You probably learned to take derivatives in school. We start with a simple mathematical function like - -```julia -f(x) = 3x^2 + 2x + 1 - -f(5) -``` - -In simple cases it's pretty easy to work out the gradient by hand – here it's `6x+2`. But it's much easier to make Flux do the work for us! - -```julia -using Flux: gradient - -df(x) = gradient(f, x)[1] - -df(5) -``` - -You can try this with a few different inputs to make sure it's really the same as `6x+2`. We can even do this multiple times (but the second derivative is a fairly boring `6`). - -```julia -ddf(x) = gradient(df, x)[1] - -ddf(5) -``` - -Flux's AD can handle any Julia code you throw at it, including loops, recursion and custom layers, so long as the mathematical functions you call are differentiable. For example, we can differentiate a Taylor approximation to the `sin` function. - -```julia -mysin(x) = sum((-1)^k*x^(1+2k)/factorial(1+2k) for k in 0:5) - -x = 0.5 - -mysin(x), gradient(mysin, x) - -sin(x), cos(x) -``` - -You can see that the derivative we calculated is very close to `cos(x)`, as we expect. - -This gets more interesting when we consider functions that take *arrays* as inputs, rather than just a single number. For example, here's a function that takes a matrix and two vectors (the definition itself is arbitrary) - -```julia -myloss(W, b, x) = sum(W * x .+ b) - -W = randn(3, 5) -b = zeros(3) -x = rand(5) - -gradient(myloss, W, b, x) -``` - -Now we get gradients for each of the inputs `W`, `b` and `x`, which will come in handy when we want to train models. - -Because ML models can contain hundreds of parameters, Flux provides a slightly different way of writing `gradient`. We instead mark arrays with `param` to indicate that we want their derivatives. `W` and `b` represent the weight and bias respectively. - -```julia -using Flux: params - -W = randn(3, 5) -b = zeros(3) -x = rand(5) - -y(x) = sum(W * x .+ b) - -grads = gradient(()->y(x), params([W, b])) - -grads[W], grads[b] -``` - - -We can now grab the gradients of `W` and `b` directly from those parameters. - -This comes in handy when working with *layers*. A layer is just a handy container for some parameters. For example, `Dense` does a linear transform for you. - -```julia -using Flux - -m = Dense(10, 5) - -x = rand(Float32, 10) -``` - -We can easily get the parameters of any layer or model with params with `params`. - -```julia -params(m) -``` - -This makes it very easy to calculate the gradient for all parameters in a network, even if it has many parameters. - -```julia -x = rand(Float32, 10) -m = Chain(Dense(10, 5, relu), Dense(5, 2), softmax) -l(x) = sum(Flux.crossentropy(m(x), [0.5, 0.5])) -grads = gradient(params(m)) do - l(x) -end -for p in params(m) - println(grads[p]) -end -``` - -You don't have to use layers, but they can be convient for many simple kinds of models and fast iteration. - -The next step is to update our weights and perform optimisation. As you might be familiar, *Gradient Descent* is a simple algorithm that takes the weights and steps using a learning rate and the gradients. `weights = weights - learning_rate * gradient`. - -```julia -using Flux.Optimise: update!, Descent -η = 0.1 -for p in params(m) - update!(p, -η * grads[p]) -end -``` - -While this is a valid way of updating our weights, it can get more complicated as the algorithms we use get more involved. - -Flux comes with a bunch of pre-defined optimisers and makes writing our own really simple. We just give it the learning rate η: - -```julia -opt = Descent(0.01) -``` - -`Training` a network reduces down to iterating on a dataset mulitple times, performing these steps in order. Just for a quick implementation, let’s train a network that learns to predict `0.5` for every input of 10 floats. `Flux` defines the `train!` function to do it for us. - -```julia -data, labels = rand(10, 100), fill(0.5, 2, 100) -loss(x, y) = sum(Flux.crossentropy(m(x), y)) -Flux.train!(loss, params(m), [(data,labels)], opt) -``` - -You don't have to use `train!`. In cases where aribtrary logic might be better suited, you could open up this training loop like so: - -```julia - for d in training_set # assuming d looks like (data, labels) - # our super logic - gs = gradient(params(m)) do #m is our model - l = loss(d...) - end - update!(opt, params(m), gs) - end -``` - -## Training a Classifier - -Getting a real classifier to work might help cement the workflow a bit more. [CIFAR10](https://https://www.cs.toronto.edu/~kriz/cifar.html) is a dataset of 50k tiny training images split into 10 classes. - -We will do the following steps in order: - -* Load CIFAR10 training and test datasets -* Define a Convolution Neural Network -* Define a loss function -* Train the network on the training data -* Test the network on the test data - -### Loading the Dataset - - -```julia -using Statistics -using Flux, Flux.Optimise -using MLDatasets: CIFAR10 -using Images.ImageCore -using Flux: onehotbatch, onecold -using Base.Iterators: partition -using CUDA -``` - -This image will give us an idea of what we are dealing with. - -![title](https://pytorch.org/tutorials/_images/cifar10.png) - - -```julia -train_x, train_y = CIFAR10.traindata(Float32) -labels = onehotbatch(train_y, 0:9) -``` - -The `train_x` contains 50000 images converted to 32 X 32 X 3 arrays with the third dimension being the 3 channels (R,G,B). Let's take a look at a random image from the train_x. For this, we need to permute the dimensions to 3 X 32 X 32 and use `colorview` to convert it back to an image. - -```julia -using Plots -image(x) = colorview(RGB, permutedims(x, (3, 2, 1))) -plot(image(train_x[:,:,:,rand(1:end)])) -``` - -We can now arrange the training data in batches of say, 1000 and keep a validation set to track our progress. This process is called minibatch learning, which is a popular method of training large neural networks. Rather that sending the entire dataset at once, we break it down into smaller chunks (called minibatches) that are typically chosen at random, and train only on them. It is shown to help with escaping [saddle points](https://en.wikipedia.org/wiki/Saddle_point). - -The first 49k images (in batches of 1000) will be our training set, and the rest is for validation. `partition` handily breaks down the set we give it in consecutive parts (1000 in this case). - -```julia -train = ([(train_x[:,:,:,i], labels[:,i]) for i in partition(1:49000, 1000)]) |> gpu -valset = 49001:50000 -valX = train_x[:,:,:,valset] |> gpu -valY = labels[:, valset] |> gpu -``` - -### Defining the Classifier -Now we can define our Convolutional Neural Network (CNN). - -A convolutional neural network is one which defines a kernel and slides it across a matrix to create an intermediate representation to extract features from. It creates higher order features as it goes into deeper layers, making it suitable for images, where the strucure of the subject is what will help us determine which class it belongs to. - -```julia -m = Chain( - Conv((5,5), 3=>16, relu), - MaxPool((2,2)), - Conv((5,5), 16=>8, relu), - MaxPool((2,2)), - x -> reshape(x, :, size(x, 4)), - Dense(200, 120), - Dense(120, 84), - Dense(84, 10), - softmax) |> gpu -``` - -We will use a crossentropy loss and an Momentum optimiser here. Crossentropy will be a good option when it comes to working with mulitple independent classes. Momentum gradually lowers the learning rate as we proceed with the training. It helps maintain a bit of adaptivity in our optimisation, preventing us from over shooting from our desired destination. - -```julia -using Flux: crossentropy, Momentum - -loss(x, y) = sum(crossentropy(m(x), y)) -opt = Momentum(0.01) -``` - -We can start writing our train loop where we will keep track of some basic accuracy numbers about our model. We can define an `accuracy` function for it like so. - -```julia -accuracy(x, y) = mean(onecold(m(x), 0:9) .== onecold(y, 0:9)) -``` - -### Training the Classifier - - -Training is where we do a bunch of the interesting operations we defined earlier, and see what our net is capable of. We will loop over the dataset 10 times and feed the inputs to the neural network and optimise. - -```julia -epochs = 10 - -for epoch = 1:epochs - for d in train - gs = gradient(params(m)) do - l = loss(d...) - end - update!(opt, params(m), gs) - end - @show accuracy(valX, valY) -end -``` - -Seeing our training routine unfold gives us an idea of how the network learnt the function. This is not bad for a small hand-written network, trained for a limited time. - -### Training on a GPU - -The `gpu` functions you see sprinkled through this bit of the code tell Flux to move these entities to an available GPU, and subsequently train on it. No extra faffing about required! The same bit of code would work on any hardware with some small annotations like you saw here. - -### Testing the Network - -We have trained the network for 100 passes over the training dataset. But we need to check if the network has learnt anything at all. - -We will check this by predicting the class label that the neural network outputs, and checking it against the ground-truth. If the prediction is correct, we add the sample to the list of correct predictions. This will be done on a yet unseen section of data. - -Okay, first step. Let us perform the exact same preprocessing on this set, as we did on our training set. - -```julia -test_x, test_y = CIFAR10.testdata(Float32) -test_labels = onehotbatch(test_y, 0:9) - -test = gpu.([(test_x[:,:,:,i], test_labels[:,i]) for i in partition(1:10000, 1000)]) -``` - -Next, display an image from the test set. - -```julia -plot(image(test_x[:,:,:,rand(1:end)])) -``` - -The outputs are energies for the 10 classes. Higher the energy for a class, the more the network thinks that the image is of the particular class. Every column corresponds to the output of one image, with the 10 floats in the column being the energies. - -Let's see how the model fared. - -```julia -ids = rand(1:10000, 5) -rand_test = test_x[:,:,:,ids] |> gpu -rand_truth = test_y[ids] -m(rand_test) -``` - -This looks similar to how we would expect the results to be. At this point, it's a good idea to see how our net actually performs on new data, that we have prepared. - -```julia -accuracy(test[1]...) -``` - -This is much better than random chance set at 10% (since we only have 10 classes), and not bad at all for a small hand written network like ours. - -Let's take a look at how the net performed on all the classes performed individually. - -```julia -class_correct = zeros(10) -class_total = zeros(10) -for i in 1:10 - preds = m(test[i][1]) - lab = test[i][2] - for j = 1:1000 - pred_class = findmax(preds[:, j])[2] - actual_class = findmax(lab[:, j])[2] - if pred_class == actual_class - class_correct[pred_class] += 1 - end - class_total[actual_class] += 1 - end -end - -class_correct ./ class_total -``` - -The spread seems pretty good, with certain classes performing significantly better than the others. Why should that be? diff --git a/tutorials/_posts/2020-10-18-transfer-learning.md b/tutorials/_posts/2020-10-18-transfer-learning.md deleted file mode 100644 index dfb4250e..00000000 --- a/tutorials/_posts/2020-10-18-transfer-learning.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: Transfer Learning with Flux -author: Dhairya Gandhi -layout: blog -tag: Transfer learning ---- - -This article is intended to be a general guide to how transfer learning works in the Flux ecosystem. We assume a certain familiarity of the reader with the concept of transfer learning. Having said that, we will start off with a basic definition of the setup and what we are trying to achieve. There are many resources online that go in depth as to why transfer learning is an effective tool to solve many ML problems, and we recommend checking some of those out. - -Machine Learning today has evolved to use many highly trained models in a general task, where they are tuned to perform especially well on a subset of the problem. - -This is one of the key ways in which larger (or smaller) models are used in practice. They are trained on a general problem, achieving good results on the test set, and then subsequently tuned on specialised datasets. - -In this process, our model is already pretty well trained on the problem, so we don't need to train it all over again as if from scratch. In fact, as it so happens, we don't need to do that at all! We only need to tune the last couple of layers to get the most performance from our models. The exact last number of layers is dependant on the problem setup and the expected outcome, but a common tip is to train the last few `Dense` layers in a more complicated model. - -So let's try to simulate the problem in Flux. - -We'll tune a pretrained ResNet from Metalhead as a proxy. We will tune the `Dense` layers in there on a new set of images. - -```julia -using Flux, Metalhead -using Flux: @epochs -using Metalhead.Images -resnet = ResNet().layers -``` -
- -If we intended to add a new class of objects in there, we need only `reshape` the output from the previous layers accordingly. -Our model would look something like so: - -```julia - model = Chain( - resnet[1:end-2], # We only need to pull out the dense layer in here - x -> reshape(x, size_we_want), # / global_avg_pooling layer - Dense(reshaped_input_features, n_classes) - ) -``` -
- -We will use the [Dogs vs. Cats](https://www.kaggle.com/c/dogs-vs-cats/data?select=train.zip) dataset from Kaggle for our use here. -Make sure to download the `train.zip` file and extract it into a `train` folder. - -The [`dataloader.jl`](https://github.com/FluxML/model-zoo/blob/master/tutorials/transfer_learning/dataloader.jl) script contains a pre-written `load_batch` function which will load a set of images, shuffled between dogs and cats along with their correct labels. - -```julia -include("dataloader.jl") -``` -
- -Finally, the model looks something like: - -```julia -model = Chain( - resnet[1:end-2], - Dense(2048, 1000), - Dense(1000, 256), - Dense(256, 2), # we get 2048 features out, and we have 2 classes -) -``` -
- -To speed up training, let’s move everything over to the GPU - -```julia -model = model |> gpu -dataset = [gpu.(load_batch(10)) for i in 1:10] -``` -
- -After this, we only need to define the other parts of the training pipeline like we usually do. - -```julia -opt = ADAM() -loss(x,y) = Flux.Losses.logitcrossentropy(model(x), y) -``` -
- -Now to train. As discussed earlier, we don’t need to pass all the parameters to our training loop. Only the ones we need to fine-tune. Note that we could have picked and chosen the layers we want to train individually as well, but this is sufficient for our use as of now. - -```julia -ps = Flux.params(model) -``` -**Note**: Normally, you would only re-train the dense layers via `model[2:end]` but in this case, the pre-trained models from Metalhead.jl are not currently available. This will change in the future once the pre-trained models are once again available. -
- -And now, let's train! - -```julia -@epochs 2 Flux.train!(loss, ps, dataset, opt) -``` -
- -And there you have it, a pretrained model, fine tuned to tell the the dogs from the cats. - -We can verify this too. - -```julia -imgs, labels = gpu.(load_batch(10)) -display(model(imgs)) - -labels -``` -
diff --git a/tutorials/_posts/2021-01-21-data-loader.md b/tutorials/_posts/2021-01-21-data-loader.md deleted file mode 100755 index e67cc069..00000000 --- a/tutorials/_posts/2021-01-21-data-loader.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: Using Flux DataLoader -author: Liliana Badillo, Dhairya Gandhi -layout: blog -tag: Learning Flux ---- - -In this tutorial, we show how to load image data in Flux DataLoader and process it in mini-batches. We use the [DataLoader](https://fluxml.ai/Flux.jl/stable/data/dataloader/#Flux.Data.DataLoader) type to handle iteration over mini-batches of data. For this example, we load the [MNIST dataset](https://juliaml.github.io/MLDatasets.jl/stable/datasets/MNIST/) using the [MLDatasets](https://juliaml.github.io/MLDatasets.jl/stable/) package. - -Before we start, make sure you have installed the following packages: - -* [Flux](https://github.com/FluxML/Flux.jl) -* [MLDatasets](https://juliaml.github.io/MLDatasets.jl/stable/) - -To install these packages, run the following in the REPL: - -```julia -Pkg.add("Flux") -Pkg.add("MLDatasets") -``` - -
- -Load the packages we'll need: - -```julia -using MLDatasets: MNIST -using Flux.Data: DataLoader -using Flux: onehotbatch -``` - -## Step1: Loading the MNIST data set - -We load the MNIST train and test data from MLDatasets: - -```julia -train_x, train_y = MNIST(:train)[:] -test_x, test_y = MNIST(:test)[:] -``` -
- -This code loads the MNIST train and test images as Float32 as well as their labels. The data set `train_x` is a 28×28×60000 multi-dimensional array. It contains 60000 elements and each one of it contains a 28x28 array. Each array represents a 28x28 image (in grayscale) of a handwritten digit. Moreover, each element of the 28x28 arrays is a pixel that represents the amount of light that it contains. On the other hand, `test_y` is a 60000 element vector and each element of this vector represents the label or actual value (0 to 9) of a handwritten digit. - -## Step 2: Loading the dataset onto DataLoader - -Before we load the data onto a DataLoader, we need to reshape it so that it has the correct shape for Flux. For this example, the MNIST train data must be of the same dimension as our model's input and output layers. - -For example, if our model's input layer expects a 28x28x1 multi-dimensional array, we need to reshape the train and test data as follows: - -```julia -train_x = reshape(train_x, 28, 28, 1, :) -test_x = reshape(test_x, 28, 28, 1, :) -``` -
- -Also, the MNIST labels must be encoded as a vector with the same dimension as the number of categories (unique handwritten digits) in the data set. To encode the labels, we use the [Flux's onehotbatch](https://fluxml.ai/Flux.jl/stable/data/onehot/#Batches-1) function: - -```julia -train_y, test_y = onehotbatch(train_y, 0:9), onehotbatch(test_y, 0:9) -``` -
- ->**Note:** For more information on other encoding methods, see [Handling Data in Flux](https://fluxml.ai/Flux.jl/stable/data/onehot/). - -Now, we load the train images and their labels onto a DataLoader object: - -```julia -data_loader = DataLoader((train_x, train_y); batchsize=128, shuffle=true) -``` -
- -Notice that we set the DataLoader `batchsize` to 128. This will enable us to iterate over the data in batches of size 128. Also, by setting `shuffle=true` the DataLoader will shuffle the observations each time that iterations are re-started. - -## Step 3: Iterating over the data - -Finally, we can iterate over the 60000 MNIST train data in mini-batches (most of them of size 128) using the Dataloader that we created in the previous step. Each element of the DataLoader is a tuple `(x, y)` in which `x` represents a 28x28x1 array and `y` a vector that encodes the corresponding label of the image. - -```julia -for (x, y) in data_loader - @assert size(x) == (28, 28, 1, 128) || size(x) == (28, 28, 1, 96) - @assert size(y) == (10, 128) || size(y) == (10, 96) - ... -end -``` - -
- - -Now, we can create a model and train it using the `data_loader` we just created. For more information on building models in Flux, see [Model-Building Basics](https://fluxml.ai/Flux.jl/stable/models/basics/#Model-Building-Basics-1). diff --git a/tutorials/_posts/2021-01-26-mlp.md b/tutorials/_posts/2021-01-26-mlp.md deleted file mode 100644 index da35d18c..00000000 --- a/tutorials/_posts/2021-01-26-mlp.md +++ /dev/null @@ -1,177 +0,0 @@ ---- -title: Simple multi-layer perceptron -author: Adarsh Kumar, Mike J Innes, Andrew Dinhobl, Jerry Ling, natema, Zhang Shitian, Liliana Badillo, Dhairya Gandhi -layout: blog -tag: Examples from Flux Model Zoo ---- - -In this example, we create a simple [multi-layer perceptron](https://en.wikipedia.org/wiki/Multilayer_perceptron#:~:text=A%20multilayer%20perceptron%20(MLP)%20is,artificial%20neural%20network%20(ANN).&text=An%20MLP%20consists%20of%20at,uses%20a%20nonlinear%20activation%20function.) (MLP) that classifies handwritten digits using the MNIST dataset. A MLP consists of at least *three layers* of stacked perceptrons: Input, hidden, and output. Each neuron of an MLP has parameters (weights and bias) and uses an [activation function](https://en.wikipedia.org/wiki/Activation_function) to compute its output. - -To run this example, we need the following packages: - -```julia -using Flux, Statistics -using Flux.Data: DataLoader -using Flux: onehotbatch, onecold, logitcrossentropy, throttle, @epochs -using Base.Iterators: repeated -using Parameters: @with_kw -using CUDA -using MLDatasets -if has_cuda() # Check if CUDA is available - @info "CUDA is on" - CUDA.allowscalar(false) -end -``` -
- -We set default values for learning rate, batch size, epochs, and the usage of a GPU (if available) for our model: - -```julia -@with_kw mutable struct Args - η::Float64 = 3e-4 # learning rate - batchsize::Int = 1024 # batch size - epochs::Int = 10 # number of epochs - device::Function = gpu # set as gpu, if gpu available -end -``` - -
- -If a GPU is available on our local system, then Flux uses it for computing the loss and updating the weights and biases when training our model. - -## Data - -We create the function `getdata` to load the MNIST train and test data sets from [MLDatasets](https://juliaml.github.io/MLDatasets.jl/latest/) and prepare them for the training process. In addition, we set mini-batches of the data sets by loading them onto a [DataLoader](https://fluxml.ai/Flux.jl/stable/data/dataloader/#Flux.Data.DataLoader) object. - -```julia -function getdata(args) - ENV["DATADEPS_ALWAYS_ACCEPT"] = "true" - - # Loading Dataset - xtrain, ytrain = MLDatasets.MNIST.traindata(Float32) - xtest, ytest = MLDatasets.MNIST.testdata(Float32) - - # Reshape Data in order to flatten each image into a linear array - xtrain = Flux.flatten(xtrain) - xtest = Flux.flatten(xtest) - - # One-hot-encode the labels - ytrain, ytest = onehotbatch(ytrain, 0:9), onehotbatch(ytest, 0:9) - - # Batching - train_data = DataLoader((xtrain, ytrain), batchsize=args.batchsize, shuffle=true) - test_data = DataLoader((xtest, ytest), batchsize=args.batchsize) - - return train_data, test_data -end -``` - -
- -`getdata` performs the following steps: - -* **Loads MNIST data set:** Loads the train and test set tensors. The shape of train data is `28x28x60000` and test data is `28X28X10000`. -* **Reshapes the train and test data:** Uses the [flatten](https://fluxml.ai/Flux.jl/stable/models/layers/#Flux.flatten) function to reshape the train data set into a `784x60000` array and test data set into a `784x10000`. Notice that we reshape the data so that we can pass these as arguments for the input layer of our model (a simple MLP expects a vector as an input). -* **One-hot encodes the train and test labels:** Creates a batch of one-hot vectors so we can pass the labels of the data as arguments for the loss function. For this example, we use the [logitcrossentropy](https://fluxml.ai/Flux.jl/stable/models/losses/#Flux.Losses.logitcrossentropy) function and it expects data to be one-hot encoded. -* **Creates batches of data:** Creates two DataLoader objects (train and test) that handle data mini-batches of size `1024 ` (as defined above). We create these two objects so that we can pass the entire data set through the loss function at once when training our model. Also, it shuffles the data points during each iteration (`shuffle=true`). - -## Model - -As we mentioned above, a MLP consist of *three* layers that are fully connected. For this example, we define out model with the following layers and dimensions: - -* **Input:** It has `784` perceptrons (the MNIST image size is `28x28`). We flatten the train and test data so that we can pass them as arguments to this layer. -* **Hidden:** It has `32` perceptrons that use the [relu](https://fluxml.ai/Flux.jl/stable/models/nnlib/#NNlib.relu) activation function. -* **Output:** It has `10` perceptrons that output the model's prediction or probability that a digit is 0 to 9. - - -We define our model with the `build_model` function: - -```julia -function build_model(; imgsize=(28,28,1), nclasses=10) - return Chain( - Dense(prod(imgsize), 32, relu), - Dense(32, nclasses)) -end -``` - -
- -Note that we use the functions [Dense](https://fluxml.ai/Flux.jl/stable/models/layers/#Flux.Dense) so that our model is *densely* (or fully) connected and [Chain](https://fluxml.ai/Flux.jl/stable/models/layers/#Flux.Chain) to chain the computation of the three layers. - -## Loss functions - -Now, we define the loss function `loss_all`. It expects a DataLoader object and the `model` function we defined aboved as arguments. Notice that this function iterates through the `dataloader` object in mini-batches and uses the function [logitcrossentropy](https://fluxml.ai/Flux.jl/stable/models/losses/#Flux.Losses.logitcrossentropy) to compute the difference between the predicted and actual values. - -```julia -function loss_all(dataloader, model) - l = 0f0 - for (x,y) in dataloader - l += logitcrossentropy(model(x), y) - end - l/length(dataloader) -end -``` - -
- -In addition, we define the function (`accuracy`) to report the accuracy of our model during the training process. To compute the accuray, we need to decode the output of our model using the [onecold](https://fluxml.ai/Flux.jl/stable/data/onehot/#Flux.onecold) function. - -```julia -function accuracy(data_loader, model) - acc = 0 - for (x,y) in data_loader - acc += sum(onecold(cpu(model(x))) .== onecold(cpu(y)))*1 / size(x,2) - end - acc/length(data_loader) -end -``` -
- - -## Train our model - -Finally, we create the `train` function that calls the functions we defined and trains the model. - -```julia -function train(; kws...) - # Initializing Model parameters - args = Args(; kws...) - - # Load Data - train_data,test_data = getdata(args) - - # Construct model - m = build_model() - train_data = args.device.(train_data) - test_data = args.device.(test_data) - m = args.device(m) - loss(x,y) = logitcrossentropy(m(x), y) - - ## Training - evalcb = () -> @show(loss_all(train_data, m)) - opt = ADAM(args.η) - - @epochs args.epochs Flux.train!(loss, params(m), train_data, opt, cb = evalcb) - - @show accuracy(train_data, m) - - @show accuracy(test_data, m) -end -``` - -
- -`train` performs the following steps: - -* **Initializes the model parameters:** Creates the `args` object that contains the defult values for training our model. -* **Loads the train and test data:** Calls the function `getdata` we defined above. -* **Constructs the model:** Builds the model and loads the train and test data sets, and our model onto the GPU (if available). -* **Trains the model:** Defines the *callback* function `evalcb` to show the value of the `loss_all` function during the training process. Then, it sets [ADAM](https://fluxml.ai/Flux.jl/stable/training/optimisers/#Flux.Optimise.ADAM) as the optimiser for training out model. Finally, it runs the training process with the macro `@epochs` for `10` epochs (as defined in the `args` object) and shows the `accuracy` value for the train and test data. - - -To see the full version of this example, see [Simple multi-layer perceptron - model-zoo](https://github.com/FluxML/model-zoo/blob/master/vision/mlp_mnist/mlp_mnist.jl). - -## Resources - -* [3Blue1Brown Neural networks videos](https://www.youtube.com/watch?v=aircAruvnKk&list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi). -* [Neural Networks and Deep Learning](http://neuralnetworksanddeeplearning.com/). diff --git a/tutorials/_posts/2021-02-07-convnet.md b/tutorials/_posts/2021-02-07-convnet.md deleted file mode 100644 index 1c956daf..00000000 --- a/tutorials/_posts/2021-02-07-convnet.md +++ /dev/null @@ -1,272 +0,0 @@ ---- -title: Simple ConvNet -author: Elliot Saba, Adarsh Kumar, Mike J Innes, Dhairya Gandhi, Sudhanshu Agrawal, Sambit Kumar Dash, fps.io, Carlo Lucibello, Andrew Dinhobl, Liliana Badillo -layout: blog -tag: Computer vision ---- - -In this tutorial, we build a simple Convolutional Neural Network (ConvNet) to classify the MNIST dataset. This model has a simple architecture with three feature detection layers (Conv -> ReLU -> MaxPool) followed by a final dense layer that classifies MNIST handwritten digits. Note that this model, while simple, should hit around 99% test accuracy after training for approximately 20 epochs. - -This example writes out the saved model to the file `mnist_conv.bson`. Also, it demonstrates basic model construction, training, saving, conditional early-exit, and learning rate scheduling. - -To run this example, we need the following packages: - -```julia -using Flux, MLDatasets, Statistics -using Flux: onehotbatch, onecold, logitcrossentropy -using MLDatasets: MNIST -using Base.Iterators: partition -using Printf, BSON -using Parameters: @with_kw -using CUDA -CUDA.allowscalar(false) -``` -
- -We set default values for learning rate, batch size, number of epochs, and path for saving the file `mnist_conv.bson`: - -```julia -@with_kw mutable struct Args - lr::Float64 = 3e-3 - epochs::Int = 20 - batch_size = 128 - savepath::String = "./" -end -``` -
- -To train our model, we need to bundle images together with their labels and group them into mini-batches (makes the training process faster). We define the function `make_minibatch` that takes as inputs the images (`X`) and their labels (`Y`) as well as the indices for the mini-batches (`idx`): - -```julia -function make_minibatch(X, Y, idxs) - X_batch = Array{Float32}(undef, size(X)[1:end-1]..., 1, length(idxs)) - for i in 1:length(idxs) - X_batch[:, :, :, i] = Float32.(X[:,:,idxs[i]]) - end - Y_batch = onehotbatch(Y[idxs], 0:9) - return (X_batch, Y_batch) -end -``` -
- -`make_minibatch` takes the following steps: - -* Creates the `X_batch` array of size `28x28x1x128` to store the mini-batches. -* Stores the mini-batches in `X_batch`. -* One hot encodes the labels of the images. -* Stores the labels in `Y_batch`. - - - - `get_processed_data` loads the train and test data from `Flux.Data.MNIST`. First, it loads the images and labels of the train data set, and creates an array that contains the indices of the train images that correspond to each mini-batch (of size `args.batch_size`). Then, it calls the `make_minibatch` function to create all of the train mini-batches. Finally, it loads the test images and creates one mini-batch that contains them all. - -```julia -function get_processed_data(args) - # Load labels and images - train_imgs, train_labels = MNIST.traindata() - mb_idxs = partition(1:length(train_labels), args.batch_size) - train_set = [make_minibatch(train_imgs, train_labels, i) for i in mb_idxs] - - # Prepare test set as one giant minibatch: - test_imgs, test_labels = MNIST.testdata() - test_set = make_minibatch(test_imgs, test_labels, 1:length(test_labels)) - - return train_set, test_set - -end -``` -
- - -Now, we define the `build_model` function that creates a ConvNet model which is composed of *three* convolution layers (feature detection) and *one* classification layer. The input layer size is `28x28`. The images are grayscale, which means there is only *one* channel (compared to 3 for RGB) in every data point. Combined together, the convolutional layer structure would look like `Conv(kernel, input_channels => output_channels, ...)`. Each convolution layer reduces the size of the image by applying the Rectified Linear unit (ReLU) and MaxPool operations. -On the other hand, the classification layer outputs a vector of 10 dimensions (a dense layer), that is, the number of classes that the model will be able to predict. - - -```julia -function build_model(args; imgsize = (28,28,1), nclasses = 10) - cnn_output_size = Int.(floor.([imgsize[1]/8,imgsize[2]/8,32])) - - return Chain( - # First convolution, operating upon a 28x28 image - Conv((3, 3), imgsize[3]=>16, pad=(1,1), relu), - MaxPool((2,2)), - - # Second convolution, operating upon a 14x14 image - Conv((3, 3), 16=>32, pad=(1,1), relu), - MaxPool((2,2)), - - # Third convolution, operating upon a 7x7 image - Conv((3, 3), 32=>32, pad=(1,1), relu), - MaxPool((2,2)), - - # Reshape 3d array into a 2d one using `Flux.flatten`, at this point it should be (3, 3, 32, N) - flatten, - Dense(prod(cnn_output_size), 10)) -end -``` -
- -To chain the layers of a model we use the Flux function [Chain](https://fluxml.ai/Flux.jl/stable/models/layers/#Flux.Chain). It enables us to call the layers in sequence on a given input. Also, we use the function [flatten](https://fluxml.ai/Flux.jl/stable/models/layers/#Flux.flatten) to reshape the output image from the last convolution layer. Finally, we call the [Dense](https://fluxml.ai/Flux.jl/stable/models/layers/#Flux.Dense) function to create the classification layer. - - -Before training our model, we need to define a few functions that will be helpful for the process: - - -* `augment` augments the data by adding gaussian random noise to our image to make it more robust: - - ```julia - augment(x) = x .+ gpu(0.1f0*randn(eltype(x), size(x))) - ``` -
- - -* `anynan` checks whether any element of the params is NaN or not: - - ```julia - anynan(x) = any(y -> any(isnan, y), x) - ``` -
- -* `accuracy` computes the accuracy of our ConvNet: - - ```julia - accuracy(x, y, model) = mean(onecold(cpu(model(x))) .== onecold(cpu(y))) - ``` -
- -Finally, we define the `train` function: - -```julia -function train(; kws...) - args = Args(; kws...) - - @info("Loading data set") - train_set, test_set = get_processed_data(args) - - # Define our model. We will use a simple convolutional architecture with - # three iterations of Conv -> ReLU -> MaxPool, followed by a final Dense layer. - @info("Building model...") - model = build_model(args) - - # Load model and datasets onto GPU, if enabled - train_set = gpu.(train_set) - test_set = gpu.(test_set) - model = gpu(model) - - # Make sure our model is nicely precompiled before starting our training loop - model(train_set[1][1]) - - # `loss()` calculates the crossentropy loss between our prediction `y_hat` - # (calculated from `model(x)`) and the ground truth `y`. We augment the data - # a bit, adding gaussian random noise to our image to make it more robust. - function loss(x, y) - x̂ = augment(x) - ŷ = model(x̂) - return logitcrossentropy(ŷ, y) - end - - # Train our model with the given training set using the ADAM optimizer and - # printing out performance against the test set as we go. - opt = ADAM(args.lr) - - @info("Beginning training loop...") - best_acc = 0.0 - last_improvement = 0 - for epoch_idx in 1:args.epochs - # Train for a single epoch - Flux.train!(loss, params(model), train_set, opt) - - # Terminate on NaN - if anynan(Flux.params(model)) - @error "NaN params" - break - end - - # Calculate accuracy: - acc = accuracy(test_set..., model) - - @info(@sprintf("[%d]: Test accuracy: %.4f", epoch_idx, acc)) - # If our accuracy is good enough, quit out. - if acc >= 0.999 - @info(" -> Early-exiting: We reached our target accuracy of 99.9%") - break - end - - # If this is the best accuracy we've seen so far, save the model out - if acc >= best_acc - @info(" -> New best accuracy! Saving model out to mnist_conv.bson") - BSON.@save joinpath(args.savepath, "mnist_conv.bson") params=cpu.(params(model)) epoch_idx acc - best_acc = acc - last_improvement = epoch_idx - end - - # If we haven't seen improvement in 5 epochs, drop our learning rate: - if epoch_idx - last_improvement >= 5 && opt.eta > 1e-6 - opt.eta /= 10.0 - @warn(" -> Haven't improved in a while, dropping learning rate to $(opt.eta)!") - - # After dropping learning rate, give it a few epochs to improve - last_improvement = epoch_idx - end - - if epoch_idx - last_improvement >= 10 - @warn(" -> We're calling this converged.") - break - end - end -end -``` -
- -`train` calls the functions we defined above and trains our model. It stops when the model achieves 99% accuracy (early-exiting) or after performing 20 steps. More specifically, it performs the following steps: - - * Loads the MNIST dataset. - * Builds our ConvNet model (as described above). - * Loads the train and test data sets as well as our model onto a GPU (if available). - * Defines a `loss` function that calculates the crossentropy between our prediction and the ground truth. - * Sets the [ADAM optimiser](https://fluxml.ai/Flux.jl/stable/training/optimisers/#Flux.Optimise.ADAM) to train the model with learning rate `args.lr`. - * Runs the training loop. For each step (or epoch), it executes the following: - * Calls `Flux.train!` function to execute one training step. - * If any of the parameters of our model is `NaN`, then the training process is terminated. - * Calculates the model accuracy. - * If the model accuracy is >= 0.999, then early-exiting is executed. - * If the actual accuracy is the best so far, then the model is saved to `mnist_conv.bson`. Also, the new best accuracy and the current epoch is saved. - * If there has not been any improvement for the last 5 epochs, then the learning rate is dropped and the process waits a little longer for the accuracy to improve. - * If the last improvement was more than 10 epochs ago, then the process is terminated. - - -Finally, to test our model we define the `test` function: - -```julia -function test(; kws...) - args = Args(; kws...) - - # Loading the test data - _,test_set = get_processed_data(args) - - # Re-constructing the model with random initial weights - model = build_model(args) - - # Loading the saved parameters - BSON.@load joinpath(args.savepath, "mnist_conv.bson") params - - # Loading parameters onto the model - Flux.loadparams!(model, params) - - test_set = gpu.(test_set) - model = gpu(model) - @show accuracy(test_set...,model) -end -``` -
- -`test` loads the MNIST test data set, reconstructs the model, and loads the saved parameters (in `mnist_conv.bson`) onto it. Finally, it computes our model's predictions for the test set and shows the test accuracy (around 99%). - -To see the full version of this example, see [Simple ConvNets - model-zoo](https://github.com/FluxML/model-zoo/blob/master/vision/conv_mnist/conv_mnist.jl). - -## Resources - -* [Neural Networks in Flux.jl with Huda Nassar (working with the MNIST dataset)](https://youtu.be/Oxi0Pfmskus) -* [Convolutional Neural Networks (CNNs / ConvNets)](https://cs231n.github.io/convolutional-networks/). -* [Convolutional Neural Networks Tutorial in PyTorch](https://adventuresinmachinelearning.com/convolutional-neural-networks-tutorial-in-pytorch/). - diff --git a/tutorials/_posts/2021-10-14-vanilla-gan.md b/tutorials/_posts/2021-10-14-vanilla-gan.md deleted file mode 100644 index 29f7dd6e..00000000 --- a/tutorials/_posts/2021-10-14-vanilla-gan.md +++ /dev/null @@ -1,287 +0,0 @@ ---- -title: Generative Adversarial Networks -author: Ralph Kube -layout: blog -tag: Learning Flux ---- - -This tutorial describes how to implement a vanilla Generative Adversarial -Network using Flux and how train it on the MNIST dataset. It is based on this -[Pytorch tutorial](https://medium.com/ai-society/gans-from-scratch-1-a-deep-introduction-with-code-in-pytorch-and-tensorflow-cb03cdcdba0f). The original GAN [paper](https://arxiv.org/abs/1406.2661) by Goodfellow et al. is a great resource that describes the motivation and theory behind GANs: - -``` -In the proposed adversarial nets framework, the generative model is pitted against an adversary: a -discriminative model that learns to determine whether a sample is from the model distribution or the -data distribution. The generative model can be thought of as analogous to a team of counterfeiters, -trying to produce fake currency and use it without detection, while the discriminative model is -analogous to the police, trying to detect the counterfeit currency. Competition in this game drives -both teams to improve their methods until the counterfeits are indistinguishable from the genuine -articles. -``` - -Let's implement a GAN in Flux. To get started we first import a few useful packages: - - -```julia -using MLDatasets: MNIST -using Flux.Data: DataLoader -using Flux -using CUDA -using Zygote -using UnicodePlots -``` - -To download a package in the Julia REPL, type `]` to enter package mode and then -type `add MLDatasets` or perform this operation with the Pkg module like this - -```julia -> import Pkg -> Pkg.add(MLDatasets) -``` - -While [UnicodePlots]() is not necessary, it can be used to plot generated samples -into the terminal during training. Having direct feedback, instead of looking -at plots in a separate window, use fantastic for debugging. - -
- -Next, let us define values for learning rate, batch size, epochs, and other -hyper-parameters. While we are at it, we also define optimizers for the generator -and discriminator network. More on what these are later. - -```julia - lr_g = 2e-4 # Learning rate of the generator network - lr_d = 2e-4 # Learning rate of the discriminator network - batch_size = 128 # batch size - num_epochs = 1000 # Number of epochs to train for - output_period = 100 # Period length for plots of generator samples - n_features = 28 * 28# Number of pixels in each sample of the MNIST dataset - latent_dim = 100 # Dimension of latent space - opt_dscr = ADAM(lr_d)# Optimizer for the discriminator - opt_gen = ADAM(lr_g) # Optimizer for the generator -``` - -
- -In this tutorial I'm assuming that a CUDA-enabled GPU is available on the -system where the script is running. If this is not the case, simply remove -the `|>gpu` decorators: [piping](https://docs.julialang.org/en/v1/manual/functions/#Function-composition-and-piping). - -## Data loading -The MNIST data set is available from [MLDatasets](https://juliaml.github.io/MLDatasets.jl/latest/). The first time you instantiate it you will be prompted -if you want to download it. You should agree to this. - -GANs can be trained unsupervised. Therefore only keep the images from the training -set and discard the labels. - -After we load the training data we re-scale the data from values in [0:1] -to values in [-1:1]. GANs are notoriously tricky to train and this re-scaling -is a recommended [GAN hack](https://github.com/soumith/ganhacks). The -re-scaled data is used to define a data loader which handles batching -and shuffling the data. - -```julia - # Load the dataset - train_x, _ = MNIST.traindata(Float32); - # This dataset has pixel values ∈ [0:1]. Map these to [-1:1] - train_x = 2f0 * reshape(train_x, 28, 28, 1, :) .- 1f0 |>gpu; - # DataLoader allows to access data batch-wise and handles shuffling. - train_loader = DataLoader(train_x, batchsize=batch_size, shuffle=true); -``` - -
- -## Defining the Networks - - -A vanilla GAN, the discriminator and the generator are both plain, [feed-forward -multilayer perceptrons](https://boostedml.com/2020/04/feedforward-neural-networks-and-multilayer-perceptrons.html). We use leaky rectified linear units [leakyrelu](https://fluxml.ai/Flux.jl/stable/models/nnlib/#NNlib.leakyrelu) to ensure out model is non-linear. - -Here, the coefficient `α` (in the `leakyrelu` below), is set to 0.2. Empirically, -this value allows for good training of the network (based on prior experiments). -It has also been found that Dropout ensures a good generalization of the learned -network, so we will use that below. Dropout is usually active when training a -model and inactive in inference. Flux automatically sets the training mode when -calling the model in a gradient context. As a final non-linearity, we use the -`sigmoid` activation function. - -```julia -discriminator = Chain(Dense(n_features, 1024, x -> leakyrelu(x, 0.2f0)), - Dropout(0.3), - Dense(1024, 512, x -> leakyrelu(x, 0.2f0)), - Dropout(0.3), - Dense(512, 256, x -> leakyrelu(x, 0.2f0)), - Dropout(0.3), - Dense(256, 1, sigmoid)) |> gpu -``` - -Let's define the generator in a similar fashion. This network maps a latent -variable (a variable that is not directly observed but instead inferred) to the -image space and we set the input and output dimension accordingly. A `tanh` squashes -the output of the final layer to values in [-1:1], the same range that we squashed -the training data onto. - -```julia -generator = Chain(Dense(latent_dim, 256, x -> leakyrelu(x, 0.2f0)), - Dense(256, 512, x -> leakyrelu(x, 0.2f0)), - Dense(512, 1024, x -> leakyrelu(x, 0.2f0)), - Dense(1024, n_features, tanh)) |> gpu -``` - - - -## Training functions for the networks - -To train the discriminator, we present it with real data from the MNIST -data set and with fake data and reward it by predicting the correct labels for -each sample. The correct labels are of course 1 for in-distribution data -and 0 for out-of-distribution data coming from the generator. -[Binary cross entropy](https://fluxml.ai/Flux.jl/stable/models/losses/#Flux.Losses.binarycrossentropy) -is the loss function of choice. While the Flux documentation suggests to use -[Logit binary cross entropy](https://fluxml.ai/Flux.jl/stable/models/losses/#Flux.Losses.logitcrossentropy), -the GAN seems to be difficult to train with this loss function. -This function returns the discriminator loss for logging purposes. We can -calculate the loss in the same call as evaluating the pullback and resort -to getting the pullback directly from Zygote instead of calling -`Flux.train!` on the model. To calculate the gradients of the loss -function with respect to the parameters of the discriminator we then only have to -evaluate the pullback with a seed gradient of 1.0. These gradients are used -to update the model parameters - - -```julia -function train_dscr!(discriminator, real_data, fake_data) - this_batch = size(real_data)[end] # Number of samples in the batch - # Concatenate real and fake data into one big vector - all_data = hcat(real_data, fake_data) - - # Target vector for predictions: 1 for real data, 0 for fake data. - all_target = [ones(eltype(real_data), 1, this_batch) zeros(eltype(fake_data), 1, this_batch)] |> gpu; - - ps = Flux.params(discriminator) - loss, pullback = Zygote.pullback(ps) do - preds = discriminator(all_data) - loss = Flux.Losses.binarycrossentropy(preds, all_target) - end - # To get the gradients we evaluate the pullback with 1.0 as a seed gradient. - grads = pullback(1f0) - - # Update the parameters of the discriminator with the gradients we calculated above - Flux.update!(opt_dscr, Flux.params(discriminator), grads) - - return loss -end -``` - - -Now we need to define a function to train the generator network. The job of the -generator is to fool the discriminator so we reward the generator when the discriminator -predicts a high probability for its samples to be real data. In the training function -we first need to sample some noise, i.e. normally distributed data. This has -to be done outside the pullback since we don't want to get the gradients with -respect to the noise, but to the generator parameters. Inside the pullback we need -to first apply the generator to the noise since we will take the gradient with respect -to the parameters of the generator. We also need to call the discriminator in order -to evaluate the loss function inside the pullback. Here we need to remember to deactivate -the dropout layers of the discriminator. We do this by setting the discriminator into -test mode before the pullback. Immediately after the pullback we set it back into training -mode. Then we evaluate the pullback, call it with a seed gradient of 1.0 as above, update the -parameters of the generator network and return the loss. - - -```julia -function train_gen!(discriminator, generator) - # Sample noise - noise = randn(latent_dim, batch_size) |> gpu; - - # Define parameters and get the pullback - ps = Flux.params(generator) - # Set discriminator into test mode to disable dropout layers - testmode!(discriminator) - # Evaluate the loss function while calculating the pullback. We get the loss for free - loss, back = Zygote.pullback(ps) do - preds = discriminator(generator(noise)); - loss = Flux.Losses.binarycrossentropy(preds, 1.) - end - # Evaluate the pullback with a seed-gradient of 1.0 to get the gradients for - # the parameters of the generator - grads = back(1.0f0) - Flux.update!(opt_gen, Flux.params(generator), grads) - # Set discriminator back into automatic mode - trainmode!(discriminator, mode=:auto) - return loss -end -``` - -## Training -Now we are ready to train the GAN. In the training loop we keep track -of the per-sample loss of the generator and the discriminator, where -we use the batch loss returned by the two training functions defined above. -In each epoch we iterate over the mini-batches given by the data loader. -Only minimal data processing needs to be done before the training functions -can be called. - -```julia -lossvec_gen = zeros(num_epochs) -lossvec_dscr = zeros(num_epochs) - -for n in 1:num_epochs - loss_sum_gen = 0.0f0 - loss_sum_dscr = 0.0f0 - - for x in train_loader - # - Flatten the images from 28x28xbatchsize to 784xbatchsize - real_data = flatten(x); - - # Train the discriminator - noise = randn(latent_dim, size(x)[end]) |> gpu - fake_data = generator(noise) - loss_dscr = train_dscr!(discriminator, real_data, fake_data) - loss_sum_dscr += loss_dscr - - # Train the generator - loss_gen = train_gen!(discriminator, generator) - loss_sum_gen += loss_gen - end - - # Add the per-sample loss of the generator and discriminator - lossvec_gen[n] = loss_sum_gen / size(train_x)[end] - lossvec_dscr[n] = loss_sum_dscr / size(train_x)[end] - - if n % output_period == 0 - @show n - noise = randn(latent_dim, 4) |> gpu; - fake_data = reshape(generator(noise), 28, 4*28); - p = heatmap(fake_data, colormap=:inferno) - print(p) - end -end -``` - -For the hyper-parameters shown in this example, the generator produces useful -images after about 1000 epochs. And after about 5000 epochs the result look -indistinguishable from real MNIST data. Using a Nvidia V100 GPU on a 2.7 -GHz Power9 CPU with 32 hardware threads, training 100 epochs takes about 80 -seconds when using the GPU. The GPU utilization is between 30 and 40%. -To observe the network more frequently during training you can for example set -`output_period=20`. Training the GAN using the CPU takes about 10 minutes -per epoch and is not recommended. - -## Results - -Below you can see what some of the images output may look like after different numbers of epochs. - -Screen Shot 2021-10-22 at 6 51 00 AM - -Screen Shot 2021-10-22 at 6 51 14 AM - -Screen Shot 2021-10-22 at 6 51 35 AM - -Screen Shot 2021-10-22 at 6 51 46 AM - -## Resources - -* [A collection of GANs in Flux](https://github.com/AdarshKumar712/FluxGAN) -* [Wikipedia](https://en.wikipedia.org/wiki/Generative_adversarial_network) -* [GAN hacks](https://github.com/soumith/ganhacks) - diff --git a/tutorials/_posts/2021-10-8-dcgan-mnist.md b/tutorials/_posts/2021-10-8-dcgan-mnist.md deleted file mode 100644 index 2bb58e9b..00000000 --- a/tutorials/_posts/2021-10-8-dcgan-mnist.md +++ /dev/null @@ -1,367 +0,0 @@ ---- -title: Deep Convolutional Generative Adversarial Network(DCGAN) -author: Deeptendu Santra -layout: blog -tag: Generative Adversarial Neural Networks ---- - -This is a beginner level tutorial for generating images of handwritten digits using a [Deep Convolutional Generative Adversarial Network](https://arxiv.org/pdf/1511.06434.pdf) inspired by the [TensorFlow tutorial on DCGAN](https://www.tensorflow.org/tutorials/generative/dcgan). - -## What are GANs? -[Generative Adversarial Neural Networks or simply GANs](https://arxiv.org/abs/1406.2661) introduced by Goodfellow et al. is one of the most innovative ideas in modern-day machine learning. GANs are used extensively in the field of image and audio processing to generate high-quality synthetic data that can easily be passed off as real data. - -A GAN is composed of two sub-models - the **generator** and the **discriminator** acting against one another. The generator can be considered as an artist who draws (generates) new images that look real, whereas the discriminator is a critic who learns to tell real images apart from fakes. - - - -The GAN starts with a generator and discriminator which have very little or no idea about the underlying data. During training, the generator progressively becomes better at creating images that look real, while the discriminator becomes better at telling them apart. The process reaches equilibrium when the discriminator can no longer distinguish real images from fakes. - - - -[[source]](https://www.tensorflow.org/tutorials/generative/dcgan) - -This tutorial demonstrates the process of training a DC-GAN on the [MNIST dataset for handwritten digits](http://yann.lecun.com/exdb/mnist/). The following animation shows a series of images produced by the generator as it was trained for 25 epochs. The images begin as random noise, but over time, the images become increasingly similar to handwritten numbers. - -

-

- -

- -## Setup - -We need to install some Julia packages before we start with our implementation of DCGAN. - -```julia -using Pkg - -# Activate a new project environment in the current directory -Pkg.activate(".") -# Add the required packages to the environment -Pkg.add(["Images", "Flux", "MLDatasets", "CUDA", "Parameters"]) -``` -*Note: Depending on your internet speed, it may take a few minutes for the packages install.* - -
-After installing the libraries, load the required packages and functions: -```julia -using Base.Iterators: partition -using Printf -using Statistics -using Random -using Images -using Parameters: @with_kw -using Flux -using Flux.Data: DataLoader -using Flux.Optimise: update! -using Flux.Losses: logitbinarycrossentropy -using MLDatasets: MNIST -using CUDA -``` -
-Now we set default values for the learning rates, batch size, epochs, the usage of a GPU (if available) and other hyperparameters for our model. - -```julia -@with_kw struct HyperParams - batch_size::Int = 128 - latent_dim::Int = 100 - epochs::Int = 25 - verbose_freq::Int = 1000 - output_dim::Int = 5 - disc_lr::Float64 = 0.0002 - gen_lr::Float64 = 0.0002 - device::Function = gpu -end -``` - -## Loading the data -As mentioned before, we will be using the MNIST dataset for handwritten digits. So we begin with a simple function for loading and pre-processing the MNIST images: -```julia -function load_MNIST_images(hparams) - images = MNIST.traintensor(Float32) - - # Normalize the images to (-1, 1) - normalized_images = @. 2f0 * images - 1f0 - image_tensor = reshape(normalized_images, 28, 28, 1, :) - - # Create a dataloader that iterates over mini-batches of the image tensor - dataloader = DataLoader(image_tensor, batchsize=hparams.batch_size, shuffle=true) - - return dataloader -end -``` -To learn more about loading images in Flux, you can check out [this tutorial](https://fluxml.ai/tutorials/2021/01/21/data-loader.html). - -*Note: The data returned from the dataloader is loaded is on the CPU. To train on the GPU, we need to transfer the data to the GPU beforehand.* - -## Create the models - - -### The generator - -Our generator, a.k.a. the artist, is a neural network that maps low dimensional data to a high dimensional form. - -- This low dimensional data (seed) is generally a vector of random values sampled from a normal distribution. -- The high dimensional data is the generated image. - -The `Dense` layer is used for taking the seed as an input which is upsampled several times using the [ConvTranspose](https://fluxml.ai/Flux.jl/stable/models/layers/#Flux.ConvTranspose) layer until we reach the desired output size (in our case, 28x28x1). Furthermore, after each `ConvTranspose` layer, we apply the Batch Normalization to stabilize the learning process. - -We will be using the [relu](https://fluxml.ai/Flux.jl/stable/models/nnlib/#NNlib.relu) activation function for each layer except the output layer, where we use `tanh` activation. - -We will also apply the weight initialization method mentioned in the original DCGAN paper. - -```julia -# Function for intializing the model weights with values -# sampled from a Gaussian distribution with μ=0 and σ=0.02 -dcgan_init(shape...) = randn(Float32, shape) * 0.02f0 -``` -
- -```julia -function Generator(latent_dim) - Chain( - Dense(latent_dim, 7*7*256, bias=false), - BatchNorm(7*7*256, relu), - - x -> reshape(x, 7, 7, 256, :), - - ConvTranspose((5, 5), 256 => 128; stride = 1, pad = 2, init = dcgan_init, bias=false), - BatchNorm(128, relu), - - ConvTranspose((4, 4), 128 => 64; stride = 2, pad = 1, init = dcgan_init, bias=false), - BatchNorm(64, relu), - - # The tanh activation ensures that output is in range of (-1, 1) - ConvTranspose((4, 4), 64 => 1, tanh; stride = 2, pad = 1, init = dcgan_init, bias=false), - ) -end -``` -
-Time for a small test!! We create a dummy generator and feed a random vector as a seed to the generator. If our generator is initialized correctly it will return an array of size (28, 28, 1, `batch_size`). The `@assert` macro in Julia will raise an exception for the wrong output size. - -```julia -# Create a dummy generator of latent dim 100 -generator = Generator(100) -noise = randn(Float32, 100, 3) # The last axis is the batch size - -# Feed the random noise to the generator -gen_image = generator(noise) -@assert size(gen_image) == (28, 28, 1, 3) -``` - -
-Our generator model is yet to learn the correct weights, so it does not produce a recognizable image for now. To train our poor generator we need its equal rival, the *discriminator*. -
-
- -### Discriminator - -The Discriminator is a simple CNN based image classifier. The `Conv` layer a is used with a [leakyrelu](https://fluxml.ai/Flux.jl/stable/models/nnlib/#NNlib.leakyrelu) activation function. - -```julia -function Discriminator() - Chain( - Conv((4, 4), 1 => 64; stride = 2, pad = 1, init = dcgan_init), - x->leakyrelu.(x, 0.2f0), - Dropout(0.3), - - Conv((4, 4), 64 => 128; stride = 2, pad = 1, init = dcgan_init), - x->leakyrelu.(x, 0.2f0), - Dropout(0.3), - - # The output is now of the shape (7, 7, 128, batch_size) - flatten, - Dense(7 * 7 * 128, 1) - ) -end -``` -For a more detailed implementation of a CNN-based image classifier, you can refer to [this tutorial](https://fluxml.ai/tutorials/2021/02/07/convnet.html). - -Now let us check if our discriminator is working: - -```julia -# Dummy Discriminator -discriminator = Discriminator() -# We pass the generated image to the discriminator -logits = discriminator(gen_image) -@assert size(logits) == (1, 3) -``` -
-Just like our dummy generator, the untrained discriminator has no idea about what is a real or fake image. It needs to be trained alongside the generator to output positive values for real images, and negative values for fake images. - -## Loss functions for GAN - -In a GAN problem, there are only two labels involved: fake and real. So Binary CrossEntropy is an easy choice for a preliminary loss function. - -But even if Flux's `binarycrossentropy` does the job for us, due to numerical stability it is always preferred to compute cross-entropy using logits. Flux provides [logitbinarycrossentropy](https://fluxml.ai/Flux.jl/stable/models/losses/#Flux.Losses.logitbinarycrossentropy) specifically for this purpose. Mathematically it is equivalent to `binarycrossentropy(σ(ŷ), y, kwargs...).` -
- -### Discriminator Loss - -The discriminator loss quantifies how well the discriminator can distinguish real images from fakes. It compares - -- discriminator's predictions on real images to an array of 1s, and -- discriminator's predictions on fake (generated) images to an array of 0s. - -These two losses are summed together to give a scalar loss. So we can write the loss function of the discriminator as: - -```julia -function discriminator_loss(real_output, fake_output) - real_loss = logitbinarycrossentropy(real_output, 1) - fake_loss = logitbinarycrossentropy(fake_output, 0) - return real_loss + fake_loss -end -``` -
-### Generator Loss - -The generator's loss quantifies how well it was able to trick the discriminator. Intuitively, if the generator is performing well, the discriminator will classify the fake images as real (or 1). - -```julia -generator_loss(fake_output) = logitbinarycrossentropy(fake_output, 1) -``` -
-We also need optimizers for our network. Why you may ask? Read more [here](https://towardsdatascience.com/overview-of-various-optimizers-in-neural-networks-17c1be2df6d5). For both the generator and discriminator, we will use the [ADAM optimizer](https://fluxml.ai/Flux.jl/stable/training/optimisers/#Flux.Optimise.ADAM). - -## Utility functions - -The output of the generator ranges from (-1, 1), so it needs to be de-normalized before we can display it as an image. To make things a bit easier, we define a function to visualize the output of the generator as a grid of images. - -```julia -function create_output_image(gen, fixed_noise, hparams) - fake_images = cpu(gen.(fixed_noise)) - image_array = reduce(vcat, reduce.(hcat, partition(fake_images, hparams.output_dim))) - image_array = permutedims(dropdims(image_array; dims=(3, 4)), (2, 1)) - image_array = @. Gray(image_array + 1f0) / 2f0 - return image_array -end -``` - -## Training - -For the sake of simplifying our training problem, we will divide the generator and discriminator training into two separate functions. - -```julia -function train_discriminator!(gen, disc, real_img, fake_img, opt, ps, hparams) - - disc_loss, grads = Flux.withgradient(ps) do - discriminator_loss(disc(real_img), disc(fake_img)) - end - - # Update the discriminator parameters - update!(opt, ps, grads) - return disc_loss -end -``` -
-We define a similar function for the generator. - -```julia -function train_generator!(gen, disc, fake_img, opt, ps, hparams) - - gen_loss, grads = Flux.withgradient(ps) do - generator_loss(disc(fake_img)) - end - - update!(opt, ps, grads) - return gen_loss -end -``` -
- -Now that we have defined every function we need, we integrate everything into a single `train` function where we first set up all the models and optimizers and then train the GAN for a specified number of epochs. - -```julia -function train(hparams) - - dev = hparams.device - # Check if CUDA is actually present - if hparams.device == gpu - if !CUDA.has_cuda() - dev = cpu - @warn "No gpu found, falling back to CPU" - end - end - - # Load the normalized MNIST images - dataloader = load_MNIST_images(hparams) - - # Initialize the models and pass them to correct device - disc = Discriminator() |> dev - gen = Generator(hparams.latent_dim) |> dev - - # Collect the generator and discriminator parameters - disc_ps = params(disc) - gen_ps = params(gen) - - # Initialize the ADAM optimizers for both the sub-models - # with respective learning rates - disc_opt = ADAM(hparams.disc_lr) - gen_opt = ADAM(hparams.gen_lr) - - # Create a batch of fixed noise for visualizing the training of generator over time - fixed_noise = [randn(Float32, hparams.latent_dim, 1) |> dev for _=1:hparams.output_dim^2] - - # Training loop - train_steps = 0 - for ep in 1:hparams.epochs - @info "Epoch $ep" - for real_img in dataloader - - # Transfer the data to the GPU - real_img = real_img |> dev - - # Create a random noise - noise = randn!(similar(real_img, (hparams.latent_dim, hparams.batch_size))) - # Pass the noise to the generator to create a fake imagae - fake_img = gen(noise) - - # Update discriminator and generator - loss_disc = train_discriminator!(gen, disc, real_img, fake_img, disc_opt, disc_ps, hparams) - loss_gen = train_generator!(gen, disc, fake_img, gen_opt, gen_ps, hparams) - - if train_steps % hparams.verbose_freq == 0 - @info("Train step $(train_steps), Discriminator loss = $(loss_disc), Generator loss = $(loss_gen)") - # Save generated fake image - output_image = create_output_image(gen, fixed_noise, hparams) - save(@sprintf("output/dcgan_steps_%06d.png", train_steps), output_image) - end - train_steps += 1 - end - end - - output_image = create_output_image(gen, fixed_noise, hparams) - save(@sprintf("output/dcgan_steps_%06d.png", train_steps), output_image) - - return nothing -end -``` -
-Now we finally get to train the GAN: - -```julia -# Define the hyper-parameters (here, we go with the default ones) -hparams = HyperParams() -train(hparams) -``` - -## Output -The generated images are stored inside the `output` folder. To visualize the output of the generator over time, we create a gif of the generated images. - -```julia -folder = "output" -# Get the image filenames from the folder -img_paths = readdir(folder, join=true) -# Load all the images as an array -images = load.(img_paths) -# Join all the images in the array to create a matrix of images -gif_mat = cat(images..., dims=3) -save("./output.gif", gif_mat) -``` -
-

- -

- -## Resources & References -- [The DCGAN implementation in Model Zoo.](http=s://github.com/FluxML/model-zoo/blob/master/vision/dcgan_mnist/dcgan_mnist.jl) -