ตัวอย่างการสร้าง machine learning พยากรณ์ราคาหุ้น บน เว็บไซต์ ด้วย tensorflow.js ( neural network , deep learning )

Machine Learning นับว่าเข้ามามีส่วนในชีวิตของเรามากขึ้นจึงจำเป็นอย่างยิ่งที่ เราจะต้องศึกษาการเขียนโปรแกรมลักษณะนี้ ในตัวอย่างนี้ จะแสดงตัวอย่างการพยากรณ์ราคาหุ้นด้วย javascript โดยแสดงผลอยู่บน ( ในที่นี้จะใช้ราคาหุ้น CPF ) บนเว็บไซต์ ซึ่งจะใช้ tensorflow.js  ซึ่งคือ neural network และ deep learning library ซึ่งพัฒนาโดย google ดังนี้

ตัวอย่าง source code
https://jsfiddle.net/zqyhx7pm/2/

<!DOCTYPE html>
<html lang="en">
<head>
  <title>TensorFlow</title>
 
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
 
  <!-- IMPORT bootstrap และ jquery -->
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
  <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" ></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" ></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" ></script>
 
    <!-- IMPORT tensorflow.js -->
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.0.0/dist/tf.min.js"></script>

    <!-- IMPORT ประวัติราคาหุ้น CPF -->
    <script src="https://xn--12cb3ech1bdffb0m0b3iuam.net/stock/cpf_history.js"></script>


</head>
<body>

    <div class="container" >

        <div class="card">
            <div class="card-body">
                    <!----  แสดงสถานะการ train  --->
                    <div class="row">
                        <div class="col-sm-6">
                            <div>Epoch: <input  class="form-control form-control-sm" id="train-epoch" readonly="true"></input></div>
                           
                        </div>
                        <div class="col-sm-6">
                           
                            <div>Training loss: <input id="train-loss" class="form-control form-control-sm" readonly="true"></input></div>
                          
                        </div>
                    </div>

                    <!----  div สำหรับแสดงผลการทดสอบ model  --->
                    <div id="result_div" ></div>

            </div>
           
          </div>

          <!----  div สำหรับแสดงว่ากำลัง train อยู่  --->
          <div id="traning_div" class="alert alert-warning">Training</div>
         
          <!----  ตารางแสดงข้อมูลดิบที่ใช้ train model  --->
        <table class="table table-border table-sm" id="raw_data" >

            <tr class="table-active">

                <td>Date</td>
                <td>Open</td>
                <td>High</td>
                <td>Low</td>
                <td>Close</td>
               
            </tr>
           
        </table>


        <script>
       
            var input_data=[];//สร้างตัวแปร array สำหรับเก็บ input สำหรับ tarin model ที่เป็นประวัติราคา
            var output_data=[];//สร้างตัวแปร array สำหรับเก็บ output สำหรับ tarin model ที่เป็นราคาปิด

            var test_input_data=[];//สร้างตัวแปร array สำหรับเก็บ input สำหรับทดสอบ model ที่เป็นประวัติราคา
            var test_output_data=[];//สร้างตัวแปร array สำหรับเก็บ output สำหรับทดสอบ model ที่เป็นราคาปิด

            var critical= Math.round(cpf.length*0.8) ;//แบ่งจำนวน train-data 80% และ test-data 20%

            cpf.map((item,i)=>{ //อ่านข้อมูลประวัติราคาทีละแถว

                    //แสดงประวัติราคา ในตาราง
                    $("#raw_data").append(`<tr >
                        <td>`+item.Date+`</td>
                        <td>`+item.Open+`</td>
                        <td>`+item.High+`</td>
                        <td>`+item.Low+`</td>
                        <td>`+item.Close+`</td>
                       
                    </tr>`);

                    if(i<=critical)//สำหรับข้อมูล 80% จะเป็นข้อมูลสำหรับ train
                    {
                        input_data.push([item.Open,item.High,item.Low]);//ใช้ข้อมูล ราคา Open ราคา High ราคา Low เป็น ตัวแปรสำหรับทำนาย
                        output_data.push(item.Close);

                    }
                    else//สำหรับข้อมูลอีก 20% จะเป็นข้อมูลสำหรับ ทดสอบ model
                    {
                        test_input_data.push([item.Open,item.High,item.Low]);
                        test_output_data.push(item.Close);
                    }

            });

            var train_data = tf.tensor2d(input_data);//สร้าง tensor object ประวัติราคา สำหรับ  train model
            var result_data = tf.tensor1d(output_data);//สร้าง tensor object ผลลัพธ์ สำหรับ  train model
            var test_data = tf.tensor2d(test_input_data);//สร้าง tensor object ประวัติราคา สำหรับทดสอบ model
            var test_output= tf.tensor1d(test_output_data);//สร้าง tensor object ผลลัพธ์ สำหรับทดสอบ  model

            //สร้าง model neural network สำหรับพยากรณ์ โดยมี 3 Layer แต่ละ Layer มี 3 Node
            var model = tf.sequential();
           
            model.add(tf.layers.dense({
                        inputShape: 3,
                        activation: "linear",
                        units: 3  ,
            }));

            model.add(tf.layers.dense({
                        inputShape: 3,
                        activation: "linear",
                        units: 3 ,
            }));
           
            model.add(tf.layers.dense({
                        inputShape: 3,
                        activation: "linear",
                        units: 1 ,
            }));
           
            model.compile({
                loss: "meanSquaredError",// เช่น ค่าจริง 3 ผลเป็น  5  meanSquaredError คือ (5-3)ยกกำลัง2
                optimizer: tf.train.adam(0.01),//สุ่มเลขเปลี่ยนทีละ 0.01
            });
           
            model.fit(train_data, result_data, {epochs:500, callbacks: { onEpochEnd: async (epoch, logs) => {
                  
                    //แสดง Update สถานะการสร้าง model แต่ละ epco
                    document.getElementById('train-epoch').value = (epoch + 1)+" / 500";
                    document.getElementById('train-loss').value = logs.loss.toFixed(4);
                  

          } },} ).then((history) => {
             
                var predict=model.predict(test_data);//ทดสอบ Model โดยใช้ test_data ที่เก็บเอาไว้
               
               
                console.log(predict.dataSync());
              
                var result_predict=predict.dataSync();//สร้างตัวแปรเก็บราคาปิดที่เป็นผลลัพธ์ของการพยากรณ์
                var real_result=test_output.dataSync();//สร้างตัวแปรเก็บราคาปิดจริง

                var predict_html=`<br /><h4>ทดสอบ Model</h4><table class='table table-sm'>
                        <tr class='table-active'>
                            
                            <td>Open</td>
                            <td>High</td>
                            <td>Low</td>
                         
                            <td>Close</td>

                            <td>ราคาClose ที่พยากรณ์ได้</td>
               
                        </tr>
                    `;
                //วน loop ราคาที่พยากรณ์ได้เทียบกับราคาจริง
                for(var i=0;i<result_predict.length;i++)
                {
                    //หาเปอร์เซ็นความผิดพลาดของราคาจริงกับราคาที่พยากรณ์ได้
                    var diff_percent=(Math.abs(real_result[i]-result_predict[i])/real_result[i])*100;
                    //แสดงแถวข้อมูลราคาที่พยกรณ์ได้เทียบกับราคาจริง
                    predict_html+=`
                        <tr>
                            <td> `+test_input_data[i][0]+`</td>
                            <td> `+test_input_data[i][1]+`</td>
                            <td> `+test_input_data[i][2]+`</td>
                           
                            <td> `+real_result[i]+` </td>

                            <td> `+result_predict[i].toFixed(2)+`<div class='text-danger' >( ผิดพลาด `+diff_percent.toFixed(2)+` % )</div>`+` </td>
               
                        </tr>
                    `;
                }

                predict_html+=`</table><br />`;
                $("#result_div").html(predict_html);//แสดงตารางผลการทดสอบ Model
               
                $("#traning_div").remove();//เมื่อพยากรณ์เสร็จแล้ว นำ div สำหรับแสดงว่ากำลัง train อยู่ ออก
       

            });

        </script>


    </div>



</body>
</html>

ผลลัพธ์ที่ได้คือ