전공정리/알고리즘

[알고리즘] 기계학습

HU_717 2023. 2. 3. 16:32

인공지능

  • 사람이 해야할 일을 기계가 대신할 수 있는 모든 자동화에 해당

머신러닝

  • 명시적으로 규칙을 프로그래밍하지 않고 데이터로부터 의사결정을 위한 패턴을 기계가 스스로 학습

딥러닝

  • 입공신경망 기반의 모델로, 비정형 데이터로부터 특징 추출 및 판단까지 기계가 한 번에 수행

기계학습

  • 지도 학습
    • 문제와 정답을 모두 알려주고 학습
  • 비지도 학습
    • 답을 가르쳐주지 않고 학습
  • 강화 학습
    • 보상을 통해 상은 최대화, 벌은 최소화하는 방향으로 학습

기계학습 알고리즘 예시

  • 회귀 분석 : 예측
    • 입력 데이터들의 특징을 기준으로 연속된 값 예측
    • 어떤 패턴, 경향성 예측
    • 특이 값 분석, 관리 중요
    • 선형 회귀, 비선형 회귀
    • 로지스틱 회귀 : 0,1 분류
  • 분류
    • 입력 데이터를 두개 이상의 "정해진 결과"로 예측
    • 데이터의 특성에 따른 범주를 구분하여 경계를 나누는 방식으로 학습
    • 대표 알고리즘
      • KNN, SVM
        • 이미지/문자 분류, 스팸 분류
  • 군집화
    • 정답없이 학습
    • 비슷한 특징을 지닌 데이터들 간의 그룹화
    • 대표 알고리즘
      • K-means
    • 과일의 등급, 제품 사이즈
지도 학습: 선형 회귀
  • 종속 변수 y와 한 개 이상의 독립 변수 x와의 선형 상관 관계를 모델링하는 기법
    1) 데이터 주어짐
    2) 가설 세우기 H(W,b) = Wx + b
    3) 오차가 최소 되도록 , 평균 제곱 오차 구하기4) 파라미터 최적화 W, b
    5) 예측에 이용
  • 1) 오차가 최소 되도록 파라미터 최적화 - 비용 함수 도입 - 비용 줄이기
  • 수학적 접근 방법 - 단순 성형 회귀
  • 알고리즘
    • Exhaustive, Random
    • Gradient Descent
      • 비용함수의 형태를 이용함
      • W, b를 각각 구하여 반복적으로 업데이트

< Linear Regression with GD >

import matplotlib.pyplt as plt
import numpy as np
import pandas as pd

x = [1,3,5,7,9]
y = [3,7,11,15,19]

x_data = np.array(x) #넘파이 배열로 변환
y_data = np.array(y)

w = 3 #기울기 w 초기화
b = 5 #y절편 b 초기화

lr = 0.005 # 학습률 설정 (learning rate)

epochs = 3000 # 반복 횟수 ㅓㅅㄹ정

fig = plt.figure()

# 경사 하강법 시작
for i in range(epochs):
    y_pred = w * x_data + b # y 예측 값을 구하는 식
    error = y_date - y_pred # 오차 error = y 값 - y 예측 값

    w_diff = -(1 / len(x_data)) * sum(x_data * (error)) # 평균 제곱 오차를 w로 미분한 값
    b_diff = -(1 / len(x_data)) * sum(y_data - y_pred) # 평균 제곱 오차를 b로 미분한 값

    w = w - lr * w_diff # 학습률 * 미분 결과 후 기존 w 값 업데이트
    b = b - lr * b_diff # 학습률 * 미분 결과 후 기존 b 값 업데이트

    if i % 200 == 0:
        print("epoch = %.f, 기울기 = %.04f, 절편 %.04f, 에러 = %.04f" % (i,w,b,error.mean()))    
        plt.scatter(x,y) # 이하 그래프 출력
        ax = fig.add_subplot(111)
        ax.plot([min(x_data), max(x_data)], [min(y_pred), max(y_pred)])
지도 학습: kNN
  • k-NN
    • 새로운 데이터를 분류할 때, 인접 k개의 데이터 분류 결과를 활용
      -> k개 중 가장 많은 분류 결과를 새로운 데이터로 분류
      • k값이 짝수일 경우 동률 발생 가능
        -> 일반적으로 k는 홀수 사용
      • 상황에 따른 k값 최적화가 필요
      • 거리 계산
        • 새로운 데이터와 인접 데이터 간 거리
class KNN:
    def __init__(self, k):
        self.k = k

    def fit(self, X, y):
        self.X_train = X
        self.y_train = y

    def distance(self, X1, X2):
        distance = scipy.spatial.distance.euclidean(X1, X2)

    def predict(self, X_test):
        final_output = []
        for i in range(len(x_test)):
            d = []
            votes = []
            for j in range(len(x_train)):
                dist = scipy.spatial.distance.euclidean(x_train[j] , x_test[i])
                d.append([dist, j])
            d.sort()
            d = d[0:self.k]
            for d, j in d:
                votes.append(y_train[j])
            ans = Counter(votes).most_common(1)[0][0]
            final_output.append(ans)

        return final_output

    def score(self, X_test, y_test):
        predictions = self.predict(x_test)
        return (predictions == y_test).sum() / len(y_test)
비지도학습: k-means
  • k-means
    • 주어진 데이터를 k개의 집합으로 구분하는 군집화 알고리즘
      1) 주어진 데이터 중 k개의 데이터를 임의로 선택
      -> 각 군집의 중심으로 설정
      2) 데이터를 군집의 중심과 가장 가까운 군집으로 할당
      3) 군집에 속한 데이터의 평균 값을 통해 중심 업데이트(재조정)
      4) 모든 데이터를 분류할 때까지 2),3) 반복
class K_Means:
    def __init__(self, k=3, tol=0.001, max_iter=300):
        self.k = k
        self.tol = tol
        self.max_iter = max_iter

    def fit(self,data):

        self.centroids = {}

        for i in range(self.k):
            self.centroids[i] = data[i]

        for i in range(self.max_iter):
            self.classifications = {}

            for i in range(self.k):
                self.classifications[i] = []

            for featureset in data:
                distances = [np.linalg.norm(featureset-self.centroids[centroid]) for centroid in self.centroids]
                classification = distances.index(min(distances))
                self.classifications[classification].append(featureset)

            prev_centroids = dict(self.centroids)

            for classification in self.classifications:
                self.centroids[classification] = np.average(self.classifications[classification],axis=0)

            optimized = True

            for c in self.centroids:
                original_centroid = prev_centroids[c]
                current_centroid = self.centroids[c]
                if np.sum((current_centroid-original_centroid)/original_centroid*100.0) > self.tol:
                    print(np.sum((current_centroid-original_centroid)/original_centroid*100.0))
                    optimized = False

            if optimized:
                break

    def predict(self,data):
        distances = [np.linalg.norm(data-self.centroids[centroid]) for centroid in self.centroids]
        classification = distances.index(min(distances))
        return classification