[회고] 신입 iOS 개발자가 되기까지 feat. 카카오 자세히보기

🛠 기타/Data & AI

단층 퍼셉트론 - 선택 분류 구현

inu 2020. 7. 30. 22:22
반응형

https://inuplace.tistory.com/460?category=912534

 

단층 퍼셉트론 - 회귀분석 구현

데이터를 기반으로 전복의 고리수를 예측하는 단층 퍼셉트론을 구현해보자. 주어진 데이터는 'Sex', 'Length', 'Diameter', 'Height', 'Whole weight', 'Shucked weight', 'Viscera weight', 'Shell weight', 그리..

inuplace.tistory.com

  • 이전에 작성한 코드 중 일부를 재활용한다.
  • 철판 데이터를 분석해 철판 상태를 7가지로 분류한다.
  • 수업에 사용된 코드를 분석한 자료입니다.

메인 함수 정의

def steel_exec(epoch_count=10, mb_size=10, report=1):
    load_steel_dataset()
    init_model()
    train_and_test(epoch_count, mb_size, report)
  • 기존과 크게 다를 것 없이, 데이터 불러오기 / 모델 초기화 / 학습 및 테스트의 과정을 따른다.

데이터 적재함수 정의

def load_steel_dataset():
    with open('faults.csv') as csvfile:
        csvreader = csv.reader(csvfile)
        next(csvreader, None)
        rows = []
        for row in csvreader:
            rows.append(row)

    global data, input_cnt, output_cnt
    input_cnt, output_cnt = 27, 7
    data = np.asarray(rows, dtype='float32')
  • faults.csv로부터 데이터를 가져오고 이를 data에 저장한다.
  • 특성이 27개이기 때문에 input_cnt는 27이고 철판의 상태가 7개이기 때문에 output_cnt는 7이다.

소프트맥스 관련 함수

def softmax(x):
    max_elem = np.max(x, axis=1)
    diff = (x.transpose() - max_elem).transpose()
    exp = np.exp(diff)
    sum_exp = np.sum(exp, axis=1)
    probs = (exp.transpose() / sum_exp).transpose()
    return probs
  • 주어진 로짓 벡터에 소프트맥스 함수를 적용해 확률 벡터를 도출해내는 함수이다.
  • x는 output이 될 것이다. (로짓값)
  • max함수로 각 행의 최대 로짓값을 구한다.
  • max_elem은 각 행의 최대 로짓값이 저장된 리스트 형태이기 때문에 주어진 형태에서 바로 최대값을 빼주는 것은 의미없고 (대부분) 불가능하다. 따라서 x의 전치행렬을 구해 값을 빼주고 다시 형태를 되돌리는 전략을 선택한다.
  • 그렇게 구한 행렬에 exp를 적용해서 $e^{logit}$ 을 만든다.
  • 그리고 공식에 따라 $y_i = {e^{x_i - x_k} \over e^{x_1 - x_k} + ... + e^{x_n - x_k}}$를 최종적으로 구하고 리턴한다.
def softmax_derv(x, y):
    mb_size, nom_size = x.shape
    derv = np.ndarray([mb_size, nom_size, nom_size])
    for n in range(mb_size):
        for i in range(nom_size):
            for j in range(nom_size):
                derv[n, i, j] = -y[n,i] * y[n,j]
            derv[n, i, i] += y[n,i]
    return derv
  • 소프트맥스 함수의 미분값이다. 경우를 나눠 맞는 값을 리턴하도록 한다.
def softmax_cross_entropy_with_logits(labels, logits):
    probs = softmax(logits)
    return -np.sum(labels * np.log(probs+1.0e-10), axis=1)
  • 로짓값과 정답 레이블을 기반으로 소프트맥스 교차 엔트로피값을 구한다.
  • 로짓 벡터를 확률 벡터로 바꾸고 교차엔트로피 공식에 대입한다.
def softmax_cross_entropy_with_logits_derv(labels, logits):
    return softmax(logits) - labels
  • 소프트맥스 교차 엔트로피의 편미분값인 $q_i - p_i$를 리턴한다.

순전파 관련 함수 재정의

def forward_postproc(output, y):
    entropy = softmax_cross_entropy_with_logits(y, output)
    loss = np.mean(entropy) 
    return loss, [y, output, entropy]
  • 순전파에서 y와 output(로짓대상)을 기반으로 소프트맥스 교차 엔트로피 값을 구한다.
  • 그를 기반으로 미니배치 전체에 대한 평균 손실을 구해 최종 손실함수값을 도출하고 리턴한다.
  • y와 output, entropy 모두 역전파과정에서 활용되어야 할 값이므로 리스트 형태로 리턴해준다,

역전파 관련 함수 재정의

def backprop_postproc(G_loss, aux):
    y, output, entropy = aux

    g_loss_entropy = 1.0 / np.prod(entropy.shape)
    g_entropy_output = softmax_cross_entropy_with_logits_derv(y, output)

    G_entropy = g_loss_entropy * G_loss
    G_output = g_entropy_output * G_entropy

    return G_output
  • forward_postproc에서 리턴받은 aux값을 기반으로 y, output, entropy값을 파악한다.
  • 그를 기반으로 부분 손실기울기를 구해 리턴한다. (해당 값은 실질적으로 역전파를 수행하는 backprop_neuralnet에 활용된다.)

정확도 함수 정의

def eval_accuracy(output, y):
    estimate = np.argmax(output, axis=1)
    answer = np.argmax(y, axis=1)
    correct = np.equal(estimate, answer)

    return np.mean(correct)
  • output에서 각 행의 최대값 (선택 항목)
  • y에서 각 행의 최대값 (정답 항목)
  • 둘의 위치를 비교하여 이 불립값을 활용해 정확도를 구하고 리턴한다.
반응형