반응형

1. 인공 신경망

  • 생물학적 뉴런에서 영감을 받아 만든 머신러닝 알고리즘
  • 신경망은 기존의 머신러닝 알고리즘으로 다루기 어려웠던 이미지, 음성, 텍스트 분야에서 뛰어난 성능을 발휘
  • 인공 신경망 알고리즘을 종종 딥러닝이라고도 부름
  • 텐서플로
    • 구글이 만든 딥러닝 라이브러리
    • CPU와 GPU를 사용해 인공 신경망 모델을 효율적으로 훈련하며 모델 구축과 서비스에 필용한 다양한 도구를 제공
    • 텐서플로 2.0부터는 신경망 모델을 빠르게 구성할 수 있는 케라스를 핵심 API로 채택
    • 케라스를 사용하면 간단한 모델에서 아주 복잡한 모델까지 손쉽게 만들 수 있음
  • 밀집층
    • 가장 간단한 인공 신경망의 층
    • 뉴런들이 모두 연결되어 있기 때문에 완전 연결 층이라고도 부름
    • 출력층에 밀집층을 사용할 때는 분류하려는 클래스와 동일한 개수의 뉴런을 사용
  • 원-핫 인코딩
    • 정숫값을 배열에서 해당 정수 위칭의 원소만 1이고 나머지는 모두 0으로 변환
    • 다중 분류에서 출력층에서 만든 확률과 크로스 엔트로피 손실을 계산하기 위해서 변환이 필요
    • 텐서플로에서는 'sparse_categorical_entropy' 손실을 지정하면 이런 변환을 수행할 필요가 없음
  • 확인 문제
    1. 밀집층에 있는 뉴런 개수가 10개일 때 100개의 입력층과 연결된다. 1000개의 가중치가 발생 함. 뉴런마다 1개의 절편이 있으니 1010개의 모델 파라미터가 필요.
    2. sigmoid의 non-linear curver를 적용
    3. compile()
      1. loss 매개변수에 손실 함수를 지정
      2. 이진 부류일 경우 'binary_crossentropy', 다중 분류일 경우 'categorical_crossentropy'를 지정
      3. 정수일 경우 'sparse_categorical_crossentropy'로 지정
      4. 회귀 모델일 경우 'mean_square_error' 등으로 지정
      5. metrics 매개변수에 훈련 과정에서 측정하고 싶은 지표를 지정할 수 있음
      6. 측정 지표가 1개 이상일 경우 리스트로 전달
    4. 정수 레이블을 타겟으로 가지는 다중 분류 모델일 경우 compile() 메서드의 categorical_crossentropy를 지정

2. 심층 신경망

  • 2개 이상의 층을 포함한 신경망
  • 다층 인공 신경망, 심층 신경망, 딥러닝을 같은 의미로 사용
  • 렐루 함수
    • 이미지 분류 모델의 은닉층에 많이 사용하는 활성화 함수
    • 시그모이드 함수는 층이 많을수록 활성화 함수의 양쪽 끝에서 변화가 작기 때문에 학습이 어려워짐
    • 렐루 함수는 이런 문제가 없으며 계산도 간단함
  • 옵티마이저
    • 신경망의 가중치와 절편을 학습하기 위한 알고리즘 또는 방법
    • 케라스에는 다양한 경사 하강법 알고리즘이 구현되어 있음
    • 대표적으로 SGD, 네스테로프 모멘텀, RMSprop, Adam 등이 있음.
  • 확인 문제
    1. add()
      1. 케라스 모델에 층을 추가하는 메서드
      2. keras.layers 패키지 아래에 있는 층의 객체를 입력받아 신경망 모델에 추가
      3. add() 메서드를 호출하여 전달한 순서대로 층이 차례대로 늘어남
    2. Flatten - 
    3. relu 함수는 이미지 분류 모델의 은닉층에 많이 사용하는 활성화 함수
    4. SDG - 모멘텀, 네스테로프 모멘텀 알고리즘을 구현하는 클래스, 일정한 학습률을 사용함.

3. 신경망 모델 훈련

  • 드롭아웃
    • 은닉층에 있는 뉴런의 출력을 랜덤하게 꺼서 과대적합을 막는 기법
    • 훈련 중에 적용되며 평가나 예측에서는 적용하지 않음
    • 텐서플로는 이를 자동으로 처리
  • 콜백
    • 케라스 모델을 훈련하는 도중에 어떤 작업을 수행할 수 있도록 도와주는 도구
    • 대표적으로 최상의 모델을 자동으로 저장해 주거나 검증 점수가 더 이상 향상되지 않으면 일
      찍 종료할 수 있음
    • 조기종료
      • 검증 점수가 더 이상 감소하지 않고 상승하여 과대적합이 일어나면 훈련을 계속 진행하지 않고 멈추는 기법
      • 계산 비용과 시간을 절약할 수 있음
반응형
반응형

비지도 학습

머신러닝의 한 종류로 훈련 데이터에 타깃이 없음.

타깃이 없기 때문에 외부의 도움 없이 스스로 유용한 무언가를 학습해야 함.

대표적인 비지도 학습 작업은 군집, 차원 축소등이 있음

 

군집 알고리즘

히스토그램 : 값이 발생한 빈도를 그래프로 표시한 것. 보통 x축이 값의 구간(계급), y축은 발생 빈도(도수).

군집 : 비슷한 샘플끼리 그룹으로 모으는 작업

클러스터 : 군집 알고리즘에서 만든 그룹

실제 비지도 학습에서는 타깃값을 모르기 때문에 이처럼 샘플의 평균값을 미리 구할 수 없음

타깃값을 모르면서 어떻게 평균값을 찾을 수 있을까?

K-평균 알고리즘

k-평균 군집 알고리즘이 평균값을 자동으로 찾아 줌.

이 평균값이 클러스터의 중심에 위치하기 때문에 클러스터 중심 또는 센트로이드라고 부름.

k-평균 알고리즘 동작방식

1. 무작위로 k개의 클러스터 중심으로 정합니다.

2. 각 샘플에서 가장 가까운 클러스터 중심을 찾아 해당 클러스터의 샘플로 지정합니다.

3. 클러스터에 속한 샘플의 평균값으로 클러스터 중심을 변경합니다.

4. 클러스터 중심에 변화가 없을 때까지 2번으로 돌아가 반복합니다.

 

k-평균 알고리즘은 처음에는 랜덤하게 클러스터 중심을 선택하고 점차 가장 가까운 샘플의 중심으로 이동하는 비교적 간단한 알고리즘

 

k-평균 알고리즘의 단점 중 하나는 클러스터 개수를 사전에 지정해야 한다는 것. 실전에서는 몇개의 클러스터가 있는지 알 수 없습니다. 어떻게 하면 적절한 k 값을 찾을 수 있을까?

 

군집 알고리즘에서 적절한 k 값을 찾기 위한 완벽한 방법은 없다. 적절한 클러스터 개수를 찾기 위한 대표적인 방법인 엘보우 방법

주성분 분석

 

반응형

'IT > 머신러닝&딥러닝' 카테고리의 다른 글

06. 딥러닝  (0) 2023.02.19
04. 교차 검증 및 앙상블 학습  (0) 2023.02.05
03. 로지스틱 회귀  (0) 2023.01.24
02. 회귀 알고리즘과 모델 규제  (0) 2023.01.15
01. 머신러닝, 딥러닝 정리 및 개발 환경  (0) 2023.01.08
반응형

교차 검증

지금까지는 훈련 세트에서 모델을 훈련하고 테스트 세트에서 모델을 평가

테스트 세트에서 얻은 점수를 보고 일반화 성능을 가능

그런데 테스트 세트를 사용해 자꾸 성능을 확인하다 보면 점점 테스트 세트에 맞추게 되는 셈

 

테스트 세트로 일반화 성능을 올바르게 예측하려면 가능한 한 테스트 세트를 사용하지 말아야 함.

모델을 만들고 나서 마지막에 딱 한번만 사용하는 것이 좋음

 

테스트 세트를 사용하지 않으면 모델이 과대적합인지 과소적합인지 판단하기 어렵다.

테스트 세트를 사용하지 않고 이를 측정하는 간단한 방법은 훈련 세트를 또 나누는 것.

해당 데이터를 검증 세트라고 부른다.

 

전체 데이터 중 20%를 테스트 세트로 만들고 나머지 80%를 훈련 세트로 만들고, 이 훈련 세트 중에서 다시 20%를 떼어 검증 세트로 만듬.훈련세트에서 모델을 훈련하고 검증 세트로 모델을 평가. 이런식으로 테스트하고 싶은 매개변수를 바꿔가며 가장 좋은 모델을 고름.

 

k-fold 교차 검증

 

교차 검증 장,단점

장점 

  • 모든 데이터셋을 훈련에 활용할 수 있음
    • 정확도 향상
    • 데이터 부족으로 인한 underfitting을 방지
  • 모든 데이터셋을 평가에 활용할 수 있음
    • 평가에 사용되는 데이터 편중을 막을 수 있음
    • 평가 결과에 따라 좀 더 일반화된 모델을 만들 수 있음

단점

  • 반복 횟수가 많아서 훈련 평가 시간이 오래 걸림

 

앙상블 학습

정형 데이터를 다루는 데 가장 뛰어난 성과를 내는 알고리즘.

하나의 데이터를 여러개의 분류기를 통해 다수의 학습 모델을 만들어 학습시키고 학습 결과를 결합함으로써 과적합을 방지하고 정확도를 높이는 학습 기법.

 

종류

  • 보팅 : 앙상블 학습의 기본, 하위 모든 기법들이 보팅 사용
  • 배깅 : 하나의 데이터를 여러개로 나누어 학습하는 앙상블 학습법
    • 일반적으로 보팅은 하나의 데이터에 여러 알고리즘 적용
    • 배깅은 여러개로 나우어진 데이터에 하나의 알고리즘을 적용하는 것으로 구분
    • 여러개로 나누어진 데이터를 이용하는 배깅에서도 최종 예측값을 선택하는 행위 '보팅'이라고 함
  • 부스팅 : 병렬로 수행되는 배깅과 달리 각 결과값을 이용하여 순차적으로 결합
  • 랜덤 포레스트 : 배깅 + 결정 트리

랜덤 포레스트

앙상블 학습의 대표 주자 중 하나로 안정적인 성능 덕분에 널리 사용

결정 트리를 랜덤하게 만들어 결정트리의 숲을 만듬. 

각 결정 트리의 예측을 사용해 최종 예측을 만듬.

 

 

각 노드를 분할할 때 전체 특성 중에서 일부 특성을 무작위로 고른 다음 이 중에서 최선의 분할을 찾는다.

분류 모델인 RandomForestClassifier는 기본적으로 전체 특성 개수의 제곱근만큼의 특성을 선택하여 사용. 다만 회귀 모델인 RandomForestRegressor는 전체 특성을 사용.

 

RandomForest 학습 코드

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split

wine = pd.read_csv('https://bit.ly/wine_csv_data')

data = wine[['alcohol', 'sugar', 'pH']].to_numpy()
target = wine['class'].to_numpy()

train_input, test_input, train_target, test_target = train_test_split(data, target, test_size=0.2, random_state=42)

from sklearn.model_selection import cross_validate
from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(n_jobs=-1, random_state=42)
scores = cross_validate(rf, train_input, train_target, return_train_score=True, n_jobs=-1)

print(np.mean(scores['train_score']), np.mean(scores['test_score']))

rf.fit(train_input, train_target)
print(rf.feature_importances_)

rf = RandomForestClassifier(oob_score=True, n_jobs=-1, random_state=42)

rf.fit(train_input, train_target)
print(rf.oob_score_)


result :
0.9973541965122431 0.8905151032797809
[0.23167441 0.50039841 0.26792718]
0.8934000384837406

 

엑스트라 트리 ( Extra Trees)

랜덤 포레스트와 매우 비슷하게 동작. 기본적으로 100개의 결정 트리를 훈련.

전체 특성 중 일부 특성을 랜덤하게 선택하여 노드를 분할하는 데 사용.

 

랜덤 포레스트와 엑스트라 트리의 차이점은 부트스트랩 샘플을 사용하지 않는다는 점.

각 결정 트리를 만들 때 전체 훈련 세트를 사용. 대신 노드를 분할할 때 가장 좋은 분할을 찾는 것이 아니라 무작위로 분할.

하나의 결정 트리에서 특성을 무작위로 분할한다면 성능이 낮아지겠지만 많은 트리를 앙상블 하기 때문에 과대적합을 막고 검증 세트의 점수를 높이는 효과가 있다.

 

엑스트라 트리 ( Extra Trees ) 학습 코드

from sklearn.ensemble import ExtraTreesClassifier

et = ExtraTreesClassifier(n_jobs=-1, random_state=42)
scores = cross_validate(et, train_input, train_target, return_train_score=True, n_jobs=-1)

print(np.mean(scores['train_score']), np.mean(scores['test_score']))

et.fit(train_input, train_target)
print(et.feature_importances_)


result:
0.9974503966084433 0.8887848893166506
[0.20183568 0.52242907 0.27573525]

 

그레이디언트 부스팅 ( Gradient boosting )

깊이가 얕은 결정 트리를 사용하여 이전 트리의 오차를 보완하는 방식으로 앙상블 하는 방법

사이킷런의 GradientBoostingClassifier는 기본적으로 깊이가 3인 결정 트리를 100개 사용. 깊이가 얕은 결정 트리를 사용하기 때문에 과대적합에 강하고 일반적으로 높은 일반화 성능을 기대할 수 있다.

 

경사 하강법을 사용하여 트리를 앙상블에 추가한다. 분류에서는 로지스틱 손실 함수를 사용하고 회귀에서는 평균 제곱 오차 함수를 사용한다. 

 

그레이디언트 부스팅은 결정 트리는 결정 트리를 계속 추가하면서 가장 낮은 곳을 찾아 이동한다. 

 

그레이디언트 부스팅 ( Gradient boosting ) 학습 코드

from sklearn.ensemble import GradientBoostingClassifier

gb = GradientBoostingClassifier(random_state=42)
scores = cross_validate(gb, train_input, train_target, return_train_score=True, n_jobs=-1)

print(np.mean(scores['train_score']), np.mean(scores['test_score']))

gb = GradientBoostingClassifier(n_estimators=500, learning_rate=0.2, random_state=42)
scores = cross_validate(gb, train_input, train_target, return_train_score=True, n_jobs=-1)

print(np.mean(scores['train_score']), np.mean(scores['test_score']))

gb.fit(train_input, train_target)
print(gb.feature_importances_)


result : 
0.8881086892152563 0.8720430147331015
0.9464595437171814 0.8780082549788999
[0.15872278 0.68010884 0.16116839]

 

 

히스토그램 기반 그레이디언트 부스팅 ( Histogram-based gradient boosting )

정형 데이터를 다루는 머신러닝 알고리즘 중에 가장 인기가 높은 알고리즘

입력 특성을 256개의 구간으로 나눕니다. 따라서 노드를 분할할 때 최적의 분할을 매우 빠르게 찾을 수 있다.

256개의 구간 중에서 하나를 떼어 놓고 누락된 값을 위해서 사용한다. 따라서 입력에 누락된 특성이 있더라도 이를 따로 전처리할 필요가 없다. 

과대적합을 잘 억제하면서 그레이디언트 부스팅보다 조금 더 높은 성능을 제공한다. 

 

히스토그램 기반 그레이디언트 부스팅 ( Histogram-based gradient boosting) 학습 코드

from sklearn.ensemble import HistGradientBoostingClassifier

hgb = HistGradientBoostingClassifier(random_state=42)
scores = cross_validate(hgb, train_input, train_target, return_train_score=True, n_jobs=-1)

print(np.mean(scores['train_score']), np.mean(scores['test_score']))

from sklearn.inspection import permutation_importance

hgb.fit(train_input, train_target)
result = permutation_importance(hgb, train_input, train_target, n_repeats=10,
                                random_state=42, n_jobs=-1)
print(result.importances_mean)

result = permutation_importance(hgb, test_input, test_target, n_repeats=10,
                                random_state=42, n_jobs=-1)
print(result.importances_mean)

hgb.score(test_input, test_target)

from xgboost import XGBClassifier

xgb = XGBClassifier(tree_method='hist', random_state=42)
scores = cross_validate(xgb, train_input, train_target, return_train_score=True, n_jobs=-1)

print(np.mean(scores['train_score']), np.mean(scores['test_score']))

from lightgbm import LGBMClassifier

lgb = LGBMClassifier(random_state=42)
scores = cross_validate(lgb, train_input, train_target, return_train_score=True, n_jobs=-1)

print(np.mean(scores['train_score']), np.mean(scores['test_score']))


result : 
0.9321723946453317 0.8801241948619236
[0.08876275 0.23438522 0.08027708]
[0.05969231 0.20238462 0.049     ]
0.8824322471423747 0.8726214185237284
0.9338079582727165 0.8789710890649293

 

 

Colab 실행 화면

반응형

'IT > 머신러닝&딥러닝' 카테고리의 다른 글

06. 딥러닝  (0) 2023.02.19
05. 비지도 학습  (0) 2023.02.12
03. 로지스틱 회귀  (0) 2023.01.24
02. 회귀 알고리즘과 모델 규제  (0) 2023.01.15
01. 머신러닝, 딥러닝 정리 및 개발 환경  (0) 2023.01.08
반응형

로지스틱 회귀 ( Logistic Regression)

* 선형 방적식을 사용한 분류 알고리즘

* 선형 회귀와 달리 시그모이드 함수나 소프트 맥스 함수를 사용하여 클래스 확률을 출력

* 로지스틱 회귀는 다중 분류를 위해 소프트맥스 함수를 사용하여 클래스를 예측

 

로지스틱 회귀에서 이진 분류 확률을 출력하기

로지스틱 회귀에서 이진 분류 확률을 출력하기 위해서는 시그모이드 함수(Sigmoid function)을 사용해야한다.

 

샘플 데이터를 사용하여 로지스틱 회귀를 위한 시그모이드 함수를 사용해보겠습니다.

 

 

"""# 데이터 준비 """

import pandas as pd

fish = pd.read_csv('https://bit.ly/fish_csv_data')
fish.head()

 

샘플 csv 파일을 불러와서 데이터 프레임으로 변환 후 처음 5개 행을 출력

 

시그 모이드 함수 식

시그모이드 함수 그래프

 

시그모이드 선형 방정식의 출력 z의 음수를 사용해 자연상수  e를 거듭제곱하고 1을 더한 값의 역수를 취함

시그모이드 함수가 이렇게 복잡하게 계산한 이유는 아래 시그 모이드 함수 그래프를 만들 수 있기 때문이다.

 

z가 무한하게 큰 음수일 경우 이 함수는 0에 가까워지고, z가 무한하게 큰 양수가 될 때는 1에 가까워진다. z가 0일 경우 0.5이다. z가 어떤 값이 되더라도 결과는 전대로 0~1 사이의 범위를 벗어날수 없다. 그렇다면 0~100%까지 확률로 해석할 수 있다. 

import numpy as np
import matplotlib.pyplot as plt

z = np.arange(-5, 5, 0.1)
phi = 1 / (1 + np.exp(-z))

plt.plot(z, phi)
plt.xlabel('z')
plt.ylabel('phi')
plt.show()

 

준비한 샘플 데이터를 가지고 로지스틱 회귀로 이진 분류를 수행

 

불리언 인덱싱을 적용해서 훈련 세트에서 도미와 빙어의 행만 골라내기

bream_smelt_indexes = (train_target == 'Bream') | (train_target == 'Smelt')
train_bream_smelt = train_scaled[bream_smelt_indexes]
target_bream_smelt = train_target[bream_smelt_indexes]

 

분리한 도미와 빙어 데이터로 로지스틱 회귀 모델을 훈련

from sklearn.linear_model import LogisticRegression

lr = LogisticRegression()
lr.fit(train_bream_smelt, target_bream_smelt)

 

훈련한 모델을 사용해서 train_bream_smelt에 있는 처음 5개의 샘플을 예측

print(lr.predict(train_bream_smelt[:5]))
==> result : ['Bream' 'Smelt' 'Bream' 'Bream' 'Bream']

predict_proba() 메서드를 사용하여 처음 5개 샘플의 예측 확률을 출력

print(lr.predict_proba(train_bream_smelt[:5]))
==> result : 
[[0.99759855 0.00240145]
 [0.02735183 0.97264817]
 [0.99486072 0.00513928]
 [0.98584202 0.01415798]
 [0.99767269 0.00232731]]

첫번째 열이 음성 클래스에 대한 확률이고, 두번째 열이 양성 클래스에 대한 확률

 

어떤것이 음성 클래스이고 어떤것이 양성 클래스인지 확인

print(lr.classes_)
==> result : 
['Bream' 'Smelt']

도미가 음성, 빙어가 양성 클래스

 

 

에포크와 과대/과소적합

확률적 경사 하강법을 사용한 모델은 에포크 횟수에 따라 과소적합이나 과대적합이 될 수 있다.

 

* 이런 현상이 발생하는 이유

** 적은 에포크 횟수 동안에 훈련한 모델은 훈련 세트와 테스트 세트에 잘 맞지 않는 과소적합된 모델일 가능성이 높음

** 많은 에포크 횟수 동안에 훈련한 모델은 훈련 세트에 너무 잘 맞아 테스트 세트에는 오히려 점수가 나쁜 과대적합된 모델일 가능성이 높음

 

과대 / 과소 적합을 위한 데이터 준비

import pandas as pd

fish = pd.read_csv('https://bit.ly/fish_csv_data')

fish_input = fish[['Weight','Length','Diagonal','Height','Width']].to_numpy()
fish_target = fish['Species'].to_numpy()

from sklearn.model_selection import train_test_split

train_input, test_input, train_target, test_target = train_test_split(
    fish_input, fish_target, random_state=42)

from sklearn.preprocessing import StandardScaler

ss = StandardScaler()
ss.fit(train_input)
train_scaled = ss.transform(train_input)
test_scaled = ss.transform(test_input)

 

 

* 훈련이 진행되는 동안 fit() 메서드가 아닌 partial_fit() 메서드만 사용

* np.unique() 함수로 train_target에 있는 7개의 생선의 목록을 생성

* 에포크마다 훈련 세트와 테스트 세트에 대한 점수를 기록하기 위해 2개의 리스트를 준비

from sklearn.linear_model import SGDClassifier
import numpy as np

sc = SGDClassifier(loss='log', random_state=42)

train_score = []
test_score = []

classes = np.unique(train_target)

 

 

* 300번의 에포크 동안 훈련을 반복 진행

* 매 반복마다 훈련 세트와 테스트 세트의 점수를 계산하여 train_score, test_score에 추가

* 300번의 에포크 동안 기록한 훈련 세트와 테스트 세트의 점수를 그래프로 표시

for _ in range(0, 300):
    sc.partial_fit(train_scaled, train_target, classes=classes)
    train_score.append(sc.score(train_scaled, train_target))
    test_score.append(sc.score(test_scaled, test_target))

import matplotlib.pyplot as plt

plt.plot(train_score)
plt.plot(test_score)
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.show()

 

백번째 에포크 이후에 훈련 세트와 테스트 세트의 점수가 조금씩 벌어짐

에포크 초기에는 과소적합되어 훈련세트와 테스트 세트의 점수가 낮음

해당 모델의 경우 백번째 에포크가 적절한 반복횟수로 보임

 

* SGDClassifier의 반복 횟수를 100에 맞추고 모델을 다시 훈련

* 최종적으로 테스트 세트와 훈련세트에서 점수를 출력

sc = SGDClassifier(loss='log', max_iter=100, tol=None, random_state=42)
sc.fit(train_scaled, train_target)

print(sc.score(train_scaled, train_target))
print(sc.score(test_scaled, test_target))

==> result : 
0.957983193277311
0.925

SGDClassifier는 일정 에포크 동안 성능이 향상되지 않으면 더 훈련하지 않고 자동으로 멈춤

 

tol 매개변수에서 향상될 최소값을 지정. None으로 지정하여 자동으로 멈추지 않고 max_iter=100 만큼 무조건 반복

 

 

** 추가 **

SGDClassifier의 loss 매개변수의 기본값은 hinge이다.

힌지 손실은 서포트 벡터 머신이라 불리는 또 다른 머신러닝 알고리즘을 위한 손실 함수

 

반응형
반응형

지도 학습 알고리즘

지도 학습 알고리즘은 크게 분류와 회귀로 나뉨

분류 : 샘플을 몇 개의 클래스 중 하나로 분류하는 문제

회귀 : 클래스 중 하나로 분류하는 것이 아니라 임의의 어떤 숫자를 예측하는 문제

 

예) 내년도 경제 성장률을 예측하거나 배달이 도착하는 시간을 예측하는 것이 회귀 문제

 

# K-최근접 이웃 회귀

K-최근접 이웃 알고리즘이 회귀에도 작동한다.

K-최근접 이웃 알고리즘은 어떻게 숫자를 예측할 수 있는가?

- K-최근접 이웃 분류 알고리즘 : 

--> 예측하려는 샘플에 가장 가까운 샘플 k개를 선택 -> 샘플들의 클래스를 확인하여 다수 클래스를 새로운 샘플의 클래스로 예측

 

- K-최근접 이웃 회귀 알고리즘 : 

--> 예측하려는 샘플에 가장 가까운 샘플 k개를 선택 -> 이웃한 샘플의 타깃이 어떤 클래스가 아닌 임의의 수치 -> 이웃 샘플의 수치를 사용해 새로운 샘플 x의 타깃을 예측 ( 이웃 수치들의 평균을 구함)

 

실습

데이터 준비

넘파이 배열을 사용한 농어의 길이와 무게 데이터 준비

perch_length = np.array([8.4, 13.7, 15.0, 16.2, 17.4, 18.0, 18.7, 19.0, 19.6, 20.0, 21.0,
       21.0, 21.0, 21.3, 22.0, 22.0, 22.0, 22.0, 22.0, 22.5, 22.5, 22.7,
       23.0, 23.5, 24.0, 24.0, 24.6, 25.0, 25.6, 26.5, 27.3, 27.5, 27.5,
       27.5, 28.0, 28.7, 30.0, 32.8, 34.5, 35.0, 36.5, 36.0, 37.0, 37.0,
       39.0, 39.0, 39.0, 40.0, 40.0, 40.0, 40.0, 42.0, 43.0, 43.0, 43.5,
       44.0])
perch_weight = np.array([5.9, 32.0, 40.0, 51.5, 70.0, 100.0, 78.0, 80.0, 85.0, 85.0, 110.0,
       115.0, 125.0, 130.0, 120.0, 120.0, 130.0, 135.0, 110.0, 130.0,
       150.0, 145.0, 150.0, 170.0, 225.0, 145.0, 188.0, 180.0, 197.0,
       218.0, 300.0, 260.0, 265.0, 250.0, 250.0, 300.0, 320.0, 514.0,
       556.0, 840.0, 685.0, 700.0, 700.0, 690.0, 900.0, 650.0, 820.0,
       850.0, 900.0, 1015.0, 820.0, 1100.0, 1000.0, 1100.0, 1000.0,
       1000.0])

 

특성 데이터를 x축에 놓고 타깃 데이터를 y축에 놓아 데이터가 어떤 형태를 띠고 있는지 산점도로 표시

 

 

데이터를 머신러닝 모델에 사용하기 전에 훈련 세트와 테스트 세트로 나누기

사이킷런의 train_test_split() 함수를 사용해 훈련 세트와 테스트 세트로 나누기

from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = train_test_split(perch_length, perch_weight, random_state=42)

 

 

reshape() 메서드를 사용해 train_input과  test_input을 2차원 배열로 변경

train_input = train_input.reshape(-1,1)
test_input = test_input.reshape(-1,1)
print(train_input.shape, test_input.shape)

 

사이킷런에서 k-최근접 이웃 회귀 알고리즘을 구현한 KNeighborsRegressor 클래스를 사용

해당 클래스의 객체를 생성하고 fit() 메서드로 회귀 모델을 훈련

from sklearn.neighbors import KNeighborsRegressor
knr = KNeighborsRegressor();
knr.fit(train_input, train_target)
print(knr.score(test_input, test_target))

 

프린트 된 값은 결정계수 또는 R^2이라고 한다. 

이 값은 다음의 식으로 계산 된다.

R^2 = 1- ((타깃 - 예측)^2의 합 / (타킷 - 평균)^2 의 합)

타깃의 평균 정도를 예측하는 수준이라면 0에 가까워지고, 예측이 타깃에 가까워지면 1에 가까운 값이 된다.

 

타깃과 예측한 값 사이의 차이를 구햅면 어느 정도 예측이 벗어났는지 가늠하기 좋다.

사이킷런의 sklearn.metrics 패키지 아래 여러가지 측정 도구를 제공한다.

mean_absolute_error을 사용하면 타깃과 예측의 절대값 오차를 평균하여 반환

from sklearn.metrics import mean_absolute_error
test_prediction = knr.predict(test_input)
mae = mean_absolute_error(test_target, test_prediction)
print(mae)

 

훈련 세트에서 점수가 좋았는데 테스트 세트에서는 점수가 굉장히 나쁘다면 모델이 훈련세트에 과대적합 되었다고 한다. 훈련세트에만 잘 맞는 모델이라 테스트 세트와 나중에 실전에 투입하여 새로운 샘플에 대한 예측을 만들 때 잘 동작하지 않을 것이다. 

반대로 훈련 세트보다 테스트 세트의 점수가 높거나 두점수가 모두 낮은 경우는 과소적합이라고 한다. 모델이 너무 단하여 훈련 세트에 적절히 훈련되지 않은 경우이다. 훈련 세트가 전체 데이터를 대표한다고 가정하기 때문에 훈련 세트를 잘 학습하는 것이 중요하다.

 

 

위 샘플 데이터의 훈련 세트와 테스트 세트의 점수를 비교해보면 과소적합이라고 할 수 있다. 이것을 해결하기 위해 모델을 조금 더 복잡하게 만들어서 해결하면 된다. 훈련 세트에 더 잘 맞게 만들면 테스트 세트의 점수는 조금 나아질것이다. 

k-최근접 이웃 알고리즘으로 모델을 더 복잡하게 만드는 방법은 이웃의 개수를 줄이는 것이다. 이웃의 개수를 줄이면 훈련 세트에 있는 국지적인 패턴에 민감해지고, 이웃의 개수를 늘리면 데이터 전반에 있는 일반적인 패턴을 따를 것이다. 

 

 

[미션]  과대적합 과소적합 예측 그래프

knr = KNeighborsRegressor()
x = np.arange(5,45).reshape(-1, 1)
for n in [1,5,10]:
  knr.n_neighbors = n
  knr.fit(train_input, train_target)
  prediction = knr.predict(x)

  plt.scatter(train_input, train_target)
  plt.plot(x, prediction)
  plt.title('n_neibors = {}'.format(n))
  plt.xlabel('length')
  plt.ylabel('weight')
  plt.show()

결과

[선택 미션] 모델 파라미터

선형 회귀가 찾은 가중치처럼 머신러닝 모델이 특성에서 학습한 파라미터를 말한다.

모델에 적용할 하나 이상의 파라미터를 사용하여 새로운 샘플에 대한 예측을 하기 위해 사용

머신러닝 훈련 모델에 의해 요구되는 변수.

 

특징 

- 머신 러닝 훈련 모델의 성능은 파라미터에 의해 결정된다.

- 파라미터는 데이터로부터 추정 또는 학습 된다.

- 파라미터는 개발자에 의해 수동으로 설정하지 않는다. (임의 조정 불가)

- 학습된 모델의 일부로 저장

 

모델 파라미터의 예

- 인공신경망의 가중치

- 서포트 벡터 머신의 서포트 벡터

- 선형 회귀 또는 로지스틱 회귀에서의 결정계수

반응형
반응형
 
혼자 공부하는 머신러닝+딥러닝
이 책은 수식과 이론으로 중무장한 머신러닝, 딥러닝 책에 지친 ‘독학하는 입문자’가 ‘꼭 필요한 내용을 제대로’ 학습할 수 있도록 구성했다. 구글 머신러닝 전문가(Google ML expert)로 활동하고 있는 저자는 여러 차례의 입문자들과 함께한 머신러닝&딥러닝 스터디와 번역ㆍ집필 경험을 통해 ‘무엇을’ ‘어떻게’ 학습해야 할지 모르는 입문자의 막연함을 이해하고, 과외 선생님이 알려주듯 친절하게 핵심적인 내용을 콕콕 집어준다. 컴퓨터 앞에서 〈손코딩〉을 따라하고, 확인 문제를 풀다 보면 그간 어렵기만 했던 머신러닝과 딥러닝을 개념을 스스로 익힐 수 있을 것이다! - 베타리더가 함께 만든 입문서 베타리딩 과정을 통해 입문자에게 적절한 난이도, 분량, 학습 요소 등을 고민하고 반영했다. 어려운 용어와 개념은 한 번 더 풀어 쓰고, 복잡한 설명은 눈에 잘 들어오는 그림으로 풀어 냈다. ‘혼자 공부해본’ 여러 입문자의 마음과 눈높이가 책 곳곳에 반영된 것이 이 책의 가장 큰 장점이다.
저자
박해선
출판
한빛미디어
출판일
2020.12.21

[기본]

인공지능, 머신러닝, 딥러닝 간단 정리

인공지능 : 사람처럼 학습하고 추론할 수 있는 지능을 가진 시스템을 만드는 기술. 강인공지능과 약인공지능으로 나뉜다.

머신러닝 : 규칙을 프로그래밍하지 않아도 자동으로 데이터에서 규칙을 학습하는 알고리즘 연구분야. 사이킷런이 대표적인 라이브러리

딥러닝 : 인공 신경망. 텐서플로와 파이토치가 대표적인 라이브러리

 

 


구글 코랩

로컬 환경에 별도의 개발 환경을 구축하지 않아도 구글에서 지원해주는 웹브라우저 기반 파이선 프로그램의 테스트 및 저장할 수 있는 서비스.

 

요약 : 클라우드 기반의 주피터 노트북 개발 환경

 

구글 계정만 있다면 누구나 무료로 사용할 수 있다. 

 

로그인 및 코랩 접속은 (https://colab.research.google.com) 에서 할 수 있다.

구글 계정으로 로그인 하지 않아도 코랩에 접속할 순 있지만 코드 실행 및 저장을 위해서는 로그인하는 것을 권장.

 


1차 코랩 실습 

- k-최근접이웃 알고리즘을 사용하여 2개의 종류를 분류하는 머신러닝 모델 훈련

- #특성 #훈련 #k-최근접이웃알고리즘 #모델 #정확도

 

- 특성 : 데이터의 특징. 예) 도미의 특징을 길이와 무게로 표현한 것

아래 사용하는 생선 데이터셋은 캐글에 공개된 데이터셋을 사용.(https://www.kaggle.com/aungpyaeap/fish-market)

* 도미 데이터셋

bream_length = [25.4, 26.3, 26.5, 29.0, 29.0, 29.7, 29.7, 30.0, 30.0, 30.7, 31.0, 31.0, 
                31.5, 32.0, 32.0, 32.0, 33.0, 33.0, 33.5, 33.5, 34.0, 34.0, 34.5, 35.0, 
                35.0, 35.0, 35.0, 36.0, 36.0, 37.0, 38.5, 38.5, 39.5, 41.0, 41.0]
bream_weight = [242.0, 290.0, 340.0, 363.0, 430.0, 450.0, 500.0, 390.0, 450.0, 500.0, 475.0, 500.0, 
                500.0, 340.0, 600.0, 600.0, 700.0, 700.0, 610.0, 650.0, 575.0, 685.0, 620.0, 680.0, 
                700.0, 725.0, 720.0, 714.0, 850.0, 1000.0, 920.0, 955.0, 925.0, 975.0, 950.0]

 

- 산점도 : x, y축으로 이뤄진 좌표계에 두 변수(x, y)의 관계를 표현하는 방법

- 맷플롯립(matplotlib)의 scatter() 함수를 사용하여 산점도 그래프를 사용

- 도미 데이터셋의 길이를 x축, 무게를 y축으로 산점도를 표시

import matplotlib.pyplot as plt

bream_length = [25.4, 26.3, 26.5, 29.0, 29.0, 29.7, 29.7, 30.0, 30.0, 30.7, 31.0, 31.0, 
                31.5, 32.0, 32.0, 32.0, 33.0, 33.0, 33.5, 33.5, 34.0, 34.0, 34.5, 35.0, 
                35.0, 35.0, 35.0, 36.0, 36.0, 37.0, 38.5, 38.5, 39.5, 41.0, 41.0]
bream_weight = [242.0, 290.0, 340.0, 363.0, 430.0, 450.0, 500.0, 390.0, 450.0, 500.0, 475.0, 500.0, 
                500.0, 340.0, 600.0, 600.0, 700.0, 700.0, 610.0, 650.0, 575.0, 685.0, 620.0, 680.0, 
                700.0, 725.0, 720.0, 714.0, 850.0, 1000.0, 920.0, 955.0, 925.0, 975.0, 950.0]

plt.scatter(bream_length, bream_weight)
plt.xlabel('length')
plt.ylabel('weight')
plt.show()

 

- 코랩 실행 결과

도미데이터를 기준으로 산점도를 표시한 결과

 

* 빙어 데이터셋

smelt_length = [9.8, 10.5, 10.6, 11.0, 11.2, 11.3, 11.8, 11.8, 12.0, 12.2, 12.4, 13.0, 14.3, 15.0]
smelt_weight = [6.7, 7.5, 7.0, 9.7, 9.8, 8.7, 10.0, 9.9, 9.8, 12.2, 13.4, 12.2, 19.7, 19.9]

 - 기존 scatter() 함수에 빙어 데이터셋 추가

import matplotlib.pyplot as plt

bream_length = [25.4, 26.3, 26.5, 29.0, 29.0, 29.7, 29.7, 30.0, 30.0, 30.7, 31.0, 31.0, 
                31.5, 32.0, 32.0, 32.0, 33.0, 33.0, 33.5, 33.5, 34.0, 34.0, 34.5, 35.0, 
                35.0, 35.0, 35.0, 36.0, 36.0, 37.0, 38.5, 38.5, 39.5, 41.0, 41.0]
bream_weight = [242.0, 290.0, 340.0, 363.0, 430.0, 450.0, 500.0, 390.0, 450.0, 500.0, 475.0, 500.0, 
                500.0, 340.0, 600.0, 600.0, 700.0, 700.0, 610.0, 650.0, 575.0, 685.0, 620.0, 680.0, 
                700.0, 725.0, 720.0, 714.0, 850.0, 1000.0, 920.0, 955.0, 925.0, 975.0, 950.0]

smelt_length = [9.8, 10.5, 10.6, 11.0, 11.2, 11.3, 11.8, 11.8, 12.0, 12.2, 12.4, 13.0, 14.3, 15.0]
smelt_weight = [6.7, 7.5, 7.0, 9.7, 9.8, 8.7, 10.0, 9.9, 9.8, 12.2, 13.4, 12.2, 19.7, 19.9]

plt.scatter(bream_length, bream_weight)
plt.scatter(smelt_length, smelt_weight)
plt.xlabel('length')
plt.ylabel('weight')
plt.show()

 

- 코랩 실행 결과

빙어 데이터를 추가하여 산점도를 표시

 


k-최근접 이웃 알고리즘 적용

- k-최근접 이웃 알고리즘을 적용하여 도미와 빙어 데이터를 구분

- 사이킷런을 사용하여 머신러닝을 진행

- 사이킷런을 사용하기 위해서는 각 특성의 리스트를 세로 방향으로 늘어뜨린 2차원 리스트가 필요

- 파이썬의 zip() 함수와 리스트 내포(list comprehension) 구문을 사용하여 2차원 리스트를 생성

 

* 도미와 빙어의 데이터를 하나의 데이터로 만들기

length = bream_length + smelt_length
weight = bream_weight + smelt_weight

fish_data = [[l,w] for l, w in zip(length, weight)]
print(fish_data)

- 코랩 실행 결과

도미와 빙어의 데이터를 합쳐서 2차원 리스트로 만든 결과

 

- 머신 러닝을 하기 전에 준비할 정답 데이터셋.

- 머신 러닝 알고리즘이 생선의 길이와 무게를 보고 도미와 빙어를 구분하는 규칙을 찾기 원하기 때문

- 기존 데이터에서 어떤 것이 도미이고 어떤 것이 빙어인지 알려주어야 함

 

* 정답 데이터셋 만들기

fish_target = [1] * 35 + [0] * 14
print(fish_target)

 

- 코랩 실행 결과

정답 데이터셋

 

- 사이킷런의 k-최근접 이웃 알고리즘을 구현한 KNeighborsClassifier 클래스를 사용

- 훈련 : 기준 데이터를 사이킷런에 전달하여 학습시키는 과정

- 사이킷런에서는 fit() 메서드를 사용한다.

- fit() 메서드로 주어진 데이터로 알고리즘 훈련 후 얼마나 잘 훈련되었는지 score() 메서드를 사용하여 모델을 평가

- score() 메서드는 0~1 사이의 값을 반환. 1은 모든 데이터를 정확히 맞혔다는 것

 

* 데이터 알고리즘 학습

from sklearn.neighbors import KNeighborsClassifier

kn = KNeighborsClassifier()
kn.fit(fish_data, fish_target)
kn.score(fish_data, fish_target)

- 코랩 실행 결과

알고리즘 학습 결과


[선택] 간단히 사이킷런을 사용하여 알고리즘 학습을 진행해 보았고, 책에 나온 문제 내용을 정리

 

1. 머신 러닝 알고리즘의 한종류. 샘플 입력과 타깃을 알고 있을 때 사용할 수 있는 학습 방법 - 지도학습 

- 지도학습 : 훈련하기 위한 데이터와 정답이 필요. 정답(타깃)이 있으니 알고리즘 정답을 맞히는 것을 학습

- 비지도학습 : 타깃 없이 입력 ㅔ이터만 사용. 정답을 사요하지 않으므로 무언가를 맞힐 순 없으나 데이터를 잘 파악하거나 변형하는 데 도움을 줌

- 차원축소 : 비지도 학습의 큰 축. 고차원의 원본 데이터를 저 차원의 부분공간으로 투영하여 데이터를 축소하는 기법. 예) 10차원 이상의 데이터가 주어졌을 때 2~3차원의 데이터로 부분공간으로 투영하여 데이터를 축소. 차원이 증가할수록 데이터 포인트 간 거리가 기하급수적으로 멀어져 희소한 구조를 가지게 됨. 피처가 많아지게 되면 개별 피처 간 상관관계가 높아 다중공선성의 문제 과적합이나 예측 성능이 저하될 우려가 있음.

- 강화학습 : 현재의 상태(state)에서 어떤 행동(action)을 취하는 것이 최적인지를 학습하는 것. 행동을 취할 때마다 외부 환경에서 보상(reward)이 주어지고, 보상을 최대화하는 방향으로 학습이 진행

 

2. 훈련 세트와 테스트 세트가 잘못 만들어져 전체 데이터를 대표하지 못하는 현상 - 샘플링 편향

- 샘플링 오류 : sampling error는 랜덤 표본의 통계와 실제 모집단 값 사이의 불일치를 의미. 자연적인 우연인자를 말하는 것이지, 설계가 부실하고 실행이 잘 안되어 있는 실험에 의한 측정 오류는 아니다.

- 샘플링 실수 : 아직 답을 찾는 중입니다. 향후 업데이트

- 샘플링 편차 : 아직 답을 찾는 중입니다. 향후 업데이트

- 샘플링 편향 : 일반적으로 훈련 세트와 테스트 세트에 샘플이 골고루 섞여 있지 않으면 샘플링 한쪽으로 치우쳤다는 의미

 

3. 사이킷런은 입력 데이터(배열)가 어떻게 구성되어 있을 것으로 기대하는가

- 테이블의 행은 수많은 샘플들로 구성되고, 열은 샘플의 특성들로 구성.

- 샘플이 특성에 비해 너무 적으면 overfit이 발생하거나 예측이 안될 수 있음.

 

반응형

'IT > 머신러닝&딥러닝' 카테고리의 다른 글

05. 비지도 학습  (0) 2023.02.12
04. 교차 검증 및 앙상블 학습  (0) 2023.02.05
03. 로지스틱 회귀  (0) 2023.01.24
02. 회귀 알고리즘과 모델 규제  (0) 2023.01.15
00. 혼자 공부하는 머신러닝 & 딥러닝  (0) 2023.01.08
반응형

이번에 '혼자 공부하는 머신러닝 딥러닝'이란 책으로 공부하며 해당 내용들에 대한 정리를 위해 블로그에 글을 남겨 보고자 합니다. 

반응형
반응형
  1. 서브쿼리

서브쿼리는 SELECT 명령에 의한 데이터 질의로, 상부가 아닌 하부의 부수적 질의를 의미합니다.

서브쿼리를 지정하는 방법은 간단하게 SELECT 쿼리를 괄호로 묶어서 SELECT / FROM / WHERE 구 등에서 사용할 수 있습니다.

  1. 스칼라 값

서브쿼리를 다른 구에서 사용하는 것을 설명하기전에 스칼라 값이라는 것에 대해 설명해 보겠습니다.

서브쿼리를 사용할 때는 그 쿼리가 어떤 값을 반환하는지 주의할 필요가 있습니다. SELECT 쿼리를 실행 시 여러가지 패턴들이 나올수 있지만 일반적인 패턴에 대해 아래 표에 설명하겠습니다.


#

쿼리

설명

1

SELECT MIN(컬럼) FROM 테이블명

하나의 값을 반환

2

SELECT 컬럼 FROM 테이블명

하나의 컬럼에 복수의 레코드

3

SELECT MIN(컬럼1), MAX(컬럼2) FROM 테이블명

하나의 레코드 복수의 컬럼

4

SELECT 컬럼1, 컬럼2 FROM 테이블명

복수의 레코드 복수의 컬럼

[표 11. SELECT 쿼리 실행 시 반환되는 일반적인 패턴]


[표 11]에서 보면 다른 패턴과 다르게 1번 패턴은 하나의 값만을 반환합니다. 이렇게 SELECT 쿼리가 하나의 값만 반환하는 것을 단일값 또는 스칼라 값 이라고 합니다.

  1. WHERE 구에서 사용

WHERE 구에서 서브쿼리는 조건식에서 변수와 같이 사용이 가능합니다.

예를 들어 하나의 테이블에서 특정 컬럼의 최소 값을 찾아서 해당 레코드를 삭제해야 하는 경우를 생각해 보겠습니다. 이때 테이블에 데이터가 적고 한눈에 확인이 가능한 정도라면 눈으로 찾을 수 있겠지만 보통은 그렇게 찾을 수 없습니다. 이때 서브쿼리를 활용한다면 보다 쉽게 쿼리 작성이 됩니다.

먼저 서브쿼리는 해당 컬럼의 최소값을 찾을 것입니다.


1

SELECT MIN(컬럼) FROM 테이블;

[표 12. 최소값을 찾는 서브쿼리]


[표 12]와 같이 서브쿼리 작성이 되었다면 실제 레코드 삭제 부분에 적용해 보겠습니다.


1

DELETE FROM 테이블 WHERE 컬럼 = (SELECT MIN(컬럼) FROM 테이블);

[표 13. 최소값을 가진 레코드를 삭제하는 쿼리]


생각보다 간단하죠? 서브쿼리의 스칼라값을 조건식의 변수로 지정하여 사용하는 방법입니다. 하지만 데이터베이스별로 해당 쿼리가 실행이 되지 않을 수 있습니다.

동일한 테이블 내에서 추가나 갱신할 경우 서브쿼리가 제한될 수 있으니 사용하시는 데이터베이스 메뉴얼을 확인하길 바랍니다.

  1. SELECT 구에서 사용

SELECT 구에서 서브쿼리를 지정할 때는 스칼라 서브쿼리가 필요합니다.


1

SELECT

(SELECT COUNT(*) FROM 테이블명) AS sq;

[표 14. SELECT 구에서 서브쿼리 사용 방법]


[표 14]에서는 주의할 점이 있습니다. 서브쿼리가 아닌 상부의 SELECT 구에 FROM 구가 없다는 것입니다. 이것이 MySQL에서는 실행이 되지만 ORACLE과 같이 데이터 베이스에 따라 실행이 되지 않을 수 있습니다. 그럴때는 FROM 구를 정의해 줘야 합니다. 예를 들어 Oracle을 보면 FROM DUAL로 지정하면 실행할 수 있습니다. 다른 데이터베이스를 사용하신다면 메뉴얼을 확인하길 바랍니다.

  1. SET 구에서 사용

UPDATE의 SET구에서도 서브쿼리를 사용할 수 있습니다. SET 구에서도 서브쿼리를 사용할 때 스칼라 서브쿼리를 지정할 필요가 있습니다.


1

UPDATE 테이블 SET 컬럼 = (SELECT MAX(컬럼) FROM 테이블);

[표 15. SET구에서 서브쿼리 사용 방법]

  1. FROM 구에서 사용

지금까지는 FROM 구에서 테이블명을 지정하였습니다. 하지만 FROM 구에도 서브쿼리를 지정할 수 있습니다. 위에서는 서브쿼리를 사용할 때 스칼라 서브쿼리를 사용하라고 했었지만 FROM 구에서 사용되는 서브쿼리는 스칼라 값을 반환하지 않아도 됩니다.


1

SELECT * FROM (SELECT * FROM 테이블2);

[표 16. FROM 구에서 서브쿼리 사용 방법]


구조가 조금 특이하게 SELECT 쿼리 안에 SELECT 쿼리가 들어 있는 것처럼 보입니다. 이런것은 ‘네스티드 구조' 또는 ‘중첩구조', ‘내표 구조'라고 합니다.

[표 16]은 2단계 중첩 구조입니다. 중첩 구조는 몇단계를 구성해도 상관은 없습니다. 하지만 3단계 이상은 추천하지 않습니다.

  1. INSERT에서 사용

INSERT 쿼리에서도 VALUES 구의 일부로 서브쿼리를 사용할 수 있고, VALUE 구 대신 SELECT 쿼리를 사용하는 두가지 방법이 있습니다.


첫째, VALUES 구의 일부로 사용될 때

이때는 서브쿼리는 스칼라 서브쿼리를 사용해야 하고 자료형도 일치해야 합니다.


1

INSERT INTO 테이블 VALUES (

  (SELECT COUNT(*) FROM 테이블2), ...

);

[표 17. VALUES 구의 일부로 서브쿼리 사용 방법]


둘째, VALUES 구 대신 서브쿼리가 사용될 때

흔히 ‘INSERT SELECT’라 불리는 쿼리입니다. INSERT SELECT 쿼리는 SELECT 쿼리의 결과를 INSERT INTO로 지정된 테이블에 전부 추가합니다. 여기서 주의할 것은 SELECT 쿼리에서 반환하는 컬럼의 수와 자료형이 INSERT할 테이블과 일치해야 합니다. 그래서 INSERT SELECT는 테이터의 복사나 이동을 할 때 자주 사용됩니다.


1

INSERT INTO 테이블 SELECT * FROM 테이블2;

[표 18. VALUES 구 대신 SELECT 쿼리를 사용하는 방법]


반응형
반응형
  1. 집계 함수

이번에는 대표적인 집계 함수 COUNT, SUM, AVG, MIN, MAX와 GROUP BY를 사용하여 그룹화하는 방법을 알아보겠습니다.

SQL은 집합을 다루는 집계함수를 제공합니다. 일반적으로 함수는 파라미터로 하나의 값을 지정합니다. 하지만 집계함수의 경우는 파라미터로 집합을 지정합니다.

여기서 얘기하는 집계함수의 파라미터로 집합을 지정한다는 말이 쉽게 이해하기 어려울 수 있습니다. 이것에 대해서는 COUNT에서 한번 설명해 보겠습니다.

    1. COUNT

COUNT 함수는 파라미터로 주어진 집합의 개수를 반환합니다.


1

SELECT COUNT(컬럼명) FROM 테이블명 WHERE 조건식;

[표 1. COUNT 함수의 사용 방법]


간단합니다. 뭘 어떻게 더 설명하기 어려울 정도로 간단합니다.


추가로 설명을 하면 COUNT 집계를 사용할때 컬럼의 값 중 NULL이 있을 경우 NULL은 포함하지 않습니다. 또한 중복 데이터의 경우는 별도로 중복제거를 하지 않는다면 포함하여 집계합니다.

그러면 중복을 제외하고 집계해야하는 상황에서는 어떻게 해야할까요?

DISTINCT를 지정한 컬럼은 중복값을 제외하고 결과를 반환하는 함수입니다.

그래서 DISTINCT를 사용한 결과를 집계 함수에 적용하면 중복값을 제거한 집계 결과를 확인할 수 있습니다.


1

SELECT COUNT(DISTINCT 컬럼명) FROM 테이블명 WHERE 조건식;

[표 2. DISTINCT 를 이용한 COUNT 함수 사용 방법]

    1. SUM

집합 연산 중에서 합계를 구하기 위해 자주 사용하는 것이 SUM 함수입니다.

SUM 함수를 사용하면 지정한 컬럼의 합계를 구할 수 있습니다. 집계 가능한 범위는 수치형 데이터만 가능합니다. 문자열이나 날짜형의 데이터를 지정할 수 없습니다.

SUM도 COUNT와 마찬가지로 NULL 값을 제거한 뒤에 합계를 반환합니다.


1

SELECT SUM(컬럼명) FROM 테이블명 WHERE 조건식;

[표 3. SUM 함수 사용 방법]

    1. AVG

평균값을 구하기 위해서는 SUM / COUNT 와 같이 지정하면 구할 수 있지만 굳이 저렇게 사용하지 않아도 간단히 평균값을 구할 수 있습니다. 바로 AVG 함수를 이용하면 됩니다. AVG 함수는 지정한 컬럼의 평균값을 구하는 함수로서 SUM과 마찬가지로 수치형만 가능합니다.

AVG 함수도 NULL값은 제거한 뒤에 계산을 합니다. 하지만 NULL을 0으로 간주해서 평균을 내고 싶다면 CASE를 이용해서 NULL을 0으로 변환한뒤 AVG를 사용하면 됩니다.


1

SELECT AVG(컬럼명) FROM 테이블명 WHERE 조건식;

[표 4. AVG 함수 사용 방법]

    1. MIN / MAX

MIN, MAX 함수는 컬럼에서 최소값과 최대값을 구할 수 있습니다.

위의 다른 함수와 달리 문자열과 날짜형에도 사용할 수 있고 NULL 값은 무시합니다.


1

SELECT MIN(컬럼명), MAX(컬럼명) FROM 테이블명;

[표 5. MIN, MAX 함수 사용 방법]

    1. GROUP BY

GROUP BY 에 컬럼을 지정하여 그룹화하면 지정된 컬럼의 값이 같은 레코드들이 하나의 그룹으로 묶입니다.

각 그룹에 묶인 값들은 동일합니다. 그래서 GROUP BY를 사용하면 DISTINCT와 같이 중복을 제거하는 효과가 있습니다.

그렇다면 DISTINCT와 GROUP BY는 무슨 차이가 있을까요?

두가지 함수 모두 중복값을 제거 한다는것은 동일하지만 GROUP BY는 집계 함수와 쓰이지 않으면 별 의미가 없습니다. GROUP BY로 그룹화하고 각각의 그룹을 집계 함수에서 파라미터로 사용해야 GROUP BY가 의미가 있습니다.


1

SELECT SUM(컬럼명) FROM 테이블명 GROUP BY 컬럼명;

[표 6. GROUP BY 사용 방법]

    1. HAVING

그러면 그룹화를 시키고 집계 함수를 사용할 때 WHERE 구의 조건식에는 집계 함수를 사용할 수는 없을까요? 네 없습니다. 그룹화가 필요한 집계 함수는 WHERE 구에서 지정할 수 없습니다.

이게 무슨 말일까요 아래 표를 보고 설명 드리겠습니다.


1

SELECT SUM(컬럼명) FROM 테이블명 WHERE COUNT(컬럼명) = 1 GROUP BY 컬럼명;

[표 7. WHERE 구에서 집계 함수 사용]


[표 7]에서 사용한 문법 사용대로 한다면 에러가 발생합니다.

그 이유는 GROUP BY와 WHERE 구의 처리 순서 때문입니다. WHERE 구의 처리는 GROUP BY 보다 빠릅니다. 그래서 그룹화가 되기전에 조건절에서 컬럼을 집계하려고 하면 에러가 발생하는 것입니다.

쿼리의 내부처리 순서를 다시 한번 살펴 보겠습니다.


순위

1

WHERE

2

GROUP BY

3

SELECT

4

ORDER BY

[표 8. 쿼리의 내부 처리 순서]


지금까지 HAVING을 설명하기전 다른것은 왜 안되는지에 대해 먼저 살펴 보았습니다.

우리가 원하는대로 집계한 결과에서 조건에 맞는 값을 가져오기 위해서는 HAVING을 사용하면 됩니다.


HAVING은 GROUP BY 구 뒤에 기술하고 WHERE와 동일하게 조건식 지정이 가능합니다. 즉, 그룹화된 컬럼을 이용하여 조건식에서 집계 함수를 사용할 수 있다는 것입니다.

[표 8]에서 설명한 쿼리의 내부처리 순서에 HAVING이 들어간다면 2번째인 GROUP BY 다음에 들어가게 됩니다.


순위

1

WHERE

2

GROUP BY

3

HAVING

4

SELECT

5

ORDER BY

[표 9. HAVING을 추가한 쿼리의 내부 처리 순서]


1

SELECT SUM(컬럼명) FROM 테이블명 GROUP BY 컬럼명 HAVING COUNT(컬럼명) = 식;

[표 10. HAVING을 이용한 조건식 사용법]


반응형
반응형
  1. INSERT

이전 글들은 SELECT를 활용해서 데이터를 검색하는 것이었다면 지금은 데이터를 입력할 때의 방법을 설명하겠습니다.


우리가 게시판을 하나 만들었다고 한다면 최초 서비스가 올라갔을 때는 게시글이 하나도 없을 것입니다. 그러면 우리는 ‘글쓰기' 또는 ‘만들기’와 같은 버튼을 클릭했을 때 데이터 추가 기능을 사용할 것입니다. 여기서 사용하는 것이 INSERT라고 생각하면 됩니다.

    1. INSERT로 레코드 추가하기

RDBMS에서는 INSERT 명령으로 레코드 단위로 데이터를 추가합니다.


1

INSERT INTO 테이블명 VALUES (값1, 값2, 값3 ...);

[표 1. INSERT를 사용하는 방법]


해당 쿼리의 형식으로 실행 시 지정한 테이블에 레코드가 추가됩니다.


INSERT 쿼리는 실행을 하면 처리 상태만 표시되고 SELECT와 같이 실행했을 때 결과를 보여주지 않습니다. 제대로 들어갔는지 확인하기 위해서는 SELECT 쿼리를 실행하여 확인하면됩니다.


스크린샷 2017-02-21 오후 3.06.33.png

[그림 1. INSERT 쿼리 실행과 검색]

    1. 값을 저장할 컬럼 지정하기

INSERT 쿼리 실행 시 테이블명만 지정하고 컬럼명을 지정하지 않을 경우는 모든 컬럼의 값을 VALUES 부분에 모든 컬럼에 대한 값을 지정해야 합니다.

하지만 테이블을 지정하고 괄호로 값을 넣을 컬럼명을 지정할 경우 해당 컬럼에만 값이 들어갑니다.


1

INSERT INTO 테이블명 (컬럼1, 커럼2 …) VALUES (값1, 값2, 값3 ...);

[표 2. 컬럼을 지정하여 값 지정]


스크린샷 2017-02-21 오후 3.14.44.png

[그림 2. 컬럼을 지정하여 실행한 결과]

    1. NOT NULL

레코드를 추가할 때 NULL을 지정하고 싶을 경우에는 VALUES에서 NULL로 값을 지정할 수 있습니다.


1

INSERT INTO 테이블명 VALUES (NULL, NULL, NULL ...);

[표 3. NULL값을 지정]


스크린샷 2017-02-21 오후 3.15.27.png

[그림 3. NULL 값을 지정하여 실행한 결과]


지금 샘플 테이블에는 모든 컬럼이 NULL을 허용하고 있습니다. 그런데 만약 컬럼 중 NOT NULL 제약이 걸려있는 것이 있다고 하면 샘플로 실행한 쿼리는 에러가 발생합니다. 그 이유는 NOT NULL 제약이 걸려 있는 컬럼은 NULL 값을 허용안되기 때문입니다.

    1. DEFAULT

DEFAULT는 명시적으로 값을 지정하지 않았을 경우 사용하는 초기값을 말합니다. 이것은 테이블을 정의할 때 지정할 수 있습니다.


DEFAULT는 두가지 방법으로 사용할 수 있습니다.

DEFAULT를 명시하는 방법과 암묵적으로 디폴트를 사용하는 방법이 있습니다.

보통 INSERT 사용 시 디폴트가 지정되어 있는 컬럼을 제외하고 쿼리를 실행 합니다. 그렇게 실행을 하더라도 컬럼의 값이 디폴트로 저장이 되기 때문입니다.

  1. DELETE

서비스를 하다보면 데이터를 삭제해야 하는 경우가 있습니다.

예를 들어 게시판의 글 중에 글을 하나 삭제한다고 했을 때 ‘삭제' 또는 ‘지우기'같은 버튼을 클릭 했을 때 데이터 삭제 기능을 사용할 것입니다.

    1. DELETE로 레코드 삭제하기

RDBMS에서 데이터를 삭제할 경우에는 DELETE 쿼리를 실행합니다.


1

DELETE FROM 테이블명 WHERE 조건식;

[표 4. DELECT를 사용하는 방법]


[표 4]에서 WHERE 조건식이 없다면 테이블의 모든 레코드를 삭제하게 됩니다. 그래서 조건에 부합하는 레코드만 삭제되도록 조건식을 넣어줘야 합니다.


아마 컬럼의 데이터만 삭제할 수 있지 않을까? 라고 생각하시는 분들이 있습니다. 결론은 안된다. 입니다. 컬럼 단위로 삭제가 아닌 레코드 단위이고 조건에 일치하는 모든행을 삭제하므로 사용시 주의해야 합니다.


스크린샷 2017-02-21 오후 3.40.30.png

[그림 4. DELETE 쿼리를 실행한 결과]

  1. UPDATE

데이터 갱신 작업은 시스템에서 자주 발생합니다.

예를 들어 게시판에서 게시글을 수정할 때 ‘수정' 또는 ‘갱신'과 같은 버튼을 클릭 시 내부적으로 데이터 갱신 기능을 사용할 것입니다.

    1. UPDATE로 데이터 갱신하기

RDBMS에서는 UPDATE 쿼리로 데이터를 갱신할 수 있습니다. 이것은 테이블의 셀 값을 갱신하는 명령입니다.


1

UPDATE 테이블명 SET 컬럼명 = 값 WHERE 조건식;

[표 5. UPDATE의 사용 방법]


DELETE와 달리 셀 단위로 데이터를 갱신할 수 있습니다. WHERE 조건식을 일치하는 모든 레코드를 갱신할 수 있습니다. 만약 WHERE 조건식을 제외한다면 테이블의 모든 레코드가 갱신됩니다.


스크린샷 2017-02-21 오후 3.49.38.png

[그림 5. UPDATE 쿼리를 실행한 결과]

    1. 복수의 컬럼 갱신

위에서는 컬럼 하나에 대한것만 갱신을 하였습니다. 이번에는 복수의 컬럼을 갱신할 때 UPDATE를 어떻게 사용해야하는지 보겠습니다.


1

UPDATE 테이블명 SET 컬럼명1 = 값1, 컬럼명 2 = 값2, …  WHERE 조건식;

[표 6. 복수의 컬럼을 지정한 UPDATE 사용 방법]


스크린샷 2017-02-21 오후 4.33.05.png

[그림 6. 복수의 컬럼을 지정한 UPDATE 쿼리 실행 결과]


만약 NULL로 데이터를 초기화하려고 한다면 컬럼명 = NULL 로 지정하면 됩니다. 이런것을 NULL 초기화라고 합니다. 대신 갱신하려는 컬럼이 NOT NULL 제약 조건이 걸려있는것은 아닌지 확인하고 실행하면 됩니다.

  1. 물리 삭제, 논리 삭제

실제 서비스를 진행하면서 데이터를 삭제할 때 데이터를 삭제해 버리는 경우와 별도 삭제 플래그를 넣어서 실제 레코드는 삭제되지 않지만 플래그 값을 기준으로 삭제를 판단하는 경우가 있습니다. 여기서 말하는 삭제하는 것을 물리삭제, 삭제 플래그를 지정하는 것을 논리 삭제라고합니다.

왜 이렇게 사용한다라고 말을 하기보다는 데이터 특성이나 서비스 운영 정책에 따라 달라지기 때문에 뭐라 단정지어서 말하기 어렵습니다.

어느 테이블의 경우는 데이터를 삭제를 해야하고 어느 테이블은 삭제 플래그를 넣고 데이터는 유지하는 것처럼 섞여서 사용되기 때문에 내부 서비스 정책 및 용도에 맞게 선택하여 사용하면 될 것 같습니다.



반응형

+ Recent posts