TensorFlow.js — การสร้างการคาดการณ์จากข้อมูล 2 มิติ

1. บทนำ

ในโค้ดแล็บนี้ คุณจะได้ฝึกโมเดลเพื่อทำการคาดการณ์จากข้อมูลตัวเลขที่อธิบายชุดรถยนต์

แบบฝึกหัดนี้จะแสดงขั้นตอนที่ใช้กันทั่วไปในการฝึกโมเดลหลายประเภท แต่จะใช้ชุดข้อมูลขนาดเล็กและโมเดลอย่างง่าย (แบบตื้น) เป้าหมายหลักคือการช่วยให้คุณคุ้นเคยกับคำศัพท์ แนวคิด และไวยากรณ์พื้นฐานเกี่ยวกับการฝึกโมเดลด้วย TensorFlow.js รวมถึงเป็นก้าวแรกในการสำรวจและเรียนรู้เพิ่มเติม

เนื่องจากเรากำลังฝึกโมเดลเพื่อคาดการณ์ตัวเลขต่อเนื่อง งานนี้จึงอาจเรียกว่างานการถดถอย เราจะฝึกโมเดลโดยแสดงตัวอย่างอินพุตจำนวนมากพร้อมกับเอาต์พุตที่ถูกต้อง ซึ่งเรียกว่าการเรียนรู้ที่มีการควบคุมดูแล

สิ่งที่คุณจะสร้าง

คุณจะสร้างหน้าเว็บที่ใช้ TensorFlow.js เพื่อฝึกโมเดลในเบราว์เซอร์ เมื่อได้รับ "แรงม้า" สำหรับรถยนต์ โมเดลจะเรียนรู้ที่จะคาดการณ์ "ไมล์ต่อแกลลอน" (MPG)

โดยทำดังนี้

  • โหลดข้อมูลและเตรียมข้อมูลสำหรับการฝึก
  • กำหนดสถาปัตยกรรมของโมเดล
  • ฝึกโมเดลและตรวจสอบประสิทธิภาพขณะฝึก
  • ประเมินโมเดลที่ฝึกแล้วโดยทำการคาดการณ์

สิ่งที่คุณจะได้เรียนรู้

  • แนวทางปฏิบัติแนะนำในการจัดเตรียมข้อมูลสำหรับแมชชีนเลิร์นนิง ซึ่งรวมถึงการสับเปลี่ยนและการทำให้เป็นมาตรฐาน
  • ไวยากรณ์ TensorFlow.js สำหรับการสร้างโมเดลโดยใช้ tf.layers API
  • วิธีตรวจสอบการฝึกในเบราว์เซอร์โดยใช้ไลบรารี tfjs-vis

สิ่งที่คุณต้องมี

2. ตั้งค่า

สร้างหน้า HTML และใส่ JavaScript

96914ff65fc3b74c.png คัดลอกโค้ดต่อไปนี้ลงในไฟล์ HTML ที่ชื่อ

index.html

<!DOCTYPE html>
<html>
<head>
  <title>TensorFlow.js Tutorial</title>

  <!-- Import TensorFlow.js -->
  <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js"></script>
  <!-- Import tfjs-vis -->
  <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-vis@1.0.2/dist/tfjs-vis.umd.min.js"></script>
</head>
<body>
  <!-- Import the main script file -->
  <script src="script.js"></script>
</body>
</html>

สร้างไฟล์ JavaScript สำหรับโค้ด

  1. ในโฟลเดอร์เดียวกับไฟล์ HTML ด้านบน ให้สร้างไฟล์ชื่อ script.js แล้ววางโค้ดต่อไปนี้ลงในไฟล์
console.log('Hello TensorFlow');

ทดสอบเลย

ตอนนี้คุณได้สร้างไฟล์ HTML และ JavaScript แล้ว ให้ทดสอบไฟล์เหล่านั้น เปิดไฟล์ index.html ในเบราว์เซอร์และเปิดคอนโซลเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์

หากทุกอย่างทำงานได้ตามปกติ ควรมีตัวแปรส่วนกลาง 2 รายการที่สร้างขึ้นและพร้อมใช้งานในคอนโซลเครื่องมือสำหรับนักพัฒนาเว็บ ดังนี้

  • tf คือการอ้างอิงถึงไลบรารี TensorFlow.js
  • tfvis เป็นการอ้างอิงถึงไลบรารี tfjs-vis

เปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ของเบราว์เซอร์ คุณควรเห็นข้อความที่ระบุว่า Hello TensorFlow ในเอาต์พุตของคอนโซล หากเป็นเช่นนั้น คุณก็พร้อมที่จะไปยังขั้นตอนถัดไป

3. โหลด จัดรูปแบบ และแสดงภาพข้อมูลอินพุต

ขั้นตอนแรกคือการโหลด จัดรูปแบบ และแสดงภาพข้อมูลที่เราต้องการใช้ฝึกโมเดล

เราจะโหลดชุดข้อมูล "รถยนต์" จากไฟล์ JSON ที่เราโฮสต์ไว้ให้คุณ ซึ่งมีฟีเจอร์ต่างๆ มากมายเกี่ยวกับรถแต่ละคัน สำหรับบทแนะนำนี้ เราต้องการดึงข้อมูลเกี่ยวกับแรงม้าและไมล์ต่อแกลลอนเท่านั้น

96914ff65fc3b74c.png เพิ่มโค้ดต่อไปนี้ลงใน

script.js file

/**
 * Get the car data reduced to just the variables we are interested
 * and cleaned of missing data.
 */
async function getData() {
  const carsDataResponse = await fetch('https://storage.googleapis.com/tfjs-tutorials/carsData.json');
  const carsData = await carsDataResponse.json();
  const cleaned = carsData.map(car => ({
    mpg: car.Miles_per_Gallon,
    horsepower: car.Horsepower,
  }))
  .filter(car => (car.mpg != null && car.horsepower != null));

  return cleaned;
}

การดำเนินการนี้จะนำรายการที่ไม่ได้กำหนดทั้งไมล์ต่อแกลลอนหรือแรงม้าออกด้วย นอกจากนี้ เรายังจะพล็อตข้อมูลนี้ในแผนภูมิกระจายเพื่อดูว่ามีลักษณะอย่างไร

96914ff65fc3b74c.png เพิ่มโค้ดต่อไปนี้ที่ด้านล่างของ

script.js file

async function run() {
  // Load and plot the original input data that we are going to train on.
  const data = await getData();
  const values = data.map(d => ({
    x: d.horsepower,
    y: d.mpg,
  }));

  tfvis.render.scatterplot(
    {name: 'Horsepower v MPG'},
    {values},
    {
      xLabel: 'Horsepower',
      yLabel: 'MPG',
      height: 300
    }
  );

  // More code will be added below
}

document.addEventListener('DOMContentLoaded', run);

เมื่อคุณรีเฟรชหน้า คุณควรเห็นแผงทางด้านซ้ายมือของหน้าเว็บที่มีแผนภูมิกระจายของข้อมูล ซึ่งควรมีหน้าตาเช่นนี้

cf44e823106c758e.png

แผงนี้เรียกว่า "แผงควบคุม" และจัดทำโดย tfjs-vis ซึ่งเป็นที่ที่สะดวกในการแสดงภาพข้อมูล

โดยทั่วไปแล้ว เมื่อทำงานกับข้อมูล คุณควรหาวิธีดูข้อมูลและล้างข้อมูลหากจำเป็น ในกรณีนี้ เราจึงต้องนำข้อมูลบางรายการออกจาก carsData ที่ไม่มีช่องที่จำเป็นทั้งหมด การแสดงข้อมูลด้วยภาพจะช่วยให้เราทราบว่าข้อมูลมีโครงสร้างใดที่โมเดลสามารถเรียนรู้ได้หรือไม่

จากแผนภาพด้านบน เราจะเห็นว่าแรงม้าและ MPG มีความสัมพันธ์ในเชิงลบ กล่าวคือ เมื่อแรงม้าเพิ่มขึ้น รถยนต์มักจะวิ่งได้ระยะทางต่อแกลลอนน้อยลง

กำหนดแนวคิดของงาน

ตอนนี้ข้อมูลนำเข้าของเราจะมีลักษณะดังนี้

...
{
  "mpg":15,
  "horsepower":165,
},
{
  "mpg":18,
  "horsepower":150,
},
{
  "mpg":16,
  "horsepower":150,
},
...

เป้าหมายของเราคือการฝึกโมเดลที่จะรับตัวเลขหนึ่งแรงม้า และเรียนรู้ที่จะคาดการณ์ตัวเลขหนึ่งไมล์ต่อแกลลอน โปรดทราบว่าการแมปแบบหนึ่งต่อหนึ่งนี้จะมีความสำคัญต่อส่วนถัดไป

เราจะป้อนตัวอย่างเหล่านี้ ซึ่งก็คือแรงม้าและ MPG ให้กับโครงข่ายประสาทที่จะเรียนรู้จากตัวอย่างเหล่านี้เป็นสูตร (หรือฟังก์ชัน) เพื่อคาดการณ์ MPG ที่กำหนดแรงม้า การเรียนรู้จากตัวอย่างที่เรามีคำตอบที่ถูกต้องเรียกว่าการเรียนรู้ที่มีการควบคุมดูแล

4. กำหนดสถาปัตยกรรมโมเดล

ในส่วนนี้ เราจะเขียนโค้ดเพื่ออธิบายสถาปัตยกรรมของโมเดล สถาปัตยกรรมโมเดลเป็นเพียงวิธีที่ดูดีในการพูดว่า "โมเดลจะเรียกใช้ฟังก์ชันใดเมื่อดำเนินการ" หรืออีกนัยหนึ่งคือ "โมเดลจะใช้อัลกอริทึมใดในการคำนวณคำตอบ"

โมเดล ML คืออัลกอริทึมที่รับอินพุตและสร้างเอาต์พุต เมื่อใช้โครงข่ายประสาทเทียม อัลกอริทึมคือชุดเลเยอร์ของนิวรอนที่มี "น้ำหนัก" (ตัวเลข) ซึ่งควบคุมเอาต์พุต กระบวนการฝึกจะเรียนรู้ค่าที่เหมาะสมที่สุดสำหรับน้ำหนักเหล่านั้น

96914ff65fc3b74c.png เพิ่มฟังก์ชันต่อไปนี้ลงใน

script.js เพื่อกำหนดสถาปัตยกรรมของโมเดล

function createModel() {
  // Create a sequential model
  const model = tf.sequential();

  // Add a single input layer
  model.add(tf.layers.dense({inputShape: [1], units: 1, useBias: true}));

  // Add an output layer
  model.add(tf.layers.dense({units: 1, useBias: true}));

  return model;
}

นี่เป็นโมเดลที่ง่ายที่สุดโมเดลหนึ่งที่เรากำหนดได้ใน tensorflow.js มาดูแต่ละบรรทัดกัน

สร้างอินสแตนซ์ของโมเดล

const model = tf.sequential();

ซึ่งจะสร้างออบเจ็กต์ tf.Model โมเดลนี้เป็น sequential เนื่องจากอินพุตจะไหลลงไปยังเอาต์พุตโดยตรง โมเดลประเภทอื่นๆ อาจมีสาขา หรือแม้แต่มีอินพุตและเอาต์พุตหลายรายการ แต่ในหลายกรณี โมเดลของคุณจะเป็นแบบลำดับ นอกจากนี้ โมเดลแบบลำดับยังมี API ที่ใช้งานง่ายขึ้นด้วย

เพิ่มเลเยอร์

model.add(tf.layers.dense({inputShape: [1], units: 1, useBias: true}));

ซึ่งจะเพิ่มเลเยอร์อินพุตลงในเครือข่ายของเรา ซึ่งจะเชื่อมต่อกับเลเยอร์ dense โดยอัตโนมัติที่มีหน่วยที่ซ่อนไว้ 1 หน่วย denseเลเยอร์เป็นเลเยอร์ประเภทหนึ่งที่คูณอินพุตด้วยเมทริกซ์ (เรียกว่าน้ำหนัก) แล้วบวกตัวเลข (เรียกว่าอคติ) กับผลลัพธ์ เนื่องจากนี่คือเลเยอร์แรกของเครือข่าย เราจึงต้องกำหนด inputShape inputShape คือ [1] เนื่องจากเรามี1 เป็นอินพุต (แรงม้าของรถยนต์คันหนึ่งๆ)

units กำหนดขนาดของเมทริกซ์น้ำหนักในเลเยอร์ การตั้งค่าเป็น 1 ที่นี่หมายความว่าจะมีน้ำหนัก 1 รายการสำหรับฟีเจอร์อินพุตแต่ละรายการของข้อมูล

model.add(tf.layers.dense({units: 1}));

โค้ดด้านบนสร้างเลเยอร์เอาต์พุต เราตั้งค่า units เป็น 1 เนื่องจากต้องการแสดงผลหมายเลข 1

สร้างอินสแตนซ์

96914ff65fc3b74c.png เพิ่มโค้ดต่อไปนี้ลงใน

run ฟังก์ชันที่เรากำหนดไว้ก่อนหน้านี้

// Create the model
const model = createModel();
tfvis.show.modelSummary({name: 'Model Summary'}, model);

การดำเนินการนี้จะสร้างอินสแตนซ์ของโมเดลและแสดงข้อมูลสรุปของเลเยอร์ในหน้าเว็บ

5. เตรียมข้อมูลสำหรับการฝึก

หากต้องการรับประโยชน์ด้านประสิทธิภาพของ TensorFlow.js ที่ทำให้การฝึกโมเดลแมชชีนเลิร์นนิงเป็นไปได้จริง เราต้องแปลงข้อมูลเป็นเทนเซอร์ นอกจากนี้ เราจะทำการเปลี่ยนรูปแบบข้อมูลตามแนวทางปฏิบัติแนะนำหลายอย่าง ได้แก่ การสับเปลี่ยนและการปรับให้เป็นมาตรฐาน

96914ff65fc3b74c.png เพิ่มโค้ดต่อไปนี้ลงใน

script.js file

/**
 * Convert the input data to tensors that we can use for machine
 * learning. We will also do the important best practices of _shuffling_
 * the data and _normalizing_ the data
 * MPG on the y-axis.
 */
function convertToTensor(data) {
  // Wrapping these calculations in a tidy will dispose any
  // intermediate tensors.

  return tf.tidy(() => {
    // Step 1. Shuffle the data
    tf.util.shuffle(data);

    // Step 2. Convert data to Tensor
    const inputs = data.map(d => d.horsepower)
    const labels = data.map(d => d.mpg);

    const inputTensor = tf.tensor2d(inputs, [inputs.length, 1]);
    const labelTensor = tf.tensor2d(labels, [labels.length, 1]);

    //Step 3. Normalize the data to the range 0 - 1 using min-max scaling
    const inputMax = inputTensor.max();
    const inputMin = inputTensor.min();
    const labelMax = labelTensor.max();
    const labelMin = labelTensor.min();

    const normalizedInputs = inputTensor.sub(inputMin).div(inputMax.sub(inputMin));
    const normalizedLabels = labelTensor.sub(labelMin).div(labelMax.sub(labelMin));

    return {
      inputs: normalizedInputs,
      labels: normalizedLabels,
      // Return the min/max bounds so we can use them later.
      inputMax,
      inputMin,
      labelMax,
      labelMin,
    }
  });
}

มาดูรายละเอียดสิ่งที่เกิดขึ้นกัน

สับเปลี่ยนข้อมูล

// Step 1. Shuffle the data
tf.util.shuffle(data);

ในที่นี้ เราจะสุ่มลำดับของตัวอย่างที่จะป้อนให้กับอัลกอริทึมการฝึก การสับเปลี่ยนเป็นสิ่งสำคัญเนื่องจากโดยปกติแล้วในระหว่างการฝึก ชุดข้อมูลจะแบ่งออกเป็นชุดย่อยๆ ที่เล็กลงเรียกว่าแบทช์ ซึ่งโมเดลจะได้รับการฝึกในแบทช์เหล่านั้น การสับเปลี่ยนช่วยให้แต่ละกลุ่มมีข้อมูลที่หลากหลายจากการกระจายข้อมูล การทำเช่นนี้จะช่วยให้โมเดลทำสิ่งต่อไปนี้ได้

  • ไม่เรียนรู้สิ่งต่างๆ ที่ขึ้นอยู่กับลำดับการป้อนข้อมูลเท่านั้น
  • ไม่ไวต่อโครงสร้างในกลุ่มย่อย (เช่น หากเห็นเฉพาะรถยนต์ที่มีแรงม้าสูงในช่วงครึ่งแรกของการฝึก ก็อาจเรียนรู้ความสัมพันธ์ที่ไม่สามารถใช้กับส่วนที่เหลือของชุดข้อมูลได้)

แปลงเป็นเทนเซอร์

// Step 2. Convert data to Tensor
const inputs = data.map(d => d.horsepower)
const labels = data.map(d => d.mpg);

const inputTensor = tf.tensor2d(inputs, [inputs.length, 1]);
const labelTensor = tf.tensor2d(labels, [labels.length, 1]);

ในที่นี้ เราจะสร้างอาร์เรย์ 2 รายการ รายการหนึ่งสำหรับตัวอย่างอินพุต (รายการแรงม้า) และอีกรายการหนึ่งสำหรับค่าเอาต์พุตจริง (ซึ่งเรียกว่าป้ายกำกับในแมชชีนเลิร์นนิง)

จากนั้นเราจะแปลงข้อมูลอาร์เรย์แต่ละรายการเป็นเทนเซอร์ 2 มิติ เทนเซอร์จะมีรูปร่างเป็น [num_examples, num_features_per_example] ในที่นี้เรามีinputs.lengthตัวอย่างและแต่ละตัวอย่างมี1ฟีเจอร์อินพุต (แรงม้า)

ทำให้ข้อมูลเป็นมาตรฐาน

//Step 3. Normalize the data to the range 0 - 1 using min-max scaling
const inputMax = inputTensor.max();
const inputMin = inputTensor.min();
const labelMax = labelTensor.max();
const labelMin = labelTensor.min();

const normalizedInputs = inputTensor.sub(inputMin).div(inputMax.sub(inputMin));
const normalizedLabels = labelTensor.sub(labelMin).div(labelMax.sub(labelMin));

จากนั้นเราจะทำตามแนวทางปฏิบัติแนะนำอีกอย่างสำหรับการฝึกแมชชีนเลิร์นนิง เราปรับให้เป็นมาตรฐาน ในที่นี้ เราจะปรับข้อมูลให้เป็นช่วงตัวเลข 0-1 โดยใช้การปรับขนาดแบบ Min-Max การปรับให้เป็นมาตรฐานเป็นสิ่งสำคัญเนื่องจากภายในของโมเดลแมชชีนเลิร์นนิงจำนวนมากที่คุณจะสร้างด้วย TensorFlow.js ออกแบบมาให้ทำงานกับตัวเลขที่ไม่ใหญ่เกินไป ช่วงที่ใช้กันทั่วไปในการปรับข้อมูลให้เป็นค่าปกติ ได้แก่ 0 to 1 หรือ -1 to 1 คุณจะฝึกโมเดลได้สำเร็จมากขึ้นหากสร้างนิสัยในการปรับข้อมูลให้เป็นช่วงที่สมเหตุสมผล

ส่งคืนข้อมูลและขอบเขตการปรับให้เป็นมาตรฐาน

return {
  inputs: normalizedInputs,
  labels: normalizedLabels,
  // Return the min/max bounds so we can use them later.
  inputMax,
  inputMin,
  labelMax,
  labelMin,
}

เราต้องการเก็บค่าที่ใช้ในการปรับให้เป็นมาตรฐานระหว่างการฝึกไว้ เพื่อให้เราสามารถยกเลิกการปรับเอาต์พุตให้เป็นมาตรฐานเพื่อนำกลับไปใช้ในสเกลเดิม และเพื่อให้เราสามารถปรับข้อมูลอินพุตในอนาคตให้เป็นมาตรฐานในลักษณะเดียวกันได้

6. ฝึกโมเดล

เมื่อสร้างอินสแตนซ์โมเดลและแสดงข้อมูลเป็นเทนเซอร์แล้ว เราก็พร้อมที่จะเริ่มกระบวนการฝึก

96914ff65fc3b74c.png คัดลอกฟังก์ชันต่อไปนี้ลงใน

script.js file

async function trainModel(model, inputs, labels) {
  // Prepare the model for training.
  model.compile({
    optimizer: tf.train.adam(),
    loss: tf.losses.meanSquaredError,
    metrics: ['mse'],
  });

  const batchSize = 32;
  const epochs = 50;

  return await model.fit(inputs, labels, {
    batchSize,
    epochs,
    shuffle: true,
    callbacks: tfvis.show.fitCallbacks(
      { name: 'Training Performance' },
      ['loss', 'mse'],
      { height: 200, callbacks: ['onEpochEnd'] }
    )
  });
}

มาดูรายละเอียดกัน

เตรียมพร้อมสำหรับการฝึก

// Prepare the model for training.
model.compile({
  optimizer: tf.train.adam(),
  loss: tf.losses.meanSquaredError,
  metrics: ['mse'],
});

เราต้อง "คอมไพล์" โมเดลก่อนที่จะฝึก เราจึงต้องระบุสิ่งสำคัญบางอย่างดังนี้

  • optimizer: นี่คืออัลกอริทึมที่จะควบคุมการอัปเดตโมเดลเมื่อเห็นตัวอย่าง TensorFlow.js มีตัวเพิ่มประสิทธิภาพมากมายให้ใช้งาน ในที่นี้เราเลือกใช้ตัวเพิ่มประสิทธิภาพ Adam เนื่องจากมีประสิทธิภาพค่อนข้างมากในทางปฏิบัติและไม่ต้องมีการกำหนดค่า
  • loss: ฟังก์ชันนี้จะบอกโมเดลว่าโมเดลเรียนรู้แต่ละกลุ่ม (ชุดข้อมูลย่อย) ที่แสดงได้ดีเพียงใด ในที่นี้ เราใช้ meanSquaredError เพื่อเปรียบเทียบการคาดการณ์ที่โมเดลสร้างขึ้นกับค่าจริง
const batchSize = 32;
const epochs = 50;

จากนั้นเราจะเลือก batchSize และจํานวน Epoch ดังนี้

  • batchSize หมายถึงขนาดของชุดข้อมูลย่อยที่โมเดลจะเห็นในการฝึกแต่ละครั้ง โดยทั่วไปแล้ว ขนาดกลุ่มมักจะอยู่ในช่วง 32-512 ไม่มีขนาดกลุ่มที่เหมาะสมอย่างแท้จริงสำหรับทุกปัญหา และการอธิบายแรงจูงใจทางคณิตศาสตร์สำหรับขนาดกลุ่มต่างๆ นั้นอยู่นอกเหนือขอบเขตของบทแนะนำนี้
  • epochs หมายถึงจำนวนครั้งที่โมเดลจะดูชุดข้อมูลทั้งหมดที่คุณให้ ในที่นี้ เราจะทำการวนซ้ำ 50 ครั้งผ่านชุดข้อมูล

เริ่มการวนซ้ำของรถไฟ

return await model.fit(inputs, labels, {
  batchSize,
  epochs,
  callbacks: tfvis.show.fitCallbacks(
    { name: 'Training Performance' },
    ['loss', 'mse'],
    { height: 200, callbacks: ['onEpochEnd'] }
  )
});

model.fit คือฟังก์ชันที่เราเรียกใช้เพื่อเริ่มลูปการฝึก ฟังก์ชันนี้เป็นฟังก์ชันแบบไม่พร้อมกัน ดังนั้นเราจึงส่งคืน Promise ที่ฟังก์ชันนี้ให้เราเพื่อให้ผู้เรียกสามารถระบุได้ว่าการฝึกเสร็จสมบูรณ์เมื่อใด

เราจะส่งการเรียกกลับบางรายการไปยัง model.fit เพื่อตรวจสอบความคืบหน้าในการฝึก เราใช้ tfvis.show.fitCallbacks เพื่อสร้างฟังก์ชันที่สร้างแผนภูมิสำหรับเมตริก "loss" และ "mse" ที่เราระบุไว้ก่อนหน้านี้

นำข้อมูลทุกอย่างมารวมกัน

ตอนนี้เราต้องเรียกใช้ฟังก์ชันที่เรากำหนดจากฟังก์ชัน run

96914ff65fc3b74c.png เพิ่มโค้ดต่อไปนี้ที่ด้านล่างของ

run ฟังก์ชัน

// Convert the data to a form we can use for training.
const tensorData = convertToTensor(data);
const {inputs, labels} = tensorData;

// Train the model
await trainModel(model, inputs, labels);
console.log('Done Training');

เมื่อรีเฟรชหน้าเว็บ คุณจะเห็นกราฟต่อไปนี้อัปเดตหลังจากผ่านไป 2-3 วินาที

c6d3214d6e8c3752.png

โดยจะสร้างขึ้นจากฟังก์ชันเรียกกลับที่เราสร้างไว้ก่อนหน้านี้ โดยจะแสดงการสูญเสียและ MSE ซึ่งหาค่าเฉลี่ยจากทั้งชุดข้อมูลเมื่อสิ้นสุดแต่ละยุค

เมื่อฝึกโมเดล เราต้องการให้ค่าการสูญเสียลดลง ในกรณีนี้ เนื่องจากเมตริกของเราเป็นการวัดข้อผิดพลาด เราจึงต้องการให้เมตริกลดลงด้วย

7. ทำการคาดการณ์

ตอนนี้โมเดลได้รับการฝึกแล้ว เราจึงต้องการทำการคาดการณ์ มาประเมินโมเดลโดยดูว่าโมเดลคาดการณ์อะไรสำหรับช่วงตัวเลขที่สม่ำเสมอของแรงม้าต่ำถึงสูง

96914ff65fc3b74c.png เพิ่มฟังก์ชันต่อไปนี้ลงในไฟล์ script.js

function testModel(model, inputData, normalizationData) {
  const {inputMax, inputMin, labelMin, labelMax} = normalizationData;

  // Generate predictions for a uniform range of numbers between 0 and 1;
  // We un-normalize the data by doing the inverse of the min-max scaling
  // that we did earlier.
  const [xs, preds] = tf.tidy(() => {

    const xsNorm = tf.linspace(0, 1, 100);
    const predictions = model.predict(xsNorm.reshape([100, 1]));

    const unNormXs = xsNorm
      .mul(inputMax.sub(inputMin))
      .add(inputMin);

    const unNormPreds = predictions
      .mul(labelMax.sub(labelMin))
      .add(labelMin);

    // Un-normalize the data
    return [unNormXs.dataSync(), unNormPreds.dataSync()];
  });


  const predictedPoints = Array.from(xs).map((val, i) => {
    return {x: val, y: preds[i]}
  });

  const originalPoints = inputData.map(d => ({
    x: d.horsepower, y: d.mpg,
  }));


  tfvis.render.scatterplot(
    {name: 'Model Predictions vs Original Data'},
    {values: [originalPoints, predictedPoints], series: ['original', 'predicted']},
    {
      xLabel: 'Horsepower',
      yLabel: 'MPG',
      height: 300
    }
  );
}

สิ่งที่คุณควรทราบเกี่ยวกับฟังก์ชันด้านบนมีดังนี้

const xsNorm = tf.linspace(0, 1, 100);
const predictions = model.predict(xsNorm.reshape([100, 1]));

เราสร้าง "ตัวอย่าง" ใหม่ 100 รายการเพื่อป้อนให้กับโมเดล Model.predict คือวิธีที่เราป้อนตัวอย่างเหล่านั้นลงในโมเดล โปรดทราบว่ารูปภาพต้องมีรูปร่างคล้ายกัน ([num_examples, num_features_per_example]) กับตอนที่เราทำการฝึก

// Un-normalize the data
const unNormXs = xsNorm
  .mul(inputMax.sub(inputMin))
  .add(inputMin);

const unNormPreds = predictions
  .mul(labelMax.sub(labelMin))
  .add(labelMin);

หากต้องการนำข้อมูลกลับไปยังช่วงเดิม (ไม่ใช่ 0-1) เราจะใช้ค่าที่คำนวณขณะทำการปรับให้เป็นมาตรฐาน แต่จะกลับการดำเนินการ

return [unNormXs.dataSync(), unNormPreds.dataSync()];

.dataSync() เป็นวิธีที่เราใช้เพื่อรับ typedarray ของค่าที่จัดเก็บไว้ในเทนเซอร์ ซึ่งช่วยให้เราประมวลผลค่าเหล่านั้นใน JavaScript ปกติได้ นี่คือเวอร์ชันแบบซิงโครนัสของเมธอด .data() ซึ่งโดยทั่วไปแล้วเราขอแนะนำให้ใช้

สุดท้าย เราใช้ tfjs-vis เพื่อพล็อตข้อมูลต้นฉบับและการคาดการณ์จากโมเดล

96914ff65fc3b74c.png เพิ่มโค้ดต่อไปนี้ลงใน

run ฟังก์ชัน

// Make some predictions using the model and compare them to the
// original data
testModel(model, data, tensorData);

รีเฟรชหน้าเว็บ แล้วคุณจะเห็นข้อความคล้ายกับข้อความต่อไปนี้เมื่อโมเดลฝึกเสร็จ

fe610ff34708d4a.png

ยินดีด้วย คุณเพิ่งฝึกโมเดลแมชชีนเลิร์นนิงอย่างง่าย ปัจจุบันฟีเจอร์นี้จะดำเนินการที่เรียกว่าการถดถอยเชิงเส้น ซึ่งพยายามปรับเส้นให้เข้ากับแนวโน้มที่มีอยู่ในข้อมูลอินพุต

8. สรุปประเด็นสำคัญ

ขั้นตอนในการฝึกโมเดลแมชชีนเลิร์นนิงมีดังนี้

กำหนดรูปแบบงาน

  • เป็นปัญหาการถดถอยหรือการแยกประเภท
  • สามารถทำได้ด้วยการเรียนรู้แบบมีผู้ดูแลหรือการเรียนรู้แบบไม่มีผู้ดูแล
  • ข้อมูลอินพุตมีรูปร่างอย่างไร ข้อมูลเอาต์พุตควรมีลักษณะอย่างไร

เตรียมข้อมูล

  • ล้างข้อมูลและตรวจสอบรูปแบบด้วยตนเองเมื่อเป็นไปได้
  • สับเปลี่ยนข้อมูลก่อนนำไปใช้ในการฝึก
  • ปรับข้อมูลให้อยู่ในช่วงที่สมเหตุสมผลสำหรับโครงข่ายประสาทเทียม โดยปกติแล้ว 0-1 หรือ -1-1 เป็นช่วงที่ดีสำหรับข้อมูลตัวเลข
  • แปลงข้อมูลเป็นเทนเซอร์

สร้างและเรียกใช้โมเดล

  • กำหนดโมเดลโดยใช้ tf.sequential หรือ tf.model จากนั้นเพิ่มเลเยอร์โดยใช้ tf.layers.*
  • เลือกตัวเพิ่มประสิทธิภาพ ( โดยปกติแล้ว adam เป็นตัวเลือกที่ดี) และพารามิเตอร์ เช่น ขนาดกลุ่มและจำนวน Epoch
  • เลือกฟังก์ชันการสูญเสียที่เหมาะสมสำหรับปัญหาของคุณ และเมตริกความแม่นยำเพื่อช่วยประเมินความคืบหน้า meanSquaredError เป็นฟังก์ชันการสูญเสียที่ใช้กันทั่วไปสำหรับปัญหาการถดถอย
  • ตรวจสอบการฝึกเพื่อดูว่าการสูญเสียลดลงหรือไม่

ประเมินโมเดล

  • เลือกเมตริกการประเมินสำหรับโมเดลที่คุณตรวจสอบได้ขณะฝึก เมื่อฝึกโมเดลแล้ว ให้ลองทำการคาดการณ์ทดสอบเพื่อดูคุณภาพการคาดการณ์

9. เครดิตพิเศษ: สิ่งที่ควรลอง

  • ทดลองเปลี่ยนจำนวน Epoch คุณต้องใช้กี่ยุคก่อนที่กราฟจะแบนราบ
  • ทดลองเพิ่มจำนวนหน่วยในเลเยอร์ที่ซ่อนอยู่
  • ทดลองเพิ่มเลเยอร์ที่ซ่อนอยู่มากขึ้นระหว่างเลเยอร์ที่ซ่อนอยู่แรกที่เราเพิ่มและเลเยอร์เอาต์พุตสุดท้าย โค้ดสำหรับเลเยอร์เพิ่มเติมเหล่านี้ควรมีลักษณะดังนี้
model.add(tf.layers.dense({units: 50, activation: 'sigmoid'}));

สิ่งใหม่ที่สำคัญที่สุดเกี่ยวกับเลเยอร์ที่ซ่อนอยู่เหล่านี้คือการนำฟังก์ชันการเปิดใช้งานแบบไม่เชิงเส้นมาใช้ ซึ่งในกรณีนี้คือการเปิดใช้งาน sigmoid ดูข้อมูลเพิ่มเติมเกี่ยวกับฟังก์ชันการกระตุ้นได้ที่บทความนี้

ดูว่าคุณสามารถทำให้โมเดลสร้างเอาต์พุตได้เหมือนในรูปภาพด้านล่างหรือไม่

a21c5e6537cf81d.png