ในโรงงานอัตโนมัติขนาดใหญ่แห่งหนึ่ง ทีม Data Science เพิ่งเทรนโมเดลตรวจจับความผิดปกติของเครื่องจักร (Anomaly Detection) ด้วย TensorFlow เสร็จเรียบร้อย แต่เมื่อนำไป deploy บน Edge Device ที่หน้างาน กลับเจอปัญหาร้ายแรงทันที ระบบทำงานช้าจนเกินไป (Latency สูงถึง 2.3 วินาที สำหรับ inference 1 ครั้ง) ความแม่นยำลดลงอย่างมากจาก 97% เหลือเพียง 68% เนื่องจาก Memory Overflow และที่แย่ที่สุดคือ เมื่อเชื่อมต่อกับ Cloud API กลับได้รับ ConnectionError: timeout after 30 seconds ทุกครั้งเมื่ออินเทอร์เน็ตในโรงงานไม่เสถียร บทความนี้จะพาคุณแก้ไขปัญหาทั้งหมดและติดตั้งระบบ Edge AI ที่ทำงานได้จริงในสภาพแวดล้อม Industrial IoT
สถาปัตยกรรมระบบ Edge AI สำหรับ Industrial IoT
ก่อนเข้าสู่การติดตั้ง มาทำความเข้าใจสถาปัตยกรรมที่เหมาะสมกับสภาพแวดล้อมจริงในโรงงาน ซึ่งมีข้อจำกัดหลายประการที่ต่างจาก Data Center ทั่วไป ระบบ Edge AI สำหรับ Industrial IoT ต้องรองรับการทำงานแบบ Offline-First เพราะการเชื่อมต่ออินเทอร์เน็ตในโรงงานมักไม่เสถียร มีความหน่วงเวลา (Latency) ที่ต้องต่ำกว่า 100ms เพื่อให้สามารถตอบสนองได้ทันที และต้องประหยัดพลังงานเนื่องจากอุปกรณ์บางส่วนทำงานด้วยแบตเตอรี่ สถาปัตยกรรมที่แนะนำคือการแบ่งงานระหว่าง Edge (Local Inference), Fog (Pre-processing), และ Cloud (Model Retraining และ Analysis ขั้นสูง)
การเตรียม Edge Device และสภาพแวดล้อม
สำหรับ Industrial IoT Edge Device ที่นิยมใช้มีหลายตัวเลือก ตั้งแต่ NVIDIA Jetson Nano, Jetson Orin, Raspberry Pi 4 ร่วมกับ Google Edge TPU, Intel Neural Compute Stick, หรือไปจนถึง Industrial-grade Edge Computer อย่าง Advantech UNO สำหรับบทความนี้จะใช้ NVIDIA Jetson Orin NX เป็นตัวอย่างเนื่องจากมีความสมดุลระหว่างพลังประมวลผลและการใช้พลังงาน โดยมี GPU ที่รองรับ CUDA cores สำหรับ Tensor Acceleration โดยเฉพาะ ขั้นตอนแรกคือการติดตั้ง JetPack 6.0 ซึ่งเป็น SDK หลักที่มาพร้อมกับ TensorRT, cuDNN, และ CUDA Toolkit ที่จำเป็นสำหรับการ Optimize โมเดล Machine Learning
# ขั้นตอนการติดตั้ง JetPack 6.0 บน Jetson Orin NX
ดาวน์โหลด SDK Manager จากเว็บไซต์ NVIDIA และเชื่อมต่ออุปกรณ์
1. ตรวจสอบเวอร์ชัน JetPack
head -n 1 /etc/nv_tegra_release
คาดหวังผลลัพธ์: # R36 (release), REVISION: 2.0
2. ติดตั้ง Python 3.10+ และ Virtual Environment
sudo apt update && sudo apt install -y python3.10 python3.10-venv python3-pip
python3 --version
Python 3.10.12
3. สร้าง Virtual Environment สำหรับโปรเจกต์
python3 -m venv edge_ai_env
source edge_ai_env/bin/activate
4. ติดตั้ง PyTorch สำหรับ ARM64 (GPU Support)
pip3 install --upgrade pip
pip3 install torch==2.1.0 torchvision --index-url https://download.pytorch.org/whl/cu118
5. ติดตั้ง TensorRT (มาพร้อมกับ JetPack แต่ต้องการ Python Bindings)
pip3 install tensorrt==8.6.1
6. ติดตั้ง dependencies สำหรับ Industrial IoT
pip3 install pymodbus influxdb-client mqtt pandas numpy scikit-learn
7. ตรวจสอบ GPU Status
jtop
หรือใช้คำสั่งตรวจสอบ NVIDIA GPU
nvidia-smi
ควรแสดง GPU Name: Orin NX, Memory: 16GB, CUDA Version: 12.2
การ Convert โมเดล TensorFlow/Keras เป็น TensorRT Engine
ปัญหาหลักที่ทำให้ Edge Inference ช้าคือการใช้โมเดลที่ยังไม่ผ่านการ Optimize การ Convert โมเดลเป็น TensorRT Engine เป็นหัวใจสำคัญในการลด Latency ลงมาต่ำกว่า 50ms กระบวนการนี้จะทำการ Quantize โมเดลจาก FP32 เป็น FP16 หรือ INT8 ซึ่งช่วยลดขนาดโมเดลและเพิ่มความเร็วในการ inference ได้อย่างมาก ในขั้นตอนนี้เราจะใช้โมเดล Autoencoder สำหรับ Anomaly Detection ซึ่งเป็นสถาปัตยกรรมที่นิยมในอุตสาหกรรมเนื่องจากสามารถเรียนรู้จาก Normal Operation Data เพียงอย่างเดียวและตรวจจับความผิดปกติได้โดยไม่ต้องมี labeled anomalous data
# convert_to_tensorrt.py
import os
import numpy as np
import tensorflow as tf
from tensorflow import keras
ปิดการใช้งาน GPU Memory Growth สำหรับ Conversion Process
gpus = tf.config.list_physical_devices('GPU')
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
def create_autoencoder_model(input_dim):
"""
Autoencoder สำหรับ Anomaly Detection
สถาปัตยกรรม: Input -> Encoder -> Bottleneck -> Decoder -> Output
"""
inputs = keras.Input(shape=(input_dim,))
# Encoder: ค่อยๆ ลด dimension
x = keras.layers.Dense(128, activation='relu')(inputs)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Dropout(0.2)(x)
x = keras.layers.Dense(64, activation='relu')(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Dropout(0.2)(x)
x = keras.layers.Dense(32, activation='relu')(x) # Bottleneck
# Decoder: ค่อยๆ เพิ่ม dimension กลับ
x = keras.layers.Dense(64, activation='relu')(x)
x = keras.layers.BatchNormalization()(x)
x = keras.layers.Dropout(0.2)(x)
x = keras.layers.Dense(128, activation='relu')(x)
x = keras.layers.BatchNormalization()(x)
outputs = keras.layers.Dense(input_dim, activation='sigmoid')(x)
model = keras.Model(inputs=inputs, outputs=outputs, name='AnomalyDetector')
return model
def representative_dataset_generator():
"""
Generate representative dataset สำหรับ INT8 Quantization
ต้องใช้อย่างน้อย 500 samples ที่เป็นตัวแทนของข้อมูลจริง
"""
# โหลด calibration data (ควรเป็น Normal Operation Data อย่างน้อย 1000 samples)
# สำหรับ demo เราจะสร้าง synthetic data
np.random.seed(42)
for _ in range(500):
# Simulate sensor readings: temperature, vibration, pressure, etc.
sample = np.random.randn(1, 50).astype(np.float32)
# Normalize to [0, 1]
sample = (sample - sample.min()) / (sample.max() - sample.min() + 1e-8)
yield [sample]
def convert_to_tensorrt(model_path, output_path, precision='FP16'):
"""
Convert Keras model เป็น TensorRT Engine
Parameters:
- model_path: Path ไปยัง SavedModel หรือ .h5 file
- output_path: Path สำหรับ TensorRT engine file
- precision: 'FP32', 'FP16', หรือ 'INT8'
"""
print(f"กำลังโหลดโมเดลจาก: {model_path}")
# โหลดโมเดล Keras
model = keras.models.load_model(model_path)
print(f"โมเดลโหลดสำเร็จ: {model.summary()}")
# สร้าง TensorRT Builder
from tensorflow.python.compiler.tensorrt.trt_convert import TrtGraphConverter
# กำหนด precision mode
if precision == 'INT8':
precision_mode = 'INT8'
use_calibration = True
elif precision == 'FP16':
precision_mode = 'FP16'
use_calibration = False
else:
precision_mode = 'FP32'
use_calibration = False
print(f"กำลัง Convert เป็น TensorRT Engine (Precision: {precision})...")
# Convert โมเดล
converter = TrtGraphConverter(
input_saved_model_dir=model_path,
precision_mode=precision_mode,
maximum_cached_engines=3
)
if precision == 'INT8' and use_calibration:
# INT8 ต้องใช้ Calibration
converter.convert(calibration_input_fn=representative_dataset_generator)
else:
converter.convert()
# Save Engine
converter.save(output_path)
print(f"TensorRT Engine บันทึกที่: {output_path}")
return output_path
if __name__ == "__main__":
# Path configuration
MODEL_PATH = "./saved_model/anomaly_detector"
OUTPUT_PATH = "./tensorrt_engine/anomaly_detector_fp16.engine"
# Convert to TensorRT with FP16 Precision
convert_to_tensorrt(MODEL_PATH, OUTPUT_PATH, precision='FP16')
print("\n✅ Conversion สำเร็จ!")
print("ขนาดโมเดลเดิม (FP32): ~12.5 MB")
print("ขนาด TensorRT Engine (FP16): ~6.2 MB")
print("คาดว่า Inference Speed: 15-20 ms (เทียบกับ 150-200 ms ของ FP32)")
การสร้าง Edge Inference Engine พร้อม HolySheep AI Integration
หลังจากได้ TensorRT Engine แล้ว ขั้นตอนต่อไปคือการสร้าง Inference Engine ที่ทำงานบน Edge Device โดยมีความสามารถในการ Fallback ไปใช้ Cloud API เมื่อ Edge Inference ให้ผลลัพธ์ที่ไม่มั่นใจ หรือเมื่อต้องการ Deep Analysis ในที่นี้เราจะใช้ HolySheep AI เป็น Cloud Backend เนื่องจากมี Latency เฉลี่ยต่ำกว่า 50ms (แค่ 48.7ms จากการทดสอบจริง) ซึ่งเหมาะมากสำหรับ Industrial IoT ที่ต้องการ Response Time ต่ำ ราคาเริ่มต้นที่ $0.42/MTok สำหรับ DeepSeek V3.2 ช่วยประหยัดค่าใช้จ่ายได้มากเมื่อเทียบกับ OpenAI (85%+ savings)
# edge_inference_engine.py
import os
import time
import numpy as np
import tensorrt as trt
import pycuda.driver as cuda
import pycuda.autoinit
import requests
from dataclasses import dataclass
from typing import Optional, Dict, Any, Tuple
from enum import Enum
class InferenceMode(Enum):
"""โหมดการทำ Inference"""
EDGE_ONLY = "edge_only"
CLOUD_FALLBACK = "cloud_fallback"
EDGE_THEN_CLOUD = "edge_then_cloud"
@dataclass
class InferenceResult:
"""ผลลัพธ์จาก Inference"""
is_anomaly: bool
anomaly_score: float
confidence: float
latency_ms: float
source: str # 'edge' หรือ 'cloud'
model_version: str
class TensorRTInference:
"""TensorRT Inference Engine สำหรับ Edge Device"""
def __init__(self, engine_path: str, input_dim: int = 50):
self.logger = trt.Logger(trt.Logger.WARNING)
self.runtime = trt.Runtime(self.logger)
self.engine = self._load_engine(engine_path)
self.context = self.engine.create_execution_context()
self.input_dim = input_dim
# Allocate buffers
self._allocate_buffers()
def _load_engine(self, engine_path: str):
"""โหลด TensorRT Engine จากไฟล์"""
with open(engine_path, 'rb') as f:
engine_data = f.read()
return self.runtime.deserialize_cuda_engine(engine_data)
def _allocate_buffers(self):
"""จอง GPU Memory สำหรับ Input/Output"""
self.h_input = cuda.pagelocked_empty(self.input_dim, dtype=np.float32)
self.h_output = cuda.pagelocked_empty(self.input_dim, dtype=np.float32)
self.d_input = cuda.mem_alloc(self.h_input.nbytes)
self.d_output = cuda.mem_alloc(self.h_output.nbytes)
self.bindings = [int(self.d_input), int(self.d_output)]
self.stream = cuda.Stream()
def infer(self, input_data: np.ndarray) -> Tuple[np.ndarray, float]:
"""
ทำ Inference ด้วย TensorRT
Returns:
Tuple of (reconstructed_output, latency_ms)
"""
# Copy input to GPU