• 티스토리 홈
  • 프로필사진
    Cat_Code
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
Cat_Code
  • 프로필사진
    Cat_Code
    • 분류 전체보기 (117)
      • [네이버 부스트캠프] (46)
        • ⭐주간 학습 정리 (43)
        • 🎶추가 학습 정리 (3)
      • [연습의 흔적들] (27)
        • 백준⚾ (26)
        • 캐글 & 데이콘 🤝 (1)
      • [ML] (23)
        • 머신러닝 💕 (5)
        • 딥러닝 🔫 (10)
        • 데이터 분석 🖤 (1)
        • 수학 ☑️ (4)
        • LLM🦜 (3)
      • [CS] (17)
        • 파이썬 🖤 (13)
        • 해체 분석기📝 (3)
        • Service Product (1)
        • MultiMedia (0)
      • [개발일지] (2)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
        등록된 공지가 없습니다.
      # Home
      # 공지사항
      #
      # 태그
      # 검색결과
      # 방명록
      • [궁금한건 못참아]라이브러리 vs. 직접구현
        2023년 11월 16일
        • Cat_Code
        • 작성자
        • 2023.11.16.:01

        피어슨 상관계수와 코사인 유사도에 글을 정리하던 중

        이미 해당 공식들은 numpy나 scipy에 존재했다 

         

        피어슨 상관계수?

         

        [머신러닝+선형대수] 상관관계와 코사인 유사도

        통계와 머신러닝에서 가장 근본적이면서 중요한 분석 방법은 상관관계를 분석하는 것이다 상관관계를 살펴보기 위해서는 상관계수를 구하는 방법이 있다 상관계수는 -1 부터 +1까지의 범위로

        eumgill98.tistory.com

         

        이때 갑자기 의문점이 하나 생겼다

         

        과연 직접 구현함 함수와 라이브러리에 있는 함수의 속도 차이가 존재할까?

         

        오늘은 이런 의문점을 해결하기 위해서 간단한 실험을 진행해 보았다

         

        실험 설계 

        오늘 비교할 공식 재료 : `피어슨 상관계수`

         

        비교할 대상

        (1) 직접 구현한 피어슨 상관계수 함수

        (2) Numpy의 np.corrcoef

        (3) Scipy의 stats.pearsonr

         

        이때 직접 구현한 상관계수 함수는 아래와 같다

        def corrcoef(v1, v2):
          v1m = v1 - np.mean(v1)
          v2m = v2 - np.mean(v2)
        
          return np.dot(v1m, v2m) / (np.linalg.norm(v1m) * np.linalg.norm(v2m))

         

         

        비교 방법

        (1) 해당 함수들의 인자로 들어가는 vector의 size를 순차적으로 늘려가면서 비교해본다.

         

        (2) 해당 함수들의 인자로 들아가는 vector의 value에 따른 차이도 비교한다.

         

        (3) 해당 함수들을 각각 연속적으로 수행하는 횟수를 늘려 비교한다.

         

        실험결과

         

        조건

        - 10^10 범위의 랜덤 값을 같는 배열의 길이를 순차적으로 증가시키며 비교

         

        3000까지의 길이를 증가했을때 sicpy가 압도적으로 느렸음

        numpy와 직접 구현을 비교했을 때는 아래와 같음

        큰 차이는 없었지만 미세하게 직접구현이 빨랐음

         

        | 알수 있는 것 |

        - Scipy의 경우 `피어슨 상관계수` 뿐만 아니라 `p-value`까지 계산을 하기 때문에 연산에서 조금더 오래걸리는 것 같다

        - 직접구현이 numpy 보다 빨라보임

         

        | 코드 |

        # 실험 1
        def ex1(max_v, iter):
          """
          max_v : range of values
          iter : max_num of vector
          """
          result = defaultdict()
        
          for num in tqdm(range(2,iter+1)):
            v1 = np.random.randint(max_v, size=num)
            v2 = np.random.randint(max_v, size=num)
            
            #case1
            tic = time.time()
            corrcoef(v1, v2)
            t1 = time.time() - tic
        
            #case2
            tic = time.time()
            np.corrcoef(v1, v2)
            t2 = time.time() - tic
        
            #case3
            tic = time.time()
            pearsonr(v1, v2)
            t3 = time.time() - tic
        	
            #값 저장
            result[num] = [t1, t2, t3]
          
          return result

         

        이때 문제점으로 보이는 지점을 발견했다

        중간중간에 time이 높은 이상치들이 존재 -> 이는 배열의 value의 크기에도 영향을 받아서가 아닐까하는 생각이 들었다

        따라서 배열의 value를 동일한 값으로 고정한채 (1로 고정) 배열의 길이만 증가시켜보기로 했다

         

        수정된 조건

        - 배열의 value를 1로 고정

         

        갑자기 scipy의 속도가 가장 빨라졌다??

        아무래도 values의 영향도 있는 것 같다

         

        직접구현과 numpy 비교했을때 아직도 numpy의 속도가 더 느렸다

         

        | 알수 있는 것 |

        - 아무래도 value의 영향도 존재한다

        - sicpy가 느린건 p-value 때문이 아니라 value의 크기때문?

        def ex2(iter):
          """
          iter : max_num of vector
          """
          result = defaultdict()
        
          for num in tqdm(range(2,iter+1)):
          	#모든 값을 1로 고정
            v1 = np.ones(num)
            v2 = np.ones(num)
            
            #case1
            tic = time.time()
            corrcoef(v1, v2)
            t1 = time.time() - tic
        
            #case2
            tic = time.time()
            np.corrcoef(v1, v2)
            t2 = time.time() - tic
        
            #case3
            tic = time.time()
            pearsonr(v1, v2)
            t3 = time.time() - tic
        
            result[num] = [t1, t2, t3]
          
          return result

         


        이번에는 최대 배열의 크기를 3000에서 30만까지 증가 시켜서 진행해 보았다. (참고로 오래걸림)

        참고로 values는 1로 고정했다 - 예상 scipy가 가장빠를 듯

         

        놀랍게도? scipy가 가장 빨랐다

        그리고 진짜 놀란건 직접 구현이 가장 오래 걸렸다는 것 -> numpy가 역전!

         

        아무래도 배열의 크기가 증가하면 numpy와 직접구현의 차이가 사라지는듯하다

        왜? 

         


        이번에는 각 함수별로 연산을 지정횟수 만큼 반복했을 때 걸리는 시간을 비교해 보았다

        즉, 지정횟수가 300번이라고 했을때

        직접구현 300번 걸리는 시간, numpy 300번 걸리는 시간 ... 비교

         

        앞 그래프에서 차이점이 잘 보이지 않아서 이를 중첩시켜 차이를 늘려보기 위해서 이다

         

        조건)

        -300 길이의 벡터까지 각 함수를 500번씩 반복 수행

        -values는 1로 고정

        이방법을 통해서 조금더 차이점을 눈으로 볼 수 있었다 

        왜냐하면 차이가 존재한다면 반복 수행할 수록 그 차이는 더 벌어질 것이기 때문이다

         

        역시 배열의 길이를 짧게 했을때는 직접 구현이 numpy 보다 빨랐다

         


        각 함수의 반복을 10배 올려 5000번으로 수정해 보았다

        먼가 시계열 데이터 같이 변했다 - 일정한 주기로 증가하고 감소하는 부분은 CPU 클록 차이인가 하는 생각도 해본다


        마지막으로 values를 1 고정이 아니라 범위 안에서 랜덤값으로 지정해서 실햄해 보았다

        처음에 한방법과 지정반복횟수를 합친 방법으로 수행한 것이다

        역시 values의 값을 변경하니 scipy 시간이 가장 오래 거렸다...

         

        def ex4(max_v, iter, loops):
          """
          max_v : range of values
          iter : max_num of vector
          loops : 반복횟수 지정
          """
          result = defaultdict()
        
          for num in tqdm(range(2,iter+1)):
            v1 = np.random.randint(max_v, size=num)
            v2 = np.random.randint(max_v, size=num)
            
            #case1
            tic = time.time()
            for i in range(loops):
              corrcoef(v1, v2)
            t1 = time.time() - tic
        
            #case2
            tic = time.time()
            for i in range(loops):
              np.corrcoef(v1, v2)
            t2 = time.time() - tic
        
            #case3
            tic = time.time()
            for i in range(loops):
              pearsonr(v1, v2)
            t3 = time.time() - tic
        
            result[num] = [t1, t2, t3]
          
          return result

        결론

        - Scipy는 value의 크기의 영향을 많이 받는다 - 아무래도 p-value 연산 때문인가? 

        - 참고로 Scipy는 numpy 기반이다 그래서 더 걸리는 것 일 수도 

        - 직접 구현이 numpy보다 빠르다 (in 피어슨 상관계수)

        - 하지만 이는 피어슨 상관계수를 구하는 함수에만 국한 된 것이기 때문에 전체 라이브러리의 속도 차이는 아니다

        - 일반화 하지 말것...

         

         

        +) 입력 벡터 형태를 넘파이 array가 아니라 list일 경우 달라질 수도? (변환과정이 추가되니까)

        입력을 리스트로 넣었을때 scipy와의 속도는 더 벌어지고 직접구현과 numpy의 차이는 줄어들었다

        벡터의 크기가 작을때는 직접 구현이 더 빨랐지만 벡터의 사이즈가 증가했을 때는 차이점이 사라지는 것 같았다

         

        '[CS] > 해체 분석기📝' 카테고리의 다른 글

        [궁금한건 못참아] 다양한 이미지 포맷.. 보이지 않는 너머에 대해  (1) 2023.11.15
        [Einops] 차원관리의 새로운 차원  (0) 2023.10.17
        다음글
        다음 글이 없습니다.
        이전글
        이전 글이 없습니다.
        댓글
      조회된 결과가 없습니다.
      스킨 업데이트 안내
      현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
      ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
      목차
      표시할 목차가 없습니다.
        • 안녕하세요
        • 감사해요
        • 잘있어요

        티스토리툴바