尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Pipeline huấn luyện ResNet-18 (PyTorch) phân loại ảnh rác thành 10 loại:
battery, cardboard, clothes, glass, metal, organic, paper, plastic,
shoes, trash (rác còn lại: hộp xốp, vỏ bánh kẹo, giấy ăn, ống hút, cốc giấy…).
Giao diện gộp lại thành 4 nhóm: hữu cơ, tái chế, không thể tái chế (clothes, shoes,
trash), nguy hại. Desktop (trash_ai_ui/) và API (backend/) dùng cùng checkpoint v6, cùng
tăng sáng ảnh tối và luật pin 50% với web (26/10/2026). Web chạy bản TF.js nén uint8 nên xác suất
lệch PyTorch tới ~0,05 trên cùng ảnh 224×224; trên 49 ảnh realworld_curated (gốc + làm tối 25%),
7/98 lần web chọn nhóm khác PyTorch.
Kèm các giao diện sử dụng: web (frontend/, Vercel), desktop (PyQt5) và API (Flask).
frontend/models/r18-10lop-v6 — ResNet-18 train trên dataset_8lop_v6 (22.511 ảnh), 50 epoch
không dừng sớm (--patience 50), lấy epoch tốt nhất trên val (48). Luật pin và ngưỡng
"chưa chắc" giữ như v5 (50%). Lý do thêm 2 loại: trước đây nhóm "không thể tái chế" chỉ có
clothes, nên dép, hộp xốp, vỏ snack không thuộc loại nào và web chỉ báo "Chưa chắc".
Dữ liệu (dựng bằng garbage_classifier/scripts/build_dataset_v6.py, lọc trùng dHash
Hamming ≤ 4 với v5 và mọi bộ realworld_*, báo cáo trong dataset_8lop_v6_report.json):
shoes (1.459): 1.449 ảnh giày của sumn2u vốn bị gộp vào clothes từ v2, tách ra lại;
thêm 6 crop TACO và 4 ảnh nhóm tự chụp.trash (3.030): sumn2u trash (899, ảnh web), MTA s-litter + m-composite (554 crop, không
lấy phần test), RealWaste Miscellaneous Trash (494), VN Trash Foam_box (343 — chỉ giữ ảnh
chụp thật, bỏ 881 ảnh stock/quảng cáo có cả hộp nhựa gắn nhầm nhãn), TACO (xốp, giấy ăn, vỏ
snack, cốc giấy, ống hút, găng tay — 544 crop), BDWaste vỏ snack + cốc giấy (158, tách từ
v5), 38 crop MTA plastic-film xem tay là vỏ snack (scripts/mta_film_vo_snack.txt).plastic.anh_tu_chup/: 7 pin, 4 dép, 3 ly nhựa) — chia ngẫu nhiên nên chỉ 8
ảnh vào train.Bộ test 10 loại: realworld_rw5_test_10lop và realworld_bdw_test_10lop là bản gắn lại
nhãn của rw5/BDWaste (bộ cũ giữ nguyên): vỏ snack, ống hút, giấy ăn, cốc giấy, găng tay chuyển
sang trash — 245 ảnh rw5 xem tay từng ảnh, 43 ảnh BDWaste theo tên file. Ca không chắc (hoá
đơn, đĩa giấy, hộp nước, giấy vò) giữ nhãn cũ. Danh sách trong manifest.json của từng bộ.
Đo trên 9 bộ (2.654 ảnh: rw5 + BDWaste bản 10 loại, test, test2, clothes_test,
pin_test, MTA, Bower, curated), luật pin 50%, đúng theo 4 nhóm:
| v5 (8 loại) | v6, 15 epoch | v6 + vỏ snack | v6 gộp, 50 epoch ← web | |
|---|---|---|---|---|
| Đúng nhóm (/2.654) | 2.153 | 2.211 | 2.184 | 2.218 |
| Báo nhầm thành pin | 47 | 47 | 51 | 20 |
| Báo nhầm "không tái chế" | 50 | 140 | 175 | 167 |
Nhận đúng trash ở rw5 (/244) | 26 | 104 | 116 | 115 |
realworld_pin_test (/141) | 107 | 109 | 111 | 100 |
| Test split (theo loại) | 91,3% (8 loại) | 88,8% | 89,1% | 90,1% |
curated 41/49, test2 44/52, PyTorch 43 và 45.Bỏ ngang: UGV-NBWASTE (dép nhựa chụp thật, CC BY 4.0) chưa dùng vì Mendeley chặn tải tự động —
tải tay "Download All", giải nén vào downloads/ugv_yolo rồi chạy lại script là có.
v5 vẫn giữ ở frontend/models/r18-8lop-v5; muốn quay lại thì đổi THU_MUC_MODEL và bỏ
shoes/trash khỏi danh sách ví dụ của nhóm "không thể tái chế".
frontend/models/r18-8lop-v5 — ResNet-18 train trên dataset_8lop_v5 (19.657 ảnh, thêm ảnh
pin thật). Luật pin: xác suất pin ≥ 50% thì báo nguy hại, dưới 50% thì chọn loại cao nhất
trong 7 loại còn lại (bỏ luật "có thể là pin" ở 30% của bản v2). Số đo xem mục v5 bên dưới.
| Trước (v2 + luật pin 30%) | Sau (v5 + luật pin 50%) | |
|---|---|---|
| Nhận ra pin | cứ 10 pin bỏ sót 4 | cứ 10 pin bỏ sót 2 |
| Báo nhầm thành pin | 47 lần | 45 lần |
| Đúng nhóm, 1.642 ảnh rác chụp thật | 86,9% | 91,2% |
| Hữu cơ (/300) | 250 | 250 |
| Quần áo chụp thật | — | 31/43 (bộ test mới, xem mục v6a/v6b) |
Dòng "quần áo sai hết" trước đây là do bộ test: phần lớn ảnh "quần áo" trong đó không có quần áo (thùng thu gom, logo chữ…). Đã lọc lại — xem mục v6a/v6b.
Bản v2 vẫn giữ ở frontend/models/r18-8lop-v1; muốn quay lại thì đổi THU_MUC_MODEL và
khôi phục luật pin cũ (commit d364ddf).
Hai dataset dataset_8lop_v6a/v6b đã xoá (26/10/2026); tên v6 giờ dùng cho bản 10 loại ở trên.
Bộ test quần áo cũ đo sai. 7/10 ảnh "quần áo" không có quần áo làm vật chính (cây treo
vải, thùng thu gom quần áo, xe tải chở kiện vải, hộp điện, logo chữ). Đã chuyển sang
realworld_loai_bo/ (lý do ghi trong manifest.json), còn lại 1 ảnh ở realworld_test và
2 ảnh ở realworld_mta_test.
Bộ test mới realworld_clothes_test (43 ảnh): Wikimedia Commons, lọc tay từng ảnh — giày
cũ vứt trên vỉa hè/cỏ/bùn, quần áo đổ đống bên đường, giẻ treo, áo bỏ trên cầu thang. Bỏ ảnh
người mặc, ảnh sản phẩm, tranh vẽ. Lọc trùng dHash với train (gần nhất cách 10 bit). Mới lọc
420/1.103 ảnh ứng viên (Commons giới hạn tốc độ tải); phần lớn là giày, ít quần áo.
Dữ liệu train thêm (đều là đồ cũ thật chụp trải phẳng trên nền trắng, không có bối cảnh rác):
dataset_8lop_v6a = v5 + 1.000 ảnh RISE "Clothing Dataset for Second-Hand Fashion"
(CC BY 4.0, bản front-only trên Hugging Face): chọn usage = Recycle hoặc condition ≤ 2,
ưu tiên đồ thủng/bẩn, mỗi loại đồ ≤ 15%, cắt sát món đồ.dataset_8lop_v6b = v6a + 575 ảnh Na Uy "Norway post-consumer garment data" (CC BY-SA
4.0, Zenodo, chỉ tải khu F 8,3 GB): chỉ lấy món Sorted_as = T_waste (đồ vứt bỏ), bỏ ảnh
nhãn mác/thẻ số, cắt theo vùng vật lớn nhất.clothes: 3.656 →
4.656 (v6a) → 5.231 (v6b).Đo bằng uv run python -m garbage_classifier.realworld (đúng luật web: tăng sáng ảnh tối, pin
≥ 50%, đúng theo 4 nhóm, bỏ trùng MD5). Bộ test cũ đã bỏ 7 ảnh nên số khác bảng trước.
| v5 (web) | v6a | v6b | |
|---|---|---|---|
Quần áo thật realworld_clothes_test (43) | 31 | 30 | 29 |
realworld_test (43) · test2 (52) · curated (49) | 28 · 39 · 40 | 26 · 42 · 41 | 27 · 43 · 43 |
| MTA (175) · Bower (313) · BDWaste (196) | 165 · 281 · 196 | 168 · 282 · 195 | 166 · 282 · 196 |
| rw5 (1.642) | 1.498 (91%) | 1.498 (91%) | 1.512 (92%) |
| Tổng đúng nhóm, 8 bộ (2.513) | 2.278 | 2.282 | 2.298 |
| Báo nhầm thành pin (8 bộ) | 47 | 50 | 35 |
| Báo nhầm thành quần áo (8 bộ) | 75 | 78 | 69 |
realworld_pin_test (141) | 107 | 112 | 111 |
Quần áo chụp trải phẳng không giúp nhận quần áo trong rác: 31 → 30 → 29/43 (chênh trong sai số). Ảnh còn sai là giày nhỏ giữa vỉa hè/cỏ, quần áo đổ đống lẫn rác, mũ/áo nhàu — model đoán giấy/nhựa/kim loại. Thứ còn thiếu là ảnh đồ trong bối cảnh rác, không phải thêm ảnh đồ cũ.
Nền trắng của RISE/Na Uy không làm model đoán bừa sang quần áo (báo nhầm 75 → 69).
v6b nhỉnh hơn v5 ở lần train đầu (+20 ảnh, ít báo nhầm pin hơn), nhưng train lại 3 seed thì hết chênh (seed đổi cả cách chia train/val) — nên giữ v5 trên web:
| 3 lần train (seed 42 · 1 · 2) | v5 | v6b |
|---|---|---|
| Quần áo thật (/43) | 31 · 29 · 29 (TB 29,7) | 29 · 31 · 27 (TB 29,0) |
| Tổng đúng nhóm, 8 bộ (/2.513) | 2.278 · 2.278 · 2.291 (TB 2.282) | 2.298 · 2.265 · 2.290 (TB 2.284) |
| Báo nhầm thành pin | 47 · 47 · 41 | 35 · 74 · 39 |
| Báo nhầm thành quần áo | 75 · 72 · 74 | 69 · 70 · 70 |
realworld_pin_test (/141) | 107 · 111 · 110 | 111 · 114 · 115 |
Cùng một dataset, chỉ đổi seed đã lệch tới 33 ảnh tổng và 39 lần báo nhầm pin (v6b seed 1) — mọi chênh lệch nhỏ hơn thế giữa hai model đơn lẻ đều không đáng tin.
Số v5 đo lại bằng script mới lệch README cũ 1 ảnh ở MTA (165 so với 166) và 3 ảnh ở
realworld_pin_test (107 so với 110).
frontend/ chạy ResNet-18 8 loại ngay trong trình duyệt (TensorFlow.js, nén uint8,
11 MB) — không cần server, ảnh không rời máy người dùng.
Đo trên 49 ảnh đời thực (realworld_curated), tính đúng theo 4 nhóm:
| Model | Đúng | Pin (13 ảnh) |
|---|---|---|
| Teachable Machine 4 nhóm (MobileNet, chỉ train phần đầu) | 37/49 | 5 |
ResNet-18 7 lớp cũ (new11k, chưa có hữu cơ) | 43/49 | 9 |
ResNet-18 8 lớp (v2_r18) ← web lúc đó | 44/49 | 11 |
| MobileNetV3-Large 8 lớp | 40/49 | 5 |
| ResNet-18 / MobileNetV3 + cân bằng lớp | 43/49 · 36/49 | — |
ResNet-18 trên dataset_merged + augmentation mạnh | 38/49 | 6 |
new11k: 15 epoch, batch 32, không augmentation mạnh, không cân bằng lớp
— hai thứ này đều làm kết quả trên ảnh thật kém đi.Cần một môi trường riêng Python 3.11 + tensorflow-cpu==2.15.1, onnx==1.15.0,
protobuf==4.25.3, onnx2tf==1.19.16 và tensorflowjs==4.17.0 (hai gói cuối cài
--no-deps; tensorflowjs cần thêm tensorflow_hub==0.15.0 và setuptools<70, còn
tensorflow_decision_forests / jax không có bản Windows — tạo module rỗng cùng tên là đủ,
bộ chuyển CNN không dùng tới; jax cần thêm jax/experimental/__init__.py chứa
jax2tf = None). Bản TF 2.16+ dùng Keras 3, các công cụ trên không chạy.
uv run --extra export garbage-export-onnx --checkpoint artifacts/v2_r18/best_model.pt --output r18.onnx
onnx2tf -i r18.onnx -o r18_tf -osd -n
python -m tensorflowjs.converters.converter --input_format=tf_saved_model --output_format=tfjs_graph_model --quantize_uint8="*" r18_tf r18_tfjs
onnx2tf đòi tải file ảnh mẫu calibration_image_sample_data_20x128x128x3_float32.npy
từ một server đã hỏng — tự tạo file đó (20 ảnh 128×128×3, giá trị 0–1) trong thư mục chạy lệnh.
Chép r18_tfjs/* vào thư mục mới frontend/models/<tên>/, thêm meta.json (danh sách
lớp đúng thứ tự, mean/std ImageNet), rồi đổi THU_MUC_MODEL trong frontend/index.html.
Đừng ghi đè thư mục cũ: Vercel cache models/ 1 năm.
Bản nộp Vòng Khu vực được gắn tag vong-khu-vuc-2026.
Gộp dataset_8lop_v2 với hai bộ ảnh chụp thật thành dataset_8lop_v3 (17.581 ảnh):
test của bộ này giữ riêng
làm realworld_mta_test (175 ảnh), không dùng để train.realworld_*.real_world: xem mẫu thì là ảnh sản phẩm/stock trên web, có cả ảnh
sai nhãn — không phải ảnh rác đời thực như tên gọi.Garbage Classification v2 (Kaggle, sumn2u) chính là dataset_8lop_v2 — đã có sẵn.Số ảnh đúng theo 4 nhóm:
| Bộ test | v2 (web lúc đó) | v3 | v3 + --oversample battery=2 |
|---|---|---|---|
realworld_curated (49) | 44 | 42 | 41 |
realworld_test (49, bộ cũ trước khi bỏ 6 ảnh) | 22 | 29 | 27 |
realworld_test2 (53, bộ cũ trước khi bỏ 1 ảnh) | 43 | 45 | 43 |
| 3 bộ, bỏ ảnh trùng (102) | 65 (64%) | 74 (73%) | — |
| Pin, bỏ ảnh trùng (14) | 10 | 7 | — |
realworld_mta_test (175, cùng nguồn với dữ liệu train) | 146 | 170 | 170 |
Ba bộ realworld_* trùng ảnh nhau: realworld_curated lấy lại ảnh từ hai bộ kia, nên
151 ảnh chỉ có 102 ảnh khác nhau (so MD5), pin 27 ảnh chỉ có 14. Cộng thẳng 3 bộ (109 / 116,
pin 20 / 14) là đếm một ảnh hai lần — mọi con số "151 ảnh" cũ nên đọc theo dòng 102.
v3 đúng nhiều hơn trên ảnh thật nói chung nhưng nhận pin kém đi — dữ liệu mới không có ảnh pin nào, pin bị các lớp khác lấn át. Lấy mẫu pin gấp đôi không chữa được. Vì pin là rác nguy hại, web giữ v2. Việc cần làm tiếp: tự chụp 200–300 ảnh pin thật (nhiều nền, đèn vàng, chỗ tối) rồi train lại v3. Vẫn chưa có bộ test ảnh tối nên chưa đo được độ bền ánh sáng.
Ba bước thêm trước và sau khi chạy model trong frontend/index.html:
Đo trên 102 ảnh không trùng (PyTorch), số ảnh đúng theo 4 nhóm. Chưa có ảnh tối thật nên làm tối giả (còn 25% độ sáng):
| Đúng nhóm | Pin đúng (/14) | Báo nhầm thành pin | |
|---|---|---|---|
| v2 gốc | 65 | 10 | 4 |
| + cân bằng độ sáng | 65 | 10 | 4 |
| + ưu tiên pin 30% (web lúc đó, v2) | 65 | 10 | 4 |
| Ảnh tối giả, v2 gốc | 58 | 7 | 6 |
| Ảnh tối giả, + cân bằng độ sáng | 68 | 8 | 3 |
Trên trình duyệt (web lúc đó, v2): 63/102 đúng nhóm, pin 11/14, báo nhầm pin 5; ảnh tối giả 66/102. Lệch vài ảnh so với PyTorch vì trình duyệt thu nhỏ ảnh hơi khác.
Ưu tiên pin chỉ sửa được 1 ảnh (pin AA rò rỉ, xác suất pin 34%, trước bị đoán thủy tinh), và ngưỡng 30% được chọn trên chính bộ test này — đây là quy tắc an toàn, không phải model tốt hơn. Hạ xuống 20% không nhận thêm pin nào mà báo nhầm tăng từ 4 lên 8. 3 ảnh pin v2 vẫn sai: vỉ pin còn bao bì giấy (đoán bìa), pin nhỏ nằm ở mép trên ảnh mạch điện (bị cắt mất khi lấy phần giữa ảnh), và ảnh thùng thu gom pin — ảnh này không có pin, không nên tính là lỗi.
Ngưỡng tin cậy (đã có ưu tiên pin), đúng – sai – "Chưa chắc" trên 102 ảnh — số đo ở giai đoạn v2, chưa tái hiện được bằng script hiện tại; số của v5 (đang chạy) xem bảng 5.4 trong báo cáo: 0,4 → 67-20-15; 0,5 → 64-19-19; 0,6 → 59-13-30.
| Ngưỡng | Đúng | Sai | Chưa chắc |
|---|---|---|---|
| 0,4 | 65 | 28 | 9 |
| 0,5 (chọn ở giai đoạn v2) | 64 | 23 | 15 |
| 0,6 | 61 | 16 | 25 |
Giữ 0,5: lên 0,6 bớt 7 lần sai nhưng 3 ảnh đúng bị đổi thành "Chưa chắc", và cứ 4 ảnh thì 1 ảnh không có câu trả lời.
dataset_8lop_v4 (19.157 ảnh) = v3 + hai bộ mới, train y như v3 (15 epoch, batch 32):
realworld_bower_test. Thêm được 59 ảnh pin train.realworld_bdw_test.tuhanasinan, CC BY 4.0): 1.647 ảnh (1.642 sau khi bỏ 5 ảnh trùng MD5) tự chụp ở khuôn
viên trường, chỉ dùng để test → realworld_rw5_test. Đây là bộ test ảnh thật lớn nhất
hiện có, nguồn khác hẳn dữ liệu train; có 300 ảnh hữu cơ thật.Số ảnh đúng theo 4 nhóm (bỏ ảnh trùng MD5 trong từng bộ):
| Bộ test | v2 (web) | v3 | v4 |
|---|---|---|---|
| 102 ảnh cũ | 65 | 74 | 71 |
| — pin (/14) | 10 | 7 | 6 |
realworld_rw5_test (1.642) | 1.425 (87%) | 1.522 (93%) | 1.534 (93%) |
| — hữu cơ (/300) | 250 | 226 | 251 |
realworld_bower_test (313, pin 11) | 254, pin 10 | 280, pin 9 | 281, pin 11 |
realworld_bdw_test (196) | 153 | 166 | 196 ⚠ |
realworld_mta_test (175) | 146 | 170 | 167 |
realworld_bdw_test 100% là không đáng tin: ảnh cùng một người chụp, cùng nền, chỉ
khác góc — dHash không bắt được hết các ảnh gần giống đó. Đừng dùng bộ này để so model.realworld_clothes_test).dataset_8lop_v5 = v4 + ảnh pin lọc tay từng ảnh:
realworld_pin_test (141 ảnh).v5 nhận pin tốt hẳn nhưng báo nhầm thành pin nhiều hơn (lon, chai kim loại → pin). Chữa bằng ngưỡng: pin chỉ khi P(pin) ≥ t, không thì lấy lớp cao nhất không tính pin. Chọn t trên một nửa các bộ test (chia theo MD5), nửa còn lại để báo cáo — không chỉnh trên chính số liệu báo cáo.
| v2 + ưu tiên pin 30% (web lúc đó) | v5, t = 0,5 | v5, t = 0,7 | |
|---|---|---|---|
| 102 ảnh cũ: đúng nhóm · pin /14 · báo nhầm | 65 · 10 · 4 | 67 · 10 · 5 | 70 · 9 · 1 |
realworld_pin_test (141 pin) | 77 (54,6%) | 107 (75,9%) | 95 (67,4%) |
realworld_rw5_test (1.642): đúng · báo nhầm | 86,9% · 21 | 91,2% · 35 | 92,8% · 8 |
realworld_bower_test (313): đúng · pin /11 · nhầm | 250 · 10 · 20 | 281 · 9 · 5 | 283 · 8 · 2 |
realworld_mta_test (175): đúng · báo nhầm | 144 · 2 | 165 · 0 | 165 · 0 |
| Tổng pin nhận đúng (/166) | 97 | 126 | 112 |
| Tổng báo nhầm thành pin (102 ảnh cũ + rw5 + Bower + MTA) | 47 | 45 | 11 |
realworld.py --nguong-pin 0.3. t = 0,7 gần như hết báo nhầm nhưng bỏ sót pin nhiều hơn t = 0,5.realworld_pin_test cùng nguồn (Open Images, Commons) với ảnh pin train nên con số 75,9% là
lạc quan. Trên 14 + 11 pin của các bộ khác, v5 ngang v2 (19 so với 20, trong sai số).| Model | Dữ liệu train | Ảnh cùng nguồn dataset | Ảnh từ nguồn khác |
|---|---|---|---|
full | 980 | 90,0% | 53,1% |
big | 2.890 | 94,4% | 44,9% |
gentle | 2.890, backbone LR 3e-6 | 90,1% | 49,0% |
aug | 2.890 + augmentation mạnh | 96,0% | 44,9% |
new11k | 7.772 | 94,4% | 57,1% ← tốt nhất thực tế |
merged | 8.435 + augmentation mạnh | 96,0% | 51,0% |
Cột bên phải mới là con số thật. Nó đo trên 49 ảnh rác lấy từ Wikimedia Commons — ảnh chụp ngoài đời, không thuộc bất kỳ bộ dữ liệu huấn luyện nào.
Model tốt nhất đạt 96% trên ảnh dataset nhưng chỉ 57% trên ảnh đời thực. Cứ 10 tấm ảnh bạn tự chụp thì sai hơn 4 tấm. Đây là giới hạn thật của dự án, không phải con số đem giấu đi.
Dữ liệu huấn luyện gần như toàn ảnh chụp studio: một vật, nền trắng, ánh sáng đều. Ảnh đời thực có nhiều vật trong khung, nền lộn xộn, ánh sáng bất kỳ — model chưa từng thấy. Hiện tượng này gọi là domain shift.
Kiểm chứng trong quá trình làm:
archive (4.133 ảnh) thực chất chính là TrashNet — đối chiếu md5 thấy 86,7% ảnh
giống nhau từng byte. TrashNet nổi tiếng vì chụp mỗi vật trên một tấm bìa trắng.dataset_sach_zip (1.400 ảnh) là tập con của archive, giống hệt từng byte.Tức là ba bộ dữ liệu ban đầu thực ra chỉ là một nguồn duy nhất.
| Cách | Thay đổi trên ảnh đời thực |
|---|---|
| Augmentation mạnh (TrivialAugmentWide, crop 0.3–1.0, blur, random erasing) | 0 điểm — thử 2 lần, kể cả khi train đủ 43 epoch |
| Hạ learning rate của backbone xuống 10 lần | +4 điểm (nằm trong sai số ±7) |
| Thêm 7.922 ảnh từ nguồn khác | +12,2 điểm ← cách duy nhất có tác dụng |
| Thêm 948 ảnh cùng kiểu studio | 0 điểm |
Kết luận: chỉ dữ liệu đa dạng mới chữa được, và phải là dữ liệu KHÁC KIỂU. Thêm ảnh cùng phong cách không giúp gì.
Muốn cải thiện tiếp, việc đáng làm nhất là bổ sung ảnh chụp bằng điện thoại trong bối cảnh thật — nhiều vật một khung, trong thùng rác, ánh sáng trong nhà.
garbage_classifier/ Pipeline train + đánh giá (phần chính)
src/garbage_classifier/
data.py Chia tập, augmentation
model.py ResNet-18 + lưu/nạp checkpoint
engine.py Vòng train và đánh giá
train.py Lệnh train
evaluate.py Lệnh đánh giá
predict.py Dự đoán 1 ảnh
artifacts/ Checkpoint + số liệu (không đẩy lên git)
trash_ai_ui/ Giao diện sử dụng
giao_dien_pyqt.py Desktop PyQt5
phan_loai_rac.py Logic AI dùng chung
app.py API Flask
index.html + tfjs_model/ Web chạy trong trình duyệt
garbage_resnet18.pt Model đang triển khai
Cần uv. Từ thư mục garbage_classifier:
uv sync
Về GPU: pyproject.toml đã trỏ sang index CUDA 13.0 của PyTorch. Mặc định PyPI chỉ
có bản torch CPU-only cho Windows — cài nhầm bản đó thì train chậm hơn khoảng 24 lần
(72 phút so với 3 phút cho cùng một lần train). Kiểm tra bằng:
uv run python -c "import torch; print(torch.__version__, torch.cuda.is_available())"
Phải ra 2.14.0+cu130 True. Nếu ra +cpu thì GPU đang không được dùng.
Kiểm tra dataset:
uv run garbage-data --data-dir "duong/dan/toi/dataset"
Train:
uv run garbage-train --data-dir "duong/dan/toi/dataset" --output-dir "artifacts/lan1" --epochs 20 --batch-size 64 --num-workers 8
Tham số quan trọng: --strong-augment (augmentation mạnh), --freeze-epochs (số epoch
đóng băng backbone), --patience (dừng sớm), --backbone-learning-rate.
Đánh giá lại:
uv run garbage-evaluate --data-dir "duong/dan/toi/dataset" --checkpoint "artifacts/lan1/best_model.pt" --output "artifacts/lan1/evaluation.json"
Dự đoán một ảnh:
uv run garbage-predict "anh.jpg" --checkpoint "artifacts/lan1/best_model.pt"
Desktop (PyQt5) — từ trash_ai_ui, cần pip install -r requirements.txt:
python giao_dien_pyqt.py
API (Flask) — từ trash_ai_ui:
python app.py
Gửi POST /predict kèm file ảnh, trả về JSON có class, ten, confidence, chac_chan,
goi_y_xu_ly, all_scores.
Web frontend/ chạy v5 (luật pin 50%, tăng sáng ảnh tối). API backend/ và giao diện
desktop vẫn dùng v2 (backend/model.pt, trash_ai_ui/garbage_resnet18.pt), chọn loại cao nhất
trong 8 loại, chưa có luật pin, nên kết quả có thể khác web. Riêng trash_ai_ui/index.html
còn dùng model Teachable Machine cũ (37/49).
Ngưỡng tin cậy 50%. Dưới mức này giao diện báo "không chắc chắn" và không đưa gợi ý xử lý. Đây là thiết kế có chủ đích: khi model sai, nó thường sai ở vùng 25–50%, nên chặn lại tốt hơn là khuyên bừa.
Model Teachable Machine thì ngược lại. Cùng tấm ảnh kiện giấy phế liệu, nó trả về
Glass 99,5% — sai nhưng tự tin, vượt ngưỡng nên vẫn đưa lời khuyên sai. Model ResNet-18
trên cùng ảnh đó trả 40,8% và bị chặn. Với ứng dụng khuyên người ta vứt rác, sai mà tự tin
nguy hiểm hơn sai mà biết ngập ngừng.
Lớp yếu nhất của v2 là plastic (86,7% ngay cả trên ảnh dataset; ở v5 là cardboard 85,9%, plastic 87,2%). Chai nhựa trong và chai
thủy tinh trông rất giống nhau.
Bộ test 49 ảnh là thước đo yếu. Sai số khoảng ±7 điểm, và không có lớp clothes
(tìm mãi không ra ảnh quần áo cũ hợp lệ trên Wikimedia). Chỉ nên tin những chênh lệch
lớn hơn 10 điểm.
Dataset không đẩy lên git vì dung lượng. Các bộ đã dùng:
battery và clothesrealworld_curated/manifest.jsonrealworld_clothes_test — Wikimedia Commons, nguồn, giấy phép, tác giả
trong realworld_clothes_test/manifest.jsontrash lấy từ bản mirror huggingface.co/datasets/omasteam/waste-garbage-management-dataset; gốc kaggle.com/datasets/sumn2u/garbage-classification-v2Phần trash_ai_ui/ ban đầu do một thành viên khác viết cho model Teachable Machine.
Ở đây đã được chuyển sang dùng model ResNet-18; hai file gốc giữ lại dưới dạng .bak.