부스트 캠프 ai tech 3주 2일차 Data 시각화 (9)


Grid

  • 축과 평행한 선을 사용하여 거리 및 값 등을 보조적으로 알려준다
  • 색은 최대한 방해하지 않도록 무채색을 사용한다
  • Layer상 항상 맨 아래 오도록 zorder를 0으로 조정
  • axis를 이용해서 x, y축 또는 동시에 격자를 보이게 할 수 있다
  • which 를 이용하여 큰격자, 세부격자 등을 보이게 할 수 있다

추가적인 보조 처리

  • 보조선 긋기
    • axvline(), axhline()으로 수평선을 그을 수 있다
    • axvline(start, color, linestyle, zorder, alpha)
  • start : 선을 그어질 point
  • color : 색
  • linestyle : 선 스타일
  • zorder : z축 순서
  • alpha : 투명도 조절
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def drow_graph(x, y, d, function_name, y_lim, x_lim, minmax):
fig, ax = plt.subplots(1, 2, figsize=(16, 4))

ax[0].plot(x, y)
ax[0].set_title(f"{function_name}")

ax[1].plot(x, d)
ax[1].set_title(f"{function_name} (Derivative)")
if minmax:
ax[0].axhline(max(y), color="red", linestyle="--", zorder=1)
ax[0].axhline(min(y), color="blue", linestyle="--", zorder=1)
ax[1].axhline(max(d), color="red", linestyle="--", zorder=1, xmax=0.5)

for i in range(2):
ax[i].axvline(0, color="gray", linestyle="-", zorder=0)
ax[i].axhline(0, color="gray", linestyle="-", zorder=0)
ax[i].set_xlim(x_lim)
ax[i].set_ylim(y_lim)
ax[i].spines['top'].set_visible(False)
ax[i].spines['right'].set_visible(False)
  • 보조 면 추가하기
    • axvspan(), axhspan()으로 영역에 색을 칠할 수 있다
    • axvspan(start, color, linestyle, zorder, alpha)
  • start : 시작 point
  • end : 끝 지점
  • color : 색
  • linestyle : 경계 스타일
  • zorder : z축 순서
  • alpha : 투명도 조절
1
2
3
4
5
6
7
8
9
10
fig, ax = plt.subplots()

ax.set_aspect(1)
ax.axvspan(0,0.5, color='red')
ax.axhspan(0,0.5, color='green')

ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)

plt.show()

reference

부스트 캠프 ai tech 3주 2일차 Data 시각화 (8)


Facet

  • 분할을 의미한다
  • 화면상에 view를 분할하여 큰틀에서는 볼 수 없는 부분집합을 세세하게 보여줄 수 있다.

1. Figure & Axes

  • Figure는 그래프가 들어가는 큰 틀, Axes는 각 plot이 들어가는 공간을 말한다.
  • Figure는 항상 1개, Axes는 여러개가 존재할 수 있다.
  • 아래의 함수들로 N by M 의 Axes(subplot)들을 만들 수 있다.
    • plt.subplot()
    • plt.figure() + fig.add_subplot()
    • plt.subplots()
  • sharex, sharey를 통해 subplot끼리의 x축, y축의 범위를 통일 할 수 있다
  • squeeze를 False로 지정해서 subplot의 index를 n by m Matrix로 바꿀 수 있다.
    • 기본으로 True이기 때문에 1차원 배열로 나오게 된다
  • aspect을 통해서 눈금간의 간격의 길이를 설정 할 수 있다
1
2
3
4
fig = plt.figure(figsize=(12, 5))
ax1 = fig.add_subplot(121, aspect=1)
ax2 = fig.add_subplot(122, aspect=0.5)
plt.show()

2. Grid spec

  • css의 그리드 처럼 동일 크기 분할이 아닌 다양한 크기의 그래프를 그리고 싶을때 사용하는 방식이다
  • add_subplot
    • numpy의 slicing과 비슷하게 사용이 가능하다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
fig = plt.figure(figsize=(8, 5))
gs = fig.add_gridspec(3, 3)

ax = [None for _ in range(3)]

ax[0] = fig.add_subplot(gs[0, :2])
ax[0].set_title('gs[0, :]')

ax[1] = fig.add_subplot(gs[0:, -1])
ax[1].set_title('gs[0, -1]')

ax[2] = fig.add_subplot(gs[1:3, 0:2])
ax[2].set_title('gs[-1, 0]')

for ix in range(3):
ax[ix].set_xticks([])
ax[ix].set_yticks([])

plt.tight_layout()
plt.show()
  • subplot2grid((shape), (y, x), colspan = dx, rowspan = dy)
    • shape를 통해 그리고자하는 grid를 설정
    • y, x : 시작하고자하는 좌표값
    • colspan, rawspan : 할당하고자 하는 가로 세로 길이
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fig = plt.figure(figsize=(8, 5))
ax = [None for _ in range(6)]

ax[0] = plt.subplot2grid((3,4), (0,0), colspan=4)
ax[1] = plt.subplot2grid((3,4), (1,0), colspan=2)
ax[2] = plt.subplot2grid((3,4), (1,2), colspan=1)
ax[3] = plt.subplot2grid((3,4), (1,3), colspan=1,rowspan=2)
ax[4] = plt.subplot2grid((3,4), (2,0), colspan=3)

for ix in range(5):
ax[ix].set_title('ax[{}]'.format(ix)) # make ax title for distinguish:)
ax[ix].set_xticks([]) # to remove x ticks
ax[ix].set_yticks([]) # to remove y ticks

fig.tight_layout()
plt.show()

3. insert

  • subplot 내부에 subplot을 생성하는 방법이다.
  • ax.inset_axes()
    • Ax 내부에 subplot을 추가하는 방법
    • 메인 시각화를 해치지 않는 선에서 사용하자
1
2
3
4
5
6
7
8
9
10
11
12
fig, ax = plt.subplots()

color=['royalblue', 'tomato']
ax.bar(['A', 'B'], [1, 2],
color=color
)

ax.margins(0.2)
axin = ax.inset_axes([0.8, 0.8, 0.2, 0.2])
axin.pie([1, 2], colors=color,
autopct='%1.0f%%')
plt.show()
  • make_axes_locatable(ax)
    • Ax 사이드에 부가적인 정보를 주는 방법
    • 보통 colorbar로 많이 사용한다
1
2
3
4
5
6
7
8
9
10
11
fig, ax = plt.subplots(1, 1)

# 이미지를 보여주는 시각화
# 2D 배열을 색으로 보여줌
im = ax.imshow(np.arange(100).reshape((10, 10)))

divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)

fig.colorbar(im, cax=cax)
plt.show()

reference

부스트 캠프 ai tech 3주 2일차 Data 시각화 (7)


color

  • 시각화에서 색을 통해서 효과적으로 채널을 구분할 수 있다
  • 심미적인 요소 또한 시각화의 일부 요소이다
  • 전달하고 싶은 내용을 깔끔하게 색을 통해서 전달하는것이 주 목표이다
    • 꼭 화려한것이 답은 아니다

Color Palette

1. categorical color

  • Discrete, Qualitative등의 다양한 이름으로 불린다
  • 독립된 색상으로 구성되어 범주형 변수에 주로 사용된다
  • 이산적인 개별값을 나타낼때 적합하다
categorical

2. Sequential color

  • 정렬된 값을 가지는 연속형 변수에 적합나다
  • 연속적인 색상을 사용하여 표현한다
    • 어두운곳에서는 밝은색, 밝은 곳에서는 어두운색을 이용한다.
  • 색상은 단일 색조로 표현하는것이 좋다.
  • 대표적으로 github commit log의 색이 있다.
subplot

3. Divergence color

  • 연속형과 유사하지만 중앙을 기준으로 서로 다른색으로 나타난다
  • 상반된 값을 표현하는데 좋다(기온, 지지율 등)
subplot

그 외에 고려할 점

  • 다름을 보이기 위한 Highlighting을 색으로 표현 할 수 있다.
  • 보통 먼 색일수록 차이가 더 크게보이는 색상 대비를 사용한다.
  • 색약이나 색맹을 가지는 읽는 사람을 위해 색 선택을 고려할 필요가 있다.

reference

부스트 캠프 ai tech 3주 2일차 Data 시각화 (6)


Text

  • 시각화에 적절한 Text는 시각적인것으로만 전달하기 힘든 설명을 추가하거나 잘못된 전달에서 생기는 오해를 방지 할 수 있다
  • 하지만 과한 Text는 오히려 방해가 될 수 있으니 주의할 필요가 있다

1. Anatomy of a Figure

  • Title : 그래프의 주제
  • Label : 축에 해당되는 데이터 정보
  • Tick Lable : 축의 grid의 스케일 정보
  • Legend : 한 그래프에서 여러개의 데이터 분류를 위한 보조 정보
  • Annotation : 그 외의 시각화를 위한 보조정보
1
코드 추가 필요

2. Text Properties

  1. font Components

    • family : 글씨체
    • size or fontsize : 사이즈
    • style or fontstyle : 스타일(기울임체 등등)
    • weight or fontweight : 두께
    • matplot Docs Fonts Demo
  2. Detail

    • color : 글씨의 색
    • linespacing : 줄간격
    • backgroundcolor : 배경색
    • alpha : 투명도
    • zorder : z축 순서
    • visible : 랜더 유무
  3. 정렬

    • ha : horizontal alignment
    • va : vertical alignment
    • rotation : 가로로 적을지 세로로 적을지 설정
    • multialignment : 추가적인 정렬
  4. 그 외 추가적인 항목

reference

부스트 캠프 ai tech 3주 1일차 Data 시각화 (4)


Lineplot

  • 연속적으로 변화하는 값을 점으로 나타내고 선으로 연결한 그래프

1. 기본적인 Lineplot

  • .plot()으로 그래프를 그릴 수 있다
  • 5개 이하의 선을 사용하는것이 가독성이 좋다
    • 색상, 마커, 선의 종류 등으로 선을 구분해서 가독성을 더 끌어 올릴 수 있다.
    • color : 색상 지정
    • marker : 점의 모양 지정
    • linestyle : 선의 종류 지정(solid, dashed, dashdot, dotted, None)
  • 흐름의 파악을 원할하게 하기 위해 smoothing을 사용해서 Noise를 줄인다

2. Lineplot의 특징

1. 흐름에 집중하는 그래프

  • 데이터의 흐름을 보기위한 그래프이다
    • 그렇기에 bar와 다르게 축을 0에 맞출 필요는 없다
  • 너무 구체적인 정보는 오히려 흐름을 보는데 방해 될 수 있다
    • Grid, Annotate등을 최소한으로 사용한다
    • 디테일한 정보는 따로 표로 제공하는것도 좋다
  • 생략되지 않는 선에서 범위를 조절해서 표현한다
    • .set_ylim()을 이용하자

2. 간격

  • 축의 간격이 다를경우 기울기 정보에서 오해를 일으킬 수 있다. 또한 점과 점 사이를 선으로 연결한 것이기 때문에 실제로 데이터가 없는부분에서 있다고 오해가 가능하다
    • 수치형 데이터일 경우 matplot에서 알아서 맞추어준다
    • 데이터의 위치에 mark를 해서 오해를 줄일 수 있다

3. 보간

  • 점과 점사이를 실제 데이터가 없지만 이어서 선으로 만드는 방법
  • 데이터의 error나 Noise가 포함되어 있을경우 보간을 사용해서 어느정도 보정해 이해를 도울 수 있다.
    • scipy모듈을 이용하여 사용
  • 데이터를 분석할 경우 미세한 차이를 놓치거나, 없는데이터를 있다고 생각하게 할수 있기때문에 EDA에서는 지양하는것이 좋다.

4. 이중 축 사용

  • 한 plot에 대해서 2개의 축을 사용하는 방법
  • 같은 시간축에서 서로다른 데이터를 표현하기 위해서 쓴다.
    • .twinx()를 사용해서 구현한다
  • 보통 한 데이터에 대한 다른단위 표현을 위해 사용한다
    • .secondary_xaxis(), .secondary_yaxis()를 사용한다
  • 두 데이터에 대해서 이중 축을 사용하는것은 강제로 상관관계를 부여할 수 있으니 지양하고 2개의 plot을 사용하는쪽이 좀 더 가독성 면에서도 좋다

5.그 외 팁

  • 라인 끝에 label을 추가하면 식별에 도움이 된다
  • 주요 포인트에는 annotation을 추가하면 도움이 될 수도 있다
  • 연한색으로 uncerainty 표현이 가능하다

reference

Week3 - Day 1 Review


1. 오늘 하루 한 것

  • 강의
    • 1, 2강 완료
  • 정리
    • 1강 완료, 2강 Barplot

2. 피어세션에서 한 것

  • 피어슨 상관계수

3. 내일 할 것

  • 정리 마무리
  • 3, 4 강의

4. 하루 느낀점

  • 설연휴 좀 쉬었더니 빠르게 정리가 잘 되지 않는다
  • 쉰다고 많이 못했어….

부스트 캠프 ai tech 3주 1일차 Data 시각화 (3)


Barplot

  • 직사각형의 막대를 사용하여 데이터를 표현하는 그래프
  • category에 따른 수치값을 비교하기에 적합하다

1. 기본적인 Barplot

  • barplot은 기본적으로 bar, barh가 존재한다.
  • bar는 수직, barh는 수평으로 막대를 그린다
1
2
3
4
5
6
fig, ax = plt.subplots(1, 2, figsize=(12, 7))
x = list('ABCDE')
y = np.array([1, 2, 3, 4, 5])
ax[0].bar(x, y)
ax[1].barh(x, y)
plt.show()
subplot

2. 다양한 Barplot 기법

  • 다양한 barplot에 대해서 이야기를 할 예정이다
  • 사용하는 데이터는 Boostcamp에서 제공한 데이터를 사용하였다
  • Multiple
    • plot을 여러개 그리는 방법이다.
    • subplots의 sharey를 이용하여 y축의 범위를 공유할 수 있다.
    • 각 group의 분포를 알기 좋지만 group간 비교하기에는 쉽지 않다
1
2
3
4
fig, ax = plt.subplots(1, 2, figsize=(12, 6), sharey=True)
ax[0].bar(group['male'].index, group['male'], color='royalblue')
ax[1].bar(group['female'].index, group['female'], color='tomato')
plt.show()
subplot
  • Stack
    • 2개 이상의 그룹을 쌓아서 표현하는 방식이다
    • 맨 밑 group의 분포는 파악하기 쉽지만 그외는 파악하기 힘들다
    • bottom : bar의 시작 y좌표를 설정 할 수 있다.
1
2
3
4
5
6
7
8
fig, axes = plt.subplots(1, 2, figsize=(15, 7))
group_cnt = student['race/ethnicity'].value_counts().sort_index()
axes[0].bar(group_cnt.index, group_cnt, color='darkgray')
axes[1].bar(group['male'].index, group['male'], color='royalblue')
axes[1].bar(group['female'].index, group['female'], bottom=group['male'], color='tomato') # 각 category의 y축 시작지점을 group['male']의 수치로 지정한다
for ax in axes:
ax.set_ylim(0, 350)
plt.show()
subplot
  • Percentage Stack
    • Stack을 응용하여 만든 BarPlot
    • bal_label을 이용하여 중간에 퍼센트를 찍어주었다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fig, ax = plt.subplots(1, 1, figsize=(12, 7))

group = group.sort_index(ascending=False) # 역순 정렬
total=group['male']+group['female'] # 각 그룹별 합

for name, color in zip(['male', 'female'], ['royalblue', 'tomato']):
rects = ax.barh(group[name].index, group[name]/total,
left=group['male']/total if name == 'female' else 0,
color=color)
ax.bar_label(rects, fmt='%.2g', label_type='center')

ax.set_xlim(0, 1)
for s in ['top', 'bottom', 'left', 'right']:
ax.spines[s].set_visible(False)

plt.show()
subplot
  • Overlap
    • 2개의 그룹만 비교할때 사용하기 좋은 방식
      • 3개 이상은 파악이 어렵다
    • 같은 축을 사용하기 때문에 비교하기 쉽다
    • Bar보다는 Area에서 더 효과적이다
1
2
3
4
5
6
7
8
9
10
11
group = group.sort_index()
fig, axes = plt.subplots(1, 1, figsize=(8, 6))

axes.bar(group['male'].index, group['male'],
color='royalblue',
alpha=0.7)
axes.bar(group['female'].index, group['female'],
color='tomato',
alpha=0.7)
ax.set_ylim(0, 200)
plt.show()
subplot
  • Group
    • 그룹별 범주에 따른 막대를 이웃되게 배치하는 방법
    • Matplotlib로는 구현이 까다롭다
    • 그룹이 5~7개 이하일때 효과적이다
      • 많으면 오히려 역효과가 난다

시각화시 주의해야할점

  1. 실제값과 그래픽으로 표현되는 부분은 비례해야한다
    • 반드시 x축의 시작은 0부터 한다
    • 차이를 나타내고 싶다면 세로의 비율을 늘리자
  2. 정확한 정보를 전달하기 위해서 정렬을 하자
    • 데이터의 종류에따라 여러 기준으로 정렬을 한다.
    • 시계열 : 시간
    • 수치형 : 크기
    • 순서형 : 범주의 순서대로
    • 명목형 : 범주의 값에 따라서
    • interactive로 제공하는 것이 유용하다
  3. 여백을 잘 조절하자
    • 너무 꽉차있거나 비어있으면 가독성이 떨어진다. 적절한 조절로 가독성을 높이자
    • .set_xlim(), .set_ylim()으로 표시할 영역을 지정한다
    • .spines[pos].set_visible()을 이용해서 외곽선을 안보이게 조절한다
    • Gap, Margins을 이용해서 적절히 간격을 띄운다
  4. 복잡함을 줄이자
    • 3D는 왠만해서는 쓰지말자…
    • 축과 디테일을 조절하여 가독성과 깔끔함을 동시에 챙기자
      • text, annotate등을 이용하자

reference

부스트 캠프 ai tech 3주 1일차 Data 시각화 (2)


3. matplot.pyplot 기초

  • 이 글에서는 python 시각화 라이브러리 matplot에 대해서 다루어 본다
  • 기본적으로 가장 많이 사용하는 matplot.pyplot을 이용하여 그래프를 그린다.

들어가기전에

  • 보통 아래와 같이 많이 pyplot을 plt로 선언 한다
1
2
import numpy as np
import matplotlib.pyplot as plt

Figure & Axes

  • plt.figure로 그래프틀을 선언하고, plt.show()를 이용하여 화면에 나타낼 수 있다.
  • num : figure의 id를 지정한다. 이미 지정한 id가 존재하고 그것이 다시 정의될 경우에 원래 존재하던 figure를 반환한다
  • figsize : 그래프틀의 크기를 지정한다
  • dpi : 해상도를 설정한다
  • facecolor : 배경화면의 색을 지정한다
  • edgecolor : 가장자리 라인의 색을 지정한다
1
2
3
4
5
fig = plt.figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None)
plt.show()
==========
output
<Figure size 432x288 with 0 Axes>
  • 위의 코드에 Axes라는 subplot을 추가해야지만 제대로 그래프가 나온다
  • figure의 add_subplot()을 이용하여 Axes를 지정할 수 있다
1
2
3
fig = plt.figure()
ax = fig.add_subplot()
plt.show()
viz2

subplot

  • Axes에 추가적인 Argument 입력을 통해서 위치를 지정해 줄 수 있다.
  • suplots를 이용하여 fig와 Axes들을 동시에 정의 할 수도 있다.
1
2
3
4
fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(1, 2, 2)
plt.show()
subplot

plot

  • plot을 통해서 그래프를 그릴 수 있다.
  • x축과 y축의 수치가 1대1 대응으로 그래프가 그려진다.
  • figure, subplot에 plot을 통해 입력이 가능하다
  • 여러번 plot을 할 경우 여러개의 그래프가 그려진다
  • 직접 색을 입력해서 그래프의 색상을 지정 할 수 있다
  • x : x축이 될 데이터들
  • y : y축이 될 데이터들
1
2
3
4
5
fig = plt.figure()
ax1 = fig.add_subplot(1, 1, 1)
ax1.plot([1, 2], [1, 3], color = 'forestgreen')
ax1.plot([2, 3], [3, 1], color = 'r')
plt.show()
plot

text

  • label : 그래프에 label을 붙일 수 있다.
  • 단 label을 표시하기 위해서는 legend()를 이용해야 한다.
1
2
3
4
5
6
fig = plt.figure()
ax1 = fig.add_subplot(1, 1, 1)
ax1.plot([1, 2], [1, 3], color = 'forestgreen', label = '1')
ax1.plot([2, 3], [3, 1], color = 'r', label = '2')
ax1.legend() # 이게 없으면 label 표시가 나오지 않음
plt.show()
plot
  • 여러 메소드를 이용하여 그래프의 특정부분을 변경 시킬 수 있다.
  • set_title : title을 지정할 수 있다.
  • set_xticks : x축의 범주값을 지정할 수 있다.
  • set_ticklabels : x축을 텍스트 값으로 지정할 수 있다.
  • annotate : 그래프에 여러가지를 추가 할 수 있다.
  • 여러 메소드의 자세한 내용들은 추후에 다룰 예정이다.

reference

부스트 캠프 ai tech 3주 1일차 Data 시각화 (1)


1. Data의 종류

  • Dataset은 아래와 같이 분류가 가능하다.
    1. 정형 데이터
    2. 시계열 데이터
    3. 지리 데이터
    4. 관계형 데이터
    5. 계층적 데이터
  • 데이터는 아래와 같이 분류가 가능하다.
    • 수치형 데이터(numerical) : 수치로 표현된 데이터
      • 연속형(continuous) : 길이, 무게, 온도 등
      • 이산형(discrete) : 사람 수, 주사위 눈금 등
    • 범주형(categorical) : 문자로 표현되는 데이터
      • 명목형(norminal) : 혈액형, 종교, 주소 등
      • 순서형(ordinal) : 학년, 등급, 성적 등

1. 정형 데이터

  • 가장 기본적인 데이터 형태
  • 테이블 형태로 제공되는 데이터이다.

2. 시계열 데이터

  • 시간에 흐름에 따른 데이터
  • 기온 주가 등의 정형 데이터로 표현한 데이터와 음성, 비디오와 같이 비정형인 데이터가 존재한다.

3. 지리/지도 데이터

  • 지형과 지명이 들어가 있는 데이터
  • 위도와 경도를 이용해서 정형데이터로도 표현이 가능하다.
  • 지도 정보와 보고자하는 정보간의 조화를 잘 맞추어 주는것이 중요하다

4. 관계형 데이터

  • 객체와 객체간의 관계를 시각화 할 수 있는 데이터
  • 객체는 Node로, 관계는 Link로 표현이 가능하다
  • 크기와 색, 수 등으로 관계의 가중치를 표현 가능하다
  • 보기쉽게 하기위해 휴리스틱하게 노드의 배치를 구성할 수 있다

5. 계층적 데이터

  • 위의 관예형 데이터중에서 포함관계가 분명한 데이터
  • Tree, Treemap등의 형태의 데이터가 포함된다

2. 시각화

  • 수치와 문제로 이루어진 데이터를 점,선,면을 이용해서 한눈에 보기 쉽게 만들어준다
  • 아래의 속성들을 적절하게 사용해서 시각적으로 분리를 일으켜서 주의 깊게 보지 않아도 한눈에 알아볼수 있도록 하는것이 목표이다
    • 너무 많이 사용하면 오히려 인지하기 힘든 부작용이 나타난다
viz

reference

Garbage collection


서론

이 글에서는 Python의 Garbage Collector에 대해서 다룬다.

Garbage collection

Garbage Collector(이하 GC)는 메모리 관리 기법중 하나로 동적으로 할당했던 메모리 영역 중에 필요없게 된 부분을 해제하는 기능이다. C, C++등의 언어들은 수동메모리 관리를 전재로 설계되어 malloc, free등의 함수로 직접 메모리를 관리 해주어야 하지만, Python, Java, C# 같은 고급 언어들은 GC가 내장되어 있어 자동으로 메모리 관리를 해준다.

Python GC의 작동방식

Python의 GC는 reference count + Generational GC 방식으로 메모리를 관리한다.

reference count

1
2
3
4
5
typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt; /* reference count */
struct _typeobject *ob_type;
} PyObject;

python의 객체들은 모두 reference count를 가지고 있으며 이것을 통해서 GC가 언제 메모리에서 제거할지를 판단한다. 참조가 이루어지면 reference count가 1증가하고, 참조가 끝나면 1감소한다. 최종적으로 0이 되면 GC에서 더이상 필요없는 오브젝트로 판단하고 메모리에서 삭제한다.

이러한 방식은 프로그래머가 어느정도 오브젝트의 메모리 할당 해제 시점을 유추 할 수 있고, 대부분 사용된 직후 해제되기 때문에 캐시에 저장되어 있을 확률이 높아 빠르게 할당 해제가 이루어지는 장점이 존재한다.

하지만 아래와 같은 단점 또한 존재한다. 두개 이상의 객체가 서로 가리키고 있을 경우(순환 참조) reference count가 0까지 내려가지 않는 상황이 발생 할 수 있다. 또한 Multi Thread 환경에서는 공유자원에 대한 참조가 되기 때문에 추가적인 Lock 등이 필요하거나, 지속해서 GC에서 판단하는 프로세스를 거쳐야 하기 때문에 수행 성능의 저하 등의 문제가 발생 할 수 있다.

이러한 단점들을 해결하기 위해 Python에서는 순환 참조를 탐지하는 알고리즘과, 보조적인 Generational GC를 두었고, GIL로 Multi Threading에 제한을 걸어 버렸다.

Generational GC

새롭게 할당된 오브젝트일수록 금방 메모리에서 해제될 확률이 높다는 통계에서 기반한 메모리 관리방법이다. 각각의 오브젝트가 GC가 실행하고나서 메모리에서 해제되지 않으면 다음 세대로 넘어가게 되는 방식인데 더 젊은 세대(금방 생성)일수록 자주 GC의 프로세스에서 할당 해제할 오브젝트인지 판단이 내려지게 된다.

이 과정을 보조적으로 추가하면서 python에서는 조금더 효율적으로 메모리를 관리 하고 있다.

Generational GC

reference