Sử dụng socket để deploy model Machine Learning

Khi sử dụng Machine Learning bạn sẽ thấy thời gian load model thường lâu hơn thời gian predict 1 ảnh. Để khắc phục nhược điểm đó thì giải pháp là load sẵn model lên RAM để xử lý. Có vài cách load sẵn model như là load model lên Django và xử lý bằng HTTP request. Hôm nay mình chia sẻ thêm 1 cách nữa là dùng socket để xử lý request.

Lợi ích của socket khi load sẵn model là:

  • Load sẵn model Machine Learning lên RAM để tiết kiệm thời gian load model từ đầu
  • Xử lý request từ nhiều chương trình/nhiều ngôn ngữ lập trình khác nhau
  • Code ít hơn, gọn gàng hơn sử dụng Django
  • Dễ dàng tích hợp, debug và chạy như 1 service trên Linux

Giới thiệu về socket

Socket là giao thức kết nối giữa các thiết bị thông qua mạng (local hoặc Internet) với khả năng kết nối phong phú:

  • Socket truyền nhận data giữa các máy tính chạy các hệ điều hành khác nhau
  • Socket truyền nhận data giữa các thiết bị khác nhau như Arduino, PLC,…
  • Socket kết nối các chương trình viết bằng các ngôn ngữ khác nhau, hầu hết các ngôn ngữ đều hỗ trợ socket (Python/C#/C++/Java…)
  • Mỗi socket sẽ lắng nghe ở 1 port tùy bạn chọn (miễn là không trùng với port đang được sử dụng)
  • Socket server luôn lắng nghe incomming connection

Nhờ những đặc điểm trên mà chúng ta load model bằng socket server để lắng nghe client gửi ảnh lên và nhận diện, sau đó trả kết quả về client hiển thị.

Trong trường hợp model nặng, predict chậm chúng ta phải kết hợp với lập trình multiple thread để xử lý nhiều request cùng lúc.

Nguyên lý hoạt động

  1. Socket server load model Machine Learning
  2. Socket server khởi tạo và chờ client kết nối
  3. Socket client gửi ảnh dạng base64 đến Socket server
  4. Socket server nhận được kết nối thì xử lý data chuyển thành hình ảnh, sau đó predict hình ảnh
  5. Kết quả sau khi xử lý được trả về với dạng JSON
  6. Socket client trả về kết quả cho user
  7. Tất cả dữ liệu khi gửi qua socket đều là dạng byte

Truyền/nhận dữ liệu có thể bằng nhiều format khác nhau, tuy nhiên với kinh nghiệm làm nhiều dự án multiple platform thì recommend các bạn:

  • Chuyển ảnh sang format base64 để hạn chế lỗi xảy ra khi lập trình với nhiều ngôn ngữ/OS khác nhau
  • Dữ liệu nên format bằng dạng JSON để dễ dàng lấy kết quả và xử lý nhanh

Tất cả các ngôn ngữ lập trình phổ biến hiện nay như JS/C++/C#/Python/Java/… đều hỗ trợ base64 và JSON nên các bạn sẽ không gặp vấn đề gì khi sử dụng.

Source code example Socket server và Socket client

Trong ví dụ này mình sẽ tạo 1 Socket server xử lý ảnh để detect khuôn mặt, sau đó trả về client ảnh đã được vẽ các khung chữ nhật và tọa độ bouding box khuôn mặt. Link ở cuối bài viết

  • Các bạn chạy file server.py trước, server sẽ load model sẵn và chờ đợi client kết nối
  • Tiếp theo các bạn chạy file client.py, file này sẽ load ảnh và chuyển thành string base64. String base64 này đưa vào 1 trường của object data, mục đích là để các bạn dễ dàng thêm các trường khác.
  • Khi có kết nối thì server lấy string từ trường imageBase64 chuyển thành ảnh
  • Sau khi predict ta được 2 trường là ảnh đã vẽ khuôn mặt và các hình chữ nhật
  • Server trả dữ liệu về client bằng format JSON và tiếp tục chờ kết nối mới
  • Client lấy ảnh từ trường frameDraw trong object trả về và save xuống file

Ghi chú

  • Data truyền nhận mình đang set là 1MB, cỡ đó là vừa, nếu ảnh nặng hơn bạn nên cân nhắc tiền xử lý, resize… dưới client
  • PORT đang dùng là 8000, các bạn có thể thay đổi tùy ý
  • Các bạn có thể detect bằng GPU bằng cách truyền biến “gpu” vào hàm khởi tạo
  • Phiên bản Python đang dùng là 3.7.3

Tạo service trên Linux

Đầu tiên các bạn copy file server.py vào 1 folder trên linux, ở đây mình chọn folder /home/ubuntu.

Tiếp theo tạo file /lib/systemd/system/socket_server.service với nội dung như bên dưới

Sau đó start service bằng lệnh
sudo systemctl start socket_server.service

Nếu muốn auto chạy service sau khi khởi động thì dùng lệnh
sudo systemctl enable socket_server.service

Như vậy chương trình sẽ luôn chạy dưới dạng service để chờ client kết nối và gửi ảnh.

Kết luận

Source code socket được đơn giản hóa đến mức tối đa để có thể hiểu được dễ dàng nhưng cũng dễ dàng thêm trường dữ liệu gửi đi, chúc các bạn thành công.

https://github.com/thigiacmaytinh/Socket-ML

Leave a Reply