[DL 프로젝트: 패션 스타일 분류 앱 'FASI'] 1. 개요 및 무신사 스냅 사진 크롤링

개요

목적

  • 설정한 포지션에서 적합한 데이터셋 구한 뒤 그에 맞는 가설을 세우고 검증한다.
  • 가설 검증을 위한 딥러닝 파이프라인을 구축한다.

설명

관심 데이터 선정

  • 원하는 도메인의 데이터를 선정한다.

데이터 선정 이유

  • 선정한 데이터와 그 데이터를 가공하면서 얻은 지식과 경험을 어느 부분에 적용해 볼 수 있을 지 생각해서 기록한다.

데이터를 이용한 가설 수립

  • 데이터를 선정함과 동시에 무엇을 해볼 수 있을 지 가설을 세운다.

데이터 전처리

  • 데이터를 가공한다.
    • 데이터 정규화
    • 노이즈 및 이상치(Outlier) 제거
    • 타겟 레이블(Label or Ground Truth) 생성 혹은 선택 등

딥러닝 방식 적용

  • 굳이 딥러닝을 적용해야 하는 지 확인한다.
  • 딥러닝의 큰 장점은 ‘어려운 문제를 더 어렵게 풀지만, 그 결과가 끝내주게 좋다.’라는 것이다.
  • 너무 쉬운 문제에 딥러닝을 적용한다거나 DL이 아닌 ML 방법론보다 더 많은 리소스를 하는데도 성능이 낮으면 안된다.

찬스 레벨(Chance Level)이 넘는 지 확인

  • 딥러닝을 적용한 결과가 찬스 레벨보다 월등하게 좋은 성능을 기록하는지 체크한다.
  • 그렇지 않다면 데이터를 다시 보거나 모델을 뜯어보면서 내 가설이 틀렸을 수 있다는 것을 확인한다.

모델 검증

  • 성능이 어느정도 나왔다면, CV를 통해서 일반화될 가능성이 있는 지 확인한다.
  • K-Fold 교차 검증을 통해 일반화가 어느정도 되는 지 알 수 있다.
  • 하이퍼파라미터를 변경하며 최적화까지 해볼 수 있다.

Requirements.txt 제작 및 재구현

  • 딥러닝 모델을 다시 사용할 수 있도록 저장하고 새로운 환경에서도 동작할 수 있도록 만든다.

기준

  • 문제 설정(데이터셋을 사용하여 어떤 문제를 풀고자 하는 지)
  • 모델 선택(모델을 설정한 이유)
  • 모델 학습(데이터 전처리 및 입력)
  • 한계점과 추후 해결 방안

데이터 수집

패션에 관심이 많고 사랑하는 사람으로써, 매 프로젝트마다 패션 도메인으로 진행해보고 싶다는 생각은 있었지만, 적절한 주제를 찾지 못했다.
비로소 딥러닝을 배우고 원하는 프로젝트를 진행할 수 있게 됐다.
데이터에 대해 접하고 나서 언젠가 데이터를 활용하여 초개인화된 서비스를 만들고 싶은 마음이 컸다.
그래서 이번 프로젝트의 주제를 ‘패션 스타일 분류’로 정했다.

만약 패션에 관련된 커뮤니티가 형성되고, 개개인의 옷사진을 분석하여 데이터화할 수 있다면 추천 알고리즘에 큰 도움이 되지 않을까란 생각을 했다.
굳이 커뮤니티가 아니더라도 각종 SNS 등에 게시 된 사진으로도 개인화 광고 등에 유용하게 쓰일 수 있을 거라 판단하여 컴퓨터 비전 모델링을 진행하고자 한다.

필요한 데이터

일단 스타일 별 전신 패션 이미지가 필요하다.
전부터 알고 있었던 ‘무신사 커뮤니티의 스트릿 스냅’ 이미지를 사용하고자 한다.
무신사에 소속된 리포터가 촬영한 사진으로 남성 5가지, 여성 7가지의 스타일(스트릿/힙합, 심플/캐주얼, 포멀/클래식, 유니크/키치, 걸리시, 섹시/페미닌)로 분류 되어있어 손쉽게 분석에 활용할 수 있어 기쁘다.
여러장의 이미지를 손쉽게 다운로드하기 위해 셀레니움을 활용하여 크롤링을 하고자 한다.
BUT! 저작권자의 저작물은 소중하니 저작권관련 가이드라인을 찾아보았다.

image

다행히도 비상업적인 용도로 활용할 수 있었다.
기분좋은 마음으로 7가지의 스타일 당 600장 정도로만 크롤링을 진행한다.
(이번 프로젝트의 기간이 매우 짧기 때문에 욕심 부리지 않고 적절한 만큼의 데이터만 모은다. 혹시나 성능이 별로면 더 긁어와야징….)

DB에 저장해야 할까?

데이터를 모으기 전, 데이터 엔지니어링 복습도 할 겸 파이프라인 구축을 위해 적절한 데이터 베이스에 저장해볼까란 생각을 했다. 하지만 알아보니 이미지를 DB에 저장하는 것을 추천하지 않는다고 하는데 그 이유는 아래와 같다.

  • 이미지 크기가 3, 4메가 정도 되는 사진이라면 병목이 생긴다.
  • 용량을 많이 차지하고 로딩 속도가 느리다.
  • 관리가 복잡하고 비효율적이다.

정보가 유출되면 안되는 보안이 필요하지 않다면 일반적으로 이미지 메타 정보만 저장하고 나머지는 물리적인 파일에 저장하는 것이 좋다고 한다.

크롤링(Crawling)

  • 동적 웹 스크레이핑을 해야 하므로 셀레니움을 이용한다.

셀레니움(selenium) 설치

1
$ pip install selenium

크롬 웹 드라이버(Chrome WebDriver) 설치

  • 셀레니움은 웹드라이버를 통해 디바이스에 설치된 브라우저를 제어할 수 있다.
  • 웹 드라이버로 크롬을 사용한다.
  • 크롬 드라이버 다운로드
  • ‘chrome://version’로 현재 크롬의 버전을 확인하여 일치하는 드라이버를 사용한다.

image

image

  • 드라이버는 사용하고자 하는 py파일과 함께 배치한다.
    (다른 경로에 두고 지정해도 되지만 이게 더 편하다.)
  • py파일을 생성하여 크롤링을 진행하자!
  • 셀레니움을 이용한 무신사 스트릿 스냅 크롤링 코드는 아래와 같다.
  • 무신사 스트릿 스냅 크롤러 레포지토리 바로가기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# musinsa-snap-crawler.py
from urllib.request import urlretrieve
from selenium import webdriver
import os

path = '/Users/6mini/musinsa-snap-crawler/chromedriver' # chromedriver의 절대경로
driver = webdriver.Chrome(path)

page_num = 1 # 크롤링 시작 페이지
last_page_num = 10 # 마지막 페이지 설정
ordw = 'submitdate' # 정렬 순서(최신으로 설정)
'''
submitdate: 최신 순
hit: 조회 순
comment: 댓글 많은 순
inc: 추천 순
d_comment: 최신 댓글 순
'''
styles = ['01', '02', '04', '09', '11', '12', '14'] # 크롤링 할 스타일 설정
'''
01: 스트릿/힙합
02: 심플/캐주얼
04: 포멀/클래식
09: 유니크/키치
11: 걸리시
12: 섹시/페미닌
14: 워크/밀리터리
'''

for style in styles:
    while page_num <= last_page_num: # 자동으로 페이지가 이동되게 while문 사용
        url = 'https://magazine.musinsa.com/index.php?m=street&style=0{}&ordw={}&_mon=&p={}#listStart'.format(style, ordw, page_num)
        driver.get(url) # url 접속

        img_num = 0
        while img_num < 60: # 60 고정: 무신사 스트릿 스냅 페이지의 이미지 수 60장
            driver.find_elements_by_css_selector('.articleImg')[img_num].click() # 이미지 접속
            img_url = driver.find_elements_by_css_selector('.lbox')[0].get_attribute('href') # url 파싱 

            if not os.path.isdir(style): # 기본적으로 스타일 번호를 폴더로 지정, 폴더 없으면 생성
                os.mkdir(style)

            try:
                urlretrieve(img_url, '{}/{}-{}.jpg'.format(style, page_num, img_num)) # img_url에서 이미지 다운로드, style 폴더에 'page_num-img_num.jpg' 형태로 저장
            except : # 오류 시 오류 선언하고 pass
                print('some error!(style: {}, page num: {}, img num: {})'.format(style, page_num, img_num))
                pass

            driver.get(url) # 뒤로가기 대신 url 재접속을 사용(오류 최소화)
            img_num += 1
        page_num += 1
    page_num = 1 # 하나의 스타일에 대한 cycle이 다 돌고 재설정

스크린샷 2021-11-07 21 19 29

  • 몇몇 이미지의 경우 파싱되지 않는 경우가 생겨서 try, except문을 추가했다.
  • 8장을 제외하고 모두 다운받는데 총 4시간이 걸렸다.
  • 결과적으로 7가지 style 폴더에 ‘page_num-img_num.jpg’ 형태로 각 600장 총 4200장 저장된다.

image

  • 카테고리 별로 이름을 보기쉽게 변경해준다.

image

추가 크롤링

  • 안녕하세요. 전 미래에서 왔습니다.
  • 모델링 성능이 마음에 들지 않아 추가 크롤링을 진행했다.
  • 딱 두배가 되게끔 더 긁어왔다.
  • 스타일 별 1200장, 총 8400장의 이미지 데이터를 구축했다.

image

0%