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

แพลตฟอร์มและสภาพแวดล้อม

TensorFlow.js ทำงานในเบราว์เซอร์และ Node.js และในทั้งสองแพลตฟอร์มมีการกำหนดค่าที่แตกต่างกันมากมาย แต่ละแพลตฟอร์มมีการพิจารณาที่แตกต่างกันซึ่งจะส่งผลต่อวิธีการพัฒนาแอปพลิเคชัน

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

ใน Node.js TensorFlow.js รองรับการเชื่อมโยงโดยตรงกับ TensorFlow API หรือทำงานด้วยการใช้งาน vanilla CPU ที่ช้าลง

สภาพแวดล้อม

เมื่อโปรแกรม TensorFlow.js ถูกเรียกใช้การกำหนดค่าเฉพาะจะเรียกว่าสภาพแวดล้อม สภาพแวดล้อมประกอบด้วยแบ็กเอนด์ส่วนกลางเดียวและชุดของแฟล็กที่ควบคุมคุณลักษณะแบบละเอียดของ TensorFlow.js

แบ็กเอนด์

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

หากต้องการค้นหาแบ็กเอนด์ที่คุณใช้:

console.log(tf.getBackend());

หากคุณต้องการเปลี่ยนแบ็กเอนด์ด้วยตนเอง:

tf.setBackend('cpu');
console.log(tf.getBackend());

แบ็กเอนด์ WebGL

ปัจจุบันแบ็กเอนด์ WebGL ซึ่งเป็น "webgl" เป็นแบ็กเอนด์ที่ทรงพลังที่สุดสำหรับเบราว์เซอร์ แบ็กเอนด์นี้เร็วกว่าแบ็กเอนด์ vanilla CPU ถึง 100 เท่า Tensors จะถูกจัดเก็บเป็นพื้นผิว WebGL และการดำเนินการทางคณิตศาสตร์จะถูกนำไปใช้ใน WebGL Shaders สิ่งที่มีประโยชน์บางประการที่ควรทราบเมื่อใช้แบ็กเอนด์นี้: \

หลีกเลี่ยงการบล็อกเธรด UI

เมื่อมีการเรียกการดำเนินการเช่น tf.matMul (a, b) ผลลัพธ์ tf.Tensor จะถูกส่งกลับแบบซิงโครนัสอย่างไรก็ตามการคำนวณของการคูณเมทริกซ์อาจยังไม่พร้อมจริง ซึ่งหมายความว่า tf. Tensor ที่ส่งคืนเป็นเพียงตัวจัดการในการคำนวณ เมื่อคุณเรียกใช้ x.data() หรือ x.array() ค่าจะแก้ไขเมื่อการคำนวณเสร็จสมบูรณ์จริง สิ่งนี้ทำให้การใช้ x.data() และ x.array() แบบอะซิงโครนัสเป็นสิ่งสำคัญเหนือคู่ของซิงโครนัส x.dataSync() และ x.arraySync() เพื่อหลีกเลี่ยงการบล็อกเธรด UI ในขณะที่การคำนวณเสร็จสิ้น

การจัดการหน่วยความจำ

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

ในการทำลายหน่วยความจำของ tf.Tensor คุณสามารถใช้เมธอด dispose() :

const a = tf.tensor([[1, 2], [3, 4]]);
a.dispose();

เป็นเรื่องปกติมากที่จะเชื่อมโยงการทำงานหลายอย่างเข้าด้วยกันในแอปพลิเคชัน การอ้างอิงถึงตัวแปรกลางทั้งหมดเพื่อกำจัดมันสามารถลดความสามารถในการอ่านโค้ด เพื่อแก้ปัญหานี้ TensorFlow.js มีวิธี tf.tidy() ซึ่งจะล้าง tf.Tensor ทั้งหมดที่ไม่ส่งคืนโดยฟังก์ชันหลังจากเรียกใช้งานคล้ายกับวิธีล้างตัวแปรภายในเมื่อฟังก์ชันถูกเรียกใช้:

const a = tf.tensor([[1, 2], [3, 4]]);
const y = tf.tidy(() => {
  const result = a.square().log().neg();
  return result;
});
ความแม่นยำ

บนอุปกรณ์เคลื่อนที่ WebGL อาจรองรับเฉพาะพื้นผิวทศนิยม 16 บิตเท่านั้น อย่างไรก็ตามโมเดลแมชชีนเลิร์นนิงส่วนใหญ่ได้รับการฝึกฝนด้วยน้ำหนักและการเปิดใช้งานทศนิยม 32 บิต ซึ่งอาจทำให้เกิดปัญหาด้านความแม่นยำเมื่อย้ายโมเดลสำหรับอุปกรณ์เคลื่อนที่เนื่องจากตัวเลขลอยตัว 16 บิตสามารถแสดงเฉพาะตัวเลขในช่วง [0.000000059605, 65504] ซึ่งหมายความว่าคุณควรระมัดระวังว่าน้ำหนักและการเปิดใช้งานในแบบจำลองของคุณจะต้องไม่เกินช่วงนี้ ในการตรวจสอบว่าอุปกรณ์รองรับพื้นผิว 32 บิตหรือไม่ให้ตรวจสอบค่าของ tf.ENV.getBool('WEBGL_RENDER_FLOAT32_CAPABLE') หากเป็นเท็จแสดงว่าอุปกรณ์รองรับเฉพาะพื้นผิวทศนิยม 16 บิตเท่านั้น คุณสามารถใช้ tf.ENV.getBool('WEBGL_RENDER_FLOAT32_ENABLED') เพื่อตรวจสอบว่าขณะนี้ TensorFlow.js ใช้พื้นผิว 32 บิตหรือไม่

การรวบรวม Shader และการอัปโหลดพื้นผิว

TensorFlow.js เรียกใช้การดำเนินการบน GPU โดยเรียกใช้โปรแกรม WebGL shader เฉดสีเหล่านี้ถูกประกอบและคอมไพล์อย่างเฉื่อยชาเมื่อผู้ใช้ขอให้ดำเนินการ การคอมไพล์ของ shader เกิดขึ้นกับ CPU บนเธรดหลักและอาจช้า TensorFlow.js จะแคชเฉดสีที่คอมไพล์โดยอัตโนมัติทำให้การเรียกครั้งที่สองเป็นการดำเนินการเดียวกันกับเทนเซอร์อินพุตและเอาท์พุตที่มีรูปร่างเดียวกันเร็วขึ้นมาก โดยปกติแอปพลิเคชัน TensorFlow.js จะใช้การดำเนินการเดียวกันหลายครั้งตลอดอายุการใช้งานของแอปพลิเคชันดังนั้นการส่งผ่านโมเดลการเรียนรู้ของเครื่องครั้งที่สองจึงเร็วกว่ามาก

TensorFlow.js ยังเก็บข้อมูล tf.Tensor เป็น WebGLTextures เมื่อสร้าง tf.Tensor เราจะไม่อัปโหลดข้อมูลไปยัง GPU ในทันที แต่เราจะเก็บข้อมูลไว้ใน CPU จนกว่าจะใช้ tf.Tensor ในการดำเนินการ หากใช้ tf.Tensor เป็นครั้งที่สองข้อมูลจะอยู่ใน GPU แล้วดังนั้นจึงไม่มีค่าใช้จ่ายในการอัปโหลด ในรูปแบบแมชชีนเลิร์นนิงทั่วไปซึ่งหมายความว่าน้ำหนักจะถูกอัปโหลดในระหว่างการคาดคะเนครั้งแรกผ่านแบบจำลองและการส่งผ่านแบบจำลองครั้งที่สองจะเร็วขึ้นมาก

หากคุณสนใจเกี่ยวกับประสิทธิภาพของการคาดคะเนแรกผ่านโมเดลหรือโค้ด TensorFlow.js ของคุณเราขอแนะนำให้อุ่นโมเดลโดยส่งอินพุต Tensor ที่มีรูปร่างเดียวกันก่อนที่จะใช้ข้อมูลจริง

ตัวอย่างเช่น:

const model = await tf.loadLayersModel(modelUrl);

// Warmup the model before using real data.
const warmupResult = model.predict(tf.zeros(inputShape));
warmupResult.dataSync();
warmupResult.dispose();

// The second predict() will be much faster
const result = model.predict(userData);

Node.js แบ็กเอนด์ TensorFlow

ในแบ็กเอนด์ TensorFlow Node.js "โหนด" TensorFlow C API จะใช้เพื่อเร่งการดำเนินการ ซึ่งจะใช้การเร่งฮาร์ดแวร์ที่มีอยู่ของเครื่องเช่น CUDA หากมี

ในแบ็กเอนด์นี้เช่นเดียวกับแบ็กเอนด์ WebGL การดำเนินการจะส่งคืน tf.Tensor พร้อมกัน อย่างไรก็ตามไม่เหมือนกับแบ็กเอนด์ WebGL การดำเนินการจะเสร็จสิ้นก่อนที่คุณจะได้รับเทนเซอร์กลับคืนมา ซึ่งหมายความว่าการเรียกใช้ tf.matMul(a, b) จะบล็อกเธรด UI

ด้วยเหตุนี้หากคุณต้องการใช้สิ่งนี้ในแอปพลิเคชันที่ใช้งานจริงคุณควรรัน TensorFlow.js ในเธรดของผู้ปฏิบัติงานเพื่อไม่บล็อกเธรดหลัก

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ Node.js โปรดดูคู่มือนี้

แบ็กเอนด์ WASM

TensorFlow.js จัดเตรียม แบ็กเอนด์ WebAssembly ( wasm ) ซึ่งมีการเร่งความเร็วของ CPU และสามารถใช้เป็นทางเลือกแทน vanilla JavaScript CPU ( cpu ) และ WebGL Accelerated ( webgl ) วิธีใช้:

// Set the backend to WASM and wait for the module to be ready.
tf.setBackend('wasm');
tf.ready().then(() => {...});

หากเซิร์ฟเวอร์ของคุณให้บริการไฟล์. .wasm บนพา ธ อื่นหรือชื่ออื่นให้ใช้ setWasmPath ก่อนที่คุณจะเตรียมใช้งานแบ็กเอนด์ ดูส่วน "การใช้ Bundlers" ใน README สำหรับข้อมูลเพิ่มเติม:

import {setWasmPath} from '@tensorflow/tfjs-backend-wasm';
setWasmPath(yourCustomPath);
tf.setBackend('wasm');
tf.ready().then(() => {...});
ทำไมต้องเป็น WASM?

WASM เปิดตัวในปี 2015 ในรูปแบบไบนารีบนเว็บใหม่โดยให้โปรแกรมที่เขียนด้วย JavaScript, C, C ++ และอื่น ๆ เป็นเป้าหมายการคอมไพล์สำหรับการทำงานบนเว็บ WASM ได้รับการ สนับสนุน โดย Chrome, Safari, Firefox และ Edge ตั้งแต่ปี 2017 และรองรับ 90% ของอุปกรณ์ ทั่วโลก

ประสิทธิภาพ

แบ็กเอนด์ WASM ใช้ประโยชน์จาก ไลบรารี XNNPACK เพื่อการปรับใช้ตัวดำเนินการเครือข่ายประสาทเทียมให้เหมาะสมที่สุด

เมื่อเทียบกับ JavaScript : ไบนารี WASM โดยทั่วไปเร็วกว่าบันเดิล JavaScript มากสำหรับเบราว์เซอร์ในการโหลดแยกวิเคราะห์และดำเนินการ JavaScript ถูกพิมพ์แบบไดนามิกและรวบรวมขยะซึ่งอาจทำให้การทำงานช้าลงเมื่อรันไทม์

เมื่อเทียบกับ WebGL : WebGL เร็วกว่า WASM สำหรับรุ่นส่วนใหญ่ แต่สำหรับรุ่นเล็ก ๆ WASM สามารถทำงานได้ดีกว่า WebGL เนื่องจากต้นทุนค่าโสหุ้ยคงที่ในการเรียกใช้ WebGL Shader ส่วน“ ฉันควรใช้ WASM เมื่อใด” ด้านล่างนี้จะกล่าวถึงฮิวริสติกส์สำหรับการตัดสินใจนี้

ความสามารถในการพกพาและความเสถียร

WASM มีเลขคณิตลอยตัว 32 บิตแบบพกพาซึ่งนำเสนอความเท่าเทียมกันอย่างแม่นยำในทุกอุปกรณ์ ในทางกลับกัน WebGL เป็นอุปกรณ์เฉพาะฮาร์ดแวร์และอุปกรณ์ที่แตกต่างกันอาจมีความแม่นยำที่แตกต่างกัน (เช่นทางเลือกกลับเป็น 16 บิตลอยบนอุปกรณ์ iOS)

เช่นเดียวกับ WebGL WASM ได้รับการสนับสนุนอย่างเป็นทางการจากเบราว์เซอร์หลักทั้งหมด ต่างจาก WebGL ตรงที่ WASM สามารถรันใน Node.js และใช้งานฝั่งเซิร์ฟเวอร์ได้โดยไม่ต้องคอมไพล์ไลบรารีเนทีฟ

ฉันควรใช้ WASM เมื่อใด

ขนาดโมเดลและความต้องการในการคำนวณ

โดยทั่วไป WASM เป็นตัวเลือกที่ดีเมื่อรุ่นมีขนาดเล็กลงหรือคุณสนใจเกี่ยวกับอุปกรณ์ระดับล่างที่ไม่มีการรองรับ WebGL (ส่วนขยาย OES_texture_float ) หรือมี GPU ที่มีประสิทธิภาพน้อยกว่า แผนภูมิด้านล่างแสดงเวลาในการอนุมาน (ณ TensorFlow.js 1.5.2) ใน Chrome บน MacBook Pro ปี 2018 สำหรับ รุ่นที่ รองรับอย่างเป็นทางการ 5 รุ่น ใน WebGL, WASM และ CPU แบ็กเอนด์:

รุ่นเล็กกว่า

รุ่น WebGL WASM ซีพียู หน่วยความจำ
BlazeFace 22.5 มิลลิวินาที 15.6 มิลลิวินาที 315.2 มิลลิวินาที .4 ลบ
FaceMesh 19.3 มิลลิวินาที 19.2 มิลลิวินาที 335 มิลลิวินาที 2.8 ลบ

รุ่นใหญ่ขึ้น

รุ่น WebGL WASM ซีพียู หน่วยความจำ
PoseNet 42.5 มิลลิวินาที 173.9 มิลลิวินาที 1514.7 มิลลิวินาที 4.5 ลบ
BodyPix 77 มิลลิวินาที 188.4 มิลลิวินาที 2683 มิลลิวินาที 4.6 ลบ
MobileNet เวอร์ชัน 2 37 มิลลิวินาที 94 มิลลิวินาที 923.6 มิลลิวินาที 13 ล้านบาท

ตารางด้านบนแสดงให้เห็นว่า WASM เร็วกว่าแบ็กเอนด์ JS CPU ธรรมดา 10-30 เท่าในทุกรุ่นและแข่งขันกับ WebGL สำหรับรุ่นเล็กเช่น BlazeFace ซึ่งมีน้ำหนักเบา (400KB) แต่มีจำนวนตัวเลือกที่เหมาะสม (~ 140) เนื่องจากโปรแกรม WebGL มีต้นทุนค่าโสหุ้ยคงที่ต่อการดำเนินการ op จึงอธิบายได้ว่าทำไมโมเดลเช่น BlazeFace จึงเร็วกว่าบน WASM

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

การอนุมานเทียบกับการฝึกอบรม

เพื่อจัดการกับกรณีการใช้งานหลักสำหรับการปรับใช้โมเดลที่ได้รับการฝึกอบรมมาแล้วการพัฒนาแบ็กเอนด์ของ WASM จะจัดลำดับความสำคัญของการ อนุมาน เหนือ การ สนับสนุนการ ฝึกอบรม ดูรายการตัว เลือกล่าสุดที่ รองรับใน WASM และ แจ้งให้เราทราบ หากโมเดลของคุณมี op ที่ไม่รองรับ สำหรับโมเดลการฝึกอบรมเราขอแนะนำให้ใช้แบ็กเอนด์โหนด (TensorFlow C ++) หรือแบ็กเอนด์ WebGL

แบ็กเอนด์ของ CPU

แบ็กเอนด์ของซีพียู 'cpu' เป็นแบ็กเอนด์ที่มีประสิทธิภาพน้อยที่สุด แต่จะง่ายที่สุด การดำเนินการทั้งหมดถูกนำไปใช้ใน vanilla JavaScript ซึ่งทำให้คู่ขนานน้อยลง พวกเขายังบล็อกเธรด UI

แบ็กเอนด์นี้มีประโยชน์มากสำหรับการทดสอบหรือบนอุปกรณ์ที่ไม่สามารถใช้งาน WebGL ได้

ธง

TensorFlow.js มีชุดของแฟล็กสภาพแวดล้อมที่ได้รับการประเมินโดยอัตโนมัติและกำหนดคอนฟิกูเรชันที่ดีที่สุดในแพลตฟอร์มปัจจุบัน แฟล็กเหล่านี้ส่วนใหญ่เป็นแฟล็กภายใน แต่โกลบอลแฟล็กบางส่วนสามารถควบคุมได้ด้วย Public API

  • tf.enableProdMode(): เปิดใช้งานโหมดการผลิตซึ่งจะลบการตรวจสอบความถูกต้องของแบบจำลองการตรวจสอบ NaN และการตรวจสอบความถูกต้องอื่น ๆ เพื่อเพิ่มประสิทธิภาพ
  • tf.enableDebugMode() : เปิดใช้งานโหมดดีบักซึ่งจะล็อกเข้าสู่คอนโซลทุกการดำเนินการที่ดำเนินการตลอดจนข้อมูลประสิทธิภาพรันไทม์เช่นรอยเท้าหน่วยความจำและเวลาดำเนินการเคอร์เนลทั้งหมด โปรดทราบว่าสิ่งนี้จะทำให้แอปพลิเคชันของคุณช้าลงอย่างมากอย่าใช้สิ่งนี้ในการผลิต