ดูการสาธิต #MadeWithTFJS ใหม่ที่แสดงต่อไปของเราและบอกสดในวันที่ 1 ต.ค. 09:00 PT ดูบน YouTube

แบบฝึก

คู่มือนี้จะถือว่าคุณได้อ่านแล้ว รุ่นและชั้น คู่มือ

ใน TensorFlow.js มีสองวิธีในการฝึกโมเดลการเรียนรู้ของเครื่อง:

  1. ใช้เลเยอร์ API กับ LayersModel.fit() หรือ LayersModel.fitDataset()
  2. โดยใช้หลัก API กับ Optimizer.minimize()

อันดับแรก เราจะดู Layers API ซึ่งเป็น API ระดับสูงกว่าสำหรับการสร้างและฝึกโมเดล จากนั้นเราจะแสดงวิธีฝึกโมเดลเดียวกันโดยใช้ Core API

บทนำ

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

การฝึกอบรมเกี่ยวข้องกับหลายขั้นตอน:

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

โมเดลที่ได้รับการฝึกอบรมมาอย่างดีจะให้การแมปที่แม่นยำจากอินพุตไปยังเอาต์พุตที่ต้องการ

พารามิเตอร์โมเดล

มากำหนดโมเดล 2 ชั้นอย่างง่ายโดยใช้ Layers API:

const model = tf.sequential({
 layers: [
   tf.layers.dense({inputShape: [784], units: 32, activation: 'relu'}),
   tf.layers.dense({units: 10, activation: 'softmax'}),
 ]
});

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

model.weights.forEach(w => {
 console.log(w.name, w.shape);
});

เราได้รับผลลัพธ์ต่อไปนี้:

> dense_Dense1/kernel [784, 32]
> dense_Dense1/bias [32]
> dense_Dense2/kernel [32, 10]
> dense_Dense2/bias [10]

มีทั้งหมด 4 ตุ้มน้ำหนัก 2 ต่อชั้นหนาแน่น นี้คาดว่าตั้งแต่ชั้นหนาแน่นเป็นตัวแทนของฟังก์ชั่นที่แมปอินพุตเมตริกซ์ x ไปยังเมตริกซ์เอาท์พุท y ผ่านสม y = Ax + b ที่ (kernel) และ A b (อคติ) เป็นพารามิเตอร์ของชั้นความหนาแน่นสูง

หมายเหตุ: โดยค่าเริ่มต้นชั้นหนาแน่น ได้แก่ อคติ แต่คุณสามารถยกเว้นได้โดยระบุ {useBias: false} ในตัวเลือกเมื่อมีการสร้างชั้นหนาแน่น

model.summary() เป็นวิธีที่มีประโยชน์ถ้าคุณต้องการที่จะได้รับภาพรวมของรูปแบบของคุณและดูจำนวนของพารามิเตอร์:

เลเยอร์ (ประเภท) รูปร่างเอาต์พุต พารามิเตอร์ #
หนาแน่น_Dense1 (หนาแน่น) [null,32] 25120
หนาแน่น_หนาแน่น2 (หนาแน่น) [null,10] 330
พารามิเตอร์ทั้งหมด: 25450
Params ที่ฝึกได้: 25450
พารามิเตอร์ที่ไม่สามารถฝึกได้: 0

น้ำหนักในรูปแบบแต่ละส่วนหลังโดย Variable วัตถุ ใน TensorFlow.js เป็น Variable เป็นจุดลอยตัว Tensor ด้วยวิธีการอีกหนึ่ง assign() ใช้สำหรับการปรับปรุงค่าของมัน Layers API จะเริ่มต้นน้ำหนักโดยอัตโนมัติโดยใช้แนวทางปฏิบัติที่ดีที่สุด เพื่อประโยชน์ของการสาธิตเราสามารถเขียนทับน้ำหนักโดยการเรียก assign() บนตัวแปรอ้างอิง:

model.weights.forEach(w => {
  const newVals = tf.randomNormal(w.shape);
  // w.val is an instance of tf.Variable
  w.val.assign(newVals);
});

เครื่องมือเพิ่มประสิทธิภาพ การสูญเสีย และเมตริก

ก่อนที่คุณจะทำการฝึกใดๆ คุณต้องตัดสินใจสามสิ่ง:

  1. เพิ่มประสิทธิภาพ งานของเครื่องมือเพิ่มประสิทธิภาพคือการตัดสินใจว่าจะเปลี่ยนพารามิเตอร์แต่ละตัวในแบบจำลองมากน้อยเพียงใด โดยพิจารณาจากการคาดการณ์แบบจำลองปัจจุบัน เมื่อใช้เลเยอร์ API คุณสามารถให้ทั้งระบุสตริงของการเพิ่มประสิทธิภาพที่มีอยู่ (เช่น 'sgd' หรือ 'adam' ) หรืออินสแตนซ์ของ Optimizer ระดับ
  2. ฟังก์ชั่นการสูญเสีย วัตถุประสงค์ที่ตัวแบบจะพยายามย่อให้เล็กสุด เป้าหมายของมันคือการให้ตัวเลขเดียวสำหรับ "ความผิดพลาด" ของการคาดการณ์ของแบบจำลอง การสูญเสียจะถูกคำนวณจากข้อมูลทุกชุดเพื่อให้โมเดลสามารถอัปเดตน้ำหนักได้ เมื่อใช้เลเยอร์ API คุณสามารถให้ทั้งระบุสตริงของฟังก์ชั่นการสูญเสียที่มีอยู่ (เช่น 'categoricalCrossentropy' ) หรือฟังก์ชั่นใด ๆ ที่ใช้คาดการณ์และมูลค่าที่แท้จริงและผลตอบแทนการสูญเสีย ดู รายการของการสูญเสียที่มีอยู่ ในเอกสาร API ของเรา
  3. รายการเมตริก คล้ายกับการสูญเสีย เมตริกคำนวณตัวเลขเดียว โดยสรุปว่าแบบจำลองของเราทำงานได้ดีเพียงใด เมตริกมักจะคำนวณจากข้อมูลทั้งหมดเมื่อสิ้นสุดแต่ละยุค อย่างน้อยที่สุด เราต้องการติดตามว่าการสูญเสียของเราลดลงเมื่อเวลาผ่านไป อย่างไรก็ตาม เรามักต้องการเมตริกที่เป็นมิตรต่อมนุษย์ เช่น ความแม่นยำ เมื่อใช้เลเยอร์ API คุณสามารถให้ทั้งระบุสตริงของที่มีอยู่ตัวชี้วัด (เช่น 'accuracy' ) หรือฟังก์ชั่นใด ๆ ที่ใช้คาดการณ์และมูลค่าที่แท้จริงและผลตอบแทนคะแนน ดู รายชื่อของตัวชี้วัดที่มีอยู่ ในเอกสาร API ของเรา

เมื่อคุณได้ตัดสินใจรวบรวม LayersModel โดยการเรียก model.compile() ที่มีตัวเลือกให้:

model.compile({
  optimizer: 'sgd',
  loss: 'categoricalCrossentropy',
  metrics: ['accuracy']
});

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

การฝึกอบรม

มีสองวิธีในการฝึกอบรมเป็น LayersModel :

  • ใช้ model.fit() และการให้ข้อมูลเป็นเมตริกซ์ขนาดใหญ่หนึ่ง
  • ใช้ model.fitDataset() และการให้ข้อมูลผ่านทาง Dataset วัตถุ

รุ่นพอดี()

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

// Generate dummy data.
const data = tf.randomNormal([100, 784]);
const labels = tf.randomUniform([100, 10]);

function onBatchEnd(batch, logs) {
  console.log('Accuracy', logs.acc);
}

// Train for 5 epochs with batch size of 32.
model.fit(data, labels, {
   epochs: 5,
   batchSize: 32,
   callbacks: {onBatchEnd}
 }).then(info => {
   console.log('Final accuracy', info.history.acc);
 });

ภายใต้ประทุน, model.fit() สามารถทำมากสำหรับเรา:

  • แยกข้อมูลออกเป็นชุดฝึกอบรมและชุดการตรวจสอบ และใช้ชุดการตรวจสอบความถูกต้องเพื่อวัดความคืบหน้าระหว่างการฝึก
  • สับเปลี่ยนข้อมูลแต่หลังจากแยกแล้วเท่านั้น เพื่อความปลอดภัยคุณควรก่อนสับข้อมูลก่อนที่จะผ่านไป fit()
  • แยกเมตริกซ์ข้อมูลที่มีขนาดใหญ่เป็นเทนเซอร์ขนาดเล็กขนาด batchSize.
  • โทร optimizer.minimize() ในขณะที่การคำนวณการสูญเสียของรูปแบบด้วยความเคารพชุดของข้อมูล
  • มันสามารถแจ้งให้คุณทราบเมื่อเริ่มต้นและสิ้นสุดของแต่ละยุคหรือแบทช์ ในกรณีของเราเราได้รับแจ้งในตอนท้ายของทุกชุดโดยใช้ callbacks.onBatchEnd ตัวเลือก ตัวเลือกอื่น ๆ ได้แก่ : onTrainBegin , onTrainEnd , onEpochBegin , onEpochEnd และ onBatchBegin
  • มันให้ผลกับเธรดหลักเพื่อให้แน่ใจว่างานที่อยู่ในคิวในลูปเหตุการณ์ JS สามารถจัดการได้ทันท่วงที

สำหรับข้อมูลเพิ่มเติมโปรดดูที่ เอกสาร ของ fit() โปรดทราบว่าหากคุณเลือกใช้ Core API คุณจะต้องใช้ตรรกะนี้ด้วยตนเอง

model.fitDataset()

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

function* data() {
 for (let i = 0; i < 100; i++) {
   // Generate one sample at a time.
   yield tf.randomNormal([784]);
 }
}

function* labels() {
 for (let i = 0; i < 100; i++) {
   // Generate one sample at a time.
   yield tf.randomUniform([10]);
 }
}

const xs = tf.data.generator(data);
const ys = tf.data.generator(labels);
// We zip the data and labels together, shuffle and batch 32 samples at a time.
const ds = tf.data.zip({xs, ys}).shuffle(100 /* bufferSize */).batch(32);

// Train the model for 5 epochs.
model.fitDataset(ds, {epochs: 5}).then(info => {
 console.log('Accuracy', info.history.acc);
});

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับชุดข้อมูลให้ดูที่ เอกสาร ของ model.fitDataset()

การทำนายข้อมูลใหม่

เมื่อรูปแบบที่ได้รับการฝึกอบรมที่คุณสามารถเรียก model.predict() ที่จะทำให้การคาดการณ์เกี่ยวกับข้อมูลที่มองไม่เห็น:

// Predict 3 random samples.
const prediction = model.predict(tf.randomNormal([3, 784]));
prediction.print();

Core API

ก่อนหน้านี้ เรากล่าวว่ามีสองวิธีในการฝึกโมเดลการเรียนรู้ของเครื่องใน TensorFlow.js

กฎทั่วไปคือพยายามใช้ Layers API ก่อน เนื่องจากมีการสร้างแบบจำลองตาม Keras API ที่ได้รับการยอมรับอย่างดี Layers API ยังนำเสนอโซลูชั่นต่างๆ ที่พร้อมใช้งานได้ทันที เช่น การเริ่มต้นน้ำหนัก การทำซีเรียลไลซ์โมเดล การฝึกตรวจสอบ การพกพา และการตรวจสอบความปลอดภัย

คุณอาจต้องการใช้ Core API เมื่อใดก็ตามที่:

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

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ API นี้อ่านส่วน "แกน API" ใน รุ่นและเลเยอร์ คู่มือ

โมเดลเดียวกับด้านบนที่เขียนโดยใช้ Core API มีลักษณะดังนี้:

// The weights and biases for the two dense layers.
const w1 = tf.variable(tf.randomNormal([784, 32]));
const b1 = tf.variable(tf.randomNormal([32]));
const w2 = tf.variable(tf.randomNormal([32, 10]));
const b2 = tf.variable(tf.randomNormal([10]));

function model(x) {
  return x.matMul(w1).add(b1).relu().matMul(w2).add(b2);
}

นอกจาก Layers API แล้ว Data API ยังทำงานร่วมกับ Core API ได้อย่างราบรื่น ลองนำมาใช้ชุดข้อมูลที่เรากำหนดไว้ก่อนหน้านี้ใน model.fitDataset () ส่วนซึ่งไม่สับและผสมเรา:

const xs = tf.data.generator(data);
const ys = tf.data.generator(labels);
// Zip the data and labels together, shuffle and batch 32 samples at a time.
const ds = tf.data.zip({xs, ys}).shuffle(100 /* bufferSize */).batch(32);

มาฝึกโมเดลกันเถอะ:

const optimizer = tf.train.sgd(0.1 /* learningRate */);
// Train for 5 epochs.
for (let epoch = 0; epoch < 5; epoch++) {
  await ds.forEachAsync(({xs, ys}) => {
    optimizer.minimize(() => {
      const predYs = model(xs);
      const loss = tf.losses.softmaxCrossEntropy(ys, predYs);
      loss.data().then(l => console.log('Loss', l));
      return loss;
    });
  });
  console.log('Epoch', epoch);
}

โค้ดด้านบนเป็นสูตรมาตรฐานเมื่อฝึกโมเดลด้วย Core API:

  • วนซ้ำจำนวนยุค
  • ภายในแต่ละยุค ให้วนซ้ำชุดข้อมูลของคุณ เมื่อใช้ Dataset , dataset.forEachAsync() เป็นวิธีที่สะดวกห่วงมากกว่าแบตช์ของคุณ
  • สำหรับแต่ละชุดโทร optimizer.minimize(f) ซึ่งดำเนิน f และลดการส่งออกของตนโดยการไล่ระดับสีการคำนวณเกี่ยวกับตัวแปรที่สี่ที่เรากำหนดไว้ก่อนหน้านี้
  • f คำนวณการสูญเสีย มันเรียกหนึ่งในฟังก์ชันการสูญเสียที่กำหนดไว้ล่วงหน้าโดยใช้การคาดการณ์ของแบบจำลองและมูลค่าที่แท้จริง