Tensorflow.js: простая линейная регрессия не работает - PullRequest
2 голосов
/ 02 июля 2019

У меня есть этот основной код из примера видео (первая половина видео делает это, но с другим набором данных).

Код:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' />
        <title>Website</title>
        <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.0.0/dist/tf.min.js"></script>
        <style>

        </style>
        <script>
            var linearModel = tf.sequential();
            linearModel.add(tf.layers.dense({units: 1, inputShape: [1]}));
            linearModel.compile({loss: 'meanSquaredError', optimizer: 'sgd'});

            var xs = tf.tensor1d([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100]);
            var ys = tf.tensor1d([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100]);

            linearModel.fit(xs, ys);

            function linearPrediction(val) {
                var output = linearModel.predict(tf.tensor2d([val], [1,1]));
                var prediction = Array.from(output.dataSync())[0];
                console.log(prediction);
            }

            linearPrediction(50);
        </script>
    </head>
    <body>
        Welcome to my website.
    </body>
</html>

Я тренирую это с 100 значениями, где вход совпадает с выходом. Затем, когда я пытаюсь запустить его с 50 в качестве ввода после тренировки, я получаю результаты, которые варьируются от -50 до 60.

Это нормально? Я ожидал бы значения, близкие к 50.

Кроме того, когда я тренируюсь с массивом со значениями от 1 до 1000 и вводом 500, я даже получаю выходные данные, начиная с -600.

1 Ответ

0 голосов
/ 02 июля 2019

В вашем коде есть две основные проблемы.

Проблема 1: Не дожидается завершения Обещания

linearModel.fit возвращает Обещание, которое будет решенокогда обучение закончено.Это означает, что сейчас модель начнет обучение, но до того, как обучение закончится, вы уже запрашиваете прогнозы.

Вам нужно дождаться разрешения Обещания.Самый простой способ сделать это - поместить свой код в функцию async и использовать await следующим образом:

(async () => {
  var linearModel = tf.sequential();
  // ...
  await linearModel.fit(xs, ys);
  // ...
})();

Проблема 2. Плохая скорость обучения

Обучение по умолчаниюставка для sgd составляет 0.01, что является слишком высоким в вашем случае.Обучение вашей модели с этим значением увеличивало значение loss для каждой итерации обучения для меня, указывая, что скорость обучения слишком высока.Если вам нужна дополнительная информация по теме, ознакомьтесь с этим руководством по «Оценка оптимальной скорости обучения» .

. Вы можете изменить скорость обучения с помощью tf.train.sgd функция (вместо использования строки) и прохождение скорости обучения, как это:

linearModel.compile({ loss: 'meanSquaredError', optimizer: tf.train.sgd(0.0001) });

Дальнейшее улучшение: тренировка для более чем одной эпохи

Хотя вышеупомянутые советы уже должны датьрезультаты, близкие к 50, позволяют дополнительно улучшить вашу модель, обучаясь более одной эпохи.Вы можете передать параметр epochs следующим образом:

await linearModel.fit(xs, ys, {
  epochs: 10
});

Попробуйте сами

Я добавил улучшения в ваш код в следующем фрагменте кода.Вы можете изменить значения epochs и learning rate, чтобы увидеть, как это влияет на итоговый прогноз 50.

document.querySelector('button').addEventListener('click', async () => {
    const learningRate = document.querySelector('#learning_rate').value;
    const epochs = document.querySelector('#epochs').value;
    
    const linearModel = tf.sequential();
    linearModel.add(tf.layers.dense({ units: 1, inputShape: [1] }));
    linearModel.compile({ loss: 'meanSquaredError', optimizer: tf.train.sgd(learningRate) });

    const xs = tf.tensor1d([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100]);
    const ys = tf.tensor1d([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100]);

    await linearModel.fit(xs, ys, {
        epochs,
        callbacks: {
            onEpochEnd: (epoch, logs) => console.log(`Loss, epoch ${epoch}: ${logs.loss}`),
        },
    });

    function linearPrediction(val) {
        const output = linearModel.predict(tf.tensor1d([val]));
        const prediction = Array.from(output.dataSync())[0];
        console.log(`Prediction for 50: ${prediction}`);
    }

    linearPrediction(50);
});
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.0.0/dist/tf.min.js"></script>

epochs: <input type="number" id="epochs" value="1" />
learning rate: <input type="number" id="learning_rate" value="0.0001" />
<button id="train">Train</button>
...