[50일차] 나의 첫 머신러닝 & 데이터 다루기
1. 인공지능과 머신러닝, 딥러닝
2. 코랩과 주피터 노트북
3. 마켓과 머신러닝
4. 훈련 세트와 테스트 세트
5. 데이터 전처리
1. 인공지능과 머신러닝, 딥러닝
1. 인공지능
: 사람처럼 학습하고 추론할 수 있는 지능을 가진 컴퓨터 시스템을 만드는 기술
📌퍼셉트론 : 로지스틱 회귀의 초기 버전
2. 머신러닝
- 규칙을 일일이 프로그래밍하지 않아도 자동으로 데이터에서 규칙을 학습하는 알고리즘 연구
➡ 스스로 규칙을 찾음
📌사이킷런 ➡ 파이썬 API를 사용하는데 파이썬 언어는 배우기 쉽고 컴파일하지 않아도 되기 때문에 사용하기 편리
3. 딥러닝
: 머신러닝 알고리즘 중 인공 신경망을 기반으로 한 방법들을 통칭
📌AlexNet : 이미지 분류하는 모델
📌텐서플로 : 구글의 딥러닝 라이브러리
2. 코랩과 주피터 노트북
1. 구글 코랩
: 웹 브라우저에서 무료로 파이썬 프로그램을 테스트하고 저장할 수 있는 프로그램
2. 노트북
- 코랩의 프로그램 작성 단위
- 대화식으로 프로그램을 만들 수 있음 ➡ 데이터 분석이나 교육에 적합
- 코드, 코드의 실행 결과, 문서 모두 저장하여 보관 가능
- 구글 클라우드의 가상 서버는 최대 5개
3. 구글 드라이브
- 구글이 제공하는 클라우드 파일 저장 서비스
3. 마켓과 머신러닝
🧐 가정 : 생선 분류
➡ 생선 이름을 자동으로 알려주는 머신러닝 만들기😎
0. 데이터 준비
💻 도미 데이터 준비 후 산점도로 나타내기
#도미 데이터
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.title('bream')
plt.show()
📌 특성 : 데이터의 특징 ex) 도미의 특징 ➡ 길이, 무게
💻 빙어 데이터 준비 후 산점도로 나타내기
# 빙어 데이터
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] # 방어 무게 리스트
# 도미 데이터와 빙어 데이터 시각화
import matplotlib.pyplot as plt
plt.scatter(bream_length, bream_weight, color='green')
plt.scatter(smelt_length, smelt_weight, color='skyblue')
plt.xlabel('length')
plt.ylabel('weight')
plt.title('bream & smelt')
plt.show()
1. 첫 번째 머신러닝 프로그램 : k-최근접 이웃 알고리즘
💻 데이터 하나로 묶기
length = bream_length + smelt_length
weight = bream_weight + smelt_weight
📍 KNeighborsClassifier : 가장 가까운 이웃을 참고하여 정답을 예측하는 알고리즘이 구현된 사이킷런 클래스
💻 사이킷런을 사용하려면 필요한 2차원 리스트 생성
fish_data = [[l,w] for l,w in zip(length,weight)]
💻 도미는 1, 빙어는 0 ➡ 생선 리스트 생성
fish_target = [1] * 35 + [0] * 14
# 35개의 도미 데이터와 14개의 빙어 데이터를 가지고 있음
💻 사이킷런 패키지 임포트 후 코드 작성
📌 데이터분석은 객체 만들기 ➡ 훈련 ➡ 평가 ➡ 예측 순으로 이루어짐
from sklearn.neighbors import KNeighborsClassifier
# 1) 객체 만들기
kn = KNeighborsClassifier()
# 2) 훈련 fit
kn.fit(fish_data, fish_target)
# 3) 평가 score
kn.score(fish_data, fish_target)
>>> 1.0 # 정확도 산출
# 4) 예측 predict
kn.predict([[30, 600]])
>>> array([1])
📌훈련 : 머신러닝 알고리즘이 데이터에서 규칙을 찾는 과정
📌정확도 : 정확한 답을 몇 개 맞혔는지를 백분율로 나타낸 값, 사이킷런에서는 0~1사이의 값으로 출력
📍 _fit_X : fit에 속한 X값
._y : fit에 속한 Y값
📌n_neighbors 매개변수 가까운 몇 개의 데이터를 참고하는지 알 수 있음, 기본값은 5
kn49 = KNeighborsClassifier(n_neighbors=49) # 참고 데이터를 49개로 한 kn49 모델
kn49.fit(fish_data, fish_target)
kn49.score(fish_data, fish_target)
>>> 0.7142857142857143
print(35 /49)
>>> 0.7142857142857143
4. 훈련세트와 테스트 세트
1. 지도학습과 비지도 학습
- 지도 학습
- 입력(데이터)과 타깃(정답)으로 이뤄진 훈련 데이터가 필요
- 정답 맞히는 것을 학습하는 알고리즘
- 비지도 학습
- 타깃 없이 입력 데이터만 사용
- 정답을 사용하지 않음
- 강화 학습
- 보상 사용
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]
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()
💻 훈련 세트와 테스트 세트 생성
train_input = fish_data[:35]
train_target = fish_target[:35]
test_input = fish_data[35:]
test_target = fish_target[35:]
🔎 훈련 세트로는 입력값 중 0부터 34번째 인덱스까지 사용, 테스트 세트로는 35번째부터의 인덱스부터 사용
💻 훈련 후 평가
kn.fit(train_input, train_target)
kn.score(test_input,test_target)
>>> 0.0
🔎 35번째까지의 인덱스는 도미만 가지고 있다. 이 훈련 데이터로 훈련을 한 채로, 빙어만 있는 테스트 데이터를 평가하니 0이 뜬 것!
3. 샘플링 편향
: 훈련 세트와 테스트 세트에 샘플이 골고루 섞여 있지 않아, 샘플링이 한쪽으로 치우친 상태
4. 넘파이
: 파이썬의 대표적인 배열 라이브러리
💻 넘파이 라이브러리 임포트
import numpy as np
💻 파이썬 리스트를 넘파이 배열로 바꾸기
input_arr = np.array(fish_data)
target_arr = np.array(fish_target)
📍 shape 속성 : 샘플 수, 특성 수 파악
input_arr.shape
>>> (49, 2)
💻 랜덤 시드 42에 인덱스 번호 생성 후 섞기
np.random.seed(42)
index = np.arange(49)
np.random.shuffle(index)
index
>>> array([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])
💻 랜덤하게 35개의 샘플 훈련 세트와, 14개의 테스트 세트 생성
train_input = input_arr[index[:35]]
train_target = target_arr[index[:35]]
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()
5. 두 번째 머신러닝 프로그램
📌 fit 메서드 특징 : fit 메서드 실행할 때마다 KNeighborsClassifier 클래스의 객체는 이전에 학습한 모든 것을 잃어버림
💻 훈련 후 평가
kn.fit(train_input, train_target
kn.score(test_input, test_target)
>>> 1.0
💻 predict() 메서드로 테스트 세트의 예측 결과와 실제 타깃 확인
kn.predict(test_input)
>>> array([0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0])
test_target
>>> array([0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0])
5. 데이터 전처리
1. 넘파이로 데이터 준비하기
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
📍 column_stack() : 함수로 전달받은 리스트를 일렬로 세운 다음 차례대로 나란히 연결
fish_data=np.column_stack((fish_length, fish_weight))
fish_data[:5]
>>> array([[ 25.4, 242. ],
[ 26.3, 290. ],
[ 26.5, 340. ],
[ 29. , 363. ],
[ 29. , 430. ]])
📍 np.ones() & np.zeros() : 각각 원하는 개수의 1과 0을 채운 배열
fish_target = np.concatenate((np.ones(35), np.zeros(14)))
fish_target
>>> array([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.])
2. 사이킷런으로 훈련 세트와 테스트 세트 나누기
📍 train_test_split() 함수 : 전달되는 리스트나 배열을 섞은 후, 비율에 맞게 훈련 세트와 테스트 세트로 나누어 줌
💻 train_test_split() 함수 임포트 후 훈련 세트와 테스트 세트 나누기
from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = train_test_split(fish_data, fish_target, random_state=42)
test_target
>>> array([1., 0., 0., 0., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
🔎 1과 0의 비율이 치우쳐져 있음
📍 stratify 매개변수 : 타깃 데이터를 매개변수에 전달하면 클래스 비율에 맞게 데이터 나눔
train_input, test_input,train_target, test_target = train_test_split(fish_data, fish_target, stratify=fish_target, random_state=42)
test_target
>>> array([0., 0., 1., 0., 1., 0., 1., 1., 1., 1., 1., 1., 1.])
3. 수상한 도미 한 마리
💻 훈련 데이터로 모델 훈련 후 테스트 데이터로 모델 평가
from sklearn.neighbors import KNeighborsClassifier
kn = KNeighborsClassifier()
kn.fit(train_input, train_target)
kn.score(test_input, test_target)
>>> 1.0
💻 25,150의 도미 데이터 넣고 결과 예측
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()
🔎 도미 데이터와 가까운데 왜 빙어로..?
📍 kneighbors() 메서드 : 주어진 샘플에서 가장 가까운 이웃을 찾아 줌, 이웃까지의 거리와 이웃 샘플의 인덱스 반환
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()
🔎 5개의 샘플 중 4개는 빙어, 1개는 도미
💻 샘플 데이터 확인
train_input[indexes]
>>> array([[[ 25.4, 242. ],
[ 15. , 19.9],
[ 14.3, 19.7],
[ 13. , 12.2],
[ 12.2, 12.2]]])
train_target[indexes]
>>> array([[1., 0., 0., 0., 0.]])
💻 이웃 샘플까지의 거리
print(distances)
>>> [[ 92.00086956 130.48375378 130.73859415 138.32150953 138.39320793]]
4. 기준을 맞춰라
📌 스케일 : 특성의 범위
🔎 x축과 y축의 범위가 다른 기존 산점도
💻 x축과 y축의 범위를 동일하게 하여 관찰
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()
📌 데이터 전처리 : 특성값을 일정한 기준으로 맞춰 주는 것
📌 표준점수 : 각 데이터가 원점에서 몇 표준편차만큼 떨어져 있는지 나타내는 값
📌 표준편차 : 분산의 제곱근으로 데이터가 분산된 정도
💻 평균과 표준편차 구하기
mean = np.mean(train_input, axis=0) #axis=0 세로
std = np.std(train_input, axis=0) #axis=0 세로
mean
>>> array([ 27.29722222, 454.09722222])
std
>>> array([ 9.98244253, 323.29893931])
💻 표준점수로 변환 = (원본 데이터 - 평균)/표준편차
train_scaled = (train_input - mean) / std
📌 브로드캐스팅 : 크기가 다른 넘파이 배열에서 자동으로 사칙 연산을 모든 행이나 열로 확장하여 수행하는 기능
5. 전처리 데이터로 모델 훈련하기
💻 변환한 표준점수로 산점도
plt.scatter(train_scaled[:,0], train_scaled[:,1])
plt.scatter(25, 150, marker='^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
🔎 테스트 샘플은 표준점수로 변환을 안했군..!
💻 테스트 샘플을 변환하고 산점도
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()
💻 데이터셋으로 k-최근접 이웃 모델 훈련 후 평가
kn.fit(train_scaled, train_target)
test_scaled = (test_input - mean) / std
kn.score(test_scaled, test_target)
>>> 1.0
💻 예측
kn.predict([new])
>>> array([1.])
💻 k-최근접 이웃 구한 후 산점도 그리기
distances, indexes = kn.kneighbors([new])
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()