인공지능 응용 공학

텐서플로우 선형회귀법 예제

coding art 2023. 1. 3. 13:48
728x90

그림의 선형회귀법 예제에서 기울기 w를 미지수로 생각하고 회귀법(regression)으로 찾아보자. 미지의 웨이트 값 w는 처음에 random number 나 임의의 상수값을 준 상태에서 시작하면 된다. 한가지 주의할 점은 직선의 방정식을 결정하는 과정에서 2개 이상의 많은 수의 데이터들이 주어질 경우 이 점들을 대표할 수 있는 직선을 결정하게 되는 것이며, 이는 통계학이나 사회학 분야에서 많이 응용되는 기법이다.

 

 

 

TensorFlow 라이브러리를 사용하여 1차식 regression 코드를 작성하자. 아울러 matplotlib.pyplot 라이브러리를 사용하여 주어진 좌표 데이터를 사용하여 점그래프(scatter graph)와 구해진 1차식 regression graph를 함께 작도하도록 한다.

 

1 import tensorflow as tf
import matplotlib.pyplot as plt
 
이 선형회귀 예제에서 필요한 입력 데이타들을 텐서플로우 상수형 리스트 자료구조로 선언하자.
 
 
2 x = tf.constant([[1], [1.5], [2], [2.5], [3], [4]], dtype=tf.float32)
y = tf.constant([[10], [11], [20], [27], [30], [34]], dtype=tf.float32)

 

함수 regression_line의 인수들 중 a는 직선의 기울기, b는 직선의 편향이며, x 는 샘플 (x, y)x 좌표 값으로 tf.constant 에서 설정된다. 함수 계산 결과, 반환되는 y x 와 마찬가지로 tf.constant 가 된다.

 

 

3 def regression_line(a, b, x):
y = a*x + b
return y

 

regression 직선의 기울기에 해당하는 가중치 w 와 편향 b 는 머신러닝 과정을 통해 결정해야 할 중요 변수이므로 반드시 TensorFlow 변수로 선언되어야 regression이 가능해진다. 일단 학습을 위한 초기값으로 각각 0.0 으로 설정하자.

 

 

4 w = tf.Variable(0.0, dtype=tf.float32)
b = tf.Variable(0.0, dtype=tf.float32)

 

아래와 같이 1차식 회귀 모델(model) hypothesisy_hat으로 정의하자.

 

 

5 y_hat = w * x + b
 
Cost 함수 또는 loss 함수를 mean square error 형으로 두자. 즉 각 데이터 별 hypothesis y 데이터와의 차이의 제곱을 계산하여 합산한 후 데이터 수로 나누어 평균을 낸다. 최종적으로 에러가 최소화된 hypothesis 의 정확한 값을 찾아내게 되면 이 loss의 값은 그 형태가 평균(mean) 대신 hypothesis 값을 사용하는 분산과 대단히 유사함을 알 수 있다.

 

6 loss = tf.reduce_mean(tf.square(y_hat - y))

 

여러 종류의 옵티마이저 중 SGD를 정의하자. 지금의 예제 계산은 정확히 y=f(x)=10x fh 근사할 수 있으므로 예측 가능한 특성이 있지만 현실적인 regression 문제에 있어서는 입력 데이터의 수와 분포가 예측이 어려울 정도로 불규칙할 수가 있다. 이때 적합한 경사하강법 중의 하나가 바로 SGD(stochastic gradient descent)기법이다. learning rate lr0.1로 두자. lr 값에 따라 학습 횟수에 미치는 영향이 크다.

 

 

7 optimizer = tf.optimizers.SGD(learning_rate=0.1)

 

이 예제 코드의 학습(train, iteration) 횟수는 100회로 하자.

tf.Gradient를 상속을 위해서 약어 tape로 두고, tape.gradient 명령을 사용하여 기울기를 구해보자. Cost 함수인 loss를 변수 [w, b]에 관해서 편미분하여 기울기(gradients)와 편향을 계산하여 저장한다.

 

 

8 for i in range(100):
with tf.GradientTape() as tape:
y_hat = w * x + b
loss = tf.reduce_mean(tf.square(y - y_hat))
gradients = tape.gradient(loss, [w, b])
optimizer.apply_gradients(zip(gradients, [w, b]))

 

옵티마이저를 상속한 apply_gradients는 저장한 기울기와 편향을 사용하여 그 다음 값을 업데이트하여 최소값을 찾는다. 학습을 계속하여 기울기나 편행 값의 변화가 거의 없는 상태에 도달하면 경사하강법 적용이 끝나게 된다.

 

w b 는 텐서플로우 변수로 선언되었으므로 직접 수치 출력이 되지 않으므로 numpy() 처리해서 print 문으로 출력하도록 한다.

 

 

9 print(w.numpy(), b.numpy()) 1.9900767 0.029176058
 
이렇게 regression에 의해서 그래프상에서 기울기에 해당하는 w 와 편향 b 가 결정되면 언제든지 지정된 w 값에 대한 hypothesis 값을 계산할 수 있게 된다. 만약 w 가 시간 요소라면 next step 즉 다음 단계에서 예상값 즉 prediction 이 가능해진다. 이러한 유형의 문제는 앞으로 다루게 될 수기문자 판독에서처럼 샘플 별로 분류(classification)를 위한 라벨(label) 값을 지정할 필요가 없는 비지도 학습(unsupervised learning)이라고 볼 수 있으며, 특히 이문제는 단일 레이어를 사용하기 때문에 별도의 역전파 계산이 필요 없음에 유의하자.

함수 regression line을 사용하여 x 좌표에 대응하는 y 좌표 값을 계산한다.

 

 

10 line_y = regression_line(w.numpy(), b.numpy(), x)
plt.plot(x, line_y, color='black', linewidth=1,
marker='x', markerfacecolor='blue', markersize='12')
plt.scatter(x.numpy(), y.numpy(), color=’red’) #점그래프(scatter)
plt.title('Linear Line Plot') # Add a title and axis labels
plt.xlabel('x-axis'); plt.ylabel('y-axis') ; plt.show()

 

직선 그래프를 작도하고 아울러 중복적으로 점그래프를 작성한다. 마지막으로 show 명령을 사용하여 화면에 출력한다.

 

블로그에서 코드 linearregression.py 를 복사하여 Jupyter 나 Colab에서 셀별로 또는 스크립트 처리 Spyder 로 실행해보자.

 

 

#linearregression.py

import tensorflow as tf
import matplotlib.pyplot as plt

def regression_line(a, b, x):
    y = a*x + b
    return y

# Define the input and output data
x = tf.constant([[1], [1.5], [2], [2.5], [3], [4]], dtype=tf.float32)
y = tf.constant([[10], [11], [20], [27], [30], [34]], dtype=tf.float32)

# Define the model variables
w = tf.Variable(tf.random.normal([1, 1]), dtype=tf.float32)
b = tf.Variable(tf.zeros([1, 1]), dtype=tf.float32)

# Define the model
y_hat = tf.matmul(x, w) + b

# Define the loss function (mean squared error)
loss = tf.reduce_mean(tf.square(y - y_hat))

# Define the optimizer
optimizer = tf.optimizers.SGD(learning_rate=0.01)

# Training loop
for i in range(100):
  with tf.GradientTape() as tape:
    y_hat = tf.matmul(x, w) + b
    loss = tf.reduce_mean(tf.square(y - y_hat))
  gradients = tape.gradient(loss, [w, b])
  optimizer.apply_gradients(zip(gradients, [w, b]))

# Print the final values of the model parameters
print(w.numpy(), b.numpy())

line_y = regression_line(w.numpy(), b.numpy(), x)

plt.plot(x, line_y, color='black', linewidth=1, 
         marker='x', markerfacecolor='blue', markersize='12')
plt.scatter(x.numpy(), y.numpy(), color='red')
# Add a title and axis labels
plt.title('Linear Line Plot')
plt.xlabel('x-axis')
plt.ylabel('y-axis')

# Show the plot
plt.show()