데이터 엔지니어링 과정/python

[50일차] 나의 첫 머신러닝 & 데이터 다루기

오리는짹짹 2023. 3. 6. 19:27
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()