머신러닝

MATPLOTLIB

haniru 2026. 1. 7. 23:22

데이터 시각화

 

matplotlib 설치

 

plt.plot(y)처럼 y 값만 전달했을 때 Matplotlib은 다음과 같이 동작한다.

  • 인덱스 활용: 데이터의 개수(n)를 파악한 뒤, 0부터 n-1까지의 정수를 $x$ 값으로 자동 생성한다.
  • 좌표 대응: 주어진 예시 y = [1, 2, 3, 4]의 경우, 내부적으로 생성된 x = [0, 1, 2, 3]과 결합하여 (0, 1), (1, 2), (2, 3), (3, 4) 지점을 선으로 잇는다.
import matplotlib.pyplot as plt
y = [1,2,3,4] # x값을 안 넣으면 알아서 값을 넣어준다
plt.plot(y)
plt.show()

 

 

 독립변수와 종속변수의 정의

데이터 분석과 머신러닝에서 두 변수는 다음과 같은 역할을 수행한다.

  • 독립변수 (Independent Variable, x): 원인이 되는 변수다. 머신러닝에서는 특성(Feature) 또는 설명 변수라고 부른다. 실험자가 직접 조절하거나 관찰의 기준으로 삼는 값이다.
  • 종속변수 (Dependent Variable, y): 결과가 되는 변수다. 머신러닝에서는 타깃(Target) 또는 **레이블(Label)**이라고 부른다. 독립변수 $x$의 변화에 따라 그 값이 결정된다.
y = [1,2,3,4]
x = [1,2,3,4]
plt.plot(x, y)

plt.ylabel('y label')
plt.xlabel('x label')

plt.show()

 

 

비선형(Non-linear) 관계를 시각화

 

  • np.arange(-10, 11): -10부터 10까지 21개의 점을 생성한다. 이 점들을 연결해 곡선처럼 보이게 만든다.
  • plt.axis([-10, 10, 0, 100]): 그래프의 뷰포트를 설정한다.
    • x축: -10에서 10까지 표시
    • y축: 0에서 100까지 표시
    • 이 설정을 통해 데이터가 그래프 영역에 꽉 차게 보이거나, 특정 부분을 확대해서 볼 수 있다.

 

import numpy as np
x = np.arange(-10, 11)  # 독립변수
y = x ** 2 # 종속변수
print(x)
print(y)

plt.plot(x, y)
plt.show()

plt.plot(x, y)
# -10, 10: x축의 최소값을 -10, 최대값을 10으로 설정
# 0, 100: y축의 최소값을 0, 최대값을 100으로 설정
plt.axis([-10, 10, 0, 100]) # 비율에 맞춰서 그림을 그려준다
plt.show()

 

 

선형과 비선형을 그래프에 시각화

x = np.arange(-20, 21)
y1 = 2*x
y2 = (1/3) * x ** 2 + 5
y3 = -x ** 2 - 5

plt.plot(x, y1, 'g--') # 끊어진선으로 초록
plt.plot(x, y2, 'r^-') # --: 점선, -: 실선, : 점선
plt.plot(x, y3, 'b*:')
plt.axis([-30, 30, -30, 30])
plt.show()

코드 색상 (Color) 마커 (Marker) 선 스타일 (Line Style)
'g--' Green (초록) 없음 Dashed (파선/끊어진 선)
'r^-' Red (빨강) Triangle Up (삼각형) Solid (실선)
'b*:' Blue (파랑) Star (별표) Dotted (점선)

 

무작위 데이터를 시각화(이산적)

N = 50
x = np.arange(N)
y = np.random.random(size=N)

plt.plot(x, y, 'g^:')

 

이산적 데이터, 연속적 데이터

import numpy as np
import matplotlib.pyplot as plt

# 1. arange: 간격 중심 (이산적 느낌)
x_discrete = np.arange(0, 10, 1) # 0, 1, 2, ..., 9
y_discrete = np.sin(x_discrete)

# 2. linspace: 개수 중심 (연속적 느낌)
x_continuous = np.linspace(0, 10, 100) # 0부터 10 사이를 100개로 쪼갬
y_continuous = np.sin(x_continuous)

plt.plot(x_discrete, y_discrete, 'ro', label='arange (Discrete)')
plt.plot(x_continuous, y_continuous, 'b-', label='linspace (Continuous)')
plt.legend()
plt.show()

 

삼각함수의 시각화

np.linspace(0, np.pi * 2, 1000)은 0도부터 360도까지를 1000개로 쪼갠 것이다.

import numpy as np
import matplotlib.pyplot as plt

# 0서부터 360도를 1000개로 나눠줘라?
x = np.linspace(0, np.pi * 2, 1000)
y1 = np.sin(x)
y2 = np.cos(x)

plt.plot(x, y1, 'r-') # 사인함수: 기함수
plt.plot(x, y2, 'b:') # 코사인: 우함수

# 저장
plt.savefig('sin_cosine.jpg')
plt.savefig('sin_cosine.png')
plt.savefig('sin_cosine.svg')
plt.savefig('sin_cosine.pdf')

plt.show() # 이걸 먼저 호출하면 현재 생성된 그래프창을 화면에 띄우고 내부적으로 그래프를 그리는데 사용된 메모리를 비워버림

 

x = np.linspace(0, np.pi * 2, 100)
plt.title('Sin cos curve')
plt.plot(x, np.sin(x), 'r-', label='sin curve')
plt.plot(x, np.cos(x), 'b:', label='cos curve')
plt.xlabel('x value')
plt.ylabel('y value')
# plt.legend() # 범례
plt.legend(loc='upper right') # 위쪽 오른편에 범례를 표시
# matplotlib 에서 사용할 수 있는 범례의 위치를 알려줘
plt.show()

위치 문자열 (String) 정수 코드 (Code) 설명
'best' 0 그래프 데이터와 가장 덜 겹치는 곳을 자동으로 계산
'upper right' 1 오른쪽 위 (기본값)
'upper left' 2 왼쪽 위
'lower left' 3 왼쪽 아래
'lower right' 4 오른쪽 아래
'right' 5 오른쪽 중앙
'center left' 6 왼쪽 중앙
'center right' 7 오른쪽 중앙
'lower center' 8 아래쪽 중앙
'upper center' 9 위쪽 중앙
'center' 10 정중앙

 

# 스타일 시트 - 배경을 예쁘게 하고 싶을 때 (토너 많이 먹음..)
import numpy as np
import matplotlib.pyplot as plt

# 1. 스타일 설정 (그래프를 그리기 전에 설정해야 함)
plt.style.use('seaborn-v0_8-whitegrid')

# 2. 데이터 생성
x = np.linspace(0, np.pi * 2, 100)
y1 = np.sin(x)
y2 = np.cos(x)

# 3. 그래프 그리기
plt.figure(figsize=(8, 5)) # 그래프 크기 설정
plt.plot(x, y1, label='Sin Wave', color='tab:blue', linewidth=2)
plt.plot(x, y2, label='Cos Wave', color='tab:red', linestyle='--')

# 4. 꾸미기
plt.title('Sine & Cosine with Whitegrid Style')
plt.xlabel('X (radians)')
plt.ylabel('Amplitude')
plt.legend() # 범례 표시

# 5. 출력 및 저장
plt.show()

 

 

1. Figure와 Axes의 개념 정립

Matplotlib의 구조는 계층적이다. 이 관계를 이해하는 것이 커스터마이징의 시작이다.

  • Figure (fig): 도화지 전체를 의미함. 여러 개의 서브플롯(Axes)을 담는 가장 큰 바구니이다. 전체 크기(figsize), 배경색 등을 결정한다.
  • Axes (ax): 도화지 안에 그려지는 개별 '그래프'이다. 실제 데이터가 그려지는 공간이며, $x$축, $y$축, 제목, 눈금 등을 개별적으로 가진다.
  • Axis: 그래프의 축($x$축 또는 $y$축) 자체를 의미하며, 눈금(tick)과 라벨을 관리한다.

2. plt.subplots()의 반환값

fig, ax = plt.subplots(2, 2)는 튜플(Tuple) 형태의 데이터를 반환하며, 언패킹(Unpacking)을 통해 각각 변수에 할당된다.

  • fig: Figure 객체 하나.
  • ax: 지정한 행렬 크기에 따른 Axes 객체들의 NumPy 배열.
    • 2x2로 설정했으므로 ax는 shape=(2, 2)인 행렬이 된다.
    • ax[0, 0], ax[0, 1], ax[1, 0], ax[1, 1]처럼 인덱스로 접근하여 각각 다른 그림을 그릴 수 있다.

 

np.random.randn(n): 표준 정규 분포(평균 0, 표준편차 1)를 따르는 난수를 생성함. 중앙에 데이터가 몰려 있는 종 모양의 분포를 가짐.

np.random.uniform(low, high, size): 지정한 범위 내에서 모든 값이 나올 확률이 동일한 균일 분포를 가짐. imshow에서 노이즈 이미지를 만들거나 가중치 초기화 시 자주 사용됨.

fig, ax = plt.subplots(2, 2)

# 랜덤
X = np.random.randn(100) # 정규분포를 가지는 데이터
Y = np.random.randn(100) # 정규분포를 가지는 데이터

# (0,0) :처음에다가 scatter, 상관적인 산점도 그려주세요
ax[0, 0].scatter(X, Y) # 산점도 그림

# (0, 1): 여기에다가 bar 타입으로 그려주세요, 플롯 타입을 그려주세요
X = np.arange(10) # 0에서 9 사이의 연속값
Y = np.random.uniform(1, 10, 10) # 균일분포값

ax[0, 1].bar(X, Y) # 막대차트

# (1, 0): cos 그림을 그려주세요
X = np.linspace(0, 10, 100)
Y = np.cos(X)
ax[1, 0].plot(X, Y) # 실선을 함수로 그림

# (0, 1): 가로 5, 세로 5 픽셀값을 만들어주세요
Z = np.random.uniform(0, 1, (5,5))
ax[1, 1].imshow(Z) # 분포를 2D 이미지로 그림

scatter (산점도)

  • 용도: 두 변수 사이의 상관관계를 파악할 때 사용함.
  • 특징: 점들이 모여 있는 형태를 보고 양의 상관관계, 음의 상관관계, 혹은 무상관인지 판단할 수 있음.

bar (막대 그래프)

  • 용도: 범주형 데이터의 수치 비교에 적합함.
  • 종류: bar(수직), barh(수평)가 있음.

plot (선 그래프)

  • 용도: 시간의 흐름에 따른 변화(시계열)나 연속적인 함수를 표현할 때 사용함.

imshow (이미지 표시)

  • 용도: 2차원 배열 데이터를 이미지 형태로 시각화함.
  • 활용: 딥러닝에서 필터의 가중치 확인, 픽셀 데이터 확인, 혹은 히트맵(Heatmap)을 그릴 때 필수적임.

이중 for문을 활용하여 여러 개의 서브플롯(Axes)을 효율적으로 제어하는 전형적인 패턴

# fig, ax = plt.subplots(2, 3)
_, ax = plt.subplots(2, 3)
# i,j를 문자열로 만들어주고 폰트사이즈로 출력을 해주세요
for i in range(2): # 2행
    for j in range(3): # 3열
        ax[i, j].text(0.3, 0.5, str((i, j)), fontsize=11) # 텍스트만 표시

 

**산점도(Scatter Plot)**의 핵심 기능과 이를 확장한 **버블 차트(Bubble Chart)**의 개념

N = 30
x = np.random.rand(N) # 1미만 1은 안나옴
print(x)
y = np.random.rand(N)
print(y)
colors = np.random.rand(N)
area = (30 * np.random.rand(N)) ** 2

plt.scatter(x, y, s=area, c=colors, alpha=0.5)
plt.show()

 

상관관계

 

  • 상관관계 0 (무상관/독립):
    • 현재 코드의 결과물이다. xy가 완전히 랜덤하게 생성되었으므로 서로 아무런 영향을 주지 않는다.
    • 그래프상에서 점들이 규칙 없이 듬성듬성 퍼져 있다.
    • 해석: "x값만으로는 y값을 전혀 예측할 수 없다."
  • 양의 상관관계 (Positive Correlation):
    • x가 증가할 때 y도 대체로 증가하는 경향이 있다.
    • 그래프는 왼쪽 아래에서 오른쪽 위로 향하는 대각선 형태를 띤다.
    • 예: 키와 몸무게, 공부 시간과 성적.
  • 음의 상관관계 (Negative Correlation):
    • x가 증가할 때 y는 대체로 감소하는 경향이 있다.
    • 그래프는 왼쪽 위에서 오른쪽 아래로 향하는 대각선 형태를 띤다.
    • 예: 자동차의 속도와 연비(속도가 너무 빠르면 연비 감소), 알코올 섭취량과 판단력.

 

중첩 막대 그래프 - 막대그래프 하나가 가려짐

x = np.arange(3)
years = ['2010', '2011', '2012']
domestic = [6801, 7695, 8010]
foreign = [777, 1046, 1681]

# domestic 과 foreign 순서 바꾸면 forieing 이 사라져버림
plt.bar(x, domestic)
plt.bar(x, foreign)
plt.xticks(x, years
개념 설명
Tick (눈금) 그래프의 축에 값을 표시하는 지점. xticks는 x축의 눈금 위치와 이름을 결정한다.
Width (너비) 막대의 두께. 그룹형 그래프에서는 이 너비를 계산하여 x 좌표를 이동시킨다.
Bottom 누적 막대그래프에서 위에 쌓일 막대의 시작 높이를 결정하는 옵션이다.

 

**오프셋(0.3)**을 더하고 **너비(width=0.25)**를 조절해서 막대가 겹치는 문제를 해결

x = np.arange(3)
years = ['2010', '2011', '2012']
domestic = [6801, 7695, 8010]
foreign = [777, 1046, 1681]

plt.bar(x, domestic, width=0.25)
plt.bar(x+0.3, foreign, width=0.25)
plt.xticks(x, years)

plt.show()

 

가로막대그래프

import numpy as np
import matplotlib.pyplot as plt

years = ['2010', '2011', '2012']
domestic = [6801, 7695, 8010]
foreign = [777, 1046, 1681]

y = np.arange(len(years))
height = 0.3  # 막대 두께

fig, ax = plt.subplots(figsize=(8, 5))

# 가로 막대 그리기 (위치 조절 포함)
ax.barh(y, domestic, height=height, label='Domestic', color='tab:blue')
ax.barh(y + 0.35, foreign, height=height, label='Foreign', color='tab:orange')

# 축 설정
ax.set_yticks(y + 0.175) # 두 막대의 중간에 연도가 오도록 조정
ax.set_yticklabels(years)
ax.set_xlabel('Number of Tourists')
ax.set_title('Tourist Statistics (2010-2012)')

# 시간 순서대로 위에서 아래로 배치
ax.invert_yaxis() 

ax.legend()
plt.tight_layout()
plt.show()

 

파이차트

data = [5,4,6,11]
clist = ['cyan', 'gray', 'orange', 'red']
# 폭파할 수 있음
explode = [.06, .07, .08, .09]
plt.pie(data, autopct = '%.2f%%', colors=clist,
        labels=clist, explode=explode
        )
plt.show()

 

히트맵

data = np.random.random((10, 10))
# data = data.astype(np.unit8) # openCV 는 이렇게함
plt.imshow(data, cmap='hot', interpolation='nearest') # gray scale 출력하기 위해 reverse
# plt.imshow(data)
plt.colorbar()
plt.show()

 

히스토그램

  • 빈 (Bins): 메모에서 언급한 '깡통' 또는 '바구니'다. 데이터의 최솟값부터 최댓값까지의 범위를 몇 개의 구간으로 나눌지 결정한다.
    • bins=6이면 전체 범위를 동일한 간격으로 6등분한다.
    • 구간이 너무 적으면 분포가 뭉뚱그려지고, 너무 많으면 노이즈가 심해져 흐름을 보기 어렵다.
  • 도수 (Frequency): 각 바구니에 들어간 데이터의 개수다. $y$축이 바로 이 도수를 나타낸다.
heights = np.array([175, 165, 164, 164, 171, 165, 160, 169, 164, 159, 163, 167,
163, 172, 159, 160, 156, 162, 166, 162, 158, 167, 160, 161, 156, 172, 168, 165, 165,
177])
plt.hist(heights, bins=6) # 히스토그램 bins는 구간의 수
plt.xlabel("height")
plt.ylabel("frequency")
plt.show()

 

히스토그램에서 bins의 개수를 조절하는 것은 데이터의 해상도를 결정하는 것과 같다. bins를 6에서 12로 늘리면 데이터의 분포를 더 세밀하게 관찰할 수 있지만, 동시에 전체적인 흐름을 파악하기 어려워질 수도 있다.

heights = np.array([175, 165, 164, 164, 171, 165, 160, 169, 164, 159, 163, 167,
163, 172, 159, 160, 156, 162, 166, 162, 158, 167, 160, 161, 156, 172, 168, 165, 165,
177])
plt.hist(heights, bins=12) # 히스토그램, bins 의 갯수에 따라 그림이 달라보이는 현상. bins는 구간의 수
plt.xlabel("height")
plt.ylabel("frequency")
plt.show()

 

cumulative=True 옵션을 사용하는 순간 히스토그램은 단순한 빈도 측정을 넘어 **누적 분포 함수(CDF, Cumulative Distribution Function)**의 성질을 갖게 된다. 일반 히스토그램은 bins 설정에 따라 데이터가 왜곡되어 보일 위험이 있지만, 누적 히스토그램은 전체적인 흐름을 안정적으로 보여준다.

 

  • 히스토그램 왜곡: bins의 경계값을 교묘하게 설정하면 특정 데이터가 강조되거나 사라져 보이게 할 수 있다.
  • 누적의 안정성: 누적 히스토그램은 데이터가 쌓여가는 '기울기'를 보여준다. 기울기가 급하다면 해당 구간에 데이터가 밀집되어 있다는 뜻이고, 완만하다면 데이터가 적다는 뜻이다. 이는 구간을 어떻게 나누느냐보다 전체적인 데이터의 흐름을 파악하는 데 더 큰 가치를 둔다.

 

heights = np.array([175, 165, 164, 164, 171, 165, 160, 169, 164, 159, 163, 167,
163, 172, 159, 160, 156, 162, 166, 162, 158, 167, 160, 161, 156, 172, 168, 165, 165,
177])
plt.hist(heights, bins=12, label='cumulative=True', cumulative=True) # 히스토그램, bins 의 갯수에 따라 그림이 달라보이는 현상. bins는 구간의 수

plt.hist(heights, bins=12, label='cumulative=False', cumulative=False)
plt.xlabel("height")
plt.ylabel("frequency")
plt.show()

 

표준정규분포

이 그래프에서 $x$값이 3보다 크거나 -3보다 작은 구간에 위치한 데이터는 전체의 0.3% 미만이다. 데이터 분석 시 이런 값들은 보통 **이상치(Outlier)**로 간주하여 제거하거나 별도로 관리하는 기준이 된다.

import numpy as np
import matplotlib.pyplot as plt

f1 = np.random.randn(100000)
plt.hist(f1, bins=200, color='red', alpha=.7,\
         label='avg 0 std 1')
plt.axis([-8, 8, -2, 2500])
plt.legend()

 

 

표준정규분포2

작성한 코드에서 두 분포는 표준편차가 동일하기 때문에 그래프의 **기형(Shape)**은 완벽히 같다. 단지 중심점만 0에서 3으로 이동했을 뿐이다.

데이터 분류와 중첩의 한계 (Error 영역)

  • 교집합 영역 (Purple): 두 그래프가 겹치는 구간에서 추출된 데이터는 그것이 어디에서 왔는지 확신할 수 없다.
  • 결정 경계 (Decision Boundary): 두 분포가 만나는 중간 지점(약 1.5)을 기준으로 삼아 데이터를 분류하더라도, 겹치는 영역만큼은 반드시 **오분류(Misclassification)**가 발생한다.
  • 학습 데이터로서의 가치: 데이터가 겹치는 구간이 적을수록(두 평균의 차이가 표준편차에 비해 클수록) 모델은 데이터를 더 명확하게 구분할 수 있고 학습 성능도 올라간다.

# 평균 0, 표준편차 1
# 평균 3, 표준편차 1
f1 = np.random.normal(loc=0, scale=1, size=100000)
f2 = np.random.normal(loc=3, scale=1, size=100000)

plt.hist(f1, bins=200, color='red', alpha=.4, label='avg 0 std 1')
plt.hist(f2, bins=200, color='blue', alpha=.4, label='avg 3 std 1')
plt.axis([-8, 8, -2, 2500])
plt.legend()

 

 

표준정규분포3

1. 분산(Scale)이 분류에 미치는 영향

  • 빨간색 (f_1): 표준편차가 1로 작아서 평균 0 근처에 아주 뾰족하게 모여 있다. 데이터의 정체성이 명확하다.
  • 초록색 (f_2): 평균은 3이지만 표준편차가 3으로 크다. 이 때문에 평균에서 멀리 떨어진 값들이 많이 나타나고, 그래프가 낮고 넓게 퍼진다.
  • 문제점: 초록색 데이터의 상당 부분이 빨간색 데이터의 영역($-2 \sim 2$)을 완전히 덮어버린다. 이 구간의 데이터는 모델 입장에서 어느 쪽인지 판단하기 매우 모호해진다.

2. 임계값(Threshold)과 쓰레기 데이터 처리

분류 모델은 보통 특정 임계값(Threshold)을 기준으로 결정을 내린다.

  • 교집합의 딜레마: 메모한 것처럼 교집합 영역에 있는 데이터를 그대로 학습시키면 모델은 혼란에 빠진다. 이를 노이즈 또는 애매한 데이터로 취급할 수 있다.
  • 데이터 정제 전략:
    • Confidence 필터링: 모델이 예측한 확률이 높은(예: 90% 이상) 데이터만 사용하고, 애매한 중간 데이터는 버리는 방식이다.
    • Hard Example Mining: 오히려 겹치는 영역의 '어려운 데이터'를 집중적으로 학습시켜 경계선을 정교하게 긋는 방법도 있다. 하지만 데이터 자체가 레이블링 오류이거나 구분이 불가능한 수준이라면 버리는 것이 성능 향상에 도움이 된다.

3. 통계적 해석

  • 데이터 유효성: 분산이 너무 큰 데이터셋은 특성(Feature)으로서의 가치가 떨어진다. f_2처럼 넓게 퍼진 데이터는 x값이 무엇이냐에 따라 클래스를 예측하기가 매우 힘들기 때문이다.
  • 차원의 저주와 연결: 변수가 많아질 때 이런 식으로 겹치는 구간이 많아지면 분류 정확도는 급격히 떨어진다.
f1 = np.random.normal(loc=0, scale=1, size=100000)
f2 = np.random.normal(loc=3, scale=3, size=100000)

plt.hist(f1, bins=200, color='red', alpha=.4, label='avg 0 std 1')
plt.hist(f2, bins=200, color='green', alpha=.4, label='avg 3 std 3')
plt.axis([-8, 8, -2, 2500])
plt.legend()

 

상자수염

하나의 상자에는 다섯 가지 주요 통계 지표(Five-number summary)가 담겨 있다.

  • 중앙값 (Q2, Median): 상자 내부의 가로선. 데이터를 크기순으로 나열했을 때 정중앙에 위치한 값이다.
  • 제1사분위수 (Q1) / 제3사분위수 (Q3): 상자의 밑면과 윗면. 각각 하위 25%와 75% 지점을 나타낸다.
  • IQR (Interquartile Range): 상자의 높이 (Q3 - Q1). 데이터의 중간 50%가 모여 있는 구간이다.
  • 수염 (Whisker): 상자 위아래로 뻗은 선.
  • 이상치 (Outlier): 수염 범위를 벗어난 점들. 데이터 수집 오류이거나 특별한 케이스다.
plt.style.use('dark_background')

np.random.seed(85)
data1 = np.random.normal(100, 10, 200) # 평균 100, 분산 10
data2 = np.random.normal(100, 40, 200) # 평균 100, 분산 40
data3 = np.random.normal(80, 40, 200) # 평균 80, 분산 40
data4 = np.random.normal(80, 60, 200) # 평균 80, 분산 60
plt.boxplot([data1, data2, data3, data4])

plt.title('Box Plot of Random Data')
plt.xlabel('Group')
plt.ylabel('Value')

plt.show()

데이터 그룹 특성 (μ,σ) 상자 모양 특징
Data 1 (100, 10) 분산이 작아 상자의 높이(IQR)가 매우 낮고 데이터가 조밀함.
Data 2 (100, 40) 평균은 같으나 분산이 4배 커서 상자가 길고 수염도 길게 뻗음.
Data 3 (80, 40) 평균이 80으로 낮아져 상자 자체가 아래쪽($y$축 기준)에 배치됨.
Data 4 (80, 60) 분산이 가장 커서 데이터가 매우 넓게 퍼져 있으며 이상치가 발생할 확률이 가장 높음.

 

그래프와 그리드 그리기 - 그래프에 격자(Grid)를 그리면 데이터의 위치를 눈으로 쫓기 훨씬 수월해진다.

X = np.linspace(0, 2*np.pi, 200)
Y = np.sin(X)
plt.figure(figsize=(4.2, 3.6))
plt.plot(X, Y)
# plt.grid()
plt.grid(color='r', linestyle='dotted', linewidth=2)

'머신러닝' 카테고리의 다른 글

PANDAS  (0) 2026.01.08
SEABORN  (0) 2026.01.07
넘파이(NumPy) 2  (0) 2026.01.07
넘파이(NumPy) 1  (0) 2026.01.06
파이참 설치  (0) 2026.01.05