SeSAC - 머신러닝 및 AI 기술 개요(1)


신경정보처리 시스템학회

https://nips.cc/

튜링 테스트

https://terms.tta.or.kr/dictionary/dictionaryView.do?subject=%ED%8A%9C%EB%A7%81+%EC%8B%9C%ED%97%98

생각에 관한 생각

https://www.yes24.com/Product/Goods/59616093

LLaMa, 알파카

https://www.storagereview.com/ko/review/meta-llama-and-alpacas-loose-in-the-lab-running-large-language-models-locally

머신러닝

  1. 인공지능은 어떠한 방법이든 수학적인 방법이 있어야한다.
  2. 모든 프로그램은 수학적인 방법이 기저가 된다.
  3. 데이터를 통해서 어떠한 것을 예측할 수 있는 통찰을 얻어내는것 -> 머신러닝
  4. 머신러닝은 딥러닝을 포함한다.

알고리즘과 모델

알고리즘 : 컴퓨터가 어떤일을 수행하는 명시적인 조건의 나열 모델 : 수학적인 기저가 있는 특정한 방법

알고리즘의 분류

수학적인 방법에 따라 4가지로 분류

  • Similarity-Based Learning : 유사성 기반

-> 누구와 얼마나 비슷한지

-> 두 숫자가 있다면 그 두 숫자를 기하학적으로 두 숫자의 가까운 거리로 유사성을 측정


  • probablity-Based Learning : 확률 기반


  • Information-Based Learning : 정보 기반

-> 스무고개와 비슷하다

-> 여기서 가장 유명한게 Decision Tree


  • Error-Based Learning : 오차 베이스, 틀린것을 측정해서 오차가 줄어들때 까지 공부하는것, 딥러닝

-> 내가 가지고 있는 데이터를 가장 잘 설명하는 직선

-> 원본 데이터와 가장 오차가 작은 직선


머신러닝은 데이터라는 축으로 분류하면 3가지로 분류

  • Supervised Learning : 지도학습 -> 사진을 제시하고, 그것에 대한 답을 알려준다. 라벨이 있음
  • Reinforcement Learning : 강화학습 -> 데이터가 없음, 시도에 의한 경험에 의해서 학습
  • Unsupervised Learning : 비지도학습 -> 사진을 제시하고, 라벨이 없는 데이터를 비슷한 특징끼리 군집화 하여 새로운 데이터에 대한 결과를 예측, 라벨이 없음


Supervised Learning

지도학습은 다시 다음에 따라 나눠진다.

  • Regression(회귀) : 선형적, 연속적인 수치를 예측할때 -> Linear, Logistic, Decision Tree
  • classification(분류) : 이상값들을 예측할때 -> KNeighbors


깃허브 페이지 내에 ipynb파일 따라해보기

https://github.com/rickiepark/hg-mldl


생선 분류 문제(1-3)

도미 데이터 준비하기

# 도미의 길이
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]
import matplotlib.pyplot as plt

# 산점도를 그린다.
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]
# 기본적으로 plt는 subplot figure등을 사용하지 않으면 한 그래프에 덮어쓴다.
plt.scatter(bream_length, bream_weight)
plt.scatter(smelt_length, smelt_weight)
plt.xlabel('length')
plt.ylabel('weight')
plt.show()


첫 번째 머신러닝 프로그램

length = bream_length+smelt_length
weight = bream_weight+smelt_weight
# 리스트 컴프리헨션 l, w가 만들어질 조건을 제시
# zip함수가 만들어줘서 던져주는 l, w를 리스트로 묶어서 저장  
fish_data = [[l, w] for l, w in zip(length, weight)]

print(fish_data)

-> [[25.4, 242.0], [26.3, 290.0], [26.5, 340.0], [29.0, 363.0], [29.0, 430.0], [29.7, 450.0], [29.7, 500.0], [30.0, 390.0], [30.0, 450.0], [30.7, 500.0], [31.0, 475.0], [31.0, 500.0], [31.5, 500.0], [32.0, 340.0], [32.0, 600.0], [32.0, 600.0], [33.0, 700.0], [33.0, 700.0], [33.5, 610.0], [33.5, 650.0], [34.0, 575.0], [34.0, 685.0], [34.5, 620.0], [35.0, 680.0], [35.0, 700.0], [35.0, 725.0], [35.0, 720.0], [36.0, 714.0], [36.0, 850.0], [37.0, 1000.0], [38.5, 920.0], [38.5, 955.0], [39.5, 925.0], [41.0, 975.0], [41.0, 950.0], [9.8, 6.7], [10.5, 7.5], [10.6, 7.0], [11.0, 9.7], [11.2, 9.8], [11.3, 8.7], [11.8, 10.0], [11.8, 9.9], [12.0, 9.8], [12.2, 12.2], [12.4, 13.4], [13.0, 12.2], [14.3, 19.7], [15.0, 19.9]]
# 1이면 돔, 0이면 빙어
fish_target = [1]*35 + [0]*14
print(fish_target)

->   
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# pip install scikit-learn
from sklearn.neighbors import KNeighborsClassifier
# 사이킷 런, 지도학습 모델, 분류에 사용
# 변수의 이름이자, 모델 객체
kn = KNeighborsClassifier()
# 기본적으로 fit에는 매개변수가 2개 들어간다.
kn.fit(fish_data, fish_target)

# 성능이 1이 나오면 100점이 나온것
kn.score(fish_data, fish_target)
-> 1.0

k #  k-NN 모델에서의 k값은 하이퍼파라미터

파라미터, 하이퍼파라미터

https://heekangpark.github.io/ml-shorts/parameter-vs-hyperparameter

# k-최근접 이웃 알고리즘
plt.scatter(bream_length, bream_weight)
plt.scatter(smelt_length, smelt_weight)
plt.scatter(30, 600, marker='^') # 30, 600위치에 캐럿마크를 남긴다
plt.xlabel("length")
plt.ylabel("weight")
plt.show()

# 30, 600은 도미일까? 빙어일까?
kn.predict([[30, 600]])
-> array([1]) # 도미
print(kn._fit_X)
[[   1.   242. ]
 [   1.   290. ]
 [   1.   340. ]
 [   1.   363. ]
 [   1.   430. ]
 [   1.   450. ]
 [   1.   500. ]
 [   1.   390. ]
 [   1.   450. ]
 [   1.   500. ]
 [   1.   475. ]
 [   1.   500. ]
 [   1.   500. ]
 [   1.   340. ]
 [   1.   600. ]
 [   1.   600. ]
 [   1.   700. ]
 [   1.   700. ]
 [   1.   610. ]
 [   1.   650. ]
 [   1.   575. ]
 [   1.   685. ]
 [   1.   620. ]
 [   1.   680. ]
 [   1.   700. ]
 [   1.   725. ]
 [   1.   720. ]
 [   1.   714. ]
 [   1.   850. ]
 [   1.  1000. ]
 [   1.   920. ]
 [   1.   955. ]
 [   1.   925. ]
 [   1.   975. ]
 [   1.   950. ]
 [   1.     6.7]
 [   1.     7.5]
 [   1.     7. ]
 [   1.     9.7]
 [   1.     9.8]
 [   1.     8.7]
 [   1.    10. ]
 [   1.     9.9]
 [   1.     9.8]
 [   1.    12.2]
 [   1.    13.4]
 [   1.    12.2]
 [   1.    19.7]
 [   1.    19.9]]
 
print(kn._y)
[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0]

지도학습은 자료와 라벨이 있어야한다. 통계학에서는 독립변수(데이터, feature)라 부르고, 라벨은 종속변수(타겟)라 부른다.

# 이웃 49개를 확인, 이렇게 하면 유용한 모델을 얻지 못한다.
# 도미가 35, 빙어가 14인데, 전체 49개 클래스를 확인하면 
kn49 = KNeighborsClassifier(n_neighbors=49)
kn49.fit(fish_data, fish_target)
kn49.score(fish_data, fish_target)
-> 0.7142857142857143

# 전체에서 도미를 나눈 약 70%확률만 나온다.
print(35/49)
-> 0.7142857142857143
# 확인 문제
kn = KNeighborsClassifier()
kn.fit(fish_data, fish_target)

for n in range(5, 50):
    # 최근접 이웃 개수 설정
    kn.n_neighbors = n
    # 점수 계산
    score = kn.score(fish_data, fish_target)
    # 100% 정확도에 미치지 못하는 이웃 개수 출력
    if score < 1:
        print(n, score)
        break


-> 18 0.9795918367346939

훈련 세트와 테스트 세트

fish_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, 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]
                
fish_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, 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]
# 리스트 컴프리헨션
fish_data = [[l, w] for l, w in zip(fish_length, fish_weight)]
fish_target = [1]*35 + [0]*14
from sklearn.neighbors import KNeighborsClassifier

kn = KNeighborsClassifier()
# fish_data의 5번째 값 출력
print(fish_data[4])
-> [29.0, 430.0]

print(fish_data[0:5])
-> [[25.4, 242.0], [26.3, 290.0], [26.5, 340.0], [29.0, 363.0], [29.0, 430.0]]

print(fish_data[:5])
-> [[25.4, 242.0], [26.3, 290.0], [26.5, 340.0], [29.0, 363.0], [29.0, 430.0]]

print(fish_data[44:])
-> [[12.2, 12.2], [12.4, 13.4], [13.0, 12.2], [14.3, 19.7], [15.0, 19.9]]
train_input = fish_data[:35]
train_target = fish_target[:35]

test_input = fish_data[35:]
test_target = fish_target[35:]
kn.fit(train_input, train_target) 
kn.score(test_input, test_target)
-> 0.0


(2-1)

numpy

# 넘파이를 불러온다
import numpy as np

# fish_data와 fish_target을 numpy array형태로 바꾼다.
input_arr = np.array(fish_data)
target_arr = np.array(fish_target)


# 리스트는 차원이 없어서 출력시 일렬로 쭉 나열되지만
# numpy array는 차원이 있어서 정렬된 형태로 출력된다.
print(input_arr)
->
[[  25.4  242. ]
 [  26.3  290. ]
 [  26.5  340. ]
 [  29.   363. ]
 [  29.   430. ]
 [  29.7  450. ]
 [  29.7  500. ]
 [  30.   390. ]
 [  30.   450. ]
 [  30.7  500. ]
 [  31.   475. ]
 [  31.   500. ]
 [  31.5  500. ]
 [  32.   340. ]
 [  32.   600. ]
 [  32.   600. ]
 [  33.   700. ]
 [  33.   700. ]
 [  33.5  610. ]
 [  33.5  650. ]
 [  34.   575. ]
 [  34.   685. ]
 [  34.5  620. ]
 [  35.   680. ]
 [  35.   700. ]
 [  35.   725. ]
 [  35.   720. ]
 [  36.   714. ]
 [  36.   850. ]
 [  37.  1000. ]
 [  38.5  920. ]
 [  38.5  955. ]
 [  39.5  925. ]
 [  41.   975. ]
 [  41.   950. ]
 [   9.8    6.7]
 [  10.5    7.5]
 [  10.6    7. ]
 [  11.     9.7]
 [  11.2    9.8]
 [  11.3    8.7]
 [  11.8   10. ]
 [  11.8    9.9]
 [  12.     9.8]
 [  12.2   12.2]
 [  12.4   13.4]
 [  13.    12.2]
 [  14.3   19.7]
 [  15.    19.9]]
print(input_arr.shape) # 49개의 데이터가 있는데, 2차원의 형태로 있다.
-> (49, 2)

np.random.seed(42)
index = np.arange(49)
np.random.shuffle(index)

print(index)
-> [13 45 47 44 17 27 26 25 31 19 12  4 34  8  3  6 40 41 46 15  9 16 24 33 30  0 43 32  5 29 11 36  1 21  2 37 35 23 39 10 22 18 48 20  7 42 14 28 38]
# 0에서 48까지 랜덤으로 값이 담긴다

# input_arr의 2번째 값과 4번째 값을 출력
print(input_arr[[1, 3]])
-> [[ 26.3 290. ]
 [ 29.  363. ]]

# 0에서 34까지 
train_input = input_arr[index[:35]]
train_target = target_arr[index[:35]]

print(input_arr[13], train_input[0])
-> [ 32. 340.] [ 32. 340.]

test_input = input_arr[index[35:]]
test_target = target_arr[index[35:]]
import matplotlib.pyplot as plt

# 파란색 = 훈련 데이터
plt.scatter(train_input[:, 0], train_input[:, 1])
# 주황색 = 테스트 데이터
plt.scatter(test_input[:, 0], test_input[:, 1])
plt.xlabel('length')
plt.ylabel('weight')
plt.show()


데이터 전처리(2-2)

fish_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, 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]
fish_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, 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]
import numpy as np

# 2행 3열
np.column_stack(([1,2,3], [4,5,6]))
->
array([[1, 4],
       [2, 5],
       [3, 6]])
# zip과 같다. 
fish_data = np.column_stack((fish_length, fish_weight))
print(fish_data[:5])
-> [[ 25.4 242. ]
 [ 26.3 290. ]
 [ 26.5 340. ]
 [ 29.  363. ]
 [ 29.  430. ]]
print(np.ones(5))
-> [1. 1. 1. 1. 1.]

fish_target = np.concatenate((np.ones(35), np.zeros(14)))
print(fish_target)
-> [1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]


사이킷런으로 훈련 세트와 테스트 세트 나누기

https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html

from sklearn.model_selection import train_test_split


# 2개의 매개변수를 받아 쪼개고, 4개의 변수에 넣어준다.
# train_test_split(x:data, y:target)
train_input, test_input, train_target, test_target = train_test_split( fish_data, fish_target, random_state=42)

print(train_input.shape, test_input.shape)
-> (36, 2) (13, 2)

# 타겟의 shape가 차원이 없다. 0차원
print(train_target.shape, test_target.shape)
-> (36,) (13,)

print(test_target)
->[1. 0. 0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
# stratipy : 비율 맞추기
train_input, test_input, train_target, test_target = train_test_split(
    fish_data, fish_target, stratify=fish_target, random_state=42)
    
print(test_target)
-> [0. 0. 1. 0. 1. 0. 1. 1. 1. 1. 1. 1. 1.]

stratipy https://yeko90.tistory.com/entry/what-is-stratify-in-traintestsplit


수상한 도미 한마리

  
from sklearn.neighbors import KNeighborsClassifier kn = KNeighborsClassifier() kn.fit(train_input, train_target) 

kn.score(test_input, test_target)
-> 1.0

print(kn.predict([[25, 150]]))
-> [0.]
import matplotlib.pyplot as plt

plt.scatter(train_input[:,0], train_input[:,1])
plt.scatter(25, 150, marker='^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()

distances, indexes = kn.kneighbors([[25, 150]])

# 캐럿에서 가까운것을 찍어본다.
plt.scatter(train_input[:,0], train_input[:,1])
plt.scatter(25, 150, marker='^')
plt.scatter(train_input[indexes,0], train_input[indexes,1], marker='D')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()

# 분명 보기에는 빙어가 캐럿(도미)보다 멀어보이지만 캐럿이 빙어와 더 가깝다고 한다.
# 보이는것이 왜곡된 것
print(train_input[indexes])
->
[[[ 25.4 242. ]
  [ 15.   19.9]
  [ 14.3  19.7]
  [ 13.   12.2]
  [ 12.2  12.2]]]

print(train_target[indexes])
-> [[1. 0. 0. 0. 0.]]

print(distances)
-> [[ 92.00086956 130.48375378 130.73859415 138.32150953 138.39320793]]


기준을 맞춰라(표준화, standardization)

# 표준화를 하고 보니 캐럿이 빙어가 더 가까운게 맞다.
plt.scatter(train_input[:,0], train_input[:,1])
plt.scatter(25, 150, marker='^')
plt.scatter(train_input[indexes,0], train_input[indexes,1], marker='D')
plt.xlim((0, 1000))
plt.xlabel('length')
plt.ylabel('weight')
plt.show()

# 데이터의 각 열 (axis 0)을 따라 평균과 표준 편차를 계산
mean = np.mean(train_input, axis=0)
std = np.std(train_input, axis=0)

print(mean, std)
# 길이의 평균, 무게의 평균, 길이의 표준편차, 무게의 표준편차
# 표준편차 : 평균에서 벗어난 정도
-> [ 27.29722222 454.09722222] [  9.98244253 323.29893931]

# standardization 표준화
# train_input(2차원 데이터)에서 평균(2차원 데이터)을 빼고 표준편차(2차원 데이터)로 나눴다.
# 평균과 표준편차를 프린트 해보면 [ 27.29722222 454.09722222] [  9.98244253 323.29893931]처럼 2차원 데이터로 나와있는데 이것을 자동으로 각각의 데이터끼리 빼고 나눠줬다는걸 알수있다.
# 이것을 통해 무게, 길이와 같이 단위가 다른 유닛을 맞춰서 표준화 한다.
train_scaled = (train_input - mean) / std
# 0에서 1사이로 쏠려있다.
# 질문하는 데이터는 표준화가 되어있지 않기때문에 멀리 떨어져있다. 
plt.scatter(train_scaled[:,0], train_scaled[:,1])
plt.scatter(25, 150, marker='^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()


머신러닝 : 데이터를 통해서 새로운 것을 예측

  • 개와 고양이의 사진 5000장이 있을 때 우리는 이것을 훈련에 사용했다면 우리는 저 5000장의 사진을 잘 알아보기 위해 개와 고양이 사진을 사용했는가? -> 아니다.
  • 새로운 개와 고양이 사진을 잘 알아보기 위해 훈련용으로 사용했을 뿐이다.
  • 샘플이 자연계의 개라는 모집단과 고양이라는 모집단을 대변할 수는 없다.
  • 정규분포를 따르는가? 샘플을 뽑아서 원본의 정규분포를 따르는지 확인


# 질문하는 데이터에 평균을 빼고 표준편차로 나눠서 다시 출력해본다.
new = ([25, 150] - mean) / std

plt.scatter(train_scaled[:,0], train_scaled[:,1])
plt.scatter(new[0], new[1], marker='^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()

kn.fit(train_scaled, train_target)
test_scaled = (test_input - mean) / std
# 양쪽의 스케일을 맞춰서 표준화를 하니 도미로 나온다.
# 이를 통해 모든 숫자의 데이터는 표준화가 중요하다는것을 알수있다.
kn.score(test_scaled, test_target)
-> 1.0
print(kn.predict([new]))
-> [1.]
plt.scatter(train_scaled[:,0], train_scaled[:,1])
plt.scatter(new[0], new[1], marker='^')
plt.scatter(train_scaled[indexes,0], train_scaled[indexes,1], marker='D')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()


k-최근접 이웃 회귀(3-1)


데이터 준비

import numpy as np
# 농어의 무게를 입력하면 길이 예측해보기 -> 지도 학습 회귀모델
# k-최근접 이웃 회귀의 한계 : 내가 가지고 있는 데이터가 한정적인데 새롭게 들어오는 데이터를 예측하기가 어렵다. 예를들어 여기 리스트에서 55cm의 농어라면?
# -> 선형 회귀(Linear)로 해결

# 선형회귀는 곡선이 유용해 보이는데 왜 직선형일까?
# 차원이 높아지면 우리는 볼수없기 때문에
# 이 데이터는 무게를 입력하면 길이를 예측해보는 것이지만, 경매가 예측 같이 입력이 많아지면
# 우리는 그 차원 상의 데이터를 그려볼 수 없다. 그렇기 때문에 직선으로 한다.

# 농어의 길이
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]
     )
import matplotlib.pyplot as plt
plt.scatter(perch_length, perch_weight)
plt.xlabel("length")
plt.ylabel("weight")
plt.show()

from sklearn.model_selection import train_test_split

# train_test_split()을 이용해 훈련 세트와 테스트 세트로 나눈다.
train_input, test_input, train_target, test_target = train_test_split(perch_length, perch_weight, random_state=42)

# 0차원 데이터
# [30, 24, 3] 0차원
# [[30], [24], [3]] 1차원
print(train_input.shape, test_input.shape)
-> (42,) (14,)
test_array = np.array([1,2,3,4])
print(test_array.shape)
-> (4,)
test_array = test_array.reshape(2, 2)
print(test_array.shape)
-> (2, 2)

# 아래 코드의 주석을 제거하고 실행하면 에러가 발생
# test_array = test_array.reshape(2, 3)
# -1 : 모든 데이터에 대해
# 1 : 1차원으로 바꿔라
train_input = train_input.reshape(-1, 1)
test_input = test_input.reshape(-1, 1)

print(train_input.shape, test_input.shape)
-> (42, 1) (14, 1)


결정 계수 ($R^2$, R square) : 평가 척도

-> 회귀에서 사용되는 가장 보편적인 평가 지표


비지도 학습 모델은 성능 측정을 할 수 없다 -> 라벨이 없기 때문에

지도 학습, 회귀 모델의 성능 측정은 어떻게 할수 있을까?

$R^2 = 1-\tfrac{오차^2}{편차^2}$

$= 1-\tfrac{\sum (예측값 - 실제값)^2}{\sum (실제값평균-실제값)^2}$

-> $R^2$ 가 가장 좋은 값은 1이다.

from sklearn.neighbors import KNeighborsRegressor
knr = KneighborsRegressor
# k-최근접 이웃 회귀 모델을 훈련
knr.fit(train_input, train_target)
knr.score(test_input, test_target)
-> 0.992809406101064
from sklearn.metrics import mean_absolute_error
# 테스트 세트에 대한 예측을 생성
test_prediction = knr.predict(test_input)
# 테스트 세트에 대한 평균 절댓값 오차를 계산
mae = mean_absolute_error(test_target, test_prediction)
print(mae)
-> 19.157142857142862


과대적합 vs 과소적합

  • 훈련 데이터에 과하게 적합되어 있을 때 : 과적합(overfitting)
  • 훈련 데이터 보다 테스트 데이터 의 점수가 높거나 두 점수가 모두 낮을때 : 과소적합(underfitting) https://heytech.tistory.com/125
print(knr.score(train_input, train_target)
-> 0.9698823289099254
# 이웃의 갯수를 3으로 설정, 기본값은 5
knr.n_neighbors = 3

# 모델을 다시 훈련
knr.fit(train_input, train_target)
print(knr.score(train_input, train_target))
-> 0.9804899950518966


print(knr.score(test_input, test_target))
-> 0.9746459963987609

# 이 데이터는 훈련 데이터에 과하게 적합되어 있다. -> 과적합(overfitting)


확인문제

# k-최근접 이웃 회귀 객체를 생성
knr = KneighborsRegressor()
# 5에서 45까지 x좌표를 생성
x = np.arrange(5, 45).reshape(-1, 1)

# n = 1, 5, 10일 때 예측 결과를 그래프로 그린다
for n in [1, 5, 10]:
    # 모델 훈련
    knr.n_neighbors = n
    knr.fit(train_input, train_target)
    # 지정한 범위 x에 대한 예측 구하기
    prediction = knr.predict(x)
    # 훈련 세트와 예측 결과 그래프 그리기
    plt.scatter(train_input, train_target)
    plt.plot(x, prediction)
    plt.title('n_neighbors = {}'.format(n))
    plt.xlabel('length')
    plt.ylabel('weight')
    plt.show() 

# 우리는 훈련에 사용한 개, 고양이 데이터를 잘 맞추는걸 필요로 하는게 아니다.
# 훈련하지 않았던 미지의 개, 미지의 고양이를 맞춰야한다.

# 과적합 -> 훈련 데이터에 과하게 직찹하는 것
# 훈련데이터에 너무 과적합 되어서는 안된다.

# 성능을 증가시키는 2가지 방법
# -> 훈련 데이터 양을 늘리거나 증강한다.
# -> 머신을 바보로 만든다. 훈련 데이터의 정답을 말하더라도 '일부러' 틀렸다고 한다.

관심있을 포스팅