AI / ML 공부를 하면 무조건(?) 사용하게 되는 "주피터 노트북(Jupyter Notebook)"

 

pandas, numpy, scikit-learn 등 착실하게 공부를 해야하는 것은 맞지만

모든 것들을 외워서 사용하기에는 어려움이 많고, 또 일일이 타이핑을 하는 것이 효율적이지도 않다.

 

그래서 Jupyter Notebook을 사용하면서 도움을 주는 기능들에 대해서 하나씩 알아보자.

 

 

① 자동 완성(auto complete) : Tab

  - IDE를 사용하거나 리눅스 커맨드 창에서 bash 또는 zsh 등을 사용할 때, 가장 많이 사용하는 tab !!!

  - 그런데, Jupyter Notebook에서 아래와 같이 타이핑을 하다가 tab을 눌러도 .... 아무런 반응이 없다.

 

 

  - import를 먼저 실행해서 "pd"가 뭔지 알려줘야 자동완성 기능을 사용할 수 있게 된다.

 

 

② 툴팁 (Tool Tip) : Shift + Tab 

  - 함수의 파라미터(parameter)들이 뭐가 있는지 확인하고 싶다면? Shift-Tab을 눌러주면 된다 !!!

 

 

③ 툴팁 (Tool Tip) : ?

  - pop-up으로 뜨는 툴팁이 조금 불편하다면, "?"를 이용해도 된다.

  - 함수명 뒤에 "?"를 타이핑하고, 실행을 시키면 밑에 출력이 된다.

 

 

 

④ Display parameter : set_config

  - scikit-learn의 model을 사용하다보면 parameter들을 확인해보고 싶을 때가 있다.

 

 

  - model에서 명시적으로 입력한 parameter 값만 확인이 되는데,

  - 현재 default로 지정된 parameter 값을 포함해서 전체 내역을 확인하고 싶을 때가 있다

 

  - scikit-learn 환경설정을 통해서 해결할 수 있다.

 

 

  - 이제 어떤 parameter로 해당 모델이 실행되는지 눈으로 확인할 수 있다 !!!

 

 

⑤ 도움말 (Help) : help

  - 자고로 도움말은 help !!!

 

 

  - 예쁘게 출력되진 않지만, 많은 정보를 보여준다.

 

반응형

게임 관련해서는 거의 포스팅하지 않았었는데...

연휴가 길어지다보니 게임 관련해서도 포스팅하는 일이 벌어지고 있다 ^^

 

라떼를 찾는 나이를 많이 먹어버린 아저씨이다보니 오래된 게임들을 애정하고 있고

그 중 가장 애정하는 것은 SFC (슈퍼 패미콤) 이다.

 

하지만, 애정만으로는 그래픽의 아쉬움을 달랠 수가 없기에

최근에는 PS2 (플레이스테이션2) 게임을 아주 애정하고 있다 !!!

 

이런 history를 갖고 있기에

SFC 시절에 좋아했던 게임을 PS2로 만나면 더더욱 애정할 수 밖에 없다.

 

"로맨싱 사가 (Romacing SaGa)"를 SFC 시절에 즐길 때에도 그 음악이 뭔가 매력적이었는데,

PS2로 리메이크 되면서 뭔가 음악과 아주 친화적인 제목인

"로맨싱 사가 - 민스트럴 송 (Romacing SaGa - Minstrel Song)"라는 이름으로 출시 되었다.

 

 

게임 시작하자마자 음유시인 처럼 생긴 서부 총잡이(?)가 기타를 치면서 노래를 부르는 인트로 영상이 나온다.

"Minstrel" 이라는 단어 자체가 "음유시인"이라는 뜻이다 !!!

 

이 게임은 "사가 (SaGa)" 시리즈의 하나라고 한다.

그러면 '사가'는 어떤 의미일까?

 

출처 : https://dict.naver.com/dict.search?query=사가

 

한글 '사가'와 같은 의미이지 않을까 싶다 ^^

 

 

SFC (슈퍼 패미콤)에서 Romancing Sage는 1 / 2 / 3 가 나왔었고,

그 중 1992년도에 출시된 1에 해당하는 것이 2005년도에 PS2로 리메이크 되면서

"로맨싱 사가 - 민스트럴 송 (Romacing SaGa - Minstrel Song)"으로 나온 것인데,

 

일어판은 첫 화면에 "민스트럴 송 (Minstrel Song)"이라는 부제목이 같이 나오는데,

영문판(북미판)에서는 희한하게 사라졌다.

 

 

8명의 주인공 중에 한 명을 선택해서 진행하는 방식인데,

어떤 주인공을 선택하느냐에 따라 다른 스토리로 진행이 되는데

선형적이지 않고 비선형적으로 진행이 되는 오픈월드 방식이라서 게임 진행이 쉽지 않다.

 

게임 자체가 그다지 친절하지 않다.

 

 

여러 나라의 많은 도시가 보인다. 왠지 두렵다 ^^

 

 

내가 선택한 '클라우디아'는 황녀이지만, 신변 보호를 위해 저 할머니가 숲에서 기르고 있다.

 

 

전투 방식은 턴제 인데... 전투 횟수에 따른 제약이 존재한다.

 

레벨업을 위해 무식하게 전투를 많이 하게 되면 ... 시나리오 진행을 할 때 뭔가 스킵되거나 하기도 하고 ...

그렇다고 전투를 피해 다니면 레벨업을 못해 지나가던 보스에게 한 대 얻어맞고 죽어버리고 ...

게임 진행 시간 제약이 있는 이벤트도 있고 ...

 

공략집 없이 진행하기에는 쉽지 않은 게임이다.

다들 VGL 공략집과 함께 하라는 조언을 해주는 게임이다.

 

하지만, 뭐 그냥 혼자서 묵묵히 진행할 수는 있을 것 같다.

뭐 꼭 Good Ending을 봐야 하나 ?! ㅋㅋㅋ

 

 

PS2 게임기로 하다가 눈치가 보여서 (아무리 명절이라지만 ... 거실 TV에서 게임을 하고 있자니 ...)

에뮬레이터로 실행했는데, 잘 된다.

 

뭔가 힐링이 되는 게임을 하고 싶은 상황이기에, 살짝 맛만 보고 껐다 ^^

전투 제한이나 시간 제한 있는 게임은 심장이 너무 두근거려서....

늙은이 건강에 해로워....

반응형

Chapter 06

 

어느덧 6주차까지 왔다. 혼공 완주 !!!

스스로에게 칭찬해줘야지 !!! 쓰담~ 쓰담~

 

▶ 내용 요약

06-1 객체지향 API로 그래프 꾸미기

- pyplot 방식과 객체지향 API 방식

 

 

- 그래프에 한글 출력하기

  . 한글 폰트가 필요하기 때문에, 나눔폰트를 설치해야 한다.

  . 예제에서는 구글 코랩에 대해서만 설명되어 있지만, 일반적인 Ubuntu 환경에서도 적용된다.

 

 

  . 사용할 수 있는 폰트 목록을 확인해볼 수도 있다.

  . 사용할 폰트를 지정할 수도 있고, 크기도 정할 수 있다.

 

 

  . 잘 되는지 확인해보자.

 

 

- 출판사별 발행 도서 개수 산점도 그리기

  . 교재와는 다르게, 내가 이용하는 도서관의 데이터로 진행해봤다.

 

 

  . 모든 데이터가 아닌 Top 30 출판사를 뽑아서 사용한다.

 

 

  . 산점도를 그리면 된다!

 

 

  . Marker 크기를 확인하거나 설정을 할 수도 있다.

  . 그냥 점이 아니라 크기에 따라 의미를 부여해보자. (대출건수)

 

 

- 맷플롯립의 다양한 기능으로 그래프 개선하기

 

 

 

 

06-2 맷플롯립의 고급 기능 배우기

- 실습준비하기

  . 한글 폰트 설치 및 도서관 CSV 파일 읽어오기 (앞에서 진행했던 내용 활용)

 

- 하나의 피겨에 여러 개의 선 그래프 그리기

  . 대출건수 크기가 유사한 출판사 2개를 선택해서 그려보자

 

 

  . 레전드를 표현하거나 모든 출판사 정보를 그려보거나 해보자.

 

 

  . 피봇 테이블을 이용해서 데이터를 만들어서 stackplot으로 그려보자.

 

 

 

- 하나의 피겨에 여러 개의 막대 그래프 그리기

 

 

  . 나란히 나오도록 할 수도 있다.

 

 

  . 2개의 bar 그래프를 합쳐서 그리는 2가지 방법이 있다.

 

 

 

  . 데이터 값 누적한 것을 그려보기 위해서 데이터를 먼저 확인해보자

 

 

  . cumsum()을 이용해서 누적 데이터를 만들 수 있다.

 

 

- 원 그래프 그리기

  . 10개 출판사를 뽑아서 pie를 그리면 된다.

 

 

  . startangle 및 여러 옵션들을 줘서 멋진 원 그래프를 만들 수 있다.

 

 

- 여러 종류의 그래프가 있는 서브플롯 그리기

  . 앞에서 살펴본 것들의 종합판이다!

 

 

  . 한 방에 모두 그려진다!!!

 

 

- 판다스로 여러 개의 그래프 그리기

  . DataFrame에서 바로 그래프를 그릴 수도 있다.

 

 

 

 

▶ 기본 미션

p.344의 손코(맷플롯립의 컬러맵으로 산점도 그리기)를 코랩에서 그래프 출력하고 화면 캡쳐하기

 

→ 코랩이 아닌 로컬 환경에서 실행해봤다 ^^

 

 

 

 

▶ 선택 미션

p.356~359의 스택 영역 그래프를 그리는 과정을 정리하기

 

① 기본 데이터 준비

  - 작업 준비 과정이다.

 

 

② 그래프로 표현할 데이터 만들기

  - Top30 출판사 기준으로 "출판사 / 발행년도 / 대출건수"를 추출하고,

  - "출판사 / 발행년도" 기준으로 그룹핑을 하면서, 대출건수는 sum()을 했다.

  - 전체적으로 reset_index()까지 해줬다.

 

 

③ pivot_table()

  - 발행년도를 X축으로 하고, 출판사를 Y축으로 하고, 대출건수를 데이터로 하는 테이블을 만든다.

 

 

④ get_level_values()

  - pivot_table()을 사용했다보니, column이 다단으로 구성되어 있다.

  - 이런 경우 원하는 레벨의 값만 추출하기 위해 get_level_values()를 사용했다.

 

 

⑤ stackplot()

  - 이제 그래프를 그리면 된다.

 

 

우와~~~ 다했다!!!!

반응형

출처: https://www.whatwant.com

 

기사 작위를 갖고 계시는 '토니 호어'로 불리우시는 분이 1961년에 발표한 정말 정말 유명한 알고리즘이다.

이름 그대로 제일 빠른 정렬 알고리즘이 뭐야? 라고 하면 누구나 외치는 "퀵 정렬" !!!

(참고로 '토니 호어'님은 아직도 시니어 연구원으로 계신다고 한다. 무려 90세의 나이임에도 .... @.@)

 

출처: https://en.wikipedia.org/wiki/Quicksort

 

[ 공부 목차 ]

① Partition

② Balanced partitioning vs Unbalanced partitioning

③ Randomized-Partition

④ Quick-Sort

 

 

① Partition (vanilla Partition)

  - 'Quick Sort'에 있어서 가장 중요한 개념이 바로 partition 이다.

 

출처: https://www.whatwant.com

 

  - 기준값(Pivot element) 보다 작은 값은 왼쪽에, 큰 값은 오른쪽에 배치하여 나누는 것을 의미한다.

  - 가장 기본이 되는 partition 방법은 제일 오른쪽 값을 pivot으로 해서 하나씩 비교하는 것이다.

 

출처: https://www.whatwant.com

 

  - 제일 오른쪽 값을 기준으로 제일 왼쪽부터 하나씩 비교해서 작은값 그룹과 큰값 그룹을 만들어 간다.

  - 그런데, "1"값을 만났을 때 작은값 그룹에 묶을 때가 문제가 된다.

 

출처: https://www.whatwant.com

 

  - 이럴 때에는 큰값의 제일 왼쪽에 위치한 것과 swap을 하면 된다. (i값 위치의 변화도 살펴봐야 한다)

  - 이렇게 하다보면 끝까지 진행을 하게 될텐데, 마지막에 위치한 pivot 값은 어떻게 해야할까?

 

출처: https://www.whatwant.com

 

  - 역시 마찬가지로 큰값의 제일 왼쪽값과 swap 하면 된다.

  - 이 과정을 pseudo code로 살펴보면 다음과 같다.

 

출처: https://www.whatwant.com

 

  - Running Time을 계산해보면 다음과 같다.

 

출처: https://www.whatwant.com

 

 

② Balanced partitioning vs Unbalanced partitioning

  - partitioning을 할 때에 좌우 균형이 잘 맞춰져서 나뉘어지면 좋겠지만,

  - 그렇지 않고 한 쪽에 치우칠 수도 있다.

 

출처: https://www.whatwant.com

 

  - 균형이 맞지 않는 극단적인 경우를 보면 다음과 같다.

 

출처: https://www.whatwant.com

 

  - Running Time은 다음과 같이 구할 수 있다.

 

출처: https://www.whatwant.com

 

  - 즉, 최악의 상황에서는 n제곱, 보통은 n로그n 이라고 정리하면 되겠다.

  - 그러면, 최악의 상황을 막을 방법은 없을까!?

 

③ Randomized-Partition

  - 최악의 상황이 발생하는 것은 pivot 값을 무조건 제일 끝값을 택하기 때문에 발생을 한다.

  - 그러면, pivot 값을 random하게 선택을 하게 되면 최악의 상황이 벌어질 가능성을 낮출 수 있다.

 

출처: https://www.whatwant.com

 

  - random하게 값을 뽑아서, 그것을 제일 오른쪽(끝) 값과 swap을 한 다음에 partition을 하면 되는 것이다.

 

출처: https://www.whatwant.com

 

  - 그런데, radom 호출 하는 것 자체가 over-head가 될 수도 있다. radom 자체가 비용이 크기 때문이다.

  - 그래서, (첫값 + 가운데값 + 끝값) 3개 중에 중간값을 선택하는 방법도 있긴 하다.

 

 

④ Quick-Sort

  - 지금까지 우리는 Partition을 공부했다. 이를 이용해서 Sort는 어떻게 할 수 있을까!?

 

출처: https://www.whatwant.com

 

  - 일단 partition을 한 다음, 왼쪽/오른쪽 각각 QuickSort를 하면 된다.

  - 그렇다 !!! Divide-and-Conquer 알고리즘이다.

 

출처: https://www.whatwant.com

 

  - Quick-Sort의 Running Time은 어떻게 될까?

 

출처: https://www.whatwant.com

 

  - 메모리 사용은?! 위치를 가르칠 변수 정도면 충분하다. 즉, 입력 데이터의 크기에 영향을 받지 않는다.

 

 

 

지금까지 여러 Sorting algorithm을 알아봤는데, 성능 비교 등을 해보면 좋을텐데...^^

다음 기회로~~~

 

반응형

Chapter 05

 

뭔가 내가 대단해진 것 같은 느낌!!! 그 이유는? 책의 절반을 넘겨서?! ^^

 

▶ 내용요약

5-1 맷플롯립 기본 요소 알아보기

  - plt.figure(figsize=(x, y)) : 그래프 크기
  - plt.figure(dpi=d) : DPI
    . plt.figure(figsize=(x/d, y/d)) : 이처럼 계산하면 크기를 계산하면서 조절할 수 있다
  - plt.rcParams[parameter] : 관련 속성값을 확인하거나 설정할 수 있음
  - fig, axs = plt.subplots() : 그래프 묶음 관리. axs 를 통해 각 그래프를 지

 

5-2 선 그래프와 막대 그래프 그리기

  - plt.plot() : 선 그래프

plt.plot(count_by_year.index, count_by_year.values)
plt.title('Books by year')
plt.xlabel('year')
plt.ylabel('number of books')
plt.show()

  - marker='.', linestyle=':', color='red' : 꾸미기 옵션
    . '*-g' : 여러 옵션을 한 방에 해치우기
  - plt.xticks() : 눈금값 설정하기

plt.plot(count_by_year, '*-g')
plt.title('Books by year')
plt.xlabel('year')
plt.ylabel('number of books')
plt.xticks( range(1947, 2030, 10) )
plt.show()

  - plt.annotate() : 값 텍스트 출력
    . xytext : 출력 위치 보정
    . textcoords : 상대값으로 위치 보정

plt.plot(count_by_year, '*-g')
plt.title('Books by year')
plt.xlabel('year')
plt.ylabel('number of books')
plt.xticks( range(1947, 2030, 10) )
for idx, val in count_by_year[::5].items():
  # plt.annotate(val, (idx, val), xytext=(idx+1, val+10))
  plt.annotate(val, (idx, val), xytext=(2, 2), textcoords='offset points')
plt.show()

  - plt.bar() : 막대 그래프

plt.bar(count_by_subject.index, count_by_subject.values)
plt.title('Books by subject')
plt.xlabel('subject')
plt.ylabel('number of books')
plt.xticks( range(1947, 2030, 10) )
for idx, val in count_by_subject.items():
  plt.annotate(val, (idx, val), xytext=(0, 2), textcoords='offset points')
plt.show()

  - plt.annotate() : 값 텍스트 출력
    . fontsize : 폰트 크기
    . ha : 정렬

plt.bar(count_by_subject.index, count_by_subject.values, width=0.7, color='blue' )
plt.title('Books by subject')
plt.xlabel('subject')
plt.ylabel('number of books')
plt.xticks( range(1947, 2030, 10) )
for idx, val in count_by_subject.items():
  plt.annotate(val, (idx, val), xytext=(0, 2), textcoords='offset points',
               fontsize=9, va='center', color='green')
plt.show()

  - plt.barh() : 막대 그래프 (세로)
    . height : 막대의 높
    . plt.annotate(va='center') : 정렬 (세로)

plt.barh(count_by_subject.index, count_by_subject.values, height=0.7, color='blue' )
plt.title('Books by subject')
plt.xlabel('subject')
plt.ylabel('number of books')
plt.xticks( range(1947, 2030, 10) )
for idx, val in count_by_subject.items():
  plt.annotate(val, (val, idx), xytext=(2, 0), textcoords='offset points',
               fontsize=8, ha='center', color='green')
plt.show()

 

 

그래프에 대한 용어 파악을 위해 캡쳐&편집 해봤다.

(이런 정성을 보여야 우수 혼공족이 될 것 같은 욕심이........ 😁)

 

anotion

 

▶ 기본 미션

p. 314의 손코딩(맷플롯립에서 bar()함수로 막대 그래프 그리기)을 코랩에서 그래프 출력하고 화면 캡처하기

 

코랩에서는 다른 분들도 많이 할테니, 나는 나만의 환경에서~ ^^

 

 

① 데이터 불러오기 및 컬럼 정리

  - 지난 번에 '발행년도'를 int64로 만들기 위해 별의별 짓을 다 했는데 ... 간단히 끝냈다. 이런....

 

 

 

② 그래프 그리기

  - 나는 왜 매번 이상한 결과가 나오지!? ㅠ

 

 

 

③ sort_index

  - 'count_by_year' 의 index 값이 제대로 정렬이 되지 않아서 발생한 이슈이다.

  - 그래서, sort_index를 해줘야 한다.

 

 

 

④ graph

  - 이제 다시 그래프를 그려보자.

 

그런데, 미래에 출간된 책들은 정체가 뭘까!?

 

 

▶ 선택 미션

p. 316의 손코딩(텍스트 정렬, 막대 조절 및 색상 바꾸기)을 코랩에서 출력하고 화면 캡처하기

 

① 데이터 불러오기 및 컬럼 정리

  - 책에 있는 내용대로 데이터를 만들었다.

 

 

② graph

  - 이거... 바로 결과가 나오니 뭔가 불안하다. 뭐지 ?!

 

 

 

 

주말에 가족여행이 있어서, 조금 서둘러 공부했다 !!! 아자 !!! 아자 !!!

반응형

Chapter04. 데이터 요약하

 

정신없이 달리다보니 어느덧 반환점을 돌고 있다. 앗싸~!!!

 

▶ 내용 요약

04-1. 통계로 요약하기

- df.describe()
  . 25%/50%/75% 가 아닌 다른 범위를 알고 싶을 때 : df.describe(percentiles=[0.3, 06, 0.9])
  . object 컬럼의 값 통계를 보고 싶을 때 : df.describe(include='object')


- 일반적인 수학 함수
  . df.mean() / df.median() / df.max() / df.min()


- df.quantile() / sr.quantile() : 분위수
  . df.quantile(0.25)
  . df.quantile([0.25, 0.5, 0.75])


- df.var() : 분산
  . 평균을 먼저 구한 뒤, 평균과 각 데이터 차이를 제곱해서 더한 뒤 데이터 갯수로 나눔


- df.std() : 표준 편차
  . 분산에 루트를 씌운 값

 

import numpy as np

diff = df['대출건수'] - df['대출건수'].mean()
np.sqrt( np.sum(diff**2) / (len(df) - 1) )


- df.mode() : 최빈값. 제일 자주 나오는 값


04-2. 분포 요약하기

- 산점도 : plt.scatter(df['column1'], df['column2'], alpha=0.1)


- 히스토그램
  . plt.hist(df['column1'], bins=5) : y축 폭을 5로 해서 그려라
  . plt.historgram_bin_edge(df['column1'], bins=5)

 

- 상자 수염 그림
  . 상자에서부터 1.5배 IQR 거리 안에서 가장 멀리 떨어져 있는 것 까지 표시

 

plt.boxplot( df[ ['column1', 'column2'] ])
plt.yscale('column')
plt.show()

 

 

▶ 기본 미션

p. 279의 확인 문제 5번 풀고 인증하기

 

기본 미션

 

우와 문제 스케일이 좀 크다 ^^

 

① 데이터 확보

  - https://www.data4library.kr/ 접속해서 데이터를 확보하자.

  - '데이터 제공' 탭을 통해서 데이터를 내려 받을 수 있다.

 

도서관 정보나루

 

② 데이터 읽어들이기

  - 다운로드 받은 데이터를 불러들여서 기본 모양을 살펴보자.

  - 특히, encoding을 신경써야 한다 !!! (정부차원에서 이거 그냥 UTF-8 쓰도록 강제해야하는 것 아닌가)

pd.read_csv()

 

③ Column 상태 확인 및 수정

  - '발행년도'를 가지고 통계를 내야 하는데, 수치형이 맞는지 확인하고, 아니아면 변경을 해야한다.

 

astype()

 

  - 그런데, 위와 같이 에러가 발생한다.

  - 이유는 제일 밑에 나와 있다. "2022(2021)"처럼 입력되어 있는 데이터가 있다보니 casting이 안되는 것이다.

 

  - '("를 포함한 데이터가 얼마나 있는지 확인해보고, '(*)' 부분을 삭제하도록 하자.

 

replace()

 

  - 다시 casting 해보자.

 

error

 

  - 또 에러가 나온다. 숫자가 아닌 데이터가 많은 것 같다.

  - 확인해보자.

 

숫자가 아닌 데이터

 

  - 이거.... 쉽게 갈 수 있는 길을 너무 어렵게 가는 것 같은데....

  - 일단 '.'을 포함한 것들이 많아 보이니 이를 먼저 처리해보자.

 

replace()

 

  - 아직도 243개나 남았다.

  - 데이터를 한 번 더 확인해보고 처리해보자.

 

replace()

 

  - 이제 85개 밖에 안남았다.

  - 데이터 확인해보고, 숫자가 아닌 것들을 전부 날려버리자.

replace()

 

  - astype()을 적용하기 위해서는 ''(공백), NaN 값이 있으면 안된다.

  - ''(공백)을 NaN으로 변환하고, NaN을 모두 0으로 변환해 astype()을 돌리자.

 

astype()

 

  - 드디어 int64 dtype으로 변환되었다.

 

④ draw Histogram

  - 이제 Boolean Indexing을 이용해서 원하는 범위를 한정하고, histogram을 그리면 된다.

histogram

 

 

▶ 선택미션

Ch.04(04-1)에서 배운 8가지 기술통계량(평균, 중앙값, 최솟값, 최댓값, 분위수, 분산, 표준편차, 최빈값)의 개념을 정리하기

 

일반적인 개념 정의는 너무나 잘 정리된 내용이 여기 저기 많이 있으므로 ^^

앞에서 만든 데이터를 가지고 직접 확인해보면서 살펴보겠다.

 

발행년도에 따른 대출건수가 어떻게 되는지를 scatter() 로 표현해봤다.

 

scatter()

 

8가지 기술통계량을 직접 확인해보자.

 

기술통계량

 

① max / ② min : 해당 값의 최댓값 / 최솟값

③ mean / ④ median

    . 평균값은 전체 데이터의 합을 전체 갯수로 나눈값이고,

    . 중앙값은 데이터를 줄 세웠을 때 중간 위치에 해당하는 실제값을 의미한다.

⑤ quantile

    . 분위수를 알려주는 것인데, 일반적으로는 IQR(InterQuartile Range, 사분범위) 사용

    . 명시적으로 원하는 분위수를 확인할 수도 있다.

⑥ var / ⑦ std

    . 분산은 각 데이터와 평균의 차이의 제곱의 총합을 전체 데이터 갯수만큼 나눠준 값이다.

    . 표준편차는 분산에 루트를 씌운 값이다.

⑧ mode

    . 최빈값은 데이터 값 중에서 가장 많은 빈도로 나오는 것을 의미한다.

 

 

우리 모두 파이팅 !!!

반응형

Chapter 03

 

어느덧 3주차 스터디까지 왔다! 와아 ~~~~ !!!

2주차 우수혼공족에 선정되어 간식 선물까지 받았다 ~~~ !!! 꺄아 ~~~~ !!!

 

우수혼공족

 

▶ 요약

3-1. 불필요한 데이터 삭제하기
- *.loc[]
  . slicing(슬라이싱)
    ( *.loc[:, '번호':'등록일자'] )
  . boolean array(불리언 배열)
    ( df.loc[:, df.column != 'map'] )
- *.drop()
  . 지칭하는 column을 삭제
    ( *.drop(column_name, axis=1) )
  . 지칭하는 row를 삭제
    ( *.drop([0,1]) # 0행, 1행을 삭제 )
- *.dropna()
  . NaN 값을 1개라도 갖고 있으면 column 삭제
    ( *.dropna(axis=1) )
  . NaN 값을 모두 갖고 있으면 column 삭제
    ( *.dropna(axis=1, how='all') )
- *.duplicated()
  . 지정한 columns의 값이 동일하면 중복된 행의 값을 리턴
    ( *.duplicated(subset=['도서명','저자','ISBN'], keep=False) )
- *.groupby()
  . 지정한 columns의 값이 동일한 것들을 묶어줌
    ( *.groupby(by=['도서명', '저자', 'ISBN', '권'], dropna=False).sum() )

3-2. 잘못된 데이터 수정하기
- *.info()
  . DataFrame의 다양한 통계를 보여주는 유용한 method
- *.isna()
  . NaN 값을 갖고 있는 column을 보여줌
    ( *.isna().sum() )
- Nan
  . None
  . np.nan
- *.fillna()
  . NaN 값을 갖고 있는 columns에 지정한 값을 채움
    ( *.fillna('없음') )
    ( *['부가기호'].fillna('없음') )
    ( *.fillna( {'부가기호':'없음'} ) )
- *.replace()
  . 값 exchange
    ( *.replace(np.nan, '없음') )
    ( *.replace( [np.nan, '2021'], ['없음', '21']) )
    ( *.replace( {np.nan: '없음', '2021' : '21']) )
    ( *.replace( {'부가기호': np.nan}, '없음') )
    ( *.replace( {'부가기호': {np.nan : '없음'}, '발행년도': {'2021' : '21'}} ) )
  . 정규표현식
    ( *.replace( {'발행년도': {r'\d{2}(\d{2})' : r'\1'}}, regex=True) )

 

 

▶ 기본 미션

p. 182의 확인 문제 2번 풀고 인증하기

 

[문제]

1번 문제의 df1 데이터프레임에서 'col1' 열의 합을 계산하는 명령으로 올바르지 않은 것은 무엇인가요?

 

 

df1['col1'].sum()

df1[['col1']].sum()

df1.loc[:, df1.columns == 'col1'].sum()

df1.loc[:, [False,False,True]].sum()

 

 

※ 위 문제에서 bold 표기한 부분은 책에서 잘못된 부분을 수정한 내용입니다.

    - 문제에서 "것은" 부분이 빠져있었습니다.

    - 보기에서 "df"가 아니라 "df1"이라고 해야합니다.

 

[풀이]

④ 에서 boolean으로 표기된 내역을 보면 [False,False,True]로 되어있기에 'col1'이 아니라 'col3'의 합계가 출력된다.

 

그러면, 이것을 검증해보자.

 

일단, 데이터를 준비해봤다.

NaN 값을 처리하기 위해 Numpy의 np.nan을 사용했다.

 

 

각 보기의 값을 확인해보자.

 

 

확인 끝~

 

 

▶ 선택 미션

p. 219의 확인 문제 5번 풀고 인증하기

 

[문제]

다음과 같은 df 데이터프레임에서 df.replace(r'ba.*', 'new', regex=True)의 결과는 무엇인가요?

 

보기는 생략.

 

※ 위 문제에서 bold 표기한 부분은 책에서 잘못된 부분을 수정한 내용입니다.

    - 문제에서 "같은" 부분이 빠져있었습니다.

 

[풀이]

정규식을 이용한 replace() 문제이다.

정규식을 보면 r'ba.*' 부분을 살펴보면 'ba'로 시작하는 문자열을 지칭하고 있다.

그래서 'ba'로 시작하는 문자열을 'new'로 바꿔치기하면 된다.

 

교재(책) 보기로 보면 ③ 번에 해당하는 결과가 정답이 된다.

 

이것을 검증해보자.

 

 

 

이번 Chapter는 비교적 수월했다.

남은 기간 스스로에게 파이팅 !!!

 

반응형

이번에 살펴볼 정렬 알고리즘은 "Heap Sort(힙 정렬)"이다.

 

[출처] ChatGPT + WHATWANT

 

보통은 위키피디아의 animated-gif 를 통해서 정렬 알고리즘을 엿볼 수 있었는데,

heap-sort 경우에는 도저히 파악이 안되는 내용이라 다른 자료를 찾아봤다. (내가 무지해서 이해를 못한 것이겠지...)

 

[출처] https://www.cs.usfca.edu/~galles/visualization/HeapSort.html

 

너무나 친절한 Visualization을 제공해주는 곳은 다음과 같다.

- https://www.cs.usfca.edu/~galles/visualization/HeapSort.html

- 왼쪽 상단의 "Heap Sort" 버튼을 클릭하면 animation을 보여준다.

 

[출처] https://www.cs.usfca.edu/~galles/visualization/HeapSort.html

 

왜 저렇게 정렬이 되는지 바로 이해가 되시는 분은 그만 공부하셔도 된다!!! ^^

 

사실 공부하기 전에는 대체 어떤 이유로 이렇게 움직이는 것인지 잘 보이지 않아야 정상일 것 같다 ^^

우리에게 필요한건?

 

공부!!!

 

Heap Sort를 알기 위해서는 일단 Heap이 무엇인지 부터 알아야 한다.

 

⑴ Heap의 정의

⑵ MAX-HEAPIFY()

⑶ BUILD-MAX-HEAP()

⑷ HEAP-SORT

 

 

⑴ Heap

Heap은 2가지의 속성을 갖고 있다. 이에 대해서 알아보자.

 

  ① A nearly complete binary tree

  ② max-heap

 

① A nearly complete binary tree

일단 tree 구조와 관련한 용어부터 확인해야 이야기가 쉬울 것 같다.

 

[출처] https://www.whatwant.com

 

tree 관련한 용어들이 더 있지만, 일단 이 정도만 알아도 될 것 같다.

 

그러면, tree 구조 관련하여  "complete binary tree"가 뭔지부터 파악하고

"nearly complete binary tree"가 뭔지 이해해보도록 하자.

 

[출처] https://www.whatwant.com

 

▷ Complete Binary Tree

  - all leaves the same depth

  - all internal nodes have degree 2

 

그러면 nearly complete binary tree는 어떻게 생겼을까!?

 

[출처] https://www.whatwant.com

 

▷ A Nearly Complete Binary Tree

  - 기본적으로는 Complete Binary Tree 구조를 갖고자 

  - all internal nodes have degree 2, but 마지막 leaf는 1개가 부족할 수 있다.

  - 마지막 depth의 leaves는 왼쪽부터 차례대로 배치

 

 

우리가 공부하고자 하는 Heap 구조는 바로 이 "nearly complete binary tree"를 따르고 있다.

 

왜 그럴까!?

 

▷ Array

 

"nearly complete binary tree" 구조를 따를 경우에 이를 array 방식으로 표현하기가 쉽기 때문이다.

반대로 말하면 array를 사용하기 위해서는 nearly complete binary tree 구조여야 한다!!!

 

[출처] https://www.whatwant.com

 

이렇게 되면 어떤 장점이 있을까?

 

[출처] https://www.whatwant.com

 

그렇다 ! 위치에 대한 계산이 가능해진다 !!!

 

여기에서 하나 더 확인해볼 것은 "The height of a heap"이다.

 

▷ The height of a heap

  - 기본적으로 height는 depth와 같은 개념이고, 특정 node를 기준으로 depth가 얼마인지를 의미한다.

  - The height of a heap = The height of the root : 그러면 depth의 의미이다.

  - 그러면, 여기에서 질문 하나

    : 어떤 Heap의 전체 node의 갯수(n)를 알면 height가 얼마인지 알 수 있을까?

 

[출처] https://www.whatwant.com

 

  - height를 h라고 하면, 다음과 같다.

 

[출처] https://www.whatwant.com

 

② max-heap

'binary heap'은 max-heaps와 min-heaps의 2가지 종류가 있다.

 

앞에서는 tree 구조에 대해서만 이야기 했지, 각 node에 들어있는 값에 대해서 이야기하지 않았다.

이제는 각 node에 들어있는 값에 대한 이야기이다.

 

[출처] https://www.whatwant.com

 

위 그림을 보고 오해를 하면 안된다.

당연하게도 모든 parent-child 를 살펴봐도 모두 저 관계를 만족해야 한다.

 

그러면 제일 위의 root node에 들어있는 값은 전체 모든 node 중에서 가장 큰 값이 위치하게 된다.

 

min-heap은 반대이다. root node가 가장 작은 값을 갖는다.

 

우리는 보통 max-heap을 사용한다.

 

 

⑵ MAX-HEAPIFY()

"Max-Heapify" 함수에 대해서 알아보겠다.

함수이기에 입력(input)과 출력(output)이 있고, 그 과정에서 어떤 처리(processing)이 있을 것이다.

 

① input

  - 입력은 어떤 하나의 node가 된다.

 

[출처] https://www.whatwant.com

 

   - 단, 그 노드가 갖고 있는 왼쪽/오른쪽의 subtree들이 이미 max-heap 구조를 갖고 있어야 한다.

 

② float down

  - "4" node를 기준으로 왼쪽/오른쪽 subtree가 각각 max-heap이기에 max-heapify 가능

  - 그래서 "4" 값과 "14"값을 exchange

  - 그런데, "4" node를 봤더니 max-heap 상태가 아님

  - subtree 들은 각각 max-heap 상태이기에 max-heapify 실행

  - 그래서 "4"와 "8"값 exchange

  - 그랬더니, 처음 "4"에서 실행한 max-heapify가 전체적으로 이루어짐

 

[출처] https://www.whatwant.com

 

이렇게 밑으로 흘러가듯이 이루어지는 과정을 "float down"이라고 

 

③ running time

  - max-heapify의 running time을 알아보자.

 

[출처] https://www.whatwant.com

 

 

⑶ BUILD-MAX-HEAP()

max-heap을 만드는 것에 대한 Pseudo Code를 살펴봅시다!!!

 

[출처] https://www.whatwant.com

 

Text에서 floor 함수 표기가 쉽지 않아 조금 이상하게 보이는 부분은 이해해주시길 바라옵니다 ^^

 

일단 A는 max-heap을 하고자 하는 입력 데이터를 의미한다.

 

[출처] https://www.whatwant.com

 

그러면, 밑의 순환문은 어떤 의미일까!?

 

[출처] https://www.whatwant.com

 

그러므로, 순환문의 시작 위치는 다음과 같다.

 

[출처] https://www.whatwant.com

 

그 다음 index가 하나씩 감소하기 때문에 다음과 같은 흐름으로 진행하게 된다.

 

[출처] https://www.whatwant.com

 

전체 길이의 절반 위치에서 시작하는 것은 그 이후의 node는 edge-node 즉, leaves 들이기 때문에

이미 max-heapify가 되어 있어서 굳이 max-heapify를 할 필요가 없는 것이다.

 

▷ Running time

① Upper bound

  - Pseudo code를 기반으로 해서 찬찬히 살펴보면 다음과 같이 실행 시간(횟수)를 확인할 수 있다.

 

[출처] https://www.whatwant.com

 

이를 계산하면 다음과 같이 정리가 된다.

 

[출처] https://www.whatwant.com

 

 

② Tighter bound

 

그런데, 실제로 분석해보면 이는 지나친 upper-bound라고 볼 수 있다.

즉, 이것 보다는 조금 더 tighter-bound를 계산해볼 수 있는 것이다.

 

1번 node 기준으로 max-heapify를 한다고 했을 때, "n = 10" 이므로 O(log 10) 소요시간이 걸린다.

그러면, 5번 node 기준으로 max-heapify를 하면 소요시간이 얼마나 걸릴까?

 

[출처] https://www.whatwant.com

 

5번 node 위치에서의 "n = 2" 이므로 O(log 2) 소요시간이 걸린다.

4번 node 위치에서는 O(log 3), 3번 node 위치에서도 O(log 3) 이다.

 

즉, 실제로 많은 node에서 소요되는 시간이 우리가 계산한 O(log n) 값보다 작다는 것이다.

 

[출처] https://www.whatwant.com

 

이걸 고려해서 계산을 해보면 다음과 같다.

 

[출처] https://www.whatwant.com

 

엇?! 선형(linear)으로 정리가 되었다 !!!

 

⑷ HEAP-SORT

이제 마무리 단계에 왔다.

앞에서 공부한 것들을 모두 모아서 정렬하는데에 어떻게 사용할 수 있는지 Pseudo Code로 살펴보자.

 

[출처] https://www.whatwant.com

 

응!? 이건 뭔가 싶다.

 

▷ Extract-Max

  - BUILD-MAX-HEAP() 실행을 마치면, root-node에 있는 값이 가장 큰 값이 되게 된다.

 

[출처] https://www.whatwant.com

 

  - root-node에 있는 값을 제일 뒤에 있는 node와 교환을 한다.

  - 제일 뒤에 있는 node를 제외한 tree를 가지고, root-node에서 MAX-HEAPFY()를 실행한다.

  - 이 방식 가능한 이유는 이미 BUILD-MAX-HEAP()을 통해, 그 밑의 subtree들이 max-heap 상태이기 때문이다.

 

 

▷ Running Time

  - Pseudo Code를 가지고 수행 시간을 살펴보자.

 

[출처] https://www.whatwant.com

 

  - Worst-case는 이렇게 되겠지만, Best-case는? 모든 것이 같은 값일 때 !!!

  - 5번 라인의 경우 값이 하나씩 줄어들기 때문에, 시간이 조금씩 더 적게 들겠지만 유의미하지는 않다.

  - 결론적으로 Heap-Sort의 Running Time은 다음과 같이 정리할 수 있다.

 

[출처] https://www.whatwant.com

 

▷ Memory

  - Heap-Sort는 추가적인 메모리가 필요하지 않은 in-place 알고리즘이다.

  - 별도의 메모리 공간이 아니라 node 사이의 값을 exchange하는 것으로 처리되기 때문이다.

 

 

우아앙~ 너무 힘들었다.

반응형

+ Recent posts