Teachers open the door but You must enter by yourself.

Open Media Lab.
オープンメディアラボ

【事前学習】ニューラルネットワークの基礎を復習してきましょう。

回帰問題
Regression

直線による回帰

直線 y=2x 上の分布データを入力として、それが y=2x 上の点であることをニューラルネットワークに学習させてみましょう。

<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@4.13.0/dist/tf.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-vis@latest"></script>
<script>
async function trainModel(model, inputs, labels){
	model.compile({
		optimizer: tf.train.sgd(0.01), //学習の効率に関わる
		loss: tf.losses.meanSquaredError,//平均二乗誤差を減少するように学習
		metrics: ['mse'],
	});

	const batchSize = 32;
	const epochs = 100;//学習の反復回数

	return await model.fit(inputs, labels,{
		batchSize,
		epochs,
		shuffle:true,
		callbacks: tfvis.show.fitCallbacks(
			document.getElementById('training'),
			['mse'], 
			{width:350, height:200, callbacks:['onEpochEnd']}
		)
	});
}

async function run() {
	//学習データ
	const x = [1,2,3,4];
	const y = [2,4,6,8];
	//数値データの配列をテンソル化
	const xs = tf.tensor2d(x,[x.length,1]);
	const ys = tf.tensor2d(y,[y.length,1]);

	const model=tf.sequential();
	//層を追加、inputShape[]を与えると入力層も自動的に設定されるので
	//これだけで1入力1出力の構成となる。
	const layer=tf.layers.dense({inputShape:[1], units:1});
	model.add(layer);

	await trainModel(model, xs, ys);//学習の関数をコール

	document.getElementById('output').innerHTML
		= '<pre>'+model.predict(xs).toString()+'</pre>';
	document.getElementById('weight').innerHTML
		= '<pre>'+layer.getWeights().toString()
			.replace(',Tensor',',<br>Tensor')+'</pre>';
	document.getElementById('loss').innerHTML
		= '<pre>'+model.evaluate(xs,ys).toString()
			.replace(',Tensor',',<br>Tensor')+'</pre>';

	const answer = Array(x.length).fill()
		.map((ai, i) => ({x:x[i], y:y[i]}));
	const predict = model.predict(xs).arraySync()
		.map((yi, i) => ({x:x[i], y:yi}));

	tfvis.render.scatterplot(
		document.getElementById('chart'),
		{values:[answer,predict], series:['Answer','Predict']},
		{xLabel:'x values', yLabel:'y values', width:350, height:600}
	);
}
document.addEventListener('DOMContentLoaded', run);
</script>
</head>
<body>
<h3>ニューラルネットワークの学習結果</h3>
<div id="training"></div>
<div id="chart"></div>
<h4>学習後のネットワークの出力値</h4>
<div id="output"></div>
<h4>第1層のパラメータ</h4>
<div id="weight"></div>
<h4>2乗誤差の平均 (MSE)</h4>
<div id="loss"></div>
<p><small>※ 結果が表示されるまでしばらくお待ちください。</small></p>
</body>
</html>

ニューラルネットワークの学習結果

学習後のネットワークの出力値

第1層のパラメータ

2乗誤差の平均 (MSE)

※ 結果が表示されるまでしばらくお待ちください。

Lesson

  1. データを変更してみましょう。
  2. const x = [1,2,3,4];
    const y = [3,5,7,9];
    
  3. データを変更してみましょう。
    
    const x = [1,2,3,4];
    const y = [1,4,9,16];
    ※ 1-1ネットワークでは直線の当てはめにしかならないことを確認して、
    1-2-1ネットワークに変更する。反復回数は1000回ぐらい
    const layer=tf.layers.dense({inputShape:[1], units:2, activation:'softplus'});
    model.add(layer);
    const layer2=tf.layers.dense({units:1});
    model.add(layer2);
    
  4. データを追加してみましょう。
    
    const x = [-4,-3,-2,1,0,1,2,3,4];
    const y = [16,9,4,1,0,1,4,9,16];
    
  5. Tensorflow.jsTensorflow.jsのチュートリアルで提供されている車の燃費に関するデータをネットワークに学習させてみましょう。
  6. 
    const X=[130, 165, 150, 150, 140, 198, 220, 215, 225, 190, 170, 160, 150, 225, 95, 95, 97, 85, 88, 46, 87, 90, 95, 113, 90, 215, 200, 210, 193, 88, 90, 95, 100, 105, 100, 88, 100, 165, 175, 153, 150, 180, 170, 175, 110, 72, 100, 88, 86, 90, 70, 76, 65, 69, 60, 70, 95, 80, 54, 90, 86, 165, 175, 150, 153, 150, 208, 155, 160, 190, 97, 150, 130, 140, 150, 112, 76, 87, 69, 86, 92, 97, 80, 88, 175, 150, 145, 137, 150, 198, 150, 158, 150, 215, 225, 175, 105, 100, 100, 88, 95, 46, 150, 167, 170, 180, 100, 88, 72, 94, 90, 85, 107, 90, 145, 230, 49, 75, 91, 112, 150, 110, 122, 180, 95, 100, 100, 67, 80, 65, 75, 100, 110, 105, 140, 150, 150, 140, 150, 83, 67, 78, 52, 61, 75, 75, 75, 97, 93, 67, 95, 105, 72, 72, 170, 145, 150, 148, 110, 105, 110, 95, 110, 110, 129, 75, 83, 100, 78, 96, 71, 97, 97, 70, 90, 95, 88, 98, 115, 53, 86, 81, 92, 79, 83, 140, 150, 120, 152, 100, 105, 81, 90, 52, 60, 70, 53, 100, 78, 110, 95, 71, 70, 75, 72, 102, 150, 88, 108, 120, 180, 145, 130, 150, 68, 80, 58, 96, 70, 145, 110, 145, 130, 110, 105, 100, 98, 180, 170, 190, 149, 78, 88, 75, 89, 63, 83, 67, 78, 97, 110, 110, 48, 66, 52, 70, 60, 110, 140, 139, 105, 95, 85, 88, 100, 90, 105, 85, 110, 120, 145, 165, 139, 140, 68, 95, 97, 75, 95, 105, 85, 97, 103, 125, 115, 133, 71, 68, 115, 85, 88, 90, 110, 130, 129, 138, 135, 155, 142, 125, 150, 71, 65, 80, 80, 77, 125, 71, 90, 70, 70, 65, 69, 90, 115, 115, 90, 76, 60, 70, 65, 90, 88, 90, 90, 78, 90, 75, 92, 75, 65, 105, 65, 48, 48, 67, 67, 67, 67, 62, 132, 100, 88, 72, 84, 84, 92, 110, 84, 58, 64, 60, 67, 65, 62, 68, 63, 65, 65, 74, 75, 75, 100, 74, 80, 76, 116, 120, 110, 105, 88, 85, 88, 88, 88, 85, 84, 90, 92, 74, 68, 68, 63, 70, 88, 75, 70, 67, 67, 67, 110, 85, 92, 112, 96, 84, 90, 86, 52, 84, 79, 82];
    const Y=[18, 15, 18, 16, 17, 15, 14, 14, 14, 15, 15, 14, 15, 14, 24, 22, 18, 21, 27, 26, 25, 24, 25, 26, 21, 10, 10, 11, 9, 27, 28, 25, 19, 16, 17, 19, 18, 14, 14, 14, 14, 12, 13, 13, 18, 22, 19, 18, 23, 28, 30, 30, 31, 35, 27, 26, 24, 25, 23, 20, 21, 13, 14, 15, 14, 17, 11, 13, 12, 13, 19, 15, 13, 13, 14, 18, 22, 21, 26, 22, 28, 23, 28, 27, 13, 14, 13, 14, 15, 12, 13, 13, 14, 13, 12, 13, 18, 16, 18, 18, 23, 26, 11, 12, 13, 12, 18, 20, 21, 22, 18, 19, 21, 26, 15, 16, 29, 24, 20, 19, 15, 24, 20, 11, 20, 19, 15, 31, 26, 32, 25, 16, 16, 18, 16, 13, 14, 14, 14, 29, 26, 26, 31, 32, 28, 24, 26, 24, 26, 31, 19, 18, 15, 15, 16, 15, 16, 14, 17, 16, 15, 18, 21, 20, 13, 29, 23, 20, 23, 24, 25, 24, 18, 29, 19, 23, 23, 22, 25, 33, 28, 25, 25, 26, 27, 17.5, 16, 15.5, 14.5, 22, 22, 24, 22.5, 29, 24.5, 29, 33, 20, 18, 18.5, 17.5, 29.5, 32, 28, 26.5, 20, 13, 19, 19, 16.5, 16.5, 13, 13, 13, 31.5, 30, 36, 25.5, 33.5, 17.5, 17, 15.5, 15, 17.5, 20.5, 19, 18.5, 16, 15.5, 15.5, 16, 29, 24.5, 26, 25.5, 30.5, 33.5, 30, 30.5, 22, 21.5, 21.5, 43.1, 36.1, 32.8, 39.4, 36.1, 19.9, 19.4, 20.2, 19.2, 20.5, 20.2, 25.1, 20.5, 19.4, 20.6, 20.8, 18.6, 18.1, 19.2, 17.7, 18.1, 17.5, 30, 27.5, 27.2, 30.9, 21.1, 23.2, 23.8, 23.9, 20.3, 17, 21.6, 16.2, 31.5, 29.5, 21.5, 19.8, 22.3, 20.2, 20.6, 17, 17.6, 16.5, 18.2, 16.9, 15.5, 19.2, 18.5, 31.9, 34.1, 35.7, 27.4, 25.4, 23, 27.2, 23.9, 34.2, 34.5, 31.8, 37.3, 28.4, 28.8, 26.8, 33.5, 41.5, 38.1, 32.1, 37.2, 28, 26.4, 24.3, 19.1, 34.3, 29.8, 31.3, 37, 32.2, 46.6, 27.9, 40.8, 44.3, 43.4, 36.4, 30, 44.6, 33.8, 29.8, 32.7, 23.7, 35, 32.4, 27.2, 26.6, 25.8, 23.5, 30, 39.1, 39, 35.1, 32.3, 37, 37.7, 34.1, 34.7, 34.4, 29.9, 33, 33.7, 32.4, 32.9, 31.6, 28.1, 30.7, 25.4, 24.2, 22.4, 26.6, 20.2, 17.6, 28, 27, 34, 31, 29, 27, 24, 36, 37, 31, 38, 36, 36, 36, 34, 38, 32, 38, 25, 38, 26, 22, 32, 36, 27, 27, 44, 32, 28, 31];
    //元データを0~1の範囲に正規化したデータを学習に用いる
    const x=X.map(xi=>(xi-46)/(230-46));
    const y=Y.map(yi=>(yi-9)/(46.6-9));
    
    //データプロットでは正規化前の値を用いる
    const answer = Array(x.length).fill()
    	.map((ai, i) => ({x:x[i]*(230-46)+46, y:y[i]*(46.6-9)+9}));
    const predict = model.predict(xs).arraySync()
    	.map((yi, i) => ({x:x[i]*(230-46)+46, y:yi*(46.6-9)+9}));
    
    
    1. 出力層に非線形の活性化関数を設定
      
      const layer=tf.layers.dense({inputShape:[1], units:1, activation:'sigmoid'});
      model.add(layer);
      

      ※ optimizer: tf.train.adam() に変更してください。

    2. 更にユニット数2の中間層の増やし、非線形の活性化関数(sigmoid)を設定
      
      const layer=tf.layers.dense({inputShape:[1], units:2, activation:'sigmoid'});
      model.add(layer);
      const layer2=tf.layers.dense({units:1, activation:'softplus'});
      model.add(layer2);
      

      ※ optimizer: tf.train.adam() に変更してください。


【事後学習】深層学習を回帰問題に適応させる方法を復習しておきましょう。

This site is powered by Powered by MathJax