[회고] 신입 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에서 각 행의 최대값 (정답 항목)
  • 둘의 위치를 비교하여 이 불립값을 활용해 정확도를 구하고 리턴한다.