생선이름을 자동으로 알려주는 머신러닝 만들기
->머신러닝은 스스로 기준을 찾아서 30~40CM인 길이의 생선은 도미라고 정의한다.
->어떻게 이런 기준을 찾니..? 여러개의 도미생선을 보면서 스스로 구분할 기준을 찾는다
혼공머신은 35마리의 도미를 준비했다.
#도미데이터
생선의 길이,무게
[ ] 안의 것들을 특성(데이터의 특징)이라 부른다.
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축인 산점도(sactter plot)으로 표시
산점도 : x, y축으로 이뤄진 좌표계에 두 변수(x,y)의 관계를 표현하는 방식
과학계산용 그래프를 그리는 패키지 -> matplotlib
import matplotlib.pyplot as plt
plt.scatter(bream_length, bream_weight)
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
도미 35마리를 2차원 그래프(2개의 특성을 사용)에 점으로 나타냈다.
생선의 길이가 길수록 무게가 많이 나간다고 생각.
이렇게 산점도 그래프가 일직선에 가까운 형태로 나타나는 경우를 선형적이라고 한다.
#빙어데이터
14마리 ,무게랑 크기 작다.
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()
matplotlibdms 2개의 산점도를 색깔로 구분해서 나타낸다.
빙어도 도미와 비슷하게 길이와 무게가 비례하지만 늘어나는 정도가 조금 다르다.
빙어도 선형적이지만 무게가 길이에 영향을 덜 받는다.
이제 이 두 데이터를 스스로 구분하기 위한 머신러닝 프로그램을 만들겠다.
#첫번째 머신러닝 프로그램
가장 간단하고 이해하기 쉬운 K-최근접 이웃 알고리즘 사용 -> KNN
도미+빙어 데이터
length = bream_length+smelt_length
weight = bream_weight+smelt_weight
두 리스트 합치면
length = { 도미 35개의 길이 + 빙어 14개의 길이} 이런식으로 합쳐진다.
scikit -learn 사이킷런 패키지 사용해서 머신러닝
이 패키지를 사용하려면 각 특성의 리스트를 세로방향으로 늘어뜨린 2차원 리스트를 만들어야 한다.
->파이썬의 zip() 함수와 리스트 내포 구문을 사용한다
zip() : 나열된 리스트 각각에서 하나씩 원소를 꺼내 반환한다.
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]]
"""
이렇게 출력된 리스트를 2차원 리스트라고 한다.
생선 49개의 길이와 무게를 모두 준비했다.
마지막으로 준비할 데이터는 정답데이터이다.
첫번째 생선은 도미이고 두번째 생선도 도미라는 식으로 각각 어떤 생선인지 답을 만드는 것이다.
왜이런 작업이 필요할까?
머신러닝 알고리즘이 생선의 길이와 무게를 보고 도미와 빙어를 구분하는 규칙을 찾기를 원하기 때문이다.
그렇게 하려면 적어도 어떤 생선이 도미인지 빙어인지를 알려주어야한다.
하지만 컴퓨터는 문자를 이해 못한다.
대신 도미와 빙어를 숫자 1과 0으로 표현한다.
첫번째 생선은 도미 - >1
마지막 생선은 빙어 -> 0
도미와 빙어를 순서대로 나열했기 때문에 정답 리스트는 1번이 35번 등장하고 0이 14번 등장하면 된다.
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]
"""
*보통 찾으려는 대상을 1로 놓고 그외는 0으로 놓는다.
도미를 찾고 싶어서 1로 놓을 것이다.
이제 scikit -learn 패키지에서 KNN 알고리즘을 구현한 클래스인 KNeighborsClassifier 임포트
from sklearn.neighbors import KNeighborsClassifier
임포트한 KNeighborsClassifier 클래스의 객체 만들기
kn = KNeighborsClassifier()
이 객체에 fish_data와 fish_target을 전달하여 도미를 찾기 위한 기준을 학습시킨다.
이런 과정을 머신러닝에서는 훈련이라고 부른다. -> 모델에 데이터를 전달하여 규칙을 학습하는 과정
사이킷런에서는 fit() 메서드가 이런 역할을 한다.
이 메서드에 fish_data와 fish_target을 순서대로 전달해보겠다.
kn.fit(fish_data, fish_target)
이제 객체 kn이 얼마나 잘 훈련되었는지 평가한다.
사이킷런에서 모델을 평가하는 메서드는 score() 메서드이다.
이 메서드는 0과 1 사이의 값을 반환한다.
1은 데이터를 정확히 맞췄다는 것. 0.5는 절반만 맞췄다는 것이다.
kn.score(fish_data, fish_target)
#1.0
모든 fish_data의 값을 정확히 맞췄다! -> 이 값을 정확도 라고 한다.
#KNN 알고리즘
어떤 데이터에 대한 답을 구할 때 주위의 다른 데이터를 보고 다수를 차지하는 것을 정답으로 사용한다.
예를 들어 다음 그림에 삼각형으로 표시된 새로운 데이터가 있다고 가정한다.
이 삼각형은 도미와 빙어 중 어디에 속할까?
plt.scatter(bream_length, bream_weight)
plt.scatter(smelt_length, smelt_weight)
plt.scatter(30, 600, marker='^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
아마도.. 도미라고 판단할 것이다........
KNN 알고리즘도 그렇다! 도미라고 판단할거다.
kn.predict([[30, 600]])
#array([1])
predict() 메서드는 새로운 데이터의 정답을 예측한다.
fit() 메서드와 마찬가지로 리스트의 리스트를 전달해야 한다.
1이 출력되었기 때문에 도미이다.
단점 : 데이터가 아주 많은 경우에는 사용하기 어렵다. 메모리가 많이 필요하고 직선거리를 계산하는데도 많은 시간이
필요하기 때문이다.
사이킷런의 KNeighborsClassifier 클래스도 마찬가지이다.
fish_data속성 가짐
print(kn._fit_X)
"""
[[ 25.4 242. ]
[ 26.3 290. ]
[ 26.5 340. ]
[ 29. 363. ]
[ 29. 430. ]
......]
"""
fish_target 가짐
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]
"""
실제로 KNN 알고리즘은 무언가 훈련되는게 없는 셈이다.
fit() 메서드에 전달한 데이터를 모두 저장하고 있다가 새로운 데이터가 등장하면 가장 가까운 데이터를 참고하여
도미인지 빙어인지 구분한다.
그럼 가까운 몇개의 데이터를 참고 할까 ? 정하기 나름이다...
KNeighborsClassifier의 기본값은 5이다. 바꿀 수 있다.
kn49 = KNeighborsClassifier(n_neighbors=49) #참고 데이터 49개로 한 kn49모델
가장 가까운 데이터 49개를 사용하는 KNN 모델에 fish_data를 적용하면
fish_data에 있는 모든 생선을 사용하여 예측하게 된다.
다시 말하면 fish_data의 데이터 49개 중에 도미가 35개로 다수를 차지하므로 어떤 데이터를 넣어도
무조건 도미로 예측할 것이다.
kn49.fit(fish_data, fish_target)
kn49.score(fish_data, fish_target)
#0.7142857142857143
fish_data에 있는 생선중 도미가 35개고 빙어가 14개이다.
kn49모델은 도미만 올바르게 맞추기 때문에 정확도를 계산하면 score() 메서드와 같은 값을 얻을 수 있다.
print(35/49)
#0.7142857142857143
49로 두는건 좋지않다. 기본값을 5로하여 도미를 완벽하게 분류한 모델을 사용할 거다..
#도미와 빙어 분류
첫번째 머신러닝 프로그램
도미, 빙어 구분하기 위해 만들었다.
1. 도미 35마리 빙어 14마리 길이와 무게 측정해 파이썬 리스트로 만들었다.
2. 도미와 빙어 데이터를 합쳐 리스트의 리스트로 데이터 준비
3. 사이킷런의 KNN알고리즘 사용 -> 주변에서 가장 가까운 5개의 데이터를 보고 다수결의 원칙으로 데이터 예측
4. KNeighborsClassifier 클래스의
fit() : 사이킷런 모델을 훈련할 때 사용,
predict() : 사이킷런 모델을 훈련하고 예측할때 사용,
score() : 훈련된 사이킷런 모델의 성능 측정, 먼저 predict()로 예측한 다음 사용
메서드를 사용했다.
'PYTHON > 데이터분석' 카테고리의 다른 글
2-2 데이터 전처리 (0) | 2023.09.15 |
---|---|
2-1 훈련세트와 테스트 세트 (0) | 2023.09.15 |
통계 데이터 분석 -KNN회귀 (0) | 2023.09.15 |
통계 데이터 분석 -확률 (0) | 2023.09.15 |
통계 데이터 분석 -선형회귀 (0) | 2023.09.15 |