{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":75176,"databundleVersionId":8252256,"sourceType":"competition"}],"dockerImageVersionId":30762,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# Cài đặt các thư viện cần thiết\n!pip install -q ultralytics\n!pip install -q ensemble-boxes","metadata":{"execution":{"iopub.status.busy":"2024-09-17T03:11:02.854414Z","iopub.execute_input":"2024-09-17T03:11:02.854691Z","iopub.status.idle":"2024-09-17T03:11:31.61439Z","shell.execute_reply.started":"2024-09-17T03:11:02.854659Z","shell.execute_reply":"2024-09-17T03:11:31.613158Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install -q wandb","metadata":{"execution":{"iopub.status.busy":"2024-09-17T03:11:31.616338Z","iopub.execute_input":"2024-09-17T03:11:31.616675Z","iopub.status.idle":"2024-09-17T03:11:44.506043Z","shell.execute_reply.started":"2024-09-17T03:11:31.616641Z","shell.execute_reply":"2024-09-17T03:11:44.504872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import wandb\nfrom pathlib import Path\nimport os\n\n# Thiết lập API key cho wandb\nwandb.login(key='4f88ff0bbc6e3485258bca7079d7da4c47798ccd')\n\n# # Khởi tạo một run mới với tên dự án và tên lượt chạy cụ thể\n# # wandb.init(project='vincxr_yolov8s-3labels', name='n14th9')\n\n# Paths to data directories\nROOT = Path(\"/kaggle/input/amia-public-challenge-2024/train/train\")","metadata":{"execution":{"iopub.status.busy":"2024-09-17T03:11:44.507597Z","iopub.execute_input":"2024-09-17T03:11:44.507929Z","iopub.status.idle":"2024-09-17T03:11:47.140887Z","shell.execute_reply.started":"2024-09-17T03:11:44.507894Z","shell.execute_reply":"2024-09-17T03:11:47.139984Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels = [\n    \"Aortic enlargement\",\n    \"Atelectasis\",\n    \"Calcification\",\n    \"Cardiomegaly\",\n    \"Consolidation\",\n    \"ILD\",\n    \"Infiltration\",\n    \"Lung Opacity\",\n    \"Nodule/Mass\",\n    \"Other lesion\",\n    \"Pleural effusion\",\n    \"Pleural thickening\",\n    \"Pneumothorax\",\n    \"Pulmonary fibrosis\",\n    \"No finding\",\n    \"Finding\"\n]","metadata":{"execution":{"iopub.status.busy":"2024-09-17T03:11:47.143467Z","iopub.execute_input":"2024-09-17T03:11:47.144095Z","iopub.status.idle":"2024-09-17T03:11:47.149489Z","shell.execute_reply.started":"2024-09-17T03:11:47.144029Z","shell.execute_reply":"2024-09-17T03:11:47.147951Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\ndf_train = pd.read_csv('/kaggle/input/amia-public-challenge-2024/train.csv')\ndf_train","metadata":{"execution":{"iopub.status.busy":"2024-09-17T03:11:47.150648Z","iopub.execute_input":"2024-09-17T03:11:47.151004Z","iopub.status.idle":"2024-09-17T03:11:47.626748Z","shell.execute_reply.started":"2024-09-17T03:11:47.150959Z","shell.execute_reply":"2024-09-17T03:11:47.625842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_imgsize = pd.read_csv('/kaggle/input/amia-public-challenge-2024/img_size.csv')\n\n# # Cách 1: Sử dụng rename\n# df_imgsize = df_imgsize.rename(columns={'tên_cột_cũ_1': 'tên_cột_mới_1', 'tên_cột_cũ_2': 'tên_cột_mới_2', ...})\n\n# Cách 2: Gán trực tiếp vào df.columns\ndf_imgsize.columns = ['image_id', 'width', 'height']\n\ndf_imgsize","metadata":{"execution":{"iopub.status.busy":"2024-09-17T03:11:47.627903Z","iopub.execute_input":"2024-09-17T03:11:47.628211Z","iopub.status.idle":"2024-09-17T03:11:47.666411Z","shell.execute_reply.started":"2024-09-17T03:11:47.628179Z","shell.execute_reply":"2024-09-17T03:11:47.665497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Thực hiện phép gộp inner join\ndf_train = pd.merge(df_train, df_imgsize, on='image_id', how='inner')\n\ndf_train","metadata":{"execution":{"iopub.status.busy":"2024-09-17T03:11:47.667456Z","iopub.execute_input":"2024-09-17T03:11:47.667739Z","iopub.status.idle":"2024-09-17T03:11:47.70993Z","shell.execute_reply.started":"2024-09-17T03:11:47.667708Z","shell.execute_reply":"2024-09-17T03:11:47.709091Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# In 5 dòng đầu tiên để kiểm tra\nprint(df_train.head().to_markdown(index=False, numalign=\"left\", stralign=\"left\"))","metadata":{"execution":{"iopub.status.busy":"2024-09-17T03:11:47.711032Z","iopub.execute_input":"2024-09-17T03:11:47.711328Z","iopub.status.idle":"2024-09-17T03:11:47.738191Z","shell.execute_reply.started":"2024-09-17T03:11:47.711298Z","shell.execute_reply":"2024-09-17T03:11:47.737366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_img_id = '0FDQVdLgDKI1sRnPL94LzVh9EvXDVM9m'\ntest_df = df_train[df_train['image_id'] == test_img_id]\ntest_df","metadata":{"execution":{"iopub.status.busy":"2024-09-17T03:11:47.739192Z","iopub.execute_input":"2024-09-17T03:11:47.739479Z","iopub.status.idle":"2024-09-17T03:11:47.764667Z","shell.execute_reply.started":"2024-09-17T03:11:47.739449Z","shell.execute_reply":"2024-09-17T03:11:47.763644Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\nimport matplotlib.pyplot as plt\n\nimages_dir = '/kaggle/input/amia-public-challenge-2024/train/train/'\n\ndef drawBBox(img_id, df):\n    image_path = images_dir + img_id + '.png'\n    img = cv2.imread(image_path)\n\n    if img is None:\n        print(f\"Không tìm thấy hình ảnh {image_path}\")\n        return\n\n    dh, dw, _ = img.shape\n\n    for index, row in df.iterrows():\n        class_name = row['class_name']\n        l = int(row['x_min'])\n        r = int(row['x_max'])\n        t = int(row['y_min'])\n        b = int(row['y_max'])\n        color = (0, 0, 255)\n        cv2.putText(img, class_name, (l, t), cv2.FONT_HERSHEY_SIMPLEX, 1.5, color, 3)\n        cv2.rectangle(img, (l, t), (r, b), (255, 0, 0), 2)\n\n    plt.figure(num=None, figsize=(10, 10), dpi=80, facecolor='w', edgecolor='k')\n    plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2024-09-17T03:11:47.767973Z","iopub.execute_input":"2024-09-17T03:11:47.76834Z","iopub.status.idle":"2024-09-17T03:11:47.939007Z","shell.execute_reply.started":"2024-09-17T03:11:47.768309Z","shell.execute_reply":"2024-09-17T03:11:47.938102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"drawBBox(test_img_id, test_df)","metadata":{"execution":{"iopub.status.busy":"2024-09-17T03:11:47.940162Z","iopub.execute_input":"2024-09-17T03:11:47.940433Z","iopub.status.idle":"2024-09-17T03:11:48.532863Z","shell.execute_reply.started":"2024-09-17T03:11:47.940404Z","shell.execute_reply":"2024-09-17T03:11:48.531943Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def bb_iou(boxA, boxB):\n    xA = max(boxA[0], boxB[0])\n    yA = max(boxA[1], boxB[1])\n    xB = min(boxA[2], boxB[2])\n    yB = min(boxA[3], boxB[3])\n    interArea = max(0, xB - xA + 1) * max(0, yB - yA + 1)\n    boxAArea = (boxA[2] - boxA[0] + 1) * (boxA[3] - boxA[1] + 1)\n    boxBArea = (boxB[2] - boxB[0] + 1) * (boxB[3] - boxB[1] + 1)\n    iou = interArea / float(boxAArea + boxBArea - interArea)\n    return iou","metadata":{"execution":{"iopub.status.busy":"2024-09-17T03:11:48.534152Z","iopub.execute_input":"2024-09-17T03:11:48.534467Z","iopub.status.idle":"2024-09-17T03:11:48.541224Z","shell.execute_reply.started":"2024-09-17T03:11:48.534435Z","shell.execute_reply":"2024-09-17T03:11:48.540307Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def averageCoordinates(df, threshold):\n    tmp_df = df.reset_index()\n    duplicate = {}\n    for index1, row1 in tmp_df.iterrows():\n        if index1 < len(tmp_df) - 1:\n            next_index = index1 + 1\n            for index2, row2 in tmp_df.loc[next_index:,:].iterrows():\n                if row1[\"class_id\"] == row2[\"class_id\"]:\n                    boxA = [row1['x_min'], row1['y_min'], row1['x_max'], row1['y_max']]\n                    boxB = [row2['x_min'], row2['y_min'], row2['x_max'], row2['y_max']]\n                    iou = bb_iou(boxA, boxB)\n                    \n                    # Kiểm tra tọa độ của nhãn\n                    if np.any(np.array(boxA) < 0) or np.any(np.array(boxA) > 1) or np.any(np.array(boxB) < 0) or np.any(np.array(boxB) > 1):\n                        print(f\"Invalid label coordinates found: {boxA}, {boxB}\")\n                        continue\n                    \n                    if iou > threshold:\n                        if row1[\"index\"] not in duplicate:\n                            duplicate[row1[\"index\"]] = []\n                        duplicate[row1[\"index\"]].append(row2[\"index\"])\n\n    remove_keys = []\n    for k in duplicate:\n        for i in duplicate[k]:\n            if i in duplicate:\n                for id in duplicate[i]:\n                    if id not in duplicate[k]:\n                        duplicate[k].append(id)\n                if i not in remove_keys:\n                    remove_keys.append(i)\n\n    for i in remove_keys:\n        del duplicate[i]\n\n    rows = []\n    removed_index = []\n    for k in duplicate:\n        row = tmp_df[tmp_df['index'] == k].iloc[0]\n        X_min = [row['x_min']]\n        X_max = [row['x_max']]\n        Y_min = [row['y_min']]\n        Y_max = [row['y_max']]\n        removed_index.append(k)\n        for i in duplicate[k]:\n            removed_index.append(i)\n            row = tmp_df[tmp_df['index'] == i].iloc[0]\n            X_min.append(row['x_min'])\n            X_max.append(row['x_max'])\n            Y_min.append(row['y_min'])\n            Y_max.append(row['y_max'])\n        \n        # Tính toán tọa độ trung bình\n        X_min_avg = sum(X_min) / len(X_min)\n        X_max_avg = sum(X_max) / len(X_max)\n        Y_min_avg = sum(Y_min) / len(Y_min)\n        Y_max_avg = sum(Y_max) / len(Y_max)\n        \n        new_row = [row['image_id'], row['class_name'], row['class_id'], X_min_avg, Y_min_avg, X_max_avg, Y_max_avg, row['width'], row['height']]\n        rows.append(new_row)\n\n    for index, row in tmp_df.iterrows():\n        if row['index'] not in removed_index:\n            new_row = [row['image_id'], row['class_name'], row['class_id'], row['x_min'], row['y_min'], row['x_max'], row['y_max'], row['width'], row['height']]\n            rows.append(new_row)\n\n    new_df = pd.DataFrame(rows, columns =['image_id', 'class_name', 'class_id', 'x_min', 'y_min', 'x_max', 'y_max', 'width', 'height'])\n    \n    return new_df","metadata":{"execution":{"iopub.status.busy":"2024-09-17T03:12:58.392398Z","iopub.execute_input":"2024-09-17T03:12:58.392791Z","iopub.status.idle":"2024-09-17T03:12:58.413132Z","shell.execute_reply.started":"2024-09-17T03:12:58.392745Z","shell.execute_reply":"2024-09-17T03:12:58.412149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"new_df = averageCoordinates(test_df, 0.5)\nnew_df","metadata":{"execution":{"iopub.status.busy":"2024-09-17T03:12:58.415133Z","iopub.execute_input":"2024-09-17T03:12:58.415513Z","iopub.status.idle":"2024-09-17T03:12:58.441842Z","shell.execute_reply.started":"2024-09-17T03:12:58.41546Z","shell.execute_reply":"2024-09-17T03:12:58.440985Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"drawBBox(test_img_id, new_df)","metadata":{"execution":{"iopub.status.busy":"2024-09-17T03:12:58.442952Z","iopub.execute_input":"2024-09-17T03:12:58.443489Z","iopub.status.idle":"2024-09-17T03:12:58.904199Z","shell.execute_reply.started":"2024-09-17T03:12:58.443457Z","shell.execute_reply":"2024-09-17T03:12:58.903295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport pandas as pd\n\n# Lấy danh sách các ảnh từ dataframe\nimages_lst = df_train['image_id'].unique().tolist()\nimages_dir = '/kaggle/input/amia-public-challenge-2024/train/train/'\n\nsavelabels_dir = '/kaggle/working/amia-public-challenge-2024/train/train/'\nos.makedirs(savelabels_dir, exist_ok=True)  # Tạo thư mục nếu chưa tồn tại\n\n# Add class_id=14 and class_id=15\nframes = []\nfor img_id in images_lst:\n    sub_df = df_train[df_train['image_id'] == img_id].reset_index()\n    sub_df = averageCoordinates(sub_df, 0.5)\n    frames.append(sub_df)\n    rows = []\n    \n    if int(sub_df[\"class_id\"][0]) == 14:\n        rows.append(\"14 0.5 0.5 1.0 1.0\")\n    else:\n        for index, row in sub_df.iterrows():\n            w = int(row[\"width\"])\n            h = int(row[\"height\"])\n            cx = (int(row[\"x_min\"]) + int(row[\"x_max\"])) / 2 / w\n            cy = (int(row[\"y_min\"]) + int(row[\"y_max\"])) / 2 / h\n            bw = (int(row[\"x_max\"]) - int(row[\"x_min\"])) / w\n            bh = (int(row[\"y_max\"]) - int(row[\"y_min\"])) / h\n            \n            # Kiểm tra xem giá trị tọa độ đã hợp lệ chưa\n            if not (0 <= cx <= 1 and 0 <= cy <= 1 and 0 <= bw <= 1 and 0 <= bh <= 1):\n                print(f\"Skipping invalid label: {row}\")\n                continue\n\n            row = [str(row[\"class_id\"]), str(cx), str(cy), str(bw), str(bh)]\n            rows.append(\" \".join(row))\n        rows.append(\"15 0.5 0.5 1.0 1.0\")\n    \n    # Lưu file nhãn\n    f = open(savelabels_dir + img_id + \".txt\", \"w\")\n    f.write(\"\\n\".join(rows))\n    f.close()\n\n# Kết hợp tất cả các frame lại thành một DataFrame mới và lưu thành file CSV\nnew_df = pd.concat(frames)\nnew_df.to_csv('/kaggle/working/new_train.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-09-17T03:12:58.906393Z","iopub.execute_input":"2024-09-17T03:12:58.906716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport shutil\n\ndef copy_images(source_dir, destination_dir):\n  \"\"\"Sao chép tất cả các tệp hình ảnh từ thư mục nguồn đến thư mục đích.\n\n  Args:\n      source_dir: Đường dẫn đến thư mục chứa các hình ảnh nguồn.\n      destination_dir: Đường dẫn đến thư mục đích để sao chép hình ảnh.\n  \"\"\"\n\n  # Tạo thư mục đích nếu nó chưa tồn tại\n  os.makedirs(destination_dir, exist_ok=True)\n\n  # Duyệt qua tất cả các tệp trong thư mục nguồn\n  for filename in os.listdir(source_dir):\n      # Kiểm tra xem tệp có phải là hình ảnh hay không (dựa trên phần mở rộng)\n      if filename.endswith(('.jpg', '.jpeg', '.png', '.gif', '.bmp')):  # Thêm các phần mở rộng khác nếu cần\n          source_path = os.path.join(source_dir, filename)\n          destination_path = os.path.join(destination_dir, filename)\n\n          # Sao chép tệp\n          shutil.copy2(source_path, destination_path)\n#           print(f\"Đã sao chép {filename} đến {destination_dir}\")\n\n# Ví dụ sử dụng\nsource_dir = '/kaggle/input/amia-public-challenge-2024/train/train/'\ndestination_dir = '/kaggle/working/amia-public-challenge-2024/train/train/'\n\ncopy_images(source_dir, destination_dir)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\n\ndef count_files_in_directory(directory_path):\n  \"\"\"Đếm số lượng tệp trong một thư mục.\n\n  Args:\n      directory_path: Đường dẫn đến thư mục cần đếm tệp.\n\n  Returns:\n      Số lượng tệp trong thư mục.\n  \"\"\"\n\n  count = 0\n  for filename in os.listdir(directory_path):\n      file_path = os.path.join(directory_path, filename)\n      if os.path.isfile(file_path):  # Kiểm tra xem có phải là tệp (không phải thư mục)\n          count += 1\n  return count\n\n# Ví dụ sử dụng\ndestination_dir = '/kaggle/working/amia-public-challenge-2024/train/train/'\nfile_count = count_files_in_directory(destination_dir)\nprint(f\"Số lượng tệp trong thư mục đích: {file_count}\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!cat /kaggle/working/amia-public-challenge-2024/train/train/0FDQVdLgDKI1sRnPL94LzVh9EvXDVM9m.txt","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\nfrom sklearn.model_selection import train_test_split\n\ndf_train = pd.read_csv('/kaggle/working/new_train.csv')\ntrain, val = train_test_split(df_train, test_size=0.2)\n\ntrain_images_lst = train['image_id'].unique().tolist()\nval_images_lst = val['image_id'].unique().tolist()\n\n\ndef createImagesTxt(_images, filepath):\n    images_dir = '/kaggle/working/amia-public-challenge-2024/train/train/'\n    rows = []\n    for img_id in _images:\n        rows.append(images_dir + img_id + '.png')\n    f = open(filepath, \"w\")\n    f.write(\"\\n\".join(rows))\n    f.close()\n\n\ntrain_path = '/kaggle/working/train.txt'\nval_path = '/kaggle/working/val.txt'\ncreateImagesTxt(train_images_lst, train_path)\ncreateImagesTxt(val_images_lst, val_path)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from pathlib import Path\n\nconfig_file = Path('/kaggle/working/config.yaml')\n\n# Xóa nội dung hiện có của tệp nếu nó tồn tại\nif config_file.exists():\n    config_file.write_text(\"\")\n\n# Ghi nội dung mới vào tệp\nwith config_file.open('a') as f:\n    f.write(\"train: /kaggle/working/train.txt\\n\")\n    f.write(\"val: /kaggle/working/val.txt\\n\")\n    f.write(\"nc: 16\\n\")\n    f.write(\"names: ['Aortic enlargement','Atelectasis','Calcification','Cardiomegaly','Consolidation','ILD','Infiltration','Lung Opacity','Nodule/Mass','Other lesion','Pleural effusion','Pleural thickening','Pneumothorax','Pulmonary fibrosis','No finding','Finding']\\n\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Import các thư viện\nimport os\nimport cv2\nimport numpy as np\nfrom ultralytics import YOLO\nimport torch\nfrom ensemble_boxes import weighted_boxes_fusion\nfrom pathlib import Path\nfrom tqdm import tqdm\nimport matplotlib.pyplot as plt\n\n\ndef train_model(model_name, data_yaml, epochs=1, imgsz=640, mixup=0.5, batch_size=32, device='auto'):\n    \"\"\"\n    Huấn luyện mô hình YOLOv8 với các tham số cho trước và tự động chọn thiết bị (GPU/CPU).\n    \n    Parameters:\n    - model_name: tên mô hình.\n    - data_yaml: đường dẫn đến file cấu hình dữ liệu.\n    - epochs: số lượng epochs (mặc định 1).\n    - imgsz: kích thước ảnh (mặc định 640).\n    - mixup: tỷ lệ mixup (mặc định 0.5).\n    - batch_size: kích thước batch (mặc định 32).\n    - device: thiết bị sử dụng để huấn luyện, mặc định 'auto' để tự động lựa chọn thiết bị.\n    \"\"\"\n    \n    # Kiểm tra nếu sử dụng nhiều GPU hoặc CPU\n    if device == 'auto':\n        if torch.cuda.is_available():\n            num_gpus = torch.cuda.device_count()\n            if num_gpus > 1:\n                device = ','.join(str(i) for i in range(num_gpus))  # Sử dụng nhiều GPU\n            else:\n                device = '0'  # Sử dụng một GPU\n        else:\n            device = 'cpu'  # Nếu không có GPU thì dùng CPU\n    elif device == 'cpu':\n        device = 'cpu'\n    elif isinstance(device, str) and ',' in device:\n        # Nếu chuỗi device chỉ định nhiều GPU, ví dụ: \"0,1\"\n        device = device\n    else:\n        device = '0'  # Mặc định chỉ sử dụng GPU đầu tiên nếu có\n    \n    print(f\"Training on device: {device}\")\n    \n    # Chọn trọng số mô hình phù hợp (yolov8m.pt hoặc yolov8x.pt)\n    model_weights = 'yolov8m.pt'  # Thay đổi nếu cần thiết\n    \n    # Khởi tạo mô hình YOLOv8\n    model = YOLO(model_weights)  # Khởi tạo mô hình YOLOv8\n    \n    # Huấn luyện mô hình\n    model.train(\n        data=str(data_yaml),\n        epochs=epochs,\n        batch=batch_size,\n        imgsz=imgsz,\n        mixup=mixup,  # Thay đổi mixup từ 0 thành 0.5\n        project='amia_yolov8m_16class',\n        name=model_name,\n        augment=True,  # Bật data augmentation để tăng tính đa dạng của dữ liệu\n        iou=0.5,\n        device=device,  # Sử dụng GPU hoặc CPU theo cấu hình\n        exist_ok=True,\n        verbose=True   # Log đầu ra\n    )\n    \n    return model\n\n# Huấn luyện các mô hình\n\n# Mô hình 1: trained labels-1 on all images\nmodel1 = train_model(\n    model_name='yolov8m_16class',\n    data_yaml='/kaggle/working/config.yaml'\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}