HungPH Blog Logo
Kỹ Thuật & Công Nghệ29 tháng 10, 2026•16 phút đọc•5 lượt xem

Thiết kế hệ thống AI đánh giá tình trạng vật tư từ ảnh: từ prompt đến model riêng

Một nền tảng quản lý và tái sử dụng vật tư cho phép các công trường (hoặc nhà máy, kho) đăng thông tin vật tư đang dư, để nơi khác đang cần có thể nhận lại thay vì mua mới.

1. Bài toán

Một nền tảng quản lý và tái sử dụng vật tư cho phép các công trường (hoặc nhà máy, kho) đăng thông tin vật tư đang dư, để nơi khác đang cần có thể nhận lại thay vì mua mới.

Ví dụ: công trường A còn dư 40 chiếc van. Nhân viên chụp ảnh và đăng lên nền tảng. Công trường B cần van và muốn biết hai điều: những chiếc van này còn dùng được không và tình trạng thế nào.

Hiện tại, việc đánh giá này làm bằng tay, mỗi người đánh giá một kiểu, và tốn thời gian. Chức năng AI cần làm là: nhìn ảnh vật tư và cho biết tình trạng (mới, đã dùng còn tốt, xuống cấp, hư hỏng), kèm lý do.

Có một điều cần nhớ ngay từ đầu: đánh giá sai theo hướng "hư hỏng mà báo còn dùng được" nguy hiểm hơn chiều ngược lại. Điều này ảnh hưởng đến cách thiết kế và đánh giá ở các bước sau.


2. Tổng quan giải pháp

Mình chia làm hai giai đoạn:

Giai đoạn 1: Ảnh → VLM (hiểu ảnh bằng prompt) → người duyệt → lưu (ảnh + nhãn đúng)
                                                              ↓ tích lũy dữ liệu
Giai đoạn 2: Huấn luyện model phân loại riêng bằng dữ liệu đã duyệt
             → model xử lý ca dễ; ca khó → VLM và người duyệt

Vì sao không huấn luyện model riêng ngay từ đầu? Vì chưa có dữ liệu gán nhãn. Giai đoạn 1 dùng VLM để chạy được ngay, đồng thời mỗi lần người duyệt xác nhận hoặc sửa kết quả chính là một lần gán nhãn miễn phí. Khi đã đủ dữ liệu thì chuyển sang giai đoạn 2 để rẻ hơn, nhanh hơn, ổn định hơn.


3. Các thuật ngữ cần biết (giải thích đơn giản)

  • VLM (Vision-Language Model, model hiểu ảnh và ngôn ngữ): model như Claude, GPT, Gemini (qua API) hoặc Qwen-VL (tự chạy trên máy mình). Bạn đưa ảnh và câu hỏi bằng chữ, nó trả lời bằng chữ.

  • Prompt: câu chỉ dẫn bằng chữ bạn gửi cho model.

  • Backbone (xương sống): phần "mắt" của model, biến ảnh thành một dãy số mô tả nội dung ảnh.

  • Đặc trưng (feature, embedding): dãy số mô tả ảnh do backbone tạo ra. Hai ảnh giống nhau thì dãy số gần nhau.

  • DINOv2: một backbone nổi tiếng, đã được huấn luyện trên lượng ảnh rất lớn nên "nhìn" ảnh rất tốt, đặc biệt giữ được thông tin về bề mặt (gỉ, trầy, nứt).

  • Linear probe: đóng băng backbone (không sửa gì bên trong), chỉ huấn luyện một lớp phân loại rất nhỏ đứng sau nó.

  • Fine-tune: điều chỉnh cả phần bên trong backbone (hoặc một phần của nó) để hợp hơn với bài toán của mình.

  • Epoch: một lượt huấn luyện đi qua toàn bộ dữ liệu train.

  • Train / Validation / Test: ba tập dữ liệu, giải thích ở bước 4.

  • Overfitting (học vẹt): model nhớ thuộc dữ liệu train nhưng làm sai với ảnh mới.

  • Độ tin cậy (confidence): model "chắc" đến mức nào về kết quả của nó, thường là số từ 0 đến 1.

  • Human-in-the-loop: quy trình có người xem lại và sửa kết quả của AI.

  • Precision, Recall: giải thích ở bước 6.


4. Bước 0: Thống nhất nhãn và tiêu chí với khách hàng

Trước khi viết một dòng code, hãy ngồi cùng khách để định nghĩa các nhãn và tiêu chí cho từng nhãn. Đây là bước quan trọng nhất, vì nếu tiêu chí mơ hồ thì model nào cũng khó chính xác.

Nhãn

Tiêu chí (ví dụ)

Hành động

Mới

Chưa dùng, bao bì còn nguyên

Tái sử dụng được

Đã dùng, còn tốt

Có dấu vết sử dụng nhưng không hư

Tái sử dụng được

Xuống cấp

Gỉ nhẹ, trầy xước, đổi màu

Cần kiểm tra thêm

Hư hỏng

Nứt, biến dạng, thiếu bộ phận

Không tái sử dụng

Không xác định

Ảnh mờ, thiếu góc chụp

Yêu cầu chụp lại

Nhãn "Không xác định" rất quan trọng: nó cho phép hệ thống nói "tôi không chắc" thay vì đoán bừa.

Cũng nên viết sẵn một tài liệu hướng dẫn gán nhãn kèm ảnh ví dụ cho từng nhãn, để mọi người gán nhãn giống nhau. Có thể kiểm tra bằng cách cho hai người gán nhãn cùng một số ảnh rồi xem họ đồng ý với nhau bao nhiêu phần trăm. Nếu thấp, tiêu chí chưa rõ.


5. Bước 1: Giai đoạn 1, dùng VLM để chạy ngay

Ý tưởng: VLM đã học từ lượng dữ liệu khổng lồ nên biết sẵn rất nhiều khái niệm chung (gỉ sét, vết nứt, bao bì nguyên vẹn). Mình không cần dạy nó từ đầu, chỉ cần hướng dẫn bằng prompt.

Ví dụ prompt (rút gọn):

Bạn là chuyên gia kiểm tra vật tư. Dựa vào ảnh, hãy đánh giá tình trạng theo tiêu chí:
- Mới: chưa dùng, bao bì nguyên vẹn
- Đã dùng, còn tốt: có dấu vết sử dụng nhưng không hư
- Xuống cấp: gỉ nhẹ, trầy xước, đổi màu
- Hư hỏng: nứt, biến dạng, thiếu bộ phận
- Không xác định: ảnh không đủ để kết luận
Chỉ trả lời bằng JSON: {"condition": "...", "reasons": ["..."], "need_retake": true/false}

Kết quả ví dụ cho một ảnh van bị gỉ:

json

{"condition": "Xuống cấp", "reasons": ["Có vết gỉ ở thân van", "Không thấy vết nứt"], "need_retake": false}

Mẹo: thêm vài ảnh mẫu cho từng nhãn vào prompt (gọi là few-shot, nghĩa là "cho xem vài ví dụ rồi mới hỏi") để model hiểu tiêu chí tốt hơn.

Mình chọn API hay tự chạy VLM?

Mình cân nhắc hai hướng:

  • Gọi API (Claude, GPT, Gemini): dễ bắt đầu nhất, nhưng ảnh phải gửi ra ngoài hệ thống của khách và tiền tăng theo số lượng ảnh.

  • Tự chạy VLM mã nguồn mở trên server riêng, cụ thể là họ Qwen-VL (bản cỡ vài tỷ tham số, ví dụ 3B hoặc 7–8B tuỳ GPU đang có).

Mình chọn tự chạy Qwen-VL, vì ba lý do. Một là ảnh vật tư là dữ liệu của khách, mình muốn nó không rời khỏi hệ thống. Hai là chi phí không tăng theo từng ảnh. Ba là mình đã từng chạy Qwen2.5-VL cỡ 3B qua LM Studio, và biết rõ giới hạn của nó, ví dụ bộ nhớ GPU không đủ để nạp cùng lúc hai model (một model đọc ảnh, một model xử lý chữ), nên phải xử lý theo lô: chạy xong phần đọc ảnh rồi mới nạp model còn lại.

Cái giá phải trả: mình phải tự lo hạ tầng, và model nhỏ sẽ kém model API lớn ở các ca khó. Đó cũng là lý do mình giữ người duyệt ở giai đoạn 1 và thêm model riêng ở giai đoạn 2, thay vì tin hoàn toàn vào VLM.

Vì sao mình không dùng độ tin cậy mà VLM tự báo?

Nếu bạn yêu cầu VLM "cho biết độ tin cậy", nó sẽ viết ra một con số như 0,9. Nhưng VLM sinh ra văn bản, nên con số đó chỉ là chữ nó viết, không phải xác suất đo được. Nó có thể báo 0,9 cho cả những ca sai. Vì vậy mình quyết định không dùng con số này để quyết định ca nào được tự động:

  1. Cho chạy cùng một ảnh vài lần và xem kết quả có ổn định không. Nếu mỗi lần ra một nhãn khác nhau thì coi là ca khó.

  2. Ở giai đoạn 2, dùng model phân loại riêng (có xác suất đã hiệu chỉnh) để quyết định.

  3. Với loại vật tư ảnh hưởng đến an toàn, luôn qua người duyệt.

Mình không tự sửa lỗi nhận dạng của model, mà giữ nguyên để người kiểm tra được, vì che lỗi đi sẽ làm mất niềm tin.


6. Bước 2: Người duyệt và tích lũy dữ liệu

Ở giai đoạn 1, mọi kết quả đều qua người duyệt. Giao diện chỉ cần đơn giản: hiện ảnh, kết quả AI, và nút "Đúng" hoặc "Sửa nhãn".

Mỗi lần duyệt lưu lại:

  • Ảnh gốc

  • Nhãn đúng cuối cùng (do người xác nhận hoặc sửa)

  • Nhãn AI đề xuất (để biết AI sai ở đâu)

  • Lý do sửa (nếu có), thời gian, người duyệt

Sau vài tuần hoặc vài tháng, bạn có một bộ dữ liệu gán nhãn chất lượng cao mà không cần dự án gán nhãn riêng.

Đừng quên giữ lại một tập nhỏ có đáp án chuẩn do người có kinh nghiệm gán nhãn kỹ. Tập này dùng để đánh giá chất lượng về sau.


7. Bước 3: Chuẩn bị dữ liệu cho huấn luyện

Khi đã đủ dữ liệu, ta chuẩn bị huấn luyện model riêng. Dữ liệu chia thành ba phần:

Tập

Dùng để

Train

Dạy model (cập nhật các con số bên trong model)

Validation

Chọn cấu hình, quyết định dừng huấn luyện, chọn ngưỡng

Test

Chấm điểm cuối cùng, chỉ dùng một lần

Có thể hình dung như học thi: train là bài tập để học, validation là đề thi thử để điều chỉnh cách học, test là kỳ thi thật.

Hai lưu ý rất hay bị hỏi trong phỏng vấn:

  1. Chia theo vật phẩm, không chia theo ảnh. Giả sử một chiếc van có 5 ảnh. Nếu 4 ảnh nằm trong train và 1 ảnh nằm trong test thì model đã "nhìn" chiếc van đó rồi, kết quả test đẹp giả tạo. Đây gọi là rò rỉ dữ liệu (data leakage). Cách đúng là đặt toàn bộ ảnh của một vật phẩm vào cùng một tập.

  2. Giữ tỷ lệ các nhãn trong mỗi tập (stratified, nghĩa là "chia sao cho mỗi tập đều có đủ các loại nhãn theo tỷ lệ giống nhau"). Nhãn "hư hỏng" thường ít hơn các nhãn khác. Nếu mất cân bằng nghiêm trọng, có thể dùng loss có trọng số (phạt nặng hơn khi sai nhãn hiếm) hoặc lấy mẫu cân bằng.


8. Bước 4: Huấn luyện model, bắt đầu bằng linear probe

Backbone DINOv2 giống như một người đã xem hàng chục triệu bức ảnh nên rất giỏi quan sát. Cách đơn giản nhất để dùng nó là linear probe:

  1. Giữ nguyên DINOv2, không sửa gì bên trong.

  2. Cho từng ảnh đi qua DINOv2 để lấy dãy số mô tả ảnh (đặc trưng).

  3. Huấn luyện một lớp phân loại nhỏ (ví dụ logistic regression) để học "dãy số kiểu này thì là nhãn gì".

Ví dụ mã minh hoạ (rút gọn):

python

from transformers import AutoImageProcessor, AutoModel
import torch
from sklearn.linear_model import LogisticRegression

processor = AutoImageProcessor.from_pretrained("facebook/dinov2-base")
backbone = AutoModel.from_pretrained("facebook/dinov2-base").eval()

def extract(images):
    with torch.no_grad():
        inputs = processor(images=images, return_tensors="pt")
        out = backbone(**inputs)
        return out.last_hidden_state[:, 0].numpy()   # dãy số mô tả mỗi ảnh

X_train = extract(train_images)
clf = LogisticRegression(max_iter=1000, class_weight="balanced")
clf.fit(X_train, train_labels)

Vì sao bắt đầu bằng cách này:

  • Rất nhanh và rẻ, thậm chí chạy được trên CPU với vài nghìn ảnh.

  • Cần ít ảnh có gán nhãn vì "đôi mắt" đã giỏi sẵn.

  • Có ngay một baseline (mốc để so sánh) trước khi làm cách phức tạp hơn.


9. Bước 5: Fine-tune nếu linear probe chưa đủ

Nếu độ chính xác của linear probe chưa đạt, bước tiếp theo của mình là fine-tune một phần. Để hiểu cách làm, trước hết cần biết cấu trúc bên trong DINOv2.

Cấu trúc bên trong: DINOv2 bản cỡ vừa (ViT-B) gồm 12 "block", bạn có thể hình dung là 12 tầng xử lý xếp chồng lên nhau. Ảnh đi qua từng tầng theo thứ tự:

  • Các tầng đầu học những thứ đơn giản: cạnh, góc, màu, đường nét. Bài toán nào cũng cần những thứ này, nên không cần sửa.

  • Các tầng cuối học những thứ phức tạp hơn: hình dạng, bề mặt, bộ phận của vật. Đây là phần gần với "ý nghĩa", và là phần nên điều chỉnh để hợp với bài toán của mình.

Linear probe (bước 4) là đóng băng cả 12 tầng, chỉ học lớp phân loại phía sau.

Fine-tune một phần là mở khóa vài tầng cuối (ví dụ 2 tầng cuối) để chúng được điều chỉnh, còn 10 tầng đầu vẫn đóng băng. Ví dụ: ở bài toán này, tầng cuối cần học thêm cách phân biệt "gỉ nhẹ" (xuống cấp) với "gỉ ăn sâu, biến dạng" (hư hỏng). DINOv2 gốc chưa được dạy sự khác biệt đó theo tiêu chí của khách.

LoRA là một cách khác để điều chỉnh mà tiết kiệm hơn. Thay vì sửa trực tiếp hàng chục triệu con số bên trong một tầng, mình giữ nguyên các con số gốc và gắn thêm vài "miếng vá" nhỏ để huấn luyện. Ví dụ đời thường: thay vì mài lại ống kính máy ảnh, bạn gắn thêm một kính lọc lên trước ống kính. Cách này cần ít bộ nhớ GPU, file kết quả nhỏ, và model gốc không bị thay đổi.

Lộ trình mình chọn: thử linear probe trước, nếu chưa đủ thì mở khóa 2 tầng cuối, và chỉ cân nhắc LoRA hoặc mở khóa nhiều tầng hơn nếu máy hạn chế hoặc kết quả vẫn chưa đạt.

Cách vận hành giống huấn luyện thông thường:

  • Chạy qua nhiều epoch, nhưng với model đã huấn luyện sẵn thường chỉ cần vài đến vài chục epoch.

  • Dùng tốc độ học nhỏ để không phá những gì backbone đã học.

  • Dừng sớm (early stopping): nếu điểm trên validation ngừng cải thiện thì dừng, để tránh học vẹt.

  • Tăng cường dữ liệu (data augmentation): lật, cắt, thay đổi độ sáng nhẹ để model chắc hơn. Cẩn thận với biến đổi màu mạnh vì màu có thể là dấu hiệu của gỉ.

Điều chỉnh tham số: trọng số model cập nhật tự động trong lúc huấn luyện. Các siêu tham số (tốc độ học, số block mở khóa, mức tăng cường dữ liệu) thì không chỉnh tay giữa chừng, mà chạy nhiều lần với cấu hình khác nhau, so sánh trên tập validation và chọn cấu hình tốt nhất.

Máy cần (ước lượng tham khảo):

  • Linear probe: gần như chạy được trên CPU, hoặc GPU nhỏ.

  • Fine-tune DINOv2 cỡ nhỏ hoặc vừa (ViT-S, ViT-B): GPU khoảng 8–16GB.

  • Cỡ lớn (ViT-L): GPU khoảng 24GB.

  • Thuê GPU theo giờ trên cloud là đủ cho giai đoạn này, không cần mua máy.


10. Bước 6: Đánh giá đúng cách

Không nên chỉ nhìn "độ chính xác tổng" (accuracy). Hãy xem từng nhãn một.

  • Precision (độ chính xác khi dự đoán): trong số những ca model báo "hư hỏng", bao nhiêu ca thật sự hư hỏng.

  • Recall (độ bao phủ): trong số những ca thật sự hư hỏng, model phát hiện được bao nhiêu.

  • Confusion matrix (ma trận nhầm lẫn): bảng cho thấy model hay nhầm nhãn nào với nhãn nào.

Ví dụ minh hoạ: có 100 vật tư thật sự hư hỏng. Model chỉ bắt được 90 ca và bỏ sót 10 ca (báo là còn dùng được). Recall của nhãn "hư hỏng" là 90%. Với bài toán này, 10 ca bỏ sót đó là rủi ro an toàn, nên chúng ta ưu tiên đẩy recall của nhãn "hư hỏng" lên cao, và chấp nhận kiểm tra thừa một số ca không hư.

Đánh giá cuối cùng chạy một lần trên tập test (tập có đáp án chuẩn).


11. Bước 7: Quy tắc chạy thật, dùng ngưỡng để quyết định ca nào qua người duyệt

Khi triển khai, model riêng xử lý trước, và độ tin cậy của nó quyết định ca nào cần sự giúp đỡ:

Ảnh → model DINOv2 phân loại
   ├─ độ tin cậy cao (từ ngưỡng trở lên) → ghi kết quả tự động, vẫn lấy mẫu kiểm tra định kỳ
   └─ độ tin cậy thấp → VLM (để lấy lý do) → người duyệt

Vấn đề: độ tin cậy của model đôi khi "tự tin quá mức" (báo 0,95 nhưng thực tế chỉ đúng 80%). Vì vậy cần hiệu chỉnh (calibration), một kỹ thuật phổ biến là temperature scaling (dùng tập validation để điều chỉnh sao cho "độ tin cậy 0,9" thực sự tương ứng khoảng 90% ca đúng).

Chọn ngưỡng bằng tập validation theo hướng thận trọng: ngưỡng cao hơn thì ít ca tự động hơn nhưng an toàn hơn. Có thể thêm quy tắc nghiệp vụ, ví dụ loại vật tư ảnh hưởng đến an toàn thì luôn qua người duyệt.


12. Bước 8: Vận hành sau khi chạy thật

Triển khai chỉ là bắt đầu. Cần theo dõi:

  • Tỷ lệ người duyệt sửa nhãn: nếu tăng lên, có thể dữ liệu đã thay đổi.

  • Drift (trôi dữ liệu): xuất hiện loại vật tư mới, điều kiện chụp thay đổi (ví dụ chuyển sang chụp bằng điện thoại khác).

  • Chi phí và độ trễ của VLM, và tỷ lệ ca chuyển cho người duyệt.

Định kỳ huấn luyện lại bằng dữ liệu mới đã duyệt. Trước khi thay model cũ, so sánh model mới với model cũ trên cùng tập đánh giá và chỉ thay khi tốt hơn rõ ràng.


13. Một số câu hỏi phỏng vấn có thể gặp

  1. Vì sao bắt đầu bằng VLM mà không huấn luyện model riêng? Vì chưa có dữ liệu gán nhãn; VLM chạy được ngay và quy trình duyệt tạo ra nhãn cho giai đoạn sau.

  2. Vì sao chọn DINOv2 làm backbone? Đặc trưng ảnh tốt, giữ được thông tin bề mặt, hoạt động tốt với ít dữ liệu nhờ đóng băng backbone.

  3. Vì sao không fine-tune VLM? Với bài toán chọn một nhãn trong vài nhãn thì quá nặng, chậm, khó đo độ tin cậy. Nên cân nhắc chỉ khi cần đầu ra là văn bản có cấu trúc theo mẫu riêng.

  4. Làm sao tránh rò rỉ dữ liệu? Chia train/validation/test theo vật phẩm, không chia theo ảnh.

  5. Chỉ số nào quan trọng nhất? Recall của nhãn "hư hỏng", vì bỏ sót hư hỏng là rủi ro an toàn.

  6. Làm sao biết model vẫn tốt sau khi triển khai? Theo dõi tỷ lệ sửa nhãn, drift, đánh giá định kỳ trên tập chuẩn, và huấn luyện lại bằng dữ liệu mới.


14. Tóm tắt

  1. Thống nhất nhãn và tiêu chí với khách trước tiên.

  2. Giai đoạn 1: VLM + prompt + người duyệt, chạy ngay và thu dữ liệu.

  3. Chia dữ liệu theo vật phẩm thành train, validation, test.

  4. Bắt đầu bằng DINOv2 đóng băng + lớp phân loại nhỏ (linear probe); nếu chưa đủ thì fine-tune một phần.

  5. Đánh giá theo từng nhãn, ưu tiên recall của nhãn "hư hỏng".

  6. Dùng ngưỡng độ tin cậy (đã hiệu chỉnh) để quyết định ca nào qua người duyệt.

  7. Theo dõi, huấn luyện lại, và luôn giữ vòng lặp có người duyệt.

Điểm cốt lõi của giải pháp: không cần chờ có dữ liệu mới bắt đầu, và AI luôn hoạt động cùng người duyệt chứ không thay thế hoàn toàn.

Thẻ bài viết:#Computer Vision
pochiro1996

Thành viên gia nhập từ 19/09/2026

Bình luận (0)

Hỗ trợ bình luận văn minh và tôn trọng quan điểm đa chiều.
Đang tải bình luận...
0% • Lên đầu trang