Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compile/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<file name="convnet_layers_nonlinearities.js" />
<file name="convnet_layers_dropout.js" />
<file name="convnet_layers_normalization.js" />
<file name="convnet_layers_fourier_feature.js" />
<file name="convnet_net.js" />
<file name="convnet_trainers.js" />
<file name="convnet_magicnet.js" />
Expand Down
7 changes: 7 additions & 0 deletions demo/css/jquery-ui.min.css

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions demo/image_regression.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
<head>
<title>ConvNetJS demo: Image Painting</title>
<link href='http://fonts.googleapis.com/css?family=Cabin' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="css/style.css">
<link type="text/css" rel="stylesheet" href="css/style.css">

<link rel="stylesheet" href="css/jquery-ui.min.css">
<script src="js/jquery-1.8.3.min.js"></script>
<script src="js/jquery-ui.min.js"></script>
<link type="text/css" rel="stylesheet" href="css/jquery-ui.min.css">
<script src="./js/jquery-1.8.3.min.js"></script>
<script src="./js/jquery-ui.min.js"></script>

<script src="../build/convnet.js"></script>
<script src="js/image_regression.js"></script>
Expand Down Expand Up @@ -41,7 +41,7 @@ <h1><a href="http://cs.stanford.edu/people/karpathy/convnetjs/">ConvnetJS</a> de
Note that the entire ConvNetJS definition is shown in textbox below and it gets eval()'d to create the network, so feel free to fiddle with the parameters and hit "reload". I found that, empirically and interestingly, deeper networks tend to work much better on this task given a fixed parameter budget.
</p>

<p>Report questions/bugs/suggestions to <a href="https://twitter.com/karpathy">@karpathy</a>.</p>
<p>Report questions/bugs/suggestions to <a href="https://zainraza.me">@Zain</a>.</p> Shout-out <a href="https://twitter.com/karpathy">@karpathy</a> for initially creating the ConvNetJS library :)

<textarea id="layerdef" style="width:100%; height:250px;"></textarea>
<br /><br />
Expand Down
3 changes: 2 additions & 1 deletion demo/js/image_regression.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var layer_defs, net, trainer;
// create neural net
var t = "layer_defs = [];\n\
layer_defs.push({type:'input', out_sx:1, out_sy:1, out_depth:2}); // 2 inputs: x, y \n\
layer_defs.push({type:'fourier_feature'}); \n\
layer_defs.push({type:'fc', num_neurons:20, activation:'relu'});\n\
layer_defs.push({type:'fc', num_neurons:20, activation:'relu'});\n\
layer_defs.push({type:'fc', num_neurons:20, activation:'relu'});\n\
Expand Down Expand Up @@ -69,7 +70,7 @@ function draw() {
var W = nn_canvas.width;
var H = nn_canvas.height;

var g = nn_ctx.getImageData(0, 0, W, H);
var g = nn_ctx.getImageData(0, 0, W, H, {willReadFrequently: true});
var v = new convnetjs.Vol(1, 1, 2);
for(var x=0;x<W;x++) {
v.w[0] = (x-W/2)/W;
Expand Down
6 changes: 6 additions & 0 deletions demo/js/jquery-ui.min.js

Large diffs are not rendered by default.

104 changes: 104 additions & 0 deletions src/convnet_layers_fourier_feature.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
(function(global) {
"use strict";
var Vol = global.Vol; // convenience

var FourierFeatureLayer = function(opt) {
/**
* Based on the paper "Fourier Features Let Networks Learn
* High Frequency Functions in Low Dimensional Domains" (2020) presented
* at NeurIPS (https://bmild.github.io/fourfeat/index.html)
* by Matthew Tancik, Pratul P. Srinivasan, Ben Mildenhall, Sara Fridovich-Keil,
* Nithin Raghavan, Utkarsh Singhal, Ravi Ramamoorthi, Jonathan T. Barron and Ren Ng.
*
* Please see the Python implementation to see examples of the concept in action:
* https://github.com/tancik/fourier-feature-networks/blob/master/Demo.ipynb.
*/

var opt = opt || {};

// required
this.in_depth = opt.in_depth;
this.in_sx = opt.in_sx;
this.in_sy = opt.in_sy;
this.inputMapCache = {}; // where we'll store (x, y) ==> their equivalent Fourier Feature Mapping

// optional - whether to factor in a random number (sampled from a Gaussian) in the mapping or not (defaults to -1, which signifies not to include it)
this.gaussianMappingScale = typeof opt.gaussian_mapping_scale !== 'undefined' ? opt.gaussian_mapping_scale : -1;

// computed
this.out_depth = this.in_depth * 2 * Math.abs(this.gaussianMappingScale);
this.out_sx = this.in_sx
this.out_sy = this.in_sy;
this.layer_type = 'fourier_feature';

}

FourierFeatureLayer.prototype = {
forward: function(V, is_training) {
var coordinateVolume = V;
if(!Object.hasOwn(this.inputMapCache, coordinateVolume.w)){
// compute for the first time
var transformedVolume = this.transform(coordinateVolume);
// save for future queries at these coordinates
this.inputMapCache[coordinateVolume.w] = transformedVolume;
}
return this.inputMapCache[coordinateVolume.w];
},
transform: function(V) {
this.in_act = V;

var mappedFeature = new Vol(this.out_sx, this.out_sy, this.out_depth, 0.0);

for(var d=0;d<this.out_depth; d++) {
var x = 0;
var y = 0;
for(var ax=0; ax<this.out_sx; x+=1,ax++) {
for(var ay=0; ay<this.out_sy; y+=1,ay++) {
var v = V.get(ax, ay, d % this.in_depth);
var randomProjFactor = 1;
if (this.gaussianMappingScale > 0) {
randomProjFactor *= global.randn(0.0, 1.0);
}
var a;
// for the first "half" of the fourier feature - use cosine
if (d < (this.out_depth / 2)) {
a = Math.cos(2 * Math.PI * v * randomProjFactor);
} else {
// use sine for the second "half"
a = Math.sin(2 * Math.PI * v * randomProjFactor);
}
mappedFeature.set(ax, ay, d, a);
}
}
}
this.out_act = mappedFeature;
return this.out_act;
},
backward: function() {
// no parameters, so simply compute gradient wrt data here
this.in_act.dw = global.zeros(this.in_act.w.length); // zero out gradient wrt data
},
getParamsAndGrads: function() {
return [];
},
toJSON: function() {
var json = {};
json.in_depth = this.in_depth;
json.out_depth = this.out_depth;
json.out_sx = this.out_sx;
json.out_sy = this.out_sy;
json.layer_type = this.layer_type;
return json;
},
fromJSON: function(json) {
this.out_depth = json.out_depth;
this.out_sx = json.out_sx;
this.out_sy = json.out_sy;
this.layer_type = json.layer_type;
this.in_depth = json.in_depth;
}
}

global.FourierFeatureLayer = FourierFeatureLayer;

})(convnetjs);
1 change: 1 addition & 0 deletions src/convnet_net.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
case 'tanh': this.layers.push(new global.TanhLayer(def)); break;
case 'maxout': this.layers.push(new global.MaxoutLayer(def)); break;
case 'svm': this.layers.push(new global.SVMLayer(def)); break;
case 'fourier_feature': this.layers.push(new global.FourierFeatureLayer(def)); break;
default: console.log('ERROR: UNRECOGNIZED LAYER TYPE: ' + def.type);
}
}
Expand Down