This is a t-SNE representation of a 4-dimensional array of (random) colours. The t-SNE is computed by a javascript worker, using science.ai's implementation. For eye-candy the end result is displayed as a Voronoi diagram.
Forked from Fil's block: t-SNE worker
Built with blockbuilder.org, so double-thank-you to @enjalot.
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
<script>
const width = 400,
x = d3.scaleLinear()
.domain([-1, 1])
.range([0, width]),
area = d3.area()
.x((d,i) => i)
.y0(width+90)
.y1((d,i) => width + 90 - parseInt(3 * d||0));
d3.queue()
.defer(d3.text, 'tsne.min.js')
.defer(d3.text, 'worker.js')
.await(function (err, t, w) {
const worker = new Worker(window.URL.createObjectURL(new Blob([t + w], {
type: "text/javascript"
})));
const data = d3.range(200).map(d => [Math.random(), Math.random(), Math.random(), Math.random()]);
const svg = d3.select('body').append('svg')
.attr('width', width + 100)
.attr('height', width + 100);
const polygons = svg.selectAll('path')
.data(data)
.enter()
.append('path')
.attr('d', null)
.attr('stroke-width', 0.3)
.attr('fill', d => d3.rgb(d[0] * 256, d[1] * 256, d[2] * 256))
.attr('stroke', d => d3.rgb(d[0] * 256, d[1] * 256, d[2] * 256))
.attr('opacity', d => 0.5 + 0.5 * d[3]);
const cost = svg.append('path')
.attr('fill', '#aaa');
let pos = data.map(d => [Math.random() - 0.5, Math.random() - 0.5]);
let costs = [];
const voronoi = d3.voronoi().extent([[-1, -1], [1, 1]]);
const timer = d3.timer(function () {
let p = voronoi.polygons(pos);
polygons.attr('d', (d, i) => p[i] ? "M" + (p[i]).map(d => d.map(x)).join("L") + "Z" : null);
cost.attr('d', area(costs));
});
worker.onmessage = function (e) {
if (e.data.pos) pos = e.data.pos;
if (e.data.iterations) {
costs[e.data.iterations] = e.data.cost;
if (e.data.iterations >= 399) timer.stop();
}
};
worker.postMessage({
nIter: 400,
// dim: 2,
perplexity: 20.0,
// earlyExaggeration: 4.0,
// learningRate: 100.0,
// metric: 'euclidean',
data: data
});
});
</script>
</body>
https://d3js.org/d3.v4.min.js