Deep learning with abalone
Updated:
import numpy as np
import csv
import time
import os
RND_MEAN = 0
RND_STD = 0.0030
LEARNING_RATE = 0.001
메인함수
def abalone_exec(epoch_count = 10, mb_size = 100, report = 1):
print(epoch_count,mb_size,report)
load_abalone_dataset()
# 데이터을 읽어오고 가공
init_model()
# 가중치와 편향을 초기화
train_and_test(epoch_count, mb_size, report)
# 훈련과 테스트
데이터 적재 및 가공
def load_abalone_dataset():
os.chdir(r"C:\Users\user\limjun92.github.io\data\인공지능사관학교\deep")
with open('abalone.csv') as csvfile:
csvreader = csv.reader(csvfile)
next(csvreader,None) # 가장 처음 행을 제거해 준다
rows = []
#print(type(csvreader))
#print(type(rows))
for row in csvreader:
rows.append(row)
# _csv.reader을 list로 변환
global data, input_cnt, output_cnt
# 전역 변수는 미리 선언하고 사용
input_cnt, output_cnt = 10,1
data = np.zeros([len(rows),input_cnt+output_cnt])
#print(len(rows))
#행렬을 만들고 0을 입력
# print(data)
for n, row in enumerate(rows):
if row[0] == 'I': data[n,0] = 1
if row[0] == 'M': data[n,1] = 1
if row[0] == 'F': data[n,2] = 1
# one_hot 0,1,2 를 원-핫 벡터를 사용해구현한다
data[n,3:] = row[1:]
# 나머지 데이터는 바로 뒤에 붙여준다
#print(data)
파라미터 초기화 함수 정의
def init_model():
global weight, bias, input_cnt, output_cnt
weight = np.random.normal(RND_MEAN, RND_STD,[input_cnt, output_cnt])
# 평균이 0이고 표준편차 0.003 인 랜덤값을 weight로 만들어준다
#print(weight)
bias = np.zeros([output_cnt])
# 편향?
#print(bias)
학습 및 평가 함수 정의
def train_and_test(epoch_count, mb_size, report):
step_count = arrange_data(mb_size)
# 전복의 데이터 수는 4177개
# 80%의 데이터를 훈련으로 사용함
# mb_size가100일떄 step_count는 33이다
test_x, test_y = get_test_data()
# test를 위해 사용하는 data
# test_x는 전복의 정보
# test_y는 전복의 고리수
# train_data와 test_data가 고정된다
for epoch in range(epoch_count):
#epoch_count = 100
losses, accs = [],[]
for n in range(step_count):
#step_count = 33
train_x, train_y = get_train_data(mb_size,n)
# n이 0일때 get_train_data에서 섞어주기 때문에 epoch가 증가 할때마다 매번 다른값을 가져온다
# 3300개의 데이터를 100개씩 쪼개서 33번 가져온다
loss, acc = run_train(train_x, train_y)
#losses.append(loss)
#accs.append(acc)
losses.append(loss)
#오차제곱의 평균을 입력
accs.append(acc)
#정확도 입력
if report > 0 and (epoch+1) % report == 0:
acc = run_test(test_x, test_y)
print('Epoch {}: loss={:5.3f}, accuracy={:5.3f}/{:5.3f}'. \
format(epoch+1, np.mean(losses), np.mean(accs), acc))
final_acc = run_test(test_x, test_y)
print('\nFinal Test: final accuracy = {:5.3f}'.format(final_acc))
train_data와 test_data를 분할
def arrange_data(mb_size):
global data, shuffle_map, test_begin_idx
shuffle_map = np.arange(data.shape[0])
# data.shape[0]을 통해 행의 수를 알수 있다
# data.shape[1]을 통해 열의 수를 알수 있다
# np.arange(N) 는 N수만큼 array형태로 반환해주는 함수이다
#print(shuffle_map)
np.random.shuffle(shuffle_map)
# shuffle_map을 random으로 섞어준다
#print(shuffle_map)
step_count = int(data.shape[0] * 0.8) // mb_size
# 80%의 데이터를 훈련으로 사용
#print(step_count) = 33
test_begin_idx = step_count*mb_size
# 4176의 자료 중에서 test를 시작하는 idx(3300부터 시작)
#print(test_begin_idx)
return step_count
test를 위해 사용하는 data 정의
def get_test_data():
global data, shuffle_map, test_begin_idx, output_cnt
test_data = data[shuffle_map[test_begin_idx:]]
# 섞여있는 shuffle_map의 test_begin_idx(3300)부터 끝까지 shuffle_map의 값을
# index로 가지고 있는 data를 가져온다
#print(test_data)
#print(test_data[:, :-output_cnt])
# 전복의 정보
#print(test_data[:, -output_cnt:])
# 전복의 고리수
return test_data[:, :-output_cnt], test_data[:, -output_cnt:]
train를 위해 사용하는 data 정의
def get_train_data(mb_size, nth):
global data, shuffle_map, test_begin_idx, output_cnt
if nth == 0:
#print(shuffle_map[:test_begin_idx])
np.random.shuffle(shuffle_map[:test_begin_idx])
#print(shuffle_map[:test_begin_idx])
# 각 epoch를 시작할때마다 train_data를 섞어준다
train_data = data[shuffle_map[mb_size*nth:mb_size*(nth+1)]]
# mb_size(100) 만큼 return해준다
return train_data[:,:-output_cnt], train_data[:,-output_cnt:]
train 알고리즘
def run_train(x, y):
# x는 data, y는 그에 대한 이미 알고 있는 결과
output, aux_nn = forword_neuralnet(x)
# 가중치와 편향을 적용
loss, aux_pp = forward_postproc(output, y)
# 오차 제곱의 평균과 오차행렬
accuracy = eval_accuracy(output, y)
# print(accuracy)
# G_loss = 1.0
# G_output = backprop_postproc(G_loss, aux_pp)
# backprop_neuralnet(G_output, aux_nn)
G_loss = 1.0
G_output = backprop_postproc(G_loss,aux_pp)
backprop_neuralnet(G_output, aux_nn)
return loss, accuracy
순전파
def forward_neuralnet(x):
# x는 훈련을 위한 데이터
global weight, bias
output = np.matmul(x,weight) + bias
# matmul은 2차원에서 dot과 동일하나 3차원이상에서는 다른 결과를 보인다
# dot은 내적곱인 반면 matmul은 두 배열의 행렬곱이다
# 가중치를 곱한후 편향을 더해준다
#print(weight.shape[0],weight.shape[1])
#print(x.shape[0], x.shape[1])
return output, x
오차구하기
def forward_postproc(output, y):
# output은 neuralnet 결과
# y는 실제 결과값
#print(type(output),output.shape[0],output.shape[1])
#print(type(y),y.shape[0],y.shape[1])
diff = output - y
# 계산된 결과값과 실제 결과값의 차를 구한다
square = np.square(diff)
# 계산된 결과값과 실제 결과값의 차를 제곱한다
loss = np.mean(square)
# 계산된 결과값과 실제 결과값의 차를 제곱하고 평균을 구한다
return loss,diff
# loss는 오차 제곱의 평균
# diff는 오차 행렬
정확도
def eval_accuracy(output, y):
#print(output[0])
#print(y[0])
midff = np.mean(np.abs((output-y)/y))
return 1-midff
가중치 와 편향에 변화를 주기위한 인자 구하기
def backprop_postproc(G_loss, diff):
#======================print(diff[0:5])
# diff 는 실제 결과값과 출력 결과값의 오차를 행렬로 저장한것
shape = diff.shape
#print(shape)
#print(type(shape))
g_loss_square = np.ones(shape) / np.prod(shape)
#print(np.prod(shape))
#print(np.ones(shape))
#print(type(shape))
#print(type(np.ones(shape)))
#np.prod(N) N배열안의 모든 값을 곱한다
#np.ones(shape) shape크기의 행렬을 만들고 모든값을 1로 초기화 한다
#print((g_loss_square.shape))
#np.prod(shape) = 100 일경우 g_loss_square는 모든값이 0.01인 (100,1) 행렬
g_square_diff = 2 * diff
# diff값을 2배해서 g_square_diff에 입력
g_diff_output = 1
G_square = g_loss_square * G_loss
#print(G_square)
#모든값이 0.01로 초기화된 행렬 * G_loss
G_diff = g_square_diff * G_square
#오차 행렬의 두배 * G_square
G_output = g_diff_output * G_diff
#g_diff_output(초기화 1) * G_diff
#========================print(G_output[0:5])
return G_output
# 함수에서 diff를 입력으로 받아서 G_output으로 변환한후 return
# 값이 작아졌다
가중치 와 편향에 변화 주기
def backprop_neuralnet(G_output, x):
#x = data
global weight, bias
#print(x.shape)
g_output_w = x.transpose()
# transpose 전치행렬을 만든다, x의 행과 열을 바꾸어 g_output_w에 저장한다.
#print(g_output_w.shape)
G_w = np.matmul(g_output_w, G_output)
#print(weight)
#print(G_w)
G_b = np.sum(G_output,axis = 0)
#print(G_b)
#print(weight)
weight -= LEARNING_RATE * G_w
# 가중치 조정
#print(weight)
#print(bias)
bias -= LEARNING_RATE * G_b
# 편향 조정
#print(bias)
test 구현
def run_test(x, y):
output, _ = forward_neuralnet(x)
accuracy = eval_accuracy(output, y)
return accuracy
출력
abalone_exec()
10 100 1
Epoch 1: loss=11.023, accuracy=0.780/0.799
Epoch 2: loss=6.874, accuracy=0.812/0.795
Epoch 3: loss=6.729, accuracy=0.811/0.809
Epoch 4: loss=6.588, accuracy=0.813/0.806
Epoch 5: loss=6.525, accuracy=0.813/0.809
Epoch 6: loss=6.438, accuracy=0.815/0.798
Epoch 7: loss=6.367, accuracy=0.815/0.816
Epoch 8: loss=6.293, accuracy=0.817/0.814
Epoch 9: loss=6.223, accuracy=0.819/0.801
Epoch 10: loss=6.170, accuracy=0.819/0.809
Final Test: final accuracy = 0.809
가중치와 편향의 변화 값
print(weight)
print(bias)
[[ 0.39626569]
[ 1.39064843]
[ 1.26638338]
[ 4.32336958]
[ 5.18607575]
[ 4.5062529 ]
[ 5.03768753]
[-16.05903141]
[ -2.49417499]
[ 12.0969977 ]]
[3.04648438]
하이퍼퍼라미터 수정하며 실험
- LEARNING_RATE = 0.001 -> 0.1
- epoch_count = 10 -> 100
- mb_size = 10 -> 100
LEARNING_RATE = 0.1
abalone_exec(epoch_count=100,mb_size=100,report=20)
100 100 20
Epoch 20: loss=5.905, accuracy=0.824/0.834
Epoch 40: loss=5.378, accuracy=0.831/0.841
Epoch 60: loss=5.189, accuracy=0.835/0.838
Epoch 80: loss=5.119, accuracy=0.837/0.841
Epoch 100: loss=5.082, accuracy=0.837/0.843
Final Test: final accuracy = 0.843
새로운 입력 벡터 X에 대한 예측
x = np.array([0,1,0,0.44,0.3,0.08,0.5,0.23,0.11,0.2])
output = forward_neuralnet(x)
print(output)
(array([9.22604521]), array([0. , 1. , 0. , 0.44, 0.3 , 0.08, 0.5 , 0.23, 0.11, 0.2 ]))
Leave a comment