/2023-MAICON

국방 AI 경진대회 일반인 부문 DeepFake 분류 모델 개발

Primary LanguageJupyter Notebook

2023 MAICON

개요

생성 딥러닝 모델의 발전으로 유용한 형태의 데이터를 생성할 수 있게 되었지만 동시에 우리는 지능형 사이버 위협에 노출되어있습니다. 특히 원본 영상을 변조하여 생성되는 딥페이크(DeepFake) 영상은 진위 여부를 가리기 여러워 적으로부터 보안, 국방에서의 심각한 공격으로 이어질 수 있습니다. 따라서 원본 영상과 딥페이크 영상을 구분하는 AI 모델을 설계하여 이러한 위협으로부터 기술적으로 탈피하고자 합니다. 각각 3500개의 원본 영상과 딥페이크 영상으로 감지 모델을 만들고 Public 및 Private 영상으로 검증합니다.

EDA

  • 학습 데이터의 구조는 아래와 같습니다.
dataset/
  - train/
    - fake/
        - fake_video_1.mp4
           ...
        - fake_video_3500.mp4
    - real/
        - real_video_1.mp4
           ...
        - real_video_3500.mp4
    - test/
        - video_1.mp4
          ...
  • 학습데이터는 3500개의 fake video와 3500개의 real video로 구성되어 있습니다.
    • real 데이터는 15초에서부터 1분 50초 까지 다양한 길이를 가집니다.
    • fake 데이터는 대부분 15-20초 내외의 길이를 가집니다.
  • 영상은 제한된 환경에서 촬영되었습니다.
    • 정지한 화자의 얼굴이 화면 정 중앙에 등장하고 정해진 대사를 말합니다.
    • 오디오는 없습니다.
    • Fake 비디오의 경우 얼굴 부분의 눈코입만 변조되었습니다.
      • Fake 비디오의 형태로 미루어보아 Keypoint Detection 이후에 target에 붙여넣기 하는 방식으로 만들어진 DeepFake로 추정됩니다.
  • 우리가 찾아야하는 DeepFake는 영상의 중앙에만 존재하기 때문에 YOLO v5 모델로 얼굴을 detect 하여 사용하였습니다.
    • YOLO v5 모델은 얼굴이 아닌 사람 class만 존재해 얼굴보다 더 넓은 영역을 탐지하므로, 탐지영역의 약 50% 영역을 CenterCrop 하였습니다.
    • 이 방법을 적용하고 72%에서 90%까지 Public Accuracy 성능 향상이 있었습니다.
  • DeepFake에서 느낄 수 있는 어색함은 source face와 target face 사이의 색감이 불일치하여 발생합니다
    • 이것을 정량적으로 나타내는 Co-occurrence matrix를 도입하여 같이 모델에 feed합니다.
    • 이 방법을 적용하고 90%에서 96%까지 Public Accuracy 성능 향상이 있었습니다.

Method

아래 세가지 방법 사용을 고민

  1. 3D Conv for some frames
  2. CNN + RNN or Transformer for video
  3. CNN for one frame

하나의 영상이 DeepFake로 만들어진 영상이면 모든 프레임에 DeepFake가 적용되었다고 판단하여 3의 방법을 채택

GAN based or Diffusion으로 Deepfake 영상을 생성하기 때문에 관련 논문을 탐색하였음 On the detection of synthetic images generated by diffusion model 논문을 통해 저수준에서의 특정한 pattern이 존재하며 저수준의 정보를 활용하는 방법을 사용해야겠다고 생각하였음.

최종적으로 Detecting GAN generated Fake Images using Co-occurrence Matrices의 방법론과 FCN을 사용하기로 결정하였음

Code
# rgb이미지 픽셀의 상하좌우 4방향으로 co-occurrence matrices를 반환하는 함수
def _get_co_occurrence_matrix(self, frames):
    frames = torch.squeeze(frames, 0) # (3,256,256)

    # 이미지를 그레이스케일로 변환
    transform = transforms.Grayscale()
    gray_image = transform(frames)

    # PyTorch Tensor를 NumPy 배열로 변환하고 [0, 255] 범위로 스케일 조정
    gray_image_np = (gray_image.numpy() * 255).astype(np.uint8)

    # Co-occurrence matrix 계산
    distances = [1, 2, 3]  # 거리 설정
    angles = [0, np.pi/4, np.pi/2, 3*np.pi/4] # 방향 설정

    co_occurrence_matrices = []
    for channel in range(gray_image_np.shape[0]):
        co_occurrence_matrix = graycomatrix(gray_image_np[channel], distances=distances, angles=angles, levels=256, symmetric=True, normed=True)
        co_occurrence_matrices.append(co_occurrence_matrix)

    # 각 채널별로 계산된 co-occurrence matrix를 합치기
    co_occurrence_matrix_combined = np.stack(co_occurrence_matrices, axis=0) # (1, 256, 256, 3, 4)
    co_occurrence_matrix_combined = torch.from_numpy(co_occurrence_matrix_combined)
    co_occurrence_matrix_combined = torch.squeeze(co_occurrence_matrix_combined, 0)
    co_occurrence_matrix_combined = rearrange(co_occurrence_matrix_combined, 'w h x y -> (x y) w h') # (12,256,256)
    co_occurrence_matrix_combined = torch.unsqueeze(co_occurrence_matrix_combined ,0)
class CustomModel(nn.Module):
    def __init__(self, num_classes=1):
        super().__init__()
        self.effi = timm.create_model("efficientnet_b0", pretrained=True)
        self.effi.conv_stem = nn.Conv2d(15, 32, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
        self.effi.bn2 = nn.Conv2d(1280, 64, kernel_size=1, stride=1)
        self.effi.drop = nn.Identity()
        self.effi.act = nn.Identity()
        self.effi.global_pool = nn.Identity()
        self.effi.classifier = nn.Flatten()
        self.fc = nn.Sequential(
            nn.Linear(4096, 1000),
            nn.ReLU(inplace=True),
            nn.Dropout(p=0.3),
            nn.Linear(1000, 1)
        )
    
    def forward(self, x):
        # concat with entropy map
        x = self.effi(x)
        x = self.effi.global_pool(x)
        x = self.effi.classifier(x)
        x = self.fc(x)
        x = F.sigmoid(x)
        return x

Conclusion

최종 모형은 3개의 모델(EfficientN(co_occurrence_matrix 미사용), EfficientNetB0(co_occurrence_matrix 사용),ResNet152)의 각각 가중치 2::2:1 소프트 보팅 앙상블 기법 사용하여 예측 수행

co-occurence yolo 1x1 inception voting public LB(ACC)
X X X X 60
O X X X 73
O O X X 90
O O O X 95.9
O O O O 96.6

아쉬웠던 점 이론적 접근에 대해서 아쉬웠던 점은 주어진 과제의 데이터 타입은 동영상으로 연속적인 이미지의 집합이라고 할 수 있다. 이러한 연속적인 이미지 사이의 시계열성 정보, 프레임 간의 상관성을 고려하고 이를 모델에 반영하지 못 했던 부분이 아쉬웠다. 기술적 접근에 대해서 아쉬웠던 점은 input image를 동영상 중 하나의 프레임으로 시도했었는데 Deepfake가 적용되는 주요 부분이 얼굴만 detection 하여 이 결과를 input으로 주는 시도를 했다면 시간적 측면에서 좀 더 유리하게 가져갈 수 있었을 것 같다.

최종 등수는 정량평가 70%와 정성평가 30%를 합산하여 산정되었으며, 총 15팀 중 5등(제네시스 랩 후원기업상)으로 마무리하였습니다.

아쉬운 점

  1. 시계열 계열 모델을 적용해보지 못 한 것 (프레임 별 상관성)
  2. 시간에 쫓겨 데이터를 더 살펴보지 못했음