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
머신러닝
- 인공지능은 어떠한 방법이든 수학적인 방법이 있어야한다.
- 모든 프로그램은 수학적인 방법이 기저가 된다.
- 데이터를 통해서 어떠한 것을 예측할 수 있는 통찰을 얻어내는것 -> 머신러닝
- 머신러닝은 딥러닝을 포함한다.
알고리즘과 모델
알고리즘 : 컴퓨터가 어떤일을 수행하는 명시적인 조건의 나열 모델 : 수학적인 기저가 있는 특정한 방법
알고리즘의 분류
수학적인 방법에 따라 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가지 방법
# -> 훈련 데이터 양을 늘리거나 증강한다.
# -> 머신을 바보로 만든다. 훈련 데이터의 정답을 말하더라도 '일부러' 틀렸다고 한다.