メニュー 閉じる

032. p5.jsからTensorFlow.jsをちょっといじってみる – その2

前回のコードをもうちょっとわかりやすく書き換えてみました。
「サンプルデータ作成」「予測モデル作成」「損失関数作成」「訓練関数作成」の4つのブロックに分けて適宜呼び出すようにします。

(1):最終的な理想モデルは:y = (0.1) * x + (0.3)
(2):各係数の予測モデルは:y = (a) * x + (b)

で出発します。

(1)は係数が分かっているので、どんなx値を代入しても自動的にy値が決まり、プロットすると一定の直線になります。
(2)は係数がわかっていません。試しにa、bに乱数を振り当ててx値を代入します。もちろん係数の値が違うので、(1)と違う直線になります。

ここから訓練が始まります。(1)のyと(2)のyの誤差を計算し、重みを付けて、aとbに反映します。
それを繰り返して、a => 0.1、b=> 0.3へと近づいていきます。

画像は(1)の直線が赤、(2)の未訓練の直線が緑になっています。徐々に(1)に近づく線をプロットしてみました。

http://www.velvet-number.com/p5_test/test022/

var random_data = [];

var x_data; 
var y_data;

var a_data = [];
var b_data = [];

var a = tf.variable (tf.scalar(Math.random()));
var b = tf.variable (tf.scalar(Math.random()));

var sample_num;
var train_num;
var learn_rate;
var optimizer;

function setup () {

	pixelDensity (displayDensity ());
	createCanvas (windowWidth, windowHeight);
	colorMode (RGB, 256);
	background (0);

	sample_num = 100;
	train_num = 1000;
	learn_rate = 0.5;
	optimizer = tf.train.sgd (learn_rate);

	data_create ();

	data_train (x_data, y_data, train_num);

}

function draw () {

	background (255);

	noFill ();

	stroke (0, 255, 0);

	var y_pos01 = map (a_data[0] * 0.0 + b_data[0], 0, 1, 0, height);
	var y_pos02 = map (a_data[0] * 1.0 + b_data[0], 0, 1, 0, height);
	line (0, y_pos01, width, y_pos02);

	for (var i = 0; i < train_num; i++) {
		var r = map (i, 0, train_num, 0, 255);
		stroke (r, 0, 0, r + 100);
		var y_pos01 = map (a_data[i] * 0.0 + b_data[i], 0, 1, 0, height);
		var y_pos02 = map (a_data[i] * 1.0 + b_data[i], 0, 1, 0, height);
		line (0, y_pos01, width, y_pos02);
	}

	stroke (255, 0, 0);

	var y_pos01 = map (0.1 * 0.0 + 0.3, 0, 1, 0, height);
	var y_pos02 = map (0.1 * 1.0 + 0.3, 0, 1, 0, height);
	line (0, y_pos01, width, y_pos02);

}

function data_create () {

	for (var i = 0; i < sample_num; i++) {
		random_data[i] = random ();
	}
	x_data = tf.tensor1d (random_data);
	y_data = tf.add (tf.mul (x_data, tf.scalar (0.1)), tf.scalar (0.3));

}

function data_train (xs, ys, train_num) {

	for (var i = 0; i < train_num; i++) {
		optimizer.minimize (() => data_loss (data_predict (xs), ys));
		a_data[i] = a.dataSync ()[0];
		b_data[i] = b.dataSync ()[0];
		//console.log (i, 'a: ' + a.dataSync (), 'b: ' + b.dataSync ());
	}

}

function data_predict (x) {

	return tf.tidy (() => {
		return tf.add (tf.mul (a, x), b);
	});

}

function data_loss (predict_data, actual_data) {

	const ms_error = predict_data.sub (actual_data).square ().mean ();

	return ms_error;

}

 

 

Posted in p5.js , processing