# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# +
# ch01~03
## numpy 수학 알고리즘과 배열(행렬) 조작히가 위한 메서드 많이 있다
## matplotlib 그래프를 그려주는 라이브러리

a=[1,2,3,4,5]
print(a)
a[1:]
a[:-1]

# -

dictionary={'height':180}
dictionary['height']
dictionary['weight']=70
print(dictionary)

# !pwd

# !python "/Users/jeongjongkun/Untitled Folder/deep-learning-from-scratch/ch01/hungry.py"


# +
# coding: utf-8
class Man:
    """샘플 클래스"""

    def __init__(self, name): ##class 초기화 방법 정의 생성자 클래스의 인스턴스가 만들어질때 한번만 불린다
        self.name = name
        print("Initilized!")

    def hello(self):
        print("Hello " + self.name + "!")

    def goodbye(self):
        print("Good-bye " + self.name + "!")

m = Man("David")
m.hello()
m.goodbye()


# +
#numpy n차원 배열 작성 가능 1차원 배열 : 벡터, 2차원 배열 : 행렬, 벡터와 행렬을 일반화한것을 텐서
#tensor 가 신경망을 타고 흐른다
#c/c++ 처리속도가 빠르다 numpy도 주된 처리는 c/c++로 구현

import numpy as np
x=np.array([[1,2],[3,4],[5,6]])
print(x.flatten())
x>15

# +
# coding: utf-8
import numpy as np
import matplotlib.pyplot as plt

# 데이터 준비
x = np.arange(0, 6, 0.1) # 0에서 6까지 0.1 간격으로 생성
y = np.sin(x)

# 그래프 그리기
plt.plot(x, y)
plt.show()


# +
# coding: utf-8
import numpy as np
import matplotlib.pyplot as plt

# 데이터 준비
x = np.arange(0, 6, 0.1) # 0에서 6까지 0.1 간격으로 생성
y1 = np.sin(x)
y2 = np.cos(x)

# 그래프 그리기
plt.plot(x, y1, label="sin")
plt.plot(x, y2, linestyle = "--", label="cos") # cos 함수는 점선으로 그리기
plt.xlabel("x") # x축 이름
plt.ylabel("y") # y축 이름
plt.title('sin & cos')
plt.legend()
plt.show()


# +
#perceptron 다수의 신호 받아 하나의 신호 출력
#각 뉴런에서 가중치 곱해진 신호가 뉴런 노드에 모인다 임계치 보다 크면 activate
# coding: utf-8
import numpy as np


def AND(x1, x2):
    x = np.array([x1, x2])
    w = np.array([0.5, 0.5])
    b = -0.7
    tmp = np.sum(w*x) + b
    if tmp <= 0:
        return 0
    else:
        return 1

if __name__ == '__main__':
    for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
        y = AND(xs[0], xs[1])
        print(str(xs) + " -> " + str(y))


# +
import numpy as np


def AND(x1, x2):
    x = np.array([x1, x2])
    w = np.array([0.5, 0.5])
    b = -0.7
    tmp = np.sum(w*x) + b
    if tmp <= 0:
        return 1
    else:
        return 0

if __name__ == '__main__':
    for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
        y = AND(xs[0], xs[1])
        print(str(xs) + " -> " + str(y))


# +
import numpy as np


def AND(x1, x2):
    x = np.array([x1, x2])
    w = np.array([0.5, 0.5])
    b = -0.4
    tmp = np.sum(w*x) + b
    if tmp <= 0:
        return 0
    else:
        return 1

if __name__ == '__main__':
    for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
        y = AND(xs[0], xs[1])
        print(str(xs) + " -> " + str(y))


# +
import numpy as np


def AND(x1, x2):
    x = np.array([x1, x2])
    w = np.array([-1, -1])
    tmp = np.array(w*x+0.1)
    result=(tmp[0]*tmp[1])
    if result <= 0:
        return 1
    else:
        return 0

if __name__ == '__main__':
    for xs in [(0, 0), (1, 0), (0, 1), (1, 1)]:
        y = AND(xs[0], xs[1])
        print(str(xs) + " -> " + str(y))

# -



# +
import numpy as np
def AND(num1,num2):
    a=np.array([num1,num2])
    b=np.array([0.5,0.5])
    c=-0.7
    sum=np.sum(a*b)+c
    if sum>0:
        return 1
    else:
        return 0
if __name__=='__main__':
    for i in range(2):
        for j in range(2):
            print(i,j," : ",AND(i,j))
    
    
for i in range(1):
    print(i)
    
## 저수준 소자에서 컴퓨터 만드는데 필요한 부품(모듈)을 단계적으로 만들어가는 쪽
#AND, OR 게이트 그 다음에는 반가산기와 전가산기 그 다음에는 산술 논리연산장치(ALU), 그 다음에는 CPU
#퍼셉트론은 가중치와 편향을 매개변수로 설정한다
#단순 퍼셉트론은 직선형 영역만 표현할 수 있고 다층 퍼셉트론은 비선형 영역도 표현할 수 있다


# +
#퍼셉트론 복잡한 함수도 표현 가능하지만 가중치를 설정하는 작업은 사람이 수동으로 해야한다 
#신경망은 가중치, 매개변수 적절한 값을 데잍로부터 자동으로 학습
#입력 신호의 총합을 출력 신호로 변환하는 함수를 활성화 함수라 한다 activation function
#입력 신호의 총합이 활성화를 일으키는지를 정하는 역할
#activation function 중에 퍼셉트론은 step finction 임계값을 경계로 출력이 바뀌는 것
#sigmoid 함수  s자 모양
# coding: utf-8
import numpy as np
import matplotlib.pylab as plt


def sigmoid(x):
    return 1 / (1 + np.exp(-x))    

X = np.arange(-5.0, 5.0, 0.1)
Y = sigmoid(X)
plt.plot(X, Y)
plt.ylim(-0.1, 1.1)
plt.show()
# -

import numpy as np
x=np.array([-1,0,-2,1,3])
y=x>0
y=y.astype(np.int) ## numpy 배열의 자료형을 변환 astype()매서드
y

x=np.array([-1,0,-2,1,3])
x*3

#선형함수 상수배만큼 변하는 함수를 선형함수 비선형함수는 선형이 아닌함수 직선 1개로 그릴 수 없는 함수
#activation function 비선형함수 사용해야한다 선형함수는 층을 깊게하는 것이 의미가 없다 - 은닉층의미 없는게 된다
#ReLU Rectified 정류된 max(0,x) np.maximum(0,x)
import numpy as np
a=np.array([[1,2],[3,4],[5,6]])
np.ndim(a) ## np.ndim numpy 형태 배열의 차원 return 
a.shape #(3,2)는 처음차원에 원소가 3개, 다음 차원에 원소가 2개
#np.dot(a,b)로 행렬 내적 구한다 3*2 차원 2*3 차원 처럼 사이 차원 같아야 내적 가능 
#내적 함수 이용해서 신경망 구현
# w 다음층뉴런번호 앞층뉴런번호
X=np.array([1,2])
W=np.array([[1,3,5],[2,4,6]])
Y=np.dot(X,W)
#각각의 layer로 향하는 weight들 곱한 결과
Y
#회귀문제에서는 항등함수를, 분류에서는 소프트맥스 함수를 이용한다
#분류 - 출력층의 뉴런 수, 분류하려는 클래스 수를 같게 설정한다

#softmax 함수 0~1 사이 값으로 정규화 출력 값들의 합은 1 상수e에 x를 지수 제곱해서 다더한것 분의 상수e에 x지수 제곱
# 1개 값만 True, 다른 값 False로 encoding
#softmax 에서 1000넘어가는 값 exp 계산하면 overflow난다
import numpy as np
a=np.array([1010,1000,990])
print(np.exp(a))
c=np.max(a)
a-c
print(np.exp(a-c))
print(np.exp(a-c)/np.sum(np.exp(a-c))) #값들중 최대값 분자 분모 모두에서 빼서 계산한다
print(np.sum(np.exp(a-c)/np.sum(np.exp(a-c))))
#각각의 합 1이어서 확률이 가장 큰 것 계산할 수 있다.
#exp 함수가 단조 증가함수이기 떄문에 대소관계 바뀌지 않는다
#추론단계에서 굳이 softmax 안써도 된다 
#자연상수 e 는 2.71828182846... 의 값을 가지는 무리수이며, 수학자의 이름을 따서 '오일러의 수(Euler's number)' 또는 '네이피어의 수(Napier's number)
#자연의 연속한 성장 growth 100%의 성장률 1회 연속 성장할때 가질수 있는 최대 성장량
#1년에 100% 성장한다고 했을때 이를 쪼개서 무한번 나눠서 각각의 time slice 마다 성장한 부분에 대해서도 성장하는 것 가정
#1을 무한번 제곱하면 e 된다
#50% 성장률 가지고 성장하면 e의 1/2승(성장률*횟수)
#성장량*성장률*성장횟수 중 2개를 알면 나머지 1개 알 수 있다


import matplotlib.pyplot as plt
import numpy as np
x=range(-10,10)
y=np.exp(x)
plt.plot(x,y)

sys.path

# +
import sys, os
#print(sys.path)
#sys.path.insert(0,"deep-learning-from-scratch")
sys.path.append("deep-learning-from-scratch")
print(sys.path)
import numpy as np
from dataset.mnist import load_mnist
from PIL import Image


def img_show(img):
    pil_img = Image.fromarray(np.uint8(img))
    pil_img.show()

(x_train, t_train), (x_test, t_test) = load_mnist(flatten=True, normalize=False)
#flatten 1차원 배열로 만들지, normaliza 0~1 값으로 정규화
img = x_train[0]
label = t_train[0]

print(label)  # 5

print(img.shape)  # (784,)
img = img.reshape(28, 28)  # 형상을 원래 이미지의 크기로 변형
print(img.shape)  # (28, 28)

img_show(img)


# +
#파이썬 pickle 프로그램 실행 중 특정 객체를 파일로 저장 실행 당시의 객체 즉시 복원 가능
# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 부모 디렉터리의 파일을 가져올 수 있도록 설정
import numpy as np
import pickle
from dataset.mnist import load_mnist
from common.functions import sigmoid, softmax


def get_data():
    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)
    return x_test, t_test


def init_network():
    with open("deep-learning-from-scratch/ch03/sample_weight.pkl", 'rb') as f:
        network = pickle.load(f)
    return network


def predict(network, x):
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']

    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, W3) + b3
    y = softmax(a3)

    return y


x, t = get_data()
network = init_network()
accuracy_cnt = 0
for i in range(len(x)):
    y = predict(network, x[i])
    p= np.argmax(y) # 확률이 가장 높은 원소의 인덱스를 얻는다.
    if p == t[i]:
        accuracy_cnt += 1

print("Accuracy:" + str(float(accuracy_cnt) / len(x)))
#하나로 묶은 입력 데이터를 배치라고 한다 batch = 일괄적으로 처리되는 집단
#batch - 수치 계산 라이브러리 - 큰 배열을 효율적으로 처리할 수 있도록 고도로 최적화
# 커다란 신경망에서 데이터 전송이 병목으로 작용하는 경우 - 배치 처리로 버스에 주느 부하 줄인다
# 컴퓨터에서는 큰배열 한꺼번에 계산하는 것이 작은 배열 여러번 개산하는 것보다 빠르다

# +
# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 부모 디렉터리의 파일을 가져올 수 있도록 
import numpy as np
import pickle
from dataset.mnist import load_mnist
from common.functions import sigmoid, softmax


def get_data():
    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)
    return x_test, t_test


def init_network():
    with open("deep-learning-from-scratch/ch03/sample_weight.pkl", 'rb') as f:
        network = pickle.load(f)
    return network


def predict(network, x):
    w1, w2, w3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']

    a1 = np.dot(x, w1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, w2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, w3) + b3
    y = softmax(a3)

    return y


x, t = get_data()
network = init_network()

batch_size = 100 # 배치 크기
accuracy_cnt = 0

for i in range(0, len(x), batch_size):
    x_batch = x[i:i+batch_size]
    y_batch = predict(network, x_batch)
    p = np.argmax(y_batch, axis=1) ##argmax 는 최대값의 인덱스를 가져온다
    accuracy_cnt += np.sum(p == t[i:i+batch_size])

print("Accuracy:" + str(float(accuracy_cnt) / len(x)))

# -

import numpy as np
x=np.array([[0.1,0.2,1],[4,2,1],[14,5,17]])
y=np.argmax(x,axis=1)
y

print(x_train.shape)
print(t_train.shape)
print(x_test.shape)
print(t_test.shape)

import sys
print(sys.path)


StarcoderdataJupyterScriptsDedupFiltered