<jupyter_start><jupyter_text>Single Layer Neural Network- 딥러닝 알고리즘의 가장 기본이 되는 인공신경망(artificial neural network, ANN) 그 중에서도 single-layer neural network 모델을 구현해보자. 크게 세가지 방식- 1) Random Search- 2) h-step Search- 3) Gradient Descent<jupyter_code>import numpy as np<jupyter_output><empty_output><jupyter_text>Generate Dataset- 0~1 사이에 균등분포를 가지는 100개의 샘플을 각각 x1, x2로 만든다.- 0.3 * x1 + 0.5 * x2 + 0.1의 공식을 가지는 y를 만든다.<jupyter_code>x1 = np.random.uniform(low=0.0, high=1.0, size=100)

print(x1.shape)
x1[:10]
x2 = np.random.uniform(low=0.0, high=1.0, size=100)

print(x2.shape)
x2[:10]
y = 0.3 * x1 + 0.5 * x2 + 0.1

print(y.shape)
y[:10]<jupyter_output>(100,)<jupyter_text>First idea: Random Search- 랜덤으로 weight값(w1, w2)과 바이어스(bias) 값(b)을 만들어 최소한의 error를 만들어 내는 값을 여러번의 시도를 통해 찾아낸다.- **답(목표error값)을 찾을 때까지 w1, w2, b을 랜덤으로 찾기 때문에 1번만에 끝나거나 10000을 다돌려도 못찾을 수 있다.**<jupyter_code>num_epoch = 10000

best_error = np.inf
best_epoch = None
best_w1 = None
best_w2 = None
best_b = None

for epoch in range(num_epoch):
    w1 = np.random.uniform(low=0.0, high=1.0)
    w2 = np.random.uniform(low=0.0, high=1.0)
    b = np.random.uniform(low=0.0, high=1.0)

    y_predict = x1 * w1 + x2 * w2 + b
    
    error = np.abs(y_predict - y).mean()
    
    if error < best_error:
        best_error = error
        best_epoch = epoch
        best_w1 = w1
        best_w2 = w2
        best_b = b

        print("{0:4} w1 = {1:.5f}, w2 = {2:.5f}, b = {3:.5f}, error = {4:.5f}".format(best_epoch, best_w1, best_w2, best_b, best_error))

print("----" * 15)
print("{0:4} w1 = {1:.5f}, w2 = {2:.5f}, b = {3:.5f}, error = {4:.5f}".format(best_epoch, best_w1, best_w2, best_b, best_error))<jupyter_output>0 w1 = 0.57986, w2 = 0.05484, b = 0.55502, error = 0.34047
   3 w1 = 0.67128, w2 = 0.08402, b = 0.33361, error = 0.20212
   8 w1 = 0.00712, w2 = 0.77407, b = 0.15153, error = 0.10809
  26 w1 = 0.19931, w2 = 0.41073, b = 0.21938, error = 0.03755
  95 w1 = 0.21394, w2 = 0.47162, b = 0.14996, error = 0.02235
 661 w1 = 0.32373, w2 = 0.43404, b = 0.11620, error = 0.02009
7700 w1 = 0.29914, w2 = 0.51221, b = 0.10214, error = 0.00858
------------------------------------------------------------
7700 w1 = 0.29914, w2 = 0.51221, b = 0.10214, error = 0.00858<jupyter_text>Second idea: H-step Search- w1, w2, b 값을 한번 랜덤으로 만든다.- 첫번째 error 값을 구한후, 정해진 스텝수(h)만큼 w1을 +,-하며 error가 줄어드는 방향으로 업데이트 한다.- w2와 b도 동일한 방법으로 첫번째 error와 비교하여 error가 줄어드는 방향으로 업데이트 한다.- **스텝수(h)가 적절하지 않으면 여러번 돌려도 error를 줄일 수 없다.**- **Random Search와 마찬가지로 처음생성되는 w1, w2, b값과 스텝수의 따라 1번만에 목표 error값에 도달하는 값을 찾거나 10000번이 지나도 못찾을 수도 있다.**<jupyter_code>num_epoch = 10000

w1 = np.random.uniform(low=0.0, high=1.0)
w2 = np.random.uniform(low=0.0, high=1.0)
b = np.random.uniform(low=0.0, high=1.0)

h = 0.01

for epoch in range(num_epoch):
    y_predict = x1 * w1 + x2 * w2 + b
    current_error = np.abs(y_predict - y).mean()

    if current_error < 0.005:
        break

    y_predict = x1 * (w1 + h) + x2 * w2 + b
    h_plus_error = np.abs(y_predict - y).mean()
    if h_plus_error < current_error:
        w1 = w1 + h
    else:
        y_predict = x1 * (w1 - h) + x2 * w2 + b
        h_minus_error = np.abs(y_predict - y).mean()
        if h_minus_error < current_error:
            w1 = w1 - h
            
    y_predict = x1 * w1 + x2 * (w2 + h) + b
    h_plus_error = np.abs(y_predict - y).mean()
    if h_plus_error < current_error:
        w2 = w2 + h
    else:
        y_predict = x1 * w1 + x2 * (w2 - h) + b
        h_minus_error = np.abs(y_predict - y).mean()
        if h_minus_error < current_error:
            w2 = w2 - h

    y_predict = x1 * w1 + x2 * w2 + (b + h)
    h_plus_error = np.abs(y_predict - y).mean()
    if h_plus_error < current_error:
        b = b + h
    else:
        y_predict = x1 * w1 + x2 * w2 + (b - h)
        h_minus_error = np.abs(y_predict - y).mean()
        if h_minus_error < current_error:
            b = b - h

print("{0} w1 = {1:.5f}, w2 = {2:.5f}, b = {3:.5f}, error = {4:.5f}".format(epoch, w1, w2, b, current_error))<jupyter_output>46 w1 = 0.30770, w2 = 0.49417, b = 0.10148, error = 0.00282<jupyter_text>Third Idea - Gradient Descent- **dError/dWeight한 값으로 weight를 업데이트 해주는 방법이다.** (에러를 각각 업데이트할 weight로 편미분 하면 w의 업데이트 방향설정이 가능하다.)- learning rate는 편미분한 값의 방향을 정한후 학습할 크기를 말한다. (적절한 값이 필요하다.)- 경사감소법은 기울기를 구해 error를 줄이는 방향을 설정하기 때문에 정답에 근사하게 접근할 수 있다.(위 두방법보다 업데이트의 방향성이 보장된다.)<jupyter_code>num_epoch = 100
learning_rate = 1.2

w1 = np.random.uniform(low=0.0, high=1.0)
w2 = np.random.uniform(low=0.0, high=1.0)
b = np.random.uniform(low=0.0, high=1.0)

for epoch in range(num_epoch):
    y_predict = x1 * w1 + x2 * w2 + b

    error = np.abs(y_predict - y).mean()
    if error < 0.001:
        break

    w1 = w1 - learning_rate * ((y_predict - y) * x1).mean()
    w2 = w2 - learning_rate * ((y_predict - y) * x2).mean()
    b = b - learning_rate * (y_predict - y).mean()

    if epoch % 10 == 0:
        print("{0:2} w1 = {1:.5f}, w2 = {2:.5f}, b = {3:.5f}, error = {4:.5f}".format(epoch, w1, w2, b, error))
    
print("----" * 15)
print("{0:2} w1 = {1:.5f}, w2 = {2:.5f}, b = {3:.5f}, error = {4:.5f}".format(epoch, w1, w2, b, error))<jupyter_output>0 w1 = 0.48173, w2 = 0.25863, b = -0.21823, error = 0.39827
10 w1 = 0.38164, w2 = 0.43380, b = -0.03058, error = 0.13723
20 w1 = 0.33821, w2 = 0.48555, b = 0.04449, error = 0.04710
30 w1 = 0.31844, w2 = 0.49919, b = 0.07556, error = 0.01610
40 w1 = 0.30909, w2 = 0.50182, b = 0.08888, error = 0.00564
50 w1 = 0.30454, w2 = 0.50169, b = 0.09480, error = 0.00215
------------------------------------------------------------
60 w1 = 0.30291, w2 = 0.50171, b = 0.09822, error = 0.00091
{'fraction_non_alphanumeric': 0.17977928088287648, 'fraction_numerical': 0.12922748309006765, 'mean_word_length': 2.4771039603960396, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '506263', 'license': 'MIT', 'n_tokens_mistral': 3190, 'n_tokens_neox': 3110, 'n_words': 654, 'path': 'example/01_Single_Layer_Neural_Network_part1.ipynb', 'repo_name': 'daesookimds/Deep-Learning', 'size': '5618'}