1. บทนำ
ในโค้ดแล็บนี้ คุณจะได้ฝึกโมเดลเพื่อทำการคาดการณ์จากข้อมูลตัวเลขที่อธิบายชุดรถยนต์
แบบฝึกหัดนี้จะแสดงขั้นตอนที่ใช้กันทั่วไปในการฝึกโมเดลหลายประเภท แต่จะใช้ชุดข้อมูลขนาดเล็กและโมเดลอย่างง่าย (แบบตื้น) เป้าหมายหลักคือการช่วยให้คุณคุ้นเคยกับคำศัพท์ แนวคิด และไวยากรณ์พื้นฐานเกี่ยวกับการฝึกโมเดลด้วย TensorFlow.js รวมถึงเป็นก้าวแรกในการสำรวจและเรียนรู้เพิ่มเติม
เนื่องจากเรากำลังฝึกโมเดลเพื่อคาดการณ์ตัวเลขต่อเนื่อง งานนี้จึงอาจเรียกว่างานการถดถอย เราจะฝึกโมเดลโดยแสดงตัวอย่างอินพุตจำนวนมากพร้อมกับเอาต์พุตที่ถูกต้อง ซึ่งเรียกว่าการเรียนรู้ที่มีการควบคุมดูแล
สิ่งที่คุณจะสร้าง
คุณจะสร้างหน้าเว็บที่ใช้ TensorFlow.js เพื่อฝึกโมเดลในเบราว์เซอร์ เมื่อได้รับ "แรงม้า" สำหรับรถยนต์ โมเดลจะเรียนรู้ที่จะคาดการณ์ "ไมล์ต่อแกลลอน" (MPG)
โดยทำดังนี้
- โหลดข้อมูลและเตรียมข้อมูลสำหรับการฝึก
- กำหนดสถาปัตยกรรมของโมเดล
- ฝึกโมเดลและตรวจสอบประสิทธิภาพขณะฝึก
- ประเมินโมเดลที่ฝึกแล้วโดยทำการคาดการณ์
สิ่งที่คุณจะได้เรียนรู้
- แนวทางปฏิบัติแนะนำในการจัดเตรียมข้อมูลสำหรับแมชชีนเลิร์นนิง ซึ่งรวมถึงการสับเปลี่ยนและการทำให้เป็นมาตรฐาน
- ไวยากรณ์ TensorFlow.js สำหรับการสร้างโมเดลโดยใช้ tf.layers API
- วิธีตรวจสอบการฝึกในเบราว์เซอร์โดยใช้ไลบรารี tfjs-vis
สิ่งที่คุณต้องมี
- Chrome หรือเบราว์เซอร์สมัยใหม่อื่นๆ เวอร์ชันล่าสุด
- โปรแกรมแก้ไขข้อความที่ทำงานในเครื่องของคุณหรือบนเว็บผ่านเครื่องมืออย่าง Codepen หรือ Glitch
- ความรู้เกี่ยวกับ HTML, CSS, JavaScript และเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome (หรือเครื่องมือสำหรับนักพัฒนาเว็บของเบราว์เซอร์ที่คุณต้องการ)
- ความเข้าใจเชิงแนวคิดระดับสูงเกี่ยวกับโครงข่ายประสาทเทียม หากต้องการดูข้อมูลเบื้องต้นหรือทบทวน โปรดดูวิดีโอนี้จาก 3blue1brown หรือวิดีโอเกี่ยวกับการเรียนรู้เชิงลึกใน JavaScript โดย Ashi Krishnan
2. ตั้งค่า
สร้างหน้า HTML และใส่ JavaScript
คัดลอกโค้ดต่อไปนี้ลงในไฟล์ 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 สำหรับโค้ด
- ในโฟลเดอร์เดียวกับไฟล์ HTML ด้านบน ให้สร้างไฟล์ชื่อ script.js แล้ววางโค้ดต่อไปนี้ลงในไฟล์
console.log('Hello TensorFlow');
ทดสอบเลย
ตอนนี้คุณได้สร้างไฟล์ HTML และ JavaScript แล้ว ให้ทดสอบไฟล์เหล่านั้น เปิดไฟล์ index.html ในเบราว์เซอร์และเปิดคอนโซลเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์
หากทุกอย่างทำงานได้ตามปกติ ควรมีตัวแปรส่วนกลาง 2 รายการที่สร้างขึ้นและพร้อมใช้งานในคอนโซลเครื่องมือสำหรับนักพัฒนาเว็บ ดังนี้
tfคือการอ้างอิงถึงไลบรารี TensorFlow.jstfvisเป็นการอ้างอิงถึงไลบรารี tfjs-vis
เปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ของเบราว์เซอร์ คุณควรเห็นข้อความที่ระบุว่า Hello TensorFlow ในเอาต์พุตของคอนโซล หากเป็นเช่นนั้น คุณก็พร้อมที่จะไปยังขั้นตอนถัดไป
3. โหลด จัดรูปแบบ และแสดงภาพข้อมูลอินพุต
ขั้นตอนแรกคือการโหลด จัดรูปแบบ และแสดงภาพข้อมูลที่เราต้องการใช้ฝึกโมเดล
เราจะโหลดชุดข้อมูล "รถยนต์" จากไฟล์ JSON ที่เราโฮสต์ไว้ให้คุณ ซึ่งมีฟีเจอร์ต่างๆ มากมายเกี่ยวกับรถแต่ละคัน สำหรับบทแนะนำนี้ เราต้องการดึงข้อมูลเกี่ยวกับแรงม้าและไมล์ต่อแกลลอนเท่านั้น
เพิ่มโค้ดต่อไปนี้ลงใน
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;
}
การดำเนินการนี้จะนำรายการที่ไม่ได้กำหนดทั้งไมล์ต่อแกลลอนหรือแรงม้าออกด้วย นอกจากนี้ เรายังจะพล็อตข้อมูลนี้ในแผนภูมิกระจายเพื่อดูว่ามีลักษณะอย่างไร
เพิ่มโค้ดต่อไปนี้ที่ด้านล่างของ
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);
เมื่อคุณรีเฟรชหน้า คุณควรเห็นแผงทางด้านซ้ายมือของหน้าเว็บที่มีแผนภูมิกระจายของข้อมูล ซึ่งควรมีหน้าตาเช่นนี้

แผงนี้เรียกว่า "แผงควบคุม" และจัดทำโดย tfjs-vis ซึ่งเป็นที่ที่สะดวกในการแสดงภาพข้อมูล
โดยทั่วไปแล้ว เมื่อทำงานกับข้อมูล คุณควรหาวิธีดูข้อมูลและล้างข้อมูลหากจำเป็น ในกรณีนี้ เราจึงต้องนำข้อมูลบางรายการออกจาก carsData ที่ไม่มีช่องที่จำเป็นทั้งหมด การแสดงข้อมูลด้วยภาพจะช่วยให้เราทราบว่าข้อมูลมีโครงสร้างใดที่โมเดลสามารถเรียนรู้ได้หรือไม่
จากแผนภาพด้านบน เราจะเห็นว่าแรงม้าและ MPG มีความสัมพันธ์ในเชิงลบ กล่าวคือ เมื่อแรงม้าเพิ่มขึ้น รถยนต์มักจะวิ่งได้ระยะทางต่อแกลลอนน้อยลง
กำหนดแนวคิดของงาน
ตอนนี้ข้อมูลนำเข้าของเราจะมีลักษณะดังนี้
...
{
"mpg":15,
"horsepower":165,
},
{
"mpg":18,
"horsepower":150,
},
{
"mpg":16,
"horsepower":150,
},
...
เป้าหมายของเราคือการฝึกโมเดลที่จะรับตัวเลขหนึ่งแรงม้า และเรียนรู้ที่จะคาดการณ์ตัวเลขหนึ่งไมล์ต่อแกลลอน โปรดทราบว่าการแมปแบบหนึ่งต่อหนึ่งนี้จะมีความสำคัญต่อส่วนถัดไป
เราจะป้อนตัวอย่างเหล่านี้ ซึ่งก็คือแรงม้าและ MPG ให้กับโครงข่ายประสาทที่จะเรียนรู้จากตัวอย่างเหล่านี้เป็นสูตร (หรือฟังก์ชัน) เพื่อคาดการณ์ MPG ที่กำหนดแรงม้า การเรียนรู้จากตัวอย่างที่เรามีคำตอบที่ถูกต้องเรียกว่าการเรียนรู้ที่มีการควบคุมดูแล
4. กำหนดสถาปัตยกรรมโมเดล
ในส่วนนี้ เราจะเขียนโค้ดเพื่ออธิบายสถาปัตยกรรมของโมเดล สถาปัตยกรรมโมเดลเป็นเพียงวิธีที่ดูดีในการพูดว่า "โมเดลจะเรียกใช้ฟังก์ชันใดเมื่อดำเนินการ" หรืออีกนัยหนึ่งคือ "โมเดลจะใช้อัลกอริทึมใดในการคำนวณคำตอบ"
โมเดล ML คืออัลกอริทึมที่รับอินพุตและสร้างเอาต์พุต เมื่อใช้โครงข่ายประสาทเทียม อัลกอริทึมคือชุดเลเยอร์ของนิวรอนที่มี "น้ำหนัก" (ตัวเลข) ซึ่งควบคุมเอาต์พุต กระบวนการฝึกจะเรียนรู้ค่าที่เหมาะสมที่สุดสำหรับน้ำหนักเหล่านั้น
เพิ่มฟังก์ชันต่อไปนี้ลงใน
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
สร้างอินสแตนซ์
เพิ่มโค้ดต่อไปนี้ลงใน
run ฟังก์ชันที่เรากำหนดไว้ก่อนหน้านี้
// Create the model
const model = createModel();
tfvis.show.modelSummary({name: 'Model Summary'}, model);
การดำเนินการนี้จะสร้างอินสแตนซ์ของโมเดลและแสดงข้อมูลสรุปของเลเยอร์ในหน้าเว็บ
5. เตรียมข้อมูลสำหรับการฝึก
หากต้องการรับประโยชน์ด้านประสิทธิภาพของ TensorFlow.js ที่ทำให้การฝึกโมเดลแมชชีนเลิร์นนิงเป็นไปได้จริง เราต้องแปลงข้อมูลเป็นเทนเซอร์ นอกจากนี้ เราจะทำการเปลี่ยนรูปแบบข้อมูลตามแนวทางปฏิบัติแนะนำหลายอย่าง ได้แก่ การสับเปลี่ยนและการปรับให้เป็นมาตรฐาน
เพิ่มโค้ดต่อไปนี้ลงใน
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. ฝึกโมเดล
เมื่อสร้างอินสแตนซ์โมเดลและแสดงข้อมูลเป็นเทนเซอร์แล้ว เราก็พร้อมที่จะเริ่มกระบวนการฝึก
คัดลอกฟังก์ชันต่อไปนี้ลงใน
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
เพิ่มโค้ดต่อไปนี้ที่ด้านล่างของ
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 วินาที

โดยจะสร้างขึ้นจากฟังก์ชันเรียกกลับที่เราสร้างไว้ก่อนหน้านี้ โดยจะแสดงการสูญเสียและ MSE ซึ่งหาค่าเฉลี่ยจากทั้งชุดข้อมูลเมื่อสิ้นสุดแต่ละยุค
เมื่อฝึกโมเดล เราต้องการให้ค่าการสูญเสียลดลง ในกรณีนี้ เนื่องจากเมตริกของเราเป็นการวัดข้อผิดพลาด เราจึงต้องการให้เมตริกลดลงด้วย
7. ทำการคาดการณ์
ตอนนี้โมเดลได้รับการฝึกแล้ว เราจึงต้องการทำการคาดการณ์ มาประเมินโมเดลโดยดูว่าโมเดลคาดการณ์อะไรสำหรับช่วงตัวเลขที่สม่ำเสมอของแรงม้าต่ำถึงสูง
เพิ่มฟังก์ชันต่อไปนี้ลงในไฟล์ 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 เพื่อพล็อตข้อมูลต้นฉบับและการคาดการณ์จากโมเดล
เพิ่มโค้ดต่อไปนี้ลงใน
run ฟังก์ชัน
// Make some predictions using the model and compare them to the
// original data
testModel(model, data, tensorData);
รีเฟรชหน้าเว็บ แล้วคุณจะเห็นข้อความคล้ายกับข้อความต่อไปนี้เมื่อโมเดลฝึกเสร็จ

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