Minist 데이터 활용 0,1,2 구분 인공지능 직접구현
Python/인공지능

Minist 데이터 활용 0,1,2 구분 인공지능 직접구현

728x90

이번에는 Mnist 데이터들을 활용해서 직접 0,1,2를 구분하는 인공지능을 만들어보았다.

 

이를 확장해서 구현한다면 0~9까지 구분하는 인공지능을 라이브러리 없이 직접 만들어보는 것이 가능할 것이다.

 

이전 신경망까지 잘 따라왔다면 오히려 쉽다! 입력 후보군 5개와 0,1,2로 된 출력 후보군 3개를 넣어주기만 하면 된다.

 

먼저 흐름도를 통해 전체적인 흐름을 파악해보자.

 

 

 

[배포용] MINIST Data.zip
0.83MB

우선 일반적인 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

MSE
정확도

위와같이 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%정도 정확도가 나오면 학습이 잘 된것이다!

728x90