이번에는 Mnist 데이터들을 활용해서 직접 0,1,2를 구분하는 인공지능을 만들어보았다.
이를 확장해서 구현한다면 0~9까지 구분하는 인공지능을 라이브러리 없이 직접 만들어보는 것이 가능할 것이다.
이전 신경망까지 잘 따라왔다면 오히려 쉽다! 입력 후보군 5개와 0,1,2로 된 출력 후보군 3개를 넣어주기만 하면 된다.
먼저 흐름도를 통해 전체적인 흐름을 파악해보자.
우선 일반적인 Minist 를 받아오는것이 아닌 기존에 했던것처럼 엑셀형식으로 가공된 파일이 있다. 이들을 활용해서 구현할 것이다.
출력은 0,1,2로 나오기 때문에 ONE-HOT-ENCODIG을 거친다면 100, 010, 001 3가지의 출력 후보군이 나올것이다. 그렇다면 입력 후보군들은 어떻게 선택해야 할까?
(1) 가로축 Projection => 확률밀도함수로 변환 => 기댓값
(2) 가로축 Projection => 확률밀도함수로 변환 => 분산
(3) 세로축 Projection => 확률밀도함수로 변환 => 기댓값
(4) 세로축 Projection => 확률밀도함수로 변환 => 분산
(5) Diagonal* 원소 배열 추출 => 밀도함수로 변환 => 기댓값
* Diagonal: 좌측 상단에서 우측 하단으로 내려오는 대각선
(6) Diagonal 원소 배열 추출 => 확률밀도함수로 변환 => 분산
(7) Diagonal 원소 배열 추출 => 0의 개수
(8) Anti-Diagonal** 원소 배열 추출 => 밀도함수로 변환 => 기댓값
** Anti_Diagonal: 우측 상단에서 좌측 하단으로 내려오는 대각선
(9) Anti-Diagonal 원소 배열 추출 => 확률밀도함수로 변환 => 분산
(10) Anti-Diagonal 원소 배열 추출 => 0의 개수
위와같이 10개의 후보군이 있고 여기서 5개정도를 선택하여 입력으로 넣어주기만 하면 된다.
###############################
def feature_1(input_data):
# 특징 후보 1번 : 가로축 Projection => 확률밀도함수로 변환 => 기댓값
X = sum(input_data)
input_data = input_data.T
S = sum(X)
pdf = np.array([sum(input_data[i]) / S for i in range(len(input_data))])
output_value = sum(X * pdf)
return output_value
#####################################################################################
def feature_2(input_data):
# 특징 후보 2번 : 가로축 Projection => 확률밀도함수로 변환 => 분산
X = sum(input_data)
input_data = input_data.T
S = sum(X)
pdf = np.array([ sum(input_data[i])/S for i in range(len(input_data)) ])
E = sum(X * pdf)
output_value = sum( (X - E)**2 * pdf)
return output_value
#####################################################################################
def feature_3(input_data):
# 특징 후보 3번 : 세로축 Projection => 확률밀도함수로 변환 => 기댓값
X = sum(input_data.T)
S = sum(X)
pdf = np.array([sum(input_data[i]) / S for i in range(len(input_data))])
output_value = sum(X * pdf)
return output_value
#####################################################################################
def feature_4(input_data):
# 특징 후보 4번 : 세로축 Projection => 확률밀도함수로 변환 => 분산
X = sum(input_data.T)
input_data = input_data
S = sum(X)
pdf = np.array([sum(input_data[i]) / S for i in range(len(input_data))])
E = sum(X * pdf)
output_value = sum((X - E) **2 * pdf)
return output_value
def feature_5(input_data):
# 특징 후보 5번 : Diagonal 원소배열 추출 => 밀도함수로 변환 => 기댓값
input_data = np.diag(input_data.T)
S = sum(input_data)
pdf = np.array([input_data[i] / S for i in range(len(input_data))])
output_value = sum(input_data * pdf)
return output_value
def feature_6(input_data):
# 특징 후보 6번 : Diagonal 원소배열 추출 => 밀도함수로 변환 => 분산
input_data = np.diag(input_data.T)
S = sum(input_data)
pdf = np.array([input_data[i] / S for i in range(len(input_data))])
E = sum(input_data * pdf)
output_value = sum((input_data - E) **2 * pdf)
return output_value
def feature_7(input_data):
# 특징 후보 7번 : Diagonal 원소배열 추출 => 0의 개수
input_data = np.diag(input_data.T)
cnt=0
for i in input_data:
if i ==0:
cnt +=1
return cnt
def feature_8(input_data):
# 특징 후보 8번 : Anti-Diagonal 원소배열 추출 => 밀도함수로 변환 => 기댓값
input_data = np.diag(np.fliplr(input_data))
S = sum(input_data)
pdf = np.array([input_data[i] / S for i in range(len(input_data))])
output_value = sum(input_data * pdf)
return output_value
def feature_9(input_data):
# 특징 후보 9번 : Anti-Diagonal 원소배열 추출 => 밀도함수로 변환 => 분산
input_data = np.diag(np.fliplr(input_data))
S = sum(input_data)
pdf = np.array([input_data[i] / S for i in range(len(input_data))])
E = sum(input_data * pdf)
output_value = sum((input_data - E) **2 * pdf)
return output_value
def feature_10(input_data):
# 특징 후보 10번 : Anti-Diagonal 원소배열 추출 => 0의 개수
input_data = np.diag(np.fliplr(input_data))
cnt=0
for i in input_data:
if i ==0:
cnt +=1
return cnt
feature = [0,feature_1,feature_2,feature_3,feature_4,feature_5,feature_6,feature_7,feature_8,feature_9,feature_10]
해당 후보군들을 실제로 나타낸다면 위코드들을 통해서 나타낼 수 있다.
이 코드들을 활용해서 실제 모델을 만들어보면 아래코드와 같다.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
class perceptron: # perceptron 클래스 구현
def __init__(self, w):
self.w = w
def output(self, x):
return np.dot(np.append(x, 1), self.w)
def sigmoid(x): # 시그모이드 함수
return 1 / (1 + np.exp(-x))
def one_hot_encoding(array, size):
lst = [] # one_hot_encoding 과정
for i in array:
tmp = [0] * size
tmp[i -1] +=1
lst.append(tmp)
return np.array(lst)
class Neural_Network: # 2계층 신경망 구현
def __init__(self, hidden_layer_size, Input, Output, learning_rate,Test_set):
self.hidden_layer_size = hidden_layer_size # 은닉층 노드 개수
self.Input_size = Input.shape[1] # 입력층 사이즈
self.Output_size = Output.shape[1] # 출력층 사이즈
self.X = Input # 트레이닝 셋 입력
self.Y = Output # 트레이닝 셋 출력(정답)
self.learning_rate = learning_rate # Learning rate
self.Create_Weight_Matrix() # W0,W1매트릭스 임의 생성
self.Test_set = Test_set # 테스트셋 저장
def Create_Weight_Matrix(self): # Weight 를 만드는 함수
self.W0 = np.random.randn(self.Input_size +1, self.hidden_layer_size)
self.W1 = np.random.randn(self.hidden_layer_size +1, self.Output_size)
def Set_Hidden_layer_Node_size(self, size): # 히든Node수 설정
self.hidden_layer_size = size
self.Create_Weight_Matrix()
def Check_Input_Output_size(self): # Input,Output 체크함수
print('Input 속성 수 ====>', self.Input_size)
print('Output 속성 수 ===>', self.Output_size)
def predict(self, x): # y예측 함수
INPUT_LAYER = perceptron(self.W0)
OUTPUT_LAYER = perceptron(self.W1)
self.sigmoid_input = sigmoid(INPUT_LAYER.output(x))
self.H = np.append(self.sigmoid_input, 1)
return sigmoid(OUTPUT_LAYER.output(self.sigmoid_input))
def Back_propagation(self):
lr =self.learning_rate # Learning rate
for i in range(len(self.X)):
Y_pred =self.predict(self.X[i]) # Y 예측값
Input = np.append(self.X[i], 1) # 입력층 + 1 추가
# 역전파를 1단계부터 시행하면 W가 업데이트되어 2단계부터 시행
for j in range(self.Input_size +1): # 역전파 2단계
for k in range(self.hidden_layer_size):
Etotal_h_diff =0
for q in range(self.Output_size):
Etotal_h_diff +=-2 * (self.Y[i][q] - Y_pred[q]) * Y_pred[q] * (1 - Y_pred[q]) *self.W1[k][q]
h_z_diff =self.H[k] * (1 -self.H[k])
z_w_diff = Input[j]
Etotal_w = Etotal_h_diff * h_z_diff * z_w_diff
self.W0[j][k] =self.W0[j][k] - lr * Etotal_w # W0업데이트
for j in range(self.hidden_layer_size +1): # 역전파 1단계
for k in range(self.Output_size):
E_o_diff =-2 * (self.Y[i][k] - Y_pred[k])
o_z_diff = Y_pred[k] * (1 - Y_pred[k])
z_w_diff =self.H[j]
Etotal_w = E_o_diff * o_z_diff * z_w_diff
self.W1[j][k] =self.W1[j][k] - lr * Etotal_w # W1 업데이트
def train(self, epoch):
self.epoch = epoch # epoch 저장
self.MSEs = [] # MSE그래프를 그리기 위함
self.Accuaracys = [] # 정확도 그래프를 그리기 위함
for i in range(epoch):
data = np.concatenate([self.X, self.Y], 1) # 셔플과정
np.random.shuffle(data) # 매 에폭마다 섞어주는 과정
self.X, none, self.Y = np.hsplit(data, (self.Input_size, self.Input_size))
self.Back_propagation() # 역전파 과정으로 W업데이트
if i % 100 ==0:
tmp_mse = [] # 정확도 계산
cnt =0
for j in range(len(self.X)):
Y_pred =self.predict(self.X[j])
tmp_mse.append(np.mean((self.Y[j] - Y_pred) **2))
maxindex = np.argmax(self.predict(self.X[j])) # 가장큰 index가져오기
tmp = np.array([0] *self.Output_size)
tmp[maxindex] =1
if np.array_equal(tmp, self.Y[j]): # 정답과 비교
cnt +=1
Accuracy = cnt /len(self.X)
self.Accuaracys.append(Accuracy)
MSE = np.mean(tmp_mse)
self.MSEs.append(MSE)
test_X, none, test_Y = np.hsplit(Test_set, (self.Input_size, self.Input_size))
cnt =0
for j in range(len(test_X)):
maxindex = np.argmax(self.predict(test_X[j]))
tmp = np.array([0] *self.Output_size)
tmp[maxindex] =1
if np.array_equal(tmp, test_Y[j]):
cnt +=1
test_Accuracy = cnt /len(test_X)
print(f 'EPOCH {i} ===> MSE : {MSE} , Accuracy : {Accuracy} ,Test_Accuracy : {test_Accuracy}')
# W 저장 ( W폴더를 하나 만들어야 저장이 가능함 )
# df0 = pd.DataFrame(self.W0)
# df0.to_csv(f'W\\{i}epoch_W0.csv',index=False,header='None')
# df1 = pd.DataFrame(self.W1)
# df1.to_csv(f'W\\{i}epoch_W1.csv', index=False,header='None')
#####################################################################################
def feature_1(input_data):
# 특징 후보 1번 : 가로축 Projection => 확률밀도함수로 변환 => 기댓값
X = sum(input_data)
input_data = input_data.T
S = sum(X)
pdf = np.array([sum(input_data[i]) / S for i in range(len(input_data))])
output_value = sum(X * pdf)
return output_value
#####################################################################################
def feature_2(input_data):
# 특징 후보 2번 : 가로축 Projection => 확률밀도함수로 변환 => 분산
X = sum(input_data)
input_data = input_data.T
S = sum(X)
pdf = np.array([ sum(input_data[i])/S for i in range(len(input_data)) ])
E = sum(X * pdf)
output_value = sum( (X - E)**2 * pdf)
return output_value
#####################################################################################
def feature_3(input_data):
# 특징 후보 3번 : 세로축 Projection => 확률밀도함수로 변환 => 기댓값
X = sum(input_data.T)
S = sum(X)
pdf = np.array([sum(input_data[i]) / S for i in range(len(input_data))])
output_value = sum(X * pdf)
return output_value
#####################################################################################
def feature_4(input_data):
# 특징 후보 4번 : 세로축 Projection => 확률밀도함수로 변환 => 분산
X = sum(input_data.T)
input_data = input_data
S = sum(X)
pdf = np.array([sum(input_data[i]) / S for i in range(len(input_data))])
E = sum(X * pdf)
output_value = sum((X - E) **2 * pdf)
return output_value
def feature_5(input_data):
# 특징 후보 5번 : Diagonal 원소배열 추출 => 밀도함수로 변환 => 기댓값
input_data = np.diag(input_data.T)
S = sum(input_data)
pdf = np.array([input_data[i] / S for i in range(len(input_data))])
output_value = sum(input_data * pdf)
return output_value
def feature_6(input_data):
# 특징 후보 6번 : Diagonal 원소배열 추출 => 밀도함수로 변환 => 분산
input_data = np.diag(input_data.T)
S = sum(input_data)
pdf = np.array([input_data[i] / S for i in range(len(input_data))])
E = sum(input_data * pdf)
output_value = sum((input_data - E) **2 * pdf)
return output_value
def feature_7(input_data):
# 특징 후보 7번 : Diagonal 원소배열 추출 => 0의 개수
input_data = np.diag(input_data.T)
cnt=0
for i in input_data:
if i ==0:
cnt +=1
return cnt
def feature_8(input_data):
# 특징 후보 8번 : Anti-Diagonal 원소배열 추출 => 밀도함수로 변환 => 기댓값
input_data = np.diag(np.fliplr(input_data))
S = sum(input_data)
pdf = np.array([input_data[i] / S for i in range(len(input_data))])
output_value = sum(input_data * pdf)
return output_value
def feature_9(input_data):
# 특징 후보 9번 : Anti-Diagonal 원소배열 추출 => 밀도함수로 변환 => 분산
input_data = np.diag(np.fliplr(input_data))
S = sum(input_data)
pdf = np.array([input_data[i] / S for i in range(len(input_data))])
E = sum(input_data * pdf)
output_value = sum((input_data - E) **2 * pdf)
return output_value
def feature_10(input_data):
# 특징 후보 10번 : Anti-Diagonal 원소배열 추출 => 0의 개수
input_data = np.diag(np.fliplr(input_data))
cnt=0
for i in input_data:
if i ==0:
cnt +=1
return cnt
feature = [0,feature_1,feature_2,feature_3,feature_4,feature_5,feature_6,feature_7,feature_8,feature_9,feature_10]
Training_X = np.array([],dtype ='float32') #입력 데이터 가공
Training_X=np.resize(Training_X,(0,5))
Training_Y = np.array([],dtype ='float32')
Training_Y = np.resize(Training_X,(0,3))
for i in range(3):
for j in range(1,501):
tmp_name = f '[배포용] MINIST Data\\{i}_{j}.csv'
tmp_img = pd.read_csv(tmp_name,header =None).to_numpy(dtype ='float32')
x0 = feature[2](tmp_img)
x1 = feature[4](tmp_img)
x2 = feature[6](tmp_img)
x3 = feature[7](tmp_img)
x4 = feature[9](tmp_img)
X = np.array([[x0,x1,x2,x3,x4]],dtype ='float32')
Y = np.array([[0] *3])
Y[0][i] =1
Training_X = np.concatenate((Training_X,X),axis =0)
Training_Y = np.concatenate((Training_Y,Y),axis =0)
#데이터 셔플 및 Train,Test set 구분
Train_data = np.concatenate([Training_X,Training_Y],1)
np.random.shuffle(Train_data)
Traning_set = Train_data[:1200]
Test_set = Train_data[1200:]
X,none,Y = np.hsplit(Traning_set,(5,5))
Network = Neural_Network(hidden_layer_size =4,Input =X,Output =Y,learning_rate =0.007,Test_set =Test_set)
Network.Check_Input_Output_size()
Network.train(5000)
print('W0 :',Network.W0) #학습된 W0,W1 출력
print('W1 :',Network.W1)
plt.xlabel('Epoch')
plt.ylabel("MSE")
plt.grid()
plt.plot(range(len(Network.MSEs)),Network.MSEs,color ='blue')
plt.show() #MSE 변화 출력
plt.xlabel('Epoch')
plt.ylabel("Accuracy")
plt.grid()
plt.plot(range(len(Network.Accuaracys)),Network.Accuaracys,color ='blue')
plt.show() #정확도 변화 출력
그렇다면 어떻게 구성해야 잘 나올까??
10개의 후보군들중에서 5개를 골라야 하므로 순열을 활용해서 해볼수도 있을 것이다.
이런 방법은 가장 확실하지만 시간이 굉장히 오래걸린다 (필자는 20시간정도)
아무튼 결과적으로 특성간의 차이가 큰 후보일수록 학습이 잘된다는것을 확인할 수 있었다.
은닉층 노드 수 | learning rate | 특성후보 조합 | epoch |
5 | 0.001 | 2,3,4,7,10 | 50000 |
위세팅처럼 두었을때 정확도가 가장 잘나왔는데, 96%정도 나왔다.
만약 설정값을 조금 다르게 둔다면
은닉층 노드 수 | learning rate | 특성후보 조합 | epoch |
4 | 0.007 | 2,3,4,7,10 | 5000 |
위와같이 Best Case만큼은 아니지만 학습이 잘 된것을 알 수 있다.
만약 은닉층 노드수를 극단적으로 늘리면 어떻게 될까
은닉층 노드 수 | learning rate | 특성후보 조합 | epoch |
40 | 0.007 | 2,3,4,7,10 | 5000 |
우선 시간이 정말 오래걸린다. 은닉층이 많아짐에 따라 계산량이 많아지기때문 또한 이경우 Validation 정확도는 높아지더라도 위와같이 Test_Accuracy가 낮아지는 Over fitting 현상이 잘 일어나게 된다.
learning rate를 낮게주면 가끔 Local minimum에 걸리는 현상도 관찰할 수 있었다.
은닉층 노드 수 | learning rate | 특성후보 조합 | epoch |
4 | 0.001 | 2,3,4,7,10 | 5000 |
정확도가 70프로를 넘어가지 않는데, 초기 W에 따라서 같은 설정값으로 해도 90%가까이 될때가 있었다. 즉 Learning rate가 작아 초기 w에 따라서 local minimum 현상이 일어남을 알 수 있다.
W 저장
해당 코드를 보면 학습에 따라 W가 엑셀파일로 저장되는것을 알 수 있다.
이를 가져와서 테스트하는 파일을 통해 검사해보자.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
import tensorflow_datasets
import warnings
warnings.filterwarnings('ignore')
class perceptron: # perceptron 클래스 구현
def __init__(self, w):
self.w = w
def output(self, x):
return np.dot(np.append(x, 1), self.w)
def sigmoid(x): # 시그모이드 함수
x=np.float64(x)
return 1 / (1 + np.exp(-x))
def one_hot_encoding(array, size):
lst = [] # one_hot_encoding 과정
for i in array:
tmp = [0] * size
tmp[i -1] +=1
lst.append(tmp)
return np.array(lst)
class Neural_Network: # 2계층 신경망 구현
def __init__(self, hidden_layer_size, Input, Output, learning_rate):
self.hidden_layer_size = hidden_layer_size # 은닉층 노드 개수
self.Input_size = Input.shape[1] # 입력층 사이즈
self.Output_size = Output.shape[1] # 출력층 사이즈
self.X = Input # 트레이닝 셋 입력
self.Y = Output # 트레이닝 셋 출력(정답)
self.learning_rate = learning_rate # Learning rate
self.Create_Weight_Matrix() # W0,W1매트릭스 임의 생성
def Create_Weight_Matrix(self): # Weight 를 만드는 함수
self.W0 = np.random.randn(self.Input_size +1, self.hidden_layer_size)
self.W1 = np.random.randn(self.hidden_layer_size +1, self.Output_size)
def Set_Hidden_layer_Node_size(self, size): # 히든Node수 설정
self.hidden_layer_size = size
self.Create_Weight_Matrix()
def Check_Input_Output_size(self): # Input,Output 체크함수
print('Input 속성 수 ====>', self.Input_size)
print('Output 속성 수 ===>', self.Output_size)
def predict(self, x): # y예측 함수
INPUT_LAYER = perceptron(self.W0)
OUTPUT_LAYER = perceptron(self.W1)
self.sigmoid_input = sigmoid(INPUT_LAYER.output(x))
self.H = np.append(self.sigmoid_input, 1)
return sigmoid(OUTPUT_LAYER.output(self.sigmoid_input))
def Back_propagation(self):
lr =self.learning_rate # Learning rate
for i in range(len(self.X)):
Y_pred =self.predict(self.X[i]) # Y 예측값
Input = np.append(self.X[i], 1) # 입력층 + 1 추가
# 역전파를 1단계부터 시행하면 W가 업데이트되어 2단계부터 시행
for j in range(self.Input_size +1): # 역전파 2단계
for k in range(self.hidden_layer_size):
Etotal_h_diff =0
for q in range(self.Output_size):
Etotal_h_diff +=-2 * (self.Y[i][q] - Y_pred[q]) * Y_pred[q] * (1 - Y_pred[q]) *self.W1[k][q]
h_z_diff =self.H[k] * (1 -self.H[k])
z_w_diff = Input[j]
Etotal_w = Etotal_h_diff * h_z_diff * z_w_diff
self.W0[j][k] =self.W0[j][k] - lr * Etotal_w # W0업데이트
for j in range(self.hidden_layer_size +1): # 역전파 1단계
for k in range(self.Output_size):
E_o_diff =-2 * (self.Y[i][k] - Y_pred[k])
o_z_diff = Y_pred[k] * (1 - Y_pred[k])
z_w_diff =self.H[j]
Etotal_w = E_o_diff * o_z_diff * z_w_diff
self.W1[j][k] =self.W1[j][k] - lr * Etotal_w # W1 업데이트
def train(self, epoch):
self.epoch = epoch # epoch 저장
self.MSEs = [] # MSE그래프를 그리기 위함
self.Accuaracys = [] # 정확도 그래프를 그리기 위함
for i in range(epoch):
data = np.concatenate([self.X, self.Y], 1) # 셔플과정
np.random.shuffle(data) # 매 에폭마다 섞어주는 과정
self.X, none, self.Y = np.hsplit(data, (self.Input_size, self.Input_size))
self.Back_propagation() # 역전파 과정으로 W업데이트
if i % 100 ==0:
tmp_mse = [] # 정확도 계산
cnt =0
for j in range(len(self.X)):
Y_pred =self.predict(self.X[j])
tmp_mse.append(np.mean((self.Y[j] - Y_pred) **2))
maxindex = np.argmax(self.predict(self.X[j])) # 가장큰 index가져오기
tmp = np.array([0] *self.Output_size)
tmp[maxindex] =1
if np.array_equal(tmp, self.Y[j]): # 정답과 비교
cnt +=1
Accuracy = cnt /len(self.X)
self.Accuaracys.append(Accuracy)
MSE = np.mean(tmp_mse)
self.MSEs.append(MSE)
testcnt =0
for j in range(len(data_x)):
Y_pred = Network.predict(data_x[j])
maxindex = np.argmax(Y_pred) # 가장큰 index가져오기
tmp = np.array([0] *3)
tmp[maxindex] =1
if np.array_equal(tmp, label_list[j]): # 정답과 비교
testcnt +=1
testAccuracy = testcnt /len(data_x)
print(f 'EPOCH {i} ===> MSE : {MSE} , Accuracy : {Accuracy} testAccuracy : {testAccuracy}')
df0 = pd.DataFrame(self.W0)
df0.to_csv(f'W\\{i}epoch_W0.csv',index =False)
df1 = pd.DataFrame(self.W1)
df1.to_csv(f'W\\{i}epoch_W1.csv', index =False)
def InputWs(self,W0,w1):
self.W0 = W0
self.W1 = w1
#####################################################################################
def feature_1(input_data):
# 특징 후보 1번 : 가로축 Projection => 확률밀도함수로 변환 => 기댓값
X = sum(input_data)
input_data = input_data.T
S = sum(X)
pdf = np.array([sum(input_data[i]) / S for i in range(len(input_data))])
output_value = sum(X * pdf)
return output_value
#####################################################################################
def feature_2(input_data):
# 특징 후보 2번 : 가로축 Projection => 확률밀도함수로 변환 => 분산
X = sum(input_data)
input_data = input_data.T
S = sum(X)
pdf = np.array([ sum(input_data[i])/S for i in range(len(input_data)) ])
E = sum(X * pdf)
output_value = sum( (X - E)**2 * pdf)
return output_value
#####################################################################################
def feature_3(input_data):
# 특징 후보 3번 : 세로축 Projection => 확률밀도함수로 변환 => 기댓값
X = sum(input_data.T)
S = sum(X)
pdf = np.array([sum(input_data[i]) / S for i in range(len(input_data))])
output_value = sum(X * pdf)
return output_value
#####################################################################################
def feature_4(input_data):
# 특징 후보 4번 : 세로축 Projection => 확률밀도함수로 변환 => 분산
X = sum(input_data.T)
input_data = input_data
S = sum(X)
pdf = np.array([sum(input_data[i]) / S for i in range(len(input_data))])
E = sum(X * pdf)
output_value = sum((X - E) **2 * pdf)
return output_value
def feature_5(input_data):
# 특징 후보 5번 : Diagonal 원소배열 추출 => 밀도함수로 변환 => 기댓값
input_data = np.diag(input_data.T)
S = sum(input_data)
pdf = np.array([input_data[i] / S for i in range(len(input_data))])
output_value = sum(input_data * pdf)
return output_value
def feature_6(input_data):
# 특징 후보 6번 : Diagonal 원소배열 추출 => 밀도함수로 변환 => 분산
input_data = np.diag(input_data.T)
S = sum(input_data)
pdf = np.array([input_data[i] / S for i in range(len(input_data))])
E = sum(input_data * pdf)
output_value = sum((input_data - E) **2 * pdf)
return output_value
def feature_7(input_data):
# 특징 후보 7번 : Diagonal 원소배열 추출 => 0의 개수
input_data = np.diag(input_data.T)
cnt=0
for i in input_data:
if i ==0:
cnt +=1
return cnt
def feature_8(input_data):
# 특징 후보 8번 : Anti-Diagonal 원소배열 추출 => 밀도함수로 변환 => 기댓값
input_data = np.diag(np.fliplr(input_data))
S = sum(input_data)
pdf = np.array([input_data[i] / S for i in range(len(input_data))])
output_value = sum(input_data * pdf)
return output_value
def feature_9(input_data):
# 특징 후보 9번 : Anti-Diagonal 원소배열 추출 => 밀도함수로 변환 => 기댓값
input_data = np.diag(np.fliplr(input_data))
S = sum(input_data)
pdf = np.array([input_data[i] / S for i in range(len(input_data))])
E = sum(input_data * pdf)
output_value = sum((input_data - E) **2 * pdf)
return output_value
def feature_10(input_data):
# 특징 후보 10번 : Anti-Diagonal 원소배열 추출 => 0의 개수
input_data = np.diag(np.fliplr(input_data))
cnt=0
for i in input_data:
if i ==0:
cnt +=1
return cnt
feature = [0,feature_1,feature_2,feature_3,feature_4,feature_5,feature_6,feature_7,feature_8,feature_9,feature_10]
# raw_data = pd.read_csv(f'[배포용] MINIST Data\\0_1.csv',encoding='utf-8', engine = 'python',header=None).to_numpy()
# for i in range(1,11):
# print(i,':' , feature[i](raw_data))
##########mnist
mnist = tensorflow_datasets.load('mnist')
train_set = mnist["train"]
# (train_images, train_labels), (test_images, test_labels) = mnist
data_list = []
label_list = []
one = []
two = []
zero=[]
for d in train_set:
if d["label"] ==0:
zero.append(d["image"])
elif d["label"] ==1:
one.append(d["image"])
elif d["label"] ==2:
two.append(d["image"])
data_list = zero + one + two
data_list = np.array(data_list)
print(data_list.shape)
label_list = []
one_index =len(one)
two_index =len(two)
zero_index =len(zero)
print(one_index,two_index,zero_index)
t = [[1,0,0], [0,1,0], [0,0,1]]
for i in range(zero_index):
label_list.append(t[0])
for i in range(one_index):
label_list.append(t[1])
for i in range(two_index):
label_list.append(t[2])
label_list = np.array(label_list)
data_x=np.array([])
data_x=np.resize(data_x,(0,5))
for d in data_list:
d=d.T[0].T
x0 = feature[2](d)
x1 = feature[3](d)
x2 = feature[4](d)
x3 = feature[7](d)
x4 = feature[10](d)
X = np.array([[x0,x1,x2,x3,x4]],dtype ='float32')
data_x = np.concatenate((data_x,X),axis =0)
print(data_x.shape)
Training_X = np.array([],dtype ='float64')
Training_X=np.resize(Training_X,(0,5))
Training_Y = np.array([],dtype ='float64')
Training_Y = np.resize(Training_X,(0,3))
for i in range(3):
for j in range(1,501):
tmp_name = f '[배포용] MINIST Data\\{i}_{j}.csv'
tmp_img = pd.read_csv(tmp_name,header =None).to_numpy(dtype ='float32')
x0 = feature[2](tmp_img)
x1 = feature[3](tmp_img)
x2 = feature[4](tmp_img)
x3 = feature[7](tmp_img)
x4 = feature[10](tmp_img)
X = np.array([[x0,x1,x2,x3,x4]],dtype ='float32')
Y = np.array([[0] *3])
Y[0][i] =1
Training_X = np.concatenate((Training_X,X),axis =0)
Training_Y = np.concatenate((Training_Y,Y),axis =0)
Train_data = np.concatenate([Training_X,Training_Y],1)
np.random.shuffle(Train_data)
Traning_set = Train_data[:1200]
Test_set = Train_data[1200:]
X,none,Y = np.hsplit(Traning_set,(5,5))
TX,none,TY = np.hsplit(Test_set,(5,5))
Network = Neural_Network(hidden_layer_size =4,Input =Training_X,Output =Training_Y,learning_rate =0.007)
Network.Check_Input_Output_size()
# Network.train(10000)
for i in range(100,50000,100):
w_hidden = pd.read_csv(f 'W_234710\\{i}epoch_W0.csv').to_numpy()
w_output = pd.read_csv(f 'W_234710\\{i}epoch_W1.csv').to_numpy()
Network.InputWs(w_hidden, w_output)
# 정확도 계산
cnt =0
for j in range(len(data_x)):
Y_pred = Network.predict(data_x[j])
maxindex = np.argmax(Y_pred) # 가장큰 index가져오기
tmp = np.array([0] *3)
tmp[maxindex] =1
if np.array_equal(tmp, label_list[j]): # 정답과 비교
cnt +=1
Accuracy = cnt /len(data_x)
print(f '{i}번째 Mnist Accuracy : {Accuracy} ')
cnt =0
for j in range(len(X)):
Y_pred = Network.predict(X[j])
maxindex = np.argmax(Y_pred) # 가장큰 index가져오기
tmp = np.array([0] *3)
tmp[maxindex] =1
if np.array_equal(tmp, Y[j]): # 정답과 비교
cnt +=1
Accuracy = cnt /len(X)
print(f ' Accuracy : {Accuracy} ')
cnt =0
for j in range(len(TX)):
Y_pred = Network.predict(TX[j])
maxindex = np.argmax(Y_pred) # 가장큰 index가져오기
tmp = np.array([0] *3)
tmp[maxindex] =1
if np.array_equal(tmp, TY[j]): # 정답과 비교
cnt +=1
Accuracy = cnt /len(TX)
print(f ' test Accuracy : {Accuracy} ')
해당 코드를 확인하면 저장된 w들을 가져와서 테스트셋과 비교해서 정확도를 다시 알아볼 수도 있고, 실제 Minist 데이터를 18000개정도 가져와서 형태를 맞춰 본 후에 정확도를 검사할 수도 있다.
학습이 90%넘게 되었지만 해당 데이터셋의 한계로 실제 Minist 에선 60%정도 정확도가 나오면 학습이 잘 된것이다!
'Python > 인공지능' 카테고리의 다른 글
클러스터링 K-Means 직접구현 (0) | 2022.06.11 |
---|---|
인공신경망 직접구현 (0) | 2022.06.07 |
Training , Test 선택 가우시안 모델 구현하기 (0) | 2022.04.30 |
파이참에서 GPU사용! (0) | 2022.04.24 |
가우스 함수를 이용한 선형회귀 모델 직접구현 (0) | 2022.04.17 |