Skip to content

기계학습 Multi Variables #

Find similar titles

2회 업데이트 됨.

Edit
  • 최초 작성자
    ecjang
  • 최근 업데이트
    jmkang

Structured data

Category
Programming

Multi Variable #

데이터 분석에는 변수를 하나만 다루지 않는다. 수많은 변수들을 동시다발적으로 분석하여 의미 있는 결과를 도출하는데 이를 위해 여러 개의 변수를 다룰 수 있어야 한다. 이번에는 여러 명의 성적데이터를 통해 예상 점수를 구하는 과정을 알아본다.

Purpose #

총 5명의 학생들이 있으며 각각 4개의 모의고사 점수 데이터가 있다. 앞의 3개의 모의고사 성적을 통해 4번째 모의고사 성적을 예상해보고 실제 점수와 비교해본다.

  • 모의고사는 100점이 최고 점수로 가정.
  • 해당 데이터는 아래와 같음.
    Score Table

Normal Way #

우선 일반적인 방법으로 진행해본다.

Input Data #

우선 훈련에 사용할 데이터를 입력해준다.

  • x1은 첫 번째, x2는 두 번째, x3는 세 번째 시험 점수를 의미.
  • Y_data는 마지막 4번째 시험 점수로 예상점수와 비교하기 위해 사용.
  • 숫자 뒤에 붙은 .문자는 소수점으로 표현할 수 있는 실수를 의미.

    x1_data = [73., 93., 89., 96., 73.],
    x2_data = [80., 88., 91., 98., 66.],
    x3_data = [75., 93., 90., 100., 70.],
    Y_data = [73., 93., 89., 96., 71.],
    

Set Variable #

입력한 데이터들이 들어갈 변수를 설정해준다.

  • Variable : 초기화가 필요 없으며 훈련의 대상이 되는 값.
  • Placeholder : 일반적인 변수의 의미가 아닌 자리표시자 혹은 입력값의 형태를 의미. 훈련 시 필요한 값을 제공함.
  • x1는 첫 번째 모의고사 성적이 들어갈 변수, w1은 x1에 적용될 가중치값.
  • Y는 4번째 모의고사 성적이 들어갈 변수.

    x1 = tf.placeholder(tf.float32)
    x2 = tf.placeholder(tf.float32)
    x3 = tf.placeholder(tf.float32)
    Y = tf.placeholder(tf.float32)
    
    w1 = tf.Variable(tf.random_normal([1]), name='weight1')
    w2 = tf.Variable(tf.random_normal([1]), name='weight2')
    w3 = tf.Variable(tf.random_normal([1]), name='weight3')
    b = tf.Variable(tf.random_normal([1]), name='bias')
    

Hypothesis #

이제 만들어 준 변수들을 통해 가설을 작성해준다. 예상 점수는 각 시험 점수에 가중치를 곱하고 편차(bias)를 더하여 구할 수 있다.

    hypothesis = x1 * w1 + x2 * w2 + x3 + w3 + b

Opimizer #

가설을 세웠으니 훈련을 위해 비용함수, 최적화 함수, 세션 초기화를 설정해준다.

  • 비용 : Cost라고 하며 예상 값과 실제값의 차이의 제곱 값.
  • 비용값이 적을 수록 좋은 모델이라고 할 수 있음.
  • minimize(cost)는 가장 최솟값의 cost를 찾기 위한 함수.

    # cost는 (예상값 - 실제값)의 제곱 값이다.
    cost = tf.reduce_mean(tf.square(hypothesis - Y))
    # 최적화 방식에는 경사 타기 알고리즘을 사용. 
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=1e-5)
    # train은 훈련 노드로 cost를 최소화하는 기능을 한다.
    train = optimizer.minimize(cost)
    
    sess = tf.Session()
    # 실행하기 위해 Session을 초기화해준다.
    # 초기화는 각 노드에 0이나 적당한 형태를 입력하는 것을 의미한다.
    sess.run(tf.global_variables_initializer())
    

Train #

위에서 작성한 훈련 노드를 반복문을 통해 여러 번 훈련시켜 예상 값과 비용을 출력해서 비교해본다.

  • 2000번을 반복하여 훈련.
  • 학생별 4번째 모의고사 예상 점수를 출력.

    # 2000번 반복 실행.
    for step in range(2001):
    
        # cost_val: 비용 , hy_val: 예상값 
        cost_val, hy_val, _ = \
        sess.run([cost, hypothesis, train], 
        feed_dict={x1:x1_data, x2:x2_data, x3:x3_data, Y:Y_data})
    
        # 200번 마다 비용과 예측값을 출력.
        if step % 200 == 0:
            print(" -> step{:5} : \
            Cost: {:6.4f} / \
            학생1: {:7.4f}점, \
            학생2: {:7.4f}점, \
            학생3: {:7.4f}점, \
            학생4: {:7.4f}점, \
            학생5: {:7.4f}점 \n"
                  . format(
                  step,cost_val, 
                  hy_val[0][0], 
                  hy_val[0][1], 
                  hy_val[0][2], 
                  hy_val[0][3], 
                  hy_val[0][4]
                  )
            )
    

Result #

해당 훈련의 결괏값을 아래와 같다.

  • 훈련이 반복될수록 비용값이 낮아짐을 확인.
  • 예측값과 실제값이 큰 차이가 없음을 확인.
순서 비용 예측값
step 0 Cost: 24889.8086 학생1: 222.2169점, 학생2: 253.9867점, 학생3: 256.8804점, 학생4: 279.5956점,
step 200 Cost: 35.2205 학생1: 80.4072점, 학생2: 87.0405점, 학생3: 90.4302점, 학생4: 100.2103점, 학생5: 62.8792점
step 400 Cost: 31.8119 학생1: 79.9951점, 학생2: 87.3280점, 학생3: 90.3092점, 학생4: 100.0888점, 학생5: 63.2848점
step 600 Cost: 28.7424 학생1: 79.6041점, 학생2: 87.6009점, 학생3: 90.1942점, 학생4: 99.9734점, 학생5: 63.6697점
step 800 Cost: 25.9783 학생1: 79.2330점, 학생2: 87.8597점, 학생3: 90.0852점, 학생4: 99.8639점, 학생5: 64.0350점
step 1000 Cost: 23.4893 학생1: 78.8809점, 학생2: 88.1054점, 학생3: 89.9817점, 학생4: 99.7601점, 학생5: 64.3817점
step 1200 Cost: 21.2479 학생1: 78.5468점, 학생2: 88.3385점, 학생3: 89.8835점, 학생4: 99.6615점, 학생5: 64.7106점
step 1400 Cost: 19.2296 학생1: 78.2297점, 학생2: 88.5598점, 학생3: 89.7903점, 학생4: 99.5679점, 학생5: 65.0228점
step 1600 Cost: 17.4120 학생1: 77.9288점, 학생2: 88.7697점, 학생3: 89.7019점, 학생4: 99.4791점, 학생5: 65.3190점
step 1800 Cost: 15.7753 학생1: 77.6433점, 학생2: 88.9689점, 학생3: 89.6180점, 학생4: 99.3949점, 학생5: 65.6001점
step 2000 Cost: 14.3014 학생1: 77.3724점, 학생2: 89.1579점, 학생3: 89.5383점, 학생4: 99.3150점, 학생5: 65.8668점

Problem #

결과는 정상적으로 잘 나왔지만, 위의 방법에서 몇 가지 문제점들이 있다.

  • 입력 데이터가 직접 입력하기 어려울 정도로 많아질 경우.
  • 그에 따라 훈련에 필요한 변수와 복잡도가 증가.

Matrix #

실제 업무에서는 단순히 몇 가지의 데이터만 다루는 것이 아닌 엄청난 양의 데이터를 동시 다발적으로 다룬다. 이런 작업이 가능한 이유가 바로 행렬연산이다.

  • 이번에는 행렬연산을 활용한 방법으로 실습.
  • 많은 데이터를 입력이 아닌 임포트해서 적용.

Road Data #

수많은 데이터를 손으로 직접 입력하기에는 너무 힘들고 오타가 발생할 확률이 높다. 그래서 numpy 라이브러리를 사용하여 데이터를 CSV파일에서 불러온다.

  • 위와 동일한 형식의 데이터.
  • 학생수를 5명이 아닌 25명으로 증가.
  • 4번째 시험의 점수를 100점에서 200점으로 변경.

    # Numpy 라이브러리의 loadtxt() 함수를 통해 불러옴.
    # CSV는 Comma로 구분하기 때문에 delimiter(구분자)로 ','를 적용.
    xy = np.loadtxt('data/data-01-test-score.csv', 
            delimiter=',', 
            dtype=np.float32)
    

Data Slicing #

불러온 데이터에서 훈련용으로 사용할 1, 2, 3번째 모의고사 점수와 실제값으로 사용할 4번째 모의고사 점수를 구분해준다.

  • 슬라이싱을 사용하여 데이터를 구분
  • xy[:, 0:-1]
    • 첫 번째 :는 모든 행을 의미
    • 두 번째 0:-1은 첫 번째에서 마지막 두 번째 열까지를 의미.
    • 즉 1번째부터 3번째 모의고사 점수가 해당.
  • xy[:, -1]
    • 두 번째 -1은 마지막 열을 의미.
    • 즉 4번째 모의고사 점수가 해당.
  • 불러오는 형태는 위에 있던 형식과 동일.
    Score Table

### Set Martix 행렬연산을 일반적인 방식과 다르게 행렬을 맞추어야 한다. 계산하려는 행렬의 형태에 맞는 가중치 값을 설정해주어야 행렬연산이 가능하다.

  • [5,3]x[a,b] = [5,2]라고 하면 a, b에 알맞은 수를 지정해야 함.
  • 첫 번째 행렬의 열에 해당하는 3이 a와 같음.
  • 마지막 행렬의 열에 해당하는 2가 b와 같음.
  • 그래서 [a,b][3,2] 즉 3행, 2열의 형태가 됨.

  • [None, 3] : 행을 자동으로 설정하고, 열은 3인 행렬.

  • tf.random_normal([3,1]) : 랜덤 값으로 3행 1열의 행렬을 지정.

    # X는 3개의 성적값을 입력받으므로 [None, 3].
    X = tf.placeholder(tf.float32, shape=[None,3])
    # Y는 1개의 예상값이 나오므로 [None, 1]
    Y = tf.placeholder(tf.float32, shape=[None,1])
    # 가중치는 X와 행렬연산을 하기 위해 [3,1].
    W = tf.Variable(tf.random_normal([3,1]), name='weight')
    b = tf.Variable(tf.random_normal([1]), name='bias')
    

### Hypothesis 입력받는 변수가 줄어들어 가설공식이 단순화되었으며 그만큼 계산방식도 간소화되었다.

  • matmul : 행렬의 곱셈 연산을 수행하는 기능.

    # matmul으로 곱셈 연산을 할 수 있다.
    # X와 W의 곱셈연산을 수행한다.
    hypothesis = tf.matmul(X,W) + b
    

Opimizer #

설정한 가설로 비용, 최적화 함수를 구성한다. 기존의 방식과 동일하다.

    cost = tf.reduce_mean(tf.square(hypothesis-Y))
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=1e-5)
    train = optimizer.minimize(cost)

    sess = tf.Session()
    sess.run(tf.global_variables_initializer())

Train #

위에서 작성한 훈련 노드를 반복문을 통해 여러 번 훈련시켜 예상 값과 비용을 출력해서 비교해본다.

  • 2000번을 반복하여 훈련.
  • 전체 학생 중 1~5번 학생의 결과만 출력.

    for step in range(2001):
        cost_val, hy_val, _ = \
        sess.run( [cost, hypothesis, train], 
        feed_dict={X:x_data, Y:y_data} )
    
        if step % 200 == 0:
            print(" {:5} | {:6.4f} | 
            학생1: {:7.4f}점, 
            학생2: {:7.4f}점, 
            학생3: {:7.4f}점, 
            학생4: {:7.4f}점, 
            학생5: {:7.4f}점 \n"
                  . format(step,cost_val,
                           hy_val[0][0], 
                           hy_val[1][0], 
                           hy_val[2][0], 
                           hy_val[3][0], 
                           hy_val[4][0]
                           )
                )
    

Result #

해당 훈련의 결괏값을 아래와 같다.

  • 훈련결과 예상 점수가 실제 점수와 근접함을 확인 가능.
  • 복잡한 연산을 행렬식을 사용하면 더욱 간단히 구현 가능.
순서 비용 예상점수
0 59389.4297 학생1: -73.7489점, 학생2: -89.2429점, 학생3: -87.4624점, 학생4: -97.6416점, 학생5: -66.1593점
200 43.9603 학생1: 154.9839점, 학생2: 186.0494점, 학생3: 183.5711점, 학생4: 197.8062점, 학생5: 143.6652점
400 38.6951 학생1: 154.7077점, 학생2: 186.0487점, 학생3: 183.3792점, 학생4: 197.8480점, 학생5: 143.5401점
600 34.2029 학생1: 154.4602점, 학생2: 186.0419점, 학생3: 183.2037점, 학생4: 197.8881점, 학생5: 143.4162점
800 30.3658 학생1: 154.2386점, 학생2: 186.0298점, 학생3: 183.0432점, 학생4: 197.9268점, 학생5: 143.2941점
1000 27.0845 학생1: 154.0405점, 학생2: 186.0131점, 학생3: 182.8965점, 학생4: 197.9639점, 학생5: 143.1739점
1200 24.2748 학생1: 153.8637점, 학생2: 185.9925점, 학생3: 182.7624점, 학생4: 197.9997점, 학생5: 143.0559점
1400 21.8661 학생1: 153.7061점, 학생2: 185.9686점, 학생3: 182.6398점, 학생4: 198.0340점, 학생5: 142.9403점
1600 19.7983 학생1: 153.5659점, 학생2: 185.9420점, 학생3: 182.5278점, 학생4: 198.0669점, 학생5: 142.8273점
1800 18.0208 학생1: 153.4415점, 학생2: 185.9130점, 학생3: 182.4253점, 학생4: 198.0986점, 학생5: 142.7171점
2000 16.4908 학생1: 153.3313점, 학생2: 185.8822점, 학생3: 182.3317점, 학생4: 198.1289점, 학생5: 142.6096점

Compare #

훈련의 결괏값과 실제값을 비교하여 얼마나 잘 예측하였는지 살펴보자.

  • 실제값과 예측값의 분산을 구해서 비교.
  • 실제값과 유사하게 예측하였으며 분산은 3.74로 나옴.
순서 실제값 예측값 편차 분산 표준편차
1 152 154.47 -02.47 06.10 02.47
2 185 185.31 -00.31 00.10 00.31
3 180 182.78 -02.78 07.75 02.78
4 196 198.15 -02.15 04.62 02.15
5 142 142.14 -00.14 00.02 00.14
6 101 103.61 -02.61 06.82 02.61
7 149 147.26 01.74 03.02 01.74
8 115 107.64 07.36 54.18 07.36
9 175 172.13 02.87 08.23 02.87
10 164 157.56 06.44 41.46 06.44
11 141 142.72 -01.72 02.97 01.72
12 141 140.31 00.69 00.47 00.69
13 184 189.70 -05.70 32.48 05.70
14 152 159.02 -07.02 49.31 07.02
15 148 147.81 00.19 00.04 00.19
16 192 187.24 04.76 22.65 04.76
17 147 152.46 -05.46 29.78 05.46
18 183 176.11 06.89 47.51 06.89
19 177 181.05 -04.05 16.41 04.05
20 159 161.93 -02.93 08.60 02.93
21 177 172.85 04.15 17.19 04.15
22 175 173.06 01.94 03.75 01.94
23 175 165.10 09.90 98.09 09.90
24 149 157.78 -08.78 77.05 08.78
25 192 192.47 -00.47 00.22 00.47
평균 162.04 162.03 00.01 21.55 03.74

Summary #

행렬식은 머신러닝에서 가장 중요한 연산이다. 해당 예제는 행렬식을 구성하는 원리를 알아보기 위해 작성한 예제이며 실제로는 해당 예제보다 훨씬 복잡하고 방대한 데이터를 다루게 된다. 하지만 이런 행렬식의 기초적인 이해와 구성 방법을 알고 있으면 하나하나 분석할 수 있는 발판이 될 수 있을 것이다.

0.0.1_20230725_7_v68