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

1. บทนำ

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

แบบฝึกหัดนี้จะสาธิตขั้นตอนที่เกิดขึ้นบ่อยในการฝึกโมเดลประเภทต่างๆ แต่จะใช้ชุดข้อมูลขนาดเล็กและโมเดลง่ายๆ (ตื้น) เป้าหมายหลักคือการช่วยให้คุณคุ้นเคยกับคำศัพท์พื้นฐาน แนวคิด และไวยากรณ์เกี่ยวกับโมเดลการฝึกด้วย 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 ในเบราว์เซอร์และเปิดคอนโซล Devtools

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

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

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

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

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

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

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

script.js ไฟล์

/**
 * 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 ไฟล์

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

แผงนี้เรียกว่า Visor ซึ่งให้บริการโดย tfjs-vis ซึ่งช่วยให้แสดงการแสดงภาพข้อมูลได้สะดวก

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

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

วางแนวคิดเกี่ยวกับงาน

ข้อมูลที่ป้อนของเราจะมีลักษณะดังนี้

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

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

เราจะป้อนตัวอย่างเหล่านี้ ซึ่งได้แก่ แรงม้า และ 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. เตรียมข้อมูลสำหรับการฝึก

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

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

script.js ไฟล์

/**
 * 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);

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

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

แปลงเป็น Tensor

// 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 รายการ รายการหนึ่งเป็นตัวอย่างอินพุต (รายการแรงม้า) และอีกอาร์เรย์สำหรับค่าเอาต์พุตจริง (เรียกว่าป้ายกำกับในแมชชีนเลิร์นนิง)

จากนั้นเราจะแปลงข้อมูลแต่ละอาร์เรย์เป็น Tensor แบบ 2 มิติ Tensor จะมีรูปร่างเป็น [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 โดยใช้ การปรับขนาดต่ำสุด การทำให้เป็นมาตรฐานเป็นสิ่งสำคัญเนื่องจากภายในของโมเดลแมชชีนเลิร์นนิงจำนวนมากที่คุณจะสร้างด้วย 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. ฝึกโมเดล

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

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

script.js ไฟล์

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;

ต่อไปเราจะเลือก {1/}{1/} และจำนวน 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 คือฟังก์ชันที่เราเรียกใช้เพื่อเริ่มลูปการฝึก ฟังก์ชันนี้ทำงานไม่พร้อมกัน เราจึงให้คำมั่นสัญญาที่แจ้งไว้เพื่อให้ผู้โทรระบุได้ว่าการฝึกเสร็จสมบูรณ์เมื่อใด

เราจะส่งต่อ Callback บางส่วนไปยัง model.fit เพื่อติดตามความคืบหน้าในการฝึก เราใช้ tfvis.show.fitCallbacks เพื่อสร้างฟังก์ชันที่พล็อตแผนภูมิสำหรับ "ภาวะขาดทุน" และ "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

ซึ่งสร้างโดย Callback ที่เราสร้างไว้ก่อนหน้านี้ โดยจะแสดง Loss และ mse โดยเฉลี่ยจากชุดข้อมูลทั้งหมด เมื่อสิ้นสุดแต่ละ Epoch

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

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 ของค่าที่จัดเก็บไว้ใน Tensor ซึ่งจะทำให้เราประมวลผลค่าเหล่านั้นใน 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 จะเป็นช่วงที่ดีสำหรับข้อมูลตัวเลข
  • แปลงข้อมูลเป็น Tensor

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

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

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

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

9. เครดิตเพิ่มเติม: สิ่งที่น่าลอง

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

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

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

a21c5e6537cf81d.png