종료
[제4차] 문제2. 생산설비 이상 진단하기 (중급)
2023.11.08 - 2023.11.13
138

     

    ❗️ 공지: 

     (11/13) 11월 13일 14:00 기점으로 결과 스코어가 0점일 경우 ‘제출중’으로 표시되는 버그가 수정되었습니다.

    • 채점 결과가 0점일 경우 새로고침을 하여도 채점중이라고 표시되는 버그가 있었으며, 현재는 해당 버그가 수정되어서 정상적으로 제출 완료 확인이 가능합니다.

     (11/10) (재공지) 11월 10일 14:30 기점으로 Pre-trained 모델 사용 규칙을 아래와 같이 공지합니다.

    본 대회의 Pre-trained 모델 사용 규칙에 대한 재공지를 드립니다, 대회 기간 중에 혼선을 드려 정말 대단히 죄송합니다..!

    금일 오전에 공지한 Pre-trained 모델 사용 불가 규정은 취소하고, 아래와 같이 재공지합니다

    • 본 대회 Pre-trained 모델 관련 규칙 안내
      • 사용 가능한 Pre-trained 모델
        • TensorFlow, TensorFlow Keras, PyTorch 프레임워크에서 제공하는 백본 네트워크의 사전학습 가중치
        • 또는 위의 사항에 준하는 범용 아키텍처의 개발 또는 배급자가 제공하는 사전학습 가중치로 범용 데이터 (COCO/ImageNet/CIFAR 등)으로 학습된 것 ((예: YOLO의 Darknet))
      • 사용 불가능한 Pre-trained 모델
        • 위에 명시된 범용 데이터셋 외의 데이터로, 본 태스크와 같이 전자부품을 대상 또는 포함하여 학습된 일체의 모델, 가중치의 사용을 금지함
      • 유의 사항
        • 위 1, 2의 경우 어떤 사전학습 모델을 사용했는지 제출시에 명시할 것(재현성 검증은 최초 상태에서 제출된 조건에 따라 학습부터 다시 시작해서 이루어짐에 유의)

    (11/10) (해당 공지 내용은 취소되었습니다.)11월 10일 10:00 기점으로 Pre-trained 모델 사용이 금지됩니다

    • Pre-tained 모델을 모두 사용하실 수 없습니다. Tensorflow나 PyTorch 등의 프레임워크에서 제공하는 범용 데이터셋으로 사전 학습된 백본도 모두 사용이 불가합니다.

    ■ (11/2) 11월 2일 13:30 기점으로 참가자격 조건이 완화되었으며 참가접수 기간 또한 연장되었습니다  

    • 참가자격 조건 : 팀 구성 시 usg 공유대학 필수 참여 학생을 팀 인원 수에 관계없이 1명으로 고정
    • 모집기간 : 참가모집 마감일이 11월 6일(월) 17:00에서 →  11월 10일(금) 23:59까지로 변경


     

    1. 문제 개요 🔩

    • 사람은 처음 본 물건이라도 비슷한 형상의 대상을 다른 환경에서 찾아낼 수 있는 능력이 있습니다. 
      하지만 지금까지의 지도학습 방식에서 모델은 학습에 사용한 형상, 환경에서만 정상적인 작업 수행이 가능합니다.
      만약 주어진 데이터의 형상과 추론해야 할 형상이 서로 같지 않다면 어떻게 접근하고 문제를 해결해야 할까요?
    • 본 과제에서는 낱개의 반도체 부품 이미지 데이터빈 기판(PCB) 이미지 데이터를 활용하여 조립된 형상 안에서 각 구성요소를 판별해내는 모델을(Object Detection) 만들게 됩니다.
    • 부품과 기판의 구성요소를 바탕으로 조립된 형상에 대한 디텍션이 가능하게끔 할 수 있는 솔루션/모델링/학습방법/데이터 전처리 방식에 대한 아이디어가 과제의 핵심입니다.
    • 완벽한 모델이 아니더라도 최대한 가능한 방식을 탐구합니다.
    • 데이터에 대한 상세한 설명은 [데이터] 탭을 참조하시면 됩니다. 
    • [데이터]의 상세 내용은 경진대회 시작 시, 공개 됩니다.

     

    2. 평가 방법 🧪

    • 본 대회의 평가에는 목적에 맞게 커스텀된 Macro F1 Score가 사용됩니다.
      • mAP가 아니라 F1이므로 참가자분들은 불필요한 중복 예측이 없도록 Non-Max Suppression 혹은 그에 준하는 정리 과정을 적용한 결과물을 제출하셔야 됩니다.

     

    각 항목별 개념은 다음과 같습니다.

    • F1 Score 계산 방식:
      • 위치와 클래스가 정확히 맞으면 TP
      • 둘 중 하나라도 틀리면 FP
      • 예측이 만들어지지 않은 레이블은 FN
         
    • Score 산출 과정 설명:
      1. 먼저 한 이미지 내의 모든 정답과 모든 예측 사이에 IoU를 계산합니다.
      2. 각 예측은 자신과 IoU가 0.5 이상인 정답 가운데 IoU가 가장 큰 정답에 할당됩니다.
         - 하나의 예측이 복수 정답에 할당될 수 없습니다.
      3. 각 정답은 위 할당 조건을 통과한 하나, 여럿, 또는 0개의 예측과 매칭됩니다.
         - 정답에 하나의 예측이 할당된 경우: 클래스도 맞으면 정답 클래스에 TP, 틀리면 FP로 간주합니다.
         - 정답에 여러 예측이 할당될 경우: IoU가 가장 큰 예측 하나를 진짜로 간주, 클래스도 맞으면 정답 클래스에 TP, 틀리면 FP 로 간주합니다.
         - 나머지 할당되었으나 IoU가 가장 크지 않은 예측들은 각각의 예측 클래스의 FP로 간주합니다.
         - 정답이 있으나 아무 예측도 할당되지 않은 경우 해당 정답 클래스에 FN로 간주합니다.
         - 아무 정답도 없는 구역에 생성된 예측은 해당 예측 클래스에 FP로 간주합니다.
      4. 조건에 따라 macro F1 score를 사용해 점수를 계산합니다.

     

     

    실제 사용되는 커스텀 스코어 코드는 다음과 같습니다. 

     

    import sys
    import json
    import numpy as np
    
    def intersection_over_union(boxes_labels, boxes_preds):
    
        # coco type label (x0, y0, w, h)
        x, y, w, h = boxes_labels
        x, y, w, h = float(x), float(y), float(w), float(h)
        box1_x1 = float(x)
        box1_y1 = y
        box1_x2 = x + w
        box1_y2 = y + h
        x, y, w, h = boxes_preds
        box2_x1 = x
        box2_y1 = y
        box2_x2 = x + w
        box2_y2 = y + h
        
        x1 = np.max([float(box1_x1), float(box2_x1)])
        y1 = np.max([float(box1_y1), float(box2_y1)])
        x2 = np.min([float(box1_x2), float(box2_x2)])
        y2 = np.min([float(box1_y2), float(box2_y2)])
    
        intersection = max((x2 - x1), 0) * max((y2 - y1), 0)
        box1_area = abs((box1_x2 - box1_x1) * (box1_y2 - box1_y1))
        box2_area = abs((box2_x2 - box2_x1) * (box2_y2 - box2_y1))
    
        epsilon = 1e-6 if box1_area + box2_area - intersection == 0 else 0
    
        return intersection / (box1_area + box2_area - intersection + epsilon)
    
    
    def macro_f1(gt, pr, th=0.5):
    
        tp = np.zeros(len(gt['categories']), dtype=int)
        fp = np.zeros(len(gt['categories']), dtype=int)
        fn = np.zeros(len(gt['categories']), dtype=int)
    
        tp_p = np.zeros(len(gt['categories']), dtype=int)
        fp_p = np.zeros(len(gt['categories']), dtype=int)
        fn_p = np.zeros(len(gt['categories']), dtype=int)
    
        for img in gt['images']:
            gt_img = [i for i in gt['annotations'] if i['image_id'] == img['id']]
            pr_img = [i for i in pr['annotations'] if i['image_id'] == img['id']]
            # print(pr_img)
            tp_temp = np.zeros(len(gt['categories']), dtype=int)
            fp_temp = np.zeros(len(gt['categories']), dtype=int)
            fn_temp = np.zeros(len(gt['categories']), dtype=int)
    
            # 해당 GT 이미지에 object가 있고
            if len(gt_img) > 0:
                gt_classes = [i['category_id'] for i in gt_img]
                # 해당 GT 이미지에 대한 예측이 있는 경우
                if len(pr_img) > 0:
                    ious = [intersection_over_union(i['bbox'], j['bbox']) for i in gt_img for j in pr_img]
                    # pr을 iou가 최대인 gt에 할당
                    ioumat = np.array(ious).reshape(len(gt_img), -1) # gt_dim:0, pr_dim:1
                    # assigned_indices = np.argmax(ioumat, axis=0) # pr을 gt에 할당해야 하므로
                    ioumat = ioumat * (ioumat.max(axis=0, keepdims=True) == ioumat)
    
                    # TP / FP / FN
                    pr_classes = [i['category_id'] for i in pr_img]
                    for i in range(len(gt_classes)):
                        assigned = sum(ioumat[i] >= th) # 할당 기준은 th 이상일 것
                        if assigned == 0: # 아무 오브젝트에도 예측되지 않은 정답은 해당 클래스 FN에 더함
                            fn_temp[gt_classes[i]] += 1
                        else:
                            if assigned > 1:
                                fp_temp[gt_classes[i]] += assigned - 1 # 중복 예측은 FP에 할당
                            if gt_classes[i] == pr_classes[ioumat[i].argmax()]:
                                tp_temp[gt_classes[i]] += 1
                    # 무엇에도 assign되지 않은 예측(모든 obj와 iou가 th 미만)은 해당 예측의 class에 FP로 더함
                    unassigned = np.where([np.all(ioumat[:,i] < th) for i in range(len(pr_classes))])[0]
                    if len(unassigned) > 0:
                        for j in unassigned:
                            fp_temp[pr_classes[j]] += 1
                # 해당 GT 이미지에 대한 예측이 없는 경우 모든 object를 FN에 추가
                else:
                    for i in range(len(gt_classes)):
                        fn_temp[gt_classes[i]] += 1
    
            # 해당 GT 이미지에 아예 object가 없는 경우
            else:
                # 해당 GT 이미지에 대한 예측이 있는 경우 모든 예측을 FP에 추가
                if len(pr_img) > 0:
                    pr_classes = [i['category_id'] for i in pr_img]
                    for i in range(len(pr_classes)):
                        fp_temp[pr_classes[i]] += 1
    
            # 전체 TP, FN, FN에 결과 추가
            if img['id'] in public_id:
                tp_p += tp_temp
                fp_p += fp_temp
                fn_p += fn_temp
            else:
                tp += tp_temp
                fp += fp_temp
                fn += fn_temp
    
        # macro 계산
        precision_p = tp_p / (tp_p + fp_p)
        recall_p = tp_p / (tp_p + fn_p)
        f1_score_p = (2 * precision_p * recall_p) / (precision_p + recall_p)
        # nan -> 0 추가
        f1_score_p[np.isnan(f1_score_p)] = 0
        f1_score_p = np.nanmean(f1_score_p)
    
        precision = tp / (tp + fp)
        recall = tp / (tp + fn)
        f1_score = (2 * precision * recall) / (precision + recall)
        # nan -> 0 추가
        f1_score[np.isnan(f1_score)] = 0
        f1_score = np.nanmean(f1_score)
        return f1_score_p, f1_score
     

     

     

    3. 결과 검증 🔍

    • 입상 대상자는 아래 저작물을 제출해야 합니다.
      • 모델 학습 코드 : 구글 Colab에서 작동하는 train.ipynb 및 필요한 파일(외부 파일 등) 공유
      • 모델 추론 코드 : 구글 Colab에서 작동하는 test.ipynb 및 필요한 파일(모델 가중치 등) 공유
      • 모델 설명서 : 아래 양식에 맞게 작성 후 입상후보팀에게 안내되는 메일에 회신으로 전달
    • 코드와 주석의 인코딩은 모두 UTF-8을 사용하여야 합니다.
    • 입상 대상이 되는 상위 제출 결과물은 재현성 검증 과정을 거쳐 순위를 확정짓게 됩니다.
      재현성 검증은 다음 세 단계를 거쳐 이루어집니다.
      1. 재추론 검증
        • 제출된 모델에서 주어진 데이터를 이용하여 결과가 정상 생성되는지 여부를 확인할 수 있도록 재추론합니다.
        • 원칙적으로 재추론을 통해 생성된 결과는 참가자가 실제 제출한 결과와 동일해야 합니다.
      2. 재학습 검증
        • 제출된 모델이 허가된 데이터만을 사용하여 학습되었는지, 학습된 모델은 제출된 결과를 재현할 수 있는지의 여부를 재학습을 통해 검증합니다.
      3. 소스코드 분석
        • 소스코드 표절, 미허가 데이터 사용, 모델 조건 불충족 여부 등을 소스코드 분석을 통해 검증합니다.
    • 재현성 검증에 문제가 발생하거나 소스코드 표절을 비롯한 치팅이 확인되는 경우 원칙적으로 해당 제출 결과는 무효처리됩니다.

       

    4. 대회 규칙 (중요) 📜 

    ※ 본 대회는 http://aifactory.space 의 회원가입을 완료한 회원이 아래 규칙에 대해 동의한 경우에만 참가 가능합니다.

    ※ 대회 참여 중 규칙에 위배되는 상황이 발생한 경우, 입상이 취소될 수 있습니다.

     

    스코어 관련

    이번 대회는 Public 스코어와 Private 스코어 total 점수로 최종 순위가 결정됩니다

    • Public 및 Private의 비율은 1:1
    • 대회기간 중에는 Public 스코어만 리더보드 상에 표출
    • 대회 종료시점 이후 Public 및 Private의 total 점수 및 그에 따른 최종 순위 공개

    팀 참가 관련

    • 팀(2인 이상 최대 4인), 최소 1인 이상  (✽팀 빌딩은 참가신청 이후에 [팀] 탭에서 진행하실 수 있습니다)
    • 팀 구성시 USG 공유대학 학생 1인 이상 참여 필수 

    대회 제출 관련

    • 해당 문제는 제출 관련 제한사항이 있습니다. 이전 제출 시점 기준으로 3시간 지난 시점부터 재제출이 가능하오니 이 점 참고 부탁드립니다.
    • 검증시에는 사용한 모든 데이터를, 전처리부터 처리과정의 모든 코드를 포함하여 스코어를 기록한 조건의 모델 학습/추론 코드와 함께 제출하여야 합니다.
    • 테스트 데이터는 학습에 사용하실 수 없습니다. (Pesudo-labeling 포함)
    • 본 대회 Pre-tainned 모델 관련 규칙 안내
      • 사용 가능한 Pre-trained 모델
        • TensorFlow, TensorFlow Keras, PyTorch 프레임워크에서 제공하는 백본 네트워크의 사전학습 가중치
        • 위의 사항에 준하는 범용 아키텍처의 개발 또는 배급자가 제공하는 사전학습 가중치로 범용 데이터 (COCO/ImageNet/CIFAR 등)으로 학습된 것 ((예: YOLO의 Darknet))
      • 사용 불가능한 Pre-trained 모델
        • 본 태스크와 같이 전자부품을 대상 또는 포함하여 개인, 기관, 단체에서 학습된 모델, 가중치의 사용은 일체 금지함.
      • 유의 사항
        • 위 1, 2의 경우 어떤 사전학습 모델을 사용했는지 제출시에 명시할 것(재현성 검증은 최초 상태에서 제출된 조건에 따라 학습부터 다시 시작해서 이루어짐에 유의)

    contact@aifactory.page

    대전광역시 서구 만년로 68 번길 15-20, 5 층 504호

    서울특별시 중구 세종대로18길 16, 804호

    사업자등록번호 871-81-01735