인공지능 AI

[머신러닝/인공지능] 선형회귀 예제 _단일변수/다변수

입력변수가 1개인 선형회귀 예제

앞서배운 회귀개념따라서 선형회귀를 구현하려면 y=Wx+b값을 구하고, 오차가 최소가 되는 W와 b를 구해야한다.

이를 실제로 구현할 때는 일반곱셈형식이 아니라 입력값x와 가중치W를 행렬로 변환후 y=W*x+b를 행렬곱으로 구한다.

import numpy as np


#트레이닝 데이터 준비.초기화 
x_data=np.array([1,2,3,4,5]).reshape(5,1)
y_data=np.array([2,3,4,5,6]).reshape(5,1)

#임의의 W가중치, b바이어스 준비,초기화 
W=np.random.rand(1,1) #0~1사이의 값으로 (1*1)행렬 생성 
b=np.random.rand(1) #0~1사이의 값

#손실함수 LossFunction
def loss_func(x,t):
    y=np.dot(x,W)+b
    return (np.sum((t-y)**2))/(len(x))

#학습 후 미래예측함수 predict
def predict(x):
    y=np.dot(x,W)+b
    return y



#현재의 손실함수값(error)알려주는 함수 
def loss_val(x,t):
    y=np.dot(x,W)+b
    return np.sum((t-y)**2)/len(x)

#수치미분 함수
#fx=다변수 함수
#input_list=변수 여러개 담고있는 numpy객체(배열, 행렬)
#f의 변수가 5개라면 input_list의 길이 또한 5개
def derivative(fx,input_list):
    delta_x=1e-4
    
    #결과값을 저장할 배열로, 0으로 초기화 
    ret=np.zeros_like(input_list)
    #input_list를 iterating할 변수 it 
    it=np.nditer(input_list,flags=['multi_index'],op_flags=['readwrite'])
    #input_list를 모두 순회
    #즉 모든 변수에 대해 각각 수치미분 수행 
    while not it.finished:
        i=it.multi_index

        #input_list의 원본값이 변형되므로 백업
        tmp=input_list[i]
        #input_list에 미세한 변화 
        input_list[i]=float(tmp)-delta_x
        f1=fx(input_list)

        input_list[i]=float(tmp)+delta_x
        f2=fx(input_list)
        ret[i]=(f2-f1)/(delta_x*2)

        input_list[i]=tmp
        it.iternext()
    return ret


#경사하강법 이용하여 손실함수loss_func()값이 최소가 될때까지
# 반복적으로 가중치W, 바이어스b를 업데이트하는 학습과정
learning_rate=1e-2

f=lambda x:loss_func(x_data,y_data)
print("initial error value=",loss_val(x_data,y_data),"initial W=",W,"\nb=",b)
for step in range(6001):
    W -= learning_rate*derivative(f,W)
    b -= learning_rate*derivative(f,b)

    if(step%600==0):
        print("step=",step,"loss_value=",loss_val(x_data,y_data),"W=",W,"b=",b)
print(predict(45))

입력변수1개선형회귀.py
0.00MB

손실함수 값이 지속적으로 작아지면서 W와 b가 1에 수렴함을 볼 수 있다.(y=x+1)

(참고로 손실함수값 loss_value가 ~~~e-20이런식의 값은 0.000000..(20개)같은 아주 작은 값이다.)

 

다음과 같이 45라는 값으로 predict() 입력 값을 넣었을때 46이라는 출력값으로 예측한 것을 볼 수 있다.

(결과가 입력값+1인 데이터에 기반하여 학습했기 때문 y=x+1)

 

입력변수가 2개 이상인 선형회귀 예제

data.csv
0.00MB

다음 csv파일이 이 예제의 트레이

닝데이터다.

import numpy as np
load_data = np.loadtxt('./data.csv', delimiter=',', dtype=np.float32)

#트레이닝 데이터 준비.초기화 
x_data=load_data[:,0:-1]
y_data=load_data[:,[-1]]

#임의의 W가중치, b바이어스 준비,초기화 
W=np.random.rand(3,1) #0~1사이의 값으로 (1*1)행렬 생성 
b=np.random.rand(1) #0~1사이의 값

#손실함수 LossFunction
def loss_func(x,t):
    y=np.dot(x,W)+b
    return (np.sum((t-y)**2))/(len(x))

#학습 후 미래예측함수 predict
def predict(x):
    y=np.dot(x,W)+b
    return y



#현재의 손실함수값(error)알려주는 함수 
def loss_val(x,t):
    y=np.dot(x,W)+b
    return np.sum((t-y)**2)/len(x)

#수치미분 함수
#fx=다변수 함수
#input_list=변수 여러개 담고있는 numpy객체(배열, 행렬)
#f의 변수가 5개라면 input_list의 길이 또한 5개
def derivative(fx,input_list):
    delta_x=1e-4
    
    #결과값을 저장할 배열로, 0으로 초기화 
    ret=np.zeros_like(input_list)
    #input_list를 iterating할 변수 it 
    it=np.nditer(input_list,flags=['multi_index'],op_flags=['readwrite'])
    #input_list를 모두 순회
    #즉 모든 변수에 대해 각각 수치미분 수행 
    while not it.finished:
        i=it.multi_index

        #input_list의 원본값이 변형되므로 백업
        tmp=input_list[i]
        #input_list에 미세한 변화 
        input_list[i]=float(tmp)-delta_x
        f1=fx(input_list)

        input_list[i]=float(tmp)+delta_x
        f2=fx(input_list)
        ret[i]=(f2-f1)/(delta_x*2)

        input_list[i]=tmp
        it.iternext()
    return ret


#경사하강법 이용하여 손실함수loss_func()값이 최소가 될때까지
# 반복적으로 가중치W, 바이어스b를 업데이트하는 학습과정
learning_rate=1e-5

f=lambda x:loss_func(x_data,y_data)
print("initial error value=",loss_val(x_data,y_data),"initial W=",W,"\nb=",b)
for step in range(6001):
    W -= learning_rate*derivative(f,W)
    b -= learning_rate*derivative(f,b)

    if(step%600==0):
        print("step=",step,"loss_value=",loss_val(x_data,y_data),"W=",W,"b=",b)
print(predict([100,98,81]))

또 다른 예제를 해보자.

sps.csv
0.00MB

import numpy as np
load_data = np.loadtxt('./sps.csv', delimiter=',', dtype=np.float32)

#트레이닝 데이터 준비.초기화 
x_data=load_data[:,0:-1]
y_data=load_data[:,[-1]]

#임의의 W가중치, b바이어스 준비,초기화 
W=np.random.rand(4,1) #0~1사이의 값으로 (1*1)행렬 생성 
b=np.random.rand(1) #0~1사이의 값

#손실함수 LossFunction
def loss_func(x,t):
    y=np.dot(x,W)+b
    return (np.sum((t-y)**2))/(len(x))

#학습 후 미래예측함수 predict
def predict(x):
    y=np.dot(x,W)+b
    return y



#현재의 손실함수값(error)알려주는 함수 
def loss_val(x,t):
    y=np.dot(x,W)+b
    return np.sum((t-y)**2)/len(x)

#수치미분 함수
#fx=다변수 함수
#input_list=변수 여러개 담고있는 numpy객체(배열, 행렬)
#f의 변수가 5개라면 input_list의 길이 또한 5개
def derivative(fx,input_list):
    delta_x=1e-4
    
    #결과값을 저장할 배열로, 0으로 초기화 
    ret=np.zeros_like(input_list)
    #input_list를 iterating할 변수 it 
    it=np.nditer(input_list,flags=['multi_index'],op_flags=['readwrite'])
    #input_list를 모두 순회
    #즉 모든 변수에 대해 각각 수치미분 수행 
    while not it.finished:
        i=it.multi_index

        #input_list의 원본값이 변형되므로 백업
        tmp=input_list[i]
        #input_list에 미세한 변화 
        input_list[i]=float(tmp)-delta_x
        f1=fx(input_list)

        input_list[i]=float(tmp)+delta_x
        f2=fx(input_list)
        ret[i]=(f2-f1)/(delta_x*2)

        input_list[i]=tmp
        it.iternext()
    return ret


#경사하강법 이용하여 손실함수loss_func()값이 최소가 될때까지
# 반복적으로 가중치W, 바이어스b를 업데이트하는 학습과정
learning_rate=1e-5

f=lambda x:loss_func(x_data,y_data)
print("initial error value=",loss_val(x_data,y_data),"initial W=",W,"\nb=",b)
for step in range(8001):
    W -= learning_rate*derivative(f,W)
    b -= learning_rate*derivative(f,b)

    if(step%400==0):
        print("step=",step,"loss_value=",loss_val(x_data,y_data),"W=",W,"b=",b)
print(predict([2,3,9,0]))